diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..40a3e0b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,82 @@ +# .dockerignore - Excludes files from Docker build context +# Reduces build time, image size, and prevents leaking sensitive data + +# Version control +.git/ +.gitignore +.github/ + +# Python cache and compiled files +__pycache__/ +*.py[cod] +*$py.class +*.so +.pytest_cache/ + +# Virtual environments +.venv/ +venv/ +env/ +ENV/ +.poetry/ + +# Environment variables (SECURITY: never include secrets in images) +.env +.env.* + +# Documentation +# Keep README.md for Poetry package installation +# *.md # Commented out to allow README.md +docs/ +LICENSE + +# Development and testing +.pre-commit-config.yaml +.ropeproject/ +tests/ +test_*.py + +# IDE and editor files +.vscode/ +.idea/ +*.swp +*.swo +*~ +.DS_Store + +# Docker files (don't need these inside the image) +Dockerfile +Dockerfile.* +docker-compose.yml +docker-compose.*.yml +.dockerignore + +# Build artifacts +dist/ +build/ +*.egg-info/ +*.egg +.eggs/ + +# Logs +*.log +logs/ + +# OS files +.DS_Store +Thumbs.db +Desktop.ini + +# Temporary files +*.tmp +*.temp +tmp/ +temp/ + +# Coverage reports +htmlcov/ +.coverage +.coverage.* +coverage.xml +*.cover +.hypothesis/ diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..7b1055a --- /dev/null +++ b/.env.example @@ -0,0 +1,75 @@ +# Environment Variables Template for Survey Dashboard +# Copy this file to .env and update with your actual values +# Command: cp .env.example .env + +# ============================================================================ +# Docker Compose Configuration +# ============================================================================ + +# Project name - used as prefix for container names +# Example: survey-dashboard_nginx_1, survey-dashboard_dashboard_1 +COMPOSE_PROJECT_NAME=survey-dashboard + +# ============================================================================ +# Application Configuration +# ============================================================================ + +# Port the Panel application runs on inside the container +# Default: 5006 (Panel's default port) +APP_PORT= + +# ============================================================================ +# Nginx Configuration +# ============================================================================ + +# Port nginx exposes on the host machine +# Default: 80 (standard HTTP port), 443 (standard HTTPS port) +# Change to 8080/8443 if 80/443 are already in use +NGINX_PORT= + +# Your domain name +# IMPORTANT: For HTTPS to work, this MUST be a real domain that points to your server +# In development: Use 'localhost' (HTTPS won't work, only HTTP) +# In production: Use your actual domain (e.g., survey.example.com) +# This domain is used by: +# - nginx-proxy: Routes traffic from this domain to the dashboard +# - acme-companion: Requests SSL certificate for this domain from Let's Encrypt +HOST= + +# Path on the domain where the dashboard is accessible +# If set, the dashboard will ONLY be accessible at this specific path +# Examples: +# - VIRTUAL_PATH=/survey-dashboard → https://your-domain.com/survey-dashboard +# - VIRTUAL_PATH=/dashboard → https://your-domain.com/dashboard +# - Leave empty for root path → https://your-domain.com/ +# IMPORTANT: Must start with / (forward slash) +# All other paths on this domain will return 404 +VIRTUAL_PATH= + +# ============================================================================ +# SSL/HTTPS Configuration (Let's Encrypt) +# ============================================================================ + +# Your email address for Let's Encrypt certificate registration +# REQUIRED for production HTTPS deployment +# Let's Encrypt uses this email to: +# - Send certificate expiration warnings (if auto-renewal fails) +# - Send security notices about your certificates +# - Contact you about your Let's Encrypt account +# Example: admin@example.com or your-email@gmail.com +LETSENCRYPT_EMAIL= + +# ============================================================================ +# Python Configuration +# ============================================================================ + +# Keep Python output unbuffered for better logging +PYTHONUNBUFFERED=1 + +# ============================================================================ +# NOTES +# ============================================================================ +# - Never commit the .env file to version control +# - .env is listed in .gitignore to prevent accidental commits +# - Update .env.example when adding new environment variables +# - In production, consider using Docker secrets or a secrets manager diff --git a/.env.local.example b/.env.local.example new file mode 100644 index 0000000..8cb0c2a --- /dev/null +++ b/.env.local.example @@ -0,0 +1,83 @@ +# Environment Variables for LOCAL TESTING +# Copy this file to .env.local for local Docker testing +# Command: cp .env.local.example .env.local + +# IMPORTANT: This is for LOCAL TESTING ONLY +# For production deployment, use .env.example instead + +# ============================================================================ +# Docker Compose Configuration +# ============================================================================ + +# Project name - use different name to avoid conflicts with production +COMPOSE_PROJECT_NAME=survey-dashboard-local + +# ============================================================================ +# Application Configuration +# ============================================================================ + +# Port the Panel application runs on inside the container +APP_PORT=5006 + +# ============================================================================ +# Nginx Configuration +# ============================================================================ + +# Port nginx exposes on the host machine +# Default: 80 for HTTP +# If port 80 is in use, change to 8080 or another available port +NGINX_PORT=80 + +# Domain name - use localhost for local testing +# IMPORTANT: HTTPS will NOT work with localhost (Let's Encrypt requires real domains) +# You can only test HTTP locally +HOST=localhost + +# Path on the domain where the dashboard is accessible +# Test the same path you'll use in production +# Example: VIRTUAL_PATH=/2021community +# Leave empty to serve from root: http://localhost/ +VIRTUAL_PATH=/2021community + +# ============================================================================ +# SSL/HTTPS Configuration (Let's Encrypt) +# ============================================================================ + +# Dummy email for local testing +# This is not used when HOST=localhost (Let's Encrypt won't run) +# In production, use a real email address +LETSENCRYPT_EMAIL=test@localhost + +# ============================================================================ +# Python Configuration +# ============================================================================ + +# Keep Python output unbuffered for better logging +PYTHONUNBUFFERED=1 + +# ============================================================================ +# LOCAL TESTING NOTES +# ============================================================================ + +# What works locally: +# ✅ Docker build and container startup +# ✅ HTTP access at http://localhost/2021community +# ✅ Path routing and restrictions +# ✅ WebSocket connections +# ✅ Dashboard interactivity +# ✅ Container restarts and rebuilds + +# What does NOT work locally: +# ❌ HTTPS/SSL certificates (requires real domain) +# ❌ Let's Encrypt certificate acquisition (localhost is not valid) +# ❌ External access from internet (only local machine) + +# How to test: +# 1. Copy this file: cp .env.local.example .env.local +# 2. Start containers: docker-compose --env-file .env.local up -d --build +# 3. Test in browser: http://localhost/2021community +# 4. Follow LOCAL_TESTING.md for detailed testing scenarios + +# Cleanup after testing: +# docker-compose --env-file .env.local down +# docker-compose --env-file .env.local down -v # Remove volumes too diff --git a/.gitignore b/.gitignore index 9b1fbd7..ecaa234 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # custom -*.csv +responses_cleaned_mapped_to_publish.csv +#survey_dashboard/hmc_layout/static/en_files/fonts/ # Byte-compiled / optimized / DLL files __pycache__/ @@ -106,6 +107,7 @@ celerybeat.pid # Environments .env +.env.local .venv env/ venv/ @@ -113,6 +115,9 @@ ENV/ env.bak/ venv.bak/ +# Deployment files (may contain sensitive server info) +DEPLOYMENT.md + # Spyder project settings .spyderproject .spyproject @@ -130,3 +135,7 @@ dmypy.json # Pyre type checker .pyre/ + + +# Claude +.claude/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3348f27 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,44 @@ +# Multi-stage build for survey dashboard +# Stage 1: Builder - installs dependencies +FROM python:3.12-slim as builder + +# Install poetry +RUN pip install --no-cache-dir poetry==1.8.2 + +WORKDIR /app + +# Copy dependency files first (for Docker layer caching) +COPY pyproject.toml poetry.lock README.md ./ + +# Configure poetry to not create virtual environment (we're in a container) +RUN poetry config virtualenvs.create false + +# Install dependencies (excluding dev dependencies) +# --no-root: Don't install the project itself, only dependencies +RUN poetry install --only main --no-root --no-interaction --no-ansi + +# Stage 2: Final runtime image +FROM python:3.12-slim + +WORKDIR /app + +# Copy installed packages from builder stage +COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages +COPY --from=builder /usr/local/bin /usr/local/bin + +# Copy application code +COPY survey_dashboard/ ./survey_dashboard/ +COPY pyproject.toml ./ + +# Create a non-root user for security +RUN useradd -m -u 1000 appuser && \ + chown -R appuser:appuser /app + +USER appuser + +# Expose the application port +EXPOSE 5006 + +# Run the application in production mode +# Use python -m to run the module directly since we installed with --no-root +CMD ["python", "-m", "survey_dashboard.scripts", "--production", "--host", "0.0.0.0", "--port", "5006"] diff --git a/LICENSE b/LICENSE index d417970..42fd2d7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 Materials Data Science and Informatics +Copyright (c) 2025 Materials Data Science and Informatics Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 224243a..1d23490 100644 --- a/README.md +++ b/README.md @@ -1,72 +1,229 @@ -# Survey dashboard +# Survey Dashboard -A dashboard to display survey data in an interactive way. +A dashboard to display survey data in an interactive way using Panel and Bokeh. ## Overview -This repository contains a dashboard using Panel and Bokeh, developed to display data from -HMC surveys in an interactive exploratory way. It is designed such that the code for the interactive -visualizations might be reused for other projects. -Example of a deployed version can be found [here](https://dashboard.survey.helmholtz-metadaten.de/survey_dashboard) +This repository contains an interactive dashboard developed to display data from HMC surveys in an exploratory way. The dashboard is designed to be reusable for other survey visualization projects. + +**Live Demo:** [https://dashboard.survey.helmholtz-metadaten.de/2021community](https://dashboard.survey.helmholtz-metadaten.de/2021community) + +### Screenshots -Some impressions: ![dashboard_overview](https://user-images.githubusercontent.com/24694833/230306080-9ca68ff8-5b8b-4ac4-b2fa-51e2c5361c7d.png) ![dashboard_methods](https://user-images.githubusercontent.com/24694833/230306091-637188a9-359e-4ea0-8432-4d05a1ccc68f.png) ![Dashboard_survey_data_explorer](https://user-images.githubusercontent.com/24694833/230306099-4cf71bda-0990-4f9d-be14-9a65812e7ac4.png) +## Features + +- **Interactive Visualizations**: Explore survey data through dynamic charts and plots +- **Multiple Languages**: Support for English and German (configurable via environment variables) +- **Dockerized Deployment**: Production-ready Docker setup with HTTPS support +- **Responsive Design**: Works across different screen sizes +- **Self-hosted Fonts**: Uses HIFIS DIN fonts for consistent branding + ## Installation -After downloading the git repository you can install the software either with pip or poetry. -We recommend setting it up in a separate python virtual environment. +### Prerequisites -```shell -pip install survey_dashboard -``` -or +- Python 3.12 or higher +- Poetry (recommended for development) +- Docker & Docker Compose (for production deployment) + +### Local Development Setup + +1. **Clone the repository:** + ```bash + git clone https://github.com/Materials-Data-Science-and-Informatics/survey_dashboard.git + cd survey_dashboard + ``` + +2. **Install dependencies using Poetry:** + ```bash + poetry install + ``` -```shell -poetry install . +3. **Run the development server:** + ```bash + poetry run survey-dashboard + ``` + + The dashboard will be available at `http://localhost:5006/2021community/` + +### Alternative: Using pip + +```bash +pip install . +python -m survey_dashboard.scripts ``` ## Usage +### Development Mode + +The easiest way to run the dashboard in development mode: + +```bash +poetry run survey-dashboard +``` + +This starts the server with: +- Auto-reload on code changes +- Browser opens automatically +- Development-friendly error messages + +### Manual Panel Serve + +For more control over server configuration: + +```bash +panel serve survey_dashboard/app.py \ + --port 5006 \ + --static-dirs en_files=./survey_dashboard/hmc_layout/static/en_files \ + --prefix /2021community \ + --show +``` + +### Environment Variables + +- `VIRTUAL_PATH` - URL path prefix (default: `/2021community`) +- `LANGUAGE` - Dashboard language: `EN` or `DE` (default: `EN`) + +## Production Deployment + +This project includes Docker support for production deployment with automatic HTTPS using Let's Encrypt. + +### Docker Deployment + +1. **Configure environment variables:** + ```bash + cp .env.example .env + # Edit .env with your domain and settings + ``` + +2. **Build and start containers:** + ```bash + docker compose up -d --build + ``` + +3. **Access your dashboard:** + ``` + https://your-domain.com/2021community/ + ``` + +### Deployment Architecture + +The deployment uses: +- **nginx-proxy**: Automatic reverse proxy with virtual host routing +- **acme-companion**: Automatic Let's Encrypt SSL certificate management +- **Dashboard container**: Panel/Bokeh application server + +See `docker-compose.yml` and `Dockerfile` for detailed configuration. + +## Project Structure -After installation you can start the app, i.e the panel server/bokeh server. -```shell -panel serve --port 50006 survey_dashboard/ ``` -If you have given the dashboard a specific layout like the layout specific to HMC, which is on the hmc_specific branch, you might have to link to to a specific template. -```shell -panel serve --port 50006 survey_dashboard/ --static-dirs en_files=./survey_dashboard/hmc_layout/static/en_files +survey_dashboard/ +├── survey_dashboard/ # Main application code +│ ├── app.py # Main Panel application +│ ├── scripts.py # CLI entry point +│ ├── data/ # Data processing modules +│ ├── ui/ # UI components and layout +│ ├── i18n/ # Internationalization +│ └── hmc_layout/ # Templates and static assets +│ ├── en_template.html # English template +│ ├── de_template.html # German template +│ └── static/ # CSS, JS, images +├── docs/ # Documentation +│ └── refactoring/ # Architectural documentation +├── docker-compose.yml # Docker orchestration +├── Dockerfile # Container build instructions +├── .env.example # Environment template +└── pyproject.toml # Python dependencies +``` + +## Development +### Running Tests + +```bash +poetry run pytest ``` -* Navigate to `http://localhost:50006/` in your browser. +### Code Style + +This project uses: +- Black for code formatting +- Flake8 for linting +- MyPy for type checking -## Deployment +### Making Changes -To embed the dashboard into any website, first you have to host a bokeh server with this application somewhere and then you can embed it with bokehs `sever_document` function [see](https://docs.bokeh.org/en/latest/docs/user_guide/embed.html#app-documents) +1. Create a feature branch +2. Make your changes +3. Test locally with `poetry run survey-dashboard` +4. Test with Docker if deployment-related +5. Submit a pull request -Do steps under `usage` above, but for a public exposed URL, or what ever is used for deployment. -The Language verison of the dashboard can be set with the environment variable: 'L +## Documentation +Detailed documentation can be found in the `docs/refactoring/` directory: +- Architectural overview +- Module structure +- Development guide +- Migration guide -Add the code from 'script' to you website: +## Troubleshooting -```python -from bokeh.embed import server_document -script = server_document("url_to_running_server") -script +### Port Already in Use + +If port 5006 is already in use: +```bash +lsof -ti:5006 | xargs kill -9 ``` -## Copyright and Licence +### Docker Issues + +Check container logs: +```bash +docker compose logs -f dashboard +``` + +Rebuild without cache: +```bash +docker compose build --no-cache +``` + +### Font Loading Issues + +Clear browser cache (Ctrl+Shift+Del) or test in incognito mode. + +## Technology Stack + +### Core Framework +- **Panel** (1.7.5) - High-level app and dashboarding solution +- **Bokeh** (3.7.3) - Interactive visualization library +- **Python** (3.12+) - Programming language -See [LICENSE](./LICENSE). +### Data Processing +- **Pandas** (2.3.2) - Data manipulation +- **NumPy** (2.3.2) - Numerical computing -### Main used libraries and dependencies +### Visualization +- **Matplotlib** (3.10.6) - Plotting library +- **WordCloud** (1.9.4) - Word cloud generation -The following libraries are used directly (i.e. not only transitively) in this project: +### Web Server +- **Tornado** (6.5.2) - Async web framework (used by Bokeh) +### Deployment +- **Docker** - Containerization +- **nginx-proxy** - Automatic reverse proxy +- **acme-companion** - Let's Encrypt automation + +## License + +See [LICENSE](./LICENSE) for details. ## Acknowledgements @@ -77,7 +234,41 @@ The following libraries are used directly (i.e. not only transitively) in this p
-This project was developed at the Institute for Materials Data Science and Informatics -(IAS-9) of the Jülich Research Center and funded by the Helmholtz Metadata Collaboration -(HMC), an incubator-platform of the Helmholtz Association within the framework of the -Information and Data Science strategic initiative. +This project was developed at the **Institute for Materials Data Science and Informatics (IAS-9)** of the Forschungszentrum Jülich and funded by the **Helmholtz Metadata Collaboration (HMC)**, an incubator-platform of the Helmholtz Association within the framework of the Information and Data Science strategic initiative. + +## Citation + +If you use this dashboard in your research, please cite: + +```bibtex +@software{survey_dashboard, + title = {Survey Dashboard}, + author = {Bröder, Jens and Gerlich, Silke Christine and Hofmann, Volker}, + year = {2024}, + url = {https://github.com/Materials-Data-Science-and-Informatics/survey_dashboard}, + organization = {Forschungszentrum Jülich GmbH} +} +``` + +## Contributing + +Contributions are welcome! Please: + +1. Fork the repository +2. Create a feature branch +3. Make your changes +4. Add tests if applicable +5. Ensure all tests pass +6. Submit a pull request + +For major changes, please open an issue first to discuss what you would like to change. + +## Support + +For questions or issues: +- **GitHub Issues**: [Report a bug or request a feature](https://github.com/Materials-Data-Science-and-Informatics/survey_dashboard/issues) +- **Email**: Contact the maintainers (see repository contributors) + +--- + +**Last Updated:** November 2024 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f262d92 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,146 @@ +# Docker Compose configuration for Survey Dashboard +# Orchestrates nginx reverse proxy and Panel application containers + +version: '3.8' + +services: + # Panel application container + dashboard: + build: . + # Builds from Dockerfile in current directory + # Uses multi-stage build to create optimized production image + + expose: + - "5006" + # Exposes port 5006 to other containers (not to host machine) + # Only accessible within Docker network - nginx can reach it + + restart: unless-stopped + # Automatically restart if container crashes + # Persists across system reboots unless manually stopped + + environment: + - PYTHONUNBUFFERED=1 + # Ensures Python output is sent directly to logs (not buffered) + # Makes 'docker-compose logs' show real-time output + - VIRTUAL_HOST=${HOST} + # Tells nginx-proxy which domain should route to this container + # nginx-proxy watches Docker and auto-configures when it sees this variable + - VIRTUAL_PATH=${VIRTUAL_PATH} + # Restricts access to only this specific path on the domain + # Example: VIRTUAL_PATH=/survey-dashboard means only /survey-dashboard/* is accessible + # All other paths on this domain return 404 + - VIRTUAL_PROTO=http + # Protocol nginx-proxy uses to communicate with this container + # Uses HTTP inside Docker network (fast, safe), HTTPS for external traffic + - LETSENCRYPT_HOST=${HOST} + # Tells acme-companion to get SSL certificate for this domain + # acme-companion watches Docker and auto-requests certificates when it sees this + - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL} + # Email for Let's Encrypt certificate notifications + # Used for expiry warnings and security notices about your certificates + + # Uncomment to mount local code for development + # volumes: + # - ./survey_dashboard:/app/survey_dashboard + + # Nginx reverse proxy container with auto-configuration + nginx-proxy: + container_name: nginx-proxy + image: nginxproxy/nginx-proxy:latest + # Auto-configuring reverse proxy that watches Docker containers + # Automatically generates nginx config based on container environment variables + + ports: + - "80:80" + # HTTP port - used for ACME challenges and auto-redirect to HTTPS + - "443:443" + # HTTPS port - secure encrypted connections + + volumes: + # nginx-proxy auto-generates configuration based on container env vars + # Custom per-domain configs can be placed in ./nginx/vhost.d/ + - ./nginx/certs:/etc/nginx/certs:ro + # SSL certificates storage (read-only for nginx-proxy) + # acme-companion writes certificates here, nginx-proxy reads them + - ./nginx/vhost.d:/etc/nginx/vhost.d + # Per-domain custom nginx configurations + # Files named after domains (e.g., survey.example.com) are included in that domain's config + - ./nginx/html:/usr/share/nginx/html + # Web root for serving ACME challenge files during Let's Encrypt verification + # acme-companion creates challenge files here, nginx-proxy serves them + - /var/run/docker.sock:/tmp/docker.sock:ro + # Docker socket for auto-discovery of containers + # nginx-proxy watches for containers with VIRTUAL_HOST env var + # Read-only for security (can observe but not control Docker) + + depends_on: + - dashboard + # Ensures dashboard container starts before nginx-proxy + # nginx-proxy needs dashboard to be available for proxying + + restart: unless-stopped + # Same restart policy as dashboard + + labels: + - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true" + # Identifies this container as the nginx instance for acme-companion to manage + # acme-companion will reload this container when SSL certificates are updated + + # Let's Encrypt certificate management container + letsencrypt: + container_name: acme-companion + image: nginxproxy/acme-companion + # ACME protocol client for automatic Let's Encrypt certificate management + # Watches for containers with LETSENCRYPT_HOST environment variable + + environment: + - NGINX_PROXY_CONTAINER=nginx-proxy + # Tells acme-companion which nginx container to reload when certificates update + # Must match the container_name of nginx-proxy service + - DEFAULT_EMAIL=${LETSENCRYPT_EMAIL} + # Default email for Let's Encrypt certificate registration and notifications + # Individual containers can override with their own LETSENCRYPT_EMAIL + # Used for certificate expiry warnings and security notices + + volumes: + - ./nginx/certs:/etc/nginx/certs:rw + # SSL certificates storage (read-write for acme-companion) + # acme-companion writes new certificates here, nginx-proxy reads them + # Note: :rw (not :ro like nginx-proxy) because acme-companion must write certs + - ./nginx/vhost.d:/etc/nginx/vhost.d + # Per-domain custom nginx configurations + # acme-companion may add temporary configs for ACME challenge handling + - ./nginx/html:/usr/share/nginx/html + # Web root for ACME challenge files + # acme-companion creates challenge files here, nginx-proxy serves them to Let's Encrypt + - /var/run/docker.sock:/var/run/docker.sock:ro + # Docker socket for container discovery and nginx reload + # Watches for containers with LETSENCRYPT_HOST environment variable + # Sends reload signal to nginx-proxy when certificates update + - acme-data:/etc/acme.sh + # Named volume for Let's Encrypt account data (NOT a directory) + # Stores account credentials, must persist across container restarts + # Losing this data means re-registering with Let's Encrypt + + depends_on: + - nginx-proxy + # Ensures nginx-proxy starts before acme-companion + # acme-companion needs nginx-proxy to be running to reload it when certificates update + + restart: unless-stopped + # Automatically restart if container crashes + # Persists across system reboots unless manually stopped + # Critical for certificate renewal - must stay running to renew certs every 90 days + +networks: + default: + # Docker Compose automatically creates a default network + # Both containers join this network and can communicate + # Service names (dashboard, nginx) work as DNS hostnames + +volumes: + acme-data: + # Named volume for Let's Encrypt account credentials + # Docker manages this volume's lifecycle (persists across container removals) + # Only destroyed if explicitly deleted with: docker volume rm survey-dashboard_acme-data diff --git a/docs/LOCAL_TESTING.md b/docs/LOCAL_TESTING.md new file mode 100644 index 0000000..721bf03 --- /dev/null +++ b/docs/LOCAL_TESTING.md @@ -0,0 +1,766 @@ +# Local Testing Guide - Survey Dashboard + +This guide explains how to test the Docker deployment setup locally before deploying to production. This helps catch issues early and ensures a smooth production deployment. + +--- + +## Table of Contents + +1. [Why Test Locally?](#why-test-locally) +2. [What You Can Test](#what-you-can-test) +3. [What You Cannot Test](#what-you-cannot-test) +4. [Local Testing Setup](#local-testing-setup) +5. [Testing Scenarios](#testing-scenarios) +6. [Verification Steps](#verification-steps) +7. [Troubleshooting](#troubleshooting) +8. [Cleanup](#cleanup) + +--- + +## Why Test Locally? + +Testing locally allows you to: + +- ✅ Verify Docker images build successfully +- ✅ Ensure all containers start without errors +- ✅ Test that the dashboard is accessible at the correct path +- ✅ Verify WebSocket connections work +- ✅ Catch configuration errors before production +- ✅ Understand the deployment process in a safe environment +- ✅ Test updates and changes without affecting production + +--- + +## What You Can Test + +### ✅ Fully Testable Locally + +1. **Docker Build Process** + - Multi-stage build completes successfully + - No missing dependencies + - Application code is copied correctly + +2. **Container Startup** + - All 3 containers start without errors + - Containers communicate via Docker network + - Port mappings work correctly + +3. **Application Functionality** + - Dashboard loads and displays correctly + - Interactive elements work (buttons, filters, plots) + - WebSocket connections establish successfully + - Static files (CSS, JavaScript) load properly + +4. **Path Routing** + - Dashboard accessible at specified VIRTUAL_PATH + - Root path returns expected response + - nginx-proxy routing configuration works + +5. **Environment Variables** + - Variables are read correctly by containers + - Panel receives correct --prefix argument + - Configuration is applied as expected + +--- + +## What You Cannot Test + +### ❌ Not Testable Locally (Requires Production Domain) + +1. **HTTPS/SSL Certificates** + - Let's Encrypt requires a real domain pointing to a public IP + - Cannot acquire valid SSL certificates for localhost + - **Workaround:** Test with HTTP only locally + +2. **DNS Resolution** + - localhost is not a real domain + - Cannot test DNS propagation + - **Workaround:** Use localhost or 127.0.0.1 + +3. **Public Internet Access** + - Cannot test from external networks + - Cannot verify public firewall rules + - **Workaround:** Test from local network only + +--- + +## Local Testing Setup + +### Prerequisites + +Ensure you have installed: +- Docker Engine (v20.10+) +- Docker Compose (v2.0+) + +Verify installation: +```bash +docker --version +docker-compose --version +``` + +### Step 1: Create Local Environment File + +Create a `.env.local` file for local testing: + +```bash +cp .env.example .env.local +``` + +### Step 2: Configure for Local Testing + +Edit `.env.local`: + +```bash +nano .env.local +``` + +**Local testing configuration:** + +```env +# Project name +COMPOSE_PROJECT_NAME=survey-dashboard-local + +# Application port (internal) +APP_PORT=5006 + +# Nginx ports (external) +NGINX_PORT=80 + +# Use localhost for local testing +# IMPORTANT: HTTPS will NOT work with localhost +HOST=localhost + +# Path where dashboard is accessible +VIRTUAL_PATH=/2021community + +# Dummy email for local testing (not used without real domain) +LETSENCRYPT_EMAIL=test@localhost + +# Python configuration +PYTHONUNBUFFERED=1 +``` + +**Key differences from production:** +- `HOST=localhost` (instead of real domain) +- `COMPOSE_PROJECT_NAME=survey-dashboard-local` (to avoid conflicts) +- LETSENCRYPT_EMAIL is dummy (won't be used) + +### Step 3: Point Docker Compose to Local Environment + +Use the `-f` flag or rename: + +**Option A: Use environment file flag** +```bash +docker-compose --env-file .env.local up -d +``` + +**Option B: Temporarily rename files** +```bash +# Backup production .env if it exists +mv .env .env.production 2>/dev/null || true + +# Use local env for testing +cp .env.local .env + +# Run docker-compose +docker-compose up -d + +# After testing, restore production .env +mv .env.production .env 2>/dev/null || true +``` + +I'll use **Option A** in this guide (safer, no file renaming). + +--- + +## Testing Scenarios + +### Scenario 1: Basic HTTP Deployment Test + +**Goal:** Verify all containers start and dashboard is accessible via HTTP. + +**Steps:** + +1. **Start containers with local environment:** + ```bash + docker-compose --env-file .env.local up -d --build + ``` + +2. **Verify containers are running:** + ```bash + docker-compose ps + ``` + + Expected output: + ``` + NAME STATUS + survey-dashboard-local_dashboard_1 Up + nginx-proxy Up + acme-companion Up + ``` + +3. **Check dashboard logs:** + ```bash + docker-compose logs dashboard + ``` + + Look for: + ``` + Starting HMC Survey Dashboard in PRODUCTION mode... + Using URL prefix: /2021community + Dashboard will be accessible at: http://0.0.0.0:5006/2021community + ``` + +4. **Check nginx-proxy logs:** + ```bash + docker-compose logs nginx-proxy | grep localhost + ``` + + Should show nginx-proxy detected your container. + +5. **Test HTTP access:** + ```bash + curl -I http://localhost/2021community/ + ``` + + Expected: `HTTP/1.1 200 OK` or `HTTP/1.1 302 Found` (redirect) + +6. **Open in browser:** + ``` + http://localhost/2021community/ + ``` + + Dashboard should load with full functionality. + +**Expected Result:** ✅ Dashboard accessible, interactive, no errors + +--- + +### Scenario 2: Path Restriction Test + +**Goal:** Verify that only the specified path is accessible, others return 404. + +**Steps:** + +1. **Test the correct path (should work):** + ```bash + curl -I http://localhost/2021community + ``` + + Expected: `HTTP/1.1 200 OK` + +2. **Test root path (should fail):** + ```bash + curl -I http://localhost/ + ``` + + Expected: `HTTP/1.1 404 Not Found` or `HTTP/1.1 503 Service Unavailable` + + (503 is also acceptable - means nginx-proxy has no backend for root path) + +3. **Test wrong path (should fail):** + ```bash + curl -I http://localhost/wrong-path + ``` + + Expected: `HTTP/1.1 404 Not Found` + +4. **Browser test:** + - Visit `http://localhost/2021community/` → Should load ✅ + - Visit `http://localhost/` → Should show 404 or 503 ✅ + - Visit `http://localhost/other` → Should show 404 ✅ + +**Expected Result:** ✅ Only `/2021community/` path is accessible + +--- + +### Scenario 3: WebSocket Connection Test + +**Goal:** Verify WebSocket connections work correctly for Panel interactivity. + +**Steps:** + +1. **Open dashboard in browser:** + ``` + http://localhost/2021community/ + ``` + +2. **Open browser DevTools (F12)** + +3. **Go to Network tab** + +4. **Filter by "WS" (WebSocket)** + +5. **Interact with dashboard** (click filters, buttons) + +**Expected Result:** +- ✅ WebSocket connection established (Status: 101 Switching Protocols) +- ✅ Messages flowing in both directions +- ✅ Interactive elements respond immediately +- ✅ No WebSocket errors in console + +**If WebSocket fails:** +- Check `nginx/vhost.d/default` file exists +- Check nginx-proxy logs for errors +- Restart nginx-proxy: `docker-compose restart nginx-proxy` + +--- + +### Scenario 4: Container Restart and Persistence Test + +**Goal:** Verify containers restart properly and maintain state. + +**Steps:** + +1. **Stop all containers:** + ```bash + docker-compose --env-file .env.local down + ``` + +2. **Verify containers stopped:** + ```bash + docker-compose ps + ``` + + Should show no running containers. + +3. **Start containers again:** + ```bash + docker-compose --env-file .env.local up -d + ``` + +4. **Verify dashboard accessible:** + ```bash + curl -I http://localhost/2021community + ``` + +5. **Check logs for clean startup:** + ```bash + docker-compose logs dashboard | tail -20 + ``` + +**Expected Result:** ✅ Clean restart, dashboard immediately accessible + +--- + +### Scenario 5: Build Cache and Rebuild Test + +**Goal:** Test that rebuilds work correctly (for code updates). + +**Steps:** + +1. **Make a small change to code** (e.g., add a comment): + ```bash + echo "# Test change" >> survey_dashboard/scripts.py + ``` + +2. **Rebuild and restart:** + ```bash + docker-compose --env-file .env.local up -d --build + ``` + +3. **Verify change is reflected:** + ```bash + docker-compose exec dashboard cat /app/survey_dashboard/scripts.py | tail -5 + ``` + +4. **Test dashboard still works:** + ```bash + curl -I http://localhost/2021community + ``` + +5. **Undo test change:** + ```bash + git checkout survey_dashboard/scripts.py + ``` + +**Expected Result:** ✅ Rebuild completes, changes reflected, dashboard works + +--- + +### Scenario 6: Different VIRTUAL_PATH Test + +**Goal:** Test that changing the path works correctly. + +**Steps:** + +1. **Stop containers:** + ```bash + docker-compose --env-file .env.local down + ``` + +2. **Edit .env.local to use different path:** + ```bash + # Change VIRTUAL_PATH=/2021community to VIRTUAL_PATH=/test-path + sed -i 's|VIRTUAL_PATH=/2021community|VIRTUAL_PATH=/test-path|' .env.local + ``` + +3. **Start with new path:** + ```bash + docker-compose --env-file .env.local up -d --build + ``` + +4. **Test new path:** + ```bash + curl -I http://localhost/test-path + ``` + + Expected: `HTTP/1.1 200 OK` + +5. **Test old path no longer works:** + ```bash + curl -I http://localhost/2021community + ``` + + Expected: `HTTP/1.1 404 Not Found` + +6. **Restore original path:** + ```bash + sed -i 's|VIRTUAL_PATH=/test-path|VIRTUAL_PATH=/2021community|' .env.local + docker-compose --env-file .env.local down + ``` + +**Expected Result:** ✅ Path change works, old path inaccessible + +--- + +### Scenario 7: Port Conflict Test + +**Goal:** Test behavior when port 80 is already in use. + +**Steps:** + +1. **Check if port 80 is available:** + ```bash + sudo lsof -i :80 + ``` + +2. **If port 80 is in use, use alternative port:** + + Edit `.env.local`: + ```env + NGINX_PORT=8080 + ``` + +3. **Update docker-compose ports** (temporary test): + ```bash + # This requires editing docker-compose.yml temporarily + # Change: "80:80" to "8080:80" + ``` + +4. **Start containers:** + ```bash + docker-compose --env-file .env.local up -d + ``` + +5. **Test on new port:** + ```bash + curl -I http://localhost:8080/2021community + ``` + +**Expected Result:** ✅ Works on alternative port + +**Note:** In production, you need port 80 for Let's Encrypt. This test just verifies flexibility. + +--- + +## Verification Steps + +### Complete Local Testing Checklist + +Run through this checklist to ensure everything works: + +- [ ] Docker images build without errors +- [ ] All 3 containers start successfully +- [ ] `docker-compose ps` shows all containers "Up" +- [ ] Dashboard logs show production mode with correct prefix +- [ ] nginx-proxy logs show configuration for localhost +- [ ] HTTP access works: `curl http://localhost/2021community/` +- [ ] Browser loads dashboard at `http://localhost/2021community/` +- [ ] Dashboard displays correctly with styling +- [ ] Interactive elements work (buttons, filters, plots) +- [ ] Browser console shows no errors (F12) +- [ ] WebSocket connection established (Network tab) +- [ ] Root path blocked: `http://localhost/` returns 404/503 +- [ ] Other paths blocked: `http://localhost/other` returns 404 +- [ ] Containers restart cleanly: `docker-compose down && up -d` +- [ ] Rebuild works: `docker-compose up -d --build` + +If all items are checked ✅, your setup is ready for production! + +--- + +## Troubleshooting + +### Issue 1: Port 80 Already in Use + +**Error:** +``` +Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use +``` + +**Cause:** Another service (Apache, nginx, etc.) is using port 80. + +**Solutions:** + +**Option A: Stop the conflicting service** +```bash +# Find what's using port 80 +sudo lsof -i :80 + +# Stop Apache (example) +sudo systemctl stop apache2 + +# Or stop nginx +sudo systemctl stop nginx +``` + +**Option B: Use a different port for testing** +```bash +# Edit .env.local +NGINX_PORT=8080 + +# Access via: http://localhost:8080/2021community +``` + +### Issue 2: Dashboard Container Exits Immediately + +**Check logs:** +```bash +docker-compose logs dashboard +``` + +**Common causes:** + +1. **Python error in code:** + - Look for Python tracebacks in logs + - Fix syntax or import errors + +2. **Missing dependencies:** + - Rebuild: `docker-compose up -d --build` + +3. **Wrong command:** + - Check Dockerfile CMD is correct + - Verify scripts.py is executable + +### Issue 3: 502 Bad Gateway + +**Cause:** nginx-proxy can't reach dashboard container. + +**Steps:** + +1. **Check dashboard is running:** + ```bash + docker-compose ps dashboard + ``` + +2. **Check dashboard logs for errors:** + ```bash + docker-compose logs dashboard + ``` + +3. **Verify containers are on same network:** + ```bash + docker network inspect survey-dashboard-local_default + ``` + + Should show both nginx-proxy and dashboard. + +4. **Restart both containers:** + ```bash + docker-compose restart nginx-proxy dashboard + ``` + +### Issue 4: WebSockets Not Working + +**Symptoms:** Dashboard loads but buttons/filters don't work. + +**Steps:** + +1. **Check vhost.d/default exists:** + ```bash + ls -la nginx/vhost.d/default + ``` + +2. **Verify WebSocket config content:** + ```bash + cat nginx/vhost.d/default + ``` + + Should contain: + ``` + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + ``` + +3. **Restart nginx-proxy:** + ```bash + docker-compose restart nginx-proxy + ``` + +4. **Check browser console (F12):** + - Look for WebSocket connection errors + - Should see successful WS connection + +### Issue 5: Changes Not Reflected After Rebuild + +**Cause:** Docker using cached layers. + +**Solution:** + +```bash +# Force complete rebuild without cache +docker-compose build --no-cache + +# Or rebuild specific service +docker-compose build --no-cache dashboard + +# Then restart +docker-compose up -d +``` + +### Issue 6: acme-companion Logs Show Errors + +**This is NORMAL for local testing!** + +acme-companion will show errors like: +``` +ERROR: localhost is not a valid domain for Let's Encrypt +``` + +**Why:** Let's Encrypt requires a real domain. This is expected with `HOST=localhost`. + +**Solution:** Ignore these errors during local testing. They won't occur in production with a real domain. + +--- + +## Cleanup + +### Stop and Remove Containers + +```bash +# Stop containers (preserves volumes) +docker-compose --env-file .env.local down + +# Stop and remove volumes (complete cleanup) +docker-compose --env-file .env.local down -v +``` + +### Remove Local Testing Environment File + +```bash +rm .env.local +``` + +### Remove Docker Images (Optional) + +```bash +# List images +docker images | grep survey-dashboard + +# Remove specific image +docker rmi survey-dashboard-local_dashboard + +# Remove all unused images +docker image prune -a +``` + +### Clean Up Nginx Directories + +If you want to start fresh: + +```bash +# Remove generated nginx files (certificates, etc.) +rm -rf nginx/certs/* +rm -rf nginx/html/* + +# Keep vhost.d/default (it's part of your config) +``` + +--- + +## Key Differences: Local vs Production + +| Aspect | Local Testing | Production | +|--------|---------------|------------| +| Domain | `localhost` | Real domain (e.g., `dashboard.survey.helmholtz-metadaten.de`) | +| HTTPS | ❌ Not available | ✅ Let's Encrypt SSL | +| Protocol | HTTP only | HTTPS (HTTP redirects to HTTPS) | +| Certificate | None | Valid Let's Encrypt certificate | +| Access | Only from local machine | Accessible from internet | +| DNS | Not needed | Must be configured | +| Firewall | Not needed | Ports 80, 443 must be open | +| Email | Dummy value | Real email for notifications | + +--- + +## What to Test Before Production + +### Critical Tests ✅ + +Run these tests locally before production deployment: + +1. **Docker Build:** `docker-compose build` completes without errors +2. **Container Startup:** All 3 containers start and stay running +3. **Dashboard Access:** Dashboard loads at correct path +4. **Path Routing:** Only specified path accessible, others blocked +5. **WebSockets:** Interactive elements work (check browser DevTools) +6. **Rebuild:** Code changes reflected after rebuild +7. **Restart:** Clean restart after `down` and `up` + +### Cannot Test Locally ⚠️ + +These can only be tested in production: + +1. **SSL/HTTPS:** Requires real domain +2. **Let's Encrypt:** Certificate acquisition +3. **DNS Resolution:** Public DNS records +4. **External Access:** Access from internet +5. **Auto-renewal:** Certificate renewal after 60 days + +--- + +## Quick Test Commands + +```bash +# Start local test environment +docker-compose --env-file .env.local up -d --build + +# Check status +docker-compose ps + +# Test HTTP access +curl -I http://localhost/2021community/ + +# Test root path is blocked +curl -I http://localhost/ + +# View logs +docker-compose logs -f dashboard + +# Stop and clean up +docker-compose --env-file .env.local down + +# Complete cleanup (removes volumes too) +docker-compose --env-file .env.local down -v +``` + +--- + +## Next Steps After Successful Local Testing + +Once all local tests pass: + +1. ✅ Review DEPLOYMENT.md for production steps +2. ✅ Ensure you have a real domain and it points to your VM +3. ✅ Create production `.env` file with real values +4. ✅ Follow DEPLOYMENT.md step-by-step on production VM +5. ✅ Monitor Let's Encrypt certificate acquisition +6. ✅ Verify HTTPS access works in production + +--- + +**Last Updated:** 2024-11-03 +**Purpose:** Local testing before production deployment +**Environment:** Docker Compose on local development machine diff --git a/survey_dashboard/devel_plots.ipynb b/docs/notebooks/devel_plots.ipynb similarity index 95% rename from survey_dashboard/devel_plots.ipynb rename to docs/notebooks/devel_plots.ipynb index 81d1838..a3a6b3b 100644 --- a/survey_dashboard/devel_plots.ipynb +++ b/docs/notebooks/devel_plots.ipynb @@ -63,287 +63,8 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function now() {\n", - " return new Date();\n", - " }\n", - "\n", - " const force = true;\n", - "\n", - " if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n", - " root._bokeh_onload_callbacks = [];\n", - " root._bokeh_is_loading = undefined;\n", - " }\n", - "\n", - "const JS_MIME_TYPE = 'application/javascript';\n", - " const HTML_MIME_TYPE = 'text/html';\n", - " const EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n", - " const CLASS_NAME = 'output_bokeh rendered_html';\n", - "\n", - " /**\n", - " * Render data to the DOM node\n", - " */\n", - " function render(props, node) {\n", - " const script = document.createElement(\"script\");\n", - " node.appendChild(script);\n", - " }\n", - "\n", - " /**\n", - " * Handle when an output is cleared or removed\n", - " */\n", - " function handleClearOutput(event, handle) {\n", - " const cell = handle.cell;\n", - "\n", - " const id = cell.output_area._bokeh_element_id;\n", - " const server_id = cell.output_area._bokeh_server_id;\n", - " // Clean up Bokeh references\n", - " if (id != null && id in Bokeh.index) {\n", - " Bokeh.index[id].model.document.clear();\n", - " delete Bokeh.index[id];\n", - " }\n", - "\n", - " if (server_id !== undefined) {\n", - " // Clean up Bokeh references\n", - " const cmd_clean = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n", - " cell.notebook.kernel.execute(cmd_clean, {\n", - " iopub: {\n", - " output: function(msg) {\n", - " const id = msg.content.text.trim();\n", - " if (id in Bokeh.index) {\n", - " Bokeh.index[id].model.document.clear();\n", - " delete Bokeh.index[id];\n", - " }\n", - " }\n", - " }\n", - " });\n", - " // Destroy server and session\n", - " const cmd_destroy = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n", - " cell.notebook.kernel.execute(cmd_destroy);\n", - " }\n", - " }\n", - "\n", - " /**\n", - " * Handle when a new output is added\n", - " */\n", - " function handleAddOutput(event, handle) {\n", - " const output_area = handle.output_area;\n", - " const output = handle.output;\n", - "\n", - " // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n", - " if ((output.output_type != \"display_data\") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {\n", - " return\n", - " }\n", - "\n", - " const toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", - "\n", - " if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n", - " toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n", - " // store reference to embed id on output_area\n", - " output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", - " }\n", - " if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", - " const bk_div = document.createElement(\"div\");\n", - " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", - " const script_attrs = bk_div.children[0].attributes;\n", - " for (let i = 0; i < script_attrs.length; i++) {\n", - " toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n", - " toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\n", - " }\n", - " // store reference to server id on output_area\n", - " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", - " }\n", - " }\n", - "\n", - " function register_renderer(events, OutputArea) {\n", - "\n", - " function append_mime(data, metadata, element) {\n", - " // create a DOM node to render to\n", - " const toinsert = this.create_output_subarea(\n", - " metadata,\n", - " CLASS_NAME,\n", - " EXEC_MIME_TYPE\n", - " );\n", - " this.keyboard_manager.register_events(toinsert);\n", - " // Render to node\n", - " const props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", - " render(props, toinsert[toinsert.length - 1]);\n", - " element.append(toinsert);\n", - " return toinsert\n", - " }\n", - "\n", - " /* Handle when an output is cleared or removed */\n", - " events.on('clear_output.CodeCell', handleClearOutput);\n", - " events.on('delete.Cell', handleClearOutput);\n", - "\n", - " /* Handle when a new output is added */\n", - " events.on('output_added.OutputArea', handleAddOutput);\n", - "\n", - " /**\n", - " * Register the mime type and append_mime function with output_area\n", - " */\n", - " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", - " /* Is output safe? */\n", - " safe: true,\n", - " /* Index of renderer in `output_area.display_order` */\n", - " index: 0\n", - " });\n", - " }\n", - "\n", - " // register the mime type if in Jupyter Notebook environment and previously unregistered\n", - " if (root.Jupyter !== undefined) {\n", - " const events = require('base/js/events');\n", - " const OutputArea = require('notebook/js/outputarea').OutputArea;\n", - "\n", - " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", - " register_renderer(events, OutputArea);\n", - " }\n", - " }\n", - " if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n", - " root._bokeh_timeout = Date.now() + 5000;\n", - " root._bokeh_failed_load = false;\n", - " }\n", - "\n", - " const NB_LOAD_WARNING = {'data': {'text/html':\n", - " \"
\\n\"+\n", - " \"

\\n\"+\n", - " \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n", - " \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n", - " \"

\\n\"+\n", - " \"\\n\"+\n", - " \"\\n\"+\n", - " \"from bokeh.resources import INLINE\\n\"+\n", - " \"output_notebook(resources=INLINE)\\n\"+\n", - " \"\\n\"+\n", - " \"
\"}};\n", - "\n", - " function display_loaded() {\n", - " const el = document.getElementById(\"33756\");\n", - " if (el != null) {\n", - " el.textContent = \"BokehJS is loading...\";\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " if (el != null) {\n", - " el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n", - " }\n", - " } else if (Date.now() < root._bokeh_timeout) {\n", - " setTimeout(display_loaded, 100)\n", - " }\n", - " }\n", - "\n", - " function run_callbacks() {\n", - " try {\n", - " root._bokeh_onload_callbacks.forEach(function(callback) {\n", - " if (callback != null)\n", - " callback();\n", - " });\n", - " } finally {\n", - " delete root._bokeh_onload_callbacks\n", - " }\n", - " console.debug(\"Bokeh: all callbacks have finished\");\n", - " }\n", - "\n", - " function load_libs(css_urls, js_urls, callback) {\n", - " if (css_urls == null) css_urls = [];\n", - " if (js_urls == null) js_urls = [];\n", - "\n", - " root._bokeh_onload_callbacks.push(callback);\n", - " if (root._bokeh_is_loading > 0) {\n", - " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", - " return null;\n", - " }\n", - " if (js_urls == null || js_urls.length === 0) {\n", - " run_callbacks();\n", - " return null;\n", - " }\n", - " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", - " root._bokeh_is_loading = css_urls.length + js_urls.length;\n", - "\n", - " function on_load() {\n", - " root._bokeh_is_loading--;\n", - " if (root._bokeh_is_loading === 0) {\n", - " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", - " run_callbacks()\n", - " }\n", - " }\n", - "\n", - " function on_error(url) {\n", - " console.error(\"failed to load \" + url);\n", - " }\n", - "\n", - " for (let i = 0; i < css_urls.length; i++) {\n", - " const url = css_urls[i];\n", - " const element = document.createElement(\"link\");\n", - " element.onload = on_load;\n", - " element.onerror = on_error.bind(null, url);\n", - " element.rel = \"stylesheet\";\n", - " element.type = \"text/css\";\n", - " element.href = url;\n", - " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", - " document.body.appendChild(element);\n", - " }\n", - "\n", - " for (let i = 0; i < js_urls.length; i++) {\n", - " const url = js_urls[i];\n", - " const element = document.createElement('script');\n", - " element.onload = on_load;\n", - " element.onerror = on_error.bind(null, url);\n", - " element.async = false;\n", - " element.src = url;\n", - " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", - " document.head.appendChild(element);\n", - " }\n", - " };\n", - "\n", - " function inject_raw_css(css) {\n", - " const element = document.createElement(\"style\");\n", - " element.appendChild(document.createTextNode(css));\n", - " document.body.appendChild(element);\n", - " }\n", - "\n", - " const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js\"];\n", - " const css_urls = [];\n", - "\n", - " const inline_js = [ function(Bokeh) {\n", - " Bokeh.set_log_level(\"info\");\n", - " },\n", - "function(Bokeh) {\n", - " }\n", - " ];\n", - "\n", - " function run_inline_js() {\n", - " if (root.Bokeh !== undefined || force === true) {\n", - " for (let i = 0; i < inline_js.length; i++) {\n", - " inline_js[i].call(root, root.Bokeh);\n", - " }\n", - "if (force === true) {\n", - " display_loaded();\n", - " }} else if (Date.now() < root._bokeh_timeout) {\n", - " setTimeout(run_inline_js, 100);\n", - " } else if (!root._bokeh_failed_load) {\n", - " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", - " root._bokeh_failed_load = true;\n", - " } else if (force !== true) {\n", - " const cell = $(document.getElementById(\"33756\")).parents('.cell').data().cell;\n", - " cell.output_area.append_execute_result(NB_LOAD_WARNING)\n", - " }\n", - " }\n", - "\n", - " if (root._bokeh_is_loading === 0) {\n", - " console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n", - " run_inline_js();\n", - " } else {\n", - " load_libs(css_urls, js_urls, function() {\n", - " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", - " run_inline_js();\n", - " });\n", - " }\n", - "}(window));" - ], - "application/vnd.bokehjs_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n const force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n const NB_LOAD_WARNING = {'data': {'text/html':\n \"
\\n\"+\n \"

\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"

\\n\"+\n \"\\n\"+\n \"\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"\\n\"+\n \"
\"}};\n\n function display_loaded() {\n const el = document.getElementById(\"33756\");\n if (el != null) {\n el.textContent = \"BokehJS is loading...\";\n }\n if (root.Bokeh !== undefined) {\n if (el != null) {\n el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(display_loaded, 100)\n }\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error(url) {\n console.error(\"failed to load \" + url);\n }\n\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js\"];\n const css_urls = [];\n\n const inline_js = [ function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {\n }\n ];\n\n function run_inline_js() {\n if (root.Bokeh !== undefined || force === true) {\n for (let i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }\nif (force === true) {\n display_loaded();\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n } else if (force !== true) {\n const cell = $(document.getElementById(\"33756\")).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));" + "application/javascript": "(function(root) {\n function now() {\n return new Date();\n }\n\n const force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\nconst JS_MIME_TYPE = 'application/javascript';\n const HTML_MIME_TYPE = 'text/html';\n const EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n const CLASS_NAME = 'output_bokeh rendered_html';\n\n /**\n * Render data to the DOM node\n */\n function render(props, node) {\n const script = document.createElement(\"script\");\n node.appendChild(script);\n }\n\n /**\n * Handle when an output is cleared or removed\n */\n function handleClearOutput(event, handle) {\n const cell = handle.cell;\n\n const id = cell.output_area._bokeh_element_id;\n const server_id = cell.output_area._bokeh_server_id;\n // Clean up Bokeh references\n if (id != null && id in Bokeh.index) {\n Bokeh.index[id].model.document.clear();\n delete Bokeh.index[id];\n }\n\n if (server_id !== undefined) {\n // Clean up Bokeh references\n const cmd_clean = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n cell.notebook.kernel.execute(cmd_clean, {\n iopub: {\n output: function(msg) {\n const id = msg.content.text.trim();\n if (id in Bokeh.index) {\n Bokeh.index[id].model.document.clear();\n delete Bokeh.index[id];\n }\n }\n }\n });\n // Destroy server and session\n const cmd_destroy = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n cell.notebook.kernel.execute(cmd_destroy);\n }\n }\n\n /**\n * Handle when a new output is added\n */\n function handleAddOutput(event, handle) {\n const output_area = handle.output_area;\n const output = handle.output;\n\n // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n if ((output.output_type != \"display_data\") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {\n return\n }\n\n const toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n\n if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n // store reference to embed id on output_area\n output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n }\n if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n const bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n const script_attrs = bk_div.children[0].attributes;\n for (let i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n }\n\n function register_renderer(events, OutputArea) {\n\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n const toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n const props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[toinsert.length - 1]);\n element.append(toinsert);\n return toinsert\n }\n\n /* Handle when an output is cleared or removed */\n events.on('clear_output.CodeCell', handleClearOutput);\n events.on('delete.Cell', handleClearOutput);\n\n /* Handle when a new output is added */\n events.on('output_added.OutputArea', handleAddOutput);\n\n /**\n * Register the mime type and append_mime function with output_area\n */\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n /* Is output safe? */\n safe: true,\n /* Index of renderer in `output_area.display_order` */\n index: 0\n });\n }\n\n // register the mime type if in Jupyter Notebook environment and previously unregistered\n if (root.Jupyter !== undefined) {\n const events = require('base/js/events');\n const OutputArea = require('notebook/js/outputarea').OutputArea;\n\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n }\n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n const NB_LOAD_WARNING = {'data': {'text/html':\n \"
\\n\"+\n \"

\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"

\\n\"+\n \"\\n\"+\n \"\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"\\n\"+\n \"
\"}};\n\n function display_loaded() {\n const el = document.getElementById(\"33756\");\n if (el != null) {\n el.textContent = \"BokehJS is loading...\";\n }\n if (root.Bokeh !== undefined) {\n if (el != null) {\n el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(display_loaded, 100)\n }\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error(url) {\n console.error(\"failed to load \" + url);\n }\n\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js\"];\n const css_urls = [];\n\n const inline_js = [ function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {\n }\n ];\n\n function run_inline_js() {\n if (root.Bokeh !== undefined || force === true) {\n for (let i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }\nif (force === true) {\n display_loaded();\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n } else if (force !== true) {\n const cell = $(document.getElementById(\"33756\")).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));", + "application/vnd.bokehjs_load.v0+json": "" }, "metadata": {}, "output_type": "display_data" @@ -364,426 +85,16 @@ "outputs": [ { "data": { - "application/javascript": [ - "(function(root) {\n", - " function now() {\n", - " return new Date();\n", - " }\n", - "\n", - " var force = true;\n", - "\n", - " if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n", - " root._bokeh_onload_callbacks = [];\n", - " root._bokeh_is_loading = undefined;\n", - " }\n", - "\n", - " if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n", - " root._bokeh_timeout = Date.now() + 5000;\n", - " root._bokeh_failed_load = false;\n", - " }\n", - "\n", - " function run_callbacks() {\n", - " try {\n", - " root._bokeh_onload_callbacks.forEach(function(callback) {\n", - " if (callback != null)\n", - " callback();\n", - " });\n", - " } finally {\n", - " delete root._bokeh_onload_callbacks\n", - " }\n", - " console.debug(\"Bokeh: all callbacks have finished\");\n", - " }\n", - "\n", - " function load_libs(css_urls, js_urls, js_modules, callback) {\n", - " if (css_urls == null) css_urls = [];\n", - " if (js_urls == null) js_urls = [];\n", - " if (js_modules == null) js_modules = [];\n", - "\n", - " root._bokeh_onload_callbacks.push(callback);\n", - " if (root._bokeh_is_loading > 0) {\n", - " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", - " return null;\n", - " }\n", - " if (js_urls.length === 0 && js_modules.length === 0) {\n", - " run_callbacks();\n", - " return null;\n", - " }\n", - " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", - "\n", - " function on_load() {\n", - " root._bokeh_is_loading--;\n", - " if (root._bokeh_is_loading === 0) {\n", - " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", - " run_callbacks()\n", - " }\n", - " }\n", - "\n", - " function on_error() {\n", - " console.error(\"failed to load \" + url);\n", - " }\n", - "\n", - " for (var i = 0; i < css_urls.length; i++) {\n", - " var url = css_urls[i];\n", - " const element = document.createElement(\"link\");\n", - " element.onload = on_load;\n", - " element.onerror = on_error;\n", - " element.rel = \"stylesheet\";\n", - " element.type = \"text/css\";\n", - " element.href = url;\n", - " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", - " document.body.appendChild(element);\n", - " }\n", - "\n", - " var skip = [];\n", - " if (window.requirejs) {\n", - " window.requirejs.config({'packages': {}, 'paths': {'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'gridstack': {'exports': 'GridStack'}}});\n", - " require([\"gridstack\"], function(GridStack) {\n", - "\twindow.GridStack = GridStack\n", - "\ton_load()\n", - " })\n", - " require([\"notyf\"], function() {\n", - "\ton_load()\n", - " })\n", - " root._bokeh_is_loading = css_urls.length + 2;\n", - " } else {\n", - " root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length;\n", - " } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n", - " var urls = ['https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5.js'];\n", - " for (var i = 0; i < urls.length; i++) {\n", - " skip.push(urls[i])\n", - " }\n", - " } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n", - " var urls = ['https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js'];\n", - " for (var i = 0; i < urls.length; i++) {\n", - " skip.push(urls[i])\n", - " }\n", - " } for (var i = 0; i < js_urls.length; i++) {\n", - " var url = js_urls[i];\n", - " if (skip.indexOf(url) >= 0) {\n", - "\tif (!window.requirejs) {\n", - "\t on_load();\n", - "\t}\n", - "\tcontinue;\n", - " }\n", - " var element = document.createElement('script');\n", - " element.onload = on_load;\n", - " element.onerror = on_error;\n", - " element.async = false;\n", - " element.src = url;\n", - " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", - " document.head.appendChild(element);\n", - " }\n", - " for (var i = 0; i < js_modules.length; i++) {\n", - " var url = js_modules[i];\n", - " if (skip.indexOf(url) >= 0) {\n", - "\tif (!window.requirejs) {\n", - "\t on_load();\n", - "\t}\n", - "\tcontinue;\n", - " }\n", - " var element = document.createElement('script');\n", - " element.onload = on_load;\n", - " element.onerror = on_error;\n", - " element.async = false;\n", - " element.src = url;\n", - " element.type = \"module\";\n", - " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", - " document.head.appendChild(element);\n", - " }\n", - " if (!js_urls.length && !js_modules.length) {\n", - " on_load()\n", - " }\n", - " };\n", - "\n", - " function inject_raw_css(css) {\n", - " const element = document.createElement(\"style\");\n", - " element.appendChild(document.createTextNode(css));\n", - " document.body.appendChild(element);\n", - " }\n", - "\n", - " var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js\", \"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js\"];\n", - " var js_modules = [];\n", - " var css_urls = [\"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.css\", \"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/debugger.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/dataframe.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/alerts.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/loading.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/json.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/card.css\"];\n", - " var inline_js = [ function(Bokeh) {\n", - " inject_raw_css(\"\\n .bk.pn-loading.arcs:before {\\n background-image: url(\\\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0ibWFyZ2luOiBhdXRvOyBiYWNrZ3JvdW5kOiBub25lOyBkaXNwbGF5OiBibG9jazsgc2hhcGUtcmVuZGVyaW5nOiBhdXRvOyIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4gIDxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjMyIiBzdHJva2Utd2lkdGg9IjgiIHN0cm9rZT0iI2MzYzNjMyIgc3Ryb2tlLWRhc2hhcnJheT0iNTAuMjY1NDgyNDU3NDM2NjkgNTAuMjY1NDgyNDU3NDM2NjkiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+ICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0icm90YXRlIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgZHVyPSIxcyIga2V5VGltZXM9IjA7MSIgdmFsdWVzPSIwIDUwIDUwOzM2MCA1MCA1MCI+PC9hbmltYXRlVHJhbnNmb3JtPiAgPC9jaXJjbGU+PC9zdmc+\\\");\\n background-size: auto calc(min(50%, 400px));\\n }\\n \");\n", - " }, function(Bokeh) {\n", - " Bokeh.set_log_level(\"info\");\n", - " },\n", - "function(Bokeh) {} // ensure no trailing comma for IE\n", - " ];\n", - "\n", - " function run_inline_js() {\n", - " if ((root.Bokeh !== undefined) || (force === true)) {\n", - " for (var i = 0; i < inline_js.length; i++) {\n", - " inline_js[i].call(root, root.Bokeh);\n", - " }} else if (Date.now() < root._bokeh_timeout) {\n", - " setTimeout(run_inline_js, 100);\n", - " } else if (!root._bokeh_failed_load) {\n", - " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", - " root._bokeh_failed_load = true;\n", - " }\n", - " }\n", - "\n", - " if (root._bokeh_is_loading === 0) {\n", - " console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n", - " run_inline_js();\n", - " } else {\n", - " load_libs(css_urls, js_urls, js_modules, function() {\n", - " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", - " run_inline_js();\n", - " });\n", - " }\n", - "}(window));" - ], - "application/vnd.holoviews_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls.length === 0 && js_modules.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n var skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'gridstack': {'exports': 'GridStack'}}});\n require([\"gridstack\"], function(GridStack) {\n\twindow.GridStack = GridStack\n\ton_load()\n })\n require([\"notyf\"], function() {\n\ton_load()\n })\n root._bokeh_is_loading = css_urls.length + 2;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length;\n } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n if (skip.indexOf(url) >= 0) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (var i = 0; i < js_modules.length; i++) {\n var url = js_modules[i];\n if (skip.indexOf(url) >= 0) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js\", \"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js\"];\n var js_modules = [];\n var css_urls = [\"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.css\", \"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/debugger.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/dataframe.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/alerts.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/loading.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/json.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/card.css\"];\n var inline_js = [ function(Bokeh) {\n inject_raw_css(\"\\n .bk.pn-loading.arcs:before {\\n background-image: url(\\\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0ibWFyZ2luOiBhdXRvOyBiYWNrZ3JvdW5kOiBub25lOyBkaXNwbGF5OiBibG9jazsgc2hhcGUtcmVuZGVyaW5nOiBhdXRvOyIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4gIDxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjMyIiBzdHJva2Utd2lkdGg9IjgiIHN0cm9rZT0iI2MzYzNjMyIgc3Ryb2tlLWRhc2hhcnJheT0iNTAuMjY1NDgyNDU3NDM2NjkgNTAuMjY1NDgyNDU3NDM2NjkiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+ICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0icm90YXRlIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgZHVyPSIxcyIga2V5VGltZXM9IjA7MSIgdmFsdWVzPSIwIDUwIDUwOzM2MCA1MCA1MCI+PC9hbmltYXRlVHJhbnNmb3JtPiAgPC9jaXJjbGU+PC9zdmc+\\\");\\n background-size: auto calc(min(50%, 400px));\\n }\\n \");\n }, function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, js_modules, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));" + "application/javascript": "(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls.length === 0 && js_modules.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n var skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'gridstack': {'exports': 'GridStack'}}});\n require([\"gridstack\"], function(GridStack) {\n\twindow.GridStack = GridStack\n\ton_load()\n })\n require([\"notyf\"], function() {\n\ton_load()\n })\n root._bokeh_is_loading = css_urls.length + 2;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length;\n } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n if (skip.indexOf(url) >= 0) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (var i = 0; i < js_modules.length; i++) {\n var url = js_modules[i];\n if (skip.indexOf(url) >= 0) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js\", \"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js\"];\n var js_modules = [];\n var css_urls = [\"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.css\", \"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/debugger.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/dataframe.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/alerts.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/loading.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/json.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/card.css\"];\n var inline_js = [ function(Bokeh) {\n inject_raw_css(\"\\n .bk.pn-loading.arcs:before {\\n background-image: url(\\\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0ibWFyZ2luOiBhdXRvOyBiYWNrZ3JvdW5kOiBub25lOyBkaXNwbGF5OiBibG9jazsgc2hhcGUtcmVuZGVyaW5nOiBhdXRvOyIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4gIDxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjMyIiBzdHJva2Utd2lkdGg9IjgiIHN0cm9rZT0iI2MzYzNjMyIgc3Ryb2tlLWRhc2hhcnJheT0iNTAuMjY1NDgyNDU3NDM2NjkgNTAuMjY1NDgyNDU3NDM2NjkiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+ICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0icm90YXRlIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgZHVyPSIxcyIga2V5VGltZXM9IjA7MSIgdmFsdWVzPSIwIDUwIDUwOzM2MCA1MCA1MCI+PC9hbmltYXRlVHJhbnNmb3JtPiAgPC9jaXJjbGU+PC9zdmc+\\\");\\n background-size: auto calc(min(50%, 400px));\\n }\\n \");\n }, function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, js_modules, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));", + "application/vnd.holoviews_load.v0+json": "" }, "metadata": {}, "output_type": "display_data" }, { "data": { - "application/javascript": [ - "\n", - "if ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n", - " window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n", - "}\n", - "\n", - "\n", - " function JupyterCommManager() {\n", - " }\n", - "\n", - " JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n", - " if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", - " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", - " comm_manager.register_target(comm_id, function(comm) {\n", - " comm.on_msg(msg_handler);\n", - " });\n", - " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", - " window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n", - " comm.onMsg = msg_handler;\n", - " });\n", - " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", - " google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n", - " var messages = comm.messages[Symbol.asyncIterator]();\n", - " function processIteratorResult(result) {\n", - " var message = result.value;\n", - " console.log(message)\n", - " var content = {data: message.data, comm_id};\n", - " var buffers = []\n", - " for (var buffer of message.buffers || []) {\n", - " buffers.push(new DataView(buffer))\n", - " }\n", - " var metadata = message.metadata || {};\n", - " var msg = {content, buffers, metadata}\n", - " msg_handler(msg);\n", - " return messages.next().then(processIteratorResult);\n", - " }\n", - " return messages.next().then(processIteratorResult);\n", - " })\n", - " }\n", - " }\n", - "\n", - " JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n", - " if (comm_id in window.PyViz.comms) {\n", - " return window.PyViz.comms[comm_id];\n", - " } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", - " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", - " var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n", - " if (msg_handler) {\n", - " comm.on_msg(msg_handler);\n", - " }\n", - " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", - " var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n", - " comm.open();\n", - " if (msg_handler) {\n", - " comm.onMsg = msg_handler;\n", - " }\n", - " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", - " var comm_promise = google.colab.kernel.comms.open(comm_id)\n", - " comm_promise.then((comm) => {\n", - " window.PyViz.comms[comm_id] = comm;\n", - " if (msg_handler) {\n", - " var messages = comm.messages[Symbol.asyncIterator]();\n", - " function processIteratorResult(result) {\n", - " var message = result.value;\n", - " var content = {data: message.data};\n", - " var metadata = message.metadata || {comm_id};\n", - " var msg = {content, metadata}\n", - " msg_handler(msg);\n", - " return messages.next().then(processIteratorResult);\n", - " }\n", - " return messages.next().then(processIteratorResult);\n", - " }\n", - " }) \n", - " var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n", - " return comm_promise.then((comm) => {\n", - " comm.send(data, metadata, buffers, disposeOnDone);\n", - " });\n", - " };\n", - " var comm = {\n", - " send: sendClosure\n", - " };\n", - " }\n", - " window.PyViz.comms[comm_id] = comm;\n", - " return comm;\n", - " }\n", - " window.PyViz.comm_manager = new JupyterCommManager();\n", - " \n", - "\n", - "\n", - "var JS_MIME_TYPE = 'application/javascript';\n", - "var HTML_MIME_TYPE = 'text/html';\n", - "var EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\n", - "var CLASS_NAME = 'output';\n", - "\n", - "/**\n", - " * Render data to the DOM node\n", - " */\n", - "function render(props, node) {\n", - " var div = document.createElement(\"div\");\n", - " var script = document.createElement(\"script\");\n", - " node.appendChild(div);\n", - " node.appendChild(script);\n", - "}\n", - "\n", - "/**\n", - " * Handle when a new output is added\n", - " */\n", - "function handle_add_output(event, handle) {\n", - " var output_area = handle.output_area;\n", - " var output = handle.output;\n", - " if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", - " return\n", - " }\n", - " var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", - " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", - " if (id !== undefined) {\n", - " var nchildren = toinsert.length;\n", - " var html_node = toinsert[nchildren-1].children[0];\n", - " html_node.innerHTML = output.data[HTML_MIME_TYPE];\n", - " var scripts = [];\n", - " var nodelist = html_node.querySelectorAll(\"script\");\n", - " for (var i in nodelist) {\n", - " if (nodelist.hasOwnProperty(i)) {\n", - " scripts.push(nodelist[i])\n", - " }\n", - " }\n", - "\n", - " scripts.forEach( function (oldScript) {\n", - " var newScript = document.createElement(\"script\");\n", - " var attrs = [];\n", - " var nodemap = oldScript.attributes;\n", - " for (var j in nodemap) {\n", - " if (nodemap.hasOwnProperty(j)) {\n", - " attrs.push(nodemap[j])\n", - " }\n", - " }\n", - " attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n", - " newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n", - " oldScript.parentNode.replaceChild(newScript, oldScript);\n", - " });\n", - " if (JS_MIME_TYPE in output.data) {\n", - " toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n", - " }\n", - " output_area._hv_plot_id = id;\n", - " if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n", - " window.PyViz.plot_index[id] = Bokeh.index[id];\n", - " } else {\n", - " window.PyViz.plot_index[id] = null;\n", - " }\n", - " } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", - " var bk_div = document.createElement(\"div\");\n", - " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", - " var script_attrs = bk_div.children[0].attributes;\n", - " for (var i = 0; i < script_attrs.length; i++) {\n", - " toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n", - " }\n", - " // store reference to server id on output_area\n", - " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", - " }\n", - "}\n", - "\n", - "/**\n", - " * Handle when an output is cleared or removed\n", - " */\n", - "function handle_clear_output(event, handle) {\n", - " var id = handle.cell.output_area._hv_plot_id;\n", - " var server_id = handle.cell.output_area._bokeh_server_id;\n", - " if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n", - " var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n", - " if (server_id !== null) {\n", - " comm.send({event_type: 'server_delete', 'id': server_id});\n", - " return;\n", - " } else if (comm !== null) {\n", - " comm.send({event_type: 'delete', 'id': id});\n", - " }\n", - " delete PyViz.plot_index[id];\n", - " if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n", - " var doc = window.Bokeh.index[id].model.document\n", - " doc.clear();\n", - " const i = window.Bokeh.documents.indexOf(doc);\n", - " if (i > -1) {\n", - " window.Bokeh.documents.splice(i, 1);\n", - " }\n", - " }\n", - "}\n", - "\n", - "/**\n", - " * Handle kernel restart event\n", - " */\n", - "function handle_kernel_cleanup(event, handle) {\n", - " delete PyViz.comms[\"hv-extension-comm\"];\n", - " window.PyViz.plot_index = {}\n", - "}\n", - "\n", - "/**\n", - " * Handle update_display_data messages\n", - " */\n", - "function handle_update_output(event, handle) {\n", - " handle_clear_output(event, {cell: {output_area: handle.output_area}})\n", - " handle_add_output(event, handle)\n", - "}\n", - "\n", - "function register_renderer(events, OutputArea) {\n", - " function append_mime(data, metadata, element) {\n", - " // create a DOM node to render to\n", - " var toinsert = this.create_output_subarea(\n", - " metadata,\n", - " CLASS_NAME,\n", - " EXEC_MIME_TYPE\n", - " );\n", - " this.keyboard_manager.register_events(toinsert);\n", - " // Render to node\n", - " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", - " render(props, toinsert[0]);\n", - " element.append(toinsert);\n", - " return toinsert\n", - " }\n", - "\n", - " events.on('output_added.OutputArea', handle_add_output);\n", - " events.on('output_updated.OutputArea', handle_update_output);\n", - " events.on('clear_output.CodeCell', handle_clear_output);\n", - " events.on('delete.Cell', handle_clear_output);\n", - " events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n", - "\n", - " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", - " safe: true,\n", - " index: 0\n", - " });\n", - "}\n", - "\n", - "if (window.Jupyter !== undefined) {\n", - " try {\n", - " var events = require('base/js/events');\n", - " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", - " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", - " register_renderer(events, OutputArea);\n", - " }\n", - " } catch(err) {\n", - " }\n", - "}\n" - ], - "application/vnd.holoviews_load.v0+json": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n console.log(message)\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n comm.open();\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n }) \n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n" + "application/javascript": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n console.log(message)\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n comm.open();\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n }) \n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n", + "application/vnd.holoviews_load.v0+json": "" }, "metadata": {}, "output_type": "display_data" @@ -1157,32 +468,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"90a16b69-8ae9-4a91-b725-4b57cd359465\":{\"version\":\"3.0.0.dev13\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"22960\",\"attributes\":{\"toolbar_location\":\"above\",\"x_scale\":{\"type\":\"object\",\"name\":\"CategoricalScale\",\"id\":\"22972\"},\"y_range\":{\"type\":\"object\",\"name\":\"FactorRange\",\"id\":\"22970\",\"attributes\":{\"factors\":[\"No\",\"I am not sure\",\"Yes\"]}},\"left\":[{\"type\":\"object\",\"name\":\"CategoricalAxis\",\"id\":\"22982\",\"attributes\":{\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"22985\"},\"axis_line_alpha\":0,\"formatter\":{\"type\":\"object\",\"name\":\"CategoricalTickFormatter\",\"id\":\"22983\"},\"ticker\":{\"type\":\"object\",\"name\":\"CategoricalTicker\",\"id\":\"22984\"}}}],\"width\":900,\"x_range\":{\"type\":\"object\",\"name\":\"FactorRange\",\"id\":\"22968\",\"attributes\":{\"factors\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]}},\"below\":[{\"type\":\"object\",\"name\":\"CategoricalAxis\",\"id\":\"22976\",\"attributes\":{\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"22979\"},\"axis_line_alpha\":0,\"major_label_orientation\":1,\"formatter\":{\"type\":\"object\",\"name\":\"CategoricalTickFormatter\",\"id\":\"22977\"},\"ticker\":{\"type\":\"object\",\"name\":\"CategoricalTicker\",\"id\":\"22978\"}}}],\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"22961\",\"attributes\":{\"text\":\"title\"}},\"y_scale\":{\"type\":\"object\",\"name\":\"CategoricalScale\",\"id\":\"22974\"},\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"23010\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"23007\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#A0235A\"},\"size\":{\"type\":\"field\",\"field\":\"percentage\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#A0235A\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"field\",\"field\":\"docStructured\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"23011\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"23012\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"23006\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#A0235A\"},\"size\":{\"type\":\"field\",\"field\":\"percentage\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#A0235A\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.6},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.6},\"y\":{\"type\":\"field\",\"field\":\"docStructured\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.6}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"23008\",\"attributes\":{\"fill_color\":{\"type\":\"value\",\"value\":\"#A0235A\"},\"size\":{\"type\":\"field\",\"field\":\"percentage\"},\"line_width\":{\"type\":\"value\",\"value\":5},\"y\":{\"type\":\"field\",\"field\":\"docStructured\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"23009\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#A0235A\"},\"size\":{\"type\":\"field\",\"field\":\"percentage\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#A0235A\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"field\",\"field\":\"docStructured\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"22957\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"22958\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"index\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAACQAAAAoAAAALAAAADAAAAA0AAAAOAAAADwAAABAAAAARAAAAEgAAABMAAAAUAAAA\"},\"shape\":[21],\"dtype\":\"int32\",\"order\":\"little\"}],[\"careerLevel\",{\"type\":\"ndarray\",\"array\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\",\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\",\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"],\"shape\":[21],\"dtype\":\"object\",\"order\":\"little\"}],[\"docStructured\",{\"type\":\"ndarray\",\"array\":[\"I am not sure\",\"I am not sure\",\"I am not sure\",\"I am not sure\",\"I am not sure\",\"I am not sure\",\"I am not sure\",\"No\",\"No\",\"No\",\"No\",\"No\",\"No\",\"No\",\"Yes\",\"Yes\",\"Yes\",\"Yes\",\"Yes\",\"Yes\",\"Yes\"],\"shape\":[21],\"dtype\":\"object\",\"order\":\"little\"}],[\"value\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AQAAAAIAAAAUAAAAHwAAABMAAAAbAAAAAQAAAAYAAAANAAAAIAAAADAAAAAnAAAAWgAAAAQAAAADAAAAFQAAABkAAAASAAAAJwAAAD4AAAAKAAAA\"},\"shape\":[21],\"dtype\":\"int32\",\"order\":\"little\"}],[\"total\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"FgAAAEEAAACCAAAAgAAAAJQAAAAQAQAAGAAAABYAAABBAAAAggAAAIAAAACUAAAAEAEAABgAAAAWAAAAQQAAAIIAAACAAAAAlAAAABABAAAYAAAA\"},\"shape\":[21],\"dtype\":\"int32\",\"order\":\"little\"}],[\"percentage\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"L7rooosuEkDZiZ3YiZ0IQE/sxE7sxC5AAAAAAAA4OEDPusEU+awpQFpaWlpa2iNAqqqqqqqqEEBFF1100UU7QAAAAAAAADRA2Ymd2ImdOEAAAAAAAMBCQJ51gynyWTpAS0tLS0uLQECqqqqqqqowQEUXXXTRRStAdmIndmInQECyEzuxEzszQAAAAAAAICxAnnWDKfJZOkBLS0tLS8s2QFZVVVVV1URA\"},\"shape\":[21],\"dtype\":\"float64\",\"order\":\"little\"}],[\"markersize\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"oGSaLeY+A0CLDhvcPqv/P9lcpYkWtBFAenvDhFA2FkCyj9iBASwQQB9myiLbcAxAWLvckyVtAkD4AS3HMZIXQJtnjBpgLxRAO0OVNLBkFkAFGctduKMbQPZGJcZjKxdA40IJVnv2GUBYu9yTJW0SQL9QKN/RqhBAL5LhmJ6nGUAX6ZBJB8sTQLZxPtv57BBA9kYlxmMrF0B0JV0PiYwVQPcKncV2Ih1A\"},\"shape\":[21],\"dtype\":\"float64\",\"order\":\"little\"}]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"22959\"}}}}}],\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"22967\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"HoverTool\",\"id\":\"22988\",\"attributes\":{\"tooltips\":[[\"careerLevel\",\"@careerLevel\"],[\"docStructured\",\"@docStructured\"],[\"total\",\"@total\"],[\"percentage\",\"@percentage\"]],\"renderers\":\"auto\"}},{\"type\":\"object\",\"name\":\"WheelZoomTool\",\"id\":\"22989\"},{\"type\":\"object\",\"name\":\"BoxZoomTool\",\"id\":\"22990\",\"attributes\":{\"overlay\":{\"type\":\"object\",\"name\":\"BoxAnnotation\",\"id\":\"22991\",\"attributes\":{\"fill_alpha\":0.5,\"syncable\":false,\"line_color\":\"black\",\"level\":\"overlay\",\"fill_color\":\"lightgrey\",\"line_width\":2,\"line_alpha\":1.0,\"visible\":false,\"bottom_units\":\"canvas\",\"line_dash\":[4,4],\"right_units\":\"canvas\",\"top_units\":\"canvas\",\"left_units\":\"canvas\"}}}},{\"type\":\"object\",\"name\":\"UndoTool\",\"id\":\"22992\"},{\"type\":\"object\",\"name\":\"ResetTool\",\"id\":\"22993\"},{\"type\":\"object\",\"name\":\"SaveTool\",\"id\":\"22994\"}]}},\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"22981\",\"attributes\":{\"axis\":{\"id\":\"22976\"}}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"22987\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"22982\"}}}]}}]}};\n", - " const render_items = [{\"docid\":\"90a16b69-8ae9-4a91-b725-4b57cd359465\",\"roots\":{\"22960\":\"de1dda22-2abf-413d-9878-7a5616aefeb8\"},\"root_ids\":[\"22960\"]}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"90a16b69-8ae9-4a91-b725-4b57cd359465\":{\"version\":\"3.0.0.dev13\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"22960\",\"attributes\":{\"toolbar_location\":\"above\",\"x_scale\":{\"type\":\"object\",\"name\":\"CategoricalScale\",\"id\":\"22972\"},\"y_range\":{\"type\":\"object\",\"name\":\"FactorRange\",\"id\":\"22970\",\"attributes\":{\"factors\":[\"No\",\"I am not sure\",\"Yes\"]}},\"left\":[{\"type\":\"object\",\"name\":\"CategoricalAxis\",\"id\":\"22982\",\"attributes\":{\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"22985\"},\"axis_line_alpha\":0,\"formatter\":{\"type\":\"object\",\"name\":\"CategoricalTickFormatter\",\"id\":\"22983\"},\"ticker\":{\"type\":\"object\",\"name\":\"CategoricalTicker\",\"id\":\"22984\"}}}],\"width\":900,\"x_range\":{\"type\":\"object\",\"name\":\"FactorRange\",\"id\":\"22968\",\"attributes\":{\"factors\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]}},\"below\":[{\"type\":\"object\",\"name\":\"CategoricalAxis\",\"id\":\"22976\",\"attributes\":{\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"22979\"},\"axis_line_alpha\":0,\"major_label_orientation\":1,\"formatter\":{\"type\":\"object\",\"name\":\"CategoricalTickFormatter\",\"id\":\"22977\"},\"ticker\":{\"type\":\"object\",\"name\":\"CategoricalTicker\",\"id\":\"22978\"}}}],\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"22961\",\"attributes\":{\"text\":\"title\"}},\"y_scale\":{\"type\":\"object\",\"name\":\"CategoricalScale\",\"id\":\"22974\"},\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"23010\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"23007\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#A0235A\"},\"size\":{\"type\":\"field\",\"field\":\"percentage\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#A0235A\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"field\",\"field\":\"docStructured\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"23011\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"23012\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"23006\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#A0235A\"},\"size\":{\"type\":\"field\",\"field\":\"percentage\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#A0235A\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.6},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.6},\"y\":{\"type\":\"field\",\"field\":\"docStructured\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.6}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"23008\",\"attributes\":{\"fill_color\":{\"type\":\"value\",\"value\":\"#A0235A\"},\"size\":{\"type\":\"field\",\"field\":\"percentage\"},\"line_width\":{\"type\":\"value\",\"value\":5},\"y\":{\"type\":\"field\",\"field\":\"docStructured\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"23009\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#A0235A\"},\"size\":{\"type\":\"field\",\"field\":\"percentage\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#A0235A\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"field\",\"field\":\"docStructured\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"22957\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"22958\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"index\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAACQAAAAoAAAALAAAADAAAAA0AAAAOAAAADwAAABAAAAARAAAAEgAAABMAAAAUAAAA\"},\"shape\":[21],\"dtype\":\"int32\",\"order\":\"little\"}],[\"careerLevel\",{\"type\":\"ndarray\",\"array\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\",\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\",\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"],\"shape\":[21],\"dtype\":\"object\",\"order\":\"little\"}],[\"docStructured\",{\"type\":\"ndarray\",\"array\":[\"I am not sure\",\"I am not sure\",\"I am not sure\",\"I am not sure\",\"I am not sure\",\"I am not sure\",\"I am not sure\",\"No\",\"No\",\"No\",\"No\",\"No\",\"No\",\"No\",\"Yes\",\"Yes\",\"Yes\",\"Yes\",\"Yes\",\"Yes\",\"Yes\"],\"shape\":[21],\"dtype\":\"object\",\"order\":\"little\"}],[\"value\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AQAAAAIAAAAUAAAAHwAAABMAAAAbAAAAAQAAAAYAAAANAAAAIAAAADAAAAAnAAAAWgAAAAQAAAADAAAAFQAAABkAAAASAAAAJwAAAD4AAAAKAAAA\"},\"shape\":[21],\"dtype\":\"int32\",\"order\":\"little\"}],[\"total\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"FgAAAEEAAACCAAAAgAAAAJQAAAAQAQAAGAAAABYAAABBAAAAggAAAIAAAACUAAAAEAEAABgAAAAWAAAAQQAAAIIAAACAAAAAlAAAABABAAAYAAAA\"},\"shape\":[21],\"dtype\":\"int32\",\"order\":\"little\"}],[\"percentage\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"L7rooosuEkDZiZ3YiZ0IQE/sxE7sxC5AAAAAAAA4OEDPusEU+awpQFpaWlpa2iNAqqqqqqqqEEBFF1100UU7QAAAAAAAADRA2Ymd2ImdOEAAAAAAAMBCQJ51gynyWTpAS0tLS0uLQECqqqqqqqowQEUXXXTRRStAdmIndmInQECyEzuxEzszQAAAAAAAICxAnnWDKfJZOkBLS0tLS8s2QFZVVVVV1URA\"},\"shape\":[21],\"dtype\":\"float64\",\"order\":\"little\"}],[\"markersize\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"oGSaLeY+A0CLDhvcPqv/P9lcpYkWtBFAenvDhFA2FkCyj9iBASwQQB9myiLbcAxAWLvckyVtAkD4AS3HMZIXQJtnjBpgLxRAO0OVNLBkFkAFGctduKMbQPZGJcZjKxdA40IJVnv2GUBYu9yTJW0SQL9QKN/RqhBAL5LhmJ6nGUAX6ZBJB8sTQLZxPtv57BBA9kYlxmMrF0B0JV0PiYwVQPcKncV2Ih1A\"},\"shape\":[21],\"dtype\":\"float64\",\"order\":\"little\"}]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"22959\"}}}}}],\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"22967\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"HoverTool\",\"id\":\"22988\",\"attributes\":{\"tooltips\":[[\"careerLevel\",\"@careerLevel\"],[\"docStructured\",\"@docStructured\"],[\"total\",\"@total\"],[\"percentage\",\"@percentage\"]],\"renderers\":\"auto\"}},{\"type\":\"object\",\"name\":\"WheelZoomTool\",\"id\":\"22989\"},{\"type\":\"object\",\"name\":\"BoxZoomTool\",\"id\":\"22990\",\"attributes\":{\"overlay\":{\"type\":\"object\",\"name\":\"BoxAnnotation\",\"id\":\"22991\",\"attributes\":{\"fill_alpha\":0.5,\"syncable\":false,\"line_color\":\"black\",\"level\":\"overlay\",\"fill_color\":\"lightgrey\",\"line_width\":2,\"line_alpha\":1.0,\"visible\":false,\"bottom_units\":\"canvas\",\"line_dash\":[4,4],\"right_units\":\"canvas\",\"top_units\":\"canvas\",\"left_units\":\"canvas\"}}}},{\"type\":\"object\",\"name\":\"UndoTool\",\"id\":\"22992\"},{\"type\":\"object\",\"name\":\"ResetTool\",\"id\":\"22993\"},{\"type\":\"object\",\"name\":\"SaveTool\",\"id\":\"22994\"}]}},\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"22981\",\"attributes\":{\"axis\":{\"id\":\"22976\"}}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"22987\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"22982\"}}}]}}]}};\n const render_items = [{\"docid\":\"90a16b69-8ae9-4a91-b725-4b57cd359465\",\"roots\":{\"22960\":\"de1dda22-2abf-413d-9878-7a5616aefeb8\"},\"root_ids\":[\"22960\"]}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -1225,32 +511,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"e32d99a3-a606-48ea-aca5-4f9f331dad4a\":{\"version\":\"3.0.0.dev13\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"21113\",\"attributes\":{\"toolbar_location\":null,\"x_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"21125\"},\"y_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"21123\"},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"21136\",\"attributes\":{\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"21139\"},\"axis_line_alpha\":0,\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"21137\"},\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"21138\",\"attributes\":{\"mantissas\":[1,2,5]}}}}],\"width\":200,\"x_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"21121\"},\"below\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"21129\",\"attributes\":{\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"21132\"},\"axis_line_alpha\":0,\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"21130\"},\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"21131\",\"attributes\":{\"mantissas\":[1,2,5]}}}}],\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"21114\",\"attributes\":{\"text\":\"Rel. amount\\nof answers [%]\"}},\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"21127\"},\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21150\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21148\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-50},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21151\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21152\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21147\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"size\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-50},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21149\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-50},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21144\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21145\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21146\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21159\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21157\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-50},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21160\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21161\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21156\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-50},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21158\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-50},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21153\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21154\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"0\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21155\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21168\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21166\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":12.6},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-150},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21169\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21170\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21165\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"size\":{\"type\":\"value\",\"value\":12.6},\"y\":{\"type\":\"value\",\"value\":-150},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21167\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":12.6},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-150},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21162\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21163\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21164\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21177\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21175\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-150},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21178\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21179\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21174\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-150},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21176\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-150},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21171\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21172\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"25\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21173\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21186\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21184\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":25.1},\"fill_color\":{\"type\":\"value\",\"value\":\"green\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-250},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21187\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21188\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21183\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"green\"},\"size\":{\"type\":\"value\",\"value\":25.1},\"y\":{\"type\":\"value\",\"value\":-250},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21185\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":25.1},\"fill_color\":{\"type\":\"value\",\"value\":\"green\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-250},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21180\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21181\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21182\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21195\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21193\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-250},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21196\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21197\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21192\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-250},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21194\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-250},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21189\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21190\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"50\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21191\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21204\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21202\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":37.6},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-350},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21205\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21206\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21201\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"size\":{\"type\":\"value\",\"value\":37.6},\"y\":{\"type\":\"value\",\"value\":-350},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21203\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":37.6},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-350},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21198\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21199\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21200\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21213\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21211\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-350},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21214\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21215\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21210\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-350},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21212\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-350},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21207\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21208\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"75\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21209\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21222\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21220\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":50.1},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-450},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21223\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21224\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21219\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"size\":{\"type\":\"value\",\"value\":50.1},\"y\":{\"type\":\"value\",\"value\":-450},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21221\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":50.1},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-450},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21216\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21217\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21218\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21231\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21229\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-450},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21232\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21233\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21228\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-450},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21230\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-450},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21225\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21226\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"100\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21227\"}}}}}],\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"21120\"},\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"21135\",\"attributes\":{\"axis\":{\"id\":\"21129\"}}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"21142\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"21136\"}}}]}}]}};\n", - " const render_items = [{\"docid\":\"e32d99a3-a606-48ea-aca5-4f9f331dad4a\",\"roots\":{\"21113\":\"2855f4da-61d7-4ba1-a134-94050ede1761\"},\"root_ids\":[\"21113\"]}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"e32d99a3-a606-48ea-aca5-4f9f331dad4a\":{\"version\":\"3.0.0.dev13\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"21113\",\"attributes\":{\"toolbar_location\":null,\"x_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"21125\"},\"y_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"21123\"},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"21136\",\"attributes\":{\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"21139\"},\"axis_line_alpha\":0,\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"21137\"},\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"21138\",\"attributes\":{\"mantissas\":[1,2,5]}}}}],\"width\":200,\"x_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"21121\"},\"below\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"21129\",\"attributes\":{\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"21132\"},\"axis_line_alpha\":0,\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"21130\"},\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"21131\",\"attributes\":{\"mantissas\":[1,2,5]}}}}],\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"21114\",\"attributes\":{\"text\":\"Rel. amount\\nof answers [%]\"}},\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"21127\"},\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21150\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21148\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-50},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21151\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21152\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21147\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"size\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-50},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21149\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-50},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21144\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21145\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21146\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21159\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21157\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-50},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21160\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21161\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21156\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-50},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21158\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-50},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21153\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21154\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"0\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21155\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21168\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21166\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":12.6},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-150},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21169\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21170\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21165\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"size\":{\"type\":\"value\",\"value\":12.6},\"y\":{\"type\":\"value\",\"value\":-150},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21167\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":12.6},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-150},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21162\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21163\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21164\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21177\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21175\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-150},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21178\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21179\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21174\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-150},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21176\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-150},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21171\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21172\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"25\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21173\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21186\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21184\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":25.1},\"fill_color\":{\"type\":\"value\",\"value\":\"green\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-250},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21187\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21188\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21183\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"green\"},\"size\":{\"type\":\"value\",\"value\":25.1},\"y\":{\"type\":\"value\",\"value\":-250},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21185\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":25.1},\"fill_color\":{\"type\":\"value\",\"value\":\"green\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-250},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21180\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21181\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21182\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21195\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21193\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-250},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21196\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21197\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21192\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-250},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21194\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-250},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21189\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21190\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"50\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21191\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21204\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21202\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":37.6},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-350},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21205\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21206\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21201\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"size\":{\"type\":\"value\",\"value\":37.6},\"y\":{\"type\":\"value\",\"value\":-350},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21203\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":37.6},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-350},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21198\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21199\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21200\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21213\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21211\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-350},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21214\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21215\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21210\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-350},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21212\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-350},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21207\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21208\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"75\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21209\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21222\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21220\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":50.1},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-450},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21223\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21224\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21219\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"size\":{\"type\":\"value\",\"value\":50.1},\"y\":{\"type\":\"value\",\"value\":-450},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21221\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":50.1},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-450},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21216\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21217\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21218\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21231\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21229\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-450},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21232\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21233\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21228\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-450},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21230\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-450},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21225\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21226\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"100\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21227\"}}}}}],\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"21120\"},\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"21135\",\"attributes\":{\"axis\":{\"id\":\"21129\"}}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"21142\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"21136\"}}}]}}]}};\n const render_items = [{\"docid\":\"e32d99a3-a606-48ea-aca5-4f9f331dad4a\",\"roots\":{\"21113\":\"2855f4da-61d7-4ba1-a134-94050ede1761\"},\"root_ids\":[\"21113\"]}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -1284,32 +545,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"a252e35c-d8b3-414c-a5ba-1f083d046034\":{\"version\":\"3.0.0.dev13\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"21113\",\"attributes\":{\"toolbar_location\":null,\"x_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"21125\"},\"y_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"21123\",\"attributes\":{\"start\":-600.0,\"end\":0.0}},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"21136\",\"attributes\":{\"minor_tick_line_alpha\":0,\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"21139\"},\"major_label_text_alpha\":0,\"axis_line_alpha\":0,\"major_tick_line_alpha\":0,\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"21137\"},\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"21138\",\"attributes\":{\"mantissas\":[1,2,5]}}}}],\"width\":200,\"x_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"21121\",\"attributes\":{\"start\":0.0,\"end\":200}},\"below\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"21129\",\"attributes\":{\"axis_label_text_alpha\":0,\"minor_tick_line_alpha\":0,\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"21132\"},\"major_label_text_alpha\":0,\"axis_line_alpha\":0,\"major_tick_line_alpha\":0,\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"21130\"},\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"21131\",\"attributes\":{\"mantissas\":[1,2,5]}}}}],\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"21114\",\"attributes\":{\"text\":\"Rel. amount\\nof answers [%]\"}},\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"21127\"},\"border_fill_alpha\":0,\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21150\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21148\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-50},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21151\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21152\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21147\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"size\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-50},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21149\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-50},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21144\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21145\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21146\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21159\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21157\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-50},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21160\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21161\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21156\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-50},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21158\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-50},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21153\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21154\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"0\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21155\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21168\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21166\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":12.6},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-150},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21169\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21170\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21165\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"size\":{\"type\":\"value\",\"value\":12.6},\"y\":{\"type\":\"value\",\"value\":-150},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21167\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":12.6},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-150},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21162\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21163\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21164\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21177\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21175\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-150},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21178\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21179\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21174\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-150},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21176\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-150},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21171\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21172\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"25\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21173\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21186\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21184\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":25.1},\"fill_color\":{\"type\":\"value\",\"value\":\"green\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-250},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21187\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21188\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21183\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"green\"},\"size\":{\"type\":\"value\",\"value\":25.1},\"y\":{\"type\":\"value\",\"value\":-250},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21185\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":25.1},\"fill_color\":{\"type\":\"value\",\"value\":\"green\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-250},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21180\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21181\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21182\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21195\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21193\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-250},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21196\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21197\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21192\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-250},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21194\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-250},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21189\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21190\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"50\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21191\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21204\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21202\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":37.6},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-350},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21205\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21206\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21201\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"size\":{\"type\":\"value\",\"value\":37.6},\"y\":{\"type\":\"value\",\"value\":-350},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21203\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":37.6},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-350},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21198\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21199\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21200\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21213\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21211\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-350},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21214\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21215\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21210\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-350},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21212\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-350},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21207\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21208\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"75\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21209\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21222\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21220\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":50.1},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-450},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21223\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21224\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21219\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"size\":{\"type\":\"value\",\"value\":50.1},\"y\":{\"type\":\"value\",\"value\":-450},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21221\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":50.1},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-450},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21216\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21217\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21218\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21231\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21229\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-450},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21232\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21233\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21228\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-450},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21230\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-450},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21225\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21226\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"100\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21227\"}}}}}],\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"21120\"},\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"21135\",\"attributes\":{\"grid_line_alpha\":0,\"axis\":{\"id\":\"21129\"}}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"21142\",\"attributes\":{\"grid_line_alpha\":0,\"dimension\":1,\"axis\":{\"id\":\"21136\"}}}]}}]}};\n", - " const render_items = [{\"docid\":\"a252e35c-d8b3-414c-a5ba-1f083d046034\",\"roots\":{\"21113\":\"60b1ea24-5899-41d5-9485-f591583715d3\"},\"root_ids\":[\"21113\"]}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"a252e35c-d8b3-414c-a5ba-1f083d046034\":{\"version\":\"3.0.0.dev13\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"21113\",\"attributes\":{\"toolbar_location\":null,\"x_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"21125\"},\"y_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"21123\",\"attributes\":{\"start\":-600.0,\"end\":0.0}},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"21136\",\"attributes\":{\"minor_tick_line_alpha\":0,\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"21139\"},\"major_label_text_alpha\":0,\"axis_line_alpha\":0,\"major_tick_line_alpha\":0,\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"21137\"},\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"21138\",\"attributes\":{\"mantissas\":[1,2,5]}}}}],\"width\":200,\"x_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"21121\",\"attributes\":{\"start\":0.0,\"end\":200}},\"below\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"21129\",\"attributes\":{\"axis_label_text_alpha\":0,\"minor_tick_line_alpha\":0,\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"21132\"},\"major_label_text_alpha\":0,\"axis_line_alpha\":0,\"major_tick_line_alpha\":0,\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"21130\"},\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"21131\",\"attributes\":{\"mantissas\":[1,2,5]}}}}],\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"21114\",\"attributes\":{\"text\":\"Rel. amount\\nof answers [%]\"}},\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"21127\"},\"border_fill_alpha\":0,\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21150\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21148\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-50},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21151\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21152\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21147\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"size\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-50},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21149\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-50},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21144\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21145\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21146\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21159\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21157\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-50},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21160\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21161\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21156\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-50},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21158\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-50},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21153\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21154\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"0\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21155\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21168\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21166\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":12.6},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-150},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21169\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21170\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21165\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"size\":{\"type\":\"value\",\"value\":12.6},\"y\":{\"type\":\"value\",\"value\":-150},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21167\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":12.6},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-150},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21162\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21163\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21164\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21177\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21175\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-150},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21178\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21179\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21174\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-150},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21176\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-150},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21171\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21172\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"25\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21173\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21186\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21184\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":25.1},\"fill_color\":{\"type\":\"value\",\"value\":\"green\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-250},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21187\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21188\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21183\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"green\"},\"size\":{\"type\":\"value\",\"value\":25.1},\"y\":{\"type\":\"value\",\"value\":-250},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21185\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":25.1},\"fill_color\":{\"type\":\"value\",\"value\":\"green\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-250},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21180\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21181\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21182\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21195\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21193\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-250},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21196\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21197\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21192\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-250},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21194\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-250},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21189\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21190\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"50\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21191\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21204\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21202\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":37.6},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-350},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21205\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21206\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21201\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"size\":{\"type\":\"value\",\"value\":37.6},\"y\":{\"type\":\"value\",\"value\":-350},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21203\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":37.6},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-350},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21198\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21199\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21200\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21213\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21211\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-350},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21214\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21215\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21210\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-350},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21212\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-350},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21207\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21208\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"75\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21209\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21222\",\"attributes\":{\"name\":\"foo\",\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21220\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":50.1},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1},\"y\":{\"type\":\"value\",\"value\":-450},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21223\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21224\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21219\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"size\":{\"type\":\"value\",\"value\":50.1},\"y\":{\"type\":\"value\",\"value\":-450},\"x\":{\"type\":\"value\",\"value\":2.0}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Circle\",\"id\":\"21221\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"size\":{\"type\":\"value\",\"value\":50.1},\"fill_color\":{\"type\":\"value\",\"value\":\"red\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2},\"y\":{\"type\":\"value\",\"value\":-450},\"x\":{\"type\":\"value\",\"value\":2.0},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21216\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21217\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21218\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"21231\",\"attributes\":{\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21229\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-450},\"text_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"21232\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"21233\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21228\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-450},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Text\",\"id\":\"21230\",\"attributes\":{\"text_baseline\":{\"type\":\"value\",\"value\":\"middle\"},\"text_font_size\":{\"type\":\"value\",\"value\":\"22px\"},\"y\":{\"type\":\"value\",\"value\":-450},\"text_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"value\",\"value\":7.0},\"text_color\":{\"type\":\"value\",\"value\":\"black\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"21225\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"21226\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"text\",[\"100\"]]]},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"21227\"}}}}}],\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"21120\"},\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"21135\",\"attributes\":{\"grid_line_alpha\":0,\"axis\":{\"id\":\"21129\"}}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"21142\",\"attributes\":{\"grid_line_alpha\":0,\"dimension\":1,\"axis\":{\"id\":\"21136\"}}}]}}]}};\n const render_items = [{\"docid\":\"a252e35c-d8b3-414c-a5ba-1f083d046034\",\"roots\":{\"21113\":\"60b1ea24-5899-41d5-9485-f591583715d3\"},\"root_ids\":[\"21113\"]}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -1712,426 +948,16 @@ "outputs": [ { "data": { - "application/javascript": [ - "(function(root) {\n", - " function now() {\n", - " return new Date();\n", - " }\n", - "\n", - " var force = true;\n", - "\n", - " if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n", - " root._bokeh_onload_callbacks = [];\n", - " root._bokeh_is_loading = undefined;\n", - " }\n", - "\n", - " if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n", - " root._bokeh_timeout = Date.now() + 5000;\n", - " root._bokeh_failed_load = false;\n", - " }\n", - "\n", - " function run_callbacks() {\n", - " try {\n", - " root._bokeh_onload_callbacks.forEach(function(callback) {\n", - " if (callback != null)\n", - " callback();\n", - " });\n", - " } finally {\n", - " delete root._bokeh_onload_callbacks\n", - " }\n", - " console.debug(\"Bokeh: all callbacks have finished\");\n", - " }\n", - "\n", - " function load_libs(css_urls, js_urls, js_modules, callback) {\n", - " if (css_urls == null) css_urls = [];\n", - " if (js_urls == null) js_urls = [];\n", - " if (js_modules == null) js_modules = [];\n", - "\n", - " root._bokeh_onload_callbacks.push(callback);\n", - " if (root._bokeh_is_loading > 0) {\n", - " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", - " return null;\n", - " }\n", - " if (js_urls.length === 0 && js_modules.length === 0) {\n", - " run_callbacks();\n", - " return null;\n", - " }\n", - " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", - "\n", - " function on_load() {\n", - " root._bokeh_is_loading--;\n", - " if (root._bokeh_is_loading === 0) {\n", - " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", - " run_callbacks()\n", - " }\n", - " }\n", - "\n", - " function on_error() {\n", - " console.error(\"failed to load \" + url);\n", - " }\n", - "\n", - " for (var i = 0; i < css_urls.length; i++) {\n", - " var url = css_urls[i];\n", - " const element = document.createElement(\"link\");\n", - " element.onload = on_load;\n", - " element.onerror = on_error;\n", - " element.rel = \"stylesheet\";\n", - " element.type = \"text/css\";\n", - " element.href = url;\n", - " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", - " document.body.appendChild(element);\n", - " }\n", - "\n", - " var skip = [];\n", - " if (window.requirejs) {\n", - " window.requirejs.config({'packages': {}, 'paths': {'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'gridstack': {'exports': 'GridStack'}}});\n", - " require([\"gridstack\"], function(GridStack) {\n", - "\twindow.GridStack = GridStack\n", - "\ton_load()\n", - " })\n", - " require([\"notyf\"], function() {\n", - "\ton_load()\n", - " })\n", - " root._bokeh_is_loading = css_urls.length + 2;\n", - " } else {\n", - " root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length;\n", - " } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n", - " var urls = ['https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5.js'];\n", - " for (var i = 0; i < urls.length; i++) {\n", - " skip.push(urls[i])\n", - " }\n", - " } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n", - " var urls = ['https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js'];\n", - " for (var i = 0; i < urls.length; i++) {\n", - " skip.push(urls[i])\n", - " }\n", - " } for (var i = 0; i < js_urls.length; i++) {\n", - " var url = js_urls[i];\n", - " if (skip.indexOf(url) >= 0) {\n", - "\tif (!window.requirejs) {\n", - "\t on_load();\n", - "\t}\n", - "\tcontinue;\n", - " }\n", - " var element = document.createElement('script');\n", - " element.onload = on_load;\n", - " element.onerror = on_error;\n", - " element.async = false;\n", - " element.src = url;\n", - " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", - " document.head.appendChild(element);\n", - " }\n", - " for (var i = 0; i < js_modules.length; i++) {\n", - " var url = js_modules[i];\n", - " if (skip.indexOf(url) >= 0) {\n", - "\tif (!window.requirejs) {\n", - "\t on_load();\n", - "\t}\n", - "\tcontinue;\n", - " }\n", - " var element = document.createElement('script');\n", - " element.onload = on_load;\n", - " element.onerror = on_error;\n", - " element.async = false;\n", - " element.src = url;\n", - " element.type = \"module\";\n", - " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", - " document.head.appendChild(element);\n", - " }\n", - " if (!js_urls.length && !js_modules.length) {\n", - " on_load()\n", - " }\n", - " };\n", - "\n", - " function inject_raw_css(css) {\n", - " const element = document.createElement(\"style\");\n", - " element.appendChild(document.createTextNode(css));\n", - " document.body.appendChild(element);\n", - " }\n", - "\n", - " var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js\", \"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js\"];\n", - " var js_modules = [];\n", - " var css_urls = [\"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.css\", \"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/alerts.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/dataframe.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/loading.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/card.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/debugger.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/json.css\"];\n", - " var inline_js = [ function(Bokeh) {\n", - " inject_raw_css(\"\\n .bk.pn-loading.arcs:before {\\n background-image: url(\\\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0ibWFyZ2luOiBhdXRvOyBiYWNrZ3JvdW5kOiBub25lOyBkaXNwbGF5OiBibG9jazsgc2hhcGUtcmVuZGVyaW5nOiBhdXRvOyIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4gIDxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjMyIiBzdHJva2Utd2lkdGg9IjgiIHN0cm9rZT0iI2MzYzNjMyIgc3Ryb2tlLWRhc2hhcnJheT0iNTAuMjY1NDgyNDU3NDM2NjkgNTAuMjY1NDgyNDU3NDM2NjkiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+ICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0icm90YXRlIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgZHVyPSIxcyIga2V5VGltZXM9IjA7MSIgdmFsdWVzPSIwIDUwIDUwOzM2MCA1MCA1MCI+PC9hbmltYXRlVHJhbnNmb3JtPiAgPC9jaXJjbGU+PC9zdmc+\\\");\\n background-size: auto calc(min(50%, 400px));\\n }\\n \");\n", - " }, function(Bokeh) {\n", - " Bokeh.set_log_level(\"info\");\n", - " },\n", - "function(Bokeh) {} // ensure no trailing comma for IE\n", - " ];\n", - "\n", - " function run_inline_js() {\n", - " if ((root.Bokeh !== undefined) || (force === true)) {\n", - " for (var i = 0; i < inline_js.length; i++) {\n", - " inline_js[i].call(root, root.Bokeh);\n", - " }} else if (Date.now() < root._bokeh_timeout) {\n", - " setTimeout(run_inline_js, 100);\n", - " } else if (!root._bokeh_failed_load) {\n", - " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", - " root._bokeh_failed_load = true;\n", - " }\n", - " }\n", - "\n", - " if (root._bokeh_is_loading === 0) {\n", - " console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n", - " run_inline_js();\n", - " } else {\n", - " load_libs(css_urls, js_urls, js_modules, function() {\n", - " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", - " run_inline_js();\n", - " });\n", - " }\n", - "}(window));" - ], - "application/vnd.holoviews_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls.length === 0 && js_modules.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n var skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'gridstack': {'exports': 'GridStack'}}});\n require([\"gridstack\"], function(GridStack) {\n\twindow.GridStack = GridStack\n\ton_load()\n })\n require([\"notyf\"], function() {\n\ton_load()\n })\n root._bokeh_is_loading = css_urls.length + 2;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length;\n } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n if (skip.indexOf(url) >= 0) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (var i = 0; i < js_modules.length; i++) {\n var url = js_modules[i];\n if (skip.indexOf(url) >= 0) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js\", \"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js\"];\n var js_modules = [];\n var css_urls = [\"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.css\", \"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/alerts.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/dataframe.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/loading.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/card.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/debugger.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/json.css\"];\n var inline_js = [ function(Bokeh) {\n inject_raw_css(\"\\n .bk.pn-loading.arcs:before {\\n background-image: url(\\\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0ibWFyZ2luOiBhdXRvOyBiYWNrZ3JvdW5kOiBub25lOyBkaXNwbGF5OiBibG9jazsgc2hhcGUtcmVuZGVyaW5nOiBhdXRvOyIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4gIDxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjMyIiBzdHJva2Utd2lkdGg9IjgiIHN0cm9rZT0iI2MzYzNjMyIgc3Ryb2tlLWRhc2hhcnJheT0iNTAuMjY1NDgyNDU3NDM2NjkgNTAuMjY1NDgyNDU3NDM2NjkiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+ICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0icm90YXRlIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgZHVyPSIxcyIga2V5VGltZXM9IjA7MSIgdmFsdWVzPSIwIDUwIDUwOzM2MCA1MCA1MCI+PC9hbmltYXRlVHJhbnNmb3JtPiAgPC9jaXJjbGU+PC9zdmc+\\\");\\n background-size: auto calc(min(50%, 400px));\\n }\\n \");\n }, function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, js_modules, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));" + "application/javascript": "(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls.length === 0 && js_modules.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n var skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'gridstack': {'exports': 'GridStack'}}});\n require([\"gridstack\"], function(GridStack) {\n\twindow.GridStack = GridStack\n\ton_load()\n })\n require([\"notyf\"], function() {\n\ton_load()\n })\n root._bokeh_is_loading = css_urls.length + 2;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length;\n } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n if (skip.indexOf(url) >= 0) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (var i = 0; i < js_modules.length; i++) {\n var url = js_modules[i];\n if (skip.indexOf(url) >= 0) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js\", \"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js\"];\n var js_modules = [];\n var css_urls = [\"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.css\", \"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/alerts.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/dataframe.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/loading.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/card.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/debugger.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/json.css\"];\n var inline_js = [ function(Bokeh) {\n inject_raw_css(\"\\n .bk.pn-loading.arcs:before {\\n background-image: url(\\\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0ibWFyZ2luOiBhdXRvOyBiYWNrZ3JvdW5kOiBub25lOyBkaXNwbGF5OiBibG9jazsgc2hhcGUtcmVuZGVyaW5nOiBhdXRvOyIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4gIDxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjMyIiBzdHJva2Utd2lkdGg9IjgiIHN0cm9rZT0iI2MzYzNjMyIgc3Ryb2tlLWRhc2hhcnJheT0iNTAuMjY1NDgyNDU3NDM2NjkgNTAuMjY1NDgyNDU3NDM2NjkiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+ICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0icm90YXRlIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgZHVyPSIxcyIga2V5VGltZXM9IjA7MSIgdmFsdWVzPSIwIDUwIDUwOzM2MCA1MCA1MCI+PC9hbmltYXRlVHJhbnNmb3JtPiAgPC9jaXJjbGU+PC9zdmc+\\\");\\n background-size: auto calc(min(50%, 400px));\\n }\\n \");\n }, function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, js_modules, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));", + "application/vnd.holoviews_load.v0+json": "" }, "metadata": {}, "output_type": "display_data" }, { "data": { - "application/javascript": [ - "\n", - "if ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n", - " window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n", - "}\n", - "\n", - "\n", - " function JupyterCommManager() {\n", - " }\n", - "\n", - " JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n", - " if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", - " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", - " comm_manager.register_target(comm_id, function(comm) {\n", - " comm.on_msg(msg_handler);\n", - " });\n", - " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", - " window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n", - " comm.onMsg = msg_handler;\n", - " });\n", - " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", - " google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n", - " var messages = comm.messages[Symbol.asyncIterator]();\n", - " function processIteratorResult(result) {\n", - " var message = result.value;\n", - " console.log(message)\n", - " var content = {data: message.data, comm_id};\n", - " var buffers = []\n", - " for (var buffer of message.buffers || []) {\n", - " buffers.push(new DataView(buffer))\n", - " }\n", - " var metadata = message.metadata || {};\n", - " var msg = {content, buffers, metadata}\n", - " msg_handler(msg);\n", - " return messages.next().then(processIteratorResult);\n", - " }\n", - " return messages.next().then(processIteratorResult);\n", - " })\n", - " }\n", - " }\n", - "\n", - " JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n", - " if (comm_id in window.PyViz.comms) {\n", - " return window.PyViz.comms[comm_id];\n", - " } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", - " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", - " var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n", - " if (msg_handler) {\n", - " comm.on_msg(msg_handler);\n", - " }\n", - " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", - " var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n", - " comm.open();\n", - " if (msg_handler) {\n", - " comm.onMsg = msg_handler;\n", - " }\n", - " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", - " var comm_promise = google.colab.kernel.comms.open(comm_id)\n", - " comm_promise.then((comm) => {\n", - " window.PyViz.comms[comm_id] = comm;\n", - " if (msg_handler) {\n", - " var messages = comm.messages[Symbol.asyncIterator]();\n", - " function processIteratorResult(result) {\n", - " var message = result.value;\n", - " var content = {data: message.data};\n", - " var metadata = message.metadata || {comm_id};\n", - " var msg = {content, metadata}\n", - " msg_handler(msg);\n", - " return messages.next().then(processIteratorResult);\n", - " }\n", - " return messages.next().then(processIteratorResult);\n", - " }\n", - " }) \n", - " var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n", - " return comm_promise.then((comm) => {\n", - " comm.send(data, metadata, buffers, disposeOnDone);\n", - " });\n", - " };\n", - " var comm = {\n", - " send: sendClosure\n", - " };\n", - " }\n", - " window.PyViz.comms[comm_id] = comm;\n", - " return comm;\n", - " }\n", - " window.PyViz.comm_manager = new JupyterCommManager();\n", - " \n", - "\n", - "\n", - "var JS_MIME_TYPE = 'application/javascript';\n", - "var HTML_MIME_TYPE = 'text/html';\n", - "var EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\n", - "var CLASS_NAME = 'output';\n", - "\n", - "/**\n", - " * Render data to the DOM node\n", - " */\n", - "function render(props, node) {\n", - " var div = document.createElement(\"div\");\n", - " var script = document.createElement(\"script\");\n", - " node.appendChild(div);\n", - " node.appendChild(script);\n", - "}\n", - "\n", - "/**\n", - " * Handle when a new output is added\n", - " */\n", - "function handle_add_output(event, handle) {\n", - " var output_area = handle.output_area;\n", - " var output = handle.output;\n", - " if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", - " return\n", - " }\n", - " var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", - " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", - " if (id !== undefined) {\n", - " var nchildren = toinsert.length;\n", - " var html_node = toinsert[nchildren-1].children[0];\n", - " html_node.innerHTML = output.data[HTML_MIME_TYPE];\n", - " var scripts = [];\n", - " var nodelist = html_node.querySelectorAll(\"script\");\n", - " for (var i in nodelist) {\n", - " if (nodelist.hasOwnProperty(i)) {\n", - " scripts.push(nodelist[i])\n", - " }\n", - " }\n", - "\n", - " scripts.forEach( function (oldScript) {\n", - " var newScript = document.createElement(\"script\");\n", - " var attrs = [];\n", - " var nodemap = oldScript.attributes;\n", - " for (var j in nodemap) {\n", - " if (nodemap.hasOwnProperty(j)) {\n", - " attrs.push(nodemap[j])\n", - " }\n", - " }\n", - " attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n", - " newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n", - " oldScript.parentNode.replaceChild(newScript, oldScript);\n", - " });\n", - " if (JS_MIME_TYPE in output.data) {\n", - " toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n", - " }\n", - " output_area._hv_plot_id = id;\n", - " if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n", - " window.PyViz.plot_index[id] = Bokeh.index[id];\n", - " } else {\n", - " window.PyViz.plot_index[id] = null;\n", - " }\n", - " } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", - " var bk_div = document.createElement(\"div\");\n", - " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", - " var script_attrs = bk_div.children[0].attributes;\n", - " for (var i = 0; i < script_attrs.length; i++) {\n", - " toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n", - " }\n", - " // store reference to server id on output_area\n", - " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", - " }\n", - "}\n", - "\n", - "/**\n", - " * Handle when an output is cleared or removed\n", - " */\n", - "function handle_clear_output(event, handle) {\n", - " var id = handle.cell.output_area._hv_plot_id;\n", - " var server_id = handle.cell.output_area._bokeh_server_id;\n", - " if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n", - " var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n", - " if (server_id !== null) {\n", - " comm.send({event_type: 'server_delete', 'id': server_id});\n", - " return;\n", - " } else if (comm !== null) {\n", - " comm.send({event_type: 'delete', 'id': id});\n", - " }\n", - " delete PyViz.plot_index[id];\n", - " if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n", - " var doc = window.Bokeh.index[id].model.document\n", - " doc.clear();\n", - " const i = window.Bokeh.documents.indexOf(doc);\n", - " if (i > -1) {\n", - " window.Bokeh.documents.splice(i, 1);\n", - " }\n", - " }\n", - "}\n", - "\n", - "/**\n", - " * Handle kernel restart event\n", - " */\n", - "function handle_kernel_cleanup(event, handle) {\n", - " delete PyViz.comms[\"hv-extension-comm\"];\n", - " window.PyViz.plot_index = {}\n", - "}\n", - "\n", - "/**\n", - " * Handle update_display_data messages\n", - " */\n", - "function handle_update_output(event, handle) {\n", - " handle_clear_output(event, {cell: {output_area: handle.output_area}})\n", - " handle_add_output(event, handle)\n", - "}\n", - "\n", - "function register_renderer(events, OutputArea) {\n", - " function append_mime(data, metadata, element) {\n", - " // create a DOM node to render to\n", - " var toinsert = this.create_output_subarea(\n", - " metadata,\n", - " CLASS_NAME,\n", - " EXEC_MIME_TYPE\n", - " );\n", - " this.keyboard_manager.register_events(toinsert);\n", - " // Render to node\n", - " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", - " render(props, toinsert[0]);\n", - " element.append(toinsert);\n", - " return toinsert\n", - " }\n", - "\n", - " events.on('output_added.OutputArea', handle_add_output);\n", - " events.on('output_updated.OutputArea', handle_update_output);\n", - " events.on('clear_output.CodeCell', handle_clear_output);\n", - " events.on('delete.Cell', handle_clear_output);\n", - " events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n", - "\n", - " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", - " safe: true,\n", - " index: 0\n", - " });\n", - "}\n", - "\n", - "if (window.Jupyter !== undefined) {\n", - " try {\n", - " var events = require('base/js/events');\n", - " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", - " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", - " register_renderer(events, OutputArea);\n", - " }\n", - " } catch(err) {\n", - " }\n", - "}\n" - ], - "application/vnd.holoviews_load.v0+json": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n console.log(message)\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n comm.open();\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n }) \n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n" + "application/javascript": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n console.log(message)\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n comm.open();\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n }) \n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n", + "application/vnd.holoviews_load.v0+json": "" }, "metadata": {}, "output_type": "display_data" @@ -2608,7 +1434,7 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAV0AAADfCAYAAABVhwDQAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAAsTAAALEwEAmpwYAABVKUlEQVR4nO3dd7yc113g/885T50+t1/de9WLVSy5xi2xkziVEALpkA3LUnYX2KUEWNiSHywsy8KywBbaEgglpLEESAghIY4Tx3GJu2XL6l26vUyfedo5vz9mdKVrSbZkS/deSeetly175plnzvPMPN85z/c0obXGMAzDWBxyqQtgGIZxLTFB1zAMYxGZoGsYhrGITNA1DMNYRCboGoZhLCITdA3DMBaR/TLPm/5khmEYF0+c7wlT0zUMw1hEJugahmEsoms66NYaAbsPjZMotdRFMQzjGvFyOd2rltaaQyemefjZw6zoKwCwc99JsmmPLesG2X1onEq9xeY1Axw6OYMAbtg0zKGTM0zOVtm+cQilNLsOjLGiv8B1q/uR8rxpHMMwlohSipmxEnGU0DfcjWVLytNVKnN18l0ZUhmf8WPTKKXIdWXoGSwixOW7lq/ZoBsnir1HJnFsi8MnZijVmnQX0qwb7mFqtsrYdIXX3rCWgydmOHBsCq2hmEtxdHQW37NxbMmxsTlKtSZrR3q4jJ+RYRivkNaaPU8c5sn7d+GnXYbW9rF+x2q+9tlH6B3qondFkUJvjq999lE23rSa4fUDdA8ULmvQvWbTC6VKA6U02zcOcWx8DikEzVZEoxUhhCCOFbVmiBACIQRrh3vo786xZd0A5VqLg8dnGOov0FvM8NTuE0RxstSHZBjGiyil2fPEQV7z5uu59wN3cGDnMUpTFYQU3Prm67npjVtRStPVn2fLresYXjdwWQMuXMM1Xdexed3N6xjoyXO0OEtPIcOhE9PMVRqsHe7hujX9TMxUWTvcjetYxHGC59qEUcLKgSLrV/bSCiI81+GWrSuxbWupD8kwjBdRiSJqxaRzPq7nkMSKwdW9bNixiq984kHW71hFsTfHyUOTPP3AbjbdvJb121de1jKJl5na0fTTNQzjiqWU4h8+/g2GNwzSP9LDNz73bd79Y2/BsiRzkxW+8slvcdPrt3Dy4ARv+/DrEFIiBJeitnveHVyzNV3DMK5+UkpuuHsL3/rCk+x98jA33L2ZymyNR7/0DEpr1m0bIdeVIVvMIC152VMLYGq6hmFc5bTWNGstVKJJ53y01tQrTYSAVDYFQBInuL5zKYPueXdkgq5hGMalZ4YBG4ZhLAcm6BqGYSwiE3QNwzAWkQm6xjWlmQQorYhVQqzipS6OcQ0yXcaMa8qDU08zkuonbfvYwmYk3b/URTKuMaame4G01tTiOpOtGRKtCFVIkIQv+ZpaXCfRZnjwclJ0smTsFHsrRwjVS39+hnE5mJruBdBoQhXxzanHGUkN0uXmaSYBEokrHRKtiHSMJSQSQawTXOnw2OxOdhQ2U3RySGERqfa8Do6wSXRColX7NZ3nLGFhicXpoH2tWpkepMcr4FsunnSXujjGNcgE3Qt0sjnBofoxVqZWEOuEZ0q7GfR6WZ9dxVNzuxhtTdLjFgFIdMKO4hbmwjKPzT5L3smyo7CZ3ZUDlKIqt3ffwHPlvSgUazMriVTM0foJ0naKW7quxxHO0h7sVeyZ0l6KTo5yVGNTbhVFN7fURTKuMSa9cAEEglXpIdZmVrI5v56U5dPv9RCqiFgnzEVletwiXW6BlOV3RpRofMvjxuIWGnGTWlxHo5kJ5ihHVWpxg+2F6xhODfJ8eS+1pMHJ5gSBueW9rK4vbOD6wgZu7d5Kn9e11MW5IFqHxNFekvgQWp//+6G1RqsaWr+ySfm1aqBU+fTfZwyciqO9JMnoK9qvsZCp6V4gIcDt1EBbScBka5pIx6zODBOrmDlVZiS9AkfazEVlpoM5UpaPJz1c6TATlpgLK/iWhxCCtO3jCAfZCei1uE6v140vvSU+0qvbXFghSEL6/S6ydnqpi3NBVDJJFNyPkF1IaxTb3oBKphAyg5QDJPEhED5CpAhbf4/j3onlbEElJ9GqhmVvQOsaSXICyxpB6xZKTSOwkfYatJpFqzJCdhGF30aIFJa9AWlp4ugQUvag4iNo3UA712HZG0jio6BrWPYmkuQEWjeQshchXJL4CEJksOw1JPFhhEgh7XUIYep4YILuBZNI7ui5CVtYgOa6/Dq01rSSAIWm6OQ5WDvKTcWtFJ08PW4XQ6l+fOlza/cOHGHT7/XgSIecnabbLZKyfIQQbC9sZjacw5EOUpgpIi+n6aBELW5wspnlxuJ1FNzsUhfpAmjAQYgs6Jgo+DYIC1veSBw9jVI1tC5hWevQOkCILCqZIGh+CSE8lJpCJaNY9kbC1j8BEqXGESKLlYwRx/sRIo1ljyCERxLtwfXfQtj8B6Q1AMJBE6F1QBQ+jhBZtK4Qh8+0HwsewnZvIoyeRWAjRAZNiFJTndp5DS/9QSxrcKlP5LJggu4FEkKQczIAOMJh0O8DIFIxW/IbCFXEgNdLj1ecf01WZjp/t2tUA1bv/HOOPJ23taVFv3/6OePyuaNnO5GOEUDa8pe6OBdM6ypSbsd2thEG38SyNyKtYZJ4D9LqQyUhCAcpuxFWLzqZAR0g7bVI2U8SH0Xaq4ijXUhZRFrDCHy0roFuIu21CNGFUocQsgeVjLdrr9ZKpOxCCB/LWUWSHEUloyTxAUChdR0hi9jO9ajkBCBQahLHvZMkOQ5obHsTQlw55/pyMxPeGMYyp5JZkuQItnMjQkjicCfSGkDIfrSaIQofQYgUjnsncfQUWsc47muIoqfRqoTt3opOZkjivVj2BkCjdYgQDog0Ws2g1DRSDiBkHiFS7XSDSBNHO7HsdSBchCig1QxC5ojD50AILHszSk1gOzcQh0+TxAcBjZRdON5dROGT7bJ5d11rgdfMMmYsL2ESM9mqkLE9HMvGEZJGHFKLA9K2i285eNJGCMFkq4IjLdKWy2xYp9vNUIsDALK2Tyls0OtncaW5cVtKWrcIml9A4IFwcP23Ia7ddJkJusbycrw+yzNzx0i0ouCkWJXp4ZnZY1iy3de56KbZWhii6Kb5xsQeer0srSQm0gmrMz3snDvOhtwAU0GVMInp9bPc0LVqqQ/rmtaOJUGnFu3TzkNfs33OzdSOxvKitKYRB+Rsn1grIpUQqph6HBDrhCCJUWhsadHtZuhys6zO9hAkEWESM5zu4nhjhlrUYm22l3LYXOpDuua1F3H1kTKPEO61HHBfkgm6xpLwLJt1uX7u6t9A0U1zsDrJykw3acsla/u40uLp2aOMNUtMtCqMt0rUooBEK1oqoplECAR9fo7dlTFG0ldGn1vDMOkFY0kordFoLCFJlCLWCZawOn8LBIJYKxxhEWvVXiwQgdIKW1rEKkEKiRSCWCU40kaampWxfJicrmEYxiIyOV3DMIzlwARdwzCMRWQ6Nl6DVKKYOjmL49oU+wtIKeYfB5BW+7dYa02t1KBZb5HO+ggpEUCz3iJoRvQOFXF9Mz2iYVwME3SvQa1GwLPf3EMmn2LldStAQ6aQYurkLEEzYuONa5gebQfl/c8cwXZsKjNVtIbe4S4mj80wsnGQYn8eE3IN4+KYoHsN0p0g29VfYOzQJOWZKtKS9I30kEQxjUqDvU8eojpXp3+kh/6VPUwen8F2LCaPzxC0QlqN8PwtBYZhnJfJ6V6DLEvSqDSZmyyT78mSxIpcV5b+kW6CZkS11CCJFAMre/HTHqOHJlizdZhNN6/Fz3gUe/MopYgjsxSRYVws02XsGqS1Jo4ShBBIS5DECikFQkqSOMGyJEmiTud6lcayJAjQSncmy9ZYjoWU5nfbMM7B9NM1DMNYROcNuhec09VakegWcO6lQAQWUvhX1HhrrTUzzW8x3fgGw/kPknU3Iq7ATKXWmnp0kOOVT9Gbvofe1OuvqM8hVlUOl/6IRnRs/rGCt4OV+Q9jXYKVNLTWaCLUgqVuBAKJFA5gXVHn69UI4mmOVv6MtL2aodz3dI7fWEwXHHRb8Rh7Zn6VMJk65/NpZy2bez6KYxUuWeEuhtaKIJnAEhkcK3+Br1KM1/+BsdoXSTtryLobX+Y9NGEyhRA2juy6LBeq1ppIzaF1jGv1XfB7lFpPcqL6GSJVpjf1+kterstLYsscUrgEyQSl1lOAYoTvBS7F8kWKE5XPMlb7/PwjQjg4skjOvY7e9OvJe9dfEwGoHh3iROXTZJx1DGTeinyZ6zVRDcJkDs8eQArT7n4pXHBCzpZZetP30JN6HRl3PfXoMM34JDlvCz3pu+lJvRYplm59r0iV2TPzX5lpPngRr5J0+3fQm7qHvLf9Zeu4iW6yf+63Gav9PZcr86KJOVL+E45W/gJNdMGvy7rX0Zu6m97UPZelXJeTLTOsKfwI2/p+lfVdP4UlUpf4HTStZJxKuItYN5AyBWjq0SGOVv6M5yZ/lrHaF1E6vsTvu/yk7GF606+nL/MmpHzpScXbd4IPs2fmvxAlc4tUwqvfBf902TLPSO6DtL+sR5hrPo5t5VlX/Ld4Vi9L3RGiGR+nEjxPX/oNF/waIQSD2XcykHlb5wfjpcNumExRaj1F2r5887bGqspc8zFy3pYLfo0QgoK3gx39/7O9GsAVSAiJwGsH3Mt4q786/4MMZt8BaKKkzGTjPg6X/oAj5Y9R8HaQdddftvdeDnx7iG29v4YQFuJlLn9NwlzrSVrxKPo8aUXj4l1w0G3f5orOf1vQmQlKCvucs8MnOiCIJ3BkEVvmSHSdKCmhUVgyjSu7zjurvNaKWFWJVRVNghAOtsxhi8yCFUW11ijdIlIVZhoPEakyQTJNPTo8v40UHr41uOB1saoTJlPoTm1VIHCtXmxx9iKF7fcIiVWF2dbjBMkEoZqjER2ZDw4SB88enL/9ilWdIJnEkYWz0hBaJ7SSCdBq/jWnco6RqlBuPUMjPk7KGaERHZkPogIL3x5EitPDEZQOacUTaE7X0ByZx5Hd5/4QF5zfCpGqzr/GlrmzVms9tX9H5rCtAolqEiVzaGIskcaxus55y9k+nphIlUlUAwBLpHCs4pLfwkvhYok0QghsmWUk90HmWt9mpvkw1XDPOYOu0iFhMofSLaRwcWQXUngv+lw1QTIJKDyrH40iTGZQOuwc+7nPFYCm/R2LkjmUDpHCxbW6XvLO8UKvkfa27e+c0sH8Y5ZI41l9nF3R0J1912jFY5RaT6J0SDM+TqIb81u5sqfznRFnvhKtE6KkRKIbCCwcqzh/vl8sVg3CZLp97ck0iQ6IktnOOfBwZHH+PEdJiVCVcGXXOVOY7fM/hdINPGsAS17qu6VL57IlaRrREZ6f/HcM5d5N1t3E8conqYUHO7nKbnrTr2dl/kO41sIAESZzjFb/lunmN2jF42gdIaWPbw3SnbqTlfnvw5Y5AGrRPo6UPtZJdRxH6RZHy3/Kicpn5/eXczezvf83FwTUUutJ9s7+Okq15r+w13X/Av2Zt5x1HK1kjENzv0ct3E8zPonSIaPVv2Oyft/8Nil7iB39v4Nn9wMw13qMF6Z/iVX5f8aawo8Ap39cIlXlhelfJFE1dvT/L3x7gFiVOVT6fcrBczTjk8SqzHTjAUqtpzl1UbhWke19v0XGXXe6bPEoz0/9e4JkCq0TNAkjufezrvgT5/xMTuWLR2ufZ6pxP0E8AWh8ewX9mbeyIvNObFmYv0Ca0Umem/pZ+tJvotu/jWOVT1AL96F0iGN10ZN6Havy/2xB7lnpiNnmI0zUv0w13EekSoDGkQUK3o2szP8zMs66ZdNwJYXXDpI6JlG1Bc9pnVAN93C88mkqwXPEuoYl0uTczYzkv4+id8N8xUETc3DufxEkU2zo+mnGal9ktvkwsarhWEV60/ewMvchXKt3wbErHVMOnuZk9XNUghdIdB1bZMh71zOc+wAFb/tZlZOLuUYAEt1g78yvUQ13o7VCk9Dt38GW3v+MLRYuQ690wsnq/2Oy/lWa8Ula8SgAz03+DGd+jzd0/TQrsu8641xpGvFRTlb+itnWY0SqhMQh7a5hKPse+tL3nPUjUmo9xb7Z/8aGro+QdtZwtPxnlIOniVUdW+boz7yZtYV/jSV8SsHT7J35dQYyb2F9108uqHwAxKrC7ulfIkgmuL7vv5N1N1zoV2DRXbagq3VMkEwxVvt7lI7w7QH6M29GqRazrUc5XPoYSkds6PrJ+S+V0u185onKZ8h72+hPvxkhHIJkklq4n0rwwoJMqi1zdPm3UfBvZKbxLaabD9KbuoeCf+P8Np7Vc9YHlPeuZ3PPf5r/8paCp0jOqAWcyRI+Rf9mct5WKq2djNW/QJd/Cz3p13EqINoyh9VZ+bd9HAFhMkWs6mj0i+oSiiiZI1Y1TvUEEcIh720n5aymHh7iZPWvyLqbGci8ff7cWMI/6wfKswbY2P1zBMk0c81HOVn9a2JVP+9nEqkS+2b/O5P1+8h5W+hLvwnQVILnOTD7P6mF+9nY9TPzNQlNTJBMM1H/MpP1f8K1uulL34siZq75GEfLf0qiG2zs/jmsToOX1oqJ+j9RCp4m62yi27kd0JRbOxmtfo5mfIxtfb+BZ/Wct5yLSemAVjyJFB7uGas1a62Zaz3BnplfIVFNulK341n9BMkEs81HqQTPsaX3l+jy75gPopGqUA6eY+/MrwOa7tSdgKAcPMXR8scJ4kmu6/mP2CIz/x4zjW+yZ/a/onVCd+p2PGuAIJ5gpvkwc60n2dLz/9Gdeu0ZP2oXd40ASJFibfFHacVj1MK9HC3/KbEqc652CYEg7aymL/MmElXjWPkTICQj+Q8tCOR5b+uCc1WP9rN7+pepRQfb14dzJ7GqMdd6kt3T/5mg+GOM5D/woju1gCCZYrb1CMcrnyTRTQrejQgkjfgEEhfRuTvIu9uwZYbJxv0M5d5HxlmzoNzVcA+l4Cm6/Tvw7RUX+S1YXJe5OVJTC/exMv/PWFv8MRxZANpf5uenfp6pxtdYmf8Qvj0AQKzKzDYfJmUPs7X3V0jZqxBCoHTcvu0gnv/CQruGOZL/QPt2KCkz03yI7tTtDOfe95Klcq1uelKvBaAS7KIUPP2S2w7n3ovWmjGRZqz+hXZ3ptyHzrqNe6VsmWFF9rsAmGl8i9HaX5N1N7Ay/71n/WCcyZIpuvxbO/+nOVn92/Nuq7WeD5596Tezsftn8ax2zTxIJtk/+z8Yr32Rgredoex7F9TG6tFhhnPvZkPXT3dSF+1AvXPqZ5hufINV+Q+TdlZ3yuSxtviv0Ch8a8V8+VvJGM9P/QKl1tPUwwN4qaUNulonRKrMZP0+ysEz5Nwt5L3r55+PVJkj5Y8RJWW29P4Kvem7EdhoIibqX2XPzH/haPnPyLlbF9zuxqqMFA5ben+ZlD0CQCM+yu7pX2Sy8VX6M2+Zb3cIkykOl/8IrSM29/wivel7kMJF6ZDpxjfZPfMrHCr9ITlvC27nR+pirxEAKWwK3vUUvOtJ2cMcr3zqvOdFCIue1F30pO4iiCcZrX0egcVQ9t3z1+mLKR1wtPwXVMIXWFf8cVbmP4Ql0oCiFh3ghamPcqT8J+S97RS8HS9KyyjGa//Iiuy7WF34F/Pfybhz13EqJeNavfSl38jh0seYa36btL1q/vrTOmG6+QBaR/Sl39B57+Xrsrd++fYKhnPvx+nctgohyXtbyLqbCJOZzu1nm8BGCp9IlamFB0l0E601Uth4dj8pe+iSBbprTayqTDbuwxIpVua/F8/q73weAs/qZyT/fVjCZ6L+FWK98Dbbs3oYyX0vjuye/wyz7gby7jbCZJYwmV2wfdpZRcZZgyW9+ffwrQG6vFtJdKOdF37pQTmXzbHKX/Ds5L/lmYkf56nxf8WBud8h46xlY/dH5i94gFq4m1LrGbpTd9GTuhMp2ossSuHSm3odGWcdlWBXO7d/BoHDQObtpOyR+WNP26sZzHwnSgfMNh9Gd3pJlIKnqYX76UndTU/67vkfKClcelJ305u6m2q4u9OF7tT+l9810oxPMNt8mIyzlqHsd2PLTOfYLbLOJoZy7yVIJplq3M/Z/fw1nj3AqsI/x7MG2g2qQuJY+Rd1/RT0pe/FsQpMNP5pPihDu9Iw23wU3x6hy79t2aSuzueyd7xL2SN4L+pvKrCxZQZNsqDDui3zDOfey4G53+GF6f9Ed+oO+tL3UvRvwbcGruXlnF+1SJVpRMfw7AFS9sqFn4cQpO2VePYA9egIUVLCOeNW0rdX4NsrFn6ZhYUts2jUiwYdtGsvoZqlGR2nlUyQqBqJDqiGewBQLF3XrFONW4lu0orH6PbvYGvvL+PbwwuOrxru6zTSznGi+hnObHA61RAZ6zqtZIIzm3UsmSLlnH1+s+4mpHBpRMdJdAuLDLVwP0pH5NwtyBfN1yaFS87dwljti1TDPfSl39xp/Ft+10grHiNIpunyX4Mtz27kyrmbsGWGargLpSOsF5Ux46ztlP38wVIIQcZZR7d/B9PNB6mGL9CdugOtNaXWMzSiowzl3otvD17y47vULnvQtWTmPN2Yzj7BQghWZN+Jbw8yWv1bZluPMd34JmlnNQOZ72Ao+25cq2fZ/5ItR0q3UDpAir5z9iCQwsESaQI9hdKtBc9ZInXWa8QZ/z4zN5ioFuP1L3Ky+je04jEs4SOlh0ASJjOX9qBegTWFH6Y/8zaCZIJdU/+BRnSYMJnBt4cXbBepMhpNqfUklWDXOffVTpct/C4KJNY5eh20c/5Wp2aagGj3EBCIs3oBQPtasK3246fz/9ayvEbabRcJtpU9q5bdvjtIIXE72734B1dgicwF/VhI4dOfeQvTjW8w2fgaRf9WtI6Zbn4TISz60m+8Iipmlz3oCuRFDayVwqPbv4uidzP16DAzzQeZqH+FQ6Xfpxbu7Yx6K16u4l52Sr94OOrikMJDCgetQxRnzw6miNtBGefsPLKQvFwfZmjXACcb/8T+2f9Byh5hU/fPkXWv64w2szla/guOlP/oEh3RK2PLPJ7V10mZfID9s7/FscpfdlryT+dCLeEjEAzl3sdQ9rvPszdJyh5a8Ei75n92o6zqDKGXwu0EJoklU2g0iT738vFKnUod+JyZCVxu14glUwgkiWpxrsa59ncubnf/OkfIudCh90IIiv4tZN1NzDQfphWfROuEudbj5NzN5N0L79u+lJZlglQIgSVT5L2trCn8K3b0/zYFbwdTja9Tiw6c71UA831vL1PJLug9BA4gOhffwm2jZG5BHvvsF3f6Q1/inKct8/j2EEEyTRifPZQ7jKcJkik8exBbXugw6oXaDUAPkKgmawo/wkDmHWTdDfj2ALYsnNUlaykJYTGQeTt5fwfTjQeYaT64IM+ccdYihE2iGmTcDeS9bef4Z8tZfUYT1ep04zq9L601jegoSoedvtZ+53a5/R716NBZo+GUjqlHhzrbrTlnTfjir5GLPksXtJVvD+BYRRrRkfl+2ae0u5IdJ1G1+eN9NVzZTV/mXoJ4nNnmt5lrPUEYT9GbfuOC3hXL2bIKuokOOp3Q4wVfWtfqw7dXoEnat2ZnEfNdtlrx2BnbdKYhvEQB7NQtYiseR80P0T37PRyrC0ukqYQvECXl+ecT1WKycR9RUjr/e4gUApsgmSRRrc5+X/1xODJPb+oeYlVhvP4lYtWY32esGozXv0SkyvSkXovzCoMu6HbwEKIz1LbzqFbUo4PMth57xeW/HFyrl5W5D4GAY5W/JEgm5s9x3ruejLOBmeaDlJqPo3Q0f760TkhUkzCZReuFDUOakKnGNzrzZ+hO3+gSk/WvIZB0+bfO1/aK3s2knZXMNL9FNdwzvy+tFbVwD9PNb+HbwxT9m+f3/8qvkYsnhIMlUsSqtqDx88XfxZS9ki7/VmrhPmaaD82XrT1XyQzjtS9iyRS9qbsRvLrbfyEEvanX41rdTDcfYLLxNVy7lx7/zs4d2fJ3wT87SkcE8SSxqlKPDqN0QKwaVILn8exBHFnoNJi98pPajI6xd+a/kXU3knU3YsscSoeUg51MN75B3t023zXpTEII8t42HKuLsdoXsGWWlD2C0gGWSNObvqdT+zzjOHQdpZoEyQSQ0IgOUw6ewxIpbJk961hO1UxS9jBTjftJlVaQcdejdIzAoi/9+vk5AzLOGgredkrBU+yb/Q160+35EEqtp5hrPf6Sv8i+PUzGWcdc6wkOl/8vBW9HZ+CDojd1z3yLrtaKMJkmUhUS3aQeHgYUQTxBJdiJlD6WyODb/fO3tCuy7zo9MU4yR1fqNYBgrvUYE7WvUPRuZCj7Pa/4M5TCpeDfwHTzAY6V/xylm1giSzM+ynjtywjat9VnOjVgoz2KqUk13IvWCaEqUQme64xi8/GtgUs+i50Qkt703fTU72Ky8XVGa59nTeGHEDh41gBriz/C3plf54WZX6I//WYyznoQgjCZphLsImUPs6HrI1ji9BwGUrhUw93smfmv7SAjJNONB5luPkCX/xp6Uq+bPwbfHmJ1/gfZN/ub7J7+RVZk34VnDxLE44zV/p4wmWFD10dI2Svn93+x18ipoB8lc6fPb2e0YCXYiSO7sGQK1+rDlgu7WtkyTdG/mROVz3Kw9Lud4fLt3GzRu3F+oI4l0qzK/wC18CD7Z3+LWnSArLORWNeZqt/PXOsJhnLfQ1fq0vQsSDur6E69lon6lxBIelL3kHZWXzEzBF7ELGPjPD/1C7TikyQ6IFZVBCWen/r3nZbWzWzr+w3cBbmkizsJ7f51grHaF+fzXAKBJdMU/dewtvAjC7r1nCnvbmdN4Yc4XvkUB+f+TzuXLBy6U3fQk7oLOg1BzfhEexRXPI7WcTv46oij5T/jROWzCGGTdTdyfd9vnDUYIe2sZl3xxzhS/hOOlP+4XTphk3e30p26DYt20HVkkfVdP8nBuf/T+TX+KlK4pOyVrC3+a6bqX6MS7j7ncXhWH+uKP8rB0u9zovIZTvBphLBJ2asoejfNB12lW+yd/TVKrWfQxO1aMTFTzW8w13q8PROa1cW23l+d73/qWf1c1/MfOFL+ONONBxivfwloT2bUl3kTawo/jP+iHOXLWzg8fEXmu2hER5mqf41dUx9FChdbZtq38t4OXpj+6IJXa0KOlD/GeO3L6E5eOdFNyq1n2Tn5M+2uWlhs6f0lei7DZD62zDKS/z5mW48zWv1r+lKvJ+dtRghJX/pNSJHieOUTjNW+0Bl4orGEj2cPdLonLfyBskWO1YUfYrJxH/tmf6PdU0F49KTuYn3XT+LIrtNnTkgGMt+BEJLjlU9yqPT7aB3Pf96bun+Owcw7FzROXew1okk4Wv4zxmpf6JzfkFjVqAS72Dn5s0hhI4XHpu6fP2tEpsBhZf5DBPEEc63HmGk+hMDGkik293x0PuiemvtjS+8vcqT0J5yofLaTw5a4Vg+rCv+cVfkPY8uF/YcvNj6cWa7+9JuZqH+JRAf0pd/QyXtfGS54EvN2rXbneUdu2TJLwds+3wgTqyrlYGdn+rzNC76c7eGVe4mSOfLe9gW1t1hVaMVjRKqM0iFC2LhWDyl7uNPKef4PSumIVjxKKx5D6RhLptrdnc6YeyFWdcrBzpdszLJlhoK345wDE7ROaMXjnSHBAZb08awBUvbwi46xXcNoRseIVAUpfNLOSjyrj3p0iDCZpeDdgHWOmZ60TgiS6fZ4d9XsDFXtJeWsnO9FoHVMOXieSJXPexxS2OTd6xfkHdtzSQQ04xMEnWk6PauXlD1yVk3y1LmyRYact3XB3AFaK2rRfoJ4krx3Pa7VNb//RDdpREcJkxmEkO3z44ygdUwleI60s3a+n7DWCbVwf3s+ipeQd7eeNYT2QrVzqodpxMfJuZvn3/uUdk3xORJVJ+tet2AQQDv9UqUZHydSJbTW2DKLbw+2ewlgdwYnROyc/Ail1lPcOPD7pJ3VNKKjJKqObeVJ26vP2Uvh1LkMk1ma8fHOENg0KXuk0wvBOmvbi7lG2p/TAVrx2HnPj0CcddwvPv5GfJQoKSOEhSPzpJ3V2DJ7zm2b8TEiVUbgdLobDp6zx0yQTFMN9uDZ/eTcTect37nUw4M8Nf6vsK08Nw384XkHbiwhs3LElU5rTbXcpNWK6OrJ4jjLv2vMtWRh0P09iv5NS12kq5bWitHa37F7+pdZXfgBNnT99HIcNPXqV44wlo7WmvGTc9z3xWfx0y69/XnuefNWEKKzfll75JNSnbXL7PYXUCUapU8/b/o3G1c6rTWhmmW89g84Vo7+9Jt4pWmKpWKC7hVi7wsnWbOhnxtfs46/+dQjHNw3wTOPH8KyJP0rCmy/aQ2PPLCHeq3FthtXU+xK88BXd+E4Fj19Oe5+8zYs68r6chrGKc3oBLXoIEoH8/NljOQ+SNbdfMVVJpZdndw4m9bQqAUUe7J4vo0Ugmq5Qb3a4k3vuIHD+yd5/KF9TE9WGF7Vw6MP7KE816BRD3jTO3Zw9NAUzca5c/GGcSWYaz3Jrqn/yPNTv8BM80EGMm9jVeEHLskaeovN1HSvAEJANuczO1Wl2YxQWuP5Dp7vkEq7WJag1Ypo1ANazYhtN67CsiW9fTlyhfT8kurG5SOwWFP4YaLce0k7a5e6OFedntRdXN/331A6xLV6ybobsMSLe0NcGUzQvUJs2jbMfV98honREms3DpDLpxg9Pss//t2TFLoy3HLHeh4J99JqhvQN5PF8h3TGQwjI5HykNDc1l5MQ0jSeXUae3Ydn9y11MS4J03vhDAuGbtLpgfqiJVl40WPnEkYxUaLI+Au7nLXCmMlSlYFiDs+9uN87rTW1aoswiCkU04ydnOPRb+7l3rdvJ5Pz8XyHRj2gUQ/I5nxsxyYKY1Jpl3otIJ1xl03g1VoThDETUxU816a/N4+Ury4vV6sHBEFET/fZSy4ZxhIwvRcuhNKa+57az+r+LvYcn+S261ZSyKbQWpP2XKbKNUZnKmxZ1Y8lJa0wJuW1+x+GcYJWmpTnUG+FKK1Jew5hnBBEMWnPQWvNY3uO8ZrrVjHSV6ARRNhS4rv2ywZyIQS5/Omhtam0y6q1ffT0nx6ym8n6ZLKn+/2e6laWzS2vjuNxovj6t/biOBZDAwXSKZeT4yUKuRS5rM/oeAmAkaEuJqYqJEqzarib2bkalWqLYiFNkihKlQaZlMfQiiJjE2WyGQ+tNeVKk5NjJQqFFFIIursylMoNshmfYydmyOdSDA0WX3WgN4xXwgTdM2itmSrVCMKYI+OzbFnVz7GpEscnS9y+eRX7T06z6+g4KddhbLZCpd5iRU+eQsbn2UNjrOorsmP9CnYeGkNKyeuuX8PRiTl2HRlnqKfAbZtXUsi0g/ih0RmePjDKxuFedqxfgXWRLbC9/Xl6+1/pHAlLq9EIqVSbvPsdN2HbFt98dB8p32X/oUlW9Bc4dGyKrkKG/YcnKVeaKK2Jo4QX9o+xaqib3p4sjzxxkEI+zWxpnHvzKcqVJuOTZfp6sjz8xEGGB4uEYcLOF45zxy3reGrnMUaGuth7cIKbrl/58oU0jMtkedxvLiO5tM/oTIVc2iOIYuqtkFKtyVS5zprBbratHmSkr8CT+07QCCKOT5VoBBEruvPctnkVKddhpK9AFMcorSnVmsSJ4sj47IKJwzIpF9exaIXRNZbEAce2UFozPVuj0QxoBRH9vTksSxLFCbmsT6ETSONEMbKii3zOJ+U5rFvdS09XFt9z2LCmj7TvksQJmYyLUpo4UYRhwoqBAoWcj1KaSrVFEMasGulmeEWRfQcniJNLMymMYVwsU9NdQNCTSzNTqdObz1BvhUyVauTSPq5jkfFdZqsNJks1rl8ziGNbrB7oIohisikXKQVBFHN0osToTIWZSoPD47OkvXZud67WYGymgtt5XT7jMz5XJVYKy7p2fv/8lMOtN6zmyZ3HGBoosGPLCC/sG2OwP08m5bH/8CSea3Pv6zZz6Ng0URSTSXuMDHXhddI5I0NdZDLtx5SG0fEStVpAtdZi+5Zhnn7uOKtGuhkaLHL42DQjK7qoVlvUagGDAwWsZZLfNq49piHtDFprmmFEnCgsIbAti0qjhZSCbMrDsSxmqw1c28JxLErVJrm0h2NbaK3xXYc4UcxU6iSJoiuXJowTWmFExm83ZJWqDWxLkvZdKo0WuZRPNuVecR28L5djJ2eZK9W5YZtJARhXNDP3gnFlSBLVnlTGNnNLGFc0E3QNw7gyaK2ZDCapRCVsadNKWvR6fcwE06SsFD1eL0fqh1nhD9NI6kQqZGV6FY48e1bAJXTeoGsSW4ZhLCuhCjlSP0if1081qgKwv7qX2XCGSlyhFJaox3WkEIw2T7SXbb+CQtmVU1LDMK4Jp9YgtKWDFBIpJBqN6PwBsDqPr82sZ7I1QTWuLGWRL4oJuoZhLCue9BhOreRE4xgpK0WYhGzIbiLn5ElbaQpOAVs4BElAPanR5XaRtq6ceRhMTtdYFO3vWYzWUWdFWIf2gpsBcGoyHokQHu10WNLZVgLLs3eH1glKx+0lhV5iEm2tFUpHL7vdeV9LgsRGkwAC+SrWITQWjRkGbCwdrTVRfJB6469IkkksawX57L9EEzFX/lVAI7CQso9C7scRwqFa/zRR9AJC5sim34fr7FhWgVdrxXRrF7V4lC53Iym7DymszsKNDWyRItYtBIJKdIxqeIwubyNpZxC0xhIeka5jCa+zeq9ACptYt3BEGkVn9WFiJptPM5i+g1KwD0t4FL0NRKqOLVNY51hSyljeTNA1Ljuly1Sqv4vr3kg28yGUKiGEj1Z1tG5SyP0UluwGYSNlnkbzHwjDZyjkf4Io2kul9jG6C/8Fy+p6+TdbJIqYZjJNt3cdU81nsYSLlB6OSFONjpF1hgmSuU6tHrr9LZSC/cyFByi4a9FaMdl8im5/C0rH1KKTpO0+wqSCb/fQiCfQWjGcubuzZLvCtfJESY1SeICp5rMU3Q30p25ajkvVGC/BfFrGZRdFe9G6RSb9bizZh22vRcwvVCiRIo2QGaTIAJJW8Cip1Ftx7M34/htAJ8TJ0SU8grMJLGzhUwmP4sgMihitk/nVfx2ZIW0P4MocUrhUwiO4Vg5XZim661A6wpY+tkjRiCc6Kw0L8u4aEh2SqADPKrYXW01mCJMqrWSOVjJHrJpIYeNaOa60pWoMU9M1FkGSTCJlLwKLWuOvaLbuI5/9cRx7FUkyylzlNxDCw7WvI5f9FySqhG0NtNd10x5C+KiXWPV4KUhh0Z+6iSApoYFyeJAefxu2SBEkczgy16mBtptFgqSCb3WhiBFYKB0BkOgWK9K3AwJHphFY5FlD4ocoHeLIDAPpW3FkhpyzEm0rPKtAxl6BI800llciE3SNy04IF00Iwiabfm+n5tvuf2lZKyjmfwZL9oBwECKFEHangQ1AoVEsx6+qLVPYMoXSCSmrB6vTOd+WK87a1pGnW9e11vT611P0NmDLFBLnrHy1Q/qs17rkznjvwUt6LMbiMekF47Kz7bWoZJokGUeIXKeHQpvAxpI9WFYfliwCEsdeRxDuROuIRE2hdQ3bGlqy8r8cKaz5gHshhBBY0sOzClhiefbMMC6f5Vd9MK46jr0Gz3sNpcpv4djrieKDpPx7AUjUFJXax5Eig5RFMunvJp16O6Xyb1Kq/CZJMoPn3oJtDy/xURjGpWH66RqLQqkGYfQCSs1iyR4cZwsAQfgYSjdod5lK47m3IYRHnBwlig4iZR7XuR4pU5hGI+MKYia8MQzDWERmwhvDMIzlwARdwzCMRWSCrmEYxiIyQdcwDGMRmaBrGIaxiEzQNQzDWEQm6BqGYSwiE3QNwzAWkQm6hmEYi8gEXcMwjEVkgq5hGMYiMkHXMAxjEZmgaxiGsYhM0DUMw1hEJugahmEsIhN0DcMwFpEJuoZhGIvIBF3DMK5aURgzMVZiYqxEFMZnPV+vtTh6aIokUefdh9aa2ZkarWZ4ScpkFqY0DOOq1WxGfP0rz7Np6xCWJTl6eIqRVb1MTZTxfIf+wQJHDk3R25/n0IEJUimHXC7F6Mk5BlYUSBKFAA4dmCSOEzZtHqJebxGFCZu2DuG6Fx9CTdA1DOMqplFKE8cJUxMV9u8ZQyWaeq3FLXesR1oSKUAlilqlSaXUIAxiXNfG8x327DqJSjRhENPVk+Xg/nFOHJ0hX0yzak2vCbqGYVyZwjCmWm5S6Epj29Yl26/r2tz22o2AptWKGF7Z06nB5khnPGana8Sxol4PyOVTxHFCV08W17XJ5VP4vksUxgwOFcjl07SaIT29ObTWpDLuKyqTWQ3YMIwlFwQR+3aPUSk3WLOujxXD3Uh53gV1rwRmNWDDMJavJFYErYi+/jzjoyXiOFnqIl02JugahrHkWs2QMIw7+VeFFFd0LfclmZyuYRhLLkkUUxNlJsfbvQqSRGE7ly63u5yYoGsYy1CiY+pxDY3CER6udIl0hC9ThCrAkS5KJ8Q6xrdSS13cVy1fSHPjLWvR6Ks64IIJusZLULpFufkQrj2IUg1iVcF31tKM9uHIXjQJjtVNoppoIrSOyXo3IoW31EW/4k22xnh05n56vH4G/RF8K83Tcw/z9sH383TpYbbmb+Z44xDHm4d468C7keLKDlL1WoskSRhZ3YvjWAiTXjCuRQIXEEiRphHvJlF1BBZBfJJIzKJ0CykctI7w7NXk/dsROEtd7KtCrGOKbg83Fe/ClR7jrRPU4iqjraM0kzqRCpkITtBKGlSiEkW3Z6mL/KrYjsXhg5NMT1bZcfNq/NQr6451JXjVQXe6WueFk5Os6e2iGUUopYmUotJssXGgl1oroNxscd2KPjLe1Xsir04aTYjWEQIHIWyEcBE4WCKFFC6t+Bi+vRpNhNJNpLjyb3WXi9HmUR7XijWZTdjSZoU/wljzOJGKqMQl6nGNgtPNaOsYBbcbcf5eSsue49rkC2mK3Zmrvp/qqw66tiUpNVpUWgGPHzoOCDKeQzGd4umjoyRKcdu6EdxL2OF5sVRma4wfnkRakr7hbvK9OQBmRuewXZtiX556uUFltsbA6l7qpQYaSGU8xo9MEYcxg2v7SWV9mvUWcxNlBlb3IaVg+sQss+MlENDVX6BvpIckTpg4Nk3fyh5cb+lrjJoEW/YghE3WuwkpPBJdw3fWoHQDgLS7FVsWiVWJMJnEkkUEV95nvRytTK/j9u43YkubE40j5JwiAsFcOM1E6ySJjolUyFjzGNfltmOJK/fGtV5tceLYDBNjJfr686RMTff8hBBYUuDaFmGc4FgWidLUWgFbhvs5PDWHa9tXZBeQ5x/czTPf2MXgmn4mj0/zvb/wPWQLaf7fb/89vUPdvPcj38mBpw/zN//7H/mJ3/0h9j1xiCROqJcbTBybJt+V5VbXZuV1Qzz/rT18+eNf58d++wfoXlHk6599mFqpxuDaAdZsG6F3pJuTB8b5+Ec/w4c/+h423rxuqQ8fKVzy/mte9OjAObf1GLr8BbqGWEIyG07xbOnb9HmD2NLBlR5DqVXsre6kEs1ye/cbKDg9fHv2flpJk4ydW+piv2L5YpqhkW6EgHTm6m4TeNVBN4hiXNvCd2zu2LAKKQSOZTHclSftOSit2Tc+zbaRAdLuldUtOEkU171mPbe/42Y+8St/TXW2RrPWQmvN3GSZ6mwdIQWOa7P70f1orZkZnePkgTE+/NH3US83yBbSKKU48PRh+lb1cPj5Y3QPFtFas3rrSjbevJZifwEhBPufOszQhgH2Pn6QDTetvaobE4yX1uet4LW9b0FphW+lSVlp+rxBXOnzzqHvQyDI2Hkkktu633DF92CoVprtIbZ97SG2V7NXHXT781necv1GAFb1FM96ftvwuWtGV4rHv/wMJ/aNMbxxBX0jPXz7S08xvH6QymyNY7tPoDVsvGUtJ/aNUejNUa808FIeQgq+/pmHyBTSvP79dzI7XmLHPVvZ/9RhbnjDNpI4Ye/jB6jMVNl+9xZcz+Hw88fYcfcWnvnGLhrVJpl8eqkP31gijnTp81ac87mC073g/6/kGi60p04UCJqNkFYz5CqPuab3wsvZeud1vP79d5ItpknihN2P7qdZbxE0Q1zfZdMt68h1Z8l1Z3n8y8+weusIlZkqftrlpnuv54VH93Hw2SNMHpvmhUf3MX54kspMFcdzeN17buf6u65DSMGJ/WMcfeE4oBk9OMHJfWNsunX9Uh++YVx2YRjTCiI2bR1CSoF6ibltrwYm6L6MTCFNvieLEILpk7Mg4MMffS+tesAX/+irNCpNBIJtd17HV//8AW58w/XEYcLf/e5XiMOYVNbjwNNHeNePv41Nt6zni3/4TxzfM0ocxjz79V3MjM4xsmkFowfGueM7b+ENH7yLx7/yDPuePMSGm9ci5ZWVkjGMi9VqRryw8zj1WotcPkU2l7qq87pmlrGXMDteQiWKnqEuhBDUyg3KU2VWrBtEK8XJ/eOkcj5aa3qHuzm2+yS57ix+2uPo7hNopRlc20+93KB/VS9+2mN6dBY0tOotJo/PIKSgb6QHy5KdAJ+jVqpTnq6wYt2ACbrGVS+KYo4cnCIIIlzXZvW6Prxl0HvnVTpvg4wJuoZhGJeemdrRMAxjOTBB1zAMYxGZoGsYhrGITNA1DMNYRCboGoZhLCITdA3DMBaRCbqGYRiLyARdwzCMRXTFBN1WEHH46DTTM1Vq9RZTM9UFsxElShF1lm2u1VuMT5RJrvIx3IbxammtmZqtEccJ03O1BUufN5ohTz5/DKXMdXQpXTFzL8zO1th/cAKNZvvWEQ4cmuT2W9cxOjaHEAKlNEePz3DTjlU88vhB0ikXIQRzpToD/Xlm5+pYliRRmkYjoK83x2B/YakPyzCWVJIoHnziAPfecR0PP3WI7dcNkcv4KKVpBhE7944CsG5VL12Xeda7E42j9Hr9+FaKWEWMtU4SJC2qcZm0lWFlei1pO0OoQk40DlONKxSdHoZTKxlrnWQunCZlZViT2YAjl+8w4iumpqs0VKpNuosZMmkP27ZoNUOOHp/l0ccPASClxPccfM9hZKiLg4cnqdYDdu8b49CRaXzf4dDhSQ4cmuTg4aklPiLDWB7myg2+9sheDp+Y5cR4iaMnZzl4bJrxqQpxkhAniieeO3bZy7G3+jylaBaAlmqxq/w0z5YeoxZXmGiN8tD01whVyJOzD7O3ugsQNJM6e6u7eHL2YZRWBKqJ1su7Zn7F1HRTvsO2zcNsXN/PidE5ZufqzJYaRHFCf1+enu4sJ07OEUYxwyuK9HZnUUpzcqzEyuFuwkJMdzHDioEiUZzgecv/0LXWKBIEEo0iVjFCCAQSpRNsaROrGEvYWOL0Cqqn0i5mEnTjQmTSHrduX0WcJFhSUmsG1OoB3YUMnmOTz/rMlOqXvRxZO8dMMMWeyvOsSq/BlR6xFbM2s5EBf5gvnPwMJxtHOdE8wlsHv4eCUyRUIV8a/Ry3dN/FSGr1ZS/jpbD8I09Hd1eG7q4MAKtX9rB6ZXv10zWrTq+Cevdd7cnUc1kfgHw+xYZ1/Qv2s23LlbOsjEJxuLaPnFNkNpxiLpxm0B+hmdSpRCXyThflaJa808W6zHXEOiJlpRlvnSRn58nYOZpJg7SVwV7Gt1vG0hFSsGX9IP3dWbZuWEF/d5bn94/huQ4r+vOEUczYVIUbt4xc9rIUnG4O1/dRjkqAJmWlCVQLAFvYONKlntQAQcpqpzqUVkQ6IGvnrphKxhUTdK+UE3pJac10OMHJ1jE86dFM6gghSHSCa/kEqkmvN0CoQsZaxxlrHmdlei0nm0cZ9EdIdMKe6k5WpdcxkjLL/xhns6Tkhs3DAGzf1K6QDPTm559fM7x4S7tn7AwTrTG2FW7gYG0vm3PbKUWzaDS1uEIradLj9gFQCmfo9QaQQpKyMkwFExScIiDaf5bxd/2KCbrXJAF5u0jWKTAXTpPoBEe4SCHpcfpIWWmO1A/gSq+9WLoK0Gh63H4sYTMbThEkLSIVLvWRGMbLSlkZHOmwNrORo/VDZOwsAsGzpcdRWrMxt4UBfwVb8zv41vTXKDhd9HoD7CjcwhNzD3OscYicneemrjtwxfJdTdjMp7uMaa0JVAtLWCQ6ppk0kMLCkz6OdNFaUYnLpKx0e42ppEHGzqJ1OwA70p1/zBHusv71N4xEJ9TiKjk7Rz2u41keraRJM2ngW2lydh4pJEorqnGFIGmStrNkrCyNpEY9ruFZPjm7gBRL3kfATGJuGIaxiMwk5oZhGMuBCbqGYRiLyARdwzCMRWSCrmEYxiIyQdcwDGMRmaBrGIaxiEzQNYxFpFSdVvgMWscXtr1uUW/+E63gCbSOLnPpjMVgRqQZxiLRWhMnxwnCp7FkkTDahyV7EcIjTk7iOduI4sMoXce2hpEyQ5LMEMdHsL1hovgocXICS/YQxUeQMoMlB4mTo7jOFqLoIJoYx15LGL2A795KGO1FCB/fux0hzOW+HJiarmEsGkUY7QcdEUb7gATPvR6lqzj2WoRIEydjhNEeEBZB+AxCZtBooD1dYRA+jdYRWrdQqkqiJrGtEaTIEUS7UGoOUCjdROkaCJtETQPJS5TLWEzmp88wFo3Gc7djyTcQJxMI4QI2jr0GIdIIbBx7LY6zHoELODjWSpRzPaARwiOTehdaN9E6wHU2Y1l9CDykzJFJvQWtFVJ249jrkLKIpRWWLALWkh65cZoZBmwYy4zWmkRNInCQsuusOTO0DlGqimUt3gxgxkUzcy8YhmEsovMGXZNeWEJaa1SiUIlCWqdu/zRag1YKy7ZIEoUQAsuWZpYww7gKmKC7hJTSPHH/C5SnK2SLGdAQRTFoqJUbDK/vZ/zoNKmMx21v2U6qsyKGYRhXLhN0l5LW1MsNWo0QpTTl6SqWbeGlXCpzdXpXFKlXmiSxWrA0tmEYVy4TdJeY49rkihnCIMJ2HbyUQyaXotCbI0kUqYyP6zvEkQm6hnE1MA1pS0hrTWm6SqPSJN+TRXXyt0IIHNem1Qhp1Jo4nkPPYAEpTbdqw7hCmN4LhmG0aa1oD7Y49SN+Kj4kncf0GY/rMx7TZ2x75n+3KwrtWKIRS79UznJgei8YhtER74Z4Hzg3g64AFshuaN0H3l0QPgEyD3igS2BvgmQUTo2Mk32QHANrFYgUyCJa9oOuQ7QH7VwPIm1625yHCbqGca1RVdCdmm60D4QF3r1gDYLIoNUMAg2yC+zNED4O1kg7wEZPgzjZHpqsZhA4YPWCtR6SMUiOgp4D93YQXUt9pMuSCbqGca0RLjibQMh2wAVIxkFNg24hrIF2gNVBO4hanVosIcgBUOMI2QciCzINqgbJEdDN9usAzIxo52VyuoZxjdGqfjrY6oT2ZR6CmgXZTzvfK9qBVodgDYAqt7cTqU5APRWwLSABVQKRATrBVg4gxDU934NpSDMMw1hEZgl2wzCM5cAEXcMwjEW06A1pWmvCMGZyskqxmEIpyOd9Go2QyckKXV0ZlFJoDZYlqVSa9PRkSadd0wXFMIwr3hIEXdi9e4wgiNBac+z4DK+9ayNBELNr1wnWr+9nz54xAHL5FJ5rUyikFruYhmEYl8Wipxe01jSbIVIKDh+ZQql2W10q5dDVlSGd9qjXA4IgZtXKHixLMjlZXexiGoZhXBaLHnSlFAwNF5mdrZPN+jTqAc88e4zZ2TrT0zXiOGHV6l5WruwmCCKCIMJxrumuJ4ZhXEWWpMuY1hqtdWe8dqcggvnHTm/XLsKpSWAMwzCuEKafrmEYxiIy/XQNwzCWAxN0DcMwFpEJuoZhGIvIBF3DMIxFZKZ2vMIkqozSAbbsu6geHVpHhPFxtA4QwsWxVyKFe4GvTYiSMaRIYcnuy9qTpP1e49iyBykXZ/VjrRVxMgFCYst+01PGuKxM0F0mtFYE8UEqzX8kiA4ghEvWex359HcghTe/3WztUwTxAYaK/wUh0i/aR0SUTOFYg2ctmZKoGrP1T9IMn0OpGqt6/wjXHrmgsindYrz862TcW+nO/sArPD5NlByn3PxHWuFuhJCk3VsppN+FJbPz28XJFCdnf57e3L8kl3rDWfuJkxmEcLBk/ox9K6aqf4BjDVJMv2d+6ZiZ2h8jRYauzPe+5BIympip6h8gZZaB/M9gLgvjcjLphWVAa00zeo4Tsx+hGT5Hyt2OYw3Sil7ozPB/Wtq7mZx/L+IctdQgPsJU5f+gCc96zpJFBgv/ib7cj6KJaM+ZesElROkGiuAij+y0MD7Eidmfp9Z6EN/ZjGOtohXtRuuFZZUyRyH9nXjOurNLoRUztU9QD759Vvma4TME0f4FjzbD52hFe7iQno9KN9C6dUHbGsarYX7SlwFNyEz14zjWEENd/xVb9gK6kwpo32InqkwQHUbg4DtbOPP3UumQKBmj2ryPVrSHZvgMAhdLduPaq88YXCIQwjl3GbQiUXNEyQSaCFt241grEOKMr4iGKBkjUdNYsohjDS18/nzHpyNm658CNMNdv45jDZ91fForwvgIiSrhu9uwZHHBPuJkjjA+TD34FkJY2LIHhIVnr0eKl5+bI4xPAArHGkEIidYJQXwIW3Yhz6g1x8kUsZpBiiyuPXLe82UYr5QJustAlIzRDJ9noPAz2LL3jACZOmObcWbrn6YZ7sR3NjLc9Rvzz8fJJDPVP6URPEaUjDJd/RhgkfFupyf7QxdUhiDez0T5t1CqBmgSXaU78yG6Mh+Y36YRPk4jfAqlayhVpyv7fXSl3/OygSlWs9SDRymm349jDZ/z+CChFnyLWutBWtELDHf9N7L+PfPP1loPUGl+hVa0F6UDmuFzSOHRn/9pXHvNS76/JmGm9hdo3WSw+P8hcNspk9Kvkk9/B8X0ewBohXsYK/8qSlWJVZlC+p30ZH9gQXrHMF4tE3SXgSSZResWrr0WgCiZIlElBBLHGkLKFJ6zieGuX2Oy8j/Puo12rCEGC7/AbP0vqTbvZ7jrfyCFD8LiQtuEHGsFffl/284HYzFb/zSz9U+RT711vjYaJzMMd/86tuyl3PwHZqp/Qtq9Gd/Z+NLHpyrtGqyzASEEcTJLrGY77zuIJbMI4dCd+X5y/r0cm/lRtE4W7COffgdp71aOzfwberI/QCH1HQAI4XEqJVAPHmOy8tucWjq8Fe0m490JgNYhakEqQ6N0C63j+UeiZJyBws/h2mupBd9isvK/yLi3kPZuubCTaBgXwOR0lwFNAoLOmlIJ5cbnOTH7UxyZ/kFa0V4ABKLz/NmT/wghkTIFOCAkUvpImer0TriwqCtFFtdaSZxMEcQHkcJDqTpKn87jZrzb8eyN2FYPOf9NaB0TRAd5maHkgOrExXbZq637OTH7EY5MfZhG8PgZxyEQWOcssxQuUvgIJFI47eOTqQUNZFq3SFSZRJVIVPmsfPHLSbk34rvbsK0ucv7dWCJLM3z+Ao7PMC6cqekuA+2WeIs4mcGzN1FMvxff2cro3H/sNHpdXlor6sFDTFc/jpQZLFkgTqbaPwZnlbNNCh8hbLRuvuz+pcggpE+spgDIp96CZ6/jxNy/u+jA+FKy/t0MFP4dp4L2idmfPsdW+oy/FwZTS+YQnXqIwEMID6Xrl6x8hgGmprssONYgjjVAPXgESNqNVPYQXEAj1ZlE57aai6yZKd1guvonuPYqhoq/wlDxl+nKfHA+AJ0SJRO0G8A0iaqgdYSU+ZdNYdiyC89eT731EEqHSJHHsYcRXFg/4RfT5+15IQCrc0cgObPG3P6BaPdO0GgSVSVRlQWvjpPJ+XSD0nWUbmDJrgtO0RjGhVi0mq7WmrDVrrW5vvOyHdDjKEZIiWVd/b8LUuTpynyAqcrvYckCKfdGovhEJ0i0+5y2uzQ12o1YukWsprAoIEVu/hbbtvqJkynqwaM49jBSZHDtkfZUmoQoVSNWc2gdESfTSJE7o4+sQOkmsZohjI9SbvwdL64JNoLHqLbux7GGKDc+jyW78J3NvFwKQ4g0XZkPMF76NaYrv0/Gfy1xMoPStflttI5JVJVYTaN1SKzmiJMZpEh3UicghI9tdVNvPYJnb0IIgWut6uR1X+L9kXj2eqrN+6m1HsSxhqi2vtYeEHGGZvQ8leY/4TubqLbuB606+VwTdY1L57IG3TiK2f/MUWYnymzYsZrpsTnGjkzxxvfdjmW99Bd59+OHKPblWLlxxeUs4rIghKCQeidax5QbX6DU+DxCOGS823CsASBhpvZxGsGT80FpdO6jONYQ/YWfxbH6AMj6d9II72Gy+rtI4ZNPvY2ezmCGWvMbzNY/i9IVQDBR/k0sWaQn98Ok3Zvpzf0I09U/Zmzul7CtnvkGKCEsBBLXGibr3UWl+WXC+ASWzDFQ+Hkc6+U/HyEEOf/16EKLufpfUWl9DYFDyrke114FQBAfZrL8OyS6hNYRc/VPUWn+A/nU2+nKvB9opyl6sj/IdPVjjJV+EVv2MVj8BRxrBNvqx5JdC97XtvqwRA6Q5FNvIYj3M1X5A6TMkHFvIZd6ayel0L7b6Mp8kHr4GHP1TyOES3/hp/Ds9ZfkMzaMUy7rfLqHd53g+Uf2c+PrN9PVVyAMIp68fxf3vv92xo9Os+/pI/SNdBO1IjbcuJoju06yYm0fzz+ynxMHJrj97TvYeMPqV1OEK4rWCYmutvuvYrVzofP9dOfOzn8KC1t2zfeVbddog/nbZktkkTLdqSnXO93Bznw9WKKAlCm0VihdRekWUvhIkSFR1U4eV5DoClKk0DpC6UZnm9xFDkVWnZp6s9MglkaINEIIlA5J1OxZ3zgp02eNPjtVToGDJQuAbPf2EDZSZOdHpCldBiRS5NqvJSRRFQQCKfNo3UTgIEQKpasIHNrd5Wqdhrv8S45kM4yXcN4L47LWdGcnyoxsHJyvrc5OlAFQiWLnQ3vZftcmdn5r7/x2x/aN0ay3yORT9K/svpxFW5aEsLBF8ZzP2dbLn49267+PtPyzHrdEdsFw27NfK7FEAYvCGe95uuY4Xy7hYXH+/bx0+SSWyGORP+s5KVykNXiB+1hYzheXtb2dwHrRuRR4yM5dQfuB0zllS5zRSMjC4dWGcSld1p/x3qEuDj1/nD1PHKI0XWV2okxpqkKt3MBPe0ydnEMrjZfyOPLCSeYmy7i+Q2W2Rr3cMCMyDcO46lzW9EISJ5w4MEFlrsbKDYOUpquUpquMrB/AT7ucODhJV18Oy7aYOjmLn/YYWN3LyQMTaK0ZWttPtmhqHYZxNdM67qSLTo1SVGgdduYXsdCEnTTQFZXqMWuknYvWmlKlidaaYj6NlKaV2jAWWyt8nmrra7j2GjLeXdSDR1CqRtq7A9vqpVT/LPn0d+FcQPppGbl8Od1GM+TkWAmlzt130rYtRoa68NzlNw4jihP++C8fpNmK+NkfewuZtBljbxiLTekWliziO1tI1CxKVUh7tyOFTxQfB50QRoew5cBVMdfxq46Eh45O8d9/9yvU6mdP+9cKInq7s/zaf3w3I0Nd53j1EtMwV27QaIZmqKdhLCGtWyjd6IwEdIiScaLkJOiIRJVohs+S8m5BcOVXjF510F090sNHfvQtJPHCIaPjkxX+9DMPsX5NH8WCycsahnFuQrjtATHJBCn3JoggiPZhyQJC+PTmf5Ja636UqiItE3TJZX1uun7lgsearZCHHz9INuPzfe++jUz6dNccrTXNVsT4ZIV6IyCdchnsz5NOufO3DrNzdaZmq6xZ2Uu11mJyuorWmt7uLL3d2QWj1LTWJIliaqbGbKmOFIK+3hxdxTRyfh7ZtjCKGZ+sUKk0yWQ8eruz50y8aK2pNwLGJys0WxHZjMdgfx7fe/mRdIZhXBzP2dwZZCOwZJF86l0oXe/MkywRwifrv/mC5m6+Elzyo1BK89BjB3ngkf380PfdxYa1p9fy0lpz5NgMn/jrR9l7cIIkUUgh2LC2jx/44F2sW92eS/axpw/z6b99nO966w4eeGQfs3N1gjAml20H8Tffsxkp24G33gj43Bef4usP7aUVxAggn/P5nu+4iTfdsxnXsee3++znn+C+b+4mSRTplMuN16+k3ggXpLyV0uzaO8onP/dtjp2YQWmNJSVbrxvi+993OyuHL+8aYYZxrWn30T7df1oIG8nCielPDRK6GlzyoHt8dJbP/O3jvObG1bzhtdfNB0eAcqXJH/7FA5SrTf71P7+HkRVFTozO8ed/9Qh/9IkH+Q8/9XaK+TRKacYmynzhK8/ynu+8mes3DzFbqvPnn32ET37u2+zYOsxgf4E4TvjCV3by+S8/y7vfcSO33byWOFJ89Zsv8PFPP0Q24/G62zegNTzwyD7+7ktP87Y3buPN92whCGO+9LXn2XNgnM0bT7eKjo6X+L2Pfx3XtfmJH76X/r48R45P86m/eYz/+xff5Bd+4u3kcy+/UoFhGMa5XNKgW6sHfOpzjyEtwYfeczvp1MK0wpM7j7H3wAQ/9+Nv4bW3tSe0Xruql7lygz/+5LfYvW+MO29tj3VXSvGGuzbxXW/dgWVJtNZMTlX5o798kJNjJQb7C0zN1PjK13dxyw2r+eB3vwbXtdFaMzLUxaGj03zxqzu5afsqhIBvPLSXFYNFPvSe2+gqZtBaU8in2LnrxHwZldJ867EDjE2W+aWffWfntYJ1q3vRGv7Pn9zPU88d4/V3bjK13WWsEVfZU3mMbm8FI6mNSCHRgNIJo82DDPprkEIihY3SCQJBJZ5ltHmQnF1kJhzHER7X5W/BXaQViY1rxyULukmiuO+bL/DUc0f5Nz/0RlYOdy0ITEpp9h+aIIxint8zysnx8vxzJ0ZnaTZDTo6XThfMtti+ZWQ+fyuEoKsrA7RzxgBjE2WmZ2u877tuxnGs+e3yOZ9N6wd48NH9lCoNXNvi5FiJ7VtH5mupQgh6u7OsGCiQdLq7RXHC/kMTdBczrFnZO19+IQSb1g/guTb7Dk5wzx0bTdBdxmIdEagmnkxxormflJWhHldoJjXK0TSRCohUwFB6PROtY9TjMp5MMZLaSMHpRQoLV6ZwzDI9xmVwSYKu1poDhyf56y8+xT13buKOW9adFZSU0jSaIWEY8+2nDuM6C1dA2LC2n3z29G27bUt8f+HaWy8Oc0EYESfJWf1rhRCkUy5RnBB08rxRrEinnAU7sS2J61o0W2q+jM1mhGNb80H8FMe2cGyLRjNEKY28ogbHXFvaK7BJQNNK6tTjErGOsYWDK32UTuj3V2EJh2o0Sz0uk0mtYS6cwJEep2YmNj+sxuVwSYJutRbwib9+lO5Chve985ZzDoSwLEE+61PIp/n5f/s2Vo/0nLXNiwPdy8lmfDzHZnZu4ez+WmvmSg18zyGdcrFtiefZVKottNLzM05EsaIVnF4jy7IExUKa46NzNFsRuezpW8tmK6QVRBRyqQV5amP5SVk51ma34UifEaebRlwlbecJkyYajW9lcKWHQLI6sxWJJGMXKEfTgKbPG0aKi/suGsaFetXRI44TvnTfc+w/NMn3f+AOBvvz56whCCHZtnmIJFE8v2cU17FIp1zSKZeU72BZEusih+EOryiyaqSHx585Qr3RHpyhtWZiqsru/WNsWjdAsZAim/FYu7KHA4cnmZqpzW83Plnm5Njc/P4c22LH1mEq1Sa79o7OD5hIEsXTzx0nSTRbrxsyw4WXOVs6DPir6XYHyNpF+v2VZO0C3d4gPd4KMnYeR3rY0qHXG6LbG8SzUvT7K8nYhU5QNrlc4/J41TXdvQcn+Nw/PEVfT5bxyQpf/vquBc87tsWN20bo7clxw7aV3HPnRv7fF55gdKzEdRsGUBpGx+ao1gP+xQfvousiJrgp5tO875038wd//gD/+4/v565b1xPFCfc/uIdWEPHd33EjvtdOUbz1DVv5nf97H7//p9/g3rs3E0UJ33psP1GczGcchBDcfss6HnnyEH/+mYeZmq4yvKLIgcOTfPnru7jrNevZvmX41Z4ywzCuYa866E7NVAHN1EyNT/y/R856PpPy6OvJ0tuTI+U7/PCHXsfwiiIPP36Qx545DAi6i2luvXENntcuju879HXnzko3uK5Nb3cWt5O+kFLwuts3YFmSL351J3/yqYeQUrB6ZQ8/86/fzI6tw/O17ttvXse//P57+NJ9z/HHn3yQrkKGt7x+C6uGexgdL81vV8yn+Dc/+Ab+9kvPcN+Du6nXAwr5FG974zbe9bYbSL0oz2wYhnExXvUsY41mSKncOP8bCEFXMT1f44R2d7BaPaDRbPdCSPku2Yw331Oh0QypVJt0FzPzARbaczmUyg2K+fSCRrb2CLKQeiNAiPYouXONHlNKU621aLZCPM+hkPOpN9qNe13FzHza4NQot3K1RRTFeK5DPudfE+u1GctHkswRJ+NImcG2hgALrZtEyShCuNjWAEkygdIBjrUCrUOiZAwhXBxraH5Vjvn9qTJxPIoQHrY9DDoijI8hZQbHGiJRJeJkEik8bGsYIXzTmPjKmakdDeNKU6n/DVFyHK1jUt5t+M71lOp/iZR5LFlE4BDFR7FkkZT3GlrRLsLoAJbsBjTF7PcjxOnKSa35FVrhc0iZw5LdONYwtdZXsa0VWLKIUg2UriOEgxR5Cpn3d1ZWNl6B8wZdU3UzjGVKk5ByX0PKvZk4GaUV7USKNMXMh8mnvxutQ2xrgGz6nTj2etAKxx7Bczajic9aql5rhe/uIOPfSxQfRxPhOVspZr6fMDpErMZx7TV49kYgxNS5Lg8TdA1j2VJUm39PrXU/vnszSjWwZA+nLtuM/3o0CXPVPyKM96JJCKK9NMOnEMLr9DY+U0K99XVqzS+T9u5A0B4xKoSDED5KVWlFu2iFO6+quQ6WGxN0DWPZEqS829vpAh1jWd3EyVh7RWXVRAiPXOod+O5NNIMnEFikvTvJp7+HOD6O0i9ua5Gk3NdQzP4gKe8OEAJ0QpxMoHUT2+on499DLv1Owujg2atPG5fE1TFXmmFchSxZwJIDuPZaWtFOsqm3E0b7KNX+DMcaRsocYXwYrSMy/j1EyUkawaME0V48ZxtSZBbsT8ocguL8qtACl1b0PLGaIuO/nig5Qb31AFKk8N0bEWYY9GVhGtIMY5lSOugMZ5ZoHXQWbYzbjV3YIGy0biGwESKNJkSrBgiJFJkFjWjAfM1VdJae1zpCqSoIBykyaB2gdROE1Xm9qZO9Cqb3gmEYxiJ6xQtTmk56hmEYl5BpSDMMw1hEJugahmEsIhN0DcMwFpEJuoZhGIvIBF3DMIxFZIKuYRjGIvr/AUH83H1PcAdOAAAAAElFTkSuQmCC\n", + "image/png": "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", "text/plain": [ "
" ] @@ -3097,32 +1923,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"228fbc7c-d827-46ec-a478-9626c245777d\":{\"defs\":[{\"extends\":null,\"module\":null,\"name\":\"ReactiveHTML1\",\"overrides\":[],\"properties\":[]},{\"extends\":null,\"module\":null,\"name\":\"FlexBox1\",\"overrides\":[],\"properties\":[{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_content\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_items\"},{\"default\":\"row\",\"kind\":null,\"name\":\"flex_direction\"},{\"default\":\"wrap\",\"kind\":null,\"name\":\"flex_wrap\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"justify_content\"}]},{\"extends\":null,\"module\":null,\"name\":\"GridStack1\",\"overrides\":[],\"properties\":[{\"default\":\"warn\",\"kind\":null,\"name\":\"mode\"},{\"default\":null,\"kind\":null,\"name\":\"ncols\"},{\"default\":null,\"kind\":null,\"name\":\"nrows\"},{\"default\":true,\"kind\":null,\"name\":\"allow_resize\"},{\"default\":true,\"kind\":null,\"name\":\"allow_drag\"},{\"default\":[],\"kind\":null,\"name\":\"state\"}]},{\"extends\":null,\"module\":null,\"name\":\"click1\",\"overrides\":[],\"properties\":[{\"default\":\"\",\"kind\":null,\"name\":\"terminal_output\"},{\"default\":\"\",\"kind\":null,\"name\":\"debug_name\"},{\"default\":0,\"kind\":null,\"name\":\"clears\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationAreaBase1\",\"overrides\":[],\"properties\":[{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationArea1\",\"overrides\":[],\"properties\":[{\"default\":[],\"kind\":null,\"name\":\"notifications\"},{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"},{\"default\":[{\"background\":\"#ffc107\",\"icon\":{\"className\":\"fas fa-exclamation-triangle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"warning\"},{\"background\":\"#007bff\",\"icon\":{\"className\":\"fas fa-info-circle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"info\"}],\"kind\":null,\"name\":\"types\"}]},{\"extends\":null,\"module\":null,\"name\":\"Notification\",\"overrides\":[],\"properties\":[{\"default\":null,\"kind\":null,\"name\":\"background\"},{\"default\":3000,\"kind\":null,\"name\":\"duration\"},{\"default\":null,\"kind\":null,\"name\":\"icon\"},{\"default\":\"\",\"kind\":null,\"name\":\"message\"},{\"default\":null,\"kind\":null,\"name\":\"notification_type\"},{\"default\":false,\"kind\":null,\"name\":\"_destroyed\"}]},{\"extends\":null,\"module\":null,\"name\":\"TemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]},{\"extends\":null,\"module\":null,\"name\":\"MaterialTemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]}],\"roots\":{\"references\":[{\"attributes\":{\"children\":[{\"id\":\"40792\"}]},\"id\":\"40793\",\"type\":\"Column\"},{\"attributes\":{},\"id\":\"40775\",\"type\":\"DataRange1d\"},{\"attributes\":{\"height\":500,\"height_policy\":\"fixed\",\"text\":\"
Click on a word to reveal more information about it.

\",\"width\":400},\"id\":\"40791\",\"type\":\"Div\"},{\"attributes\":{\"children\":[{\"id\":\"40772\"},{\"id\":\"40791\"}]},\"id\":\"40792\",\"type\":\"Row\"},{\"attributes\":{\"data\":{\"angle\":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,90,0.0,90,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],\"color\":[\"rgb(186, 222, 40)\",\"rgb(61, 78, 138)\",\"rgb(210, 226, 27)\",\"rgb(223, 227, 24)\",\"rgb(108, 205, 90)\",\"rgb(69, 4, 87)\",\"rgb(71, 16, 99)\",\"rgb(70, 50, 126)\",\"rgb(112, 207, 87)\",\"rgb(216, 226, 25)\",\"rgb(49, 103, 142)\",\"rgb(71, 17, 100)\",\"rgb(236, 229, 27)\",\"rgb(82, 197, 105)\",\"rgb(61, 78, 138)\",\"rgb(55, 91, 141)\",\"rgb(57, 86, 140)\",\"rgb(213, 226, 26)\",\"rgb(69, 55, 129)\",\"rgb(62, 74, 137)\",\"rgb(74, 193, 109)\",\"rgb(69, 53, 129)\",\"rgb(253, 231, 37)\",\"rgb(101, 203, 94)\",\"rgb(65, 66, 135)\",\"rgb(71, 13, 96)\",\"rgb(221, 227, 24)\",\"rgb(72, 20, 103)\",\"rgb(124, 210, 80)\",\"rgb(46, 179, 124)\",\"rgb(42, 119, 142)\",\"rgb(165, 219, 54)\",\"rgb(200, 224, 32)\",\"rgb(110, 206, 88)\"],\"count\":[1.0,0.6304347826086957,0.34782608695652173,0.15217391304347827,0.08695652173913043,0.08695652173913043,0.06521739130434782,0.06521739130434782,0.06521739130434782,0.06521739130434782,0.043478260869565216,0.043478260869565216,0.043478260869565216,0.043478260869565216,0.043478260869565216,0.043478260869565216,0.043478260869565216,0.043478260869565216,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608],\"font_size\":[\"50px\",\"41px\",\"32px\",\"23px\",\"18px\",\"18px\",\"16px\",\"16px\",\"16px\",\"16px\",\"13px\",\"13px\",\"13px\",\"13px\",\"13px\",\"13px\",\"13px\",\"13px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\"],\"hover_color\":[\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\"],\"hover_font_size\":[\"55px\",\"46px\",\"37px\",\"28px\",\"23px\",\"23px\",\"21px\",\"21px\",\"21px\",\"21px\",\"18px\",\"18px\",\"18px\",\"18px\",\"18px\",\"18px\",\"18px\",\"18px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\"],\"text\":[\"Institutional Repository\",\"Zenodo\",\"Gitlab GitHub\",\"GEO\",\"WDCC\",\"PANGAEA\",\"OSF\",\"Open\",\"ENA\",\"RCSB PDB\",\"Materials\",\"Cloud\",\"ProteomeXchange\",\"figshare\",\"Copernicus\",\"Access\",\"Hub\",\"EGA\",\"Energy\",\"Platform\",\"FIZ\",\"Karlsruhe\",\"FAIRDOMHub\",\"CDDIS\",\"GLIMS\",\"DataONE\",\"ArrayExpress\",\"BMRB\",\"EudraCT\",\"PUBLISSO\",\"IMPC\",\"OpenOrganelle\",\"IRRMC\",\"HEPData\"],\"x\":[4,21,215,349,679,153,731,237,533,535,146,39,541,160,360,133,597,674,683,85,440,730,588,685,53,284,509,213,417,362,22,478,307,232],\"y\":[-134,-481,-438,-196,-324,-284,-26,-150,-274,-495,-162,-446,-61,-55,-161,-20,-318,-457,-285,-316,-58,-249,-379,-175,-397,-90,-351,-367,-472,-71,-275,-186,-270,-324]},\"selected\":{\"id\":\"41279\"},\"selection_policy\":{\"id\":\"41278\"}},\"id\":\"40770\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"tools\":[{\"id\":\"40783\"},{\"id\":\"40784\"}]},\"id\":\"40785\",\"type\":\"Toolbar\"},{\"attributes\":{},\"id\":\"40777\",\"type\":\"DataRange1d\"},{\"attributes\":{\"source\":{\"id\":\"40770\"}},\"id\":\"40790\",\"type\":\"CDSView\"},{\"attributes\":{\"coordinates\":null,\"group\":null},\"id\":\"40773\",\"type\":\"Title\"},{\"attributes\":{\"args\":{\"div\":{\"id\":\"40791\"}},\"code\":\"\\n const attrs = [];\\n const args = [];\\n const line = \\\"\\\" + \\\"Basic resource information (metadata)

Category: Data source, Repository
Name: Zenodo
URL: ['https://zenodo.org/']
Other names ['Zenodo', 'Research. Shared']
Description: ZENODO builds and operates a simple and innovative service that enables researchers, scientists, EU projects and institutions to share and showcase multidisciplinary research results (data and publications) that are not part of the existing institutional or subject-based repositories of the research communities.
ZENODO enables researchers, scientists, EU projects and institutions to:
easily share the long tail of small research results in a wide variety of formats including text, spreadsheets, audio, video, and images across all fields of science.
display their research results and get credited by making the research results citable and integrate them into existing reporting lines to funding agencies like the European Commission.
easily access and reuse shared research results.
Keywords: ['FAIR', 'multidisciplinary', '1 Humanities and Social Sciences', '2 Life Sciences', '3 Natural Sciences', '4 Engineering Sciences']
\\\" + \\\"
(\\\" + args.join(\\\", \\\") + \\\")
\\\\n\\\";\\n const text = line;\\n const lines = text.split(\\\"\\\\n\\\")\\n if (lines.length > 35)\\n lines.shift();\\n div.text = lines.join(\\\"\\\\n\\\");\\n \"},\"id\":\"40796\",\"type\":\"CustomJS\"},{\"attributes\":{\"angle\":{\"field\":\"angle\",\"units\":\"deg\"},\"text_color\":{\"field\":\"color\"},\"text_font\":{\"value\":\"'Droid Sans Mono'\"},\"text_font_size\":{\"field\":\"font_size\"},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"40788\",\"type\":\"Text\"},{\"attributes\":{},\"id\":\"40779\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"40770\"},\"glyph\":{\"id\":\"40788\"},\"group\":null,\"hover_glyph\":null,\"view\":{\"id\":\"40790\"}},\"id\":\"40789\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"args\":{\"div\":{\"id\":\"40791\"}},\"code\":\"\\n const attrs = [];\\n const args = [];\\n const line = \\\"\\\" + \\\"Basic resource information (metadata)

Category: Data source, Repository
Name: Zenodo
URL: ['https://zenodo.org/']
Other names ['Zenodo', 'Research. Shared']
Description: ZENODO builds and operates a simple and innovative service that enables researchers, scientists, EU projects and institutions to share and showcase multidisciplinary research results (data and publications) that are not part of the existing institutional or subject-based repositories of the research communities.
ZENODO enables researchers, scientists, EU projects and institutions to:
easily share the long tail of small research results in a wide variety of formats including text, spreadsheets, audio, video, and images across all fields of science.
display their research results and get credited by making the research results citable and integrate them into existing reporting lines to funding agencies like the European Commission.
easily access and reuse shared research results.
Keywords: ['FAIR', 'multidisciplinary', '1 Humanities and Social Sciences', '2 Life Sciences', '3 Natural Sciences', '4 Engineering Sciences']
\\\" + \\\"
(\\\" + args.join(\\\", \\\") + \\\")
\\\\n\\\";\\n const text = line;\\n const lines = text.split(\\\"\\\\n\\\")\\n if (lines.length > 35)\\n lines.shift();\\n div.text = lines.join(\\\"\\\\n\\\");\\n \"},\"id\":\"40795\",\"type\":\"CustomJS\"},{\"attributes\":{\"callback\":null},\"id\":\"40784\",\"type\":\"TapTool\"},{\"attributes\":{\"args\":{\"div\":{\"id\":\"40791\"}},\"code\":\"\\n const attrs = [];\\n const args = [];\\n const line = \\\"\\\" + \\\"Basic resource information (metadata)

Category: Data source, Repository
Name: Zenodo
URL: ['https://zenodo.org/']
Other names ['Zenodo', 'Research. Shared']
Description: ZENODO builds and operates a simple and innovative service that enables researchers, scientists, EU projects and institutions to share and showcase multidisciplinary research results (data and publications) that are not part of the existing institutional or subject-based repositories of the research communities.
ZENODO enables researchers, scientists, EU projects and institutions to:
easily share the long tail of small research results in a wide variety of formats including text, spreadsheets, audio, video, and images across all fields of science.
display their research results and get credited by making the research results citable and integrate them into existing reporting lines to funding agencies like the European Commission.
easily access and reuse shared research results.
Keywords: ['FAIR', 'multidisciplinary', '1 Humanities and Social Sciences', '2 Life Sciences', '3 Natural Sciences', '4 Engineering Sciences']
\\\" + \\\"
(\\\" + args.join(\\\", \\\") + \\\")
\\\\n\\\";\\n const text = line;\\n const lines = text.split(\\\"\\\\n\\\")\\n if (lines.length > 35)\\n lines.shift();\\n div.text = lines.join(\\\"\\\\n\\\");\\n \"},\"id\":\"40794\",\"type\":\"CustomJS\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"\",\"@text\"]]},\"id\":\"40783\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"41278\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"41279\",\"type\":\"Selection\"},{\"attributes\":{\"height\":500,\"js_event_callbacks\":{\"doubletap\":[{\"id\":\"40795\"}],\"press\":[{\"id\":\"40796\"}],\"tap\":[{\"id\":\"40794\"}]},\"outline_line_color\":null,\"renderers\":[{\"id\":\"40789\"}],\"title\":{\"id\":\"40773\"},\"toolbar\":{\"id\":\"40785\"},\"toolbar_location\":null,\"width\":800,\"x_range\":{\"id\":\"40775\"},\"x_scale\":{\"id\":\"40779\"},\"y_range\":{\"id\":\"40777\"},\"y_scale\":{\"id\":\"40781\"}},\"id\":\"40772\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{},\"id\":\"40781\",\"type\":\"LinearScale\"}],\"root_ids\":[\"40793\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n", - " const render_items = [{\"docid\":\"228fbc7c-d827-46ec-a478-9626c245777d\",\"root_ids\":[\"40793\"],\"roots\":{\"40793\":\"93d8cc67-8532-4a7a-b785-97364e58ab0b\"}}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"228fbc7c-d827-46ec-a478-9626c245777d\":{\"defs\":[{\"extends\":null,\"module\":null,\"name\":\"ReactiveHTML1\",\"overrides\":[],\"properties\":[]},{\"extends\":null,\"module\":null,\"name\":\"FlexBox1\",\"overrides\":[],\"properties\":[{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_content\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_items\"},{\"default\":\"row\",\"kind\":null,\"name\":\"flex_direction\"},{\"default\":\"wrap\",\"kind\":null,\"name\":\"flex_wrap\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"justify_content\"}]},{\"extends\":null,\"module\":null,\"name\":\"GridStack1\",\"overrides\":[],\"properties\":[{\"default\":\"warn\",\"kind\":null,\"name\":\"mode\"},{\"default\":null,\"kind\":null,\"name\":\"ncols\"},{\"default\":null,\"kind\":null,\"name\":\"nrows\"},{\"default\":true,\"kind\":null,\"name\":\"allow_resize\"},{\"default\":true,\"kind\":null,\"name\":\"allow_drag\"},{\"default\":[],\"kind\":null,\"name\":\"state\"}]},{\"extends\":null,\"module\":null,\"name\":\"click1\",\"overrides\":[],\"properties\":[{\"default\":\"\",\"kind\":null,\"name\":\"terminal_output\"},{\"default\":\"\",\"kind\":null,\"name\":\"debug_name\"},{\"default\":0,\"kind\":null,\"name\":\"clears\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationAreaBase1\",\"overrides\":[],\"properties\":[{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationArea1\",\"overrides\":[],\"properties\":[{\"default\":[],\"kind\":null,\"name\":\"notifications\"},{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"},{\"default\":[{\"background\":\"#ffc107\",\"icon\":{\"className\":\"fas fa-exclamation-triangle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"warning\"},{\"background\":\"#007bff\",\"icon\":{\"className\":\"fas fa-info-circle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"info\"}],\"kind\":null,\"name\":\"types\"}]},{\"extends\":null,\"module\":null,\"name\":\"Notification\",\"overrides\":[],\"properties\":[{\"default\":null,\"kind\":null,\"name\":\"background\"},{\"default\":3000,\"kind\":null,\"name\":\"duration\"},{\"default\":null,\"kind\":null,\"name\":\"icon\"},{\"default\":\"\",\"kind\":null,\"name\":\"message\"},{\"default\":null,\"kind\":null,\"name\":\"notification_type\"},{\"default\":false,\"kind\":null,\"name\":\"_destroyed\"}]},{\"extends\":null,\"module\":null,\"name\":\"TemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]},{\"extends\":null,\"module\":null,\"name\":\"MaterialTemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]}],\"roots\":{\"references\":[{\"attributes\":{\"children\":[{\"id\":\"40792\"}]},\"id\":\"40793\",\"type\":\"Column\"},{\"attributes\":{},\"id\":\"40775\",\"type\":\"DataRange1d\"},{\"attributes\":{\"height\":500,\"height_policy\":\"fixed\",\"text\":\"
Click on a word to reveal more information about it.

\",\"width\":400},\"id\":\"40791\",\"type\":\"Div\"},{\"attributes\":{\"children\":[{\"id\":\"40772\"},{\"id\":\"40791\"}]},\"id\":\"40792\",\"type\":\"Row\"},{\"attributes\":{\"data\":{\"angle\":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,90,0.0,90,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],\"color\":[\"rgb(186, 222, 40)\",\"rgb(61, 78, 138)\",\"rgb(210, 226, 27)\",\"rgb(223, 227, 24)\",\"rgb(108, 205, 90)\",\"rgb(69, 4, 87)\",\"rgb(71, 16, 99)\",\"rgb(70, 50, 126)\",\"rgb(112, 207, 87)\",\"rgb(216, 226, 25)\",\"rgb(49, 103, 142)\",\"rgb(71, 17, 100)\",\"rgb(236, 229, 27)\",\"rgb(82, 197, 105)\",\"rgb(61, 78, 138)\",\"rgb(55, 91, 141)\",\"rgb(57, 86, 140)\",\"rgb(213, 226, 26)\",\"rgb(69, 55, 129)\",\"rgb(62, 74, 137)\",\"rgb(74, 193, 109)\",\"rgb(69, 53, 129)\",\"rgb(253, 231, 37)\",\"rgb(101, 203, 94)\",\"rgb(65, 66, 135)\",\"rgb(71, 13, 96)\",\"rgb(221, 227, 24)\",\"rgb(72, 20, 103)\",\"rgb(124, 210, 80)\",\"rgb(46, 179, 124)\",\"rgb(42, 119, 142)\",\"rgb(165, 219, 54)\",\"rgb(200, 224, 32)\",\"rgb(110, 206, 88)\"],\"count\":[1.0,0.6304347826086957,0.34782608695652173,0.15217391304347827,0.08695652173913043,0.08695652173913043,0.06521739130434782,0.06521739130434782,0.06521739130434782,0.06521739130434782,0.043478260869565216,0.043478260869565216,0.043478260869565216,0.043478260869565216,0.043478260869565216,0.043478260869565216,0.043478260869565216,0.043478260869565216,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608,0.021739130434782608],\"font_size\":[\"50px\",\"41px\",\"32px\",\"23px\",\"18px\",\"18px\",\"16px\",\"16px\",\"16px\",\"16px\",\"13px\",\"13px\",\"13px\",\"13px\",\"13px\",\"13px\",\"13px\",\"13px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\",\"10px\"],\"hover_color\":[\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\"],\"hover_font_size\":[\"55px\",\"46px\",\"37px\",\"28px\",\"23px\",\"23px\",\"21px\",\"21px\",\"21px\",\"21px\",\"18px\",\"18px\",\"18px\",\"18px\",\"18px\",\"18px\",\"18px\",\"18px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\"],\"text\":[\"Institutional Repository\",\"Zenodo\",\"Gitlab GitHub\",\"GEO\",\"WDCC\",\"PANGAEA\",\"OSF\",\"Open\",\"ENA\",\"RCSB PDB\",\"Materials\",\"Cloud\",\"ProteomeXchange\",\"figshare\",\"Copernicus\",\"Access\",\"Hub\",\"EGA\",\"Energy\",\"Platform\",\"FIZ\",\"Karlsruhe\",\"FAIRDOMHub\",\"CDDIS\",\"GLIMS\",\"DataONE\",\"ArrayExpress\",\"BMRB\",\"EudraCT\",\"PUBLISSO\",\"IMPC\",\"OpenOrganelle\",\"IRRMC\",\"HEPData\"],\"x\":[4,21,215,349,679,153,731,237,533,535,146,39,541,160,360,133,597,674,683,85,440,730,588,685,53,284,509,213,417,362,22,478,307,232],\"y\":[-134,-481,-438,-196,-324,-284,-26,-150,-274,-495,-162,-446,-61,-55,-161,-20,-318,-457,-285,-316,-58,-249,-379,-175,-397,-90,-351,-367,-472,-71,-275,-186,-270,-324]},\"selected\":{\"id\":\"41279\"},\"selection_policy\":{\"id\":\"41278\"}},\"id\":\"40770\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"tools\":[{\"id\":\"40783\"},{\"id\":\"40784\"}]},\"id\":\"40785\",\"type\":\"Toolbar\"},{\"attributes\":{},\"id\":\"40777\",\"type\":\"DataRange1d\"},{\"attributes\":{\"source\":{\"id\":\"40770\"}},\"id\":\"40790\",\"type\":\"CDSView\"},{\"attributes\":{\"coordinates\":null,\"group\":null},\"id\":\"40773\",\"type\":\"Title\"},{\"attributes\":{\"args\":{\"div\":{\"id\":\"40791\"}},\"code\":\"\\n const attrs = [];\\n const args = [];\\n const line = \\\"\\\" + \\\"Basic resource information (metadata)

Category: Data source, Repository
Name: Zenodo
URL: ['https://zenodo.org/']
Other names ['Zenodo', 'Research. Shared']
Description: ZENODO builds and operates a simple and innovative service that enables researchers, scientists, EU projects and institutions to share and showcase multidisciplinary research results (data and publications) that are not part of the existing institutional or subject-based repositories of the research communities.
ZENODO enables researchers, scientists, EU projects and institutions to:
easily share the long tail of small research results in a wide variety of formats including text, spreadsheets, audio, video, and images across all fields of science.
display their research results and get credited by making the research results citable and integrate them into existing reporting lines to funding agencies like the European Commission.
easily access and reuse shared research results.
Keywords: ['FAIR', 'multidisciplinary', '1 Humanities and Social Sciences', '2 Life Sciences', '3 Natural Sciences', '4 Engineering Sciences']
\\\" + \\\"
(\\\" + args.join(\\\", \\\") + \\\")
\\\\n\\\";\\n const text = line;\\n const lines = text.split(\\\"\\\\n\\\")\\n if (lines.length > 35)\\n lines.shift();\\n div.text = lines.join(\\\"\\\\n\\\");\\n \"},\"id\":\"40796\",\"type\":\"CustomJS\"},{\"attributes\":{\"angle\":{\"field\":\"angle\",\"units\":\"deg\"},\"text_color\":{\"field\":\"color\"},\"text_font\":{\"value\":\"'Droid Sans Mono'\"},\"text_font_size\":{\"field\":\"font_size\"},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"40788\",\"type\":\"Text\"},{\"attributes\":{},\"id\":\"40779\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"40770\"},\"glyph\":{\"id\":\"40788\"},\"group\":null,\"hover_glyph\":null,\"view\":{\"id\":\"40790\"}},\"id\":\"40789\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"args\":{\"div\":{\"id\":\"40791\"}},\"code\":\"\\n const attrs = [];\\n const args = [];\\n const line = \\\"\\\" + \\\"Basic resource information (metadata)

Category: Data source, Repository
Name: Zenodo
URL: ['https://zenodo.org/']
Other names ['Zenodo', 'Research. Shared']
Description: ZENODO builds and operates a simple and innovative service that enables researchers, scientists, EU projects and institutions to share and showcase multidisciplinary research results (data and publications) that are not part of the existing institutional or subject-based repositories of the research communities.
ZENODO enables researchers, scientists, EU projects and institutions to:
easily share the long tail of small research results in a wide variety of formats including text, spreadsheets, audio, video, and images across all fields of science.
display their research results and get credited by making the research results citable and integrate them into existing reporting lines to funding agencies like the European Commission.
easily access and reuse shared research results.
Keywords: ['FAIR', 'multidisciplinary', '1 Humanities and Social Sciences', '2 Life Sciences', '3 Natural Sciences', '4 Engineering Sciences']
\\\" + \\\"
(\\\" + args.join(\\\", \\\") + \\\")
\\\\n\\\";\\n const text = line;\\n const lines = text.split(\\\"\\\\n\\\")\\n if (lines.length > 35)\\n lines.shift();\\n div.text = lines.join(\\\"\\\\n\\\");\\n \"},\"id\":\"40795\",\"type\":\"CustomJS\"},{\"attributes\":{\"callback\":null},\"id\":\"40784\",\"type\":\"TapTool\"},{\"attributes\":{\"args\":{\"div\":{\"id\":\"40791\"}},\"code\":\"\\n const attrs = [];\\n const args = [];\\n const line = \\\"\\\" + \\\"Basic resource information (metadata)

Category: Data source, Repository
Name: Zenodo
URL: ['https://zenodo.org/']
Other names ['Zenodo', 'Research. Shared']
Description: ZENODO builds and operates a simple and innovative service that enables researchers, scientists, EU projects and institutions to share and showcase multidisciplinary research results (data and publications) that are not part of the existing institutional or subject-based repositories of the research communities.
ZENODO enables researchers, scientists, EU projects and institutions to:
easily share the long tail of small research results in a wide variety of formats including text, spreadsheets, audio, video, and images across all fields of science.
display their research results and get credited by making the research results citable and integrate them into existing reporting lines to funding agencies like the European Commission.
easily access and reuse shared research results.
Keywords: ['FAIR', 'multidisciplinary', '1 Humanities and Social Sciences', '2 Life Sciences', '3 Natural Sciences', '4 Engineering Sciences']
\\\" + \\\"
(\\\" + args.join(\\\", \\\") + \\\")
\\\\n\\\";\\n const text = line;\\n const lines = text.split(\\\"\\\\n\\\")\\n if (lines.length > 35)\\n lines.shift();\\n div.text = lines.join(\\\"\\\\n\\\");\\n \"},\"id\":\"40794\",\"type\":\"CustomJS\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"\",\"@text\"]]},\"id\":\"40783\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"41278\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"41279\",\"type\":\"Selection\"},{\"attributes\":{\"height\":500,\"js_event_callbacks\":{\"doubletap\":[{\"id\":\"40795\"}],\"press\":[{\"id\":\"40796\"}],\"tap\":[{\"id\":\"40794\"}]},\"outline_line_color\":null,\"renderers\":[{\"id\":\"40789\"}],\"title\":{\"id\":\"40773\"},\"toolbar\":{\"id\":\"40785\"},\"toolbar_location\":null,\"width\":800,\"x_range\":{\"id\":\"40775\"},\"x_scale\":{\"id\":\"40779\"},\"y_range\":{\"id\":\"40777\"},\"y_scale\":{\"id\":\"40781\"}},\"id\":\"40772\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{},\"id\":\"40781\",\"type\":\"LinearScale\"}],\"root_ids\":[\"40793\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n const render_items = [{\"docid\":\"228fbc7c-d827-46ec-a478-9626c245777d\",\"root_ids\":[\"40793\"],\"roots\":{\"40793\":\"93d8cc67-8532-4a7a-b785-97364e58ab0b\"}}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -3622,32 +2423,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"de95f4dc-aa68-44ac-853e-0cecaa3bc511\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"height\":500,\"outline_line_color\":null,\"renderers\":[{\"id\":\"18027\"}],\"title\":{\"id\":\"18011\"},\"toolbar\":{\"id\":\"18023\"},\"toolbar_location\":null,\"width\":800,\"x_range\":{\"id\":\"18013\"},\"x_scale\":{\"id\":\"18017\"},\"y_range\":{\"id\":\"18015\"},\"y_scale\":{\"id\":\"18019\"}},\"id\":\"18010\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"Word\",\"@text\"],[\"Count\",\"@count\"]]},\"id\":\"18021\",\"type\":\"HoverTool\"},{\"attributes\":{\"coordinates\":null,\"group\":null},\"id\":\"18011\",\"type\":\"Title\"},{\"attributes\":{\"tools\":[{\"id\":\"18021\"},{\"id\":\"18022\"}]},\"id\":\"18023\",\"type\":\"Toolbar\"},{\"attributes\":{},\"id\":\"18013\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"18015\",\"type\":\"DataRange1d\"},{\"attributes\":{\"data\":{\"angle\":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],\"color\":[\"rgb(115, 208, 86)\",\"rgb(74, 193, 109)\",\"rgb(40, 124, 142)\",\"rgb(112, 207, 87)\",\"rgb(30, 157, 137)\",\"rgb(127, 211, 78)\",\"rgb(58, 83, 139)\",\"rgb(45, 113, 142)\",\"rgb(68, 58, 131)\",\"rgb(63, 188, 115)\",\"rgb(71, 19, 101)\",\"rgb(52, 97, 141)\",\"rgb(72, 32, 113)\",\"rgb(202, 225, 31)\",\"rgb(70, 8, 92)\",\"rgb(45, 112, 142)\",\"rgb(71, 45, 123)\",\"rgb(144, 215, 67)\",\"rgb(84, 197, 104)\",\"rgb(105, 205, 91)\",\"rgb(43, 117, 142)\",\"rgb(31, 148, 140)\",\"rgb(218, 227, 25)\",\"rgb(72, 38, 119)\",\"rgb(46, 110, 142)\",\"rgb(70, 192, 111)\",\"rgb(78, 195, 107)\",\"rgb(137, 213, 72)\",\"rgb(69, 4, 87)\",\"rgb(60, 79, 138)\",\"rgb(48, 106, 142)\",\"rgb(139, 214, 70)\",\"rgb(68, 2, 86)\",\"rgb(236, 229, 27)\",\"rgb(251, 231, 35)\",\"rgb(38, 130, 142)\",\"rgb(71, 47, 125)\",\"rgb(35, 137, 142)\",\"rgb(61, 188, 116)\",\"rgb(47, 108, 142)\",\"rgb(32, 163, 134)\",\"rgb(253, 231, 37)\",\"rgb(34, 141, 141)\",\"rgb(72, 35, 116)\",\"rgb(72, 41, 121)\",\"rgb(50, 101, 142)\",\"rgb(37, 172, 130)\",\"rgb(71, 16, 99)\",\"rgb(38, 173, 129)\",\"rgb(41, 121, 142)\",\"rgb(192, 223, 37)\",\"rgb(47, 108, 142)\",\"rgb(44, 115, 142)\",\"rgb(43, 116, 142)\",\"rgb(68, 59, 132)\",\"rgb(56, 88, 140)\",\"rgb(49, 103, 142)\",\"rgb(33, 143, 141)\",\"rgb(72, 33, 115)\",\"rgb(40, 124, 142)\",\"rgb(37, 133, 142)\",\"rgb(72, 41, 121)\",\"rgb(44, 114, 142)\",\"rgb(76, 194, 108)\",\"rgb(112, 207, 87)\",\"rgb(142, 214, 69)\",\"rgb(68, 2, 86)\",\"rgb(31, 161, 135)\",\"rgb(56, 89, 140)\",\"rgb(234, 229, 26)\",\"rgb(36, 135, 142)\",\"rgb(33, 166, 133)\",\"rgb(37, 131, 142)\",\"rgb(69, 53, 129)\",\"rgb(36, 134, 142)\",\"rgb(47, 107, 142)\",\"rgb(70, 10, 93)\",\"rgb(66, 190, 113)\",\"rgb(42, 118, 142)\",\"rgb(67, 62, 133)\",\"rgb(58, 83, 139)\",\"rgb(64, 69, 136)\",\"rgb(71, 19, 101)\",\"rgb(30, 155, 138)\",\"rgb(34, 140, 141)\",\"rgb(72, 29, 111)\",\"rgb(55, 90, 140)\",\"rgb(216, 226, 25)\",\"rgb(53, 183, 121)\",\"rgb(41, 122, 142)\",\"rgb(34, 167, 133)\",\"rgb(71, 45, 123)\",\"rgb(33, 145, 140)\",\"rgb(51, 99, 141)\",\"rgb(52, 97, 141)\",\"rgb(70, 51, 127)\",\"rgb(119, 209, 83)\",\"rgb(173, 220, 48)\",\"rgb(72, 193, 110)\",\"rgb(38, 129, 142)\"],\"count\":[1.0,0.9333333333333333,0.5333333333333333,0.4666666666666667,0.4,0.26666666666666666,0.26666666666666666,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667],\"font_size\":[\"50px\",\"48px\",\"38px\",\"36px\",\"33px\",\"27px\",\"27px\",\"24px\",\"24px\",\"24px\",\"24px\",\"24px\",\"24px\",\"24px\",\"24px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\"],\"hover_color\":[\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\"],\"hover_font_size\":[\"55px\",\"53px\",\"43px\",\"41px\",\"38px\",\"32px\",\"32px\",\"29px\",\"29px\",\"29px\",\"29px\",\"29px\",\"29px\",\"29px\",\"29px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\"],\"text\":[\"Spektroskopie\",\"sequencing\",\"spectroscopy\",\"MS\",\"Mass Spectrometry\",\"DNA\",\"Scattering\",\"HPLC\",\"RNA\",\"ICP\",\"von\",\"Neutron\",\"Next Generation\",\"UV Vis\",\"pump probe\",\"analytical\",\"model\",\"IR\",\"data\",\"XRD\",\"methods\",\"ELISA\",\"High\",\"Lumineszenz\",\"Analysen\",\"Genomic\",\"Optical\",\"single\",\"cell\",\"NMR\",\"Ion\",\"Small\",\"Photoelektronenspektroskopie\",\"R\\u00f6ntgenabsorptionsspektroskopie\",\"SAXS\",\"X\",\"ray\",\"R\\u00f6ntgenspektroskopie\",\"diffraction\",\"NEXAFS\",\"XPS\",\"Particle\",\"Software\",\"repository\",\"mining\",\"Aggregation\",\"Flow\",\"cytometry\",\"FPLC\",\"Spektrophotometrie\",\"numerous\",\"GC\",\"trace\",\"generated\",\"code\",\"R\\u00f6ntgenfluoreszenz\",\"Spektoskopie\",\"Preprocessing\",\"Remote\",\"sensing\",\"Spektralanalyse\",\"Dopplerspektrum\",\"HF\",\"radar\",\"Colorimetric\",\"MTT\",\"NIRS\",\"Lidar\",\"Enzymatic\",\"Assays\",\"determine\",\"enzyme\",\"activity\",\"sugar\",\"concentration\",\"Resolution\",\"Optimal\",\"estimation\",\"optische\",\"Messungen\",\"Absorption\",\"Fluoreszenz\",\"Massenspektrometrie\",\"Photometrie\",\"Massenspktrometrie\",\"throughput\",\"sequence\",\"Molekularbiologische\",\"Affinit\\u00e4tschromatographie\",\"PCR\",\"NGS\",\"S\\u00e4ulenchromatographie\",\"Genotyping\",\"Hochdurchsatz\",\"Screening\",\"Auslesen\",\"Illumina\",\"EPIC\",\"Methylation\",\"Array\"],\"x\":[13,437,344,414,242,101,199,729,286,590,563,2,556,573,329,123,272,152,329,699,85,713,224,98,188,30,18,42,169,469,475,226,442,284,666,625,26,179,7,713,169,46,162,106,261,662,54,641,640,532,168,24,50,56,166,592,384,382,735,425,213,411,605,149,266,766,466,669,387,622,167,127,74,47,676,482,264,549,572,673,166,231,375,671,387,538,560,415,85,731,356,499,565,92,9,176,714,584,477,394],\"y\":[-473,-112,-55,-274,-150,-51,-87,-230,-105,-314,-386,-206,-362,-201,-415,-183,-361,-110,-177,-141,-417,-33,-258,-396,-48,-72,-226,-337,-290,-311,-169,-200,-462,-237,-53,-164,-257,-319,-121,-201,-146,-301,-363,-207,-118,-286,-171,-313,-23,-331,-432,-154,-100,-149,-123,-421,-17,-382,-485,-184,-16,-484,-139,-347,-382,-88,-260,-241,-338,-125,-163,-253,-358,-392,-270,-438,-401,-13,-484,-160,-235,-294,-355,-69,-201,-262,-74,-289,-489,-321,-492,-400,-213,-18,-26,-414,-246,-443,-414,-89]},\"selected\":{\"id\":\"18377\"},\"selection_policy\":{\"id\":\"18376\"}},\"id\":\"18009\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"callback\":null},\"id\":\"18022\",\"type\":\"TapTool\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"18009\"},\"glyph\":{\"id\":\"18026\"},\"group\":null,\"hover_glyph\":null,\"view\":{\"id\":\"18028\"}},\"id\":\"18027\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"angle\":{\"field\":\"angle\",\"units\":\"deg\"},\"text_color\":{\"field\":\"color\"},\"text_font\":{\"value\":\"'Droid Sans Mono'\"},\"text_font_size\":{\"field\":\"font_size\"},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"18026\",\"type\":\"Text\"},{\"attributes\":{\"source\":{\"id\":\"18009\"}},\"id\":\"18028\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"18377\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"18376\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"18019\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"18017\",\"type\":\"LinearScale\"}],\"root_ids\":[\"18010\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n", - " const render_items = [{\"docid\":\"de95f4dc-aa68-44ac-853e-0cecaa3bc511\",\"root_ids\":[\"18010\"],\"roots\":{\"18010\":\"aea4df63-1b8f-4bf3-a54f-fb8b0777cfd3\"}}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"de95f4dc-aa68-44ac-853e-0cecaa3bc511\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"height\":500,\"outline_line_color\":null,\"renderers\":[{\"id\":\"18027\"}],\"title\":{\"id\":\"18011\"},\"toolbar\":{\"id\":\"18023\"},\"toolbar_location\":null,\"width\":800,\"x_range\":{\"id\":\"18013\"},\"x_scale\":{\"id\":\"18017\"},\"y_range\":{\"id\":\"18015\"},\"y_scale\":{\"id\":\"18019\"}},\"id\":\"18010\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"Word\",\"@text\"],[\"Count\",\"@count\"]]},\"id\":\"18021\",\"type\":\"HoverTool\"},{\"attributes\":{\"coordinates\":null,\"group\":null},\"id\":\"18011\",\"type\":\"Title\"},{\"attributes\":{\"tools\":[{\"id\":\"18021\"},{\"id\":\"18022\"}]},\"id\":\"18023\",\"type\":\"Toolbar\"},{\"attributes\":{},\"id\":\"18013\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"18015\",\"type\":\"DataRange1d\"},{\"attributes\":{\"data\":{\"angle\":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],\"color\":[\"rgb(115, 208, 86)\",\"rgb(74, 193, 109)\",\"rgb(40, 124, 142)\",\"rgb(112, 207, 87)\",\"rgb(30, 157, 137)\",\"rgb(127, 211, 78)\",\"rgb(58, 83, 139)\",\"rgb(45, 113, 142)\",\"rgb(68, 58, 131)\",\"rgb(63, 188, 115)\",\"rgb(71, 19, 101)\",\"rgb(52, 97, 141)\",\"rgb(72, 32, 113)\",\"rgb(202, 225, 31)\",\"rgb(70, 8, 92)\",\"rgb(45, 112, 142)\",\"rgb(71, 45, 123)\",\"rgb(144, 215, 67)\",\"rgb(84, 197, 104)\",\"rgb(105, 205, 91)\",\"rgb(43, 117, 142)\",\"rgb(31, 148, 140)\",\"rgb(218, 227, 25)\",\"rgb(72, 38, 119)\",\"rgb(46, 110, 142)\",\"rgb(70, 192, 111)\",\"rgb(78, 195, 107)\",\"rgb(137, 213, 72)\",\"rgb(69, 4, 87)\",\"rgb(60, 79, 138)\",\"rgb(48, 106, 142)\",\"rgb(139, 214, 70)\",\"rgb(68, 2, 86)\",\"rgb(236, 229, 27)\",\"rgb(251, 231, 35)\",\"rgb(38, 130, 142)\",\"rgb(71, 47, 125)\",\"rgb(35, 137, 142)\",\"rgb(61, 188, 116)\",\"rgb(47, 108, 142)\",\"rgb(32, 163, 134)\",\"rgb(253, 231, 37)\",\"rgb(34, 141, 141)\",\"rgb(72, 35, 116)\",\"rgb(72, 41, 121)\",\"rgb(50, 101, 142)\",\"rgb(37, 172, 130)\",\"rgb(71, 16, 99)\",\"rgb(38, 173, 129)\",\"rgb(41, 121, 142)\",\"rgb(192, 223, 37)\",\"rgb(47, 108, 142)\",\"rgb(44, 115, 142)\",\"rgb(43, 116, 142)\",\"rgb(68, 59, 132)\",\"rgb(56, 88, 140)\",\"rgb(49, 103, 142)\",\"rgb(33, 143, 141)\",\"rgb(72, 33, 115)\",\"rgb(40, 124, 142)\",\"rgb(37, 133, 142)\",\"rgb(72, 41, 121)\",\"rgb(44, 114, 142)\",\"rgb(76, 194, 108)\",\"rgb(112, 207, 87)\",\"rgb(142, 214, 69)\",\"rgb(68, 2, 86)\",\"rgb(31, 161, 135)\",\"rgb(56, 89, 140)\",\"rgb(234, 229, 26)\",\"rgb(36, 135, 142)\",\"rgb(33, 166, 133)\",\"rgb(37, 131, 142)\",\"rgb(69, 53, 129)\",\"rgb(36, 134, 142)\",\"rgb(47, 107, 142)\",\"rgb(70, 10, 93)\",\"rgb(66, 190, 113)\",\"rgb(42, 118, 142)\",\"rgb(67, 62, 133)\",\"rgb(58, 83, 139)\",\"rgb(64, 69, 136)\",\"rgb(71, 19, 101)\",\"rgb(30, 155, 138)\",\"rgb(34, 140, 141)\",\"rgb(72, 29, 111)\",\"rgb(55, 90, 140)\",\"rgb(216, 226, 25)\",\"rgb(53, 183, 121)\",\"rgb(41, 122, 142)\",\"rgb(34, 167, 133)\",\"rgb(71, 45, 123)\",\"rgb(33, 145, 140)\",\"rgb(51, 99, 141)\",\"rgb(52, 97, 141)\",\"rgb(70, 51, 127)\",\"rgb(119, 209, 83)\",\"rgb(173, 220, 48)\",\"rgb(72, 193, 110)\",\"rgb(38, 129, 142)\"],\"count\":[1.0,0.9333333333333333,0.5333333333333333,0.4666666666666667,0.4,0.26666666666666666,0.26666666666666666,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667,0.06666666666666667],\"font_size\":[\"50px\",\"48px\",\"38px\",\"36px\",\"33px\",\"27px\",\"27px\",\"24px\",\"24px\",\"24px\",\"24px\",\"24px\",\"24px\",\"24px\",\"24px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\",\"15px\"],\"hover_color\":[\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\",\"black\"],\"hover_font_size\":[\"55px\",\"53px\",\"43px\",\"41px\",\"38px\",\"32px\",\"32px\",\"29px\",\"29px\",\"29px\",\"29px\",\"29px\",\"29px\",\"29px\",\"29px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"25px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\",\"20px\"],\"text\":[\"Spektroskopie\",\"sequencing\",\"spectroscopy\",\"MS\",\"Mass Spectrometry\",\"DNA\",\"Scattering\",\"HPLC\",\"RNA\",\"ICP\",\"von\",\"Neutron\",\"Next Generation\",\"UV Vis\",\"pump probe\",\"analytical\",\"model\",\"IR\",\"data\",\"XRD\",\"methods\",\"ELISA\",\"High\",\"Lumineszenz\",\"Analysen\",\"Genomic\",\"Optical\",\"single\",\"cell\",\"NMR\",\"Ion\",\"Small\",\"Photoelektronenspektroskopie\",\"R\\u00f6ntgenabsorptionsspektroskopie\",\"SAXS\",\"X\",\"ray\",\"R\\u00f6ntgenspektroskopie\",\"diffraction\",\"NEXAFS\",\"XPS\",\"Particle\",\"Software\",\"repository\",\"mining\",\"Aggregation\",\"Flow\",\"cytometry\",\"FPLC\",\"Spektrophotometrie\",\"numerous\",\"GC\",\"trace\",\"generated\",\"code\",\"R\\u00f6ntgenfluoreszenz\",\"Spektoskopie\",\"Preprocessing\",\"Remote\",\"sensing\",\"Spektralanalyse\",\"Dopplerspektrum\",\"HF\",\"radar\",\"Colorimetric\",\"MTT\",\"NIRS\",\"Lidar\",\"Enzymatic\",\"Assays\",\"determine\",\"enzyme\",\"activity\",\"sugar\",\"concentration\",\"Resolution\",\"Optimal\",\"estimation\",\"optische\",\"Messungen\",\"Absorption\",\"Fluoreszenz\",\"Massenspektrometrie\",\"Photometrie\",\"Massenspktrometrie\",\"throughput\",\"sequence\",\"Molekularbiologische\",\"Affinit\\u00e4tschromatographie\",\"PCR\",\"NGS\",\"S\\u00e4ulenchromatographie\",\"Genotyping\",\"Hochdurchsatz\",\"Screening\",\"Auslesen\",\"Illumina\",\"EPIC\",\"Methylation\",\"Array\"],\"x\":[13,437,344,414,242,101,199,729,286,590,563,2,556,573,329,123,272,152,329,699,85,713,224,98,188,30,18,42,169,469,475,226,442,284,666,625,26,179,7,713,169,46,162,106,261,662,54,641,640,532,168,24,50,56,166,592,384,382,735,425,213,411,605,149,266,766,466,669,387,622,167,127,74,47,676,482,264,549,572,673,166,231,375,671,387,538,560,415,85,731,356,499,565,92,9,176,714,584,477,394],\"y\":[-473,-112,-55,-274,-150,-51,-87,-230,-105,-314,-386,-206,-362,-201,-415,-183,-361,-110,-177,-141,-417,-33,-258,-396,-48,-72,-226,-337,-290,-311,-169,-200,-462,-237,-53,-164,-257,-319,-121,-201,-146,-301,-363,-207,-118,-286,-171,-313,-23,-331,-432,-154,-100,-149,-123,-421,-17,-382,-485,-184,-16,-484,-139,-347,-382,-88,-260,-241,-338,-125,-163,-253,-358,-392,-270,-438,-401,-13,-484,-160,-235,-294,-355,-69,-201,-262,-74,-289,-489,-321,-492,-400,-213,-18,-26,-414,-246,-443,-414,-89]},\"selected\":{\"id\":\"18377\"},\"selection_policy\":{\"id\":\"18376\"}},\"id\":\"18009\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"callback\":null},\"id\":\"18022\",\"type\":\"TapTool\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"18009\"},\"glyph\":{\"id\":\"18026\"},\"group\":null,\"hover_glyph\":null,\"view\":{\"id\":\"18028\"}},\"id\":\"18027\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"angle\":{\"field\":\"angle\",\"units\":\"deg\"},\"text_color\":{\"field\":\"color\"},\"text_font\":{\"value\":\"'Droid Sans Mono'\"},\"text_font_size\":{\"field\":\"font_size\"},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"18026\",\"type\":\"Text\"},{\"attributes\":{\"source\":{\"id\":\"18009\"}},\"id\":\"18028\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"18377\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"18376\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"18019\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"18017\",\"type\":\"LinearScale\"}],\"root_ids\":[\"18010\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n const render_items = [{\"docid\":\"de95f4dc-aa68-44ac-853e-0cecaa3bc511\",\"root_ids\":[\"18010\"],\"roots\":{\"18010\":\"aea4df63-1b8f-4bf3-a54f-fb8b0777cfd3\"}}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -3671,7 +2447,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "
" ] @@ -5332,32 +4108,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"2224d443-8f0e-4b7c-8bb6-d33a991e0067\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"10214\"}],\"center\":[{\"id\":\"10217\"},{\"id\":\"10221\"}],\"height\":300,\"left\":[{\"id\":\"10218\"}],\"renderers\":[{\"id\":\"10228\"}],\"title\":{\"id\":\"10204\"},\"toolbar\":{\"id\":\"10224\"},\"toolbar_location\":\"above\",\"width\":300,\"x_range\":{\"id\":\"10206\"},\"x_scale\":{\"id\":\"10210\"},\"y_range\":{\"id\":\"10208\"},\"y_scale\":{\"id\":\"10212\"}},\"id\":\"10203\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{},\"id\":\"10489\",\"type\":\"AllLabels\"},{\"attributes\":{\"source\":{\"id\":\"10202\"}},\"id\":\"10229\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"10490\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"data\":{\"text\":[\"abc\",\"def\",\"ghi\",\"jkl\",\"mno\",\"pqr\",\"stu\",\"vwx\",\"yz\"],\"x\":{\"__ndarray__\":\"AAAAAAAAAMAAAAAAAAD4vwAAAAAAAPC/AAAAAAAA4L8AAAAAAAAAAAAAAAAAAOA/AAAAAAAA8D8AAAAAAAD4PwAAAAAAAABA\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[9]},\"y\":{\"__ndarray__\":\"AAAAAAAAEEAAAAAAAAACQAAAAAAAAPA/AAAAAAAA0D8AAAAAAAAAAAAAAAAAANA/AAAAAAAA8D8AAAAAAAACQAAAAAAAABBA\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[9]}},\"selected\":{\"id\":\"10491\"},\"selection_policy\":{\"id\":\"10490\"}},\"id\":\"10202\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"10223\",\"type\":\"SaveTool\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"10488\"},\"group\":null,\"major_label_policy\":{\"id\":\"10489\"},\"ticker\":{\"id\":\"10215\"}},\"id\":\"10214\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"10491\",\"type\":\"Selection\"},{\"attributes\":{\"angle\":{\"units\":\"deg\",\"value\":90},\"text_color\":{\"value\":\"#96deb3\"},\"text_font_size\":{\"value\":\"40px\"},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"10227\",\"type\":\"Text\"},{\"attributes\":{},\"id\":\"10206\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"10210\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"text\":\"Da\"},\"id\":\"10204\",\"type\":\"Title\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"10485\"},\"group\":null,\"major_label_policy\":{\"id\":\"10486\"},\"ticker\":{\"id\":\"10219\"}},\"id\":\"10218\",\"type\":\"LinearAxis\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10202\"},\"glyph\":{\"id\":\"10227\"},\"group\":null,\"hover_glyph\":null,\"view\":{\"id\":\"10229\"}},\"id\":\"10228\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"10215\",\"type\":\"BasicTicker\"},{\"attributes\":{\"axis\":{\"id\":\"10214\"},\"coordinates\":null,\"group\":null,\"ticker\":null},\"id\":\"10217\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"10212\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"10208\",\"type\":\"DataRange1d\"},{\"attributes\":{\"callback\":null},\"id\":\"10222\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"10485\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"axis\":{\"id\":\"10218\"},\"coordinates\":null,\"dimension\":1,\"group\":null,\"ticker\":null},\"id\":\"10221\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"10219\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"10486\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"10488\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"tools\":[{\"id\":\"10222\"},{\"id\":\"10223\"}]},\"id\":\"10224\",\"type\":\"Toolbar\"}],\"root_ids\":[\"10203\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n", - " const render_items = [{\"docid\":\"2224d443-8f0e-4b7c-8bb6-d33a991e0067\",\"root_ids\":[\"10203\"],\"roots\":{\"10203\":\"6c172116-99b3-4f36-9553-9ea1ce6f6831\"}}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"2224d443-8f0e-4b7c-8bb6-d33a991e0067\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"10214\"}],\"center\":[{\"id\":\"10217\"},{\"id\":\"10221\"}],\"height\":300,\"left\":[{\"id\":\"10218\"}],\"renderers\":[{\"id\":\"10228\"}],\"title\":{\"id\":\"10204\"},\"toolbar\":{\"id\":\"10224\"},\"toolbar_location\":\"above\",\"width\":300,\"x_range\":{\"id\":\"10206\"},\"x_scale\":{\"id\":\"10210\"},\"y_range\":{\"id\":\"10208\"},\"y_scale\":{\"id\":\"10212\"}},\"id\":\"10203\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{},\"id\":\"10489\",\"type\":\"AllLabels\"},{\"attributes\":{\"source\":{\"id\":\"10202\"}},\"id\":\"10229\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"10490\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"data\":{\"text\":[\"abc\",\"def\",\"ghi\",\"jkl\",\"mno\",\"pqr\",\"stu\",\"vwx\",\"yz\"],\"x\":{\"__ndarray__\":\"AAAAAAAAAMAAAAAAAAD4vwAAAAAAAPC/AAAAAAAA4L8AAAAAAAAAAAAAAAAAAOA/AAAAAAAA8D8AAAAAAAD4PwAAAAAAAABA\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[9]},\"y\":{\"__ndarray__\":\"AAAAAAAAEEAAAAAAAAACQAAAAAAAAPA/AAAAAAAA0D8AAAAAAAAAAAAAAAAAANA/AAAAAAAA8D8AAAAAAAACQAAAAAAAABBA\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[9]}},\"selected\":{\"id\":\"10491\"},\"selection_policy\":{\"id\":\"10490\"}},\"id\":\"10202\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"10223\",\"type\":\"SaveTool\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"10488\"},\"group\":null,\"major_label_policy\":{\"id\":\"10489\"},\"ticker\":{\"id\":\"10215\"}},\"id\":\"10214\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"10491\",\"type\":\"Selection\"},{\"attributes\":{\"angle\":{\"units\":\"deg\",\"value\":90},\"text_color\":{\"value\":\"#96deb3\"},\"text_font_size\":{\"value\":\"40px\"},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"10227\",\"type\":\"Text\"},{\"attributes\":{},\"id\":\"10206\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"10210\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"text\":\"Da\"},\"id\":\"10204\",\"type\":\"Title\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"10485\"},\"group\":null,\"major_label_policy\":{\"id\":\"10486\"},\"ticker\":{\"id\":\"10219\"}},\"id\":\"10218\",\"type\":\"LinearAxis\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10202\"},\"glyph\":{\"id\":\"10227\"},\"group\":null,\"hover_glyph\":null,\"view\":{\"id\":\"10229\"}},\"id\":\"10228\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"10215\",\"type\":\"BasicTicker\"},{\"attributes\":{\"axis\":{\"id\":\"10214\"},\"coordinates\":null,\"group\":null,\"ticker\":null},\"id\":\"10217\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"10212\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"10208\",\"type\":\"DataRange1d\"},{\"attributes\":{\"callback\":null},\"id\":\"10222\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"10485\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"axis\":{\"id\":\"10218\"},\"coordinates\":null,\"dimension\":1,\"group\":null,\"ticker\":null},\"id\":\"10221\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"10219\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"10486\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"10488\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"tools\":[{\"id\":\"10222\"},{\"id\":\"10223\"}]},\"id\":\"10224\",\"type\":\"Toolbar\"}],\"root_ids\":[\"10203\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n const render_items = [{\"docid\":\"2224d443-8f0e-4b7c-8bb6-d33a991e0067\",\"root_ids\":[\"10203\"],\"roots\":{\"10203\":\"6c172116-99b3-4f36-9553-9ea1ce6f6831\"}}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -5417,32 +4168,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"9b2a95aa-35f3-4b0f-b949-fa91167fcbbb\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"11914\"}],\"center\":[{\"id\":\"11917\"},{\"id\":\"11921\"}],\"height\":300,\"left\":[{\"id\":\"11918\"}],\"renderers\":[{\"id\":\"11928\"}],\"title\":{\"id\":\"11904\"},\"toolbar\":{\"id\":\"11924\"},\"toolbar_location\":\"above\",\"width\":300,\"x_range\":{\"id\":\"11906\"},\"x_scale\":{\"id\":\"11910\"},\"y_range\":{\"id\":\"11908\"},\"y_scale\":{\"id\":\"11912\"}},\"id\":\"11903\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{},\"id\":\"12222\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"12224\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"12225\",\"type\":\"AllLabels\"},{\"attributes\":{\"axis\":{\"id\":\"11918\"},\"coordinates\":null,\"dimension\":1,\"group\":null,\"ticker\":null},\"id\":\"11921\",\"type\":\"Grid\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"12224\"},\"group\":null,\"major_label_policy\":{\"id\":\"12225\"},\"ticker\":{\"id\":\"11915\"}},\"id\":\"11914\",\"type\":\"LinearAxis\"},{\"attributes\":{\"tools\":[{\"id\":\"11922\"},{\"id\":\"11923\"}]},\"id\":\"11924\",\"type\":\"Toolbar\"},{\"attributes\":{},\"id\":\"10490\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"data\":{\"text\":[\"abc\",\"def\",\"ghi\",\"jkl\",\"mno\",\"pqr\",\"stu\",\"vwx\",\"yz\"],\"x\":{\"__ndarray__\":\"AAAAAAAAAMAAAAAAAAD4vwAAAAAAAPC/AAAAAAAA4L8AAAAAAAAAAAAAAAAAAOA/AAAAAAAA8D8AAAAAAAD4PwAAAAAAAABA\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[9]},\"y\":{\"__ndarray__\":\"AAAAAAAAEEAAAAAAAAACQAAAAAAAAPA/AAAAAAAA0D8AAAAAAAAAAAAAAAAAANA/AAAAAAAA8D8AAAAAAAACQAAAAAAAABBA\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[9]}},\"selected\":{\"id\":\"10491\"},\"selection_policy\":{\"id\":\"10490\"}},\"id\":\"10202\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"10491\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"11919\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"11915\",\"type\":\"BasicTicker\"},{\"attributes\":{\"angle\":{\"units\":\"deg\",\"value\":90},\"text_color\":{\"value\":\"#96deb3\"},\"text_font\":{\"value\":\"Droid Sans Mono\"},\"text_font_size\":{\"value\":\"40px\"},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"11927\",\"type\":\"Text\"},{\"attributes\":{},\"id\":\"11912\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10202\"},\"glyph\":{\"id\":\"11927\"},\"group\":null,\"hover_glyph\":null,\"view\":{\"id\":\"11929\"}},\"id\":\"11928\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"source\":{\"id\":\"10202\"}},\"id\":\"11929\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"11906\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"11923\",\"type\":\"SaveTool\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"12221\"},\"group\":null,\"major_label_policy\":{\"id\":\"12222\"},\"ticker\":{\"id\":\"11919\"}},\"id\":\"11918\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"12221\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"11910\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"text\":\"Da\"},\"id\":\"11904\",\"type\":\"Title\"},{\"attributes\":{\"axis\":{\"id\":\"11914\"},\"coordinates\":null,\"group\":null,\"ticker\":null},\"id\":\"11917\",\"type\":\"Grid\"},{\"attributes\":{\"callback\":null},\"id\":\"11922\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"11908\",\"type\":\"DataRange1d\"}],\"root_ids\":[\"11903\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n", - " const render_items = [{\"docid\":\"9b2a95aa-35f3-4b0f-b949-fa91167fcbbb\",\"root_ids\":[\"11903\"],\"roots\":{\"11903\":\"01fb2ac9-1f69-4c2f-91c8-7885b2db49cb\"}}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"9b2a95aa-35f3-4b0f-b949-fa91167fcbbb\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"11914\"}],\"center\":[{\"id\":\"11917\"},{\"id\":\"11921\"}],\"height\":300,\"left\":[{\"id\":\"11918\"}],\"renderers\":[{\"id\":\"11928\"}],\"title\":{\"id\":\"11904\"},\"toolbar\":{\"id\":\"11924\"},\"toolbar_location\":\"above\",\"width\":300,\"x_range\":{\"id\":\"11906\"},\"x_scale\":{\"id\":\"11910\"},\"y_range\":{\"id\":\"11908\"},\"y_scale\":{\"id\":\"11912\"}},\"id\":\"11903\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{},\"id\":\"12222\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"12224\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"12225\",\"type\":\"AllLabels\"},{\"attributes\":{\"axis\":{\"id\":\"11918\"},\"coordinates\":null,\"dimension\":1,\"group\":null,\"ticker\":null},\"id\":\"11921\",\"type\":\"Grid\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"12224\"},\"group\":null,\"major_label_policy\":{\"id\":\"12225\"},\"ticker\":{\"id\":\"11915\"}},\"id\":\"11914\",\"type\":\"LinearAxis\"},{\"attributes\":{\"tools\":[{\"id\":\"11922\"},{\"id\":\"11923\"}]},\"id\":\"11924\",\"type\":\"Toolbar\"},{\"attributes\":{},\"id\":\"10490\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"data\":{\"text\":[\"abc\",\"def\",\"ghi\",\"jkl\",\"mno\",\"pqr\",\"stu\",\"vwx\",\"yz\"],\"x\":{\"__ndarray__\":\"AAAAAAAAAMAAAAAAAAD4vwAAAAAAAPC/AAAAAAAA4L8AAAAAAAAAAAAAAAAAAOA/AAAAAAAA8D8AAAAAAAD4PwAAAAAAAABA\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[9]},\"y\":{\"__ndarray__\":\"AAAAAAAAEEAAAAAAAAACQAAAAAAAAPA/AAAAAAAA0D8AAAAAAAAAAAAAAAAAANA/AAAAAAAA8D8AAAAAAAACQAAAAAAAABBA\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[9]}},\"selected\":{\"id\":\"10491\"},\"selection_policy\":{\"id\":\"10490\"}},\"id\":\"10202\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"10491\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"11919\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"11915\",\"type\":\"BasicTicker\"},{\"attributes\":{\"angle\":{\"units\":\"deg\",\"value\":90},\"text_color\":{\"value\":\"#96deb3\"},\"text_font\":{\"value\":\"Droid Sans Mono\"},\"text_font_size\":{\"value\":\"40px\"},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"11927\",\"type\":\"Text\"},{\"attributes\":{},\"id\":\"11912\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10202\"},\"glyph\":{\"id\":\"11927\"},\"group\":null,\"hover_glyph\":null,\"view\":{\"id\":\"11929\"}},\"id\":\"11928\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"source\":{\"id\":\"10202\"}},\"id\":\"11929\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"11906\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"11923\",\"type\":\"SaveTool\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"12221\"},\"group\":null,\"major_label_policy\":{\"id\":\"12222\"},\"ticker\":{\"id\":\"11919\"}},\"id\":\"11918\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"12221\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"11910\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"text\":\"Da\"},\"id\":\"11904\",\"type\":\"Title\"},{\"attributes\":{\"axis\":{\"id\":\"11914\"},\"coordinates\":null,\"group\":null,\"ticker\":null},\"id\":\"11917\",\"type\":\"Grid\"},{\"attributes\":{\"callback\":null},\"id\":\"11922\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"11908\",\"type\":\"DataRange1d\"}],\"root_ids\":[\"11903\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n const render_items = [{\"docid\":\"9b2a95aa-35f3-4b0f-b949-fa91167fcbbb\",\"root_ids\":[\"11903\"],\"roots\":{\"11903\":\"01fb2ac9-1f69-4c2f-91c8-7885b2db49cb\"}}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -8367,32 +7093,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"85f39dd4-3d93-40ba-8e79-b22e8a92fb3e\":{\"defs\":[{\"extends\":null,\"module\":null,\"name\":\"ReactiveHTML1\",\"overrides\":[],\"properties\":[]},{\"extends\":null,\"module\":null,\"name\":\"FlexBox1\",\"overrides\":[],\"properties\":[{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_content\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_items\"},{\"default\":\"row\",\"kind\":null,\"name\":\"flex_direction\"},{\"default\":\"wrap\",\"kind\":null,\"name\":\"flex_wrap\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"justify_content\"}]},{\"extends\":null,\"module\":null,\"name\":\"GridStack1\",\"overrides\":[],\"properties\":[{\"default\":\"warn\",\"kind\":null,\"name\":\"mode\"},{\"default\":null,\"kind\":null,\"name\":\"ncols\"},{\"default\":null,\"kind\":null,\"name\":\"nrows\"},{\"default\":true,\"kind\":null,\"name\":\"allow_resize\"},{\"default\":true,\"kind\":null,\"name\":\"allow_drag\"},{\"default\":[],\"kind\":null,\"name\":\"state\"}]},{\"extends\":null,\"module\":null,\"name\":\"click1\",\"overrides\":[],\"properties\":[{\"default\":\"\",\"kind\":null,\"name\":\"terminal_output\"},{\"default\":\"\",\"kind\":null,\"name\":\"debug_name\"},{\"default\":0,\"kind\":null,\"name\":\"clears\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationAreaBase1\",\"overrides\":[],\"properties\":[{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationArea1\",\"overrides\":[],\"properties\":[{\"default\":[],\"kind\":null,\"name\":\"notifications\"},{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"},{\"default\":[{\"background\":\"#ffc107\",\"icon\":{\"className\":\"fas fa-exclamation-triangle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"warning\"},{\"background\":\"#007bff\",\"icon\":{\"className\":\"fas fa-info-circle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"info\"}],\"kind\":null,\"name\":\"types\"}]},{\"extends\":null,\"module\":null,\"name\":\"Notification\",\"overrides\":[],\"properties\":[{\"default\":null,\"kind\":null,\"name\":\"background\"},{\"default\":3000,\"kind\":null,\"name\":\"duration\"},{\"default\":null,\"kind\":null,\"name\":\"icon\"},{\"default\":\"\",\"kind\":null,\"name\":\"message\"},{\"default\":null,\"kind\":null,\"name\":\"notification_type\"},{\"default\":false,\"kind\":null,\"name\":\"_destroyed\"}]},{\"extends\":null,\"module\":null,\"name\":\"TemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]},{\"extends\":null,\"module\":null,\"name\":\"MaterialTemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]}],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"9061\"}],\"center\":[{\"id\":\"9064\"},{\"id\":\"9068\"},{\"id\":\"9103\"}],\"left\":[{\"id\":\"9065\"}],\"renderers\":[{\"id\":\"9091\"},{\"id\":\"9113\"}],\"title\":{\"id\":\"9051\"},\"toolbar\":{\"id\":\"9076\"},\"toolbar_location\":\"above\",\"x_range\":{\"id\":\"9053\"},\"x_scale\":{\"id\":\"9057\"},\"y_range\":{\"id\":\"9055\"},\"y_scale\":{\"id\":\"9059\"}},\"id\":\"9050\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"9098\"},\"group\":null,\"major_label_policy\":{\"id\":\"9099\"},\"ticker\":{\"id\":\"9062\"},\"visible\":false},\"id\":\"9061\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"9125\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"9062\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"9059\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"9055\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"9072\",\"type\":\"UndoTool\"},{\"attributes\":{\"label\":{\"field\":\"labels\"},\"renderers\":[{\"id\":\"9113\"}]},\"id\":\"9127\",\"type\":\"LegendItem\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9084\"}},\"fill_alpha\":{\"value\":0.8},\"fill_color\":{\"field\":\"color_outer\"},\"inner_radius\":{\"value\":0.0},\"outer_radius\":{\"value\":0.3},\"start_angle\":{\"expr\":{\"id\":\"9083\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9086\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"items\":[{\"id\":\"9104\"},{\"id\":\"9127\"}]},\"id\":\"9103\",\"type\":\"Legend\"},{\"attributes\":{\"data\":{\"All\":[1,97,128,144,224,17,9],\"Chemistry\":[0,0,0,0,0,0,0],\"Cum. Sum\":[1,36,36,63,125,9,4],\"Earth Science\":[1,6,10,18,25,2,0],\"Engineering Science\":[0,30,26,45,100,7,4],\"Life Science\":[0,0,0,0,0,0,0],\"Mathematics\":[0,0,0,0,0,0,0],\"Other\":[0,0,0,0,0,0,0],\"Physics\":[0,0,0,0,0,0,0],\"Psychology\":[0,0,0,0,0,0,0],\"angle\":{\"__ndarray__\":\"5wCiQDnBhD9fifXF2nTvP+cAokA5wfQ/BEG2aGBZ9z/KwI0YEikCQPYgrNRMDcY/BEG2aGBZtz8=\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[7]},\"careerLevel\":[\"Other\",\"PhD candidate\",\"Postdoc\",\"Principal Investigator\",\"Research Associate\",\"Student\",\"Technical Staff\"],\"color_outer\":[\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\"],\"count\":[1,97,128,144,224,17,9],\"index\":[0,1,2,3,4,5,6],\"legend_field\":[\"Total\",\"Total\",\"Total\",\"Total\",\"Total\",\"Total\",\"Total\"],\"percent\":{\"__ndarray__\":\"bRrQpgFtWj8HtGlAmwbEP20a0KYBbco/ux2q26G6zT8fF/ZxYR/XPxQcPcHRE5w/ux2q26G6jT8=\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[7]},\"x_value\":[\"Other\",\"PhD candidate\",\"Postdoc\",\"Principal Investigator\",\"Research Associate\",\"Student\",\"Technical Staff\"]},\"selected\":{\"id\":\"9101\"},\"selection_policy\":{\"id\":\"9100\"}},\"id\":\"9048\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"axis\":{\"id\":\"9065\"},\"coordinates\":null,\"dimension\":1,\"grid_line_color\":null,\"group\":null,\"ticker\":null},\"id\":\"9068\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"9066\",\"type\":\"BasicTicker\"},{\"attributes\":{\"field\":\"angle\",\"include_zero\":true},\"id\":\"9105\",\"type\":\"CumSum\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9106\"}},\"fill_alpha\":{\"value\":0.8},\"fill_color\":{\"field\":\"color\"},\"inner_radius\":{\"value\":0.3},\"outer_radius\":{\"value\":0.7},\"start_angle\":{\"expr\":{\"id\":\"9105\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9108\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"9070\",\"type\":\"WheelZoomTool\"},{\"attributes\":{\"label\":{\"field\":\"legend_field\"},\"renderers\":[{\"id\":\"9091\"}]},\"id\":\"9104\",\"type\":\"LegendItem\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9106\"}},\"fill_color\":{\"field\":\"color\"},\"inner_radius\":{\"value\":0.3},\"line_width\":{\"value\":5.0},\"outer_radius\":{\"value\":0.7},\"start_angle\":{\"expr\":{\"id\":\"9105\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9111\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"Data\",\"@x_value\"],[\"Percent\",\"@percent{0.00%}\"],[\"Count\",\"@count\"]]},\"id\":\"9069\",\"type\":\"HoverTool\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9106\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"blue\"},\"hatch_alpha\":{\"value\":0.1},\"inner_radius\":{\"value\":0.3},\"line_alpha\":{\"value\":0.5},\"outer_radius\":{\"value\":0.7},\"start_angle\":{\"expr\":{\"id\":\"9105\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9109\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"overlay\":{\"id\":\"9075\"}},\"id\":\"9071\",\"type\":\"BoxZoomTool\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"text\":\"Career level of participants.\"},\"id\":\"9051\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"9095\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9106\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"field\":\"color\"},\"hatch_alpha\":{\"value\":0.2},\"inner_radius\":{\"value\":0.3},\"line_alpha\":{\"value\":0.2},\"outer_radius\":{\"value\":0.7},\"start_angle\":{\"expr\":{\"id\":\"9105\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9112\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"9096\",\"type\":\"AllLabels\"},{\"attributes\":{\"source\":{\"id\":\"9049\"}},\"id\":\"9114\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"9053\",\"type\":\"DataRange1d\"},{\"attributes\":{\"logo\":null,\"tools\":[{\"id\":\"9069\"},{\"id\":\"9070\"},{\"id\":\"9071\"},{\"id\":\"9072\"},{\"id\":\"9073\"},{\"id\":\"9074\"}]},\"id\":\"9076\",\"type\":\"Toolbar\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9106\"}},\"fill_color\":{\"value\":\"black\"},\"inner_radius\":{\"value\":0.3},\"outer_radius\":{\"value\":0.7},\"start_angle\":{\"expr\":{\"id\":\"9105\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9110\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"9073\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"9098\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"9048\"},\"glyph\":{\"id\":\"9086\"},\"group\":null,\"hover_glyph\":{\"id\":\"9089\"},\"muted_glyph\":{\"id\":\"9090\"},\"nonselection_glyph\":{\"id\":\"9087\"},\"selection_glyph\":{\"id\":\"9088\"},\"view\":{\"id\":\"9092\"}},\"id\":\"9091\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"9099\",\"type\":\"AllLabels\"},{\"attributes\":{\"field\":\"angle\"},\"id\":\"9106\",\"type\":\"CumSum\"},{\"attributes\":{\"axis\":{\"id\":\"9061\"},\"coordinates\":null,\"grid_line_color\":null,\"group\":null,\"ticker\":null},\"id\":\"9064\",\"type\":\"Grid\"},{\"attributes\":{\"data\":{\"angle\":{\"__ndarray__\":\"5wCiQDnBhD8AAAAAAAAAAFsB8+DVIa8/2eCXrCV10z/caJqRKsjjPyGBypCH8bk/vKCDhP7c0D9M4ehMwtXtPwRBtmhgWcc/RtHjgrgv3T8lCc11jETqP7WQfrr0NtA/tZB+uvQ28D+zTP1Hcg3wP+cAokA5wZQ/ysCNGBIpsj/nAKJAOcG0PwAAAAAAAAAA5wCiQDnBpD8hgcqQh/GpPw==\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[20]},\"color\":[\"#c6dbef\",\"#e6550d\",\"#c6dbef\",\"#e6550d\",\"#ffffff\",\"#c6dbef\",\"#e6550d\",\"#ffffff\",\"#c6dbef\",\"#e6550d\",\"#ffffff\",\"#c6dbef\",\"#e6550d\",\"#ffffff\",\"#c6dbef\",\"#e6550d\",\"#ffffff\",\"#c6dbef\",\"#e6550d\",\"#ffffff\"],\"count\":[1,0,6,30,61,10,26,92,18,45,81,25,100,99,2,7,8,0,4,5],\"labels\":[\"Earth Science\",\"Engineering Science\",\"Earth Science\",\"Engineering Science\",\"Other\",\"Earth Science\",\"Engineering Science\",\"Other\",\"Earth Science\",\"Engineering Science\",\"Other\",\"Earth Science\",\"Engineering Science\",\"Other\",\"Earth Science\",\"Engineering Science\",\"Other\",\"Earth Science\",\"Engineering Science\",\"Other\"],\"percent\":{\"__ndarray__\":\"bRrQpgFtWj8AAAAAAAAAANITHD3B0YM/xhhjjDHGqD8wWf6S5S+5P4QQQgghhJA/eRWJV5F4pT/+kuUvWf7CP7sdqtuhup0/lVJKKaWUsj+5sI8L+7jAP6WUUkoppaQ/pZRSSimlxD9w9ARHT3DEP20a0KYBbWo/Hxf2cWEfhz9tGtCmAW2KPwAAAAAAAAAAbRrQpgFtej+EEEIIIYSAPw==\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[20]},\"x_value\":[\"Other, Earth Science\",\"Other, Engineering Science\",\"PhD candidate, Earth Science\",\"PhD candidate, Engineering Science\",\"PhD candidate, Other\",\"Postdoc, Earth Science\",\"Postdoc, Engineering Science\",\"Postdoc, Other\",\"Principal Investigator, Earth Science\",\"Principal Investigator, Engineering Science\",\"Principal Investigator, Other\",\"Research Associate, Earth Science\",\"Research Associate, Engineering Science\",\"Research Associate, Other\",\"Student, Earth Science\",\"Student, Engineering Science\",\"Student, Other\",\"Technical Staff, Earth Science\",\"Technical Staff, Engineering Science\",\"Technical Staff, Other\"]},\"selected\":{\"id\":\"9125\"},\"selection_policy\":{\"id\":\"9124\"}},\"id\":\"9049\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"field\":\"angle\"},\"id\":\"9084\",\"type\":\"CumSum\"},{\"attributes\":{\"source\":{\"id\":\"9048\"}},\"id\":\"9092\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"9074\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"9057\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"9095\"},\"group\":null,\"major_label_policy\":{\"id\":\"9096\"},\"ticker\":{\"id\":\"9066\"},\"visible\":false},\"id\":\"9065\",\"type\":\"LinearAxis\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9084\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"blue\"},\"hatch_alpha\":{\"value\":0.1},\"inner_radius\":{\"value\":0.0},\"line_alpha\":{\"value\":0.5},\"outer_radius\":{\"value\":0.3},\"start_angle\":{\"expr\":{\"id\":\"9083\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9087\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"9101\",\"type\":\"Selection\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9084\"}},\"fill_color\":{\"field\":\"color_outer\"},\"inner_radius\":{\"value\":0.0},\"line_width\":{\"value\":5.0},\"outer_radius\":{\"value\":0.3},\"start_angle\":{\"expr\":{\"id\":\"9083\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9089\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"bottom_units\":\"screen\",\"coordinates\":null,\"fill_alpha\":0.5,\"fill_color\":\"lightgrey\",\"group\":null,\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":1.0,\"line_color\":\"black\",\"line_dash\":[4,4],\"line_width\":2,\"right_units\":\"screen\",\"syncable\":false,\"top_units\":\"screen\"},\"id\":\"9075\",\"type\":\"BoxAnnotation\"},{\"attributes\":{},\"id\":\"9100\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"field\":\"angle\",\"include_zero\":true},\"id\":\"9083\",\"type\":\"CumSum\"},{\"attributes\":{},\"id\":\"9124\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9084\"}},\"fill_color\":{\"value\":\"black\"},\"inner_radius\":{\"value\":0.0},\"outer_radius\":{\"value\":0.3},\"start_angle\":{\"expr\":{\"id\":\"9083\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9088\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"9049\"},\"glyph\":{\"id\":\"9108\"},\"group\":null,\"hover_glyph\":{\"id\":\"9111\"},\"muted_glyph\":{\"id\":\"9112\"},\"nonselection_glyph\":{\"id\":\"9109\"},\"selection_glyph\":{\"id\":\"9110\"},\"view\":{\"id\":\"9114\"}},\"id\":\"9113\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9084\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"field\":\"color_outer\"},\"hatch_alpha\":{\"value\":0.2},\"inner_radius\":{\"value\":0.0},\"line_alpha\":{\"value\":0.2},\"outer_radius\":{\"value\":0.3},\"start_angle\":{\"expr\":{\"id\":\"9083\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9090\",\"type\":\"AnnularWedge\"}],\"root_ids\":[\"9050\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n", - " const render_items = [{\"docid\":\"85f39dd4-3d93-40ba-8e79-b22e8a92fb3e\",\"root_ids\":[\"9050\"],\"roots\":{\"9050\":\"199e4734-3c11-4319-bd9b-a8b848537f88\"}}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"85f39dd4-3d93-40ba-8e79-b22e8a92fb3e\":{\"defs\":[{\"extends\":null,\"module\":null,\"name\":\"ReactiveHTML1\",\"overrides\":[],\"properties\":[]},{\"extends\":null,\"module\":null,\"name\":\"FlexBox1\",\"overrides\":[],\"properties\":[{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_content\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_items\"},{\"default\":\"row\",\"kind\":null,\"name\":\"flex_direction\"},{\"default\":\"wrap\",\"kind\":null,\"name\":\"flex_wrap\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"justify_content\"}]},{\"extends\":null,\"module\":null,\"name\":\"GridStack1\",\"overrides\":[],\"properties\":[{\"default\":\"warn\",\"kind\":null,\"name\":\"mode\"},{\"default\":null,\"kind\":null,\"name\":\"ncols\"},{\"default\":null,\"kind\":null,\"name\":\"nrows\"},{\"default\":true,\"kind\":null,\"name\":\"allow_resize\"},{\"default\":true,\"kind\":null,\"name\":\"allow_drag\"},{\"default\":[],\"kind\":null,\"name\":\"state\"}]},{\"extends\":null,\"module\":null,\"name\":\"click1\",\"overrides\":[],\"properties\":[{\"default\":\"\",\"kind\":null,\"name\":\"terminal_output\"},{\"default\":\"\",\"kind\":null,\"name\":\"debug_name\"},{\"default\":0,\"kind\":null,\"name\":\"clears\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationAreaBase1\",\"overrides\":[],\"properties\":[{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationArea1\",\"overrides\":[],\"properties\":[{\"default\":[],\"kind\":null,\"name\":\"notifications\"},{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"},{\"default\":[{\"background\":\"#ffc107\",\"icon\":{\"className\":\"fas fa-exclamation-triangle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"warning\"},{\"background\":\"#007bff\",\"icon\":{\"className\":\"fas fa-info-circle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"info\"}],\"kind\":null,\"name\":\"types\"}]},{\"extends\":null,\"module\":null,\"name\":\"Notification\",\"overrides\":[],\"properties\":[{\"default\":null,\"kind\":null,\"name\":\"background\"},{\"default\":3000,\"kind\":null,\"name\":\"duration\"},{\"default\":null,\"kind\":null,\"name\":\"icon\"},{\"default\":\"\",\"kind\":null,\"name\":\"message\"},{\"default\":null,\"kind\":null,\"name\":\"notification_type\"},{\"default\":false,\"kind\":null,\"name\":\"_destroyed\"}]},{\"extends\":null,\"module\":null,\"name\":\"TemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]},{\"extends\":null,\"module\":null,\"name\":\"MaterialTemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]}],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"9061\"}],\"center\":[{\"id\":\"9064\"},{\"id\":\"9068\"},{\"id\":\"9103\"}],\"left\":[{\"id\":\"9065\"}],\"renderers\":[{\"id\":\"9091\"},{\"id\":\"9113\"}],\"title\":{\"id\":\"9051\"},\"toolbar\":{\"id\":\"9076\"},\"toolbar_location\":\"above\",\"x_range\":{\"id\":\"9053\"},\"x_scale\":{\"id\":\"9057\"},\"y_range\":{\"id\":\"9055\"},\"y_scale\":{\"id\":\"9059\"}},\"id\":\"9050\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"9098\"},\"group\":null,\"major_label_policy\":{\"id\":\"9099\"},\"ticker\":{\"id\":\"9062\"},\"visible\":false},\"id\":\"9061\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"9125\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"9062\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"9059\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"9055\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"9072\",\"type\":\"UndoTool\"},{\"attributes\":{\"label\":{\"field\":\"labels\"},\"renderers\":[{\"id\":\"9113\"}]},\"id\":\"9127\",\"type\":\"LegendItem\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9084\"}},\"fill_alpha\":{\"value\":0.8},\"fill_color\":{\"field\":\"color_outer\"},\"inner_radius\":{\"value\":0.0},\"outer_radius\":{\"value\":0.3},\"start_angle\":{\"expr\":{\"id\":\"9083\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9086\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"items\":[{\"id\":\"9104\"},{\"id\":\"9127\"}]},\"id\":\"9103\",\"type\":\"Legend\"},{\"attributes\":{\"data\":{\"All\":[1,97,128,144,224,17,9],\"Chemistry\":[0,0,0,0,0,0,0],\"Cum. Sum\":[1,36,36,63,125,9,4],\"Earth Science\":[1,6,10,18,25,2,0],\"Engineering Science\":[0,30,26,45,100,7,4],\"Life Science\":[0,0,0,0,0,0,0],\"Mathematics\":[0,0,0,0,0,0,0],\"Other\":[0,0,0,0,0,0,0],\"Physics\":[0,0,0,0,0,0,0],\"Psychology\":[0,0,0,0,0,0,0],\"angle\":{\"__ndarray__\":\"5wCiQDnBhD9fifXF2nTvP+cAokA5wfQ/BEG2aGBZ9z/KwI0YEikCQPYgrNRMDcY/BEG2aGBZtz8=\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[7]},\"careerLevel\":[\"Other\",\"PhD candidate\",\"Postdoc\",\"Principal Investigator\",\"Research Associate\",\"Student\",\"Technical Staff\"],\"color_outer\":[\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\"],\"count\":[1,97,128,144,224,17,9],\"index\":[0,1,2,3,4,5,6],\"legend_field\":[\"Total\",\"Total\",\"Total\",\"Total\",\"Total\",\"Total\",\"Total\"],\"percent\":{\"__ndarray__\":\"bRrQpgFtWj8HtGlAmwbEP20a0KYBbco/ux2q26G6zT8fF/ZxYR/XPxQcPcHRE5w/ux2q26G6jT8=\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[7]},\"x_value\":[\"Other\",\"PhD candidate\",\"Postdoc\",\"Principal Investigator\",\"Research Associate\",\"Student\",\"Technical Staff\"]},\"selected\":{\"id\":\"9101\"},\"selection_policy\":{\"id\":\"9100\"}},\"id\":\"9048\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"axis\":{\"id\":\"9065\"},\"coordinates\":null,\"dimension\":1,\"grid_line_color\":null,\"group\":null,\"ticker\":null},\"id\":\"9068\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"9066\",\"type\":\"BasicTicker\"},{\"attributes\":{\"field\":\"angle\",\"include_zero\":true},\"id\":\"9105\",\"type\":\"CumSum\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9106\"}},\"fill_alpha\":{\"value\":0.8},\"fill_color\":{\"field\":\"color\"},\"inner_radius\":{\"value\":0.3},\"outer_radius\":{\"value\":0.7},\"start_angle\":{\"expr\":{\"id\":\"9105\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9108\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"9070\",\"type\":\"WheelZoomTool\"},{\"attributes\":{\"label\":{\"field\":\"legend_field\"},\"renderers\":[{\"id\":\"9091\"}]},\"id\":\"9104\",\"type\":\"LegendItem\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9106\"}},\"fill_color\":{\"field\":\"color\"},\"inner_radius\":{\"value\":0.3},\"line_width\":{\"value\":5.0},\"outer_radius\":{\"value\":0.7},\"start_angle\":{\"expr\":{\"id\":\"9105\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9111\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"Data\",\"@x_value\"],[\"Percent\",\"@percent{0.00%}\"],[\"Count\",\"@count\"]]},\"id\":\"9069\",\"type\":\"HoverTool\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9106\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"blue\"},\"hatch_alpha\":{\"value\":0.1},\"inner_radius\":{\"value\":0.3},\"line_alpha\":{\"value\":0.5},\"outer_radius\":{\"value\":0.7},\"start_angle\":{\"expr\":{\"id\":\"9105\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9109\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"overlay\":{\"id\":\"9075\"}},\"id\":\"9071\",\"type\":\"BoxZoomTool\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"text\":\"Career level of participants.\"},\"id\":\"9051\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"9095\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9106\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"field\":\"color\"},\"hatch_alpha\":{\"value\":0.2},\"inner_radius\":{\"value\":0.3},\"line_alpha\":{\"value\":0.2},\"outer_radius\":{\"value\":0.7},\"start_angle\":{\"expr\":{\"id\":\"9105\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9112\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"9096\",\"type\":\"AllLabels\"},{\"attributes\":{\"source\":{\"id\":\"9049\"}},\"id\":\"9114\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"9053\",\"type\":\"DataRange1d\"},{\"attributes\":{\"logo\":null,\"tools\":[{\"id\":\"9069\"},{\"id\":\"9070\"},{\"id\":\"9071\"},{\"id\":\"9072\"},{\"id\":\"9073\"},{\"id\":\"9074\"}]},\"id\":\"9076\",\"type\":\"Toolbar\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9106\"}},\"fill_color\":{\"value\":\"black\"},\"inner_radius\":{\"value\":0.3},\"outer_radius\":{\"value\":0.7},\"start_angle\":{\"expr\":{\"id\":\"9105\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9110\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"9073\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"9098\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"9048\"},\"glyph\":{\"id\":\"9086\"},\"group\":null,\"hover_glyph\":{\"id\":\"9089\"},\"muted_glyph\":{\"id\":\"9090\"},\"nonselection_glyph\":{\"id\":\"9087\"},\"selection_glyph\":{\"id\":\"9088\"},\"view\":{\"id\":\"9092\"}},\"id\":\"9091\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"9099\",\"type\":\"AllLabels\"},{\"attributes\":{\"field\":\"angle\"},\"id\":\"9106\",\"type\":\"CumSum\"},{\"attributes\":{\"axis\":{\"id\":\"9061\"},\"coordinates\":null,\"grid_line_color\":null,\"group\":null,\"ticker\":null},\"id\":\"9064\",\"type\":\"Grid\"},{\"attributes\":{\"data\":{\"angle\":{\"__ndarray__\":\"5wCiQDnBhD8AAAAAAAAAAFsB8+DVIa8/2eCXrCV10z/caJqRKsjjPyGBypCH8bk/vKCDhP7c0D9M4ehMwtXtPwRBtmhgWcc/RtHjgrgv3T8lCc11jETqP7WQfrr0NtA/tZB+uvQ28D+zTP1Hcg3wP+cAokA5wZQ/ysCNGBIpsj/nAKJAOcG0PwAAAAAAAAAA5wCiQDnBpD8hgcqQh/GpPw==\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[20]},\"color\":[\"#c6dbef\",\"#e6550d\",\"#c6dbef\",\"#e6550d\",\"#ffffff\",\"#c6dbef\",\"#e6550d\",\"#ffffff\",\"#c6dbef\",\"#e6550d\",\"#ffffff\",\"#c6dbef\",\"#e6550d\",\"#ffffff\",\"#c6dbef\",\"#e6550d\",\"#ffffff\",\"#c6dbef\",\"#e6550d\",\"#ffffff\"],\"count\":[1,0,6,30,61,10,26,92,18,45,81,25,100,99,2,7,8,0,4,5],\"labels\":[\"Earth Science\",\"Engineering Science\",\"Earth Science\",\"Engineering Science\",\"Other\",\"Earth Science\",\"Engineering Science\",\"Other\",\"Earth Science\",\"Engineering Science\",\"Other\",\"Earth Science\",\"Engineering Science\",\"Other\",\"Earth Science\",\"Engineering Science\",\"Other\",\"Earth Science\",\"Engineering Science\",\"Other\"],\"percent\":{\"__ndarray__\":\"bRrQpgFtWj8AAAAAAAAAANITHD3B0YM/xhhjjDHGqD8wWf6S5S+5P4QQQgghhJA/eRWJV5F4pT/+kuUvWf7CP7sdqtuhup0/lVJKKaWUsj+5sI8L+7jAP6WUUkoppaQ/pZRSSimlxD9w9ARHT3DEP20a0KYBbWo/Hxf2cWEfhz9tGtCmAW2KPwAAAAAAAAAAbRrQpgFtej+EEEIIIYSAPw==\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[20]},\"x_value\":[\"Other, Earth Science\",\"Other, Engineering Science\",\"PhD candidate, Earth Science\",\"PhD candidate, Engineering Science\",\"PhD candidate, Other\",\"Postdoc, Earth Science\",\"Postdoc, Engineering Science\",\"Postdoc, Other\",\"Principal Investigator, Earth Science\",\"Principal Investigator, Engineering Science\",\"Principal Investigator, Other\",\"Research Associate, Earth Science\",\"Research Associate, Engineering Science\",\"Research Associate, Other\",\"Student, Earth Science\",\"Student, Engineering Science\",\"Student, Other\",\"Technical Staff, Earth Science\",\"Technical Staff, Engineering Science\",\"Technical Staff, Other\"]},\"selected\":{\"id\":\"9125\"},\"selection_policy\":{\"id\":\"9124\"}},\"id\":\"9049\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"field\":\"angle\"},\"id\":\"9084\",\"type\":\"CumSum\"},{\"attributes\":{\"source\":{\"id\":\"9048\"}},\"id\":\"9092\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"9074\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"9057\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"9095\"},\"group\":null,\"major_label_policy\":{\"id\":\"9096\"},\"ticker\":{\"id\":\"9066\"},\"visible\":false},\"id\":\"9065\",\"type\":\"LinearAxis\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9084\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"blue\"},\"hatch_alpha\":{\"value\":0.1},\"inner_radius\":{\"value\":0.0},\"line_alpha\":{\"value\":0.5},\"outer_radius\":{\"value\":0.3},\"start_angle\":{\"expr\":{\"id\":\"9083\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9087\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"9101\",\"type\":\"Selection\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9084\"}},\"fill_color\":{\"field\":\"color_outer\"},\"inner_radius\":{\"value\":0.0},\"line_width\":{\"value\":5.0},\"outer_radius\":{\"value\":0.3},\"start_angle\":{\"expr\":{\"id\":\"9083\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9089\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"bottom_units\":\"screen\",\"coordinates\":null,\"fill_alpha\":0.5,\"fill_color\":\"lightgrey\",\"group\":null,\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":1.0,\"line_color\":\"black\",\"line_dash\":[4,4],\"line_width\":2,\"right_units\":\"screen\",\"syncable\":false,\"top_units\":\"screen\"},\"id\":\"9075\",\"type\":\"BoxAnnotation\"},{\"attributes\":{},\"id\":\"9100\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"field\":\"angle\",\"include_zero\":true},\"id\":\"9083\",\"type\":\"CumSum\"},{\"attributes\":{},\"id\":\"9124\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9084\"}},\"fill_color\":{\"value\":\"black\"},\"inner_radius\":{\"value\":0.0},\"outer_radius\":{\"value\":0.3},\"start_angle\":{\"expr\":{\"id\":\"9083\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9088\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"9049\"},\"glyph\":{\"id\":\"9108\"},\"group\":null,\"hover_glyph\":{\"id\":\"9111\"},\"muted_glyph\":{\"id\":\"9112\"},\"nonselection_glyph\":{\"id\":\"9109\"},\"selection_glyph\":{\"id\":\"9110\"},\"view\":{\"id\":\"9114\"}},\"id\":\"9113\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9084\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"field\":\"color_outer\"},\"hatch_alpha\":{\"value\":0.2},\"inner_radius\":{\"value\":0.0},\"line_alpha\":{\"value\":0.2},\"outer_radius\":{\"value\":0.3},\"start_angle\":{\"expr\":{\"id\":\"9083\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9090\",\"type\":\"AnnularWedge\"}],\"root_ids\":[\"9050\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n const render_items = [{\"docid\":\"85f39dd4-3d93-40ba-8e79-b22e8a92fb3e\",\"root_ids\":[\"9050\"],\"roots\":{\"9050\":\"199e4734-3c11-4319-bd9b-a8b848537f88\"}}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -8427,32 +7128,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"c42bfb72-a732-40ad-a635-08d22ecf266d\":{\"defs\":[{\"extends\":null,\"module\":null,\"name\":\"ReactiveHTML1\",\"overrides\":[],\"properties\":[]},{\"extends\":null,\"module\":null,\"name\":\"FlexBox1\",\"overrides\":[],\"properties\":[{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_content\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_items\"},{\"default\":\"row\",\"kind\":null,\"name\":\"flex_direction\"},{\"default\":\"wrap\",\"kind\":null,\"name\":\"flex_wrap\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"justify_content\"}]},{\"extends\":null,\"module\":null,\"name\":\"GridStack1\",\"overrides\":[],\"properties\":[{\"default\":\"warn\",\"kind\":null,\"name\":\"mode\"},{\"default\":null,\"kind\":null,\"name\":\"ncols\"},{\"default\":null,\"kind\":null,\"name\":\"nrows\"},{\"default\":true,\"kind\":null,\"name\":\"allow_resize\"},{\"default\":true,\"kind\":null,\"name\":\"allow_drag\"},{\"default\":[],\"kind\":null,\"name\":\"state\"}]},{\"extends\":null,\"module\":null,\"name\":\"click1\",\"overrides\":[],\"properties\":[{\"default\":\"\",\"kind\":null,\"name\":\"terminal_output\"},{\"default\":\"\",\"kind\":null,\"name\":\"debug_name\"},{\"default\":0,\"kind\":null,\"name\":\"clears\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationAreaBase1\",\"overrides\":[],\"properties\":[{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationArea1\",\"overrides\":[],\"properties\":[{\"default\":[],\"kind\":null,\"name\":\"notifications\"},{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"},{\"default\":[{\"background\":\"#ffc107\",\"icon\":{\"className\":\"fas fa-exclamation-triangle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"warning\"},{\"background\":\"#007bff\",\"icon\":{\"className\":\"fas fa-info-circle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"info\"}],\"kind\":null,\"name\":\"types\"}]},{\"extends\":null,\"module\":null,\"name\":\"Notification\",\"overrides\":[],\"properties\":[{\"default\":null,\"kind\":null,\"name\":\"background\"},{\"default\":3000,\"kind\":null,\"name\":\"duration\"},{\"default\":null,\"kind\":null,\"name\":\"icon\"},{\"default\":\"\",\"kind\":null,\"name\":\"message\"},{\"default\":null,\"kind\":null,\"name\":\"notification_type\"},{\"default\":false,\"kind\":null,\"name\":\"_destroyed\"}]},{\"extends\":null,\"module\":null,\"name\":\"TemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]},{\"extends\":null,\"module\":null,\"name\":\"MaterialTemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]}],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"9513\"}],\"center\":[{\"id\":\"9516\"},{\"id\":\"9520\"},{\"id\":\"9555\"}],\"left\":[{\"id\":\"9517\"}],\"renderers\":[{\"id\":\"9543\"}],\"title\":{\"id\":\"9503\"},\"toolbar\":{\"id\":\"9528\"},\"toolbar_location\":\"above\",\"x_range\":{\"id\":\"9505\"},\"x_scale\":{\"id\":\"9509\"},\"y_range\":{\"id\":\"9507\"},\"y_scale\":{\"id\":\"9511\"}},\"id\":\"9502\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"field\":\"angle\"},\"id\":\"9536\",\"type\":\"CumSum\"},{\"attributes\":{},\"id\":\"9518\",\"type\":\"BasicTicker\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9536\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"blue\"},\"hatch_alpha\":{\"value\":0.1},\"inner_radius\":{\"value\":0.0},\"line_alpha\":{\"value\":0.5},\"outer_radius\":{\"value\":0.0},\"start_angle\":{\"expr\":{\"id\":\"9535\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9539\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"9525\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"9522\",\"type\":\"WheelZoomTool\"},{\"attributes\":{},\"id\":\"9547\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"source\":{\"id\":\"9048\"}},\"id\":\"9544\",\"type\":\"CDSView\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"Data\",\"@x_value\"],[\"Percent\",\"@percent{0.00%}\"],[\"Count\",\"@count\"]]},\"id\":\"9521\",\"type\":\"HoverTool\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9536\"}},\"fill_color\":{\"field\":\"color_outer\"},\"inner_radius\":{\"value\":0.0},\"line_width\":{\"value\":5.0},\"outer_radius\":{\"value\":0.0},\"start_angle\":{\"expr\":{\"id\":\"9535\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9541\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"overlay\":{\"id\":\"9527\"}},\"id\":\"9523\",\"type\":\"BoxZoomTool\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9536\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"field\":\"color_outer\"},\"hatch_alpha\":{\"value\":0.2},\"inner_radius\":{\"value\":0.0},\"line_alpha\":{\"value\":0.2},\"outer_radius\":{\"value\":0.0},\"start_angle\":{\"expr\":{\"id\":\"9535\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9542\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"data\":{\"All\":[1,97,128,144,224,17,9],\"Chemistry\":[0,0,0,0,0,0,0],\"Cum. Sum\":[1,36,36,63,125,9,4],\"Earth Science\":[1,6,10,18,25,2,0],\"Engineering Science\":[0,30,26,45,100,7,4],\"Life Science\":[0,0,0,0,0,0,0],\"Mathematics\":[0,0,0,0,0,0,0],\"Other\":[0,0,0,0,0,0,0],\"Physics\":[0,0,0,0,0,0,0],\"Psychology\":[0,0,0,0,0,0,0],\"angle\":{\"__ndarray__\":\"5wCiQDnBhD9fifXF2nTvP+cAokA5wfQ/BEG2aGBZ9z/KwI0YEikCQPYgrNRMDcY/BEG2aGBZtz8=\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[7]},\"careerLevel\":[\"Other\",\"PhD candidate\",\"Postdoc\",\"Principal Investigator\",\"Research Associate\",\"Student\",\"Technical Staff\"],\"color_outer\":[\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\"],\"count\":[1,97,128,144,224,17,9],\"index\":[0,1,2,3,4,5,6],\"legend_field\":[\"Total\",\"Total\",\"Total\",\"Total\",\"Total\",\"Total\",\"Total\"],\"percent\":{\"__ndarray__\":\"bRrQpgFtWj8HtGlAmwbEP20a0KYBbco/ux2q26G6zT8fF/ZxYR/XPxQcPcHRE5w/ux2q26G6jT8=\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[7]},\"x_value\":[\"Other\",\"PhD candidate\",\"Postdoc\",\"Principal Investigator\",\"Research Associate\",\"Student\",\"Technical Staff\"]},\"selected\":{\"id\":\"9101\"},\"selection_policy\":{\"id\":\"9100\"}},\"id\":\"9048\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"9524\",\"type\":\"UndoTool\"},{\"attributes\":{},\"id\":\"9548\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"9550\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"bottom_units\":\"screen\",\"coordinates\":null,\"fill_alpha\":0.5,\"fill_color\":\"lightgrey\",\"group\":null,\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":1.0,\"line_color\":\"black\",\"line_dash\":[4,4],\"line_width\":2,\"right_units\":\"screen\",\"syncable\":false,\"top_units\":\"screen\"},\"id\":\"9527\",\"type\":\"BoxAnnotation\"},{\"attributes\":{},\"id\":\"9509\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"items\":[{\"id\":\"9556\"}]},\"id\":\"9555\",\"type\":\"Legend\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9536\"}},\"fill_color\":{\"value\":\"black\"},\"inner_radius\":{\"value\":0.0},\"outer_radius\":{\"value\":0.0},\"start_angle\":{\"expr\":{\"id\":\"9535\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9540\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"9551\",\"type\":\"AllLabels\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"9048\"},\"glyph\":{\"id\":\"9538\"},\"group\":null,\"hover_glyph\":{\"id\":\"9541\"},\"muted_glyph\":{\"id\":\"9542\"},\"nonselection_glyph\":{\"id\":\"9539\"},\"selection_glyph\":{\"id\":\"9540\"},\"view\":{\"id\":\"9544\"}},\"id\":\"9543\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"label\":{\"field\":\"legend_field\"},\"renderers\":[{\"id\":\"9543\"}]},\"id\":\"9556\",\"type\":\"LegendItem\"},{\"attributes\":{},\"id\":\"9505\",\"type\":\"DataRange1d\"},{\"attributes\":{\"axis\":{\"id\":\"9517\"},\"coordinates\":null,\"dimension\":1,\"grid_line_color\":null,\"group\":null,\"ticker\":null},\"id\":\"9520\",\"type\":\"Grid\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"9547\"},\"group\":null,\"major_label_policy\":{\"id\":\"9548\"},\"ticker\":{\"id\":\"9518\"},\"visible\":false},\"id\":\"9517\",\"type\":\"LinearAxis\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"text\":\"Career level of participants.\"},\"id\":\"9503\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"9101\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"9514\",\"type\":\"BasicTicker\"},{\"attributes\":{\"field\":\"angle\",\"include_zero\":true},\"id\":\"9535\",\"type\":\"CumSum\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"9550\"},\"group\":null,\"major_label_policy\":{\"id\":\"9551\"},\"ticker\":{\"id\":\"9514\"},\"visible\":false},\"id\":\"9513\",\"type\":\"LinearAxis\"},{\"attributes\":{\"logo\":null,\"tools\":[{\"id\":\"9521\"},{\"id\":\"9522\"},{\"id\":\"9523\"},{\"id\":\"9524\"},{\"id\":\"9525\"},{\"id\":\"9526\"}]},\"id\":\"9528\",\"type\":\"Toolbar\"},{\"attributes\":{\"axis\":{\"id\":\"9513\"},\"coordinates\":null,\"grid_line_color\":null,\"group\":null,\"ticker\":null},\"id\":\"9516\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"9100\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"9511\",\"type\":\"LinearScale\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9536\"}},\"fill_alpha\":{\"value\":0.8},\"fill_color\":{\"field\":\"color_outer\"},\"inner_radius\":{\"value\":0.0},\"outer_radius\":{\"value\":0.0},\"start_angle\":{\"expr\":{\"id\":\"9535\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9538\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"9507\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"9526\",\"type\":\"SaveTool\"}],\"root_ids\":[\"9502\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n", - " const render_items = [{\"docid\":\"c42bfb72-a732-40ad-a635-08d22ecf266d\",\"root_ids\":[\"9502\"],\"roots\":{\"9502\":\"6f0ca5fa-79de-408a-a705-e5c7b18fa8e3\"}}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"c42bfb72-a732-40ad-a635-08d22ecf266d\":{\"defs\":[{\"extends\":null,\"module\":null,\"name\":\"ReactiveHTML1\",\"overrides\":[],\"properties\":[]},{\"extends\":null,\"module\":null,\"name\":\"FlexBox1\",\"overrides\":[],\"properties\":[{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_content\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_items\"},{\"default\":\"row\",\"kind\":null,\"name\":\"flex_direction\"},{\"default\":\"wrap\",\"kind\":null,\"name\":\"flex_wrap\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"justify_content\"}]},{\"extends\":null,\"module\":null,\"name\":\"GridStack1\",\"overrides\":[],\"properties\":[{\"default\":\"warn\",\"kind\":null,\"name\":\"mode\"},{\"default\":null,\"kind\":null,\"name\":\"ncols\"},{\"default\":null,\"kind\":null,\"name\":\"nrows\"},{\"default\":true,\"kind\":null,\"name\":\"allow_resize\"},{\"default\":true,\"kind\":null,\"name\":\"allow_drag\"},{\"default\":[],\"kind\":null,\"name\":\"state\"}]},{\"extends\":null,\"module\":null,\"name\":\"click1\",\"overrides\":[],\"properties\":[{\"default\":\"\",\"kind\":null,\"name\":\"terminal_output\"},{\"default\":\"\",\"kind\":null,\"name\":\"debug_name\"},{\"default\":0,\"kind\":null,\"name\":\"clears\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationAreaBase1\",\"overrides\":[],\"properties\":[{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationArea1\",\"overrides\":[],\"properties\":[{\"default\":[],\"kind\":null,\"name\":\"notifications\"},{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"},{\"default\":[{\"background\":\"#ffc107\",\"icon\":{\"className\":\"fas fa-exclamation-triangle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"warning\"},{\"background\":\"#007bff\",\"icon\":{\"className\":\"fas fa-info-circle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"info\"}],\"kind\":null,\"name\":\"types\"}]},{\"extends\":null,\"module\":null,\"name\":\"Notification\",\"overrides\":[],\"properties\":[{\"default\":null,\"kind\":null,\"name\":\"background\"},{\"default\":3000,\"kind\":null,\"name\":\"duration\"},{\"default\":null,\"kind\":null,\"name\":\"icon\"},{\"default\":\"\",\"kind\":null,\"name\":\"message\"},{\"default\":null,\"kind\":null,\"name\":\"notification_type\"},{\"default\":false,\"kind\":null,\"name\":\"_destroyed\"}]},{\"extends\":null,\"module\":null,\"name\":\"TemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]},{\"extends\":null,\"module\":null,\"name\":\"MaterialTemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]}],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"9513\"}],\"center\":[{\"id\":\"9516\"},{\"id\":\"9520\"},{\"id\":\"9555\"}],\"left\":[{\"id\":\"9517\"}],\"renderers\":[{\"id\":\"9543\"}],\"title\":{\"id\":\"9503\"},\"toolbar\":{\"id\":\"9528\"},\"toolbar_location\":\"above\",\"x_range\":{\"id\":\"9505\"},\"x_scale\":{\"id\":\"9509\"},\"y_range\":{\"id\":\"9507\"},\"y_scale\":{\"id\":\"9511\"}},\"id\":\"9502\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"field\":\"angle\"},\"id\":\"9536\",\"type\":\"CumSum\"},{\"attributes\":{},\"id\":\"9518\",\"type\":\"BasicTicker\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9536\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"blue\"},\"hatch_alpha\":{\"value\":0.1},\"inner_radius\":{\"value\":0.0},\"line_alpha\":{\"value\":0.5},\"outer_radius\":{\"value\":0.0},\"start_angle\":{\"expr\":{\"id\":\"9535\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9539\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"9525\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"9522\",\"type\":\"WheelZoomTool\"},{\"attributes\":{},\"id\":\"9547\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"source\":{\"id\":\"9048\"}},\"id\":\"9544\",\"type\":\"CDSView\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"Data\",\"@x_value\"],[\"Percent\",\"@percent{0.00%}\"],[\"Count\",\"@count\"]]},\"id\":\"9521\",\"type\":\"HoverTool\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9536\"}},\"fill_color\":{\"field\":\"color_outer\"},\"inner_radius\":{\"value\":0.0},\"line_width\":{\"value\":5.0},\"outer_radius\":{\"value\":0.0},\"start_angle\":{\"expr\":{\"id\":\"9535\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9541\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"overlay\":{\"id\":\"9527\"}},\"id\":\"9523\",\"type\":\"BoxZoomTool\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9536\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"field\":\"color_outer\"},\"hatch_alpha\":{\"value\":0.2},\"inner_radius\":{\"value\":0.0},\"line_alpha\":{\"value\":0.2},\"outer_radius\":{\"value\":0.0},\"start_angle\":{\"expr\":{\"id\":\"9535\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9542\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"data\":{\"All\":[1,97,128,144,224,17,9],\"Chemistry\":[0,0,0,0,0,0,0],\"Cum. Sum\":[1,36,36,63,125,9,4],\"Earth Science\":[1,6,10,18,25,2,0],\"Engineering Science\":[0,30,26,45,100,7,4],\"Life Science\":[0,0,0,0,0,0,0],\"Mathematics\":[0,0,0,0,0,0,0],\"Other\":[0,0,0,0,0,0,0],\"Physics\":[0,0,0,0,0,0,0],\"Psychology\":[0,0,0,0,0,0,0],\"angle\":{\"__ndarray__\":\"5wCiQDnBhD9fifXF2nTvP+cAokA5wfQ/BEG2aGBZ9z/KwI0YEikCQPYgrNRMDcY/BEG2aGBZtz8=\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[7]},\"careerLevel\":[\"Other\",\"PhD candidate\",\"Postdoc\",\"Principal Investigator\",\"Research Associate\",\"Student\",\"Technical Staff\"],\"color_outer\":[\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\"],\"count\":[1,97,128,144,224,17,9],\"index\":[0,1,2,3,4,5,6],\"legend_field\":[\"Total\",\"Total\",\"Total\",\"Total\",\"Total\",\"Total\",\"Total\"],\"percent\":{\"__ndarray__\":\"bRrQpgFtWj8HtGlAmwbEP20a0KYBbco/ux2q26G6zT8fF/ZxYR/XPxQcPcHRE5w/ux2q26G6jT8=\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[7]},\"x_value\":[\"Other\",\"PhD candidate\",\"Postdoc\",\"Principal Investigator\",\"Research Associate\",\"Student\",\"Technical Staff\"]},\"selected\":{\"id\":\"9101\"},\"selection_policy\":{\"id\":\"9100\"}},\"id\":\"9048\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"9524\",\"type\":\"UndoTool\"},{\"attributes\":{},\"id\":\"9548\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"9550\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"bottom_units\":\"screen\",\"coordinates\":null,\"fill_alpha\":0.5,\"fill_color\":\"lightgrey\",\"group\":null,\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":1.0,\"line_color\":\"black\",\"line_dash\":[4,4],\"line_width\":2,\"right_units\":\"screen\",\"syncable\":false,\"top_units\":\"screen\"},\"id\":\"9527\",\"type\":\"BoxAnnotation\"},{\"attributes\":{},\"id\":\"9509\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"items\":[{\"id\":\"9556\"}]},\"id\":\"9555\",\"type\":\"Legend\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9536\"}},\"fill_color\":{\"value\":\"black\"},\"inner_radius\":{\"value\":0.0},\"outer_radius\":{\"value\":0.0},\"start_angle\":{\"expr\":{\"id\":\"9535\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9540\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"9551\",\"type\":\"AllLabels\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"9048\"},\"glyph\":{\"id\":\"9538\"},\"group\":null,\"hover_glyph\":{\"id\":\"9541\"},\"muted_glyph\":{\"id\":\"9542\"},\"nonselection_glyph\":{\"id\":\"9539\"},\"selection_glyph\":{\"id\":\"9540\"},\"view\":{\"id\":\"9544\"}},\"id\":\"9543\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"label\":{\"field\":\"legend_field\"},\"renderers\":[{\"id\":\"9543\"}]},\"id\":\"9556\",\"type\":\"LegendItem\"},{\"attributes\":{},\"id\":\"9505\",\"type\":\"DataRange1d\"},{\"attributes\":{\"axis\":{\"id\":\"9517\"},\"coordinates\":null,\"dimension\":1,\"grid_line_color\":null,\"group\":null,\"ticker\":null},\"id\":\"9520\",\"type\":\"Grid\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"9547\"},\"group\":null,\"major_label_policy\":{\"id\":\"9548\"},\"ticker\":{\"id\":\"9518\"},\"visible\":false},\"id\":\"9517\",\"type\":\"LinearAxis\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"text\":\"Career level of participants.\"},\"id\":\"9503\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"9101\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"9514\",\"type\":\"BasicTicker\"},{\"attributes\":{\"field\":\"angle\",\"include_zero\":true},\"id\":\"9535\",\"type\":\"CumSum\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"9550\"},\"group\":null,\"major_label_policy\":{\"id\":\"9551\"},\"ticker\":{\"id\":\"9514\"},\"visible\":false},\"id\":\"9513\",\"type\":\"LinearAxis\"},{\"attributes\":{\"logo\":null,\"tools\":[{\"id\":\"9521\"},{\"id\":\"9522\"},{\"id\":\"9523\"},{\"id\":\"9524\"},{\"id\":\"9525\"},{\"id\":\"9526\"}]},\"id\":\"9528\",\"type\":\"Toolbar\"},{\"attributes\":{\"axis\":{\"id\":\"9513\"},\"coordinates\":null,\"grid_line_color\":null,\"group\":null,\"ticker\":null},\"id\":\"9516\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"9100\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"9511\",\"type\":\"LinearScale\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"9536\"}},\"fill_alpha\":{\"value\":0.8},\"fill_color\":{\"field\":\"color_outer\"},\"inner_radius\":{\"value\":0.0},\"outer_radius\":{\"value\":0.0},\"start_angle\":{\"expr\":{\"id\":\"9535\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"9538\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"9507\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"9526\",\"type\":\"SaveTool\"}],\"root_ids\":[\"9502\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n const render_items = [{\"docid\":\"c42bfb72-a732-40ad-a635-08d22ecf266d\",\"root_ids\":[\"9502\"],\"roots\":{\"9502\":\"6f0ca5fa-79de-408a-a705-e5c7b18fa8e3\"}}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -8502,32 +7178,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"48f690a9-f159-4686-bbd3-b6d0a7a9c5bd\":{\"defs\":[{\"extends\":null,\"module\":null,\"name\":\"ReactiveHTML1\",\"overrides\":[],\"properties\":[]},{\"extends\":null,\"module\":null,\"name\":\"FlexBox1\",\"overrides\":[],\"properties\":[{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_content\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_items\"},{\"default\":\"row\",\"kind\":null,\"name\":\"flex_direction\"},{\"default\":\"wrap\",\"kind\":null,\"name\":\"flex_wrap\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"justify_content\"}]},{\"extends\":null,\"module\":null,\"name\":\"GridStack1\",\"overrides\":[],\"properties\":[{\"default\":\"warn\",\"kind\":null,\"name\":\"mode\"},{\"default\":null,\"kind\":null,\"name\":\"ncols\"},{\"default\":null,\"kind\":null,\"name\":\"nrows\"},{\"default\":true,\"kind\":null,\"name\":\"allow_resize\"},{\"default\":true,\"kind\":null,\"name\":\"allow_drag\"},{\"default\":[],\"kind\":null,\"name\":\"state\"}]},{\"extends\":null,\"module\":null,\"name\":\"click1\",\"overrides\":[],\"properties\":[{\"default\":\"\",\"kind\":null,\"name\":\"terminal_output\"},{\"default\":\"\",\"kind\":null,\"name\":\"debug_name\"},{\"default\":0,\"kind\":null,\"name\":\"clears\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationAreaBase1\",\"overrides\":[],\"properties\":[{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationArea1\",\"overrides\":[],\"properties\":[{\"default\":[],\"kind\":null,\"name\":\"notifications\"},{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"},{\"default\":[{\"background\":\"#ffc107\",\"icon\":{\"className\":\"fas fa-exclamation-triangle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"warning\"},{\"background\":\"#007bff\",\"icon\":{\"className\":\"fas fa-info-circle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"info\"}],\"kind\":null,\"name\":\"types\"}]},{\"extends\":null,\"module\":null,\"name\":\"Notification\",\"overrides\":[],\"properties\":[{\"default\":null,\"kind\":null,\"name\":\"background\"},{\"default\":3000,\"kind\":null,\"name\":\"duration\"},{\"default\":null,\"kind\":null,\"name\":\"icon\"},{\"default\":\"\",\"kind\":null,\"name\":\"message\"},{\"default\":null,\"kind\":null,\"name\":\"notification_type\"},{\"default\":false,\"kind\":null,\"name\":\"_destroyed\"}]},{\"extends\":null,\"module\":null,\"name\":\"TemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]},{\"extends\":null,\"module\":null,\"name\":\"MaterialTemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]}],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"7383\"}],\"center\":[{\"id\":\"7386\"},{\"id\":\"7390\"},{\"id\":\"7413\"}],\"left\":[{\"id\":\"7387\"}],\"renderers\":[{\"id\":\"7402\"},{\"id\":\"7423\"}],\"title\":{\"id\":\"7373\"},\"toolbar\":{\"id\":\"7392\"},\"toolbar_location\":\"above\",\"x_range\":{\"id\":\"7375\"},\"x_scale\":{\"id\":\"7379\"},\"y_range\":{\"id\":\"7377\"},\"y_scale\":{\"id\":\"7381\"}},\"id\":\"7372\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"field\":\"angle\"},\"id\":\"7416\",\"type\":\"CumSum\"},{\"attributes\":{\"data\":{\"All\":[1,97,128,144,224,17,9],\"Chemistry\":[0,0,0,0,0,0,0],\"Cum. Sum\":[1,36,36,63,125,9,4],\"Earth Science\":[1,6,10,18,25,2,0],\"Engineering Science\":[0,30,26,45,100,7,4],\"Life Science\":[0,0,0,0,0,0,0],\"Mathematics\":[0,0,0,0,0,0,0],\"Other\":[0,0,0,0,0,0,0],\"Physics\":[0,0,0,0,0,0,0],\"Psychology\":[0,0,0,0,0,0,0],\"angle\":{\"__ndarray__\":\"LdQ9uU97lz+zjmWwuWrqP7OOZbC5auo/3NxYemId9z80Yebaa+4GQLOOZbC5aso/LdQ9uU97tz8=\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[7]},\"careerLevel\":[\"Other\",\"PhD candidate\",\"Postdoc\",\"Principal Investigator\",\"Research Associate\",\"Student\",\"Technical Staff\"],\"color_outer\":[\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\"],\"count\":[1,36,36,63,125,9,4],\"index\":[0,1,2,3,4,5,6],\"legend_field\":[\"Total\",\"Total\",\"Total\",\"Total\",\"Total\",\"Total\",\"Total\"],\"percent\":{\"__ndarray__\":\"iob449blbT+uyzvgSNHAP67LO+BI0cA/cKRoiD9uzT9js6DaczLdP67LO+BI0aA/iob449bljT8=\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[7]},\"x_value\":[\"Other\",\"PhD candidate\",\"Postdoc\",\"Principal Investigator\",\"Research Associate\",\"Student\",\"Technical Staff\"]},\"selected\":{\"id\":\"7036\"},\"selection_policy\":{\"id\":\"7035\"}},\"id\":\"6994\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7395\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"blue\"},\"hatch_alpha\":{\"value\":0.1},\"inner_radius\":{\"value\":0.0},\"line_alpha\":{\"value\":0.5},\"outer_radius\":{\"value\":0.5},\"start_angle\":{\"expr\":{\"id\":\"7394\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7398\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"source\":{\"id\":\"7371\"}},\"id\":\"7424\",\"type\":\"CDSView\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"items\":[{\"id\":\"7414\"},{\"id\":\"7436\"}]},\"id\":\"7413\",\"type\":\"Legend\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7416\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"field\":\"color\"},\"hatch_alpha\":{\"value\":0.2},\"inner_radius\":{\"value\":0.5},\"line_alpha\":{\"value\":0.2},\"outer_radius\":{\"value\":0.8},\"start_angle\":{\"expr\":{\"id\":\"7415\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7422\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7395\"}},\"fill_color\":{\"field\":\"color_outer\"},\"inner_radius\":{\"value\":0.0},\"line_width\":{\"value\":5.0},\"outer_radius\":{\"value\":0.5},\"start_angle\":{\"expr\":{\"id\":\"7394\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7400\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"field\":\"angle\",\"include_zero\":true},\"id\":\"7394\",\"type\":\"CumSum\"},{\"attributes\":{},\"id\":\"7409\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"7375\",\"type\":\"DataRange1d\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7395\"}},\"fill_color\":{\"value\":\"black\"},\"inner_radius\":{\"value\":0.0},\"outer_radius\":{\"value\":0.5},\"start_angle\":{\"expr\":{\"id\":\"7394\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7399\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"7406\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7395\"}},\"fill_alpha\":{\"value\":0.8},\"fill_color\":{\"field\":\"color_outer\"},\"inner_radius\":{\"value\":0.0},\"outer_radius\":{\"value\":0.5},\"start_angle\":{\"expr\":{\"id\":\"7394\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7397\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"axis\":{\"id\":\"7387\"},\"coordinates\":null,\"dimension\":1,\"grid_line_color\":null,\"group\":null,\"ticker\":null},\"id\":\"7390\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"7410\",\"type\":\"AllLabels\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"7371\"},\"glyph\":{\"id\":\"7418\"},\"group\":null,\"hover_glyph\":{\"id\":\"7421\"},\"muted_glyph\":{\"id\":\"7422\"},\"nonselection_glyph\":{\"id\":\"7419\"},\"selection_glyph\":{\"id\":\"7420\"},\"view\":{\"id\":\"7424\"}},\"id\":\"7423\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"axis\":{\"id\":\"7383\"},\"coordinates\":null,\"grid_line_color\":null,\"group\":null,\"ticker\":null},\"id\":\"7386\",\"type\":\"Grid\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7395\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"field\":\"color_outer\"},\"hatch_alpha\":{\"value\":0.2},\"inner_radius\":{\"value\":0.0},\"line_alpha\":{\"value\":0.2},\"outer_radius\":{\"value\":0.5},\"start_angle\":{\"expr\":{\"id\":\"7394\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7401\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"label\":{\"field\":\"labels\"},\"renderers\":[{\"id\":\"7423\"}]},\"id\":\"7436\",\"type\":\"LegendItem\"},{\"attributes\":{},\"id\":\"7381\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"7406\"},\"group\":null,\"major_label_policy\":{\"id\":\"7407\"},\"ticker\":{\"id\":\"7388\"},\"visible\":false},\"id\":\"7387\",\"type\":\"LinearAxis\"},{\"attributes\":{\"logo\":null,\"tools\":[{\"id\":\"7391\"}]},\"id\":\"7392\",\"type\":\"Toolbar\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"Data\",\"@x_value\"],[\"Percent\",\"@percent{0.00%}\"],[\"Count\",\"@count\"]]},\"id\":\"7391\",\"type\":\"HoverTool\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"text\":\"Career level of participants.\"},\"id\":\"7373\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"7435\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"7384\",\"type\":\"BasicTicker\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"6994\"},\"glyph\":{\"id\":\"7397\"},\"group\":null,\"hover_glyph\":{\"id\":\"7400\"},\"muted_glyph\":{\"id\":\"7401\"},\"nonselection_glyph\":{\"id\":\"7398\"},\"selection_glyph\":{\"id\":\"7399\"},\"view\":{\"id\":\"7403\"}},\"id\":\"7402\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"label\":{\"field\":\"legend_field\"},\"renderers\":[{\"id\":\"7402\"}]},\"id\":\"7414\",\"type\":\"LegendItem\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"7409\"},\"group\":null,\"major_label_policy\":{\"id\":\"7410\"},\"ticker\":{\"id\":\"7384\"},\"visible\":false},\"id\":\"7383\",\"type\":\"LinearAxis\"},{\"attributes\":{\"source\":{\"id\":\"6994\"}},\"id\":\"7403\",\"type\":\"CDSView\"},{\"attributes\":{\"field\":\"angle\"},\"id\":\"7395\",\"type\":\"CumSum\"},{\"attributes\":{},\"id\":\"7379\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"7035\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"7036\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"7377\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"7434\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7416\"}},\"fill_color\":{\"field\":\"color\"},\"inner_radius\":{\"value\":0.5},\"line_width\":{\"value\":5.0},\"outer_radius\":{\"value\":0.8},\"start_angle\":{\"expr\":{\"id\":\"7415\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7421\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"7407\",\"type\":\"AllLabels\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7416\"}},\"fill_alpha\":{\"value\":0.8},\"fill_color\":{\"field\":\"color\"},\"inner_radius\":{\"value\":0.5},\"outer_radius\":{\"value\":0.8},\"start_angle\":{\"expr\":{\"id\":\"7415\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7418\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"field\":\"angle\",\"include_zero\":true},\"id\":\"7415\",\"type\":\"CumSum\"},{\"attributes\":{},\"id\":\"7388\",\"type\":\"BasicTicker\"},{\"attributes\":{\"data\":{\"angle\":{\"__ndarray__\":\"LdQ9uU97lz8AAAAAAAAAACJf7sp7nME/6vapvZoD5j83SY2nI1rNP2Q8gsYwFOM/s45lsLlq2j8veT8OtILwP8NNuEhWWOI/w024SFZYAkAt1D25T3unP6cZFsLli8Q/AAAAAAAAAAAt1D25T3u3Pw==\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[14]},\"color\":[\"#3182bd\",\"#c6dbef\",\"#3182bd\",\"#c6dbef\",\"#3182bd\",\"#c6dbef\",\"#3182bd\",\"#c6dbef\",\"#3182bd\",\"#c6dbef\",\"#3182bd\",\"#c6dbef\",\"#3182bd\",\"#c6dbef\"],\"count\":[1,0,6,30,10,26,18,45,25,100,2,7,0,4],\"labels\":[\"Earth Science\",\"Engineering Science\",\"Earth Science\",\"Engineering Science\",\"Earth Science\",\"Engineering Science\",\"Earth Science\",\"Engineering Science\",\"Earth Science\",\"Engineering Science\",\"Earth Science\",\"Engineering Science\",\"Earth Science\",\"Engineering Science\"],\"percent\":{\"__ndarray__\":\"iob449blbT8AAAAAAAAAAOhk+iphbJY/Iv64dXkHvD8WVHtOpq+iP1DtOZm+Srg/rss74EjRsD+ZvkoYmwXFPxwpGuKPW7c/HCka4o9b1z+Khvjj1uV9P7l1eQccKZo/AAAAAAAAAACKhvjj1uWNPw==\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[14]},\"x_value\":[\"Other, Earth Science\",\"Other, Engineering Science\",\"PhD candidate, Earth Science\",\"PhD candidate, Engineering Science\",\"Postdoc, Earth Science\",\"Postdoc, Engineering Science\",\"Principal Investigator, Earth Science\",\"Principal Investigator, Engineering Science\",\"Research Associate, Earth Science\",\"Research Associate, Engineering Science\",\"Student, Earth Science\",\"Student, Engineering Science\",\"Technical Staff, Earth Science\",\"Technical Staff, Engineering Science\"]},\"selected\":{\"id\":\"7435\"},\"selection_policy\":{\"id\":\"7434\"}},\"id\":\"7371\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7416\"}},\"fill_color\":{\"value\":\"black\"},\"inner_radius\":{\"value\":0.5},\"outer_radius\":{\"value\":0.8},\"start_angle\":{\"expr\":{\"id\":\"7415\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7420\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7416\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"blue\"},\"hatch_alpha\":{\"value\":0.1},\"inner_radius\":{\"value\":0.5},\"line_alpha\":{\"value\":0.5},\"outer_radius\":{\"value\":0.8},\"start_angle\":{\"expr\":{\"id\":\"7415\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7419\",\"type\":\"AnnularWedge\"}],\"root_ids\":[\"7372\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n", - " const render_items = [{\"docid\":\"48f690a9-f159-4686-bbd3-b6d0a7a9c5bd\",\"root_ids\":[\"7372\"],\"roots\":{\"7372\":\"4137feca-db1a-4e1c-9b8d-c3b0ea883fc6\"}}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"48f690a9-f159-4686-bbd3-b6d0a7a9c5bd\":{\"defs\":[{\"extends\":null,\"module\":null,\"name\":\"ReactiveHTML1\",\"overrides\":[],\"properties\":[]},{\"extends\":null,\"module\":null,\"name\":\"FlexBox1\",\"overrides\":[],\"properties\":[{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_content\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_items\"},{\"default\":\"row\",\"kind\":null,\"name\":\"flex_direction\"},{\"default\":\"wrap\",\"kind\":null,\"name\":\"flex_wrap\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"justify_content\"}]},{\"extends\":null,\"module\":null,\"name\":\"GridStack1\",\"overrides\":[],\"properties\":[{\"default\":\"warn\",\"kind\":null,\"name\":\"mode\"},{\"default\":null,\"kind\":null,\"name\":\"ncols\"},{\"default\":null,\"kind\":null,\"name\":\"nrows\"},{\"default\":true,\"kind\":null,\"name\":\"allow_resize\"},{\"default\":true,\"kind\":null,\"name\":\"allow_drag\"},{\"default\":[],\"kind\":null,\"name\":\"state\"}]},{\"extends\":null,\"module\":null,\"name\":\"click1\",\"overrides\":[],\"properties\":[{\"default\":\"\",\"kind\":null,\"name\":\"terminal_output\"},{\"default\":\"\",\"kind\":null,\"name\":\"debug_name\"},{\"default\":0,\"kind\":null,\"name\":\"clears\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationAreaBase1\",\"overrides\":[],\"properties\":[{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationArea1\",\"overrides\":[],\"properties\":[{\"default\":[],\"kind\":null,\"name\":\"notifications\"},{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"},{\"default\":[{\"background\":\"#ffc107\",\"icon\":{\"className\":\"fas fa-exclamation-triangle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"warning\"},{\"background\":\"#007bff\",\"icon\":{\"className\":\"fas fa-info-circle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"info\"}],\"kind\":null,\"name\":\"types\"}]},{\"extends\":null,\"module\":null,\"name\":\"Notification\",\"overrides\":[],\"properties\":[{\"default\":null,\"kind\":null,\"name\":\"background\"},{\"default\":3000,\"kind\":null,\"name\":\"duration\"},{\"default\":null,\"kind\":null,\"name\":\"icon\"},{\"default\":\"\",\"kind\":null,\"name\":\"message\"},{\"default\":null,\"kind\":null,\"name\":\"notification_type\"},{\"default\":false,\"kind\":null,\"name\":\"_destroyed\"}]},{\"extends\":null,\"module\":null,\"name\":\"TemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]},{\"extends\":null,\"module\":null,\"name\":\"MaterialTemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]}],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"7383\"}],\"center\":[{\"id\":\"7386\"},{\"id\":\"7390\"},{\"id\":\"7413\"}],\"left\":[{\"id\":\"7387\"}],\"renderers\":[{\"id\":\"7402\"},{\"id\":\"7423\"}],\"title\":{\"id\":\"7373\"},\"toolbar\":{\"id\":\"7392\"},\"toolbar_location\":\"above\",\"x_range\":{\"id\":\"7375\"},\"x_scale\":{\"id\":\"7379\"},\"y_range\":{\"id\":\"7377\"},\"y_scale\":{\"id\":\"7381\"}},\"id\":\"7372\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"field\":\"angle\"},\"id\":\"7416\",\"type\":\"CumSum\"},{\"attributes\":{\"data\":{\"All\":[1,97,128,144,224,17,9],\"Chemistry\":[0,0,0,0,0,0,0],\"Cum. Sum\":[1,36,36,63,125,9,4],\"Earth Science\":[1,6,10,18,25,2,0],\"Engineering Science\":[0,30,26,45,100,7,4],\"Life Science\":[0,0,0,0,0,0,0],\"Mathematics\":[0,0,0,0,0,0,0],\"Other\":[0,0,0,0,0,0,0],\"Physics\":[0,0,0,0,0,0,0],\"Psychology\":[0,0,0,0,0,0,0],\"angle\":{\"__ndarray__\":\"LdQ9uU97lz+zjmWwuWrqP7OOZbC5auo/3NxYemId9z80Yebaa+4GQLOOZbC5aso/LdQ9uU97tz8=\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[7]},\"careerLevel\":[\"Other\",\"PhD candidate\",\"Postdoc\",\"Principal Investigator\",\"Research Associate\",\"Student\",\"Technical Staff\"],\"color_outer\":[\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\",\"#3182bd\"],\"count\":[1,36,36,63,125,9,4],\"index\":[0,1,2,3,4,5,6],\"legend_field\":[\"Total\",\"Total\",\"Total\",\"Total\",\"Total\",\"Total\",\"Total\"],\"percent\":{\"__ndarray__\":\"iob449blbT+uyzvgSNHAP67LO+BI0cA/cKRoiD9uzT9js6DaczLdP67LO+BI0aA/iob449bljT8=\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[7]},\"x_value\":[\"Other\",\"PhD candidate\",\"Postdoc\",\"Principal Investigator\",\"Research Associate\",\"Student\",\"Technical Staff\"]},\"selected\":{\"id\":\"7036\"},\"selection_policy\":{\"id\":\"7035\"}},\"id\":\"6994\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7395\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"blue\"},\"hatch_alpha\":{\"value\":0.1},\"inner_radius\":{\"value\":0.0},\"line_alpha\":{\"value\":0.5},\"outer_radius\":{\"value\":0.5},\"start_angle\":{\"expr\":{\"id\":\"7394\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7398\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"source\":{\"id\":\"7371\"}},\"id\":\"7424\",\"type\":\"CDSView\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"items\":[{\"id\":\"7414\"},{\"id\":\"7436\"}]},\"id\":\"7413\",\"type\":\"Legend\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7416\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"field\":\"color\"},\"hatch_alpha\":{\"value\":0.2},\"inner_radius\":{\"value\":0.5},\"line_alpha\":{\"value\":0.2},\"outer_radius\":{\"value\":0.8},\"start_angle\":{\"expr\":{\"id\":\"7415\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7422\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7395\"}},\"fill_color\":{\"field\":\"color_outer\"},\"inner_radius\":{\"value\":0.0},\"line_width\":{\"value\":5.0},\"outer_radius\":{\"value\":0.5},\"start_angle\":{\"expr\":{\"id\":\"7394\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7400\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"field\":\"angle\",\"include_zero\":true},\"id\":\"7394\",\"type\":\"CumSum\"},{\"attributes\":{},\"id\":\"7409\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"7375\",\"type\":\"DataRange1d\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7395\"}},\"fill_color\":{\"value\":\"black\"},\"inner_radius\":{\"value\":0.0},\"outer_radius\":{\"value\":0.5},\"start_angle\":{\"expr\":{\"id\":\"7394\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7399\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"7406\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7395\"}},\"fill_alpha\":{\"value\":0.8},\"fill_color\":{\"field\":\"color_outer\"},\"inner_radius\":{\"value\":0.0},\"outer_radius\":{\"value\":0.5},\"start_angle\":{\"expr\":{\"id\":\"7394\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7397\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"axis\":{\"id\":\"7387\"},\"coordinates\":null,\"dimension\":1,\"grid_line_color\":null,\"group\":null,\"ticker\":null},\"id\":\"7390\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"7410\",\"type\":\"AllLabels\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"7371\"},\"glyph\":{\"id\":\"7418\"},\"group\":null,\"hover_glyph\":{\"id\":\"7421\"},\"muted_glyph\":{\"id\":\"7422\"},\"nonselection_glyph\":{\"id\":\"7419\"},\"selection_glyph\":{\"id\":\"7420\"},\"view\":{\"id\":\"7424\"}},\"id\":\"7423\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"axis\":{\"id\":\"7383\"},\"coordinates\":null,\"grid_line_color\":null,\"group\":null,\"ticker\":null},\"id\":\"7386\",\"type\":\"Grid\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7395\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"field\":\"color_outer\"},\"hatch_alpha\":{\"value\":0.2},\"inner_radius\":{\"value\":0.0},\"line_alpha\":{\"value\":0.2},\"outer_radius\":{\"value\":0.5},\"start_angle\":{\"expr\":{\"id\":\"7394\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7401\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"label\":{\"field\":\"labels\"},\"renderers\":[{\"id\":\"7423\"}]},\"id\":\"7436\",\"type\":\"LegendItem\"},{\"attributes\":{},\"id\":\"7381\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"7406\"},\"group\":null,\"major_label_policy\":{\"id\":\"7407\"},\"ticker\":{\"id\":\"7388\"},\"visible\":false},\"id\":\"7387\",\"type\":\"LinearAxis\"},{\"attributes\":{\"logo\":null,\"tools\":[{\"id\":\"7391\"}]},\"id\":\"7392\",\"type\":\"Toolbar\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"Data\",\"@x_value\"],[\"Percent\",\"@percent{0.00%}\"],[\"Count\",\"@count\"]]},\"id\":\"7391\",\"type\":\"HoverTool\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"text\":\"Career level of participants.\"},\"id\":\"7373\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"7435\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"7384\",\"type\":\"BasicTicker\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"6994\"},\"glyph\":{\"id\":\"7397\"},\"group\":null,\"hover_glyph\":{\"id\":\"7400\"},\"muted_glyph\":{\"id\":\"7401\"},\"nonselection_glyph\":{\"id\":\"7398\"},\"selection_glyph\":{\"id\":\"7399\"},\"view\":{\"id\":\"7403\"}},\"id\":\"7402\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"label\":{\"field\":\"legend_field\"},\"renderers\":[{\"id\":\"7402\"}]},\"id\":\"7414\",\"type\":\"LegendItem\"},{\"attributes\":{\"coordinates\":null,\"formatter\":{\"id\":\"7409\"},\"group\":null,\"major_label_policy\":{\"id\":\"7410\"},\"ticker\":{\"id\":\"7384\"},\"visible\":false},\"id\":\"7383\",\"type\":\"LinearAxis\"},{\"attributes\":{\"source\":{\"id\":\"6994\"}},\"id\":\"7403\",\"type\":\"CDSView\"},{\"attributes\":{\"field\":\"angle\"},\"id\":\"7395\",\"type\":\"CumSum\"},{\"attributes\":{},\"id\":\"7379\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"7035\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"7036\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"7377\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"7434\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7416\"}},\"fill_color\":{\"field\":\"color\"},\"inner_radius\":{\"value\":0.5},\"line_width\":{\"value\":5.0},\"outer_radius\":{\"value\":0.8},\"start_angle\":{\"expr\":{\"id\":\"7415\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7421\",\"type\":\"AnnularWedge\"},{\"attributes\":{},\"id\":\"7407\",\"type\":\"AllLabels\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7416\"}},\"fill_alpha\":{\"value\":0.8},\"fill_color\":{\"field\":\"color\"},\"inner_radius\":{\"value\":0.5},\"outer_radius\":{\"value\":0.8},\"start_angle\":{\"expr\":{\"id\":\"7415\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7418\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"field\":\"angle\",\"include_zero\":true},\"id\":\"7415\",\"type\":\"CumSum\"},{\"attributes\":{},\"id\":\"7388\",\"type\":\"BasicTicker\"},{\"attributes\":{\"data\":{\"angle\":{\"__ndarray__\":\"LdQ9uU97lz8AAAAAAAAAACJf7sp7nME/6vapvZoD5j83SY2nI1rNP2Q8gsYwFOM/s45lsLlq2j8veT8OtILwP8NNuEhWWOI/w024SFZYAkAt1D25T3unP6cZFsLli8Q/AAAAAAAAAAAt1D25T3u3Pw==\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[14]},\"color\":[\"#3182bd\",\"#c6dbef\",\"#3182bd\",\"#c6dbef\",\"#3182bd\",\"#c6dbef\",\"#3182bd\",\"#c6dbef\",\"#3182bd\",\"#c6dbef\",\"#3182bd\",\"#c6dbef\",\"#3182bd\",\"#c6dbef\"],\"count\":[1,0,6,30,10,26,18,45,25,100,2,7,0,4],\"labels\":[\"Earth Science\",\"Engineering Science\",\"Earth Science\",\"Engineering Science\",\"Earth Science\",\"Engineering Science\",\"Earth Science\",\"Engineering Science\",\"Earth Science\",\"Engineering Science\",\"Earth Science\",\"Engineering Science\",\"Earth Science\",\"Engineering Science\"],\"percent\":{\"__ndarray__\":\"iob449blbT8AAAAAAAAAAOhk+iphbJY/Iv64dXkHvD8WVHtOpq+iP1DtOZm+Srg/rss74EjRsD+ZvkoYmwXFPxwpGuKPW7c/HCka4o9b1z+Khvjj1uV9P7l1eQccKZo/AAAAAAAAAACKhvjj1uWNPw==\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[14]},\"x_value\":[\"Other, Earth Science\",\"Other, Engineering Science\",\"PhD candidate, Earth Science\",\"PhD candidate, Engineering Science\",\"Postdoc, Earth Science\",\"Postdoc, Engineering Science\",\"Principal Investigator, Earth Science\",\"Principal Investigator, Engineering Science\",\"Research Associate, Earth Science\",\"Research Associate, Engineering Science\",\"Student, Earth Science\",\"Student, Engineering Science\",\"Technical Staff, Earth Science\",\"Technical Staff, Engineering Science\"]},\"selected\":{\"id\":\"7435\"},\"selection_policy\":{\"id\":\"7434\"}},\"id\":\"7371\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7416\"}},\"fill_color\":{\"value\":\"black\"},\"inner_radius\":{\"value\":0.5},\"outer_radius\":{\"value\":0.8},\"start_angle\":{\"expr\":{\"id\":\"7415\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7420\",\"type\":\"AnnularWedge\"},{\"attributes\":{\"end_angle\":{\"expr\":{\"id\":\"7416\"}},\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"blue\"},\"hatch_alpha\":{\"value\":0.1},\"inner_radius\":{\"value\":0.5},\"line_alpha\":{\"value\":0.5},\"outer_radius\":{\"value\":0.8},\"start_angle\":{\"expr\":{\"id\":\"7415\"}},\"x\":{\"value\":0},\"y\":{\"value\":1}},\"id\":\"7419\",\"type\":\"AnnularWedge\"}],\"root_ids\":[\"7372\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n const render_items = [{\"docid\":\"48f690a9-f159-4686-bbd3-b6d0a7a9c5bd\",\"root_ids\":[\"7372\"],\"roots\":{\"7372\":\"4137feca-db1a-4e1c-9b8d-c3b0ea883fc6\"}}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -9781,32 +8432,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"4b6d8204-639d-4b87-8837-2f46c7788fbf\":{\"defs\":[{\"extends\":null,\"module\":null,\"name\":\"ReactiveHTML1\",\"overrides\":[],\"properties\":[]},{\"extends\":null,\"module\":null,\"name\":\"FlexBox1\",\"overrides\":[],\"properties\":[{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_content\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_items\"},{\"default\":\"row\",\"kind\":null,\"name\":\"flex_direction\"},{\"default\":\"wrap\",\"kind\":null,\"name\":\"flex_wrap\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"justify_content\"}]},{\"extends\":null,\"module\":null,\"name\":\"GridStack1\",\"overrides\":[],\"properties\":[{\"default\":\"warn\",\"kind\":null,\"name\":\"mode\"},{\"default\":null,\"kind\":null,\"name\":\"ncols\"},{\"default\":null,\"kind\":null,\"name\":\"nrows\"},{\"default\":true,\"kind\":null,\"name\":\"allow_resize\"},{\"default\":true,\"kind\":null,\"name\":\"allow_drag\"},{\"default\":[],\"kind\":null,\"name\":\"state\"}]},{\"extends\":null,\"module\":null,\"name\":\"click1\",\"overrides\":[],\"properties\":[{\"default\":\"\",\"kind\":null,\"name\":\"terminal_output\"},{\"default\":\"\",\"kind\":null,\"name\":\"debug_name\"},{\"default\":0,\"kind\":null,\"name\":\"clears\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationAreaBase1\",\"overrides\":[],\"properties\":[{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationArea1\",\"overrides\":[],\"properties\":[{\"default\":[],\"kind\":null,\"name\":\"notifications\"},{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"},{\"default\":[{\"background\":\"#ffc107\",\"icon\":{\"className\":\"fas fa-exclamation-triangle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"warning\"},{\"background\":\"#007bff\",\"icon\":{\"className\":\"fas fa-info-circle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"info\"}],\"kind\":null,\"name\":\"types\"}]},{\"extends\":null,\"module\":null,\"name\":\"Notification\",\"overrides\":[],\"properties\":[{\"default\":null,\"kind\":null,\"name\":\"background\"},{\"default\":3000,\"kind\":null,\"name\":\"duration\"},{\"default\":null,\"kind\":null,\"name\":\"icon\"},{\"default\":\"\",\"kind\":null,\"name\":\"message\"},{\"default\":null,\"kind\":null,\"name\":\"notification_type\"},{\"default\":false,\"kind\":null,\"name\":\"_destroyed\"}]},{\"extends\":null,\"module\":null,\"name\":\"TemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]},{\"extends\":null,\"module\":null,\"name\":\"MaterialTemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]}],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"10366\"}],\"center\":[{\"id\":\"10368\"},{\"id\":\"10371\"}],\"left\":[{\"id\":\"10369\"}],\"outline_line_color\":null,\"renderers\":[{\"id\":\"10391\"}],\"title\":{\"id\":\"10356\"},\"toolbar\":{\"id\":\"10379\"},\"x_range\":{\"id\":\"10358\"},\"x_scale\":{\"id\":\"10362\"},\"y_range\":{\"id\":\"10360\"},\"y_scale\":{\"id\":\"10364\"}},\"id\":\"10355\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{},\"id\":\"10364\",\"type\":\"CategoricalScale\"},{\"attributes\":{},\"id\":\"10375\",\"type\":\"UndoTool\"},{\"attributes\":{\"source\":{\"id\":\"10354\"}},\"id\":\"10392\",\"type\":\"CDSView\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"orcid\",\"@x_values\"],[\"docStructured\",\"@y_values\"],[\"total\",\"@total\"],[\"percentage\",\"@percentage\"]]},\"id\":\"10372\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"10734\",\"type\":\"Selection\"},{\"attributes\":{\"axis\":{\"id\":\"10369\"},\"coordinates\":null,\"dimension\":1,\"group\":null,\"ticker\":null},\"id\":\"10371\",\"type\":\"Grid\"},{\"attributes\":{\"bottom_units\":\"screen\",\"coordinates\":null,\"fill_alpha\":0.5,\"fill_color\":\"lightgrey\",\"group\":null,\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":1.0,\"line_color\":\"black\",\"line_dash\":[4,4],\"line_width\":2,\"right_units\":\"screen\",\"syncable\":false,\"top_units\":\"screen\"},\"id\":\"10378\",\"type\":\"BoxAnnotation\"},{\"attributes\":{\"factors\":[\"Yes\",\"No\",\"Not sure\"]},\"id\":\"10358\",\"type\":\"FactorRange\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.6},\"fill_color\":{\"field\":\"color\"},\"hatch_alpha\":{\"value\":0.6},\"line_alpha\":{\"value\":0.6},\"line_color\":{\"field\":\"color\"},\"size\":{\"field\":\"markersize\"},\"x\":{\"field\":\"x_values\"},\"y\":{\"field\":\"y_values\"}},\"id\":\"10387\",\"type\":\"Circle\"},{\"attributes\":{\"axis_label\":\"\",\"axis_line_alpha\":0,\"coordinates\":null,\"formatter\":{\"id\":\"10731\"},\"group\":null,\"major_label_orientation\":1,\"major_label_policy\":{\"id\":\"10732\"},\"ticker\":{\"id\":\"10367\"}},\"id\":\"10366\",\"type\":\"CategoricalAxis\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"field\":\"color\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"field\":\"color\"},\"size\":{\"field\":\"markersize\"},\"x\":{\"field\":\"x_values\"},\"y\":{\"field\":\"y_values\"}},\"id\":\"10388\",\"type\":\"Circle\"},{\"attributes\":{},\"id\":\"10728\",\"type\":\"CategoricalTickFormatter\"},{\"attributes\":{\"fill_color\":{\"field\":\"color\"},\"line_width\":{\"value\":5},\"size\":{\"field\":\"markersize\"},\"x\":{\"field\":\"x_values\"},\"y\":{\"field\":\"y_values\"}},\"id\":\"10389\",\"type\":\"Circle\"},{\"attributes\":{},\"id\":\"10729\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"10731\",\"type\":\"CategoricalTickFormatter\"},{\"attributes\":{},\"id\":\"10376\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"10373\",\"type\":\"WheelZoomTool\"},{\"attributes\":{},\"id\":\"10370\",\"type\":\"CategoricalTicker\"},{\"attributes\":{\"factors\":[\"Yes\",\"No\",\"Not sure\"]},\"id\":\"10360\",\"type\":\"FactorRange\"},{\"attributes\":{},\"id\":\"10732\",\"type\":\"AllLabels\"},{\"attributes\":{\"data\":{\"color\":[\"#A0235A\",\"#A0235A\",\"#A0235A\",\"#A0235A\",\"#A0235A\",\"#A0235A\",\"#A0235A\",\"#A0235A\",\"#A0235A\"],\"docStructured\":[\"No\",\"No\",\"No\",\"Not sure\",\"Not sure\",\"Not sure\",\"Yes\",\"Yes\",\"Yes\"],\"index\":[0,1,2,3,4,5,6,7,8],\"markersize\":[32.57350079,37.6126389,33.31124334,14.56731241,16.82088348,24.4437699,35.68248232,29.13462482,28.97140434],\"orcid\":[\"No\",\"Not sure\",\"Yes\",\"No\",\"Not sure\",\"Yes\",\"No\",\"Not sure\",\"Yes\"],\"percentage\":[41.66666667,55.55555556,43.57541899,8.33333333,11.11111111,23.46368715,50.0,33.33333333,32.96089385],\"total\":[36,9,179,36,9,179,36,9,179],\"value\":[15,5,78,3,1,42,18,3,59],\"x_values\":[\"No\",\"Not sure\",\"Yes\",\"No\",\"Not sure\",\"Yes\",\"No\",\"Not sure\",\"Yes\"],\"y_values\":[\"No\",\"No\",\"No\",\"Not sure\",\"Not sure\",\"Not sure\",\"Yes\",\"Yes\",\"Yes\"]},\"selected\":{\"id\":\"10734\"},\"selection_policy\":{\"id\":\"10733\"}},\"id\":\"10354\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"field\":\"color\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"field\":\"color\"},\"size\":{\"field\":\"markersize\"},\"x\":{\"field\":\"x_values\"},\"y\":{\"field\":\"y_values\"}},\"id\":\"10390\",\"type\":\"Circle\"},{\"attributes\":{\"tools\":[{\"id\":\"10372\"},{\"id\":\"10373\"},{\"id\":\"10374\"},{\"id\":\"10375\"},{\"id\":\"10376\"},{\"id\":\"10377\"}]},\"id\":\"10379\",\"type\":\"Toolbar\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10354\"},\"glyph\":{\"id\":\"10387\"},\"group\":null,\"hover_glyph\":{\"id\":\"10389\"},\"muted_glyph\":{\"id\":\"10390\"},\"nonselection_glyph\":{\"id\":\"10388\"},\"view\":{\"id\":\"10392\"}},\"id\":\"10391\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"10733\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"text\":\"orcid in dependence to docStructured\"},\"id\":\"10356\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"10367\",\"type\":\"CategoricalTicker\"},{\"attributes\":{\"overlay\":{\"id\":\"10378\"}},\"id\":\"10374\",\"type\":\"BoxZoomTool\"},{\"attributes\":{\"axis_label\":\"\",\"axis_line_alpha\":0,\"coordinates\":null,\"formatter\":{\"id\":\"10728\"},\"group\":null,\"major_label_policy\":{\"id\":\"10729\"},\"ticker\":{\"id\":\"10370\"}},\"id\":\"10369\",\"type\":\"CategoricalAxis\"},{\"attributes\":{\"axis\":{\"id\":\"10366\"},\"coordinates\":null,\"group\":null,\"ticker\":null},\"id\":\"10368\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"10377\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"10362\",\"type\":\"CategoricalScale\"}],\"root_ids\":[\"10355\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n", - " const render_items = [{\"docid\":\"4b6d8204-639d-4b87-8837-2f46c7788fbf\",\"root_ids\":[\"10355\"],\"roots\":{\"10355\":\"0936b2a9-e82e-418e-a13a-33f18d7de812\"}}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"4b6d8204-639d-4b87-8837-2f46c7788fbf\":{\"defs\":[{\"extends\":null,\"module\":null,\"name\":\"ReactiveHTML1\",\"overrides\":[],\"properties\":[]},{\"extends\":null,\"module\":null,\"name\":\"FlexBox1\",\"overrides\":[],\"properties\":[{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_content\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"align_items\"},{\"default\":\"row\",\"kind\":null,\"name\":\"flex_direction\"},{\"default\":\"wrap\",\"kind\":null,\"name\":\"flex_wrap\"},{\"default\":\"flex-start\",\"kind\":null,\"name\":\"justify_content\"}]},{\"extends\":null,\"module\":null,\"name\":\"GridStack1\",\"overrides\":[],\"properties\":[{\"default\":\"warn\",\"kind\":null,\"name\":\"mode\"},{\"default\":null,\"kind\":null,\"name\":\"ncols\"},{\"default\":null,\"kind\":null,\"name\":\"nrows\"},{\"default\":true,\"kind\":null,\"name\":\"allow_resize\"},{\"default\":true,\"kind\":null,\"name\":\"allow_drag\"},{\"default\":[],\"kind\":null,\"name\":\"state\"}]},{\"extends\":null,\"module\":null,\"name\":\"click1\",\"overrides\":[],\"properties\":[{\"default\":\"\",\"kind\":null,\"name\":\"terminal_output\"},{\"default\":\"\",\"kind\":null,\"name\":\"debug_name\"},{\"default\":0,\"kind\":null,\"name\":\"clears\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationAreaBase1\",\"overrides\":[],\"properties\":[{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"}]},{\"extends\":null,\"module\":null,\"name\":\"NotificationArea1\",\"overrides\":[],\"properties\":[{\"default\":[],\"kind\":null,\"name\":\"notifications\"},{\"default\":\"bottom-right\",\"kind\":null,\"name\":\"position\"},{\"default\":0,\"kind\":null,\"name\":\"_clear\"},{\"default\":[{\"background\":\"#ffc107\",\"icon\":{\"className\":\"fas fa-exclamation-triangle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"warning\"},{\"background\":\"#007bff\",\"icon\":{\"className\":\"fas fa-info-circle\",\"color\":\"white\",\"tagName\":\"i\"},\"type\":\"info\"}],\"kind\":null,\"name\":\"types\"}]},{\"extends\":null,\"module\":null,\"name\":\"Notification\",\"overrides\":[],\"properties\":[{\"default\":null,\"kind\":null,\"name\":\"background\"},{\"default\":3000,\"kind\":null,\"name\":\"duration\"},{\"default\":null,\"kind\":null,\"name\":\"icon\"},{\"default\":\"\",\"kind\":null,\"name\":\"message\"},{\"default\":null,\"kind\":null,\"name\":\"notification_type\"},{\"default\":false,\"kind\":null,\"name\":\"_destroyed\"}]},{\"extends\":null,\"module\":null,\"name\":\"TemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]},{\"extends\":null,\"module\":null,\"name\":\"MaterialTemplateActions1\",\"overrides\":[],\"properties\":[{\"default\":0,\"kind\":null,\"name\":\"open_modal\"},{\"default\":0,\"kind\":null,\"name\":\"close_modal\"}]}],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"10366\"}],\"center\":[{\"id\":\"10368\"},{\"id\":\"10371\"}],\"left\":[{\"id\":\"10369\"}],\"outline_line_color\":null,\"renderers\":[{\"id\":\"10391\"}],\"title\":{\"id\":\"10356\"},\"toolbar\":{\"id\":\"10379\"},\"x_range\":{\"id\":\"10358\"},\"x_scale\":{\"id\":\"10362\"},\"y_range\":{\"id\":\"10360\"},\"y_scale\":{\"id\":\"10364\"}},\"id\":\"10355\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{},\"id\":\"10364\",\"type\":\"CategoricalScale\"},{\"attributes\":{},\"id\":\"10375\",\"type\":\"UndoTool\"},{\"attributes\":{\"source\":{\"id\":\"10354\"}},\"id\":\"10392\",\"type\":\"CDSView\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"orcid\",\"@x_values\"],[\"docStructured\",\"@y_values\"],[\"total\",\"@total\"],[\"percentage\",\"@percentage\"]]},\"id\":\"10372\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"10734\",\"type\":\"Selection\"},{\"attributes\":{\"axis\":{\"id\":\"10369\"},\"coordinates\":null,\"dimension\":1,\"group\":null,\"ticker\":null},\"id\":\"10371\",\"type\":\"Grid\"},{\"attributes\":{\"bottom_units\":\"screen\",\"coordinates\":null,\"fill_alpha\":0.5,\"fill_color\":\"lightgrey\",\"group\":null,\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":1.0,\"line_color\":\"black\",\"line_dash\":[4,4],\"line_width\":2,\"right_units\":\"screen\",\"syncable\":false,\"top_units\":\"screen\"},\"id\":\"10378\",\"type\":\"BoxAnnotation\"},{\"attributes\":{\"factors\":[\"Yes\",\"No\",\"Not sure\"]},\"id\":\"10358\",\"type\":\"FactorRange\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.6},\"fill_color\":{\"field\":\"color\"},\"hatch_alpha\":{\"value\":0.6},\"line_alpha\":{\"value\":0.6},\"line_color\":{\"field\":\"color\"},\"size\":{\"field\":\"markersize\"},\"x\":{\"field\":\"x_values\"},\"y\":{\"field\":\"y_values\"}},\"id\":\"10387\",\"type\":\"Circle\"},{\"attributes\":{\"axis_label\":\"\",\"axis_line_alpha\":0,\"coordinates\":null,\"formatter\":{\"id\":\"10731\"},\"group\":null,\"major_label_orientation\":1,\"major_label_policy\":{\"id\":\"10732\"},\"ticker\":{\"id\":\"10367\"}},\"id\":\"10366\",\"type\":\"CategoricalAxis\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"field\":\"color\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"field\":\"color\"},\"size\":{\"field\":\"markersize\"},\"x\":{\"field\":\"x_values\"},\"y\":{\"field\":\"y_values\"}},\"id\":\"10388\",\"type\":\"Circle\"},{\"attributes\":{},\"id\":\"10728\",\"type\":\"CategoricalTickFormatter\"},{\"attributes\":{\"fill_color\":{\"field\":\"color\"},\"line_width\":{\"value\":5},\"size\":{\"field\":\"markersize\"},\"x\":{\"field\":\"x_values\"},\"y\":{\"field\":\"y_values\"}},\"id\":\"10389\",\"type\":\"Circle\"},{\"attributes\":{},\"id\":\"10729\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"10731\",\"type\":\"CategoricalTickFormatter\"},{\"attributes\":{},\"id\":\"10376\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"10373\",\"type\":\"WheelZoomTool\"},{\"attributes\":{},\"id\":\"10370\",\"type\":\"CategoricalTicker\"},{\"attributes\":{\"factors\":[\"Yes\",\"No\",\"Not sure\"]},\"id\":\"10360\",\"type\":\"FactorRange\"},{\"attributes\":{},\"id\":\"10732\",\"type\":\"AllLabels\"},{\"attributes\":{\"data\":{\"color\":[\"#A0235A\",\"#A0235A\",\"#A0235A\",\"#A0235A\",\"#A0235A\",\"#A0235A\",\"#A0235A\",\"#A0235A\",\"#A0235A\"],\"docStructured\":[\"No\",\"No\",\"No\",\"Not sure\",\"Not sure\",\"Not sure\",\"Yes\",\"Yes\",\"Yes\"],\"index\":[0,1,2,3,4,5,6,7,8],\"markersize\":[32.57350079,37.6126389,33.31124334,14.56731241,16.82088348,24.4437699,35.68248232,29.13462482,28.97140434],\"orcid\":[\"No\",\"Not sure\",\"Yes\",\"No\",\"Not sure\",\"Yes\",\"No\",\"Not sure\",\"Yes\"],\"percentage\":[41.66666667,55.55555556,43.57541899,8.33333333,11.11111111,23.46368715,50.0,33.33333333,32.96089385],\"total\":[36,9,179,36,9,179,36,9,179],\"value\":[15,5,78,3,1,42,18,3,59],\"x_values\":[\"No\",\"Not sure\",\"Yes\",\"No\",\"Not sure\",\"Yes\",\"No\",\"Not sure\",\"Yes\"],\"y_values\":[\"No\",\"No\",\"No\",\"Not sure\",\"Not sure\",\"Not sure\",\"Yes\",\"Yes\",\"Yes\"]},\"selected\":{\"id\":\"10734\"},\"selection_policy\":{\"id\":\"10733\"}},\"id\":\"10354\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"field\":\"color\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"field\":\"color\"},\"size\":{\"field\":\"markersize\"},\"x\":{\"field\":\"x_values\"},\"y\":{\"field\":\"y_values\"}},\"id\":\"10390\",\"type\":\"Circle\"},{\"attributes\":{\"tools\":[{\"id\":\"10372\"},{\"id\":\"10373\"},{\"id\":\"10374\"},{\"id\":\"10375\"},{\"id\":\"10376\"},{\"id\":\"10377\"}]},\"id\":\"10379\",\"type\":\"Toolbar\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10354\"},\"glyph\":{\"id\":\"10387\"},\"group\":null,\"hover_glyph\":{\"id\":\"10389\"},\"muted_glyph\":{\"id\":\"10390\"},\"nonselection_glyph\":{\"id\":\"10388\"},\"view\":{\"id\":\"10392\"}},\"id\":\"10391\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"10733\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"text\":\"orcid in dependence to docStructured\"},\"id\":\"10356\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"10367\",\"type\":\"CategoricalTicker\"},{\"attributes\":{\"overlay\":{\"id\":\"10378\"}},\"id\":\"10374\",\"type\":\"BoxZoomTool\"},{\"attributes\":{\"axis_label\":\"\",\"axis_line_alpha\":0,\"coordinates\":null,\"formatter\":{\"id\":\"10728\"},\"group\":null,\"major_label_policy\":{\"id\":\"10729\"},\"ticker\":{\"id\":\"10370\"}},\"id\":\"10369\",\"type\":\"CategoricalAxis\"},{\"attributes\":{\"axis\":{\"id\":\"10366\"},\"coordinates\":null,\"group\":null,\"ticker\":null},\"id\":\"10368\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"10377\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"10362\",\"type\":\"CategoricalScale\"}],\"root_ids\":[\"10355\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n const render_items = [{\"docid\":\"4b6d8204-639d-4b87-8837-2f46c7788fbf\",\"root_ids\":[\"10355\"],\"roots\":{\"10355\":\"0936b2a9-e82e-418e-a13a-33f18d7de812\"}}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { diff --git a/survey_dashboard/survey_dashboard.ipynb b/docs/notebooks/survey_dashboard.ipynb similarity index 59% rename from survey_dashboard/survey_dashboard.ipynb rename to docs/notebooks/survey_dashboard.ipynb index 5afc6e1..fb412f1 100644 --- a/survey_dashboard/survey_dashboard.ipynb +++ b/docs/notebooks/survey_dashboard.ipynb @@ -141,426 +141,16 @@ "outputs": [ { "data": { - "application/javascript": [ - "(function(root) {\n", - " function now() {\n", - " return new Date();\n", - " }\n", - "\n", - " var force = true;\n", - "\n", - " if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n", - " root._bokeh_onload_callbacks = [];\n", - " root._bokeh_is_loading = undefined;\n", - " }\n", - "\n", - " if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n", - " root._bokeh_timeout = Date.now() + 5000;\n", - " root._bokeh_failed_load = false;\n", - " }\n", - "\n", - " function run_callbacks() {\n", - " try {\n", - " root._bokeh_onload_callbacks.forEach(function(callback) {\n", - " if (callback != null)\n", - " callback();\n", - " });\n", - " } finally {\n", - " delete root._bokeh_onload_callbacks\n", - " }\n", - " console.debug(\"Bokeh: all callbacks have finished\");\n", - " }\n", - "\n", - " function load_libs(css_urls, js_urls, js_modules, callback) {\n", - " if (css_urls == null) css_urls = [];\n", - " if (js_urls == null) js_urls = [];\n", - " if (js_modules == null) js_modules = [];\n", - "\n", - " root._bokeh_onload_callbacks.push(callback);\n", - " if (root._bokeh_is_loading > 0) {\n", - " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", - " return null;\n", - " }\n", - " if (js_urls.length === 0 && js_modules.length === 0) {\n", - " run_callbacks();\n", - " return null;\n", - " }\n", - " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", - "\n", - " function on_load() {\n", - " root._bokeh_is_loading--;\n", - " if (root._bokeh_is_loading === 0) {\n", - " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", - " run_callbacks()\n", - " }\n", - " }\n", - "\n", - " function on_error() {\n", - " console.error(\"failed to load \" + url);\n", - " }\n", - "\n", - " for (var i = 0; i < css_urls.length; i++) {\n", - " var url = css_urls[i];\n", - " const element = document.createElement(\"link\");\n", - " element.onload = on_load;\n", - " element.onerror = on_error;\n", - " element.rel = \"stylesheet\";\n", - " element.type = \"text/css\";\n", - " element.href = url;\n", - " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", - " document.body.appendChild(element);\n", - " }\n", - "\n", - " var skip = [];\n", - " if (window.requirejs) {\n", - " window.requirejs.config({'packages': {}, 'paths': {'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'gridstack': {'exports': 'GridStack'}}});\n", - " require([\"gridstack\"], function(GridStack) {\n", - "\twindow.GridStack = GridStack\n", - "\ton_load()\n", - " })\n", - " require([\"notyf\"], function() {\n", - "\ton_load()\n", - " })\n", - " root._bokeh_is_loading = css_urls.length + 2;\n", - " } else {\n", - " root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length;\n", - " } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n", - " var urls = ['https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5.js'];\n", - " for (var i = 0; i < urls.length; i++) {\n", - " skip.push(urls[i])\n", - " }\n", - " } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n", - " var urls = ['https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js'];\n", - " for (var i = 0; i < urls.length; i++) {\n", - " skip.push(urls[i])\n", - " }\n", - " } for (var i = 0; i < js_urls.length; i++) {\n", - " var url = js_urls[i];\n", - " if (skip.indexOf(url) >= 0) {\n", - "\tif (!window.requirejs) {\n", - "\t on_load();\n", - "\t}\n", - "\tcontinue;\n", - " }\n", - " var element = document.createElement('script');\n", - " element.onload = on_load;\n", - " element.onerror = on_error;\n", - " element.async = false;\n", - " element.src = url;\n", - " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", - " document.head.appendChild(element);\n", - " }\n", - " for (var i = 0; i < js_modules.length; i++) {\n", - " var url = js_modules[i];\n", - " if (skip.indexOf(url) >= 0) {\n", - "\tif (!window.requirejs) {\n", - "\t on_load();\n", - "\t}\n", - "\tcontinue;\n", - " }\n", - " var element = document.createElement('script');\n", - " element.onload = on_load;\n", - " element.onerror = on_error;\n", - " element.async = false;\n", - " element.src = url;\n", - " element.type = \"module\";\n", - " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", - " document.head.appendChild(element);\n", - " }\n", - " if (!js_urls.length && !js_modules.length) {\n", - " on_load()\n", - " }\n", - " };\n", - "\n", - " function inject_raw_css(css) {\n", - " const element = document.createElement(\"style\");\n", - " element.appendChild(document.createTextNode(css));\n", - " document.body.appendChild(element);\n", - " }\n", - "\n", - " var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js\", \"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js\"];\n", - " var js_modules = [];\n", - " var css_urls = [\"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.css\", \"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/debugger.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/dataframe.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/alerts.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/loading.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/json.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/card.css\"];\n", - " var inline_js = [ function(Bokeh) {\n", - " inject_raw_css(\"\\n .bk.pn-loading.arcs:before {\\n background-image: url(\\\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0ibWFyZ2luOiBhdXRvOyBiYWNrZ3JvdW5kOiBub25lOyBkaXNwbGF5OiBibG9jazsgc2hhcGUtcmVuZGVyaW5nOiBhdXRvOyIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4gIDxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjMyIiBzdHJva2Utd2lkdGg9IjgiIHN0cm9rZT0iI2MzYzNjMyIgc3Ryb2tlLWRhc2hhcnJheT0iNTAuMjY1NDgyNDU3NDM2NjkgNTAuMjY1NDgyNDU3NDM2NjkiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+ICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0icm90YXRlIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgZHVyPSIxcyIga2V5VGltZXM9IjA7MSIgdmFsdWVzPSIwIDUwIDUwOzM2MCA1MCA1MCI+PC9hbmltYXRlVHJhbnNmb3JtPiAgPC9jaXJjbGU+PC9zdmc+\\\");\\n background-size: auto calc(min(50%, 400px));\\n }\\n \");\n", - " }, function(Bokeh) {\n", - " Bokeh.set_log_level(\"info\");\n", - " },\n", - "function(Bokeh) {} // ensure no trailing comma for IE\n", - " ];\n", - "\n", - " function run_inline_js() {\n", - " if ((root.Bokeh !== undefined) || (force === true)) {\n", - " for (var i = 0; i < inline_js.length; i++) {\n", - " inline_js[i].call(root, root.Bokeh);\n", - " }} else if (Date.now() < root._bokeh_timeout) {\n", - " setTimeout(run_inline_js, 100);\n", - " } else if (!root._bokeh_failed_load) {\n", - " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", - " root._bokeh_failed_load = true;\n", - " }\n", - " }\n", - "\n", - " if (root._bokeh_is_loading === 0) {\n", - " console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n", - " run_inline_js();\n", - " } else {\n", - " load_libs(css_urls, js_urls, js_modules, function() {\n", - " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", - " run_inline_js();\n", - " });\n", - " }\n", - "}(window));" - ], - "application/vnd.holoviews_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls.length === 0 && js_modules.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n var skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'gridstack': {'exports': 'GridStack'}}});\n require([\"gridstack\"], function(GridStack) {\n\twindow.GridStack = GridStack\n\ton_load()\n })\n require([\"notyf\"], function() {\n\ton_load()\n })\n root._bokeh_is_loading = css_urls.length + 2;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length;\n } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n if (skip.indexOf(url) >= 0) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (var i = 0; i < js_modules.length; i++) {\n var url = js_modules[i];\n if (skip.indexOf(url) >= 0) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js\", \"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js\"];\n var js_modules = [];\n var css_urls = [\"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.css\", \"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/debugger.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/dataframe.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/alerts.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/loading.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/json.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/card.css\"];\n var inline_js = [ function(Bokeh) {\n inject_raw_css(\"\\n .bk.pn-loading.arcs:before {\\n background-image: url(\\\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0ibWFyZ2luOiBhdXRvOyBiYWNrZ3JvdW5kOiBub25lOyBkaXNwbGF5OiBibG9jazsgc2hhcGUtcmVuZGVyaW5nOiBhdXRvOyIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4gIDxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjMyIiBzdHJva2Utd2lkdGg9IjgiIHN0cm9rZT0iI2MzYzNjMyIgc3Ryb2tlLWRhc2hhcnJheT0iNTAuMjY1NDgyNDU3NDM2NjkgNTAuMjY1NDgyNDU3NDM2NjkiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+ICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0icm90YXRlIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgZHVyPSIxcyIga2V5VGltZXM9IjA7MSIgdmFsdWVzPSIwIDUwIDUwOzM2MCA1MCA1MCI+PC9hbmltYXRlVHJhbnNmb3JtPiAgPC9jaXJjbGU+PC9zdmc+\\\");\\n background-size: auto calc(min(50%, 400px));\\n }\\n \");\n }, function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, js_modules, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));" + "application/javascript": "(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls.length === 0 && js_modules.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n var skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'gridstack': {'exports': 'GridStack'}}});\n require([\"gridstack\"], function(GridStack) {\n\twindow.GridStack = GridStack\n\ton_load()\n })\n require([\"notyf\"], function() {\n\ton_load()\n })\n root._bokeh_is_loading = css_urls.length + 2;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length;\n } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.jsdelivr.net/npm/gridstack@4.2.5/dist/gridstack-h5.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n if (skip.indexOf(url) >= 0) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (var i = 0; i < js_modules.length; i++) {\n var url = js_modules[i];\n if (skip.indexOf(url) >= 0) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js\", \"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js\"];\n var js_modules = [];\n var css_urls = [\"https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.css\", \"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/debugger.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/dataframe.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/markdown.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/widgets.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/alerts.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/loading.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/json.css\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/css/card.css\"];\n var inline_js = [ function(Bokeh) {\n inject_raw_css(\"\\n .bk.pn-loading.arcs:before {\\n background-image: url(\\\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0ibWFyZ2luOiBhdXRvOyBiYWNrZ3JvdW5kOiBub25lOyBkaXNwbGF5OiBibG9jazsgc2hhcGUtcmVuZGVyaW5nOiBhdXRvOyIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4gIDxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjMyIiBzdHJva2Utd2lkdGg9IjgiIHN0cm9rZT0iI2MzYzNjMyIgc3Ryb2tlLWRhc2hhcnJheT0iNTAuMjY1NDgyNDU3NDM2NjkgNTAuMjY1NDgyNDU3NDM2NjkiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+ICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0icm90YXRlIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgZHVyPSIxcyIga2V5VGltZXM9IjA7MSIgdmFsdWVzPSIwIDUwIDUwOzM2MCA1MCA1MCI+PC9hbmltYXRlVHJhbnNmb3JtPiAgPC9jaXJjbGU+PC9zdmc+\\\");\\n background-size: auto calc(min(50%, 400px));\\n }\\n \");\n }, function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, js_modules, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));", + "application/vnd.holoviews_load.v0+json": "" }, "metadata": {}, "output_type": "display_data" }, { "data": { - "application/javascript": [ - "\n", - "if ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n", - " window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n", - "}\n", - "\n", - "\n", - " function JupyterCommManager() {\n", - " }\n", - "\n", - " JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n", - " if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", - " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", - " comm_manager.register_target(comm_id, function(comm) {\n", - " comm.on_msg(msg_handler);\n", - " });\n", - " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", - " window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n", - " comm.onMsg = msg_handler;\n", - " });\n", - " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", - " google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n", - " var messages = comm.messages[Symbol.asyncIterator]();\n", - " function processIteratorResult(result) {\n", - " var message = result.value;\n", - " console.log(message)\n", - " var content = {data: message.data, comm_id};\n", - " var buffers = []\n", - " for (var buffer of message.buffers || []) {\n", - " buffers.push(new DataView(buffer))\n", - " }\n", - " var metadata = message.metadata || {};\n", - " var msg = {content, buffers, metadata}\n", - " msg_handler(msg);\n", - " return messages.next().then(processIteratorResult);\n", - " }\n", - " return messages.next().then(processIteratorResult);\n", - " })\n", - " }\n", - " }\n", - "\n", - " JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n", - " if (comm_id in window.PyViz.comms) {\n", - " return window.PyViz.comms[comm_id];\n", - " } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", - " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", - " var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n", - " if (msg_handler) {\n", - " comm.on_msg(msg_handler);\n", - " }\n", - " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", - " var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n", - " comm.open();\n", - " if (msg_handler) {\n", - " comm.onMsg = msg_handler;\n", - " }\n", - " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", - " var comm_promise = google.colab.kernel.comms.open(comm_id)\n", - " comm_promise.then((comm) => {\n", - " window.PyViz.comms[comm_id] = comm;\n", - " if (msg_handler) {\n", - " var messages = comm.messages[Symbol.asyncIterator]();\n", - " function processIteratorResult(result) {\n", - " var message = result.value;\n", - " var content = {data: message.data};\n", - " var metadata = message.metadata || {comm_id};\n", - " var msg = {content, metadata}\n", - " msg_handler(msg);\n", - " return messages.next().then(processIteratorResult);\n", - " }\n", - " return messages.next().then(processIteratorResult);\n", - " }\n", - " }) \n", - " var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n", - " return comm_promise.then((comm) => {\n", - " comm.send(data, metadata, buffers, disposeOnDone);\n", - " });\n", - " };\n", - " var comm = {\n", - " send: sendClosure\n", - " };\n", - " }\n", - " window.PyViz.comms[comm_id] = comm;\n", - " return comm;\n", - " }\n", - " window.PyViz.comm_manager = new JupyterCommManager();\n", - " \n", - "\n", - "\n", - "var JS_MIME_TYPE = 'application/javascript';\n", - "var HTML_MIME_TYPE = 'text/html';\n", - "var EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\n", - "var CLASS_NAME = 'output';\n", - "\n", - "/**\n", - " * Render data to the DOM node\n", - " */\n", - "function render(props, node) {\n", - " var div = document.createElement(\"div\");\n", - " var script = document.createElement(\"script\");\n", - " node.appendChild(div);\n", - " node.appendChild(script);\n", - "}\n", - "\n", - "/**\n", - " * Handle when a new output is added\n", - " */\n", - "function handle_add_output(event, handle) {\n", - " var output_area = handle.output_area;\n", - " var output = handle.output;\n", - " if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", - " return\n", - " }\n", - " var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", - " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", - " if (id !== undefined) {\n", - " var nchildren = toinsert.length;\n", - " var html_node = toinsert[nchildren-1].children[0];\n", - " html_node.innerHTML = output.data[HTML_MIME_TYPE];\n", - " var scripts = [];\n", - " var nodelist = html_node.querySelectorAll(\"script\");\n", - " for (var i in nodelist) {\n", - " if (nodelist.hasOwnProperty(i)) {\n", - " scripts.push(nodelist[i])\n", - " }\n", - " }\n", - "\n", - " scripts.forEach( function (oldScript) {\n", - " var newScript = document.createElement(\"script\");\n", - " var attrs = [];\n", - " var nodemap = oldScript.attributes;\n", - " for (var j in nodemap) {\n", - " if (nodemap.hasOwnProperty(j)) {\n", - " attrs.push(nodemap[j])\n", - " }\n", - " }\n", - " attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n", - " newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n", - " oldScript.parentNode.replaceChild(newScript, oldScript);\n", - " });\n", - " if (JS_MIME_TYPE in output.data) {\n", - " toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n", - " }\n", - " output_area._hv_plot_id = id;\n", - " if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n", - " window.PyViz.plot_index[id] = Bokeh.index[id];\n", - " } else {\n", - " window.PyViz.plot_index[id] = null;\n", - " }\n", - " } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", - " var bk_div = document.createElement(\"div\");\n", - " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", - " var script_attrs = bk_div.children[0].attributes;\n", - " for (var i = 0; i < script_attrs.length; i++) {\n", - " toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n", - " }\n", - " // store reference to server id on output_area\n", - " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", - " }\n", - "}\n", - "\n", - "/**\n", - " * Handle when an output is cleared or removed\n", - " */\n", - "function handle_clear_output(event, handle) {\n", - " var id = handle.cell.output_area._hv_plot_id;\n", - " var server_id = handle.cell.output_area._bokeh_server_id;\n", - " if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n", - " var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n", - " if (server_id !== null) {\n", - " comm.send({event_type: 'server_delete', 'id': server_id});\n", - " return;\n", - " } else if (comm !== null) {\n", - " comm.send({event_type: 'delete', 'id': id});\n", - " }\n", - " delete PyViz.plot_index[id];\n", - " if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n", - " var doc = window.Bokeh.index[id].model.document\n", - " doc.clear();\n", - " const i = window.Bokeh.documents.indexOf(doc);\n", - " if (i > -1) {\n", - " window.Bokeh.documents.splice(i, 1);\n", - " }\n", - " }\n", - "}\n", - "\n", - "/**\n", - " * Handle kernel restart event\n", - " */\n", - "function handle_kernel_cleanup(event, handle) {\n", - " delete PyViz.comms[\"hv-extension-comm\"];\n", - " window.PyViz.plot_index = {}\n", - "}\n", - "\n", - "/**\n", - " * Handle update_display_data messages\n", - " */\n", - "function handle_update_output(event, handle) {\n", - " handle_clear_output(event, {cell: {output_area: handle.output_area}})\n", - " handle_add_output(event, handle)\n", - "}\n", - "\n", - "function register_renderer(events, OutputArea) {\n", - " function append_mime(data, metadata, element) {\n", - " // create a DOM node to render to\n", - " var toinsert = this.create_output_subarea(\n", - " metadata,\n", - " CLASS_NAME,\n", - " EXEC_MIME_TYPE\n", - " );\n", - " this.keyboard_manager.register_events(toinsert);\n", - " // Render to node\n", - " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", - " render(props, toinsert[0]);\n", - " element.append(toinsert);\n", - " return toinsert\n", - " }\n", - "\n", - " events.on('output_added.OutputArea', handle_add_output);\n", - " events.on('output_updated.OutputArea', handle_update_output);\n", - " events.on('clear_output.CodeCell', handle_clear_output);\n", - " events.on('delete.Cell', handle_clear_output);\n", - " events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n", - "\n", - " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", - " safe: true,\n", - " index: 0\n", - " });\n", - "}\n", - "\n", - "if (window.Jupyter !== undefined) {\n", - " try {\n", - " var events = require('base/js/events');\n", - " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", - " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", - " register_renderer(events, OutputArea);\n", - " }\n", - " } catch(err) {\n", - " }\n", - "}\n" - ], - "application/vnd.holoviews_load.v0+json": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n console.log(message)\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n comm.open();\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n }) \n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n" + "application/javascript": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n console.log(message)\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n comm.open();\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n }) \n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n", + "application/vnd.holoviews_load.v0+json": "" }, "metadata": {}, "output_type": "display_data" @@ -604,287 +194,8 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function now() {\n", - " return new Date();\n", - " }\n", - "\n", - " const force = true;\n", - "\n", - " if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n", - " root._bokeh_onload_callbacks = [];\n", - " root._bokeh_is_loading = undefined;\n", - " }\n", - "\n", - "const JS_MIME_TYPE = 'application/javascript';\n", - " const HTML_MIME_TYPE = 'text/html';\n", - " const EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n", - " const CLASS_NAME = 'output_bokeh rendered_html';\n", - "\n", - " /**\n", - " * Render data to the DOM node\n", - " */\n", - " function render(props, node) {\n", - " const script = document.createElement(\"script\");\n", - " node.appendChild(script);\n", - " }\n", - "\n", - " /**\n", - " * Handle when an output is cleared or removed\n", - " */\n", - " function handleClearOutput(event, handle) {\n", - " const cell = handle.cell;\n", - "\n", - " const id = cell.output_area._bokeh_element_id;\n", - " const server_id = cell.output_area._bokeh_server_id;\n", - " // Clean up Bokeh references\n", - " if (id != null && id in Bokeh.index) {\n", - " Bokeh.index[id].model.document.clear();\n", - " delete Bokeh.index[id];\n", - " }\n", - "\n", - " if (server_id !== undefined) {\n", - " // Clean up Bokeh references\n", - " const cmd_clean = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n", - " cell.notebook.kernel.execute(cmd_clean, {\n", - " iopub: {\n", - " output: function(msg) {\n", - " const id = msg.content.text.trim();\n", - " if (id in Bokeh.index) {\n", - " Bokeh.index[id].model.document.clear();\n", - " delete Bokeh.index[id];\n", - " }\n", - " }\n", - " }\n", - " });\n", - " // Destroy server and session\n", - " const cmd_destroy = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n", - " cell.notebook.kernel.execute(cmd_destroy);\n", - " }\n", - " }\n", - "\n", - " /**\n", - " * Handle when a new output is added\n", - " */\n", - " function handleAddOutput(event, handle) {\n", - " const output_area = handle.output_area;\n", - " const output = handle.output;\n", - "\n", - " // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n", - " if ((output.output_type != \"display_data\") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {\n", - " return\n", - " }\n", - "\n", - " const toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", - "\n", - " if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n", - " toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n", - " // store reference to embed id on output_area\n", - " output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", - " }\n", - " if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", - " const bk_div = document.createElement(\"div\");\n", - " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", - " const script_attrs = bk_div.children[0].attributes;\n", - " for (let i = 0; i < script_attrs.length; i++) {\n", - " toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n", - " toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\n", - " }\n", - " // store reference to server id on output_area\n", - " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", - " }\n", - " }\n", - "\n", - " function register_renderer(events, OutputArea) {\n", - "\n", - " function append_mime(data, metadata, element) {\n", - " // create a DOM node to render to\n", - " const toinsert = this.create_output_subarea(\n", - " metadata,\n", - " CLASS_NAME,\n", - " EXEC_MIME_TYPE\n", - " );\n", - " this.keyboard_manager.register_events(toinsert);\n", - " // Render to node\n", - " const props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", - " render(props, toinsert[toinsert.length - 1]);\n", - " element.append(toinsert);\n", - " return toinsert\n", - " }\n", - "\n", - " /* Handle when an output is cleared or removed */\n", - " events.on('clear_output.CodeCell', handleClearOutput);\n", - " events.on('delete.Cell', handleClearOutput);\n", - "\n", - " /* Handle when a new output is added */\n", - " events.on('output_added.OutputArea', handleAddOutput);\n", - "\n", - " /**\n", - " * Register the mime type and append_mime function with output_area\n", - " */\n", - " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", - " /* Is output safe? */\n", - " safe: true,\n", - " /* Index of renderer in `output_area.display_order` */\n", - " index: 0\n", - " });\n", - " }\n", - "\n", - " // register the mime type if in Jupyter Notebook environment and previously unregistered\n", - " if (root.Jupyter !== undefined) {\n", - " const events = require('base/js/events');\n", - " const OutputArea = require('notebook/js/outputarea').OutputArea;\n", - "\n", - " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", - " register_renderer(events, OutputArea);\n", - " }\n", - " }\n", - " if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n", - " root._bokeh_timeout = Date.now() + 5000;\n", - " root._bokeh_failed_load = false;\n", - " }\n", - "\n", - " const NB_LOAD_WARNING = {'data': {'text/html':\n", - " \"
\\n\"+\n", - " \"

\\n\"+\n", - " \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n", - " \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n", - " \"

\\n\"+\n", - " \"
    \\n\"+\n", - " \"
  • re-rerun `output_notebook()` to attempt to load from CDN again, or
  • \\n\"+\n", - " \"
  • use INLINE resources instead, as so:
  • \\n\"+\n", - " \"
\\n\"+\n", - " \"\\n\"+\n", - " \"from bokeh.resources import INLINE\\n\"+\n", - " \"output_notebook(resources=INLINE)\\n\"+\n", - " \"\\n\"+\n", - " \"
\"}};\n", - "\n", - " function display_loaded() {\n", - " const el = document.getElementById(\"1150\");\n", - " if (el != null) {\n", - " el.textContent = \"BokehJS is loading...\";\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " if (el != null) {\n", - " el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n", - " }\n", - " } else if (Date.now() < root._bokeh_timeout) {\n", - " setTimeout(display_loaded, 100)\n", - " }\n", - " }\n", - "\n", - " function run_callbacks() {\n", - " try {\n", - " root._bokeh_onload_callbacks.forEach(function(callback) {\n", - " if (callback != null)\n", - " callback();\n", - " });\n", - " } finally {\n", - " delete root._bokeh_onload_callbacks\n", - " }\n", - " console.debug(\"Bokeh: all callbacks have finished\");\n", - " }\n", - "\n", - " function load_libs(css_urls, js_urls, callback) {\n", - " if (css_urls == null) css_urls = [];\n", - " if (js_urls == null) js_urls = [];\n", - "\n", - " root._bokeh_onload_callbacks.push(callback);\n", - " if (root._bokeh_is_loading > 0) {\n", - " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", - " return null;\n", - " }\n", - " if (js_urls == null || js_urls.length === 0) {\n", - " run_callbacks();\n", - " return null;\n", - " }\n", - " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", - " root._bokeh_is_loading = css_urls.length + js_urls.length;\n", - "\n", - " function on_load() {\n", - " root._bokeh_is_loading--;\n", - " if (root._bokeh_is_loading === 0) {\n", - " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", - " run_callbacks()\n", - " }\n", - " }\n", - "\n", - " function on_error(url) {\n", - " console.error(\"failed to load \" + url);\n", - " }\n", - "\n", - " for (let i = 0; i < css_urls.length; i++) {\n", - " const url = css_urls[i];\n", - " const element = document.createElement(\"link\");\n", - " element.onload = on_load;\n", - " element.onerror = on_error.bind(null, url);\n", - " element.rel = \"stylesheet\";\n", - " element.type = \"text/css\";\n", - " element.href = url;\n", - " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", - " document.body.appendChild(element);\n", - " }\n", - "\n", - " for (let i = 0; i < js_urls.length; i++) {\n", - " const url = js_urls[i];\n", - " const element = document.createElement('script');\n", - " element.onload = on_load;\n", - " element.onerror = on_error.bind(null, url);\n", - " element.async = false;\n", - " element.src = url;\n", - " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", - " document.head.appendChild(element);\n", - " }\n", - " };\n", - "\n", - " function inject_raw_css(css) {\n", - " const element = document.createElement(\"style\");\n", - " element.appendChild(document.createTextNode(css));\n", - " document.body.appendChild(element);\n", - " }\n", - "\n", - " const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js\"];\n", - " const css_urls = [];\n", - "\n", - " const inline_js = [ function(Bokeh) {\n", - " Bokeh.set_log_level(\"info\");\n", - " },\n", - "function(Bokeh) {\n", - " }\n", - " ];\n", - "\n", - " function run_inline_js() {\n", - " if (root.Bokeh !== undefined || force === true) {\n", - " for (let i = 0; i < inline_js.length; i++) {\n", - " inline_js[i].call(root, root.Bokeh);\n", - " }\n", - "if (force === true) {\n", - " display_loaded();\n", - " }} else if (Date.now() < root._bokeh_timeout) {\n", - " setTimeout(run_inline_js, 100);\n", - " } else if (!root._bokeh_failed_load) {\n", - " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", - " root._bokeh_failed_load = true;\n", - " } else if (force !== true) {\n", - " const cell = $(document.getElementById(\"1150\")).parents('.cell').data().cell;\n", - " cell.output_area.append_execute_result(NB_LOAD_WARNING)\n", - " }\n", - " }\n", - "\n", - " if (root._bokeh_is_loading === 0) {\n", - " console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n", - " run_inline_js();\n", - " } else {\n", - " load_libs(css_urls, js_urls, function() {\n", - " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", - " run_inline_js();\n", - " });\n", - " }\n", - "}(window));" - ], - "application/vnd.bokehjs_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n const force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n const NB_LOAD_WARNING = {'data': {'text/html':\n \"
\\n\"+\n \"

\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"

\\n\"+\n \"
    \\n\"+\n \"
  • re-rerun `output_notebook()` to attempt to load from CDN again, or
  • \\n\"+\n \"
  • use INLINE resources instead, as so:
  • \\n\"+\n \"
\\n\"+\n \"\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"\\n\"+\n \"
\"}};\n\n function display_loaded() {\n const el = document.getElementById(\"1150\");\n if (el != null) {\n el.textContent = \"BokehJS is loading...\";\n }\n if (root.Bokeh !== undefined) {\n if (el != null) {\n el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(display_loaded, 100)\n }\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error(url) {\n console.error(\"failed to load \" + url);\n }\n\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js\"];\n const css_urls = [];\n\n const inline_js = [ function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {\n }\n ];\n\n function run_inline_js() {\n if (root.Bokeh !== undefined || force === true) {\n for (let i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }\nif (force === true) {\n display_loaded();\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n } else if (force !== true) {\n const cell = $(document.getElementById(\"1150\")).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));" + "application/javascript": "(function(root) {\n function now() {\n return new Date();\n }\n\n const force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\nconst JS_MIME_TYPE = 'application/javascript';\n const HTML_MIME_TYPE = 'text/html';\n const EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n const CLASS_NAME = 'output_bokeh rendered_html';\n\n /**\n * Render data to the DOM node\n */\n function render(props, node) {\n const script = document.createElement(\"script\");\n node.appendChild(script);\n }\n\n /**\n * Handle when an output is cleared or removed\n */\n function handleClearOutput(event, handle) {\n const cell = handle.cell;\n\n const id = cell.output_area._bokeh_element_id;\n const server_id = cell.output_area._bokeh_server_id;\n // Clean up Bokeh references\n if (id != null && id in Bokeh.index) {\n Bokeh.index[id].model.document.clear();\n delete Bokeh.index[id];\n }\n\n if (server_id !== undefined) {\n // Clean up Bokeh references\n const cmd_clean = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n cell.notebook.kernel.execute(cmd_clean, {\n iopub: {\n output: function(msg) {\n const id = msg.content.text.trim();\n if (id in Bokeh.index) {\n Bokeh.index[id].model.document.clear();\n delete Bokeh.index[id];\n }\n }\n }\n });\n // Destroy server and session\n const cmd_destroy = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n cell.notebook.kernel.execute(cmd_destroy);\n }\n }\n\n /**\n * Handle when a new output is added\n */\n function handleAddOutput(event, handle) {\n const output_area = handle.output_area;\n const output = handle.output;\n\n // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n if ((output.output_type != \"display_data\") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {\n return\n }\n\n const toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n\n if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n // store reference to embed id on output_area\n output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n }\n if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n const bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n const script_attrs = bk_div.children[0].attributes;\n for (let i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n }\n\n function register_renderer(events, OutputArea) {\n\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n const toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n const props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[toinsert.length - 1]);\n element.append(toinsert);\n return toinsert\n }\n\n /* Handle when an output is cleared or removed */\n events.on('clear_output.CodeCell', handleClearOutput);\n events.on('delete.Cell', handleClearOutput);\n\n /* Handle when a new output is added */\n events.on('output_added.OutputArea', handleAddOutput);\n\n /**\n * Register the mime type and append_mime function with output_area\n */\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n /* Is output safe? */\n safe: true,\n /* Index of renderer in `output_area.display_order` */\n index: 0\n });\n }\n\n // register the mime type if in Jupyter Notebook environment and previously unregistered\n if (root.Jupyter !== undefined) {\n const events = require('base/js/events');\n const OutputArea = require('notebook/js/outputarea').OutputArea;\n\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n }\n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n const NB_LOAD_WARNING = {'data': {'text/html':\n \"
\\n\"+\n \"

\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"

\\n\"+\n \"
    \\n\"+\n \"
  • re-rerun `output_notebook()` to attempt to load from CDN again, or
  • \\n\"+\n \"
  • use INLINE resources instead, as so:
  • \\n\"+\n \"
\\n\"+\n \"\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"\\n\"+\n \"
\"}};\n\n function display_loaded() {\n const el = document.getElementById(\"1150\");\n if (el != null) {\n el.textContent = \"BokehJS is loading...\";\n }\n if (root.Bokeh !== undefined) {\n if (el != null) {\n el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(display_loaded, 100)\n }\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error(url) {\n console.error(\"failed to load \" + url);\n }\n\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js\", \"https://unpkg.com/@holoviz/panel@0.13.1/dist/panel.min.js\"];\n const css_urls = [];\n\n const inline_js = [ function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {\n }\n ];\n\n function run_inline_js() {\n if (root.Bokeh !== undefined || force === true) {\n for (let i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }\nif (force === true) {\n display_loaded();\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n } else if (force !== true) {\n const cell = $(document.getElementById(\"1150\")).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));", + "application/vnd.bokehjs_load.v0+json": "" }, "metadata": {}, "output_type": "display_data" @@ -2426,32 +1737,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"cb133ec6-d913-49d7-8b55-dbce4731754b\":{\"version\":\"3.0.0.dev13\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"38388\",\"attributes\":{\"y_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"38398\",\"attributes\":{\"start\":0}},\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"38394\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"TapTool\",\"id\":\"38417\",\"attributes\":{\"renderers\":\"auto\"}},{\"type\":\"object\",\"name\":\"WheelZoomTool\",\"id\":\"38418\"},{\"type\":\"object\",\"name\":\"BoxZoomTool\",\"id\":\"38419\",\"attributes\":{\"overlay\":{\"type\":\"object\",\"name\":\"BoxAnnotation\",\"id\":\"38420\",\"attributes\":{\"left_units\":\"canvas\",\"bottom_units\":\"canvas\",\"fill_alpha\":0.5,\"right_units\":\"canvas\",\"line_color\":\"black\",\"fill_color\":\"lightgrey\",\"line_alpha\":1.0,\"line_dash\":[4,4],\"top_units\":\"canvas\",\"visible\":false,\"line_width\":2,\"level\":\"overlay\",\"syncable\":false}}}},{\"type\":\"object\",\"name\":\"UndoTool\",\"id\":\"38421\"},{\"type\":\"object\",\"name\":\"ResetTool\",\"id\":\"38422\"},{\"type\":\"object\",\"name\":\"SaveTool\",\"id\":\"38423\"},{\"type\":\"object\",\"name\":\"HelpTool\",\"id\":\"38387\",\"attributes\":{\"redirect\":\"https://helmholtz-metadaten.de/en/pages/structure-governance\",\"description\":\"For more information about the HMC survey click here.\"}},{\"type\":\"object\",\"name\":\"HoverTool\",\"id\":\"38776\",\"attributes\":{\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38442\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38439\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"All\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38433\",\"attributes\":{\"value\":-0.6000000000000001,\"range\":{\"type\":\"object\",\"name\":\"FactorRange\",\"id\":\"38396\",\"attributes\":{\"factors\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"],\"range_padding\":0.1}}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#3182bd\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38440\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"All\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38433\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#3182bd\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38441\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#3182bd\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#3182bd\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"All\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38433\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#3182bd\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38438\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#3182bd\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"All\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38433\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#3182bd\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38443\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38444\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"38384\",\"attributes\":{\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"38386\"},\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"38385\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"All\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAACCAAAAgAAAAJQAAAAQAQAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"careerLevel\",[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]],[\"Engineering Science\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAAvAAAAHgAAADQAAACGAAAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"Physics\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAAhAAAAJgAAACcAAAA5AAAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"Life Science\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAAcAAAAHQAAABsAAAAhAAAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"Earth Science\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAAIAAAACwAAABIAAAAgAAAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"Chemistry\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAAJAAAADAAAAAYAAAAEAAAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"Other\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAABAAAAAgAAAAMAAAAGAAAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"Psychology\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAADAAAAAgAAAAMAAAACAAAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"Mathematics\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAABAAAABAAAAAAAAAAEAAAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}]]}}},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38437\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#3182bd\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#3182bd\"},\"top\":{\"type\":\"field\",\"field\":\"All\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38433\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#3182bd\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38469\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38466\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Engineering Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38460\",\"attributes\":{\"value\":-0.45000000000000007,\"range\":{\"id\":\"38396\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#6baed6\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38467\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Engineering Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38460\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#6baed6\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38468\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#6baed6\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#6baed6\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Engineering Science\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38460\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#6baed6\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38465\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#6baed6\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Engineering Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38460\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#6baed6\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38470\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38471\"}}},\"data_source\":{\"id\":\"38384\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38464\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#6baed6\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#6baed6\"},\"top\":{\"type\":\"field\",\"field\":\"Engineering Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38460\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#6baed6\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38498\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38495\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Physics\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38489\",\"attributes\":{\"value\":-0.30000000000000004,\"range\":{\"id\":\"38396\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38496\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Physics\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38489\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38497\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Physics\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38489\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38494\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Physics\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38489\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38499\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38500\"}}},\"data_source\":{\"id\":\"38384\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38493\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"},\"top\":{\"type\":\"field\",\"field\":\"Physics\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38489\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38530\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38527\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Life Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38521\",\"attributes\":{\"value\":-0.15000000000000002,\"range\":{\"id\":\"38396\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38528\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Life Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38521\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38529\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Life Science\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38521\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38526\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Life Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38521\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38531\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38532\"}}},\"data_source\":{\"id\":\"38384\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38525\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"},\"top\":{\"type\":\"field\",\"field\":\"Life Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38521\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38565\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38562\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Earth Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38556\",\"attributes\":{\"range\":{\"id\":\"38396\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#e6550d\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38563\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Earth Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38556\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#e6550d\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38564\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#e6550d\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#e6550d\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Earth Science\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38556\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#e6550d\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38561\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#e6550d\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Earth Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38556\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#e6550d\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38566\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38567\"}}},\"data_source\":{\"id\":\"38384\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38560\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#e6550d\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#e6550d\"},\"top\":{\"type\":\"field\",\"field\":\"Earth Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38556\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#e6550d\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38603\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38600\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Chemistry\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38594\",\"attributes\":{\"value\":0.15000000000000002,\"range\":{\"id\":\"38396\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38601\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Chemistry\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38594\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38602\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Chemistry\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38594\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38599\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Chemistry\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38594\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38604\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38605\"}}},\"data_source\":{\"id\":\"38384\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38598\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"},\"top\":{\"type\":\"field\",\"field\":\"Chemistry\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38594\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38644\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38641\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Other\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38635\",\"attributes\":{\"value\":0.30000000000000004,\"range\":{\"id\":\"38396\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38642\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Other\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38635\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38643\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Other\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38635\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38640\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Other\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38635\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38645\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38646\"}}},\"data_source\":{\"id\":\"38384\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38639\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"},\"top\":{\"type\":\"field\",\"field\":\"Other\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38635\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38688\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38685\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Psychology\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38679\",\"attributes\":{\"value\":0.4500000000000002,\"range\":{\"id\":\"38396\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38686\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Psychology\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38679\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38687\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Psychology\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38679\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38684\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Psychology\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38679\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38689\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38690\"}}},\"data_source\":{\"id\":\"38384\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38683\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"},\"top\":{\"type\":\"field\",\"field\":\"Psychology\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38679\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38735\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38732\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Mathematics\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38726\",\"attributes\":{\"value\":0.6000000000000001,\"range\":{\"id\":\"38396\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#31a354\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38733\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Mathematics\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38726\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#31a354\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38734\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#31a354\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#31a354\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Mathematics\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38726\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#31a354\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38731\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#31a354\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Mathematics\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38726\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#31a354\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38736\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38737\"}}},\"data_source\":{\"id\":\"38384\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38730\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#31a354\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#31a354\"},\"top\":{\"type\":\"field\",\"field\":\"Mathematics\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38726\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#31a354\"}}}}}],\"tooltips\":[[\"careerLevel\",\"@careerLevel\"],[\"All\",\"@{All}\"],[\"Engineering Science\",\"@{Engineering Science}\"],[\"Physics\",\"@{Physics}\"],[\"Life Science\",\"@{Life Science}\"],[\"Earth Science\",\"@{Earth Science}\"],[\"Chemistry\",\"@{Chemistry}\"],[\"Other\",\"@{Other}\"],[\"Psychology\",\"@{Psychology}\"],[\"Mathematics\",\"@{Mathematics}\"]]}}],\"logo\":null}},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"38410\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"38412\"},\"axis_label\":\"Number of answers\",\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"38411\"},\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"38413\",\"attributes\":{\"mantissas\":[1,2,5]}}}}],\"below\":[{\"type\":\"object\",\"name\":\"CategoricalAxis\",\"id\":\"38404\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"CategoricalTickFormatter\",\"id\":\"38406\"},\"axis_label\":\"\",\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"38405\"},\"major_label_orientation\":1,\"ticker\":{\"type\":\"object\",\"name\":\"CategoricalTicker\",\"id\":\"38407\"}}}],\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"38402\"},\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"38409\",\"attributes\":{\"axis\":{\"id\":\"38404\"},\"grid_line_color\":null}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"38416\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"38410\"}}},{\"type\":\"object\",\"name\":\"Legend\",\"id\":\"38458\",\"attributes\":{\"items\":[{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38459\",\"attributes\":{\"renderers\":[{\"id\":\"38442\"}],\"label\":{\"type\":\"value\",\"value\":\"All\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38488\",\"attributes\":{\"renderers\":[{\"id\":\"38469\"}],\"label\":{\"type\":\"value\",\"value\":\"Engineering Science\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38520\",\"attributes\":{\"renderers\":[{\"id\":\"38498\"}],\"label\":{\"type\":\"value\",\"value\":\"Physics\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38555\",\"attributes\":{\"renderers\":[{\"id\":\"38530\"}],\"label\":{\"type\":\"value\",\"value\":\"Life Science\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38593\",\"attributes\":{\"renderers\":[{\"id\":\"38565\"}],\"label\":{\"type\":\"value\",\"value\":\"Earth Science\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38634\",\"attributes\":{\"renderers\":[{\"id\":\"38603\"}],\"label\":{\"type\":\"value\",\"value\":\"Chemistry\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38678\",\"attributes\":{\"renderers\":[{\"id\":\"38644\"}],\"label\":{\"type\":\"value\",\"value\":\"Other\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38725\",\"attributes\":{\"renderers\":[{\"id\":\"38688\"}],\"label\":{\"type\":\"value\",\"value\":\"Psychology\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38775\",\"attributes\":{\"renderers\":[{\"id\":\"38735\"}],\"label\":{\"type\":\"value\",\"value\":\"Mathematics\"}}}],\"location\":\"top_right\",\"click_policy\":\"hide\",\"orientation\":\"vertical\"}}],\"toolbar_location\":\"above\",\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"38389\",\"attributes\":{\"text\":\"this is a title\"}},\"x_scale\":{\"type\":\"object\",\"name\":\"CategoricalScale\",\"id\":\"38400\"},\"x_range\":{\"id\":\"38396\"},\"width\":1200,\"renderers\":[{\"id\":\"38442\"},{\"id\":\"38469\"},{\"id\":\"38498\"},{\"id\":\"38530\"},{\"id\":\"38565\"},{\"id\":\"38603\"},{\"id\":\"38644\"},{\"id\":\"38688\"},{\"id\":\"38735\"}],\"height\":550}}]}};\n", - " const render_items = [{\"docid\":\"cb133ec6-d913-49d7-8b55-dbce4731754b\",\"roots\":{\"38388\":\"aa654e04-abc5-4f39-9e7d-084f7db36499\"},\"root_ids\":[\"38388\"]}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"cb133ec6-d913-49d7-8b55-dbce4731754b\":{\"version\":\"3.0.0.dev13\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"38388\",\"attributes\":{\"y_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"38398\",\"attributes\":{\"start\":0}},\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"38394\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"TapTool\",\"id\":\"38417\",\"attributes\":{\"renderers\":\"auto\"}},{\"type\":\"object\",\"name\":\"WheelZoomTool\",\"id\":\"38418\"},{\"type\":\"object\",\"name\":\"BoxZoomTool\",\"id\":\"38419\",\"attributes\":{\"overlay\":{\"type\":\"object\",\"name\":\"BoxAnnotation\",\"id\":\"38420\",\"attributes\":{\"left_units\":\"canvas\",\"bottom_units\":\"canvas\",\"fill_alpha\":0.5,\"right_units\":\"canvas\",\"line_color\":\"black\",\"fill_color\":\"lightgrey\",\"line_alpha\":1.0,\"line_dash\":[4,4],\"top_units\":\"canvas\",\"visible\":false,\"line_width\":2,\"level\":\"overlay\",\"syncable\":false}}}},{\"type\":\"object\",\"name\":\"UndoTool\",\"id\":\"38421\"},{\"type\":\"object\",\"name\":\"ResetTool\",\"id\":\"38422\"},{\"type\":\"object\",\"name\":\"SaveTool\",\"id\":\"38423\"},{\"type\":\"object\",\"name\":\"HelpTool\",\"id\":\"38387\",\"attributes\":{\"redirect\":\"https://helmholtz-metadaten.de/en/pages/structure-governance\",\"description\":\"For more information about the HMC survey click here.\"}},{\"type\":\"object\",\"name\":\"HoverTool\",\"id\":\"38776\",\"attributes\":{\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38442\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38439\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"All\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38433\",\"attributes\":{\"value\":-0.6000000000000001,\"range\":{\"type\":\"object\",\"name\":\"FactorRange\",\"id\":\"38396\",\"attributes\":{\"factors\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"],\"range_padding\":0.1}}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#3182bd\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38440\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"All\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38433\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#3182bd\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38441\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#3182bd\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#3182bd\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"All\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38433\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#3182bd\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38438\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#3182bd\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"All\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38433\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#3182bd\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38443\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38444\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"38384\",\"attributes\":{\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"38386\"},\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"38385\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"All\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAACCAAAAgAAAAJQAAAAQAQAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"careerLevel\",[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]],[\"Engineering Science\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAAvAAAAHgAAADQAAACGAAAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"Physics\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAAhAAAAJgAAACcAAAA5AAAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"Life Science\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAAcAAAAHQAAABsAAAAhAAAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"Earth Science\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAAIAAAACwAAABIAAAAgAAAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"Chemistry\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAAJAAAADAAAAAYAAAAEAAAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"Other\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAABAAAAAgAAAAMAAAAGAAAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"Psychology\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAADAAAAAgAAAAMAAAACAAAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"Mathematics\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAAAAAABAAAABAAAAAAAAAAEAAAAAAAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}]]}}},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38437\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#3182bd\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#3182bd\"},\"top\":{\"type\":\"field\",\"field\":\"All\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38433\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#3182bd\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38469\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38466\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Engineering Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38460\",\"attributes\":{\"value\":-0.45000000000000007,\"range\":{\"id\":\"38396\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#6baed6\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38467\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Engineering Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38460\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#6baed6\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38468\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#6baed6\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#6baed6\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Engineering Science\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38460\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#6baed6\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38465\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#6baed6\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Engineering Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38460\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#6baed6\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38470\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38471\"}}},\"data_source\":{\"id\":\"38384\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38464\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#6baed6\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#6baed6\"},\"top\":{\"type\":\"field\",\"field\":\"Engineering Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38460\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#6baed6\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38498\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38495\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Physics\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38489\",\"attributes\":{\"value\":-0.30000000000000004,\"range\":{\"id\":\"38396\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38496\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Physics\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38489\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38497\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Physics\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38489\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38494\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Physics\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38489\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38499\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38500\"}}},\"data_source\":{\"id\":\"38384\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38493\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"},\"top\":{\"type\":\"field\",\"field\":\"Physics\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38489\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#9ecae1\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38530\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38527\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Life Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38521\",\"attributes\":{\"value\":-0.15000000000000002,\"range\":{\"id\":\"38396\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38528\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Life Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38521\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38529\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Life Science\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38521\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38526\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Life Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38521\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38531\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38532\"}}},\"data_source\":{\"id\":\"38384\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38525\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"},\"top\":{\"type\":\"field\",\"field\":\"Life Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38521\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#c6dbef\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38565\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38562\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Earth Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38556\",\"attributes\":{\"range\":{\"id\":\"38396\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#e6550d\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38563\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Earth Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38556\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#e6550d\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38564\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#e6550d\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#e6550d\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Earth Science\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38556\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#e6550d\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38561\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#e6550d\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Earth Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38556\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#e6550d\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38566\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38567\"}}},\"data_source\":{\"id\":\"38384\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38560\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#e6550d\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#e6550d\"},\"top\":{\"type\":\"field\",\"field\":\"Earth Science\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38556\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#e6550d\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38603\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38600\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Chemistry\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38594\",\"attributes\":{\"value\":0.15000000000000002,\"range\":{\"id\":\"38396\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38601\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Chemistry\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38594\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38602\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Chemistry\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38594\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38599\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Chemistry\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38594\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38604\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38605\"}}},\"data_source\":{\"id\":\"38384\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38598\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"},\"top\":{\"type\":\"field\",\"field\":\"Chemistry\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38594\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fd8d3c\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38644\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38641\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Other\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38635\",\"attributes\":{\"value\":0.30000000000000004,\"range\":{\"id\":\"38396\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38642\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Other\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38635\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38643\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Other\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38635\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38640\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Other\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38635\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38645\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38646\"}}},\"data_source\":{\"id\":\"38384\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38639\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"},\"top\":{\"type\":\"field\",\"field\":\"Other\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38635\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdae6b\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38688\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38685\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Psychology\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38679\",\"attributes\":{\"value\":0.4500000000000002,\"range\":{\"id\":\"38396\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38686\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Psychology\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38679\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38687\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Psychology\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38679\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38684\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Psychology\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38679\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38689\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38690\"}}},\"data_source\":{\"id\":\"38384\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38683\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"},\"top\":{\"type\":\"field\",\"field\":\"Psychology\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38679\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#fdd0a2\"}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"38735\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38732\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Mathematics\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"38726\",\"attributes\":{\"value\":0.6000000000000001,\"range\":{\"id\":\"38396\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#31a354\"}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38733\",\"attributes\":{\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"top\":{\"type\":\"field\",\"field\":\"Mathematics\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38726\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#31a354\"}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38734\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#31a354\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#31a354\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Mathematics\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38726\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#31a354\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38731\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#31a354\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"top\":{\"type\":\"field\",\"field\":\"Mathematics\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38726\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#31a354\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"38736\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"38737\"}}},\"data_source\":{\"id\":\"38384\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"38730\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.5},\"line_color\":{\"type\":\"value\",\"value\":\"#31a354\"},\"width\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#31a354\"},\"top\":{\"type\":\"field\",\"field\":\"Mathematics\"},\"x\":{\"type\":\"field\",\"field\":\"careerLevel\",\"transform\":{\"id\":\"38726\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#31a354\"}}}}}],\"tooltips\":[[\"careerLevel\",\"@careerLevel\"],[\"All\",\"@{All}\"],[\"Engineering Science\",\"@{Engineering Science}\"],[\"Physics\",\"@{Physics}\"],[\"Life Science\",\"@{Life Science}\"],[\"Earth Science\",\"@{Earth Science}\"],[\"Chemistry\",\"@{Chemistry}\"],[\"Other\",\"@{Other}\"],[\"Psychology\",\"@{Psychology}\"],[\"Mathematics\",\"@{Mathematics}\"]]}}],\"logo\":null}},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"38410\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"38412\"},\"axis_label\":\"Number of answers\",\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"38411\"},\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"38413\",\"attributes\":{\"mantissas\":[1,2,5]}}}}],\"below\":[{\"type\":\"object\",\"name\":\"CategoricalAxis\",\"id\":\"38404\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"CategoricalTickFormatter\",\"id\":\"38406\"},\"axis_label\":\"\",\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"38405\"},\"major_label_orientation\":1,\"ticker\":{\"type\":\"object\",\"name\":\"CategoricalTicker\",\"id\":\"38407\"}}}],\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"38402\"},\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"38409\",\"attributes\":{\"axis\":{\"id\":\"38404\"},\"grid_line_color\":null}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"38416\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"38410\"}}},{\"type\":\"object\",\"name\":\"Legend\",\"id\":\"38458\",\"attributes\":{\"items\":[{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38459\",\"attributes\":{\"renderers\":[{\"id\":\"38442\"}],\"label\":{\"type\":\"value\",\"value\":\"All\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38488\",\"attributes\":{\"renderers\":[{\"id\":\"38469\"}],\"label\":{\"type\":\"value\",\"value\":\"Engineering Science\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38520\",\"attributes\":{\"renderers\":[{\"id\":\"38498\"}],\"label\":{\"type\":\"value\",\"value\":\"Physics\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38555\",\"attributes\":{\"renderers\":[{\"id\":\"38530\"}],\"label\":{\"type\":\"value\",\"value\":\"Life Science\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38593\",\"attributes\":{\"renderers\":[{\"id\":\"38565\"}],\"label\":{\"type\":\"value\",\"value\":\"Earth Science\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38634\",\"attributes\":{\"renderers\":[{\"id\":\"38603\"}],\"label\":{\"type\":\"value\",\"value\":\"Chemistry\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38678\",\"attributes\":{\"renderers\":[{\"id\":\"38644\"}],\"label\":{\"type\":\"value\",\"value\":\"Other\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38725\",\"attributes\":{\"renderers\":[{\"id\":\"38688\"}],\"label\":{\"type\":\"value\",\"value\":\"Psychology\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"38775\",\"attributes\":{\"renderers\":[{\"id\":\"38735\"}],\"label\":{\"type\":\"value\",\"value\":\"Mathematics\"}}}],\"location\":\"top_right\",\"click_policy\":\"hide\",\"orientation\":\"vertical\"}}],\"toolbar_location\":\"above\",\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"38389\",\"attributes\":{\"text\":\"this is a title\"}},\"x_scale\":{\"type\":\"object\",\"name\":\"CategoricalScale\",\"id\":\"38400\"},\"x_range\":{\"id\":\"38396\"},\"width\":1200,\"renderers\":[{\"id\":\"38442\"},{\"id\":\"38469\"},{\"id\":\"38498\"},{\"id\":\"38530\"},{\"id\":\"38565\"},{\"id\":\"38603\"},{\"id\":\"38644\"},{\"id\":\"38688\"},{\"id\":\"38735\"}],\"height\":550}}]}};\n const render_items = [{\"docid\":\"cb133ec6-d913-49d7-8b55-dbce4731754b\",\"roots\":{\"38388\":\"aa654e04-abc5-4f39-9e7d-084f7db36499\"},\"root_ids\":[\"38388\"]}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -2779,32 +2065,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"84a04889-f987-43e6-ab22-efd5a12d02e3\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"10085\"}],\"center\":[{\"id\":\"10088\"},{\"id\":\"10092\"}],\"left\":[{\"id\":\"10089\"}],\"renderers\":[{\"id\":\"10098\"},{\"id\":\"10104\"},{\"id\":\"10110\"},{\"id\":\"10116\"},{\"id\":\"10122\"},{\"id\":\"10128\"},{\"id\":\"10134\"},{\"id\":\"10140\"},{\"id\":\"10146\"}],\"title\":{\"id\":\"10075\"},\"toolbar\":{\"id\":\"10093\"},\"toolbar_location\":\"above\",\"width\":1600,\"x_range\":{\"id\":\"10077\"},\"x_scale\":{\"id\":\"10081\"},\"y_range\":{\"id\":\"10079\"},\"y_scale\":{\"id\":\"10083\"}},\"id\":\"10074\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"data\":{\"top\":[0,0,3,2,3,2,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10437\"},\"selection_policy\":{\"id\":\"10436\"}},\"id\":\"10136\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"source\":{\"id\":\"10130\"}},\"id\":\"10135\",\"type\":\"CDSView\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#e2e2e2\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10114\",\"type\":\"VBar\"},{\"attributes\":{\"data\":{\"top\":[0,0,28,29,27,33,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10429\"},\"selection_policy\":{\"id\":\"10428\"}},\"id\":\"10112\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#e2e2e2\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10115\",\"type\":\"VBar\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10118\"},\"glyph\":{\"id\":\"10119\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10121\"},\"nonselection_glyph\":{\"id\":\"10120\"},\"view\":{\"id\":\"10123\"}},\"id\":\"10122\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#c9d9d3\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10109\",\"type\":\"VBar\"},{\"attributes\":{\"data\":{\"top\":[0,0,9,12,6,4,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10433\"},\"selection_policy\":{\"id\":\"10432\"}},\"id\":\"10124\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10106\"},\"glyph\":{\"id\":\"10107\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10109\"},\"nonselection_glyph\":{\"id\":\"10108\"},\"view\":{\"id\":\"10111\"}},\"id\":\"10110\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"source\":{\"id\":\"10118\"}},\"id\":\"10123\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"10436\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"fill_color\":{\"value\":\"#ddb7b1\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10125\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"10428\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10136\"},\"glyph\":{\"id\":\"10137\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10139\"},\"nonselection_glyph\":{\"id\":\"10138\"},\"view\":{\"id\":\"10141\"}},\"id\":\"10140\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"10437\",\"type\":\"Selection\"},{\"attributes\":{\"fill_color\":{\"value\":\"#cc7878\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10131\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"10429\",\"type\":\"Selection\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#ddb7b1\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10127\",\"type\":\"VBar\"},{\"attributes\":{\"fill_color\":{\"value\":\"#933b41\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10137\",\"type\":\"VBar\"},{\"attributes\":{\"data\":{\"top\":[0,0,8,11,18,32,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10431\"},\"selection_policy\":{\"id\":\"10430\"}},\"id\":\"10118\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"data\":{\"top\":[0,0,1,2,3,6,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10435\"},\"selection_policy\":{\"id\":\"10434\"}},\"id\":\"10130\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"source\":{\"id\":\"10136\"}},\"id\":\"10141\",\"type\":\"CDSView\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10124\"},\"glyph\":{\"id\":\"10125\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10127\"},\"nonselection_glyph\":{\"id\":\"10126\"},\"view\":{\"id\":\"10129\"}},\"id\":\"10128\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"fill_color\":{\"value\":\"#e2e2e2\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10113\",\"type\":\"VBar\"},{\"attributes\":{\"source\":{\"id\":\"10124\"}},\"id\":\"10129\",\"type\":\"CDSView\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#cc7878\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10133\",\"type\":\"VBar\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#cc7878\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10132\",\"type\":\"VBar\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#dfccce\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10120\",\"type\":\"VBar\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#933b41\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10139\",\"type\":\"VBar\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10112\"},\"glyph\":{\"id\":\"10113\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10115\"},\"nonselection_glyph\":{\"id\":\"10114\"},\"view\":{\"id\":\"10117\"}},\"id\":\"10116\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"source\":{\"id\":\"10112\"}},\"id\":\"10117\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"10438\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"fill_color\":{\"value\":\"#dfccce\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10119\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"10430\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#dfccce\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10121\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"10439\",\"type\":\"Selection\"},{\"attributes\":{\"source\":{\"id\":\"10106\"}},\"id\":\"10111\",\"type\":\"CDSView\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#ddb7b1\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10126\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"10431\",\"type\":\"Selection\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#933b41\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10138\",\"type\":\"VBar\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10130\"},\"glyph\":{\"id\":\"10131\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10133\"},\"nonselection_glyph\":{\"id\":\"10132\"},\"view\":{\"id\":\"10135\"}},\"id\":\"10134\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#c9d9d3\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10108\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"10432\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"10433\",\"type\":\"Selection\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#550b1d\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10144\",\"type\":\"VBar\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#550b1d\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10145\",\"type\":\"VBar\"},{\"attributes\":{\"data\":{\"top\":[0,0,1,4,0,4,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10439\"},\"selection_policy\":{\"id\":\"10438\"}},\"id\":\"10142\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_color\":{\"value\":\"#550b1d\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10143\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"10434\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"10435\",\"type\":\"Selection\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10142\"},\"glyph\":{\"id\":\"10143\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10145\"},\"nonselection_glyph\":{\"id\":\"10144\"},\"view\":{\"id\":\"10147\"}},\"id\":\"10146\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"10417\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"10418\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"10420\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"10421\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"10427\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"10422\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"10423\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"10077\",\"type\":\"DataRange1d\"},{\"attributes\":{\"fill_color\":{\"value\":\"#75968f\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10095\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"10081\",\"type\":\"LinearScale\"},{\"attributes\":{\"axis_label\":\"Number of answers\",\"coordinates\":null,\"formatter\":{\"id\":\"10417\"},\"group\":null,\"major_label_policy\":{\"id\":\"10418\"},\"ticker\":{\"id\":\"10090\"}},\"id\":\"10089\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"10079\",\"type\":\"DataRange1d\"},{\"attributes\":{\"axis_label\":\"Answers\",\"coordinates\":null,\"formatter\":{\"id\":\"10420\"},\"group\":null,\"major_label_policy\":{\"id\":\"10421\"},\"ticker\":{\"id\":\"10086\"}},\"id\":\"10085\",\"type\":\"LinearAxis\"},{\"attributes\":{\"coordinates\":null,\"group\":null},\"id\":\"10075\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"10083\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"10086\",\"type\":\"BasicTicker\"},{\"attributes\":{\"axis\":{\"id\":\"10085\"},\"coordinates\":null,\"group\":null,\"ticker\":null},\"id\":\"10088\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"10424\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"axis\":{\"id\":\"10089\"},\"coordinates\":null,\"dimension\":1,\"group\":null,\"ticker\":null},\"id\":\"10092\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"10090\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"10425\",\"type\":\"Selection\"},{\"attributes\":{\"source\":{\"id\":\"10142\"}},\"id\":\"10147\",\"type\":\"CDSView\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#75968f\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10096\",\"type\":\"VBar\"},{\"attributes\":{\"logo\":null},\"id\":\"10093\",\"type\":\"Toolbar\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#75968f\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10097\",\"type\":\"VBar\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10094\"},\"glyph\":{\"id\":\"10095\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10097\"},\"nonselection_glyph\":{\"id\":\"10096\"},\"view\":{\"id\":\"10099\"}},\"id\":\"10098\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"fill_color\":{\"value\":\"#a5bab7\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10101\",\"type\":\"VBar\"},{\"attributes\":{\"data\":{\"top\":[0,0,130,128,148,272,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10423\"},\"selection_policy\":{\"id\":\"10422\"}},\"id\":\"10094\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#a5bab7\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10102\",\"type\":\"VBar\"},{\"attributes\":{\"data\":{\"top\":[0,0,47,30,52,134,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10425\"},\"selection_policy\":{\"id\":\"10424\"}},\"id\":\"10100\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"data\":{\"top\":[0,0,33,38,39,57,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10427\"},\"selection_policy\":{\"id\":\"10426\"}},\"id\":\"10106\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10100\"},\"glyph\":{\"id\":\"10101\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10103\"},\"nonselection_glyph\":{\"id\":\"10102\"},\"view\":{\"id\":\"10105\"}},\"id\":\"10104\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"source\":{\"id\":\"10094\"}},\"id\":\"10099\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"10426\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#a5bab7\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10103\",\"type\":\"VBar\"},{\"attributes\":{\"fill_color\":{\"value\":\"#c9d9d3\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10107\",\"type\":\"VBar\"},{\"attributes\":{\"source\":{\"id\":\"10100\"}},\"id\":\"10105\",\"type\":\"CDSView\"}],\"root_ids\":[\"10074\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n", - " const render_items = [{\"docid\":\"84a04889-f987-43e6-ab22-efd5a12d02e3\",\"root_ids\":[\"10074\"],\"roots\":{\"10074\":\"dadade7a-26ed-489a-9e84-a90f788095b9\"}}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"84a04889-f987-43e6-ab22-efd5a12d02e3\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"10085\"}],\"center\":[{\"id\":\"10088\"},{\"id\":\"10092\"}],\"left\":[{\"id\":\"10089\"}],\"renderers\":[{\"id\":\"10098\"},{\"id\":\"10104\"},{\"id\":\"10110\"},{\"id\":\"10116\"},{\"id\":\"10122\"},{\"id\":\"10128\"},{\"id\":\"10134\"},{\"id\":\"10140\"},{\"id\":\"10146\"}],\"title\":{\"id\":\"10075\"},\"toolbar\":{\"id\":\"10093\"},\"toolbar_location\":\"above\",\"width\":1600,\"x_range\":{\"id\":\"10077\"},\"x_scale\":{\"id\":\"10081\"},\"y_range\":{\"id\":\"10079\"},\"y_scale\":{\"id\":\"10083\"}},\"id\":\"10074\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"data\":{\"top\":[0,0,3,2,3,2,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10437\"},\"selection_policy\":{\"id\":\"10436\"}},\"id\":\"10136\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"source\":{\"id\":\"10130\"}},\"id\":\"10135\",\"type\":\"CDSView\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#e2e2e2\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10114\",\"type\":\"VBar\"},{\"attributes\":{\"data\":{\"top\":[0,0,28,29,27,33,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10429\"},\"selection_policy\":{\"id\":\"10428\"}},\"id\":\"10112\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#e2e2e2\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10115\",\"type\":\"VBar\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10118\"},\"glyph\":{\"id\":\"10119\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10121\"},\"nonselection_glyph\":{\"id\":\"10120\"},\"view\":{\"id\":\"10123\"}},\"id\":\"10122\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#c9d9d3\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10109\",\"type\":\"VBar\"},{\"attributes\":{\"data\":{\"top\":[0,0,9,12,6,4,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10433\"},\"selection_policy\":{\"id\":\"10432\"}},\"id\":\"10124\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10106\"},\"glyph\":{\"id\":\"10107\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10109\"},\"nonselection_glyph\":{\"id\":\"10108\"},\"view\":{\"id\":\"10111\"}},\"id\":\"10110\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"source\":{\"id\":\"10118\"}},\"id\":\"10123\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"10436\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"fill_color\":{\"value\":\"#ddb7b1\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10125\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"10428\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10136\"},\"glyph\":{\"id\":\"10137\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10139\"},\"nonselection_glyph\":{\"id\":\"10138\"},\"view\":{\"id\":\"10141\"}},\"id\":\"10140\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"10437\",\"type\":\"Selection\"},{\"attributes\":{\"fill_color\":{\"value\":\"#cc7878\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10131\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"10429\",\"type\":\"Selection\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#ddb7b1\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10127\",\"type\":\"VBar\"},{\"attributes\":{\"fill_color\":{\"value\":\"#933b41\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10137\",\"type\":\"VBar\"},{\"attributes\":{\"data\":{\"top\":[0,0,8,11,18,32,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10431\"},\"selection_policy\":{\"id\":\"10430\"}},\"id\":\"10118\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"data\":{\"top\":[0,0,1,2,3,6,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10435\"},\"selection_policy\":{\"id\":\"10434\"}},\"id\":\"10130\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"source\":{\"id\":\"10136\"}},\"id\":\"10141\",\"type\":\"CDSView\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10124\"},\"glyph\":{\"id\":\"10125\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10127\"},\"nonselection_glyph\":{\"id\":\"10126\"},\"view\":{\"id\":\"10129\"}},\"id\":\"10128\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"fill_color\":{\"value\":\"#e2e2e2\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10113\",\"type\":\"VBar\"},{\"attributes\":{\"source\":{\"id\":\"10124\"}},\"id\":\"10129\",\"type\":\"CDSView\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#cc7878\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10133\",\"type\":\"VBar\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#cc7878\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10132\",\"type\":\"VBar\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#dfccce\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10120\",\"type\":\"VBar\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#933b41\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10139\",\"type\":\"VBar\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10112\"},\"glyph\":{\"id\":\"10113\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10115\"},\"nonselection_glyph\":{\"id\":\"10114\"},\"view\":{\"id\":\"10117\"}},\"id\":\"10116\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"source\":{\"id\":\"10112\"}},\"id\":\"10117\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"10438\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"fill_color\":{\"value\":\"#dfccce\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10119\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"10430\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#dfccce\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10121\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"10439\",\"type\":\"Selection\"},{\"attributes\":{\"source\":{\"id\":\"10106\"}},\"id\":\"10111\",\"type\":\"CDSView\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#ddb7b1\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10126\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"10431\",\"type\":\"Selection\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#933b41\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10138\",\"type\":\"VBar\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10130\"},\"glyph\":{\"id\":\"10131\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10133\"},\"nonselection_glyph\":{\"id\":\"10132\"},\"view\":{\"id\":\"10135\"}},\"id\":\"10134\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#c9d9d3\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10108\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"10432\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"10433\",\"type\":\"Selection\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#550b1d\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10144\",\"type\":\"VBar\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#550b1d\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10145\",\"type\":\"VBar\"},{\"attributes\":{\"data\":{\"top\":[0,0,1,4,0,4,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10439\"},\"selection_policy\":{\"id\":\"10438\"}},\"id\":\"10142\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_color\":{\"value\":\"#550b1d\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10143\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"10434\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"10435\",\"type\":\"Selection\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10142\"},\"glyph\":{\"id\":\"10143\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10145\"},\"nonselection_glyph\":{\"id\":\"10144\"},\"view\":{\"id\":\"10147\"}},\"id\":\"10146\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"10417\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"10418\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"10420\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"10421\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"10427\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"10422\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"10423\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"10077\",\"type\":\"DataRange1d\"},{\"attributes\":{\"fill_color\":{\"value\":\"#75968f\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10095\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"10081\",\"type\":\"LinearScale\"},{\"attributes\":{\"axis_label\":\"Number of answers\",\"coordinates\":null,\"formatter\":{\"id\":\"10417\"},\"group\":null,\"major_label_policy\":{\"id\":\"10418\"},\"ticker\":{\"id\":\"10090\"}},\"id\":\"10089\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"10079\",\"type\":\"DataRange1d\"},{\"attributes\":{\"axis_label\":\"Answers\",\"coordinates\":null,\"formatter\":{\"id\":\"10420\"},\"group\":null,\"major_label_policy\":{\"id\":\"10421\"},\"ticker\":{\"id\":\"10086\"}},\"id\":\"10085\",\"type\":\"LinearAxis\"},{\"attributes\":{\"coordinates\":null,\"group\":null},\"id\":\"10075\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"10083\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"10086\",\"type\":\"BasicTicker\"},{\"attributes\":{\"axis\":{\"id\":\"10085\"},\"coordinates\":null,\"group\":null,\"ticker\":null},\"id\":\"10088\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"10424\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"axis\":{\"id\":\"10089\"},\"coordinates\":null,\"dimension\":1,\"group\":null,\"ticker\":null},\"id\":\"10092\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"10090\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"10425\",\"type\":\"Selection\"},{\"attributes\":{\"source\":{\"id\":\"10142\"}},\"id\":\"10147\",\"type\":\"CDSView\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#75968f\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10096\",\"type\":\"VBar\"},{\"attributes\":{\"logo\":null},\"id\":\"10093\",\"type\":\"Toolbar\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#75968f\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10097\",\"type\":\"VBar\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10094\"},\"glyph\":{\"id\":\"10095\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10097\"},\"nonselection_glyph\":{\"id\":\"10096\"},\"view\":{\"id\":\"10099\"}},\"id\":\"10098\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"fill_color\":{\"value\":\"#a5bab7\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10101\",\"type\":\"VBar\"},{\"attributes\":{\"data\":{\"top\":[0,0,130,128,148,272,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10423\"},\"selection_policy\":{\"id\":\"10422\"}},\"id\":\"10094\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#a5bab7\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10102\",\"type\":\"VBar\"},{\"attributes\":{\"data\":{\"top\":[0,0,47,30,52,134,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10425\"},\"selection_policy\":{\"id\":\"10424\"}},\"id\":\"10100\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"data\":{\"top\":[0,0,33,38,39,57,0],\"x\":[\"Director (of the institute)\",\"Other\",\"PhD student\",\"Postdoc\",\"Principal Investigator\",\"Research associate\",\"Undergraduate / Masters student\"]},\"selected\":{\"id\":\"10427\"},\"selection_policy\":{\"id\":\"10426\"}},\"id\":\"10106\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"10100\"},\"glyph\":{\"id\":\"10101\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"10103\"},\"nonselection_glyph\":{\"id\":\"10102\"},\"view\":{\"id\":\"10105\"}},\"id\":\"10104\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"source\":{\"id\":\"10094\"}},\"id\":\"10099\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"10426\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#a5bab7\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10103\",\"type\":\"VBar\"},{\"attributes\":{\"fill_color\":{\"value\":\"#c9d9d3\"},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"top\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"x\"}},\"id\":\"10107\",\"type\":\"VBar\"},{\"attributes\":{\"source\":{\"id\":\"10100\"}},\"id\":\"10105\",\"type\":\"CDSView\"}],\"root_ids\":[\"10074\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n const render_items = [{\"docid\":\"84a04889-f987-43e6-ab22-efd5a12d02e3\",\"root_ids\":[\"10074\"],\"roots\":{\"10074\":\"dadade7a-26ed-489a-9e84-a90f788095b9\"}}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -3989,32 +3250,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"a983ee7e-6367-4894-8bd8-ca993559b78c\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"1706\"}],\"center\":[{\"id\":\"1708\"},{\"id\":\"1712\"}],\"left\":[{\"id\":\"1709\"}],\"renderers\":[{\"id\":\"1720\"}],\"title\":{\"id\":\"1697\"},\"toolbar\":{\"id\":\"1714\"},\"toolbar_location\":null,\"x_range\":{\"id\":\"1695\"},\"x_scale\":{\"id\":\"1702\"},\"y_range\":{\"id\":\"1700\"},\"y_scale\":{\"id\":\"1704\"}},\"id\":\"1696\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{},\"id\":\"1784\",\"type\":\"Selection\"},{\"attributes\":{\"axis_label\":\"Answers\",\"coordinates\":null,\"formatter\":{\"id\":\"1781\"},\"group\":null,\"major_label_orientation\":1,\"major_label_policy\":{\"id\":\"1782\"},\"ticker\":{\"id\":\"1707\"}},\"id\":\"1706\",\"type\":\"CategoricalAxis\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"1693\"},\"glyph\":{\"id\":\"1717\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"1719\"},\"nonselection_glyph\":{\"id\":\"1718\"},\"view\":{\"id\":\"1721\"}},\"id\":\"1720\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"1779\",\"type\":\"AllLabels\"},{\"attributes\":{\"fill_color\":{\"field\":\"value\",\"transform\":{\"id\":\"1694\"}},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"counts\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"value\"}},\"id\":\"1717\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"1783\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"1778\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"data\":{\"color\":[\"#3182bd\",\"#6baed6\",\"#9ecae1\",\"#c6dbef\",\"#e6550d\",\"#fd8d3c\",\"#fdae6b\",\"#fdd0a2\",\"#31a354\",\"#74c476\",\"#a1d99b\",\"#c7e9c0\",\"#756bb1\",\"#9e9ac8\",\"#bcbddc\",\"#dadaeb\",\"#636363\",\"#969696\"],\"counts\":[2,5,3,1,3,2,4,3,4,3,2,4,2,4,5,4,6,3],\"value\":[[\"Apples\",\"2015\"],[\"Apples\",\"2016\"],[\"Apples\",\"2017\"],[\"Pears\",\"2015\"],[\"Pears\",\"2016\"],[\"Pears\",\"2017\"],[\"Nectarines\",\"2015\"],[\"Nectarines\",\"2016\"],[\"Nectarines\",\"2017\"],[\"Plums\",\"2015\"],[\"Plums\",\"2016\"],[\"Plums\",\"2017\"],[\"Grapes\",\"2015\"],[\"Grapes\",\"2016\"],[\"Grapes\",\"2017\"],[\"Strawberries\",\"2015\"],[\"Strawberries\",\"2016\"],[\"Strawberries\",\"2017\"]]},\"selected\":{\"id\":\"1784\"},\"selection_policy\":{\"id\":\"1783\"}},\"id\":\"1693\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"factors\":[[\"Apples\",\"2015\"],[\"Apples\",\"2016\"],[\"Apples\",\"2017\"],[\"Pears\",\"2015\"],[\"Pears\",\"2016\"],[\"Pears\",\"2017\"],[\"Nectarines\",\"2015\"],[\"Nectarines\",\"2016\"],[\"Nectarines\",\"2017\"],[\"Plums\",\"2015\"],[\"Plums\",\"2016\"],[\"Plums\",\"2017\"],[\"Grapes\",\"2015\"],[\"Grapes\",\"2016\"],[\"Grapes\",\"2017\"],[\"Strawberries\",\"2015\"],[\"Strawberries\",\"2016\"],[\"Strawberries\",\"2017\"]],\"range_padding\":0.1},\"id\":\"1695\",\"type\":\"FactorRange\"},{\"attributes\":{\"end\":2,\"factors\":[\"2015\",\"2016\",\"2017\"],\"palette\":[\"#3182bd\",\"#6baed6\",\"#9ecae1\",\"#c6dbef\",\"#e6550d\",\"#fd8d3c\",\"#fdae6b\"],\"start\":1},\"id\":\"1694\",\"type\":\"CategoricalColorMapper\"},{\"attributes\":{\"source\":{\"id\":\"1693\"}},\"id\":\"1721\",\"type\":\"CDSView\"},{\"attributes\":{\"tools\":[{\"id\":\"1713\"}]},\"id\":\"1714\",\"type\":\"Toolbar\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"field\":\"value\",\"transform\":{\"id\":\"1694\"}},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"counts\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"value\"}},\"id\":\"1719\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"1710\",\"type\":\"BasicTicker\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"field\":\"value\",\"transform\":{\"id\":\"1694\"}},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"counts\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"value\"}},\"id\":\"1718\",\"type\":\"VBar\"},{\"attributes\":{\"axis_label\":\"Number of answers\",\"coordinates\":null,\"formatter\":{\"id\":\"1778\"},\"group\":null,\"major_label_policy\":{\"id\":\"1779\"},\"ticker\":{\"id\":\"1710\"}},\"id\":\"1709\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"1707\",\"type\":\"CategoricalTicker\"},{\"attributes\":{\"axis\":{\"id\":\"1706\"},\"coordinates\":null,\"grid_line_color\":null,\"group\":null,\"ticker\":null},\"id\":\"1708\",\"type\":\"Grid\"},{\"attributes\":{\"axis\":{\"id\":\"1709\"},\"coordinates\":null,\"dimension\":1,\"group\":null,\"ticker\":null},\"id\":\"1712\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"1782\",\"type\":\"AllLabels\"},{\"attributes\":{\"start\":0},\"id\":\"1700\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"1702\",\"type\":\"CategoricalScale\"},{\"attributes\":{\"coordinates\":null,\"group\":null},\"id\":\"1697\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"1704\",\"type\":\"LinearScale\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"Data\",\"@value\"],[\"Count\",\"@counts\"]]},\"id\":\"1713\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"1781\",\"type\":\"CategoricalTickFormatter\"}],\"root_ids\":[\"1696\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n", - " const render_items = [{\"docid\":\"a983ee7e-6367-4894-8bd8-ca993559b78c\",\"root_ids\":[\"1696\"],\"roots\":{\"1696\":\"e05d72db-7a9d-4fef-8ab7-7e82c89629e3\"}}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"a983ee7e-6367-4894-8bd8-ca993559b78c\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"1706\"}],\"center\":[{\"id\":\"1708\"},{\"id\":\"1712\"}],\"left\":[{\"id\":\"1709\"}],\"renderers\":[{\"id\":\"1720\"}],\"title\":{\"id\":\"1697\"},\"toolbar\":{\"id\":\"1714\"},\"toolbar_location\":null,\"x_range\":{\"id\":\"1695\"},\"x_scale\":{\"id\":\"1702\"},\"y_range\":{\"id\":\"1700\"},\"y_scale\":{\"id\":\"1704\"}},\"id\":\"1696\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{},\"id\":\"1784\",\"type\":\"Selection\"},{\"attributes\":{\"axis_label\":\"Answers\",\"coordinates\":null,\"formatter\":{\"id\":\"1781\"},\"group\":null,\"major_label_orientation\":1,\"major_label_policy\":{\"id\":\"1782\"},\"ticker\":{\"id\":\"1707\"}},\"id\":\"1706\",\"type\":\"CategoricalAxis\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"1693\"},\"glyph\":{\"id\":\"1717\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"1719\"},\"nonselection_glyph\":{\"id\":\"1718\"},\"view\":{\"id\":\"1721\"}},\"id\":\"1720\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"1779\",\"type\":\"AllLabels\"},{\"attributes\":{\"fill_color\":{\"field\":\"value\",\"transform\":{\"id\":\"1694\"}},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"counts\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"value\"}},\"id\":\"1717\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"1783\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"1778\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"data\":{\"color\":[\"#3182bd\",\"#6baed6\",\"#9ecae1\",\"#c6dbef\",\"#e6550d\",\"#fd8d3c\",\"#fdae6b\",\"#fdd0a2\",\"#31a354\",\"#74c476\",\"#a1d99b\",\"#c7e9c0\",\"#756bb1\",\"#9e9ac8\",\"#bcbddc\",\"#dadaeb\",\"#636363\",\"#969696\"],\"counts\":[2,5,3,1,3,2,4,3,4,3,2,4,2,4,5,4,6,3],\"value\":[[\"Apples\",\"2015\"],[\"Apples\",\"2016\"],[\"Apples\",\"2017\"],[\"Pears\",\"2015\"],[\"Pears\",\"2016\"],[\"Pears\",\"2017\"],[\"Nectarines\",\"2015\"],[\"Nectarines\",\"2016\"],[\"Nectarines\",\"2017\"],[\"Plums\",\"2015\"],[\"Plums\",\"2016\"],[\"Plums\",\"2017\"],[\"Grapes\",\"2015\"],[\"Grapes\",\"2016\"],[\"Grapes\",\"2017\"],[\"Strawberries\",\"2015\"],[\"Strawberries\",\"2016\"],[\"Strawberries\",\"2017\"]]},\"selected\":{\"id\":\"1784\"},\"selection_policy\":{\"id\":\"1783\"}},\"id\":\"1693\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"factors\":[[\"Apples\",\"2015\"],[\"Apples\",\"2016\"],[\"Apples\",\"2017\"],[\"Pears\",\"2015\"],[\"Pears\",\"2016\"],[\"Pears\",\"2017\"],[\"Nectarines\",\"2015\"],[\"Nectarines\",\"2016\"],[\"Nectarines\",\"2017\"],[\"Plums\",\"2015\"],[\"Plums\",\"2016\"],[\"Plums\",\"2017\"],[\"Grapes\",\"2015\"],[\"Grapes\",\"2016\"],[\"Grapes\",\"2017\"],[\"Strawberries\",\"2015\"],[\"Strawberries\",\"2016\"],[\"Strawberries\",\"2017\"]],\"range_padding\":0.1},\"id\":\"1695\",\"type\":\"FactorRange\"},{\"attributes\":{\"end\":2,\"factors\":[\"2015\",\"2016\",\"2017\"],\"palette\":[\"#3182bd\",\"#6baed6\",\"#9ecae1\",\"#c6dbef\",\"#e6550d\",\"#fd8d3c\",\"#fdae6b\"],\"start\":1},\"id\":\"1694\",\"type\":\"CategoricalColorMapper\"},{\"attributes\":{\"source\":{\"id\":\"1693\"}},\"id\":\"1721\",\"type\":\"CDSView\"},{\"attributes\":{\"tools\":[{\"id\":\"1713\"}]},\"id\":\"1714\",\"type\":\"Toolbar\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"field\":\"value\",\"transform\":{\"id\":\"1694\"}},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"counts\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"value\"}},\"id\":\"1719\",\"type\":\"VBar\"},{\"attributes\":{},\"id\":\"1710\",\"type\":\"BasicTicker\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"field\":\"value\",\"transform\":{\"id\":\"1694\"}},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"white\"},\"top\":{\"field\":\"counts\"},\"width\":{\"value\":0.9},\"x\":{\"field\":\"value\"}},\"id\":\"1718\",\"type\":\"VBar\"},{\"attributes\":{\"axis_label\":\"Number of answers\",\"coordinates\":null,\"formatter\":{\"id\":\"1778\"},\"group\":null,\"major_label_policy\":{\"id\":\"1779\"},\"ticker\":{\"id\":\"1710\"}},\"id\":\"1709\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"1707\",\"type\":\"CategoricalTicker\"},{\"attributes\":{\"axis\":{\"id\":\"1706\"},\"coordinates\":null,\"grid_line_color\":null,\"group\":null,\"ticker\":null},\"id\":\"1708\",\"type\":\"Grid\"},{\"attributes\":{\"axis\":{\"id\":\"1709\"},\"coordinates\":null,\"dimension\":1,\"group\":null,\"ticker\":null},\"id\":\"1712\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"1782\",\"type\":\"AllLabels\"},{\"attributes\":{\"start\":0},\"id\":\"1700\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"1702\",\"type\":\"CategoricalScale\"},{\"attributes\":{\"coordinates\":null,\"group\":null},\"id\":\"1697\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"1704\",\"type\":\"LinearScale\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"Data\",\"@value\"],[\"Count\",\"@counts\"]]},\"id\":\"1713\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"1781\",\"type\":\"CategoricalTickFormatter\"}],\"root_ids\":[\"1696\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n const render_items = [{\"docid\":\"a983ee7e-6367-4894-8bd8-ca993559b78c\",\"root_ids\":[\"1696\"],\"roots\":{\"1696\":\"e05d72db-7a9d-4fef-8ab7-7e82c89629e3\"}}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -4101,32 +3337,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"db39efc1-2295-4dcf-9b25-ea1b533d9eab\":{\"version\":\"3.0.0.dev13\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"32582\",\"attributes\":{\"y_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"32592\"},\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"32588\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"HoverTool\",\"id\":\"32612\",\"attributes\":{\"renderers\":\"auto\",\"tooltips\":[[\"Data\",\"@value\"],[\"Percent\",\"@percent{0.00%}\"],[\"Count\",\"@counts\"]]}},{\"type\":\"object\",\"name\":\"TapTool\",\"id\":\"32613\",\"attributes\":{\"renderers\":\"auto\"}}]}},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"32605\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"32607\"},\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"32606\"},\"visible\":false,\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"32608\",\"attributes\":{\"mantissas\":[1,2,5]}}}}],\"below\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"32598\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"32600\"},\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"32599\"},\"visible\":false,\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"32601\",\"attributes\":{\"mantissas\":[1,2,5]}}}}],\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"32596\"},\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"32604\",\"attributes\":{\"axis\":{\"id\":\"32598\"},\"grid_line_color\":null}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"32611\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"32605\"},\"grid_line_color\":null}},{\"type\":\"object\",\"name\":\"Legend\",\"id\":\"32645\",\"attributes\":{\"items\":[{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"32646\",\"attributes\":{\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"32630\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"Wedge\",\"id\":\"32627\",\"attributes\":{\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"end_angle\":{\"type\":\"expr\",\"expr\":{\"type\":\"object\",\"name\":\"CumSum\",\"id\":\"32618\",\"attributes\":{\"field\":\"angle\"}}},\"x\":{\"type\":\"value\",\"value\":0},\"radius\":{\"type\":\"value\",\"value\":0.6},\"y\":{\"type\":\"value\",\"value\":1},\"start_angle\":{\"type\":\"expr\",\"expr\":{\"type\":\"object\",\"name\":\"CumSum\",\"id\":\"32617\",\"attributes\":{\"include_zero\":true,\"field\":\"angle\"}}}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"Wedge\",\"id\":\"32628\",\"attributes\":{\"fill_color\":{\"type\":\"field\",\"field\":\"color\"},\"end_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"32618\"}},\"x\":{\"type\":\"value\",\"value\":0},\"radius\":{\"type\":\"value\",\"value\":0.6},\"y\":{\"type\":\"value\",\"value\":1},\"line_width\":{\"type\":\"value\",\"value\":5.0},\"start_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"32617\"}}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Wedge\",\"id\":\"32629\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"white\"},\"fill_color\":{\"type\":\"field\",\"field\":\"color\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"end_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"32618\"}},\"x\":{\"type\":\"value\",\"value\":0},\"radius\":{\"type\":\"value\",\"value\":0.6},\"y\":{\"type\":\"value\",\"value\":1},\"start_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"32617\"}},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Wedge\",\"id\":\"32626\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"white\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.5},\"end_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"32618\"}},\"x\":{\"type\":\"value\",\"value\":0},\"radius\":{\"type\":\"value\",\"value\":0.6},\"y\":{\"type\":\"value\",\"value\":1},\"start_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"32617\"}},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"32631\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"32632\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"32619\",\"attributes\":{\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"32621\"},\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"32620\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"index\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"value\",{\"type\":\"ndarray\",\"array\":[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\"],\"shape\":[7],\"dtype\":\"object\",\"order\":\"little\"}],[\"counts\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"bwAAAAsBAACTAwAAHwIAADcEAACZAQAAOAMAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"xlabel\",{\"type\":\"ndarray\",\"array\":[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\"],\"shape\":[7],\"dtype\":\"object\",\"order\":\"little\"}],[\"angle\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"hnyU/4WFxT9iC7aXUeLZP43r/+8KLfY/EwBTjf9R6j9cvQc8kSb6P2nho9I20+M/Togtz3D48z8=\"},\"shape\":[7],\"dtype\":\"float64\",\"order\":\"little\"}],[\"color\",{\"type\":\"ndarray\",\"array\":[\"#3182bd\",\"#6baed6\",\"#9ecae1\",\"#c6dbef\",\"#e6550d\",\"#fd8d3c\",\"#fdae6b\"],\"shape\":[7],\"dtype\":\"object\",\"order\":\"little\"}],[\"percent\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"/idWb/Fmmz/OrFQNcnqwPzw8PDw8PMw/4whM/IrBwD8wLEHY5KXQPwfqfJ72Pbk/FdIhk1xtyT8=\"},\"shape\":[7],\"dtype\":\"float64\",\"order\":\"little\"}]]}}},\"glyph\":{\"type\":\"object\",\"name\":\"Wedge\",\"id\":\"32625\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.8},\"line_color\":{\"type\":\"value\",\"value\":\"white\"},\"fill_color\":{\"type\":\"field\",\"field\":\"color\"},\"end_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"32618\"}},\"x\":{\"type\":\"value\",\"value\":0},\"radius\":{\"type\":\"value\",\"value\":0.6},\"y\":{\"type\":\"value\",\"value\":1},\"start_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"32617\"}}}}}}],\"label\":{\"type\":\"field\",\"field\":\"xlabel\"}}}]}}],\"toolbar_location\":null,\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"32583\"},\"x_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"32594\"},\"x_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"32590\"},\"renderers\":[{\"id\":\"32630\"}]}}]}};\n", - " const render_items = [{\"docid\":\"db39efc1-2295-4dcf-9b25-ea1b533d9eab\",\"roots\":{\"32582\":\"b67c0339-b1e4-4a84-b226-967788726673\"},\"root_ids\":[\"32582\"]}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"db39efc1-2295-4dcf-9b25-ea1b533d9eab\":{\"version\":\"3.0.0.dev13\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"32582\",\"attributes\":{\"y_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"32592\"},\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"32588\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"HoverTool\",\"id\":\"32612\",\"attributes\":{\"renderers\":\"auto\",\"tooltips\":[[\"Data\",\"@value\"],[\"Percent\",\"@percent{0.00%}\"],[\"Count\",\"@counts\"]]}},{\"type\":\"object\",\"name\":\"TapTool\",\"id\":\"32613\",\"attributes\":{\"renderers\":\"auto\"}}]}},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"32605\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"32607\"},\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"32606\"},\"visible\":false,\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"32608\",\"attributes\":{\"mantissas\":[1,2,5]}}}}],\"below\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"32598\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"32600\"},\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"32599\"},\"visible\":false,\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"32601\",\"attributes\":{\"mantissas\":[1,2,5]}}}}],\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"32596\"},\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"32604\",\"attributes\":{\"axis\":{\"id\":\"32598\"},\"grid_line_color\":null}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"32611\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"32605\"},\"grid_line_color\":null}},{\"type\":\"object\",\"name\":\"Legend\",\"id\":\"32645\",\"attributes\":{\"items\":[{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"32646\",\"attributes\":{\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"32630\",\"attributes\":{\"selection_glyph\":{\"type\":\"object\",\"name\":\"Wedge\",\"id\":\"32627\",\"attributes\":{\"fill_color\":{\"type\":\"value\",\"value\":\"black\"},\"end_angle\":{\"type\":\"expr\",\"expr\":{\"type\":\"object\",\"name\":\"CumSum\",\"id\":\"32618\",\"attributes\":{\"field\":\"angle\"}}},\"x\":{\"type\":\"value\",\"value\":0},\"radius\":{\"type\":\"value\",\"value\":0.6},\"y\":{\"type\":\"value\",\"value\":1},\"start_angle\":{\"type\":\"expr\",\"expr\":{\"type\":\"object\",\"name\":\"CumSum\",\"id\":\"32617\",\"attributes\":{\"include_zero\":true,\"field\":\"angle\"}}}}},\"hover_glyph\":{\"type\":\"object\",\"name\":\"Wedge\",\"id\":\"32628\",\"attributes\":{\"fill_color\":{\"type\":\"field\",\"field\":\"color\"},\"end_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"32618\"}},\"x\":{\"type\":\"value\",\"value\":0},\"radius\":{\"type\":\"value\",\"value\":0.6},\"y\":{\"type\":\"value\",\"value\":1},\"line_width\":{\"type\":\"value\",\"value\":5.0},\"start_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"32617\"}}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Wedge\",\"id\":\"32629\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"white\"},\"fill_color\":{\"type\":\"field\",\"field\":\"color\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"end_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"32618\"}},\"x\":{\"type\":\"value\",\"value\":0},\"radius\":{\"type\":\"value\",\"value\":0.6},\"y\":{\"type\":\"value\",\"value\":1},\"start_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"32617\"}},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Wedge\",\"id\":\"32626\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"white\"},\"fill_color\":{\"type\":\"value\",\"value\":\"blue\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.5},\"end_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"32618\"}},\"x\":{\"type\":\"value\",\"value\":0},\"radius\":{\"type\":\"value\",\"value\":0.6},\"y\":{\"type\":\"value\",\"value\":1},\"start_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"32617\"}},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"32631\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"32632\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"32619\",\"attributes\":{\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"32621\"},\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"32620\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"index\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"value\",{\"type\":\"ndarray\",\"array\":[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\"],\"shape\":[7],\"dtype\":\"object\",\"order\":\"little\"}],[\"counts\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"bwAAAAsBAACTAwAAHwIAADcEAACZAQAAOAMAAA==\"},\"shape\":[7],\"dtype\":\"int32\",\"order\":\"little\"}],[\"xlabel\",{\"type\":\"ndarray\",\"array\":[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\"],\"shape\":[7],\"dtype\":\"object\",\"order\":\"little\"}],[\"angle\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"hnyU/4WFxT9iC7aXUeLZP43r/+8KLfY/EwBTjf9R6j9cvQc8kSb6P2nho9I20+M/Togtz3D48z8=\"},\"shape\":[7],\"dtype\":\"float64\",\"order\":\"little\"}],[\"color\",{\"type\":\"ndarray\",\"array\":[\"#3182bd\",\"#6baed6\",\"#9ecae1\",\"#c6dbef\",\"#e6550d\",\"#fd8d3c\",\"#fdae6b\"],\"shape\":[7],\"dtype\":\"object\",\"order\":\"little\"}],[\"percent\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"/idWb/Fmmz/OrFQNcnqwPzw8PDw8PMw/4whM/IrBwD8wLEHY5KXQPwfqfJ72Pbk/FdIhk1xtyT8=\"},\"shape\":[7],\"dtype\":\"float64\",\"order\":\"little\"}]]}}},\"glyph\":{\"type\":\"object\",\"name\":\"Wedge\",\"id\":\"32625\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.8},\"line_color\":{\"type\":\"value\",\"value\":\"white\"},\"fill_color\":{\"type\":\"field\",\"field\":\"color\"},\"end_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"32618\"}},\"x\":{\"type\":\"value\",\"value\":0},\"radius\":{\"type\":\"value\",\"value\":0.6},\"y\":{\"type\":\"value\",\"value\":1},\"start_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"32617\"}}}}}}],\"label\":{\"type\":\"field\",\"field\":\"xlabel\"}}}]}}],\"toolbar_location\":null,\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"32583\"},\"x_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"32594\"},\"x_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"32590\"},\"renderers\":[{\"id\":\"32630\"}]}}]}};\n const render_items = [{\"docid\":\"db39efc1-2295-4dcf-9b25-ea1b533d9eab\",\"roots\":{\"32582\":\"b67c0339-b1e4-4a84-b226-967788726673\"},\"root_ids\":[\"32582\"]}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -4252,32 +3463,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"f7d9e2b2-e6b6-445f-bcc6-6bf9312ff27e\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"1998\"}],\"center\":[{\"id\":\"2001\"},{\"id\":\"2005\"},{\"id\":\"2053\"}],\"left\":[{\"id\":\"2002\"}],\"renderers\":[{\"id\":\"2040\"},{\"id\":\"2064\"},{\"id\":\"2089\"},{\"id\":\"2116\"},{\"id\":\"2145\"},{\"id\":\"2176\"},{\"id\":\"2209\"}],\"title\":{\"id\":\"2033\"},\"toolbar\":{\"id\":\"2020\"},\"x_range\":{\"id\":\"1990\"},\"x_scale\":{\"id\":\"1994\"},\"y_range\":{\"id\":\"1992\"},\"y_scale\":{\"id\":\"1996\"}},\"id\":\"1989\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"overlay\":{\"id\":\"2019\"}},\"id\":\"2007\",\"type\":\"PolySelectTool\"},{\"attributes\":{\"callback\":null},\"id\":\"2008\",\"type\":\"TapTool\"},{\"attributes\":{},\"id\":\"1999\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"2009\",\"type\":\"WheelZoomTool\"},{\"attributes\":{\"overlay\":{\"id\":\"2018\"}},\"id\":\"2010\",\"type\":\"BoxZoomTool\"},{\"attributes\":{},\"id\":\"2013\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"2014\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"2011\",\"type\":\"RedoTool\"},{\"attributes\":{},\"id\":\"2012\",\"type\":\"UndoTool\"},{\"attributes\":{},\"id\":\"2015\",\"type\":\"CrosshairTool\"},{\"attributes\":{},\"id\":\"2016\",\"type\":\"ZoomOutTool\"},{\"attributes\":{},\"id\":\"2017\",\"type\":\"ZoomInTool\"},{\"attributes\":{\"bottom_units\":\"screen\",\"coordinates\":null,\"fill_alpha\":0.5,\"fill_color\":\"lightgrey\",\"group\":null,\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":1.0,\"line_color\":\"black\",\"line_dash\":[4,4],\"line_width\":2,\"right_units\":\"screen\",\"syncable\":false,\"top_units\":\"screen\"},\"id\":\"2018\",\"type\":\"BoxAnnotation\"},{\"attributes\":{\"label\":{\"value\":\"x_1\"},\"renderers\":[{\"id\":\"2064\"}]},\"id\":\"2079\",\"type\":\"LegendItem\"},{\"attributes\":{\"callback\":null,\"renderers\":[{\"id\":\"2040\"}],\"toggleable\":false,\"tooltips\":[[\"X\",\"@x_0\"],[\"Y\",\"@y_0\"]]},\"id\":\"2055\",\"type\":\"HoverTool\"},{\"attributes\":{\"coordinates\":null,\"fill_alpha\":0.5,\"fill_color\":\"lightgrey\",\"group\":null,\"level\":\"overlay\",\"line_alpha\":1.0,\"line_color\":\"black\",\"line_dash\":[4,4],\"line_width\":2,\"syncable\":false,\"xs_units\":\"screen\",\"ys_units\":\"screen\"},\"id\":\"2019\",\"type\":\"PolyAnnotation\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"2035\"},\"glyph\":{\"id\":\"2037\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"2039\"},\"name\":\"x_0\",\"nonselection_glyph\":{\"id\":\"2038\"},\"view\":{\"id\":\"2041\"}},\"id\":\"2040\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"data\":{\"x_1\":[\"1\"],\"y_1\":[886]},\"selected\":{\"id\":\"2076\"},\"selection_policy\":{\"id\":\"2075\"}},\"id\":\"2059\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_color\":{\"value\":\"#ff7f0e\"},\"hatch_color\":{\"value\":\"#ff7f0e\"},\"line_color\":{\"value\":\"#ff7f0e\"},\"size\":{\"value\":7},\"x\":{\"field\":\"x_1\"},\"y\":{\"field\":\"y_1\"}},\"id\":\"2061\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#ff7f0e\"},\"hatch_alpha\":{\"value\":0.1},\"hatch_color\":{\"value\":\"#ff7f0e\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#ff7f0e\"},\"size\":{\"value\":7},\"x\":{\"field\":\"x_1\"},\"y\":{\"field\":\"y_1\"}},\"id\":\"2062\",\"type\":\"Scatter\"},{\"attributes\":{},\"id\":\"2044\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#ff7f0e\"},\"hatch_alpha\":{\"value\":0.2},\"hatch_color\":{\"value\":\"#ff7f0e\"},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"#ff7f0e\"},\"size\":{\"value\":7},\"x\":{\"field\":\"x_1\"},\"y\":{\"field\":\"y_1\"}},\"id\":\"2063\",\"type\":\"Scatter\"},{\"attributes\":{},\"id\":\"2195\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"2059\"},\"glyph\":{\"id\":\"2061\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"2063\"},\"name\":\"x_1\",\"nonselection_glyph\":{\"id\":\"2062\"},\"view\":{\"id\":\"2065\"}},\"id\":\"2064\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"2045\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"2102\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"source\":{\"id\":\"2059\"}},\"id\":\"2065\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"2047\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"2048\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"2132\",\"type\":\"Selection\"},{\"attributes\":{\"callback\":null,\"renderers\":[{\"id\":\"2176\"}],\"toggleable\":false,\"tooltips\":[[\"X\",\"@x_5\"],[\"Y\",\"@y_5\"]]},\"id\":\"2200\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"2076\",\"type\":\"Selection\"},{\"attributes\":{\"label\":{\"value\":\"x_3\"},\"renderers\":[{\"id\":\"2116\"}]},\"id\":\"2135\",\"type\":\"LegendItem\"},{\"attributes\":{\"data\":{\"x_3\":[\"3\"],\"y_3\":[497]},\"selected\":{\"id\":\"2132\"},\"selection_policy\":{\"id\":\"2131\"}},\"id\":\"2111\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"2075\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"fill_color\":{\"value\":\"#d62728\"},\"hatch_color\":{\"value\":\"#d62728\"},\"line_color\":{\"value\":\"#d62728\"},\"size\":{\"value\":9},\"x\":{\"field\":\"x_3\"},\"y\":{\"field\":\"y_3\"}},\"id\":\"2113\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#d62728\"},\"hatch_alpha\":{\"value\":0.1},\"hatch_color\":{\"value\":\"#d62728\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#d62728\"},\"size\":{\"value\":9},\"x\":{\"field\":\"x_3\"},\"y\":{\"field\":\"y_3\"}},\"id\":\"2114\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#d62728\"},\"hatch_alpha\":{\"value\":0.2},\"hatch_color\":{\"value\":\"#d62728\"},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"#d62728\"},\"size\":{\"value\":9},\"x\":{\"field\":\"x_3\"},\"y\":{\"field\":\"y_3\"}},\"id\":\"2115\",\"type\":\"Scatter\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"2111\"},\"glyph\":{\"id\":\"2113\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"2115\"},\"name\":\"x_3\",\"nonselection_glyph\":{\"id\":\"2114\"},\"view\":{\"id\":\"2117\"}},\"id\":\"2116\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"2049\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"callback\":null,\"renderers\":[{\"id\":\"2116\"}],\"toggleable\":false,\"tooltips\":[[\"X\",\"@x_3\"],[\"Y\",\"@y_3\"]]},\"id\":\"2136\",\"type\":\"HoverTool\"},{\"attributes\":{\"source\":{\"id\":\"2111\"}},\"id\":\"2117\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"2050\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"1990\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"2131\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"1996\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"group\":null},\"id\":\"2033\",\"type\":\"Title\"},{\"attributes\":{\"label\":{\"value\":\"x_0\"},\"renderers\":[{\"id\":\"2040\"}]},\"id\":\"2054\",\"type\":\"LegendItem\"},{\"attributes\":{\"label\":{\"value\":\"x_2\"},\"renderers\":[{\"id\":\"2089\"}]},\"id\":\"2106\",\"type\":\"LegendItem\"},{\"attributes\":{\"callback\":null,\"renderers\":[{\"id\":\"2064\"}],\"toggleable\":false,\"tooltips\":[[\"X\",\"@x_1\"],[\"Y\",\"@y_1\"]]},\"id\":\"2080\",\"type\":\"HoverTool\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#1f77b4\"},\"hatch_alpha\":{\"value\":0.2},\"hatch_color\":{\"value\":\"#1f77b4\"},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"#1f77b4\"},\"size\":{\"value\":6},\"x\":{\"field\":\"x_0\"},\"y\":{\"field\":\"y_0\"}},\"id\":\"2039\",\"type\":\"Scatter\"},{\"attributes\":{\"active_inspect\":[{\"id\":\"2055\"},{\"id\":\"2080\"},{\"id\":\"2107\"},{\"id\":\"2136\"},{\"id\":\"2167\"},{\"id\":\"2200\"},{\"id\":\"2235\"}],\"tools\":[{\"id\":\"2006\"},{\"id\":\"2007\"},{\"id\":\"2008\"},{\"id\":\"2009\"},{\"id\":\"2010\"},{\"id\":\"2011\"},{\"id\":\"2012\"},{\"id\":\"2013\"},{\"id\":\"2014\"},{\"id\":\"2015\"},{\"id\":\"2016\"},{\"id\":\"2017\"},{\"id\":\"2055\"},{\"id\":\"2080\"},{\"id\":\"2107\"},{\"id\":\"2136\"},{\"id\":\"2167\"},{\"id\":\"2200\"},{\"id\":\"2235\"}]},\"id\":\"2020\",\"type\":\"Toolbar\"},{\"attributes\":{\"data\":{\"x_2\":[\"2\"],\"y_2\":[848]},\"selected\":{\"id\":\"2103\"},\"selection_policy\":{\"id\":\"2102\"}},\"id\":\"2084\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"data\":{\"x_6\":[\"6\"],\"y_6\":[823]},\"selected\":{\"id\":\"2231\"},\"selection_policy\":{\"id\":\"2230\"}},\"id\":\"2204\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"click_policy\":\"hide\",\"coordinates\":null,\"group\":null,\"items\":[{\"id\":\"2054\"},{\"id\":\"2079\"},{\"id\":\"2106\"},{\"id\":\"2135\"},{\"id\":\"2166\"},{\"id\":\"2199\"},{\"id\":\"2234\"}],\"label_text_font_size\":\"14pt\"},\"id\":\"2053\",\"type\":\"Legend\"},{\"attributes\":{\"fill_color\":{\"value\":\"#2ca02c\"},\"hatch_color\":{\"value\":\"#2ca02c\"},\"line_color\":{\"value\":\"#2ca02c\"},\"size\":{\"value\":8},\"x\":{\"field\":\"x_2\"},\"y\":{\"field\":\"y_2\"}},\"id\":\"2086\",\"type\":\"Scatter\"},{\"attributes\":{},\"id\":\"1992\",\"type\":\"DataRange1d\"},{\"attributes\":{\"data\":{\"x_0\":[\"0\"],\"y_0\":[727]},\"selected\":{\"id\":\"2050\"},\"selection_policy\":{\"id\":\"2049\"}},\"id\":\"2035\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#2ca02c\"},\"hatch_alpha\":{\"value\":0.1},\"hatch_color\":{\"value\":\"#2ca02c\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#2ca02c\"},\"size\":{\"value\":8},\"x\":{\"field\":\"x_2\"},\"y\":{\"field\":\"y_2\"}},\"id\":\"2087\",\"type\":\"Scatter\"},{\"attributes\":{\"source\":{\"id\":\"2035\"}},\"id\":\"2041\",\"type\":\"CDSView\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#2ca02c\"},\"hatch_alpha\":{\"value\":0.2},\"hatch_color\":{\"value\":\"#2ca02c\"},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"#2ca02c\"},\"size\":{\"value\":8},\"x\":{\"field\":\"x_2\"},\"y\":{\"field\":\"y_2\"}},\"id\":\"2088\",\"type\":\"Scatter\"},{\"attributes\":{},\"id\":\"2103\",\"type\":\"Selection\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"2084\"},\"glyph\":{\"id\":\"2086\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"2088\"},\"name\":\"x_2\",\"nonselection_glyph\":{\"id\":\"2087\"},\"view\":{\"id\":\"2090\"}},\"id\":\"2089\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"callback\":null,\"renderers\":[{\"id\":\"2089\"}],\"toggleable\":false,\"tooltips\":[[\"X\",\"@x_2\"],[\"Y\",\"@y_2\"]]},\"id\":\"2107\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"1994\",\"type\":\"LinearScale\"},{\"attributes\":{\"source\":{\"id\":\"2084\"}},\"id\":\"2090\",\"type\":\"CDSView\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#1f77b4\"},\"hatch_alpha\":{\"value\":0.1},\"hatch_color\":{\"value\":\"#1f77b4\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#1f77b4\"},\"size\":{\"value\":6},\"x\":{\"field\":\"x_0\"},\"y\":{\"field\":\"y_0\"}},\"id\":\"2038\",\"type\":\"Scatter\"},{\"attributes\":{},\"id\":\"2162\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"label\":{\"value\":\"x_4\"},\"renderers\":[{\"id\":\"2145\"}]},\"id\":\"2166\",\"type\":\"LegendItem\"},{\"attributes\":{\"data\":{\"x_4\":[\"4\"],\"y_4\":[444]},\"selected\":{\"id\":\"2163\"},\"selection_policy\":{\"id\":\"2162\"}},\"id\":\"2140\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_color\":{\"value\":\"#9467bd\"},\"hatch_color\":{\"value\":\"#9467bd\"},\"line_color\":{\"value\":\"#9467bd\"},\"size\":{\"value\":10},\"x\":{\"field\":\"x_4\"},\"y\":{\"field\":\"y_4\"}},\"id\":\"2142\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#9467bd\"},\"hatch_alpha\":{\"value\":0.1},\"hatch_color\":{\"value\":\"#9467bd\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#9467bd\"},\"size\":{\"value\":10},\"x\":{\"field\":\"x_4\"},\"y\":{\"field\":\"y_4\"}},\"id\":\"2143\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#9467bd\"},\"hatch_alpha\":{\"value\":0.2},\"hatch_color\":{\"value\":\"#9467bd\"},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"#9467bd\"},\"size\":{\"value\":10},\"x\":{\"field\":\"x_4\"},\"y\":{\"field\":\"y_4\"}},\"id\":\"2144\",\"type\":\"Scatter\"},{\"attributes\":{},\"id\":\"2230\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"2140\"},\"glyph\":{\"id\":\"2142\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"2144\"},\"name\":\"x_4\",\"nonselection_glyph\":{\"id\":\"2143\"},\"view\":{\"id\":\"2146\"}},\"id\":\"2145\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#e377c2\"},\"hatch_alpha\":{\"value\":0.1},\"hatch_color\":{\"value\":\"#e377c2\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#e377c2\"},\"size\":{\"value\":12},\"x\":{\"field\":\"x_6\"},\"y\":{\"field\":\"y_6\"}},\"id\":\"2207\",\"type\":\"Scatter\"},{\"attributes\":{\"label\":{\"value\":\"x_6\"},\"renderers\":[{\"id\":\"2209\"}]},\"id\":\"2234\",\"type\":\"LegendItem\"},{\"attributes\":{\"source\":{\"id\":\"2140\"}},\"id\":\"2146\",\"type\":\"CDSView\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#e377c2\"},\"hatch_alpha\":{\"value\":0.2},\"hatch_color\":{\"value\":\"#e377c2\"},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"#e377c2\"},\"size\":{\"value\":12},\"x\":{\"field\":\"x_6\"},\"y\":{\"field\":\"y_6\"}},\"id\":\"2208\",\"type\":\"Scatter\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"2204\"},\"glyph\":{\"id\":\"2206\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"2208\"},\"name\":\"x_6\",\"nonselection_glyph\":{\"id\":\"2207\"},\"view\":{\"id\":\"2210\"}},\"id\":\"2209\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"2163\",\"type\":\"Selection\"},{\"attributes\":{\"source\":{\"id\":\"2204\"}},\"id\":\"2210\",\"type\":\"CDSView\"},{\"attributes\":{\"callback\":null,\"renderers\":[{\"id\":\"2209\"}],\"toggleable\":false,\"tooltips\":[[\"X\",\"@x_6\"],[\"Y\",\"@y_6\"]]},\"id\":\"2235\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"2231\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"2006\",\"type\":\"PanTool\"},{\"attributes\":{\"axis\":{\"id\":\"1998\"},\"coordinates\":null,\"group\":null,\"ticker\":null},\"id\":\"2001\",\"type\":\"Grid\"},{\"attributes\":{\"callback\":null,\"renderers\":[{\"id\":\"2145\"}],\"toggleable\":false,\"tooltips\":[[\"X\",\"@x_4\"],[\"Y\",\"@y_4\"]]},\"id\":\"2167\",\"type\":\"HoverTool\"},{\"attributes\":{\"data\":{\"x_5\":[\"5\"],\"y_5\":[1090]},\"selected\":{\"id\":\"2196\"},\"selection_policy\":{\"id\":\"2195\"}},\"id\":\"2171\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_color\":{\"value\":\"#8c564b\"},\"hatch_color\":{\"value\":\"#8c564b\"},\"line_color\":{\"value\":\"#8c564b\"},\"size\":{\"value\":11},\"x\":{\"field\":\"x_5\"},\"y\":{\"field\":\"y_5\"}},\"id\":\"2173\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_color\":{\"value\":\"#1f77b4\"},\"hatch_color\":{\"value\":\"#1f77b4\"},\"line_color\":{\"value\":\"#1f77b4\"},\"size\":{\"value\":6},\"x\":{\"field\":\"x_0\"},\"y\":{\"field\":\"y_0\"}},\"id\":\"2037\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#8c564b\"},\"hatch_alpha\":{\"value\":0.1},\"hatch_color\":{\"value\":\"#8c564b\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#8c564b\"},\"size\":{\"value\":11},\"x\":{\"field\":\"x_5\"},\"y\":{\"field\":\"y_5\"}},\"id\":\"2174\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#8c564b\"},\"hatch_alpha\":{\"value\":0.2},\"hatch_color\":{\"value\":\"#8c564b\"},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"#8c564b\"},\"size\":{\"value\":11},\"x\":{\"field\":\"x_5\"},\"y\":{\"field\":\"y_5\"}},\"id\":\"2175\",\"type\":\"Scatter\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"2171\"},\"glyph\":{\"id\":\"2173\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"2175\"},\"name\":\"x_5\",\"nonselection_glyph\":{\"id\":\"2174\"},\"view\":{\"id\":\"2177\"}},\"id\":\"2176\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"fill_color\":{\"value\":\"#e377c2\"},\"hatch_color\":{\"value\":\"#e377c2\"},\"line_color\":{\"value\":\"#e377c2\"},\"size\":{\"value\":12},\"x\":{\"field\":\"x_6\"},\"y\":{\"field\":\"y_6\"}},\"id\":\"2206\",\"type\":\"Scatter\"},{\"attributes\":{\"source\":{\"id\":\"2171\"}},\"id\":\"2177\",\"type\":\"CDSView\"},{\"attributes\":{\"label\":{\"value\":\"x_5\"},\"renderers\":[{\"id\":\"2176\"}]},\"id\":\"2199\",\"type\":\"LegendItem\"},{\"attributes\":{\"axis\":{\"id\":\"2002\"},\"coordinates\":null,\"dimension\":1,\"group\":null,\"ticker\":null},\"id\":\"2005\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"2196\",\"type\":\"Selection\"},{\"attributes\":{\"axis_label\":\"x\",\"axis_label_text_font_size\":\"18pt\",\"axis_line_width\":2,\"coordinates\":null,\"formatter\":{\"id\":\"2047\"},\"group\":null,\"major_label_policy\":{\"id\":\"2048\"},\"major_label_text_font_size\":\"16pt\",\"ticker\":{\"id\":\"1999\"}},\"id\":\"1998\",\"type\":\"LinearAxis\"},{\"attributes\":{\"axis_label\":\"y\",\"axis_label_text_font_size\":\"18pt\",\"axis_line_width\":2,\"coordinates\":null,\"formatter\":{\"id\":\"2044\"},\"group\":null,\"major_label_policy\":{\"id\":\"2045\"},\"major_label_text_font_size\":\"16pt\",\"ticker\":{\"id\":\"2003\"}},\"id\":\"2002\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"2003\",\"type\":\"BasicTicker\"}],\"root_ids\":[\"1989\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n", - " const render_items = [{\"docid\":\"f7d9e2b2-e6b6-445f-bcc6-6bf9312ff27e\",\"root_ids\":[\"1989\"],\"roots\":{\"1989\":\"2f073413-ed1d-4a1d-b2ba-1644e3bc88e5\"}}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"f7d9e2b2-e6b6-445f-bcc6-6bf9312ff27e\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"1998\"}],\"center\":[{\"id\":\"2001\"},{\"id\":\"2005\"},{\"id\":\"2053\"}],\"left\":[{\"id\":\"2002\"}],\"renderers\":[{\"id\":\"2040\"},{\"id\":\"2064\"},{\"id\":\"2089\"},{\"id\":\"2116\"},{\"id\":\"2145\"},{\"id\":\"2176\"},{\"id\":\"2209\"}],\"title\":{\"id\":\"2033\"},\"toolbar\":{\"id\":\"2020\"},\"x_range\":{\"id\":\"1990\"},\"x_scale\":{\"id\":\"1994\"},\"y_range\":{\"id\":\"1992\"},\"y_scale\":{\"id\":\"1996\"}},\"id\":\"1989\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"overlay\":{\"id\":\"2019\"}},\"id\":\"2007\",\"type\":\"PolySelectTool\"},{\"attributes\":{\"callback\":null},\"id\":\"2008\",\"type\":\"TapTool\"},{\"attributes\":{},\"id\":\"1999\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"2009\",\"type\":\"WheelZoomTool\"},{\"attributes\":{\"overlay\":{\"id\":\"2018\"}},\"id\":\"2010\",\"type\":\"BoxZoomTool\"},{\"attributes\":{},\"id\":\"2013\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"2014\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"2011\",\"type\":\"RedoTool\"},{\"attributes\":{},\"id\":\"2012\",\"type\":\"UndoTool\"},{\"attributes\":{},\"id\":\"2015\",\"type\":\"CrosshairTool\"},{\"attributes\":{},\"id\":\"2016\",\"type\":\"ZoomOutTool\"},{\"attributes\":{},\"id\":\"2017\",\"type\":\"ZoomInTool\"},{\"attributes\":{\"bottom_units\":\"screen\",\"coordinates\":null,\"fill_alpha\":0.5,\"fill_color\":\"lightgrey\",\"group\":null,\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":1.0,\"line_color\":\"black\",\"line_dash\":[4,4],\"line_width\":2,\"right_units\":\"screen\",\"syncable\":false,\"top_units\":\"screen\"},\"id\":\"2018\",\"type\":\"BoxAnnotation\"},{\"attributes\":{\"label\":{\"value\":\"x_1\"},\"renderers\":[{\"id\":\"2064\"}]},\"id\":\"2079\",\"type\":\"LegendItem\"},{\"attributes\":{\"callback\":null,\"renderers\":[{\"id\":\"2040\"}],\"toggleable\":false,\"tooltips\":[[\"X\",\"@x_0\"],[\"Y\",\"@y_0\"]]},\"id\":\"2055\",\"type\":\"HoverTool\"},{\"attributes\":{\"coordinates\":null,\"fill_alpha\":0.5,\"fill_color\":\"lightgrey\",\"group\":null,\"level\":\"overlay\",\"line_alpha\":1.0,\"line_color\":\"black\",\"line_dash\":[4,4],\"line_width\":2,\"syncable\":false,\"xs_units\":\"screen\",\"ys_units\":\"screen\"},\"id\":\"2019\",\"type\":\"PolyAnnotation\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"2035\"},\"glyph\":{\"id\":\"2037\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"2039\"},\"name\":\"x_0\",\"nonselection_glyph\":{\"id\":\"2038\"},\"view\":{\"id\":\"2041\"}},\"id\":\"2040\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"data\":{\"x_1\":[\"1\"],\"y_1\":[886]},\"selected\":{\"id\":\"2076\"},\"selection_policy\":{\"id\":\"2075\"}},\"id\":\"2059\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_color\":{\"value\":\"#ff7f0e\"},\"hatch_color\":{\"value\":\"#ff7f0e\"},\"line_color\":{\"value\":\"#ff7f0e\"},\"size\":{\"value\":7},\"x\":{\"field\":\"x_1\"},\"y\":{\"field\":\"y_1\"}},\"id\":\"2061\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#ff7f0e\"},\"hatch_alpha\":{\"value\":0.1},\"hatch_color\":{\"value\":\"#ff7f0e\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#ff7f0e\"},\"size\":{\"value\":7},\"x\":{\"field\":\"x_1\"},\"y\":{\"field\":\"y_1\"}},\"id\":\"2062\",\"type\":\"Scatter\"},{\"attributes\":{},\"id\":\"2044\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#ff7f0e\"},\"hatch_alpha\":{\"value\":0.2},\"hatch_color\":{\"value\":\"#ff7f0e\"},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"#ff7f0e\"},\"size\":{\"value\":7},\"x\":{\"field\":\"x_1\"},\"y\":{\"field\":\"y_1\"}},\"id\":\"2063\",\"type\":\"Scatter\"},{\"attributes\":{},\"id\":\"2195\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"2059\"},\"glyph\":{\"id\":\"2061\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"2063\"},\"name\":\"x_1\",\"nonselection_glyph\":{\"id\":\"2062\"},\"view\":{\"id\":\"2065\"}},\"id\":\"2064\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"2045\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"2102\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"source\":{\"id\":\"2059\"}},\"id\":\"2065\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"2047\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"2048\",\"type\":\"AllLabels\"},{\"attributes\":{},\"id\":\"2132\",\"type\":\"Selection\"},{\"attributes\":{\"callback\":null,\"renderers\":[{\"id\":\"2176\"}],\"toggleable\":false,\"tooltips\":[[\"X\",\"@x_5\"],[\"Y\",\"@y_5\"]]},\"id\":\"2200\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"2076\",\"type\":\"Selection\"},{\"attributes\":{\"label\":{\"value\":\"x_3\"},\"renderers\":[{\"id\":\"2116\"}]},\"id\":\"2135\",\"type\":\"LegendItem\"},{\"attributes\":{\"data\":{\"x_3\":[\"3\"],\"y_3\":[497]},\"selected\":{\"id\":\"2132\"},\"selection_policy\":{\"id\":\"2131\"}},\"id\":\"2111\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"2075\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"fill_color\":{\"value\":\"#d62728\"},\"hatch_color\":{\"value\":\"#d62728\"},\"line_color\":{\"value\":\"#d62728\"},\"size\":{\"value\":9},\"x\":{\"field\":\"x_3\"},\"y\":{\"field\":\"y_3\"}},\"id\":\"2113\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#d62728\"},\"hatch_alpha\":{\"value\":0.1},\"hatch_color\":{\"value\":\"#d62728\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#d62728\"},\"size\":{\"value\":9},\"x\":{\"field\":\"x_3\"},\"y\":{\"field\":\"y_3\"}},\"id\":\"2114\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#d62728\"},\"hatch_alpha\":{\"value\":0.2},\"hatch_color\":{\"value\":\"#d62728\"},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"#d62728\"},\"size\":{\"value\":9},\"x\":{\"field\":\"x_3\"},\"y\":{\"field\":\"y_3\"}},\"id\":\"2115\",\"type\":\"Scatter\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"2111\"},\"glyph\":{\"id\":\"2113\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"2115\"},\"name\":\"x_3\",\"nonselection_glyph\":{\"id\":\"2114\"},\"view\":{\"id\":\"2117\"}},\"id\":\"2116\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"2049\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"callback\":null,\"renderers\":[{\"id\":\"2116\"}],\"toggleable\":false,\"tooltips\":[[\"X\",\"@x_3\"],[\"Y\",\"@y_3\"]]},\"id\":\"2136\",\"type\":\"HoverTool\"},{\"attributes\":{\"source\":{\"id\":\"2111\"}},\"id\":\"2117\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"2050\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"1990\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"2131\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"1996\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"group\":null},\"id\":\"2033\",\"type\":\"Title\"},{\"attributes\":{\"label\":{\"value\":\"x_0\"},\"renderers\":[{\"id\":\"2040\"}]},\"id\":\"2054\",\"type\":\"LegendItem\"},{\"attributes\":{\"label\":{\"value\":\"x_2\"},\"renderers\":[{\"id\":\"2089\"}]},\"id\":\"2106\",\"type\":\"LegendItem\"},{\"attributes\":{\"callback\":null,\"renderers\":[{\"id\":\"2064\"}],\"toggleable\":false,\"tooltips\":[[\"X\",\"@x_1\"],[\"Y\",\"@y_1\"]]},\"id\":\"2080\",\"type\":\"HoverTool\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#1f77b4\"},\"hatch_alpha\":{\"value\":0.2},\"hatch_color\":{\"value\":\"#1f77b4\"},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"#1f77b4\"},\"size\":{\"value\":6},\"x\":{\"field\":\"x_0\"},\"y\":{\"field\":\"y_0\"}},\"id\":\"2039\",\"type\":\"Scatter\"},{\"attributes\":{\"active_inspect\":[{\"id\":\"2055\"},{\"id\":\"2080\"},{\"id\":\"2107\"},{\"id\":\"2136\"},{\"id\":\"2167\"},{\"id\":\"2200\"},{\"id\":\"2235\"}],\"tools\":[{\"id\":\"2006\"},{\"id\":\"2007\"},{\"id\":\"2008\"},{\"id\":\"2009\"},{\"id\":\"2010\"},{\"id\":\"2011\"},{\"id\":\"2012\"},{\"id\":\"2013\"},{\"id\":\"2014\"},{\"id\":\"2015\"},{\"id\":\"2016\"},{\"id\":\"2017\"},{\"id\":\"2055\"},{\"id\":\"2080\"},{\"id\":\"2107\"},{\"id\":\"2136\"},{\"id\":\"2167\"},{\"id\":\"2200\"},{\"id\":\"2235\"}]},\"id\":\"2020\",\"type\":\"Toolbar\"},{\"attributes\":{\"data\":{\"x_2\":[\"2\"],\"y_2\":[848]},\"selected\":{\"id\":\"2103\"},\"selection_policy\":{\"id\":\"2102\"}},\"id\":\"2084\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"data\":{\"x_6\":[\"6\"],\"y_6\":[823]},\"selected\":{\"id\":\"2231\"},\"selection_policy\":{\"id\":\"2230\"}},\"id\":\"2204\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"click_policy\":\"hide\",\"coordinates\":null,\"group\":null,\"items\":[{\"id\":\"2054\"},{\"id\":\"2079\"},{\"id\":\"2106\"},{\"id\":\"2135\"},{\"id\":\"2166\"},{\"id\":\"2199\"},{\"id\":\"2234\"}],\"label_text_font_size\":\"14pt\"},\"id\":\"2053\",\"type\":\"Legend\"},{\"attributes\":{\"fill_color\":{\"value\":\"#2ca02c\"},\"hatch_color\":{\"value\":\"#2ca02c\"},\"line_color\":{\"value\":\"#2ca02c\"},\"size\":{\"value\":8},\"x\":{\"field\":\"x_2\"},\"y\":{\"field\":\"y_2\"}},\"id\":\"2086\",\"type\":\"Scatter\"},{\"attributes\":{},\"id\":\"1992\",\"type\":\"DataRange1d\"},{\"attributes\":{\"data\":{\"x_0\":[\"0\"],\"y_0\":[727]},\"selected\":{\"id\":\"2050\"},\"selection_policy\":{\"id\":\"2049\"}},\"id\":\"2035\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#2ca02c\"},\"hatch_alpha\":{\"value\":0.1},\"hatch_color\":{\"value\":\"#2ca02c\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#2ca02c\"},\"size\":{\"value\":8},\"x\":{\"field\":\"x_2\"},\"y\":{\"field\":\"y_2\"}},\"id\":\"2087\",\"type\":\"Scatter\"},{\"attributes\":{\"source\":{\"id\":\"2035\"}},\"id\":\"2041\",\"type\":\"CDSView\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#2ca02c\"},\"hatch_alpha\":{\"value\":0.2},\"hatch_color\":{\"value\":\"#2ca02c\"},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"#2ca02c\"},\"size\":{\"value\":8},\"x\":{\"field\":\"x_2\"},\"y\":{\"field\":\"y_2\"}},\"id\":\"2088\",\"type\":\"Scatter\"},{\"attributes\":{},\"id\":\"2103\",\"type\":\"Selection\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"2084\"},\"glyph\":{\"id\":\"2086\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"2088\"},\"name\":\"x_2\",\"nonselection_glyph\":{\"id\":\"2087\"},\"view\":{\"id\":\"2090\"}},\"id\":\"2089\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"callback\":null,\"renderers\":[{\"id\":\"2089\"}],\"toggleable\":false,\"tooltips\":[[\"X\",\"@x_2\"],[\"Y\",\"@y_2\"]]},\"id\":\"2107\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"1994\",\"type\":\"LinearScale\"},{\"attributes\":{\"source\":{\"id\":\"2084\"}},\"id\":\"2090\",\"type\":\"CDSView\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#1f77b4\"},\"hatch_alpha\":{\"value\":0.1},\"hatch_color\":{\"value\":\"#1f77b4\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#1f77b4\"},\"size\":{\"value\":6},\"x\":{\"field\":\"x_0\"},\"y\":{\"field\":\"y_0\"}},\"id\":\"2038\",\"type\":\"Scatter\"},{\"attributes\":{},\"id\":\"2162\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"label\":{\"value\":\"x_4\"},\"renderers\":[{\"id\":\"2145\"}]},\"id\":\"2166\",\"type\":\"LegendItem\"},{\"attributes\":{\"data\":{\"x_4\":[\"4\"],\"y_4\":[444]},\"selected\":{\"id\":\"2163\"},\"selection_policy\":{\"id\":\"2162\"}},\"id\":\"2140\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_color\":{\"value\":\"#9467bd\"},\"hatch_color\":{\"value\":\"#9467bd\"},\"line_color\":{\"value\":\"#9467bd\"},\"size\":{\"value\":10},\"x\":{\"field\":\"x_4\"},\"y\":{\"field\":\"y_4\"}},\"id\":\"2142\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#9467bd\"},\"hatch_alpha\":{\"value\":0.1},\"hatch_color\":{\"value\":\"#9467bd\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#9467bd\"},\"size\":{\"value\":10},\"x\":{\"field\":\"x_4\"},\"y\":{\"field\":\"y_4\"}},\"id\":\"2143\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#9467bd\"},\"hatch_alpha\":{\"value\":0.2},\"hatch_color\":{\"value\":\"#9467bd\"},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"#9467bd\"},\"size\":{\"value\":10},\"x\":{\"field\":\"x_4\"},\"y\":{\"field\":\"y_4\"}},\"id\":\"2144\",\"type\":\"Scatter\"},{\"attributes\":{},\"id\":\"2230\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"2140\"},\"glyph\":{\"id\":\"2142\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"2144\"},\"name\":\"x_4\",\"nonselection_glyph\":{\"id\":\"2143\"},\"view\":{\"id\":\"2146\"}},\"id\":\"2145\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#e377c2\"},\"hatch_alpha\":{\"value\":0.1},\"hatch_color\":{\"value\":\"#e377c2\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#e377c2\"},\"size\":{\"value\":12},\"x\":{\"field\":\"x_6\"},\"y\":{\"field\":\"y_6\"}},\"id\":\"2207\",\"type\":\"Scatter\"},{\"attributes\":{\"label\":{\"value\":\"x_6\"},\"renderers\":[{\"id\":\"2209\"}]},\"id\":\"2234\",\"type\":\"LegendItem\"},{\"attributes\":{\"source\":{\"id\":\"2140\"}},\"id\":\"2146\",\"type\":\"CDSView\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#e377c2\"},\"hatch_alpha\":{\"value\":0.2},\"hatch_color\":{\"value\":\"#e377c2\"},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"#e377c2\"},\"size\":{\"value\":12},\"x\":{\"field\":\"x_6\"},\"y\":{\"field\":\"y_6\"}},\"id\":\"2208\",\"type\":\"Scatter\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"2204\"},\"glyph\":{\"id\":\"2206\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"2208\"},\"name\":\"x_6\",\"nonselection_glyph\":{\"id\":\"2207\"},\"view\":{\"id\":\"2210\"}},\"id\":\"2209\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"2163\",\"type\":\"Selection\"},{\"attributes\":{\"source\":{\"id\":\"2204\"}},\"id\":\"2210\",\"type\":\"CDSView\"},{\"attributes\":{\"callback\":null,\"renderers\":[{\"id\":\"2209\"}],\"toggleable\":false,\"tooltips\":[[\"X\",\"@x_6\"],[\"Y\",\"@y_6\"]]},\"id\":\"2235\",\"type\":\"HoverTool\"},{\"attributes\":{},\"id\":\"2231\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"2006\",\"type\":\"PanTool\"},{\"attributes\":{\"axis\":{\"id\":\"1998\"},\"coordinates\":null,\"group\":null,\"ticker\":null},\"id\":\"2001\",\"type\":\"Grid\"},{\"attributes\":{\"callback\":null,\"renderers\":[{\"id\":\"2145\"}],\"toggleable\":false,\"tooltips\":[[\"X\",\"@x_4\"],[\"Y\",\"@y_4\"]]},\"id\":\"2167\",\"type\":\"HoverTool\"},{\"attributes\":{\"data\":{\"x_5\":[\"5\"],\"y_5\":[1090]},\"selected\":{\"id\":\"2196\"},\"selection_policy\":{\"id\":\"2195\"}},\"id\":\"2171\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_color\":{\"value\":\"#8c564b\"},\"hatch_color\":{\"value\":\"#8c564b\"},\"line_color\":{\"value\":\"#8c564b\"},\"size\":{\"value\":11},\"x\":{\"field\":\"x_5\"},\"y\":{\"field\":\"y_5\"}},\"id\":\"2173\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_color\":{\"value\":\"#1f77b4\"},\"hatch_color\":{\"value\":\"#1f77b4\"},\"line_color\":{\"value\":\"#1f77b4\"},\"size\":{\"value\":6},\"x\":{\"field\":\"x_0\"},\"y\":{\"field\":\"y_0\"}},\"id\":\"2037\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#8c564b\"},\"hatch_alpha\":{\"value\":0.1},\"hatch_color\":{\"value\":\"#8c564b\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#8c564b\"},\"size\":{\"value\":11},\"x\":{\"field\":\"x_5\"},\"y\":{\"field\":\"y_5\"}},\"id\":\"2174\",\"type\":\"Scatter\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"#8c564b\"},\"hatch_alpha\":{\"value\":0.2},\"hatch_color\":{\"value\":\"#8c564b\"},\"line_alpha\":{\"value\":0.2},\"line_color\":{\"value\":\"#8c564b\"},\"size\":{\"value\":11},\"x\":{\"field\":\"x_5\"},\"y\":{\"field\":\"y_5\"}},\"id\":\"2175\",\"type\":\"Scatter\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"2171\"},\"glyph\":{\"id\":\"2173\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"2175\"},\"name\":\"x_5\",\"nonselection_glyph\":{\"id\":\"2174\"},\"view\":{\"id\":\"2177\"}},\"id\":\"2176\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"fill_color\":{\"value\":\"#e377c2\"},\"hatch_color\":{\"value\":\"#e377c2\"},\"line_color\":{\"value\":\"#e377c2\"},\"size\":{\"value\":12},\"x\":{\"field\":\"x_6\"},\"y\":{\"field\":\"y_6\"}},\"id\":\"2206\",\"type\":\"Scatter\"},{\"attributes\":{\"source\":{\"id\":\"2171\"}},\"id\":\"2177\",\"type\":\"CDSView\"},{\"attributes\":{\"label\":{\"value\":\"x_5\"},\"renderers\":[{\"id\":\"2176\"}]},\"id\":\"2199\",\"type\":\"LegendItem\"},{\"attributes\":{\"axis\":{\"id\":\"2002\"},\"coordinates\":null,\"dimension\":1,\"group\":null,\"ticker\":null},\"id\":\"2005\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"2196\",\"type\":\"Selection\"},{\"attributes\":{\"axis_label\":\"x\",\"axis_label_text_font_size\":\"18pt\",\"axis_line_width\":2,\"coordinates\":null,\"formatter\":{\"id\":\"2047\"},\"group\":null,\"major_label_policy\":{\"id\":\"2048\"},\"major_label_text_font_size\":\"16pt\",\"ticker\":{\"id\":\"1999\"}},\"id\":\"1998\",\"type\":\"LinearAxis\"},{\"attributes\":{\"axis_label\":\"y\",\"axis_label_text_font_size\":\"18pt\",\"axis_line_width\":2,\"coordinates\":null,\"formatter\":{\"id\":\"2044\"},\"group\":null,\"major_label_policy\":{\"id\":\"2045\"},\"major_label_text_font_size\":\"16pt\",\"ticker\":{\"id\":\"2003\"}},\"id\":\"2002\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"2003\",\"type\":\"BasicTicker\"}],\"root_ids\":[\"1989\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n const render_items = [{\"docid\":\"f7d9e2b2-e6b6-445f-bcc6-6bf9312ff27e\",\"root_ids\":[\"1989\"],\"roots\":{\"1989\":\"2f073413-ed1d-4a1d-b2ba-1644e3bc88e5\"}}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -4440,32 +3626,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"9f66405f-51e4-42b6-9d09-dfd2a94b3d7c\":{\"version\":\"3.0.0.dev13\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"40046\",\"attributes\":{\"y_range\":{\"type\":\"object\",\"name\":\"Range1d\",\"id\":\"40056\",\"attributes\":{\"end\":10}},\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"40052\"},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"40068\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"40070\"},\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"40069\"},\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"40071\",\"attributes\":{\"mantissas\":[1,2,5]}}}}],\"below\":[{\"type\":\"object\",\"name\":\"CategoricalAxis\",\"id\":\"40062\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"CategoricalTickFormatter\",\"id\":\"40064\"},\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"40063\"},\"major_label_orientation\":1,\"ticker\":{\"type\":\"object\",\"name\":\"CategoricalTicker\",\"id\":\"40065\"}}}],\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"40060\"},\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"40067\",\"attributes\":{\"axis\":{\"id\":\"40062\"},\"grid_line_color\":null}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"40074\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"40068\"}}},{\"type\":\"object\",\"name\":\"Legend\",\"id\":\"40098\",\"attributes\":{\"items\":[{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"40099\",\"attributes\":{\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"40083\",\"attributes\":{\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40082\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2015\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"40076\",\"attributes\":{\"range\":{\"type\":\"object\",\"name\":\"FactorRange\",\"id\":\"40054\",\"attributes\":{\"factors\":[\"Apples\",\"Pears\",\"Nectarines\",\"Plums\",\"Grapes\",\"Strawberries\"],\"range_padding\":0.1}}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40081\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2015\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40076\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"visible\":false,\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"40084\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"40085\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"40043\",\"attributes\":{\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"40045\"},\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"40044\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"fruits\",[\"Apples\",\"Pears\",\"Nectarines\",\"Plums\",\"Grapes\",\"Strawberries\"]],[\"2015\",[2,1,4,3,2,4]],[\"2016\",[5,3,3,2,4,6]],[\"2017\",[3,2,4,4,5,3]],[\"2018\",[2,1,3,6,7,2]],[\"2019\",[1,1,2,2,2,1]],[\"2020\",[5,5,4,4,5,5]]]}}},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40080\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"top\":{\"type\":\"field\",\"field\":\"2015\"},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40076\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"}}}}}],\"label\":{\"type\":\"value\",\"value\":\"2015\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"40125\",\"attributes\":{\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"40107\",\"attributes\":{\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40106\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2016\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"40100\",\"attributes\":{\"value\":-0.5,\"range\":{\"id\":\"40054\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40105\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"line_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2016\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40100\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"40108\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"40109\"}}},\"data_source\":{\"id\":\"40043\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40104\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"},\"top\":{\"type\":\"field\",\"field\":\"2016\"},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40100\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"}}}}}],\"label\":{\"type\":\"value\",\"value\":\"2016\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"40154\",\"attributes\":{\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"40133\",\"attributes\":{\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40132\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2017\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"40126\",\"attributes\":{\"value\":-0.25,\"range\":{\"id\":\"40054\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40131\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"line_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2017\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40126\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"40134\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"40135\"}}},\"data_source\":{\"id\":\"40043\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40130\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"},\"top\":{\"type\":\"field\",\"field\":\"2017\"},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40126\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"}}}}}],\"label\":{\"type\":\"value\",\"value\":\"2017\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"40186\",\"attributes\":{\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"40162\",\"attributes\":{\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40161\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2018\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"40155\",\"attributes\":{\"range\":{\"id\":\"40054\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40160\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"line_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2018\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40155\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"40163\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"40164\"}}},\"data_source\":{\"id\":\"40043\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40159\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"},\"top\":{\"type\":\"field\",\"field\":\"2018\"},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40155\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"}}}}}],\"label\":{\"type\":\"value\",\"value\":\"2018\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"40221\",\"attributes\":{\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"40194\",\"attributes\":{\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40193\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2019\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"40187\",\"attributes\":{\"value\":0.25,\"range\":{\"id\":\"40054\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40192\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"line_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2019\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40187\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"40195\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"40196\"}}},\"data_source\":{\"id\":\"40043\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40191\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"top\":{\"type\":\"field\",\"field\":\"2019\"},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40187\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"}}}}}],\"label\":{\"type\":\"value\",\"value\":\"2019\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"40259\",\"attributes\":{\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"40229\",\"attributes\":{\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40228\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#98df8a\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#98df8a\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2020\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"40222\",\"attributes\":{\"value\":0.5,\"range\":{\"id\":\"40054\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#98df8a\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40227\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"line_color\":{\"type\":\"value\",\"value\":\"#98df8a\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#98df8a\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2020\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40222\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#98df8a\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"40230\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"40231\"}}},\"data_source\":{\"id\":\"40043\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40226\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#98df8a\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#98df8a\"},\"top\":{\"type\":\"field\",\"field\":\"2020\"},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40222\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#98df8a\"}}}}}],\"label\":{\"type\":\"value\",\"value\":\"2020\"}}}],\"location\":\"top_left\",\"click_policy\":\"hide\",\"orientation\":\"horizontal\"}}],\"toolbar_location\":null,\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"40047\",\"attributes\":{\"text\":\"Fruit Counts by Year\"}},\"x_scale\":{\"type\":\"object\",\"name\":\"CategoricalScale\",\"id\":\"40058\"},\"x_range\":{\"id\":\"40054\"},\"renderers\":[{\"id\":\"40083\"},{\"id\":\"40107\"},{\"id\":\"40133\"},{\"id\":\"40162\"},{\"id\":\"40194\"},{\"id\":\"40229\"}]}}]}};\n", - " const render_items = [{\"docid\":\"9f66405f-51e4-42b6-9d09-dfd2a94b3d7c\",\"roots\":{\"40046\":\"b425f6f2-0e20-4fd2-8cc8-25cff6e34614\"},\"root_ids\":[\"40046\"]}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"9f66405f-51e4-42b6-9d09-dfd2a94b3d7c\":{\"version\":\"3.0.0.dev13\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"40046\",\"attributes\":{\"y_range\":{\"type\":\"object\",\"name\":\"Range1d\",\"id\":\"40056\",\"attributes\":{\"end\":10}},\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"40052\"},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"40068\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"40070\"},\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"40069\"},\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"40071\",\"attributes\":{\"mantissas\":[1,2,5]}}}}],\"below\":[{\"type\":\"object\",\"name\":\"CategoricalAxis\",\"id\":\"40062\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"CategoricalTickFormatter\",\"id\":\"40064\"},\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"40063\"},\"major_label_orientation\":1,\"ticker\":{\"type\":\"object\",\"name\":\"CategoricalTicker\",\"id\":\"40065\"}}}],\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"40060\"},\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"40067\",\"attributes\":{\"axis\":{\"id\":\"40062\"},\"grid_line_color\":null}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"40074\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"40068\"}}},{\"type\":\"object\",\"name\":\"Legend\",\"id\":\"40098\",\"attributes\":{\"items\":[{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"40099\",\"attributes\":{\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"40083\",\"attributes\":{\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40082\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2015\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"40076\",\"attributes\":{\"range\":{\"type\":\"object\",\"name\":\"FactorRange\",\"id\":\"40054\",\"attributes\":{\"factors\":[\"Apples\",\"Pears\",\"Nectarines\",\"Plums\",\"Grapes\",\"Strawberries\"],\"range_padding\":0.1}}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40081\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2015\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40076\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"visible\":false,\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"40084\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"40085\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"40043\",\"attributes\":{\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"40045\"},\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"40044\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"fruits\",[\"Apples\",\"Pears\",\"Nectarines\",\"Plums\",\"Grapes\",\"Strawberries\"]],[\"2015\",[2,1,4,3,2,4]],[\"2016\",[5,3,3,2,4,6]],[\"2017\",[3,2,4,4,5,3]],[\"2018\",[2,1,3,6,7,2]],[\"2019\",[1,1,2,2,2,1]],[\"2020\",[5,5,4,4,5,5]]]}}},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40080\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"},\"top\":{\"type\":\"field\",\"field\":\"2015\"},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40076\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#1f77b4\"}}}}}],\"label\":{\"type\":\"value\",\"value\":\"2015\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"40125\",\"attributes\":{\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"40107\",\"attributes\":{\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40106\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2016\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"40100\",\"attributes\":{\"value\":-0.5,\"range\":{\"id\":\"40054\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40105\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"line_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2016\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40100\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"40108\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"40109\"}}},\"data_source\":{\"id\":\"40043\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40104\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"},\"top\":{\"type\":\"field\",\"field\":\"2016\"},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40100\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#aec7e8\"}}}}}],\"label\":{\"type\":\"value\",\"value\":\"2016\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"40154\",\"attributes\":{\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"40133\",\"attributes\":{\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40132\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2017\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"40126\",\"attributes\":{\"value\":-0.25,\"range\":{\"id\":\"40054\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40131\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"line_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2017\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40126\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"40134\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"40135\"}}},\"data_source\":{\"id\":\"40043\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40130\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"},\"top\":{\"type\":\"field\",\"field\":\"2017\"},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40126\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#ff7f0e\"}}}}}],\"label\":{\"type\":\"value\",\"value\":\"2017\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"40186\",\"attributes\":{\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"40162\",\"attributes\":{\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40161\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2018\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"40155\",\"attributes\":{\"range\":{\"id\":\"40054\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40160\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"line_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2018\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40155\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"40163\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"40164\"}}},\"data_source\":{\"id\":\"40043\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40159\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"},\"top\":{\"type\":\"field\",\"field\":\"2018\"},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40155\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#ffbb78\"}}}}}],\"label\":{\"type\":\"value\",\"value\":\"2018\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"40221\",\"attributes\":{\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"40194\",\"attributes\":{\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40193\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2019\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"40187\",\"attributes\":{\"value\":0.25,\"range\":{\"id\":\"40054\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40192\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"line_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2019\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40187\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"40195\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"40196\"}}},\"data_source\":{\"id\":\"40043\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40191\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"top\":{\"type\":\"field\",\"field\":\"2019\"},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40187\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"}}}}}],\"label\":{\"type\":\"value\",\"value\":\"2019\"}}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"40259\",\"attributes\":{\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"40229\",\"attributes\":{\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40228\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":\"#98df8a\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#98df8a\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2020\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"40222\",\"attributes\":{\"value\":0.5,\"range\":{\"id\":\"40054\"}}}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#98df8a\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40227\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"line_color\":{\"type\":\"value\",\"value\":\"#98df8a\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#98df8a\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"top\":{\"type\":\"field\",\"field\":\"2020\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40222\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#98df8a\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"40230\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"40231\"}}},\"data_source\":{\"id\":\"40043\"},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"40226\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":\"#98df8a\"},\"width\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#98df8a\"},\"top\":{\"type\":\"field\",\"field\":\"2020\"},\"x\":{\"type\":\"field\",\"field\":\"fruits\",\"transform\":{\"id\":\"40222\"}},\"hatch_color\":{\"type\":\"value\",\"value\":\"#98df8a\"}}}}}],\"label\":{\"type\":\"value\",\"value\":\"2020\"}}}],\"location\":\"top_left\",\"click_policy\":\"hide\",\"orientation\":\"horizontal\"}}],\"toolbar_location\":null,\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"40047\",\"attributes\":{\"text\":\"Fruit Counts by Year\"}},\"x_scale\":{\"type\":\"object\",\"name\":\"CategoricalScale\",\"id\":\"40058\"},\"x_range\":{\"id\":\"40054\"},\"renderers\":[{\"id\":\"40083\"},{\"id\":\"40107\"},{\"id\":\"40133\"},{\"id\":\"40162\"},{\"id\":\"40194\"},{\"id\":\"40229\"}]}}]}};\n const render_items = [{\"docid\":\"9f66405f-51e4-42b6-9d09-dfd2a94b3d7c\",\"roots\":{\"40046\":\"b425f6f2-0e20-4fd2-8cc8-25cff6e34614\"},\"root_ids\":[\"40046\"]}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -4840,32 +4001,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"44d1bf3a-a74d-4b27-9c7b-4797d28be4ab\":{\"version\":\"3.0.0.dev13\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"41500\",\"attributes\":{\"y_range\":{\"type\":\"object\",\"name\":\"FactorRange\",\"id\":\"41510\",\"attributes\":{\"factors\":[\"Dec\",\"Nov\",\"Oct\",\"Sep\",\"Aug\",\"Jul\",\"Jun\",\"May\",\"Apr\",\"Mar\",\"Feb\",\"Jan\"]}},\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"41506\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"HoverTool\",\"id\":\"41528\",\"attributes\":{\"renderers\":\"auto\"}}]}},\"left\":[{\"type\":\"object\",\"name\":\"CategoricalAxis\",\"id\":\"41522\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"CategoricalTickFormatter\",\"id\":\"41524\"},\"major_label_standoff\":0,\"ticker\":{\"type\":\"object\",\"name\":\"CategoricalTicker\",\"id\":\"41525\"},\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"41523\"},\"major_tick_line_color\":null,\"axis_line_color\":null,\"major_label_text_font_size\":\"7px\"}}],\"above\":[{\"type\":\"object\",\"name\":\"CategoricalAxis\",\"id\":\"41516\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"CategoricalTickFormatter\",\"id\":\"41518\"},\"major_label_standoff\":0,\"ticker\":{\"type\":\"object\",\"name\":\"CategoricalTicker\",\"id\":\"41519\"},\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"41517\"},\"major_tick_line_color\":null,\"axis_line_color\":null,\"major_label_text_font_size\":\"7px\",\"major_label_orientation\":1.0}}],\"y_scale\":{\"type\":\"object\",\"name\":\"CategoricalScale\",\"id\":\"41514\"},\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"41521\",\"attributes\":{\"axis\":{\"id\":\"41516\"}}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"41527\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"41522\"}}}],\"toolbar_location\":null,\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"41501\",\"attributes\":{\"text\":\"US unemployment 1948\\u20142016\"}},\"x_scale\":{\"type\":\"object\",\"name\":\"CategoricalScale\",\"id\":\"41512\"},\"x_range\":{\"type\":\"object\",\"name\":\"FactorRange\",\"id\":\"41508\",\"attributes\":{\"factors\":[\"1948\",\"1949\",\"1950\",\"1951\",\"1952\",\"1953\",\"1954\",\"1955\",\"1956\",\"1957\",\"1958\",\"1959\",\"1960\",\"1961\",\"1962\",\"1963\",\"1964\",\"1965\",\"1966\",\"1967\",\"1968\",\"1969\",\"1970\",\"1971\",\"1972\",\"1973\",\"1974\",\"1975\",\"1976\",\"1977\",\"1978\",\"1979\",\"1980\",\"1981\",\"1982\",\"1983\",\"1984\",\"1985\",\"1986\",\"1987\",\"1988\",\"1989\",\"1990\",\"1991\",\"1992\",\"1993\",\"1994\",\"1995\",\"1996\",\"1997\",\"1998\",\"1999\",\"2000\",\"2001\",\"2002\",\"2003\",\"2004\",\"2005\",\"2006\",\"2007\",\"2008\",\"2009\",\"2010\",\"2011\",\"2012\",\"2013\",\"2014\",\"2015\",\"2016\"]}},\"width\":800,\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"41537\",\"attributes\":{\"muted_glyph\":{\"type\":\"object\",\"name\":\"Rect\",\"id\":\"41536\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":null},\"width\":{\"type\":\"value\",\"value\":1},\"fill_color\":{\"type\":\"field\",\"field\":\"rate\",\"transform\":{\"type\":\"object\",\"name\":\"LinearColorMapper\",\"id\":\"41499\",\"attributes\":{\"low\":2.4,\"palette\":[\"#75968f\",\"#a5bab7\",\"#c9d9d3\",\"#e2e2e2\",\"#dfccce\",\"#ddb7b1\",\"#cc7878\",\"#933b41\",\"#550b1d\"],\"high\":11.4}}},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"Year\"},\"height\":{\"type\":\"value\",\"value\":1},\"y\":{\"type\":\"field\",\"field\":\"Month\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Rect\",\"id\":\"41535\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"line_color\":{\"type\":\"value\",\"value\":null},\"width\":{\"type\":\"value\",\"value\":1},\"fill_color\":{\"type\":\"field\",\"field\":\"rate\",\"transform\":{\"id\":\"41499\"}},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"field\",\"field\":\"Year\"},\"height\":{\"type\":\"value\",\"value\":1},\"y\":{\"type\":\"field\",\"field\":\"Month\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"41538\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"41539\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"41496\",\"attributes\":{\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"41498\"},\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"41497\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"index\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"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owIAAKQCAAClAgAApgIAAKcCAACoAgAAqQIAAKoCAACrAgAArAIAAK0CAACuAgAArwIAALACAACxAgAAsgIAALMCAAC0AgAAtQIAALYCAAC3AgAAuAIAALkCAAC6AgAAuwIAALwCAAC9AgAAvgIAAL8CAADAAgAAwQIAAMICAADDAgAAxAIAAMUCAADGAgAAxwIAAMgCAADJAgAAygIAAMsCAADMAgAAzQIAAM4CAADPAgAA0AIAANECAADSAgAA0wIAANQCAADVAgAA1gIAANcCAADYAgAA2QIAANoCAADbAgAA3AIAAN0CAADeAgAA3wIAAOACAADhAgAA4gIAAOMCAADkAgAA5QIAAOYCAADnAgAA6AIAAOkCAADqAgAA6wIAAOwCAADtAgAA7gIAAO8CAADwAgAA8QIAAPICAADzAgAA9AIAAPUCAAD2AgAA9wIAAPgCAAD5AgAA+gIAAPsCAAD8AgAA/QIAAP4CAAD/AgAAAAMAAAEDAAACAwAAAwMAAAQDAAAFAwAABgMAAAcDAAAIAwAACQMAAAoDAAALAwAADAMAAA0DAAAOAwAADwMAABADAAARAwAAEgMAABMDAAAUAwAAFQMAABYDAAAXAwAAGAMAABkDAAAaAwAAGwMAABwDAAAdAwAAHgMAAB8DAAAgAwAAIQMAACIDAAAjAwAAJAMAACUDAAAmAwAAJwMAACgDAAApAwAAKgMAACsDAAAsAwAALQMAAC4DAAAvAwAAMAMAADEDAAAyAwAAMwMAADQDAAA1AwAANgMAADcDAAA4AwAAOQMAADoDAAA7AwAA\"},\"shape\":[828],\"dtype\":\"int32\",\"order\":\"little\"}],[\"Year\",{\"type\":\"ndarray\",\"array\":[\"1948\",\"1948\",\"1948\",\"1948\",\"1948\",\"1948\",\"1948\",\"1948\",\"1948\",\"1948\",\"1948\",\"1948\",\"1949\",\"1949\",\"1949\",\"1949\",\"1949\",\"1949\",\"1949\",\"1949\",\"1949\",\"1949\",\"1949\",\"1949\",\"1950\",\"1950\",\"1950\",\"1950\",\"1950\",\"1950\",\"1950\",\"1950\",\"1950\",\"1950\",\"1950\",\"1950\",\"1951\",\"1951\",\"1951\",\"1951\",\"1951\",\"1951\",\"1951\",\"1951\",\"1951\",\"1951\",\"1951\",\"1951\",\"1952\",\"1952\",\"1952\",\"1952\",\"1952\",\"1952\",\"1952\",\"1952\",\"1952\",\"1952\",\"1952\",\"1952\",\"1953\",\"1953\",\"1953\",\"1953\",\"1953\",\"1953\",\"1953\",\"1953\",\"1953\",\"1953\",\"1953\",\"1953\",\"1954\",\"1954\",\"1954\",\"1954\",\"1954\",\"1954\",\"1954\",\"1954\",\"1954\",\"1954\",\"1954\",\"1954\",\"1955\",\"1955\",\"1955\",\"1955\",\"1955\",\"1955\",\"1955\",\"1955\",\"1955\",\"1955\",\"1955\",\"1955\",\"1956\",\"1956\",\"1956\",\"1956\",\"1956\",\"1956\",\"1956\",\"1956\",\"1956\",\"1956\",\"1956\",\"1956\",\"1957\",\"1957\",\"1957\",\"1957\",\"1957\",\"1957\",\"1957\",\"1957\",\"1957\",\"1957\",\"1957\",\"1957\",\"1958\",\"1958\",\"1958\",\"1958\",\"1958\",\"1958\",\"1958\",\"1958\",\"1958\",\"1958\",\"1958\",\"1958\",\"1959\",\"1959\",\"1959\",\"1959\",\"1959\",\"1959\",\"1959\",\"1959\",\"1959\",\"1959\",\"1959\",\"1959\",\"1960\",\"1960\",\"1960\",\"1960\",\"1960\",\"1960\",\"1960\",\"1960\",\"1960\",\"1960\",\"1960\",\"1960\",\"1961\",\"1961\",\"1961\",\"1961\",\"1961\",\"1961\",\"1961\",\"1961\",\"1961\",\"1961\",\"1961\",\"1961\",\"1962\",\"1962\",\"1962\",\"1962\",\"1962\",\"1962\",\"1962\",\"1962\",\"1962\",\"1962\",\"1962\",\"1962\",\"1963\",\"1963\",\"1963\",\"1963\",\"1963\",\"1963\",\"1963\",\"1963\",\"1963\",\"1963\",\"1963\",\"1963\",\"1964\",\"1964\",\"1964\",\"1964\",\"1964\",\"1964\",\"1964\",\"1964\",\"1964\",\"1964\",\"1964\",\"1964\",\"1965\",\"1965\",\"1965\",\"1965\",\"1965\",\"1965\",\"1965\",\"1965\",\"1965\",\"1965\",\"1965\",\"1965\",\"1966\",\"1966\",\"1966\",\"1966\",\"1966\",\"1966\",\"1966\",\"1966\",\"1966\",\"1966\",\"1966\",\"1966\",\"1967\",\"1967\",\"1967\",\"1967\",\"1967\",\"1967\",\"1967\",\"1967\",\"1967\",\"1967\",\"1967\",\"1967\",\"1968\",\"1968\",\"1968\",\"1968\",\"1968\",\"1968\",\"1968\",\"1968\",\"1968\",\"1968\",\"1968\",\"1968\",\"1969\",\"1969\",\"1969\",\"1969\",\"1969\",\"1969\",\"1969\",\"1969\",\"1969\",\"1969\",\"1969\",\"1969\",\"1970\",\"1970\",\"1970\",\"1970\",\"1970\",\"1970\",\"1970\",\"1970\",\"1970\",\"1970\",\"1970\",\"1970\",\"1971\",\"1971\",\"1971\",\"1971\",\"1971\",\"1971\",\"1971\",\"1971\",\"1971\",\"1971\",\"1971\",\"1971\",\"1972\",\"1972\",\"1972\",\"1972\",\"1972\",\"1972\",\"1972\",\"1972\",\"1972\",\"1972\",\"1972\",\"1972\",\"1973\",\"1973\",\"1973\",\"1973\",\"1973\",\"1973\",\"1973\",\"1973\",\"1973\",\"1973\",\"1973\",\"1973\",\"1974\",\"1974\",\"1974\",\"1974\",\"1974\",\"1974\",\"1974\",\"1974\",\"1974\",\"1974\",\"1974\",\"1974\",\"1975\",\"1975\",\"1975\",\"1975\",\"1975\",\"1975\",\"1975\",\"1975\",\"1975\",\"1975\",\"1975\",\"1975\",\"1976\",\"1976\",\"1976\",\"1976\",\"1976\",\"1976\",\"1976\",\"1976\",\"1976\",\"1976\",\"1976\",\"1976\",\"1977\",\"1977\",\"1977\",\"1977\",\"1977\",\"1977\",\"1977\",\"1977\",\"1977\",\"1977\",\"1977\",\"1977\",\"1978\",\"1978\",\"1978\",\"1978\",\"1978\",\"1978\",\"1978\",\"1978\",\"1978\",\"1978\",\"1978\",\"1978\",\"1979\",\"1979\",\"1979\",\"1979\",\"1979\",\"1979\",\"1979\",\"1979\",\"1979\",\"1979\",\"1979\",\"1979\",\"1980\",\"1980\",\"1980\",\"1980\",\"1980\",\"1980\",\"1980\",\"1980\",\"1980\",\"1980\",\"1980\",\"1980\",\"1981\",\"1981\",\"1981\",\"1981\",\"1981\",\"1981\",\"1981\",\"1981\",\"1981\",\"1981\",\"1981\",\"1981\",\"1982\",\"1982\",\"1982\",\"1982\",\"1982\",\"1982\",\"1982\",\"1982\",\"1982\",\"1982\",\"1982\",\"1982\",\"1983\",\"1983\",\"1983\",\"1983\",\"1983\",\"1983\",\"1983\",\"1983\",\"1983\",\"1983\",\"1983\",\"1983\",\"1984\",\"1984\",\"1984\",\"1984\",\"1984\",\"1984\",\"1984\",\"1984\",\"1984\",\"1984\",\"1984\",\"1984\",\"1985\",\"1985\",\"1985\",\"1985\",\"1985\",\"1985\",\"1985\",\"1985\",\"1985\",\"1985\",\"1985\",\"1985\",\"1986\",\"1986\",\"1986\",\"1986\",\"1986\",\"1986\",\"1986\",\"1986\",\"1986\",\"1986\",\"1986\",\"1986\",\"1987\",\"1987\",\"1987\",\"1987\",\"1987\",\"1987\",\"1987\",\"1987\",\"1987\",\"1987\",\"1987\",\"1987\",\"1988\",\"1988\",\"1988\",\"1988\",\"1988\",\"1988\",\"1988\",\"1988\",\"1988\",\"1988\",\"1988\",\"1988\",\"1989\",\"1989\",\"1989\",\"1989\",\"1989\",\"1989\",\"1989\",\"1989\",\"1989\",\"1989\",\"1989\",\"1989\",\"1990\",\"1990\",\"1990\",\"1990\",\"1990\",\"1990\",\"1990\",\"1990\",\"1990\",\"1990\",\"1990\",\"1990\",\"1991\",\"1991\",\"1991\",\"1991\",\"1991\",\"1991\",\"1991\",\"1991\",\"1991\",\"1991\",\"1991\",\"1991\",\"1992\",\"1992\",\"1992\",\"1992\",\"1992\",\"1992\",\"1992\",\"1992\",\"1992\",\"1992\",\"1992\",\"1992\",\"1993\",\"1993\",\"1993\",\"1993\",\"1993\",\"1993\",\"1993\",\"1993\",\"1993\",\"1993\",\"1993\",\"1993\",\"1994\",\"1994\",\"1994\",\"1994\",\"1994\",\"1994\",\"1994\",\"1994\",\"1994\",\"1994\",\"1994\",\"1994\",\"1995\",\"1995\",\"1995\",\"1995\",\"1995\",\"1995\",\"1995\",\"1995\",\"1995\",\"1995\",\"1995\",\"1995\",\"1996\",\"1996\",\"1996\",\"1996\",\"1996\",\"1996\",\"1996\",\"1996\",\"1996\",\"1996\",\"1996\",\"1996\",\"1997\",\"1997\",\"1997\",\"1997\",\"1997\",\"1997\",\"1997\",\"1997\",\"1997\",\"1997\",\"1997\",\"1997\",\"1998\",\"1998\",\"1998\",\"1998\",\"1998\",\"1998\",\"1998\",\"1998\",\"1998\",\"1998\",\"1998\",\"1998\",\"1999\",\"1999\",\"1999\",\"1999\",\"1999\",\"1999\",\"1999\",\"1999\",\"1999\",\"1999\",\"1999\",\"1999\",\"2000\",\"2000\",\"2000\",\"2000\",\"2000\",\"2000\",\"2000\",\"2000\",\"2000\",\"2000\",\"2000\",\"2000\",\"2001\",\"2001\",\"2001\",\"2001\",\"2001\",\"2001\",\"2001\",\"2001\",\"2001\",\"2001\",\"2001\",\"2001\",\"2002\",\"2002\",\"2002\",\"2002\",\"2002\",\"2002\",\"2002\",\"2002\",\"2002\",\"2002\",\"2002\",\"2002\",\"2003\",\"2003\",\"2003\",\"2003\",\"2003\",\"2003\",\"2003\",\"2003\",\"2003\",\"2003\",\"2003\",\"2003\",\"2004\",\"2004\",\"2004\",\"2004\",\"2004\",\"2004\",\"2004\",\"2004\",\"2004\",\"2004\",\"2004\",\"2004\",\"2005\",\"2005\",\"2005\",\"2005\",\"2005\",\"2005\",\"2005\",\"2005\",\"2005\",\"2005\",\"2005\",\"2005\",\"2006\",\"2006\",\"2006\",\"2006\",\"2006\",\"2006\",\"2006\",\"2006\",\"2006\",\"2006\",\"2006\",\"2006\",\"2007\",\"2007\",\"2007\",\"2007\",\"2007\",\"2007\",\"2007\",\"2007\",\"2007\",\"2007\",\"2007\",\"2007\",\"2008\",\"2008\",\"2008\",\"2008\",\"2008\",\"2008\",\"2008\",\"2008\",\"2008\",\"2008\",\"2008\",\"2008\",\"2009\",\"2009\",\"2009\",\"2009\",\"2009\",\"2009\",\"2009\",\"2009\",\"2009\",\"2009\",\"2009\",\"2009\",\"2010\",\"2010\",\"2010\",\"2010\",\"2010\",\"2010\",\"2010\",\"2010\",\"2010\",\"2010\",\"2010\",\"2010\",\"2011\",\"2011\",\"2011\",\"2011\",\"2011\",\"2011\",\"2011\",\"2011\",\"2011\",\"2011\",\"2011\",\"2011\",\"2012\",\"2012\",\"2012\",\"2012\",\"2012\",\"2012\",\"2012\",\"2012\",\"2012\",\"2012\",\"2012\",\"2012\",\"2013\",\"2013\",\"2013\",\"2013\",\"2013\",\"2013\",\"2013\",\"2013\",\"2013\",\"2013\",\"2013\",\"2013\",\"2014\",\"2014\",\"2014\",\"2014\",\"2014\",\"2014\",\"2014\",\"2014\",\"2014\",\"2014\",\"2014\",\"2014\",\"2015\",\"2015\",\"2015\",\"2015\",\"2015\",\"2015\",\"2015\",\"2015\",\"2015\",\"2015\",\"2015\",\"2015\",\"2016\",\"2016\",\"2016\",\"2016\",\"2016\",\"2016\",\"2016\",\"2016\",\"2016\",\"2016\",\"2016\",\"2016\"],\"shape\":[828],\"dtype\":\"object\",\"order\":\"little\"}],[\"Month\",{\"type\":\"ndarray\",\"array\":[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"],\"shape\":[828],\"dtype\":\"object\",\"order\":\"little\"}],[\"rate\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"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MzMVQGZmZmZmZhRAzczMzMzMGECamZmZmZkXQM3MzMzMzBZAZmZmZmZmFkAAAAAAAAAWQDMzMzMzMxdAmpmZmZmZF0BmZmZmZmYWQJqZmZmZmRVAzczMzMzMFEAzMzMzMzMVQM3MzMzMzBRAMzMzMzMzGUAAAAAAAAAYQDMzMzMzMxdAmpmZmZmZFUCamZmZmZkVQAAAAAAAABZAZmZmZmZmFkBmZmZmZmYUQAAAAAAAABRAmpmZmZmZE0AAAAAAAAAUQAAAAAAAABRAmpmZmZmZF0DNzMzMzMwWQAAAAAAAABZAMzMzMzMzE0DNzMzMzMwSQM3MzMzMzBRAAAAAAAAAFEAzMzMzMzMTQM3MzMzMzBJAmpmZmZmZEUAzMzMzMzMRQJqZmZmZmRFAzczMzMzMFEAAAAAAAAAUQAAAAAAAABRAZmZmZmZmEEDNzMzMzMwQQM3MzMzMzBJAzczMzMzMEkAAAAAAAAASQJqZmZmZmRFAzczMzMzMEEBmZmZmZmYQQAAAAAAAABBAMzMzMzMzE0DNzMzMzMwSQJqZmZmZmRFAZmZmZmZmEEAAAAAAAAAQQAAAAAAAABJAAAAAAAAAEkDNzMzMzMwQQGZmZmZmZhBAZmZmZmZmDkBmZmZmZmYOQJqZmZmZmQ1AAAAAAAAAEkCamZmZmZkRQDMzMzMzMxFAmpmZmZmZDUBmZmZmZmYOQGZmZmZmZhBAzczMzMzMEEBmZmZmZmYQQGZmZmZmZg5AzczMzMzMDECamZmZmZkNQJqZmZmZmQ1AzczMzMzMEkBmZmZmZmYSQAAAAAAAABJAzczMzMzMEEBmZmZmZmYQQM3MzMzMzBJAzczMzMzMEkCamZmZmZkTQM3MzMzMzBJAAAAAAAAAFEAzMzMzMzMVQJqZmZmZmRVAMzMzMzMzGUBmZmZmZmYYQGZmZmZmZhhAzczMzMzMFkAAAAAAAAAWQAAAAAAAABhAmpmZmZmZF0DNzMzMzMwWQJqZmZmZmRVAMzMzMzMzFUBmZmZmZmYWQM3MzMzMzBZAAAAAAAAAGkCamZmZmZkZQM3MzMzMzBhAMzMzMzMzF0AzMzMzMzMXQAAAAAAAABpAMzMzMzMzGUAAAAAAAAAYQDMzMzMzMxdAZmZmZmZmFkBmZmZmZmYWQJqZmZmZmRVAMzMzMzMzGUAAAAAAAAAYQAAAAAAAABhAmpmZmZmZFUAzMzMzMzMVQDMzMzMzMxdAzczMzMzMFkCamZmZmZkVQGZmZmZmZhRAZmZmZmZmFEDNzMzMzMwUQGZmZmZmZhRAzczMzMzMFkAzMzMzMzMXQJqZmZmZmRVAmpmZmZmZE0CamZmZmZkTQM3MzMzMzBRAzczMzMzMFECamZmZmZkTQDMzMzMzMxNAZmZmZmZmEkAzMzMzMzMTQGZmZmZmZhJAZmZmZmZmFEBmZmZmZmYUQDMzMzMzMxNAAAAAAAAAEkCamZmZmZkRQDMzMzMzMxNAAAAAAAAAFEBmZmZmZmYSQJqZmZmZmRFAZmZmZmZmEEAzMzMzMzMRQDMzMzMzMxFAAAAAAAAAFECamZmZmZkTQAAAAAAAABJAMzMzMzMzEUAzMzMzMzMRQM3MzMzMzBJAmpmZmZmZE0BmZmZmZmYSQAAAAAAAABJAmpmZmZmZEUAAAAAAAAASQDMzMzMzMxNAmpmZmZmZFUDNzMzMzMwUQM3MzMzMzBRAMzMzMzMzE0DNzMzMzMwUQM3MzMzMzBZAAAAAAAAAGEBmZmZmZmYYQAAAAAAAABhAZmZmZmZmGEAAAAAAAAAaQGZmZmZmZhxAAAAAAAAAIUDNzMzMzMwhQAAAAAAAACJAMzMzMzMzIUAzMzMzMzMiQGZmZmZmZiNAZmZmZmZmI0AzMzMzMzMjQAAAAAAAACNAAAAAAAAAI0DNzMzMzMwiQGZmZmZmZiNAMzMzMzMzJUDNzMzMzMwkQGZmZmZmZiRAAAAAAAAAI0CamZmZmZkiQDMzMzMzMyNAZmZmZmZmI0AAAAAAAAAjQGZmZmZmZiJAAAAAAAAAIkCamZmZmZkiQDMzMzMzMyJAmpmZmZmZI0AAAAAAAAAjQGZmZmZmZiJAZmZmZmZmIUBmZmZmZmYhQJqZmZmZmSJAmpmZmZmZIkAzMzMzMzMiQJqZmZmZmSFAAAAAAAAAIUBmZmZmZmYgQJqZmZmZmSBAmpmZmZmZIUBmZmZmZmYhQM3MzMzMzCBAzczMzMzMHkCamZmZmZkfQM3MzMzMzCBAMzMzMzMzIUBmZmZmZmYgQGZmZmZmZh5AAAAAAAAAHkCamZmZmZkdQGZmZmZmZh5AAAAAAAAAIUAzMzMzMzMgQGZmZmZmZh5AZmZmZmZmHEAzMzMzMzMdQDMzMzMzMx9AzczMzMzMHkAzMzMzMzMdQAAAAAAAABxAAAAAAAAAHEBmZmZmZmYaQAAAAAAAABpAAAAAAAAAHEAAAAAAAAAcQDMzMzMzMxtAmpmZmZmZF0BmZmZmZmYYQDMzMzMzMxlAAAAAAAAAGkAzMzMzMzMZQM3MzMzMzBZAAAAAAAAAFkAAAAAAAAAWQJqZmZmZmRVAZmZmZmZmGEAzMzMzMzMXQGZmZmZmZhZAZmZmZmZmFEAzMzMzMzMVQAAAAAAAABZAZmZmZmZmFkDNzMzMzMwUQJqZmZmZmRNAMzMzMzMzE0AzMzMzMzMTQDMzMzMzMxNAMzMzMzMzFUDNzMzMzMwUQGZmZmZmZhRAzczMzMzMEkAAAAAAAAASQGZmZmZmZhRAZmZmZmZmFEAAAAAAAAAUQDMzMzMzMxNAzczMzMzMEkCamZmZmZkRQAAAAAAAABJA\"},\"shape\":[828],\"dtype\":\"float64\",\"order\":\"little\"}]]}}},\"glyph\":{\"type\":\"object\",\"name\":\"Rect\",\"id\":\"41534\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":null},\"width\":{\"type\":\"value\",\"value\":1},\"fill_color\":{\"type\":\"field\",\"field\":\"rate\",\"transform\":{\"id\":\"41499\"}},\"x\":{\"type\":\"field\",\"field\":\"Year\"},\"height\":{\"type\":\"value\",\"value\":1},\"y\":{\"type\":\"field\",\"field\":\"Month\"}}}}}],\"height\":300,\"right\":[{\"type\":\"object\",\"name\":\"ColorBar\",\"id\":\"41542\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"PrintfTickFormatter\",\"id\":\"41541\",\"attributes\":{\"format\":\"%d%%\"}},\"major_label_policy\":{\"type\":\"object\",\"name\":\"NoOverlap\",\"id\":\"41543\"},\"color_mapper\":{\"id\":\"41499\"},\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"41540\",\"attributes\":{\"mantissas\":[1,2,5],\"desired_num_ticks\":9}}}}]}}]}};\n", - " const render_items = [{\"docid\":\"44d1bf3a-a74d-4b27-9c7b-4797d28be4ab\",\"roots\":{\"41500\":\"971ef454-9e11-4765-8d30-2e09b672423d\"},\"root_ids\":[\"41500\"]}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"44d1bf3a-a74d-4b27-9c7b-4797d28be4ab\":{\"version\":\"3.0.0.dev13\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"41500\",\"attributes\":{\"y_range\":{\"type\":\"object\",\"name\":\"FactorRange\",\"id\":\"41510\",\"attributes\":{\"factors\":[\"Dec\",\"Nov\",\"Oct\",\"Sep\",\"Aug\",\"Jul\",\"Jun\",\"May\",\"Apr\",\"Mar\",\"Feb\",\"Jan\"]}},\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"41506\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"HoverTool\",\"id\":\"41528\",\"attributes\":{\"renderers\":\"auto\"}}]}},\"left\":[{\"type\":\"object\",\"name\":\"CategoricalAxis\",\"id\":\"41522\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"CategoricalTickFormatter\",\"id\":\"41524\"},\"major_label_standoff\":0,\"ticker\":{\"type\":\"object\",\"name\":\"CategoricalTicker\",\"id\":\"41525\"},\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"41523\"},\"major_tick_line_color\":null,\"axis_line_color\":null,\"major_label_text_font_size\":\"7px\"}}],\"above\":[{\"type\":\"object\",\"name\":\"CategoricalAxis\",\"id\":\"41516\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"CategoricalTickFormatter\",\"id\":\"41518\"},\"major_label_standoff\":0,\"ticker\":{\"type\":\"object\",\"name\":\"CategoricalTicker\",\"id\":\"41519\"},\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"41517\"},\"major_tick_line_color\":null,\"axis_line_color\":null,\"major_label_text_font_size\":\"7px\",\"major_label_orientation\":1.0}}],\"y_scale\":{\"type\":\"object\",\"name\":\"CategoricalScale\",\"id\":\"41514\"},\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"41521\",\"attributes\":{\"axis\":{\"id\":\"41516\"}}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"41527\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"41522\"}}}],\"toolbar_location\":null,\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"41501\",\"attributes\":{\"text\":\"US unemployment 1948\\u20142016\"}},\"x_scale\":{\"type\":\"object\",\"name\":\"CategoricalScale\",\"id\":\"41512\"},\"x_range\":{\"type\":\"object\",\"name\":\"FactorRange\",\"id\":\"41508\",\"attributes\":{\"factors\":[\"1948\",\"1949\",\"1950\",\"1951\",\"1952\",\"1953\",\"1954\",\"1955\",\"1956\",\"1957\",\"1958\",\"1959\",\"1960\",\"1961\",\"1962\",\"1963\",\"1964\",\"1965\",\"1966\",\"1967\",\"1968\",\"1969\",\"1970\",\"1971\",\"1972\",\"1973\",\"1974\",\"1975\",\"1976\",\"1977\",\"1978\",\"1979\",\"1980\",\"1981\",\"1982\",\"1983\",\"1984\",\"1985\",\"1986\",\"1987\",\"1988\",\"1989\",\"1990\",\"1991\",\"1992\",\"1993\",\"1994\",\"1995\",\"1996\",\"1997\",\"1998\",\"1999\",\"2000\",\"2001\",\"2002\",\"2003\",\"2004\",\"2005\",\"2006\",\"2007\",\"2008\",\"2009\",\"2010\",\"2011\",\"2012\",\"2013\",\"2014\",\"2015\",\"2016\"]}},\"width\":800,\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"41537\",\"attributes\":{\"muted_glyph\":{\"type\":\"object\",\"name\":\"Rect\",\"id\":\"41536\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"line_color\":{\"type\":\"value\",\"value\":null},\"width\":{\"type\":\"value\",\"value\":1},\"fill_color\":{\"type\":\"field\",\"field\":\"rate\",\"transform\":{\"type\":\"object\",\"name\":\"LinearColorMapper\",\"id\":\"41499\",\"attributes\":{\"low\":2.4,\"palette\":[\"#75968f\",\"#a5bab7\",\"#c9d9d3\",\"#e2e2e2\",\"#dfccce\",\"#ddb7b1\",\"#cc7878\",\"#933b41\",\"#550b1d\"],\"high\":11.4}}},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"x\":{\"type\":\"field\",\"field\":\"Year\"},\"height\":{\"type\":\"value\",\"value\":1},\"y\":{\"type\":\"field\",\"field\":\"Month\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Rect\",\"id\":\"41535\",\"attributes\":{\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"line_color\":{\"type\":\"value\",\"value\":null},\"width\":{\"type\":\"value\",\"value\":1},\"fill_color\":{\"type\":\"field\",\"field\":\"rate\",\"transform\":{\"id\":\"41499\"}},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"x\":{\"type\":\"field\",\"field\":\"Year\"},\"height\":{\"type\":\"value\",\"value\":1},\"y\":{\"type\":\"field\",\"field\":\"Month\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"41538\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"41539\"}}},\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"41496\",\"attributes\":{\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"41498\"},\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"41497\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"data\":{\"type\":\"map\",\"entries\":[[\"index\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"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owIAAKQCAAClAgAApgIAAKcCAACoAgAAqQIAAKoCAACrAgAArAIAAK0CAACuAgAArwIAALACAACxAgAAsgIAALMCAAC0AgAAtQIAALYCAAC3AgAAuAIAALkCAAC6AgAAuwIAALwCAAC9AgAAvgIAAL8CAADAAgAAwQIAAMICAADDAgAAxAIAAMUCAADGAgAAxwIAAMgCAADJAgAAygIAAMsCAADMAgAAzQIAAM4CAADPAgAA0AIAANECAADSAgAA0wIAANQCAADVAgAA1gIAANcCAADYAgAA2QIAANoCAADbAgAA3AIAAN0CAADeAgAA3wIAAOACAADhAgAA4gIAAOMCAADkAgAA5QIAAOYCAADnAgAA6AIAAOkCAADqAgAA6wIAAOwCAADtAgAA7gIAAO8CAADwAgAA8QIAAPICAADzAgAA9AIAAPUCAAD2AgAA9wIAAPgCAAD5AgAA+gIAAPsCAAD8AgAA/QIAAP4CAAD/AgAAAAMAAAEDAAACAwAAAwMAAAQDAAAFAwAABgMAAAcDAAAIAwAACQMAAAoDAAALAwAADAMAAA0DAAAOAwAADwMAABADAAARAwAAEgMAABMDAAAUAwAAFQMAABYDAAAXAwAAGAMAABkDAAAaAwAAGwMAABwDAAAdAwAAHgMAAB8DAAAgAwAAIQMAACIDAAAjAwAAJAMAACUDAAAmAwAAJwMAACgDAAApAwAAKgMAACsDAAAsAwAALQMAAC4DAAAvAwAAMAMAADEDAAAyAwAAMwMAADQDAAA1AwAANgMAADcDAAA4AwAAOQMAADoDAAA7AwAA\"},\"shape\":[828],\"dtype\":\"int32\",\"order\":\"little\"}],[\"Year\",{\"type\":\"ndarray\",\"array\":[\"1948\",\"1948\",\"1948\",\"1948\",\"1948\",\"1948\",\"1948\",\"1948\",\"1948\",\"1948\",\"1948\",\"1948\",\"1949\",\"1949\",\"1949\",\"1949\",\"1949\",\"1949\",\"1949\",\"1949\",\"1949\",\"1949\",\"1949\",\"1949\",\"1950\",\"1950\",\"1950\",\"1950\",\"1950\",\"1950\",\"1950\",\"1950\",\"1950\",\"1950\",\"1950\",\"1950\",\"1951\",\"1951\",\"1951\",\"1951\",\"1951\",\"1951\",\"1951\",\"1951\",\"1951\",\"1951\",\"1951\",\"1951\",\"1952\",\"1952\",\"1952\",\"1952\",\"1952\",\"1952\",\"1952\",\"1952\",\"1952\",\"1952\",\"1952\",\"1952\",\"1953\",\"1953\",\"1953\",\"1953\",\"1953\",\"1953\",\"1953\",\"1953\",\"1953\",\"1953\",\"1953\",\"1953\",\"1954\",\"1954\",\"1954\",\"1954\",\"1954\",\"1954\",\"1954\",\"1954\",\"1954\",\"1954\",\"1954\",\"1954\",\"1955\",\"1955\",\"1955\",\"1955\",\"1955\",\"1955\",\"1955\",\"1955\",\"1955\",\"1955\",\"1955\",\"1955\",\"1956\",\"1956\",\"1956\",\"1956\",\"1956\",\"1956\",\"1956\",\"1956\",\"1956\",\"1956\",\"1956\",\"1956\",\"1957\",\"1957\",\"1957\",\"1957\",\"1957\",\"1957\",\"1957\",\"1957\",\"1957\",\"1957\",\"1957\",\"1957\",\"1958\",\"1958\",\"1958\",\"1958\",\"1958\",\"1958\",\"1958\",\"1958\",\"1958\",\"1958\",\"1958\",\"1958\",\"1959\",\"1959\",\"1959\",\"1959\",\"1959\",\"1959\",\"1959\",\"1959\",\"1959\",\"1959\",\"1959\",\"1959\",\"1960\",\"1960\",\"1960\",\"1960\",\"1960\",\"1960\",\"1960\",\"1960\",\"1960\",\"1960\",\"1960\",\"1960\",\"1961\",\"1961\",\"1961\",\"1961\",\"1961\",\"1961\",\"1961\",\"1961\",\"1961\",\"1961\",\"1961\",\"1961\",\"1962\",\"1962\",\"1962\",\"1962\",\"1962\",\"1962\",\"1962\",\"1962\",\"1962\",\"1962\",\"1962\",\"1962\",\"1963\",\"1963\",\"1963\",\"1963\",\"1963\",\"1963\",\"1963\",\"1963\",\"1963\",\"1963\",\"1963\",\"1963\",\"1964\",\"1964\",\"1964\",\"1964\",\"1964\",\"1964\",\"1964\",\"1964\",\"1964\",\"1964\",\"1964\",\"1964\",\"1965\",\"1965\",\"1965\",\"1965\",\"1965\",\"1965\",\"1965\",\"1965\",\"1965\",\"1965\",\"1965\",\"1965\",\"1966\",\"1966\",\"1966\",\"1966\",\"1966\",\"1966\",\"1966\",\"1966\",\"1966\",\"1966\",\"1966\",\"1966\",\"1967\",\"1967\",\"1967\",\"1967\",\"1967\",\"1967\",\"1967\",\"1967\",\"1967\",\"1967\",\"1967\",\"1967\",\"1968\",\"1968\",\"1968\",\"1968\",\"1968\",\"1968\",\"1968\",\"1968\",\"1968\",\"1968\",\"1968\",\"1968\",\"1969\",\"1969\",\"1969\",\"1969\",\"1969\",\"1969\",\"1969\",\"1969\",\"1969\",\"1969\",\"1969\",\"1969\",\"1970\",\"1970\",\"1970\",\"1970\",\"1970\",\"1970\",\"1970\",\"1970\",\"1970\",\"1970\",\"1970\",\"1970\",\"1971\",\"1971\",\"1971\",\"1971\",\"1971\",\"1971\",\"1971\",\"1971\",\"1971\",\"1971\",\"1971\",\"1971\",\"1972\",\"1972\",\"1972\",\"1972\",\"1972\",\"1972\",\"1972\",\"1972\",\"1972\",\"1972\",\"1972\",\"1972\",\"1973\",\"1973\",\"1973\",\"1973\",\"1973\",\"1973\",\"1973\",\"1973\",\"1973\",\"1973\",\"1973\",\"1973\",\"1974\",\"1974\",\"1974\",\"1974\",\"1974\",\"1974\",\"1974\",\"1974\",\"1974\",\"1974\",\"1974\",\"1974\",\"1975\",\"1975\",\"1975\",\"1975\",\"1975\",\"1975\",\"1975\",\"1975\",\"1975\",\"1975\",\"1975\",\"1975\",\"1976\",\"1976\",\"1976\",\"1976\",\"1976\",\"1976\",\"1976\",\"1976\",\"1976\",\"1976\",\"1976\",\"1976\",\"1977\",\"1977\",\"1977\",\"1977\",\"1977\",\"1977\",\"1977\",\"1977\",\"1977\",\"1977\",\"1977\",\"1977\",\"1978\",\"1978\",\"1978\",\"1978\",\"1978\",\"1978\",\"1978\",\"1978\",\"1978\",\"1978\",\"1978\",\"1978\",\"1979\",\"1979\",\"1979\",\"1979\",\"1979\",\"1979\",\"1979\",\"1979\",\"1979\",\"1979\",\"1979\",\"1979\",\"1980\",\"1980\",\"1980\",\"1980\",\"1980\",\"1980\",\"1980\",\"1980\",\"1980\",\"1980\",\"1980\",\"1980\",\"1981\",\"1981\",\"1981\",\"1981\",\"1981\",\"1981\",\"1981\",\"1981\",\"1981\",\"1981\",\"1981\",\"1981\",\"1982\",\"1982\",\"1982\",\"1982\",\"1982\",\"1982\",\"1982\",\"1982\",\"1982\",\"1982\",\"1982\",\"1982\",\"1983\",\"1983\",\"1983\",\"1983\",\"1983\",\"1983\",\"1983\",\"1983\",\"1983\",\"1983\",\"1983\",\"1983\",\"1984\",\"1984\",\"1984\",\"1984\",\"1984\",\"1984\",\"1984\",\"1984\",\"1984\",\"1984\",\"1984\",\"1984\",\"1985\",\"1985\",\"1985\",\"1985\",\"1985\",\"1985\",\"1985\",\"1985\",\"1985\",\"1985\",\"1985\",\"1985\",\"1986\",\"1986\",\"1986\",\"1986\",\"1986\",\"1986\",\"1986\",\"1986\",\"1986\",\"1986\",\"1986\",\"1986\",\"1987\",\"1987\",\"1987\",\"1987\",\"1987\",\"1987\",\"1987\",\"1987\",\"1987\",\"1987\",\"1987\",\"1987\",\"1988\",\"1988\",\"1988\",\"1988\",\"1988\",\"1988\",\"1988\",\"1988\",\"1988\",\"1988\",\"1988\",\"1988\",\"1989\",\"1989\",\"1989\",\"1989\",\"1989\",\"1989\",\"1989\",\"1989\",\"1989\",\"1989\",\"1989\",\"1989\",\"1990\",\"1990\",\"1990\",\"1990\",\"1990\",\"1990\",\"1990\",\"1990\",\"1990\",\"1990\",\"1990\",\"1990\",\"1991\",\"1991\",\"1991\",\"1991\",\"1991\",\"1991\",\"1991\",\"1991\",\"1991\",\"1991\",\"1991\",\"1991\",\"1992\",\"1992\",\"1992\",\"1992\",\"1992\",\"1992\",\"1992\",\"1992\",\"1992\",\"1992\",\"1992\",\"1992\",\"1993\",\"1993\",\"1993\",\"1993\",\"1993\",\"1993\",\"1993\",\"1993\",\"1993\",\"1993\",\"1993\",\"1993\",\"1994\",\"1994\",\"1994\",\"1994\",\"1994\",\"1994\",\"1994\",\"1994\",\"1994\",\"1994\",\"1994\",\"1994\",\"1995\",\"1995\",\"1995\",\"1995\",\"1995\",\"1995\",\"1995\",\"1995\",\"1995\",\"1995\",\"1995\",\"1995\",\"1996\",\"1996\",\"1996\",\"1996\",\"1996\",\"1996\",\"1996\",\"1996\",\"1996\",\"1996\",\"1996\",\"1996\",\"1997\",\"1997\",\"1997\",\"1997\",\"1997\",\"1997\",\"1997\",\"1997\",\"1997\",\"1997\",\"1997\",\"1997\",\"1998\",\"1998\",\"1998\",\"1998\",\"1998\",\"1998\",\"1998\",\"1998\",\"1998\",\"1998\",\"1998\",\"1998\",\"1999\",\"1999\",\"1999\",\"1999\",\"1999\",\"1999\",\"1999\",\"1999\",\"1999\",\"1999\",\"1999\",\"1999\",\"2000\",\"2000\",\"2000\",\"2000\",\"2000\",\"2000\",\"2000\",\"2000\",\"2000\",\"2000\",\"2000\",\"2000\",\"2001\",\"2001\",\"2001\",\"2001\",\"2001\",\"2001\",\"2001\",\"2001\",\"2001\",\"2001\",\"2001\",\"2001\",\"2002\",\"2002\",\"2002\",\"2002\",\"2002\",\"2002\",\"2002\",\"2002\",\"2002\",\"2002\",\"2002\",\"2002\",\"2003\",\"2003\",\"2003\",\"2003\",\"2003\",\"2003\",\"2003\",\"2003\",\"2003\",\"2003\",\"2003\",\"2003\",\"2004\",\"2004\",\"2004\",\"2004\",\"2004\",\"2004\",\"2004\",\"2004\",\"2004\",\"2004\",\"2004\",\"2004\",\"2005\",\"2005\",\"2005\",\"2005\",\"2005\",\"2005\",\"2005\",\"2005\",\"2005\",\"2005\",\"2005\",\"2005\",\"2006\",\"2006\",\"2006\",\"2006\",\"2006\",\"2006\",\"2006\",\"2006\",\"2006\",\"2006\",\"2006\",\"2006\",\"2007\",\"2007\",\"2007\",\"2007\",\"2007\",\"2007\",\"2007\",\"2007\",\"2007\",\"2007\",\"2007\",\"2007\",\"2008\",\"2008\",\"2008\",\"2008\",\"2008\",\"2008\",\"2008\",\"2008\",\"2008\",\"2008\",\"2008\",\"2008\",\"2009\",\"2009\",\"2009\",\"2009\",\"2009\",\"2009\",\"2009\",\"2009\",\"2009\",\"2009\",\"2009\",\"2009\",\"2010\",\"2010\",\"2010\",\"2010\",\"2010\",\"2010\",\"2010\",\"2010\",\"2010\",\"2010\",\"2010\",\"2010\",\"2011\",\"2011\",\"2011\",\"2011\",\"2011\",\"2011\",\"2011\",\"2011\",\"2011\",\"2011\",\"2011\",\"2011\",\"2012\",\"2012\",\"2012\",\"2012\",\"2012\",\"2012\",\"2012\",\"2012\",\"2012\",\"2012\",\"2012\",\"2012\",\"2013\",\"2013\",\"2013\",\"2013\",\"2013\",\"2013\",\"2013\",\"2013\",\"2013\",\"2013\",\"2013\",\"2013\",\"2014\",\"2014\",\"2014\",\"2014\",\"2014\",\"2014\",\"2014\",\"2014\",\"2014\",\"2014\",\"2014\",\"2014\",\"2015\",\"2015\",\"2015\",\"2015\",\"2015\",\"2015\",\"2015\",\"2015\",\"2015\",\"2015\",\"2015\",\"2015\",\"2016\",\"2016\",\"2016\",\"2016\",\"2016\",\"2016\",\"2016\",\"2016\",\"2016\",\"2016\",\"2016\",\"2016\"],\"shape\":[828],\"dtype\":\"object\",\"order\":\"little\"}],[\"Month\",{\"type\":\"ndarray\",\"array\":[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\",\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"],\"shape\":[828],\"dtype\":\"object\",\"order\":\"little\"}],[\"rate\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"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MzMVQGZmZmZmZhRAzczMzMzMGECamZmZmZkXQM3MzMzMzBZAZmZmZmZmFkAAAAAAAAAWQDMzMzMzMxdAmpmZmZmZF0BmZmZmZmYWQJqZmZmZmRVAzczMzMzMFEAzMzMzMzMVQM3MzMzMzBRAMzMzMzMzGUAAAAAAAAAYQDMzMzMzMxdAmpmZmZmZFUCamZmZmZkVQAAAAAAAABZAZmZmZmZmFkBmZmZmZmYUQAAAAAAAABRAmpmZmZmZE0AAAAAAAAAUQAAAAAAAABRAmpmZmZmZF0DNzMzMzMwWQAAAAAAAABZAMzMzMzMzE0DNzMzMzMwSQM3MzMzMzBRAAAAAAAAAFEAzMzMzMzMTQM3MzMzMzBJAmpmZmZmZEUAzMzMzMzMRQJqZmZmZmRFAzczMzMzMFEAAAAAAAAAUQAAAAAAAABRAZmZmZmZmEEDNzMzMzMwQQM3MzMzMzBJAzczMzMzMEkAAAAAAAAASQJqZmZmZmRFAzczMzMzMEEBmZmZmZmYQQAAAAAAAABBAMzMzMzMzE0DNzMzMzMwSQJqZmZmZmRFAZmZmZmZmEEAAAAAAAAAQQAAAAAAAABJAAAAAAAAAEkDNzMzMzMwQQGZmZmZmZhBAZmZmZmZmDkBmZmZmZmYOQJqZmZmZmQ1AAAAAAAAAEkCamZmZmZkRQDMzMzMzMxFAmpmZmZmZDUBmZmZmZmYOQGZmZmZmZhBAzczMzMzMEEBmZmZmZmYQQGZmZmZmZg5AzczMzMzMDECamZmZmZkNQJqZmZmZmQ1AzczMzMzMEkBmZmZmZmYSQAAAAAAAABJAzczMzMzMEEBmZmZmZmYQQM3MzMzMzBJAzczMzMzMEkCamZmZmZkTQM3MzMzMzBJAAAAAAAAAFEAzMzMzMzMVQJqZmZmZmRVAMzMzMzMzGUBmZmZmZmYYQGZmZmZmZhhAzczMzMzMFkAAAAAAAAAWQAAAAAAAABhAmpmZmZmZF0DNzMzMzMwWQJqZmZmZmRVAMzMzMzMzFUBmZmZmZmYWQM3MzMzMzBZAAAAAAAAAGkCamZmZmZkZQM3MzMzMzBhAMzMzMzMzF0AzMzMzMzMXQAAAAAAAABpAMzMzMzMzGUAAAAAAAAAYQDMzMzMzMxdAZmZmZmZmFkBmZmZmZmYWQJqZmZmZmRVAMzMzMzMzGUAAAAAAAAAYQAAAAAAAABhAmpmZmZmZFUAzMzMzMzMVQDMzMzMzMxdAzczMzMzMFkCamZmZmZkVQGZmZmZmZhRAZmZmZmZmFEDNzMzMzMwUQGZmZmZmZhRAzczMzMzMFkAzMzMzMzMXQJqZmZmZmRVAmpmZmZmZE0CamZmZmZkTQM3MzMzMzBRAzczMzMzMFECamZmZmZkTQDMzMzMzMxNAZmZmZmZmEkAzMzMzMzMTQGZmZmZmZhJAZmZmZmZmFEBmZmZmZmYUQDMzMzMzMxNAAAAAAAAAEkCamZmZmZkRQDMzMzMzMxNAAAAAAAAAFEBmZmZmZmYSQJqZmZmZmRFAZmZmZmZmEEAzMzMzMzMRQDMzMzMzMxFAAAAAAAAAFECamZmZmZkTQAAAAAAAABJAMzMzMzMzEUAzMzMzMzMRQM3MzMzMzBJAmpmZmZmZE0BmZmZmZmYSQAAAAAAAABJAmpmZmZmZEUAAAAAAAAASQDMzMzMzMxNAmpmZmZmZFUDNzMzMzMwUQM3MzMzMzBRAMzMzMzMzE0DNzMzMzMwUQM3MzMzMzBZAAAAAAAAAGEBmZmZmZmYYQAAAAAAAABhAZmZmZmZmGEAAAAAAAAAaQGZmZmZmZhxAAAAAAAAAIUDNzMzMzMwhQAAAAAAAACJAMzMzMzMzIUAzMzMzMzMiQGZmZmZmZiNAZmZmZmZmI0AzMzMzMzMjQAAAAAAAACNAAAAAAAAAI0DNzMzMzMwiQGZmZmZmZiNAMzMzMzMzJUDNzMzMzMwkQGZmZmZmZiRAAAAAAAAAI0CamZmZmZkiQDMzMzMzMyNAZmZmZmZmI0AAAAAAAAAjQGZmZmZmZiJAAAAAAAAAIkCamZmZmZkiQDMzMzMzMyJAmpmZmZmZI0AAAAAAAAAjQGZmZmZmZiJAZmZmZmZmIUBmZmZmZmYhQJqZmZmZmSJAmpmZmZmZIkAzMzMzMzMiQJqZmZmZmSFAAAAAAAAAIUBmZmZmZmYgQJqZmZmZmSBAmpmZmZmZIUBmZmZmZmYhQM3MzMzMzCBAzczMzMzMHkCamZmZmZkfQM3MzMzMzCBAMzMzMzMzIUBmZmZmZmYgQGZmZmZmZh5AAAAAAAAAHkCamZmZmZkdQGZmZmZmZh5AAAAAAAAAIUAzMzMzMzMgQGZmZmZmZh5AZmZmZmZmHEAzMzMzMzMdQDMzMzMzMx9AzczMzMzMHkAzMzMzMzMdQAAAAAAAABxAAAAAAAAAHEBmZmZmZmYaQAAAAAAAABpAAAAAAAAAHEAAAAAAAAAcQDMzMzMzMxtAmpmZmZmZF0BmZmZmZmYYQDMzMzMzMxlAAAAAAAAAGkAzMzMzMzMZQM3MzMzMzBZAAAAAAAAAFkAAAAAAAAAWQJqZmZmZmRVAZmZmZmZmGEAzMzMzMzMXQGZmZmZmZhZAZmZmZmZmFEAzMzMzMzMVQAAAAAAAABZAZmZmZmZmFkDNzMzMzMwUQJqZmZmZmRNAMzMzMzMzE0AzMzMzMzMTQDMzMzMzMxNAMzMzMzMzFUDNzMzMzMwUQGZmZmZmZhRAzczMzMzMEkAAAAAAAAASQGZmZmZmZhRAZmZmZmZmFEAAAAAAAAAUQDMzMzMzMxNAzczMzMzMEkCamZmZmZkRQAAAAAAAABJA\"},\"shape\":[828],\"dtype\":\"float64\",\"order\":\"little\"}]]}}},\"glyph\":{\"type\":\"object\",\"name\":\"Rect\",\"id\":\"41534\",\"attributes\":{\"line_color\":{\"type\":\"value\",\"value\":null},\"width\":{\"type\":\"value\",\"value\":1},\"fill_color\":{\"type\":\"field\",\"field\":\"rate\",\"transform\":{\"id\":\"41499\"}},\"x\":{\"type\":\"field\",\"field\":\"Year\"},\"height\":{\"type\":\"value\",\"value\":1},\"y\":{\"type\":\"field\",\"field\":\"Month\"}}}}}],\"height\":300,\"right\":[{\"type\":\"object\",\"name\":\"ColorBar\",\"id\":\"41542\",\"attributes\":{\"formatter\":{\"type\":\"object\",\"name\":\"PrintfTickFormatter\",\"id\":\"41541\",\"attributes\":{\"format\":\"%d%%\"}},\"major_label_policy\":{\"type\":\"object\",\"name\":\"NoOverlap\",\"id\":\"41543\"},\"color_mapper\":{\"id\":\"41499\"},\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"41540\",\"attributes\":{\"mantissas\":[1,2,5],\"desired_num_ticks\":9}}}}]}}]}};\n const render_items = [{\"docid\":\"44d1bf3a-a74d-4b27-9c7b-4797d28be4ab\",\"roots\":{\"41500\":\"971ef454-9e11-4765-8d30-2e09b672423d\"},\"root_ids\":[\"41500\"]}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -5528,32 +4664,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"6fc7af1d-9af6-47ac-a22f-005fa4aa52d5\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"height\":648,\"outline_line_color\":null,\"renderers\":[{\"id\":\"3273\"},{\"id\":\"3279\"}],\"title\":{\"id\":\"3256\"},\"toolbar\":{\"id\":\"3267\"},\"toolbar_location\":null,\"width\":478,\"x_range\":{\"id\":\"3258\"},\"x_scale\":{\"id\":\"3262\"},\"y_range\":{\"id\":\"3260\"},\"y_scale\":{\"id\":\"3264\"}},\"id\":\"3255\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"line_alpha\":0.1,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"3277\",\"type\":\"Line\"},{\"attributes\":{\"tools\":[{\"id\":\"3266\"}]},\"id\":\"3267\",\"type\":\"Toolbar\"},{\"attributes\":{\"data\":{\"name\":[\"AWI\",\"CISPA\",\"DESY\",\"DKFZ\",\"DLR\",\"DZNE\",\"FZJ\",\"GEOMAR\",\"GFZ\",\"GSI\",\"HGF\",\"HZB\",\"HZDR\",\"HZI\",\"HelmholtzMunich\",\"Hereon\",\"KIT\",\"MDC\",\"UFZ\"],\"x\":[147,50,205,152,92,97,35,205,345,151,350,375,405,240,300,257,131,374,329],\"y\":[527,181,530,187,286,262,288,590,408,227,444,428,322,403,92,505,138,455,336]},\"selected\":{\"id\":\"3406\"},\"selection_policy\":{\"id\":\"3405\"}},\"id\":\"3254\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"3405\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"3406\",\"type\":\"Selection\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"white\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_width\":{\"value\":2},\"size\":{\"value\":12},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"3272\",\"type\":\"Scatter\"},{\"attributes\":{\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"3276\",\"type\":\"Line\"},{\"attributes\":{\"source\":{\"id\":\"3275\"}},\"id\":\"3280\",\"type\":\"CDSView\"},{\"attributes\":{\"line_alpha\":0.2,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"3278\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"3262\",\"type\":\"LinearScale\"},{\"attributes\":{\"source\":{\"id\":\"3254\"}},\"id\":\"3274\",\"type\":\"CDSView\"},{\"attributes\":{\"end\":646.0000000000002},\"id\":\"3260\",\"type\":\"Range1d\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.8},\"fill_color\":{\"value\":\"white\"},\"line_width\":{\"value\":2},\"size\":{\"value\":12},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"3270\",\"type\":\"Scatter\"},{\"attributes\":{},\"id\":\"3407\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"3275\"},\"glyph\":{\"id\":\"3276\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"3278\"},\"nonselection_glyph\":{\"id\":\"3277\"},\"view\":{\"id\":\"3280\"}},\"id\":\"3279\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"3264\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"text\":\"HGF centers\"},\"id\":\"3256\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"3408\",\"type\":\"Selection\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"white\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_width\":{\"value\":2},\"size\":{\"value\":12},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"3271\",\"type\":\"Scatter\"},{\"attributes\":{\"callback\":null},\"id\":\"3266\",\"type\":\"HoverTool\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"3254\"},\"glyph\":{\"id\":\"3270\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"3272\"},\"nonselection_glyph\":{\"id\":\"3271\"},\"view\":{\"id\":\"3274\"}},\"id\":\"3273\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"end\":475.57299999999907},\"id\":\"3258\",\"type\":\"Range1d\"},{\"attributes\":{\"data\":{\"x\":[473.30300000000136,473.30300000000136,471.05300000000136,468.2330000000014,461.45300000000145,457.8830000000015,458.69300000000146,457.80300000000136,459.81300000000135,459.92300000000125,459.4630000000012,456.8430000000013,454.3430000000013,454.29300000000137,452.2730000000014,450.83300000000133,451.83300000000133,455.43300000000124,455.19300000000123,455.3630000000013,455.79300000000137,456.2630000000014,453.33300000000133,454.18300000000124,453.3730000000013,453.3530000000013,452.58300000000133,452.58300000000133,452.7730000000014,453.6230000000013,453.57300000000134,451.1430000000013,450.3430000000013,446.40300000000127,445.7130000000012,444.7130000000012,443.5730000000011,443.2330000000012,445.27300000000116,446.2330000000012,446.8930000000013,446.66300000000126,447.2330000000012,447.80300000000113,444.15300000000104,441.40300000000104,436.443000000001,435.48300000000097,432.88300000000106,430.5830000000011,428.2130000000012,424.53300000000115,424.28300000000115,423.87300000000107,423.53300000000115,420.8130000000011,420.7130000000012,421.3830000000013,421.4930000000012,421.52300000000116,427.3430000000011,427.8630000000011,431.173000000001,430.5930000000011,431.8430000000011,433.5830000000011,432.5830000000011,431.173000000001,431.173000000001,431.0830000000011,428.78300000000115,427.76300000000117,426.5930000000011,425.963000000001,424.66300000000103,423.3630000000011,422.963000000001,422.953000000001,422.923000000001,421.713000000001,420.73300000000097,420.51300000000094,420.0330000000009,420.02300000000093,419.34300000000087,417.223000000001,417.0630000000009,415.59300000000087,414.2830000000009,411.3230000000009,409.963000000001,406.933000000001,404.963000000001,403.0930000000011,402.2230000000012,402.3230000000011,403.88300000000106,404.443000000001,404.8630000000011,407.52300000000116,408.37300000000107,409.3130000000011,411.423000000001,413.953000000001,416.223000000001,417.703000000001,418.51300000000094,418.473000000001,418.193000000001,418.173000000001,417.99300000000096,413.37300000000107,411.80300000000113,408.8230000000011,407.76300000000117,403.19300000000123,401.77300000000116,399.15300000000127,397.6030000000013,395.55300000000136,395.18300000000147,393.36300000000153,392.1730000000015,389.84300000000155,386.75300000000163,381.59300000000155,380.45300000000145,380.82300000000134,379.30300000000136,376.9930000000014,375.3730000000015,374.5530000000016,373.8830000000015,373.6430000000015,372.22300000000143,371.82300000000134,371.80300000000136,372.44300000000146,374.7330000000014,375.72300000000143,378.06300000000135,377.6130000000013,377.1230000000013,376.66300000000126,376.7130000000012,377.02300000000116,377.13300000000106,377.183000000001,377.213000000001,377.50300000000095,378.8230000000009,380.02300000000093,380.99300000000096,380.85300000000086,380.97300000000075,381.20300000000077,381.59300000000087,382.86300000000085,384.3030000000009,384.4030000000008,384.5230000000007,385.58300000000065,386.0330000000007,388.21300000000076,388.6930000000008,388.20300000000077,388.2930000000007,388.56300000000067,391.07300000000066,392.49300000000073,392.49300000000073,392.5030000000007,393.56300000000067,391.31300000000067,390.5330000000007,388.3930000000006,388.1130000000006,387.82300000000066,387.23300000000074,386.7530000000007,386.59300000000064,386.2930000000007,385.4330000000008,385.3330000000009,385.1830000000008,384.97300000000075,383.97300000000075,382.4430000000008,381.60300000000086,381.3030000000009,380.5330000000009,379.713000000001,379.37300000000107,379.38300000000106,378.01300000000117,377.5930000000011,376.26300000000117,374.92300000000125,374.4530000000012,374.1130000000013,373.31300000000135,372.08300000000133,371.30300000000136,370.8430000000013,369.93300000000124,370.7430000000012,371.5730000000011,373.90300000000104,374.0730000000011,374.0630000000011,375.0730000000011,376.12300000000107,376.01300000000117,375.4730000000012,374.4830000000012,371.0930000000011,369.0630000000011,366.4630000000012,364.4930000000012,364.0830000000011,365.4830000000012,367.8530000000011,367.37300000000107,366.48300000000097,366.15300000000104,365.943000000001,365.7930000000009,365.1630000000008,364.2630000000007,362.8030000000007,362.46300000000076,362.46300000000076,362.4430000000008,362.1430000000008,360.5130000000007,362.2730000000007,362.95300000000077,363.0030000000007,363.10300000000063,363.3030000000007,365.7930000000007,367.49300000000073,366.63300000000083,362.0530000000009,361.4230000000008,361.3030000000009,361.223000000001,363.3330000000009,363.5830000000009,364.0630000000009,366.02300000000093,367.87300000000084,368.85300000000086,370.11300000000085,372.26300000000094,372.73300000000097,373.00300000000095,374.203000000001,376.3630000000011,375.90300000000104,375.77300000000093,375.66300000000103,371.8130000000011,370.52300000000116,368.37300000000107,368.37300000000107,366.173000000001,362.673000000001,360.453000000001,361.01300000000094,361.14300000000105,360.87300000000107,358.963000000001,357.203000000001,356.98300000000097,354.87300000000107,354.5030000000012,354.3830000000013,353.65300000000127,351.6230000000013,350.7230000000012,342.92300000000125,340.78300000000115,337.41300000000126,335.6430000000013,334.7430000000012,332.80300000000113,332.14300000000105,329.223000000001,327.6030000000011,327.05300000000113,324.673000000001,323.223000000001,322.713000000001,318.51300000000094,317.0530000000009,313.99300000000096,313.953000000001,312.0730000000009,310.1930000000008,304.61300000000085,303.4230000000008,301.3130000000009,300.8330000000009,299.62300000000084,297.01300000000083,295.9130000000008,294.00300000000084,291.76300000000083,290.6430000000008,289.45300000000077,289.37300000000073,289.48300000000074,289.7930000000007,288.5130000000007,287.6330000000007,286.45300000000077,286.0030000000007,285.1430000000007,285.1630000000007,285.1630000000007,285.3830000000007,285.8030000000007,286.21300000000065,286.72300000000064,287.48300000000063,286.96300000000065,286.83300000000065,286.47300000000064,286.44300000000067,286.2930000000007,285.9230000000007,285.07300000000066,279.69300000000067,278.56300000000067,279.9230000000007,281.11300000000074,282.73300000000074,283.0030000000007,283.0030000000007,282.9030000000007,282.9130000000007,282.71300000000065,282.0330000000007,279.5530000000007,277.45300000000066,276.0430000000007,275.49300000000073,275.1430000000007,273.45300000000066,273.0510000000006,273.1950000000006,274.1590000000007,272.7880000000007,270.00100000000066,265.88100000000065,263.0890000000006,256.85300000000063,256.05900000000065,255.55300000000068,252.17000000000064,250.9220000000006,249.1910000000006,249.2920000000006,252.62000000000057,257.58800000000053,259.7200000000005,260.0130000000005,265.21800000000053,264.5380000000006,264.3600000000006,264.0990000000006,264.15000000000066,264.18800000000067,265.1000000000007,266.4130000000007,266.9080000000007,267.9900000000007,268.65600000000074,269.0050000000008,270.20900000000074,271.1930000000008,272.9650000000008,274.0780000000009,275.26300000000083,274.25800000000083,272.98400000000083,272.12700000000086,271.6600000000009,268.8890000000009,264.57500000000095,263.025000000001,260.228000000001,259.011000000001,258.713000000001,258.457000000001,258.63300000000106,258.63300000000106,259.2660000000011,259.8810000000011,262.9630000000011,263.2890000000011,263.86400000000117,262.9600000000012,262.7100000000012,262.4050000000012,261.25000000000125,260.0070000000012,258.41900000000123,252.98700000000122,251.58700000000124,247.8680000000012,247.6030000000012,243.2040000000012,242.70600000000115,235.22900000000118,231.90900000000113,230.71100000000115,226.0350000000011,224.35100000000114,222.66800000000114,221.2280000000011,221.07300000000112,220.47100000000114,220.68100000000118,221.49000000000115,219.0310000000012,218.3150000000012,216.02400000000114,214.59700000000112,209.7470000000011,205.4390000000011,204.69300000000112,204.4050000000011,205.91400000000112,206.24900000000116,211.22000000000116,212.73100000000113,213.05300000000113,213.29200000000117,212.9880000000012,211.56600000000117,211.09100000000115,209.8530000000011,210.74900000000105,209.80700000000104,207.03300000000104,205.857000000001,205.857000000001,204.92200000000105,201.222000000001,196.93600000000106,196.66600000000108,191.8480000000011,191.8480000000011,190.71100000000115,185.82100000000116,184.28500000000122,184.15900000000124,183.66000000000122,183.57700000000125,182.90800000000127,179.22100000000125,176.8730000000013,175.91500000000133,175.52100000000132,174.9740000000013,170.2090000000013,164.6660000000013,164.05300000000125,160.6130000000012,153.55400000000122,152.20000000000118,150.15200000000118,148.79300000000114,146.77000000000112,144.9530000000011,144.85100000000114,144.7760000000011,143.91100000000108,135.79900000000112,133.9150000000011,133.7130000000011,133.41700000000105,133.19200000000103,133.400000000001,133.79300000000103,134.366000000001,136.42500000000098,137.554000000001,138.79100000000096,137.81100000000094,136.650000000001,134.58500000000095,132.88700000000097,131.63900000000092,131.12400000000093,128.26300000000094,127.93200000000093,127.96300000000087,127.89100000000087,129.10400000000084,129.84500000000082,130.97200000000078,131.15700000000072,131.09200000000067,131.25100000000066,131.3940000000007,131.47800000000063,132.11200000000065,132.19300000000067,134.34800000000064,135.75900000000058,138.53400000000056,139.27000000000055,140.77900000000056,142.02200000000062,143.1140000000006,143.14500000000055,143.24100000000055,146.30800000000056,147.21100000000058,147.72800000000063,149.7010000000006,150.53600000000063,152.56300000000067,153.77600000000064,154.1910000000006,154.09400000000062,153.67500000000064,155.8350000000006,156.48100000000056,156.33800000000053,156.00000000000057,155.78800000000058,154.71300000000053,153.12000000000057,153.15900000000056,154.8390000000005,155.35500000000047,155.8200000000005,157.13600000000054,158.3630000000005,160.49700000000053,161.8870000000005,162.4500000000005,161.35300000000052,158.70600000000047,158.55400000000043,158.0310000000004,157.90200000000038,157.50800000000038,156.5450000000004,154.10000000000036,152.01800000000037,150.35000000000036,145.21200000000033,143.24000000000035,142.15000000000032,143.3810000000003,146.03600000000029,145.49300000000028,143.70300000000032,141.94300000000032,143.74100000000033,143.79200000000037,143.85100000000034,144.1850000000003,145.77800000000025,146.70100000000025,147.8140000000003,149.62500000000034,151.59200000000033,154.23100000000034,154.49600000000032,153.86100000000033,153.16200000000038,153.2330000000004,153.6270000000004,154.00900000000036,156.1220000000004,158.26100000000042,158.68800000000044,159.11000000000047,159.3720000000004,160.01400000000046,161.00600000000043,161.11100000000044,161.0120000000004,160.59300000000042,159.48400000000038,157.01400000000035,155.75400000000036,155.06800000000032,153.55700000000036,154.09600000000034,156.81200000000035,157.27900000000034,159.23100000000034,162.6840000000003,163.9590000000003,164.85900000000026,166.86500000000024,169.23000000000025,169.9770000000002,175.46000000000015,176.6840000000002,179.36100000000022,180.15300000000025,177.5450000000003,171.3340000000003,164.84500000000025,157.22900000000027,150.45100000000025,144.24300000000028,140.57200000000023,138.03200000000027,138.87900000000025,140.57200000000023,140.57200000000023,138.59900000000027,136.34000000000026,132.67600000000027,128.1600000000003,125.33500000000026,124.7710000000003,127.02700000000027,129.00800000000027,127.58900000000028,122.79600000000028,118.84200000000033,116.5880000000003,121.09700000000032,121.09700000000032,118.56200000000035,115.45800000000031,114.0450000000003,110.0930000000003,105.57800000000032,98.80400000000031,90.05600000000027,83.28200000000027,75.38300000000027,69.45300000000032,70.29900000000032,68.89000000000033,65.78200000000038,64.37400000000036,66.06800000000032,75.38300000000038,75.38300000000038,74.25100000000043,74.5360000000004,72.84300000000042,73.12400000000036,73.12400000000036,68.0410000000004,65.78200000000038,64.93600000000038,62.9640000000004,57.60100000000034,52.80700000000036,47.72200000000032,48.290000000000305,48.57000000000028,46.595000000000255,48.00300000000027,54.779000000000224,59.57400000000018,61.83500000000015,64.65800000000013,64.65800000000013,62.67900000000009,64.01100000000008,64.00900000000013,61.445000000000164,58.59300000000019,58.334000000000174,57.63700000000017,55.737000000000194,54.14300000000014,53.39800000000014,50.54000000000019,46.76900000000023,46.438000000000216,45.14100000000019,44.62400000000014,46.73400000000015,47.31900000000019,50.50500000000022,51.0300000000002,51.33700000000022,51.02400000000023,50.349000000000274,49.01800000000026,46.45900000000029,44.07600000000025,42.68700000000024,35.61800000000028,33.202000000000226,32.51400000000024,29.453000000000202,28.095000000000255,28.89500000000021,29.487000000000194,29.449000000000183,28.1550000000002,23.424000000000206,22.76600000000019,21.23400000000015,19.612000000000194,19.20400000000018,17.247000000000185,14.695000000000164,14.947000000000116,15.549000000000092,16.828000000000088,14.256000000000085,12.745000000000118,10.639000000000124,7.805000000000177,5.921000000000163,7.176000000000158,8.268000000000143,7.9340000000001965,5.606000000000222,4.5870000000002165,6.383000000000266,7.11400000000026,8.779000000000224,9.713000000000193,11.883000000000152,12.35300000000018,13.79700000000014,13.664000000000101,12.217000000000098,13.601000000000113,16.219000000000165,16.977000000000203,17.91900000000021,18.352000000000203,18.54000000000019,18.007000000000176,17.935000000000173,17.01200000000017,14.947000000000116,12.75500000000011,11.291000000000054,9.21300000000008,10.079000000000065,11.946000000000026,13.452999999999975,13.259000000000015,13.884000000000015,14.20799999999997,12.727999999999952,12.317999999999984,8.947999999999979,8.20799999999997,6.8940000000000055,4.671000000000049,4.254000000000019,3.3220000000000027,2.0810000000000173,0.42200000000002547,0.0,0.3990000000000009,0.3170000000000073,0.6789999999999736,1.891999999999939,2.74899999999991,5.378999999999905,6.760999999999854,6.945999999999799,7.093999999999824,6.736999999999853,6.416999999999803,9.058999999999855,9.614999999999895,9.712999999999852,9.923999999999864,10.031999999999812,9.782999999999788,9.276999999999816,8.284999999999854,7.410999999999831,6.251999999999839,5.763999999999783,4.951999999999771,3.6209999999997535,5.334999999999809,6.0899999999998045,6.514999999999759,6.35899999999981,6.371999999999844,8.066999999999894,8.61999999999989,10.017999999999915,10.825999999999908,11.236999999999853,12.013999999999896,12.579999999999927,12.843999999999937,14.718999999999937,16.284999999999968,17.365999999999985,17.552999999999997,17.653999999999996,18.270999999999958,17.310999999999922,15.557999999999879,13.96699999999987,14.78599999999983,15.225999999999885,15.579999999999927,17.195999999999913,18.81799999999987,19.603999999999814,22.490999999999758,23.462999999999738,23.622999999999706,23.08599999999967,23.535999999999717,23.52799999999968,23.86799999999971,23.868999999999687,24.832999999999743,24.852999999999724,25.26399999999967,25.119999999999663,25.03799999999967,23.250999999999635,22.70999999999958,21.132999999999583,18.239999999999554,15.710999999999558,13.96699999999953,12.612999999999488,12.797999999999433,11.690999999999462,10.453999999999496,10.034999999999513,9.274999999999523,8.681999999999562,9.848999999999592,11.626999999999612,12.423999999999637,13.948999999999614,17.135999999999626,18.204999999999586,21.05499999999961,21.577999999999633,22.802999999999656,22.927999999999656,22.9789999999997,27.404999999999745,29.29199999999969,29.247999999999706,28.892999999999688,28.153999999999655,27.155999999999608,24.676999999999566,24.545999999999594,23.479999999999563,20.731999999999516,20.300999999999476,19.83399999999949,19.390999999999508,20.49399999999946,20.630999999999403,23.73599999999942,27.404999999999404,30.78899999999942,32.20099999999945,32.20099999999945,33.327999999999406,37.2849999999994,39.53699999999935,39.2559999999994,41.80199999999945,44.61699999999951,46.8769999999995,46.31399999999951,51.10999999999956,55.343999999999596,56.753999999999564,59.29499999999962,61.83499999999958,68.0409999999996,71.14799999999957,72.67299999999955,72.80799999999954,73.90399999999954,74.41399999999953,77.18399999999951,77.50899999999956,79.14999999999952,80.84399999999948,80.88099999999952,82.30099999999948,83.7519999999995,85.72599999999954,86.73599999999954,87.0069999999995,87.35999999999945,90.76299999999947,91.9439999999995,92.78299999999956,93.04199999999958,93.72699999999952,94.75799999999947,96.96299999999951,97.73599999999954,97.76999999999953,98.0499999999995,99.6509999999995,100.09199999999953,102.03199999999958,104.07299999999964,105.1129999999996,106.5169999999996,109.58499999999958,111.61399999999958,112.1179999999996,116.02299999999957,118.92199999999957,118.6179999999996,114.46199999999965,113.81199999999967,111.86099999999965,107.5319999999997,105.40599999999972,104.66699999999969,100.87199999999973,96.92099999999971,94.65499999999975,93.4069999999997,93.27799999999968,92.93199999999968,92.40799999999967,92.29299999999967,89.60299999999961,87.87299999999959,86.57299999999964,85.04299999999967,84.08899999999971,82.82299999999975,84.93799999999976,85.43099999999981,84.72599999999977,83.04299999999978,81.99499999999978,81.63699999999983,81.2439999999998,80.60499999999979,80.32899999999984,79.78099999999984,81.65499999999986,83.26499999999987,83.40699999999993,85.64999999999998,87.86799999999994,88.77199999999993,88.03199999999993,87.12099999999998,87.24799999999993,89.85299999999995,91.77699999999993,95.3839999999999,99.93299999999988,100.49399999999991,102.00499999999988,104.13999999999987,113.45299999999986,121.03599999999983,122.37999999999988,128.14999999999986,132.52599999999984,133.30399999999986,133.12999999999988,134.6729999999999,135.9459999999999,138.4079999999999,138.4079999999999,139.16499999999985,141.88499999999988,142.43299999999988,142.88699999999983,140.88599999999985,138.8019999999999,136.68499999999995,135.94799999999998,133.82799999999997,131.55999999999995,131.10699999999997,132.10799999999995,134.1199999999999,134.25199999999984,135.92599999999982,139.01899999999978,140.13099999999974,140.9549999999997,142.4929999999997,144.5949999999997,148.14399999999966,146.4939999999997,144.3689999999997,144.58399999999972,147.56699999999967,148.65999999999963,148.78999999999962,149.98599999999965,151.5839999999996,152.8149999999996,151.96199999999965,152.87199999999962,154.78799999999967,155.17799999999966,157.0409999999997,159.6039999999997,164.9159999999997,166.37199999999973,174.10099999999977,176.84599999999978,183.6189999999998,189.29399999999976,190.1579999999998,194.89599999999984,195.50599999999986,197.5809999999999,198.0039999999999,198.5519999999999,200.4999999999999,203.1529999999999,204.70399999999995,205.16999999999996,205.25799999999992,205.13799999999992,205.12799999999993,205.1239999999999,206.50199999999995,207.32499999999993,208.3599999999999,208.4269999999999,208.71499999999992,210.6389999999999,211.2539999999999,212.2489999999999,215.5329999999999,216.1729999999999,216.63499999999988,218.21499999999992,222.16599999999994,222.7689999999999,224.03599999999994,223.85799999999995,222.5999999999999,224.00099999999986,226.28599999999983,229.9119999999998,230.2009999999998,230.7439999999998,230.99099999999976,230.65099999999973,229.58699999999976,228.70899999999972,230.44699999999978,231.37599999999975,232.02899999999977,239.2059999999998,243.20399999999984,245.25999999999988,245.92799999999988,246.41199999999992,245.3309999999999,244.59899999999993,244.8789999999999,246.25999999999988,248.02199999999982,252.48599999999988,253.54999999999984,255.3309999999998,258.12199999999984,260.90999999999985,263.14599999999984,266.2549999999999,267.11799999999994,268.24699999999996,267.6859999999999,266.6399999999999,269.2389999999999,270.0279999999999,270.67999999999995,273.049,273.119,277.043,277.793,285.443,286.903,286.803,287.84299999999996,288.2729999999999,289.71299999999997,291.8929999999999,292.1629999999999,295.0329999999999,295.4129999999999,298.4329999999999,299.37299999999993,299.37299999999993,298.23299999999995,298.24299999999994,300.313,302.023,303.87299999999993,307.273,307.87299999999993,308.25300000000004,312.793,313.3829999999999,314.01300000000003,316.073,318.6629999999999,322.2529999999998,330.6229999999997,330.94299999999964,333.7429999999996,336.5929999999995,338.6929999999994,340.7929999999993,340.88299999999924,342.7929999999993,341.87299999999925,341.5529999999993,340.9229999999992,342.5729999999993,343.9529999999994,343.38299999999947,343.29299999999955,344.3329999999995,347.4429999999994,351.8029999999993,353.85299999999927,354.4329999999992,357.64299999999923,358.38299999999924,360.10299999999927,362.6929999999992,363.5929999999993,367.00299999999936,367.62299999999925,369.73299999999915,371.46299999999917,372.1929999999992,374.5229999999991,375.0629999999991,374.5329999999991,374.00299999999913,373.47299999999916,377.09299999999905,379.662999999999,383.09299999999905,386.8029999999991,387.35299999999904,389.2929999999991,390.0329999999991,390.11299999999903,389.69299999999896,389.4929999999989,390.06299999999885,390.58299999999883,391.83299999999883,391.0029999999989,386.58299999999883,384.55299999999886,382.1229999999988,381.56299999999885,381.45299999999895,381.7629999999989,382.8629999999988,383.9729999999987,385.05299999999863,383.37299999999857,380.4229999999985,377.5429999999984,374.48299999999847,372.90299999999854,371.15299999999854,371.52299999999843,373.34299999999837,376.02299999999843,377.0629999999984,377.87299999999834,379.11299999999835,379.84299999999837,380.49299999999846,382.2229999999985,387.7829999999984,393.1829999999985,395.6129999999986,406.6029999999986,406.90299999999854,407.16299999999853,408.27299999999843,408.35299999999836,408.27299999999843,407.1829999999985,407.1929999999985,408.5429999999984,410.0729999999984,410.63299999999833,410.6729999999983,412.6529999999983,415.46299999999826,417.82299999999816,418.82299999999816,421.46299999999826,422.4129999999983,423.72299999999825,424.5529999999982,425.5229999999982,427.20299999999827,427.8029999999982,427.96299999999826,427.32299999999816,426.94299999999805,427.19299999999805,426.8629999999981,426.2729999999982,424.81299999999817,422.3829999999981,421.18299999999806,420.20299999999804,418.8729999999981,418.4129999999981,415.59299999999814,410.3029999999982,409.73299999999824,407.88299999999833,407.71299999999826,407.48299999999824,402.72299999999825,402.95299999999827,403.1729999999983,396.97299999999825,391.47299999999825,389.95299999999827,385.9329999999983,384.6829999999983,383.88299999999833,380.4329999999983,380.1729999999983,373.4429999999983,372.09299999999837,371.5829999999984,368.50299999999845,367.0529999999984,360.4229999999983,360.0829999999984,359.5529999999984,359.4729999999985,356.7829999999984,354.2929999999984,352.9329999999985,352.13299999999856,351.01299999999867,346.92299999999875,346.6229999999988,349.5129999999989,351.9929999999989,349.132999999999,348.86299999999903,349.00299999999913,349.10299999999904,351.412999999999,352.7529999999989,350.81299999999885,348.83299999999883,349.1029999999988,349.5929999999988,346.1329999999988,343.18299999999874,341.9729999999987,339.44299999999873,337.1329999999988,334.4629999999987,333.5029999999987,333.0729999999986,333.5829999999986,334.30299999999863,332.3129999999986,330.51299999999867,328.77299999999866,327.87299999999857,328.5929999999986,329.65299999999854,328.9729999999985,328.88299999999856,330.79299999999864,332.4829999999987,335.8729999999988,335.8729999999988,337.0029999999989,339.82299999999884,342.3629999999988,343.7729999999989,346.8829999999988,348.8529999999988,357.6029999999988,360.9929999999989,368.6029999999988,370.8729999999988,374.81299999999885,375.1029999999988,378.2029999999987,382.15299999999877,385.26299999999867,387.52299999999866,390.62299999999857,392.03299999999865,393.44299999999873,394.57299999999884,397.67299999999875,399.94299999999873,401.0629999999986,401.62299999999857,405.8629999999986,410.0929999999986,413.76299999999867,417.7129999999987,419.9729999999987,423.3629999999988,429.56299999999885,436.06299999999885,437.47299999999893,442.2729999999989,443.68299999999897,440.0129999999989,437.7529999999989,437.7529999999989,440.29299999999887,443.68299999999897,446.5029999999989,449.892999999999,454.402999999999,454.122999999999,456.10299999999904,457.50299999999913,458.9229999999992,464.00299999999913,467.6629999999992,469.63299999999924,471.9029999999992,475.00299999999913,475.57299999999907,473.30300000000136],\"y\":[347.53499999999997,347.53499999999997,356.009,361.087,363.063,365.66599999999994,365.93899999999996,366.726,368.823,373.466,375.36199999999997,378.76,382.26,382.44100000000003,385.654,387.432,390.75800000000004,398.17100000000005,399.50300000000004,402.2460000000001,403.0450000000001,410.2500000000001,415.12900000000013,417.55700000000013,418.03700000000015,418.03700000000015,418.6300000000001,418.6490000000001,418.80100000000016,419.6650000000002,422.36900000000014,424.50300000000016,424.62900000000013,425.88300000000015,427.8910000000002,431.19000000000017,433.6350000000002,435.5580000000002,438.5390000000002,439.64700000000016,443.6610000000002,444.3220000000001,447.9950000000001,449.1010000000001,453.7070000000001,455.00400000000013,458.0050000000001,460.1890000000001,463.16200000000003,464.4290000000001,465.93500000000006,469.1,469.42500000000007,469.3990000000001,469.3910000000001,470.0970000000001,470.7400000000001,472.74300000000017,476.0400000000002,479.87000000000023,484.5460000000003,485.1850000000003,490.95100000000025,498.41300000000024,502.0410000000003,506.1120000000003,507.9110000000003,511.27300000000025,512.0300000000002,512.0300000000002,519.3170000000002,522.1070000000002,525.4030000000002,526.7400000000002,531.6970000000001,538.5270000000002,539.6860000000001,539.7490000000001,539.8070000000001,544.0770000000001,546.8220000000001,547.1840000000002,547.1840000000002,547.1810000000002,547.2470000000001,546.1330000000002,545.8870000000002,544.9040000000002,544.7770000000002,545.3050000000002,545.7120000000002,546.9910000000002,548.1720000000001,549.2690000000001,550.7130000000002,550.7970000000001,551.1690000000001,551.1640000000002,551.1610000000002,552.2350000000001,553.4290000000002,554.1280000000002,554.1980000000002,554.2730000000001,554.3330000000002,554.3190000000002,554.3050000000002,555.1180000000002,560.1500000000001,560.4220000000001,560.6250000000001,565.2320000000002,566.7620000000002,569.4910000000001,570.259,572.4290000000001,572.671,574.6460000000002,577.469,579.806,579.7440000000001,576.2710000000001,576.8320000000001,577.655,576.224,574.702,574.1370000000001,571.7930000000001,573.066,577.3300000000002,578.6950000000002,578.6400000000001,578.5910000000001,578.613,581.0520000000001,581.9050000000002,581.9390000000001,581.5600000000002,580.6550000000002,580.8870000000002,583.9280000000001,585.4920000000002,586.0660000000003,586.8200000000002,586.8400000000001,586.9670000000002,587.2740000000002,587.4030000000002,587.4990000000003,588.2970000000003,589.6400000000003,590.2850000000003,590.6800000000003,590.2190000000003,589.2930000000002,589.0040000000002,588.9930000000002,590.0540000000002,591.6910000000003,591.7590000000002,591.6070000000002,590.7280000000002,590.6570000000002,591.7050000000002,590.5920000000001,587.2840000000001,586.9840000000002,586.8310000000001,586.0160000000001,587.0250000000001,590.7650000000001,590.7700000000002,591.9580000000001,595.6720000000001,596.2700000000002,597.6280000000002,597.7630000000001,597.6660000000002,597.5420000000001,598.0450000000001,598.3130000000001,598.3910000000001,599.0870000000001,599.2210000000001,599.3010000000002,599.4230000000001,599.7130000000002,599.1100000000001,598.6460000000002,598.5810000000001,599.0090000000001,599.5830000000001,601.8710000000001,601.9520000000002,604.0580000000002,604.1610000000002,605.8840000000002,607.5920000000002,607.5100000000002,607.4470000000002,609.1620000000003,610.9270000000001,610.7870000000003,610.6710000000003,610.3330000000002,611.0760000000002,611.7740000000001,614.1590000000001,614.3690000000001,614.6380000000001,616.8810000000001,620.1090000000002,620.6430000000001,620.7100000000002,620.7610000000002,620.0740000000001,619.2490000000001,618.0240000000001,614.8000000000002,613.3700000000001,613.8800000000001,614.7450000000001,612.3940000000001,610.3170000000001,609.4520000000001,609.2180000000001,609.1450000000002,609.3580000000002,609.6320000000002,608.0240000000001,605.1500000000001,605.0390000000002,604.5970000000002,603.2730000000001,599.9110000000001,597.6960000000001,597.6030000000001,597.815,597.7830000000001,597.6050000000001,596.6180000000002,594.488,593.8960000000002,593.6140000000001,593.6140000000001,592.9230000000002,591.3050000000002,588.3820000000002,588.2450000000001,587.9730000000002,586.4880000000002,584.7910000000002,584.0700000000002,583.5800000000002,585.2470000000001,585.9000000000001,586.2120000000002,586.0360000000002,586.6990000000002,586.1650000000002,586.0070000000002,585.8690000000001,583.4310000000003,583.1130000000003,583.4490000000003,583.6090000000003,583.9800000000002,586.1120000000003,590.0920000000003,593.2140000000003,593.6190000000003,593.9460000000003,595.1650000000002,596.3190000000002,597.9650000000003,598.7700000000002,598.7720000000003,598.6150000000002,598.9370000000004,599.3180000000002,599.2530000000003,598.6950000000003,598.5920000000003,598.4460000000003,598.6160000000002,599.7190000000003,601.3180000000002,601.1560000000003,596.7350000000004,593.5210000000003,592.7190000000003,587.4940000000003,585.6440000000002,585.2770000000003,581.9250000000002,580.7450000000002,576.1570000000002,576.0540000000002,575.2610000000002,575.1600000000002,573.6750000000002,572.5880000000002,571.1890000000002,571.2760000000002,572.0260000000002,573.1200000000001,572.9890000000003,572.7740000000002,571.5080000000003,570.2840000000002,568.7750000000002,568.5040000000001,568.2440000000001,566.0750000000003,567.2820000000002,567.5290000000002,566.9000000000002,566.4800000000002,564.0390000000002,563.4990000000003,563.1870000000001,562.9650000000001,562.5420000000001,562.1280000000002,562.4210000000003,562.8990000000002,562.1910000000003,561.9690000000003,561.4100000000002,561.4130000000002,561.4120000000003,561.4210000000003,561.4350000000002,559.4680000000003,555.9890000000003,555.1990000000003,555.4510000000002,556.1150000000002,556.2020000000002,556.1920000000002,554.4630000000002,553.7720000000003,551.5250000000003,551.7560000000003,553.1760000000003,554.3230000000003,554.8850000000002,555.1030000000003,554.6280000000003,553.2720000000003,553.6770000000002,556.4790000000003,557.4940000000003,557.7520000000002,558.8850000000002,560.6370000000002,559.8030000000002,555.4510000000002,555.1620000000003,555.9370000000002,557.9050000000002,558.2730000000003,560.5080000000003,562.2310000000002,564.4320000000002,567.5840000000003,569.5920000000003,569.7370000000003,574.1000000000003,579.1040000000003,579.7710000000002,585.8030000000002,586.7470000000003,587.3070000000002,587.0080000000003,587.6750000000002,589.8990000000002,591.9450000000002,592.2520000000002,591.9970000000003,591.2760000000003,591.1130000000003,590.3480000000002,589.8160000000003,590.7350000000002,593.7300000000002,595.8230000000003,597.5490000000002,598.5260000000003,601.2140000000002,602.8230000000002,603.3790000000001,601.2500000000002,598.7870000000001,597.7150000000001,595.1590000000001,594.2690000000002,593.6270000000002,593.5210000000002,593.4800000000002,594.5240000000001,594.7690000000002,593.8160000000003,591.3770000000002,591.0140000000001,590.2280000000002,590.2890000000002,590.3520000000001,590.2180000000001,588.0840000000001,586.4810000000001,583.7170000000001,583.729,586.3530000000001,586.9000000000001,589.9380000000001,591.5750000000002,592.3790000000001,594.0360000000001,593.3080000000001,592.3230000000001,591.6020000000001,591.8680000000002,593.4010000000001,593.5490000000002,594.6040000000002,597.2320000000002,597.5430000000001,598.2050000000002,597.8470000000001,596.5030000000002,594.5150000000001,594.6630000000001,594.9300000000001,596.0670000000001,596.1310000000001,598.9730000000002,605.5610000000001,608.7820000000002,610.2500000000002,612.1150000000002,612.7040000000002,612.7750000000002,613.0930000000002,615.3330000000002,620.6310000000002,623.4120000000003,624.1960000000001,622.7830000000001,620.7160000000001,622.1880000000001,624.2820000000002,624.3590000000002,626.6090000000002,629.4630000000002,628.7990000000002,625.6290000000001,623.8810000000001,623.7030000000002,625.9800000000001,626.6450000000002,626.6450000000002,624.6780000000001,623.1800000000002,623.7650000000001,625.5910000000001,627.5530000000001,629.4690000000002,630.2070000000001,630.5860000000002,631.7240000000002,631.7240000000002,631.5460000000002,631.2960000000002,631.7230000000002,632.7190000000002,632.1650000000002,632.0970000000002,632.0000000000002,630.6430000000003,630.8790000000001,631.5880000000002,632.8380000000002,635.6500000000002,639.0000000000002,639.0260000000003,638.9970000000003,638.9630000000002,640.1770000000002,641.3120000000002,643.1880000000002,644.3540000000003,645.0800000000002,646.0000000000002,644.9400000000003,641.2460000000002,639.4490000000002,631.6690000000002,625.3590000000002,623.9110000000003,622.4120000000003,618.6630000000002,618.5550000000002,619.0490000000002,622.6330000000003,622.9920000000002,626.6660000000002,626.9980000000002,627.1930000000002,628.6130000000002,628.3770000000002,626.2850000000002,626.5890000000002,627.8870000000002,628.3480000000002,628.7020000000002,628.6040000000002,628.5170000000002,628.5170000000002,627.0590000000002,621.9070000000002,621.2650000000001,619.7810000000002,614.9890000000003,612.8980000000001,610.4450000000002,609.3760000000002,608.8410000000001,607.7240000000002,605.5910000000001,604.4640000000002,604.5250000000001,604.3230000000001,602.1230000000002,600.6680000000001,599.8000000000002,597.8960000000002,594.5390000000002,593.7650000000001,593.8030000000001,593.8340000000002,593.6970000000001,593.5650000000002,595.1920000000002,598.8930000000003,597.6550000000002,595.2030000000002,592.3740000000003,592.1190000000001,591.3310000000001,591.3370000000002,591.3530000000002,591.3950000000002,591.4810000000002,591.3430000000002,591.2540000000001,590.0880000000002,588.6710000000003,587.8900000000002,587.3620000000002,586.5290000000002,586.1320000000002,585.4570000000001,584.5620000000001,580.1550000000002,580.1090000000002,580.0740000000002,579.8700000000001,578.5060000000002,577.7560000000002,578.4190000000002,579.7400000000002,580.0550000000003,579.7620000000002,577.1310000000003,574.9000000000003,573.7180000000003,569.5360000000003,568.6750000000002,567.3930000000003,565.9750000000003,566.8570000000002,567.1080000000002,566.2630000000001,565.6990000000002,564.5400000000002,562.4650000000001,559.9080000000001,559.8800000000001,559.9760000000001,560.4080000000001,561.0960000000002,560.7880000000002,560.5050000000001,559.3150000000002,557.6590000000001,553.3210000000001,552.1910000000001,548.8450000000001,547.0360000000001,547.2520000000002,547.373,547.1440000000001,546.8850000000001,546.931,546.1930000000001,545.6180000000002,542.9560000000001,540.3710000000001,542.8900000000001,545.1470000000002,543.7360000000001,542.3240000000002,543.4560000000001,546.8430000000002,541.1950000000002,532.7280000000002,525.1050000000002,520.5870000000002,516.0720000000002,519.4610000000002,520.0250000000003,521.9980000000003,525.3880000000003,522.2790000000002,517.4820000000002,516.3530000000003,514.0950000000003,508.7320000000002,507.88900000000024,511.8330000000002,515.7890000000002,516.3530000000003,521.1510000000003,526.7980000000002,529.3390000000002,533.0120000000002,533.8550000000002,533.5710000000003,532.1630000000002,529.9030000000002,531.0340000000002,529.3390000000002,523.6930000000002,520.0250000000002,518.0490000000002,515.7890000000002,509.01400000000024,502.5240000000002,502.23400000000026,499.9820000000003,494.8970000000003,491.2260000000002,488.4050000000002,482.7610000000002,473.1590000000002,463.8470000000002,455.65800000000024,448.0350000000002,444.65200000000016,445.7750000000002,446.9110000000002,445.2130000000002,440.97900000000016,439.0010000000002,436.7460000000002,431.9430000000002,429.4040000000002,429.1220000000002,430.53200000000015,424.89200000000017,420.08900000000017,413.8800000000002,412.61900000000026,412.6180000000003,411.5240000000002,409.1710000000003,408.57200000000023,408.31100000000026,407.7120000000002,404.9770000000002,403.4060000000002,402.7810000000002,399.82100000000014,399.8610000000001,399.0870000000001,397.4440000000001,395.1790000000001,394.7940000000001,392.24800000000005,391.61400000000003,391.231,390.552,389.46299999999997,387.121,384.81600000000003,386.904,386.648,383.35900000000004,382.135,382.44899999999996,384.264,383.351,381.35900000000004,380.466,380.33799999999997,381.1569999999999,383.34399999999994,383.29099999999994,383.14099999999996,383.72399999999993,384.72799999999995,386.972,385.92099999999994,384.3459999999999,383.59799999999984,381.88699999999983,382.8789999999998,383.91499999999974,382.3169999999998,381.0319999999998,379.56799999999976,376.8679999999997,375.33799999999974,375.0599999999997,373.36699999999973,371.8489999999997,372.20299999999975,372.25599999999974,371.9589999999997,369.27499999999975,365.7489999999998,365.5659999999998,364.9019999999998,364.78499999999985,362.8699999999999,360.5519999999999,356.7069999999999,354.9319999999999,352.71799999999985,351.23199999999986,346.7489999999999,342.8879999999999,340.99699999999996,339.842,337.827,334.456,332.19500000000005,327.274,325.996,325.47,325.75300000000004,325.61400000000003,324.9820000000001,324.3080000000001,323.9610000000001,323.80200000000013,321.05600000000015,320.1250000000001,319.33100000000013,316.1320000000002,315.30700000000013,316.4860000000001,318.12800000000016,317.37300000000016,314.60900000000015,312.81600000000014,311.5640000000002,309.0550000000002,308.57200000000023,308.6900000000003,309.0700000000003,309.26900000000023,309.3000000000002,309.2710000000002,308.43600000000015,305.99800000000016,304.7180000000002,304.6460000000002,303.2180000000002,301.52300000000014,300.10400000000016,300.01300000000015,299.9720000000001,300.05600000000004,300.1310000000001,299.74300000000005,298.4200000000001,296.0490000000001,294.9470000000001,292.9420000000001,292.6300000000001,292.45000000000016,291.56600000000014,288.5450000000002,287.51200000000017,287.4590000000002,287.69500000000016,287.8510000000001,287.5820000000001,285.9280000000001,284.32000000000016,282.7220000000002,280.49000000000024,280.18600000000026,280.32600000000025,280.3620000000002,280.10900000000015,278.9680000000002,278.0980000000002,277.0060000000002,274.8850000000002,271.1080000000002,270.57600000000014,269.9910000000001,268.9230000000001,269.16200000000015,269.25400000000013,266.7410000000001,265.3710000000001,263.4660000000001,258.2210000000001,257.64700000000016,257.6120000000002,257.32000000000016,257.3190000000002,256.4820000000002,256.5730000000002,256.19600000000025,255.97900000000027,255.8770000000003,254.2800000000003,254.46500000000026,254.95000000000027,252.41600000000028,250.70000000000027,249.90000000000032,244.7230000000003,244.34600000000034,243.67300000000034,241.7320000000003,239.94000000000028,238.04200000000026,232.5500000000003,229.88300000000027,226.4580000000003,225.74900000000036,222.9580000000003,217.5930000000003,216.68100000000027,215.19500000000028,215.2320000000003,215.36500000000035,215.36000000000035,214.57300000000032,211.55800000000033,210.88900000000035,209.7910000000004,206.9490000000004,204.50000000000045,203.96300000000042,200.84700000000043,199.65900000000045,197.04400000000044,192.70300000000043,191.41200000000038,190.04800000000034,188.18700000000035,188.9160000000004,188.31700000000035,184.0880000000003,182.67600000000027,179.56500000000028,176.4590000000003,174.76800000000026,171.37900000000025,166.29700000000025,163.1930000000002,160.93500000000017,158.39400000000012,156.9810000000001,160.09000000000015,162.62800000000016,162.90800000000013,160.6550000000001,156.13600000000008,155.8520000000001,155.8520000000001,154.15700000000004,154.72800000000007,156.34400000000005,155.341,156.591,157.18000000000006,157.79700000000003,157.75700000000006,157.3180000000001,156.57600000000014,155.1740000000001,151.55600000000004,150.389,149.22400000000005,149.788,149.962,149.68899999999996,146.36299999999994,146.79599999999994,147.4079999999999,147.26299999999992,146.9609999999999,146.75299999999993,147.64299999999992,148.12599999999986,148.14199999999983,147.78599999999983,146.39699999999982,146.21899999999982,145.69499999999982,146.5089999999998,147.06199999999978,146.22899999999981,144.48699999999985,143.39199999999983,143.00099999999986,141.26199999999983,139.69299999999987,139.3299999999998,133.53799999999978,131.2779999999998,127.22199999999975,124.42999999999972,120.90399999999977,119.5709999999998,115.79499999999985,107.85899999999981,101.95199999999977,98.3689999999998,96.48999999999978,92.35899999999981,87.56199999999978,87.4749999999998,83.48699999999974,79.89699999999971,77.73599999999976,74.42899999999975,72.46599999999978,65.63499999999976,60.69999999999982,59.8159999999998,57.016999999999825,52.72799999999984,48.374999999999886,45.90899999999988,45.32999999999993,40.108999999999924,38.347999999999956,37.344999999999914,30.792999999999893,27.55099999999993,26.60599999999988,25.09999999999991,26.422999999999888,27.437999999999874,26.27199999999982,24.919999999999845,23.05999999999983,21.759999999999877,22.189999999999827,24.12999999999988,26.36399999999992,24.999999999999886,22.719999999999914,22.569999999999936,24.899999999999977,28.23199999999997,27.67700000000002,24.200000000000045,24.690000000000055,24.82000000000005,25.600000000000023,28.411000000000058,28.684000000000083,27.583000000000084,26.936000000000035,26.936000000000035,29.554000000000087,30.828000000000088,32.62000000000012,34.30700000000013,34.871000000000095,33.60600000000011,32.85200000000009,32.287000000000035,33.259000000000015,35.68700000000001,37.15100000000007,40.40100000000007,41.05300000000011,41.53500000000008,42.585000000000036,43.03200000000004,41.694000000000074,40.02200000000005,42.18100000000004,39.992000000000075,38.72900000000004,36.68100000000004,35.00400000000002,33.88900000000001,34.004999999999995,34.02200000000005,33.4910000000001,32.86200000000008,33.68400000000008,36.55400000000009,36.08100000000013,32.92200000000014,31.235000000000127,30.44200000000012,31.282000000000153,33.0390000000001,32.88000000000011,30.117000000000075,29.12600000000009,25.980000000000132,18.19000000000017,18.130000000000223,20.000000000000227,20.190000000000282,19.000000000000227,18.52000000000021,18.86000000000024,20.08000000000027,19.560000000000286,20.210000000000264,21.85000000000025,21.84000000000026,22.800000000000296,22.86000000000024,22.890000000000214,26.236000000000217,26.469000000000165,26.06500000000017,25.350000000000136,22.40000000000009,21.520000000000095,21.57000000000005,21.760000000000105,22.22000000000014,22.1400000000001,21.12000000000012,18.40000000000009,16.690000000000055,16.760000000000105,14.46000000000015,13.260000000000105,10.190000000000055,8.120000000000005,7.560000000000059,9.660000000000082,9.950000000000045,9.629999999999995,8.090000000000032,6.360000000000014,3.4500000000000455,1.1300000000001091,0.0,0.14000000000010004,0.3200000000001637,4.820000000000164,9.46000000000015,12.0300000000002,13.470000000000255,18.400000000000205,19.890000000000214,22.11000000000024,23.36000000000024,22.43000000000029,22.270000000000323,24.340000000000373,25.0600000000004,24.500000000000455,23.270000000000437,22.000000000000455,21.240000000000464,22.230000000000473,22.46000000000049,21.88000000000045,20.96000000000049,19.090000000000487,18.170000000000528,18.18000000000052,18.18000000000052,15.080000000000496,14.760000000000446,11.660000000000423,11.690000000000396,13.750000000000341,14.260000000000332,13.390000000000327,12.050000000000296,11.830000000000268,11.320000000000277,13.130000000000223,13.500000000000227,15.950000000000273,15.930000000000291,15.380000000000337,15.150000000000318,19.90000000000032,18.530000000000314,18.570000000000277,21.280000000000314,21.22000000000037,21.140000000000327,22.020000000000323,24.1700000000003,25.820000000000277,27.994000000000256,28.065000000000282,28.098000000000297,27.95100000000025,27.77700000000027,28.806000000000267,31.756000000000313,31.734000000000265,31.3190000000003,30.894000000000347,30.67100000000039,30.894000000000347,30.91000000000031,31.82700000000034,34.58800000000031,35.09100000000035,39.01400000000035,40.891000000000304,42.35000000000025,39.60400000000027,38.17300000000023,37.660000000000196,38.55800000000022,39.46700000000021,38.87500000000023,37.781000000000176,34.02200000000016,33.75200000000018,33.316000000000145,34.81900000000019,35.92500000000018,38.22400000000016,38.29600000000016,38.479000000000156,37.882000000000176,36.63400000000013,34.04600000000016,33.76300000000015,33.239000000000146,32.737000000000194,30.81200000000024,27.26000000000022,25.200000000000273,22.720000000000255,21.870000000000232,21.810000000000286,23.11000000000024,24.04000000000019,26.86300000000017,27.971000000000117,29.32100000000014,32.28300000000013,32.871000000000095,38.53200000000004,40.08000000000004,44.537000000000035,43.84699999999998,42.535999999999945,43.7349999999999,44.049999999999955,46.07299999999998,48.03499999999997,49.918000000000006,56.61099999999999,59.71600000000001,63.40999999999997,67.02800000000002,70.02499999999998,70.70899999999995,72.52599999999995,74.73599999999999,76.298,78.67200000000003,81.34100000000001,82.58699999999999,82.75599999999997,82.73000000000002,82.70400000000006,83.44800000000009,88.2360000000001,89.6400000000001,90.19100000000014,98.38300000000015,101.72300000000018,104.26300000000015,107.90300000000013,108.15400000000011,108.40100000000007,112.66000000000008,113.01400000000012,113.72700000000009,115.30700000000013,116.07800000000009,116.11400000000003,114.77499999999998,113.99000000000001,113.18899999999996,112.16599999999994,110.32099999999991,110.64899999999989,112.71699999999987,114.49899999999991,115.46899999999994,118.4419999999999,120.75299999999993,125.18899999999996,126.09399999999994,128.38699999999994,130.082,133.88800000000003,135.11200000000008,137.67500000000007,141.70100000000002,142.53499999999997,142.37299999999993,142.1679999999999,142.20499999999993,145.14199999999994,148.67599999999993,148.76099999999997,147.05200000000002,146.65200000000004,146.82600000000002,149.42399999999998,150.41499999999996,153.596,159.98199999999997,160.27999999999997,162.49400000000003,166.94500000000005,168.66100000000006,170.14100000000008,174.17100000000005,174.4380000000001,178.21100000000013,178.04500000000007,177.9140000000001,177.32200000000012,178.42600000000016,183.9960000000002,184.12500000000023,187.8670000000002,189.85800000000017,192.59500000000014,199.18100000000015,200.1690000000002,200.8760000000002,205.4290000000002,207.40600000000018,209.87000000000023,212.21900000000028,213.63400000000024,213.63400000000024,213.76400000000024,214.87200000000018,215.14600000000019,219.4530000000002,222.8280000000002,224.59600000000023,225.76000000000022,226.17800000000022,228.0490000000002,230.28200000000015,231.73900000000015,232.6780000000001,234.1550000000001,236.0440000000001,238.6350000000001,239.1740000000001,240.26900000000012,242.27100000000007,245.59300000000007,247.22300000000007,247.96600000000012,248.88600000000008,249.86200000000008,250.87900000000013,252.1060000000001,255.47500000000014,255.65700000000015,256.3530000000002,252.9680000000002,251.55500000000018,249.29600000000016,247.88800000000015,246.75400000000013,253.81500000000017,257.1980000000002,259.4580000000002,262.5680000000002,264.82100000000025,266.51800000000026,266.79800000000023,264.82100000000025,267.9300000000003,272.7270000000003,273.29200000000037,273.8570000000004,276.6800000000004,281.2000000000004,280.3490000000004,284.0210000000004,287.1230000000004,284.29900000000043,283.17400000000043,285.4350000000004,289.10100000000045,292.2060000000005,292.7730000000005,293.05300000000045,294.4630000000004,294.4630000000004,296.4410000000004,301.2380000000004,302.36600000000044,306.32200000000046,308.5800000000005,310.27500000000055,313.6580000000006,316.2000000000006,317.89500000000066,320.7190000000006,322.4110000000006,321.0030000000006,321.28500000000065,321.84800000000064,318.74100000000067,314.79000000000065,313.0960000000007,310.27500000000066,307.44900000000064,305.4760000000007,307.7310000000007,313.94500000000073,321.28500000000076,334.2680000000007,340.1960000000007,347.53499999999997]},\"selected\":{\"id\":\"3408\"},\"selection_policy\":{\"id\":\"3407\"}},\"id\":\"3275\",\"type\":\"ColumnDataSource\"}],\"root_ids\":[\"3255\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n", - " const render_items = [{\"docid\":\"6fc7af1d-9af6-47ac-a22f-005fa4aa52d5\",\"root_ids\":[\"3255\"],\"roots\":{\"3255\":\"5f9e8ed1-fd26-4727-a288-1c51a1cc95ad\"}}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"6fc7af1d-9af6-47ac-a22f-005fa4aa52d5\":{\"defs\":[],\"roots\":{\"references\":[{\"attributes\":{\"height\":648,\"outline_line_color\":null,\"renderers\":[{\"id\":\"3273\"},{\"id\":\"3279\"}],\"title\":{\"id\":\"3256\"},\"toolbar\":{\"id\":\"3267\"},\"toolbar_location\":null,\"width\":478,\"x_range\":{\"id\":\"3258\"},\"x_scale\":{\"id\":\"3262\"},\"y_range\":{\"id\":\"3260\"},\"y_scale\":{\"id\":\"3264\"}},\"id\":\"3255\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"line_alpha\":0.1,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"3277\",\"type\":\"Line\"},{\"attributes\":{\"tools\":[{\"id\":\"3266\"}]},\"id\":\"3267\",\"type\":\"Toolbar\"},{\"attributes\":{\"data\":{\"name\":[\"AWI\",\"CISPA\",\"DESY\",\"DKFZ\",\"DLR\",\"DZNE\",\"FZJ\",\"GEOMAR\",\"GFZ\",\"GSI\",\"HGF\",\"HZB\",\"HZDR\",\"HZI\",\"HelmholtzMunich\",\"Hereon\",\"KIT\",\"MDC\",\"UFZ\"],\"x\":[147,50,205,152,92,97,35,205,345,151,350,375,405,240,300,257,131,374,329],\"y\":[527,181,530,187,286,262,288,590,408,227,444,428,322,403,92,505,138,455,336]},\"selected\":{\"id\":\"3406\"},\"selection_policy\":{\"id\":\"3405\"}},\"id\":\"3254\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"3405\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"3406\",\"type\":\"Selection\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.2},\"fill_color\":{\"value\":\"white\"},\"hatch_alpha\":{\"value\":0.2},\"line_alpha\":{\"value\":0.2},\"line_width\":{\"value\":2},\"size\":{\"value\":12},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"3272\",\"type\":\"Scatter\"},{\"attributes\":{\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"3276\",\"type\":\"Line\"},{\"attributes\":{\"source\":{\"id\":\"3275\"}},\"id\":\"3280\",\"type\":\"CDSView\"},{\"attributes\":{\"line_alpha\":0.2,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"3278\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"3262\",\"type\":\"LinearScale\"},{\"attributes\":{\"source\":{\"id\":\"3254\"}},\"id\":\"3274\",\"type\":\"CDSView\"},{\"attributes\":{\"end\":646.0000000000002},\"id\":\"3260\",\"type\":\"Range1d\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.8},\"fill_color\":{\"value\":\"white\"},\"line_width\":{\"value\":2},\"size\":{\"value\":12},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"3270\",\"type\":\"Scatter\"},{\"attributes\":{},\"id\":\"3407\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"3275\"},\"glyph\":{\"id\":\"3276\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"3278\"},\"nonselection_glyph\":{\"id\":\"3277\"},\"view\":{\"id\":\"3280\"}},\"id\":\"3279\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"3264\",\"type\":\"LinearScale\"},{\"attributes\":{\"coordinates\":null,\"group\":null,\"text\":\"HGF centers\"},\"id\":\"3256\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"3408\",\"type\":\"Selection\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"white\"},\"hatch_alpha\":{\"value\":0.1},\"line_alpha\":{\"value\":0.1},\"line_width\":{\"value\":2},\"size\":{\"value\":12},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"3271\",\"type\":\"Scatter\"},{\"attributes\":{\"callback\":null},\"id\":\"3266\",\"type\":\"HoverTool\"},{\"attributes\":{\"coordinates\":null,\"data_source\":{\"id\":\"3254\"},\"glyph\":{\"id\":\"3270\"},\"group\":null,\"hover_glyph\":null,\"muted_glyph\":{\"id\":\"3272\"},\"nonselection_glyph\":{\"id\":\"3271\"},\"view\":{\"id\":\"3274\"}},\"id\":\"3273\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"end\":475.57299999999907},\"id\":\"3258\",\"type\":\"Range1d\"},{\"attributes\":{\"data\":{\"x\":[473.30300000000136,473.30300000000136,471.05300000000136,468.2330000000014,461.45300000000145,457.8830000000015,458.69300000000146,457.80300000000136,459.81300000000135,459.92300000000125,459.4630000000012,456.8430000000013,454.3430000000013,454.29300000000137,452.2730000000014,450.83300000000133,451.83300000000133,455.43300000000124,455.19300000000123,455.3630000000013,455.79300000000137,456.2630000000014,453.33300000000133,454.18300000000124,453.3730000000013,453.3530000000013,452.58300000000133,452.58300000000133,452.7730000000014,453.6230000000013,453.57300000000134,451.1430000000013,450.3430000000013,446.40300000000127,445.7130000000012,444.7130000000012,443.5730000000011,443.2330000000012,445.27300000000116,446.2330000000012,446.8930000000013,446.66300000000126,447.2330000000012,447.80300000000113,444.15300000000104,441.40300000000104,436.443000000001,435.48300000000097,432.88300000000106,430.5830000000011,428.2130000000012,424.53300000000115,424.28300000000115,423.87300000000107,423.53300000000115,420.8130000000011,420.7130000000012,421.3830000000013,421.4930000000012,421.52300000000116,427.3430000000011,427.8630000000011,431.173000000001,430.5930000000011,431.8430000000011,433.5830000000011,432.5830000000011,431.173000000001,431.173000000001,431.0830000000011,428.78300000000115,427.76300000000117,426.5930000000011,425.963000000001,424.66300000000103,423.3630000000011,422.963000000001,422.953000000001,422.923000000001,421.713000000001,420.73300000000097,420.51300000000094,420.0330000000009,420.02300000000093,419.34300000000087,417.223000000001,417.0630000000009,415.59300000000087,414.2830000000009,411.3230000000009,409.963000000001,406.933000000001,404.963000000001,403.0930000000011,402.2230000000012,402.3230000000011,403.88300000000106,404.443000000001,404.8630000000011,407.52300000000116,408.37300000000107,409.3130000000011,411.423000000001,413.953000000001,416.223000000001,417.703000000001,418.51300000000094,418.473000000001,418.193000000001,418.173000000001,417.99300000000096,413.37300000000107,411.80300000000113,408.8230000000011,407.76300000000117,403.19300000000123,401.77300000000116,399.15300000000127,397.6030000000013,395.55300000000136,395.18300000000147,393.36300000000153,392.1730000000015,389.84300000000155,386.75300000000163,381.59300000000155,380.45300000000145,380.82300000000134,379.30300000000136,376.9930000000014,375.3730000000015,374.5530000000016,373.8830000000015,373.6430000000015,372.22300000000143,371.82300000000134,371.80300000000136,372.44300000000146,374.7330000000014,375.72300000000143,378.06300000000135,377.6130000000013,377.1230000000013,376.66300000000126,376.7130000000012,377.02300000000116,377.13300000000106,377.183000000001,377.213000000001,377.50300000000095,378.8230000000009,380.02300000000093,380.99300000000096,380.85300000000086,380.97300000000075,381.20300000000077,381.59300000000087,382.86300000000085,384.3030000000009,384.4030000000008,384.5230000000007,385.58300000000065,386.0330000000007,388.21300000000076,388.6930000000008,388.20300000000077,388.2930000000007,388.56300000000067,391.07300000000066,392.49300000000073,392.49300000000073,392.5030000000007,393.56300000000067,391.31300000000067,390.5330000000007,388.3930000000006,388.1130000000006,387.82300000000066,387.23300000000074,386.7530000000007,386.59300000000064,386.2930000000007,385.4330000000008,385.3330000000009,385.1830000000008,384.97300000000075,383.97300000000075,382.4430000000008,381.60300000000086,381.3030000000009,380.5330000000009,379.713000000001,379.37300000000107,379.38300000000106,378.01300000000117,377.5930000000011,376.26300000000117,374.92300000000125,374.4530000000012,374.1130000000013,373.31300000000135,372.08300000000133,371.30300000000136,370.8430000000013,369.93300000000124,370.7430000000012,371.5730000000011,373.90300000000104,374.0730000000011,374.0630000000011,375.0730000000011,376.12300000000107,376.01300000000117,375.4730000000012,374.4830000000012,371.0930000000011,369.0630000000011,366.4630000000012,364.4930000000012,364.0830000000011,365.4830000000012,367.8530000000011,367.37300000000107,366.48300000000097,366.15300000000104,365.943000000001,365.7930000000009,365.1630000000008,364.2630000000007,362.8030000000007,362.46300000000076,362.46300000000076,362.4430000000008,362.1430000000008,360.5130000000007,362.2730000000007,362.95300000000077,363.0030000000007,363.10300000000063,363.3030000000007,365.7930000000007,367.49300000000073,366.63300000000083,362.0530000000009,361.4230000000008,361.3030000000009,361.223000000001,363.3330000000009,363.5830000000009,364.0630000000009,366.02300000000093,367.87300000000084,368.85300000000086,370.11300000000085,372.26300000000094,372.73300000000097,373.00300000000095,374.203000000001,376.3630000000011,375.90300000000104,375.77300000000093,375.66300000000103,371.8130000000011,370.52300000000116,368.37300000000107,368.37300000000107,366.173000000001,362.673000000001,360.453000000001,361.01300000000094,361.14300000000105,360.87300000000107,358.963000000001,357.203000000001,356.98300000000097,354.87300000000107,354.5030000000012,354.3830000000013,353.65300000000127,351.6230000000013,350.7230000000012,342.92300000000125,340.78300000000115,337.41300000000126,335.6430000000013,334.7430000000012,332.80300000000113,332.14300000000105,329.223000000001,327.6030000000011,327.05300000000113,324.673000000001,323.223000000001,322.713000000001,318.51300000000094,317.0530000000009,313.99300000000096,313.953000000001,312.0730000000009,310.1930000000008,304.61300000000085,303.4230000000008,301.3130000000009,300.8330000000009,299.62300000000084,297.01300000000083,295.9130000000008,294.00300000000084,291.76300000000083,290.6430000000008,289.45300000000077,289.37300000000073,289.48300000000074,289.7930000000007,288.5130000000007,287.6330000000007,286.45300000000077,286.0030000000007,285.1430000000007,285.1630000000007,285.1630000000007,285.3830000000007,285.8030000000007,286.21300000000065,286.72300000000064,287.48300000000063,286.96300000000065,286.83300000000065,286.47300000000064,286.44300000000067,286.2930000000007,285.9230000000007,285.07300000000066,279.69300000000067,278.56300000000067,279.9230000000007,281.11300000000074,282.73300000000074,283.0030000000007,283.0030000000007,282.9030000000007,282.9130000000007,282.71300000000065,282.0330000000007,279.5530000000007,277.45300000000066,276.0430000000007,275.49300000000073,275.1430000000007,273.45300000000066,273.0510000000006,273.1950000000006,274.1590000000007,272.7880000000007,270.00100000000066,265.88100000000065,263.0890000000006,256.85300000000063,256.05900000000065,255.55300000000068,252.17000000000064,250.9220000000006,249.1910000000006,249.2920000000006,252.62000000000057,257.58800000000053,259.7200000000005,260.0130000000005,265.21800000000053,264.5380000000006,264.3600000000006,264.0990000000006,264.15000000000066,264.18800000000067,265.1000000000007,266.4130000000007,266.9080000000007,267.9900000000007,268.65600000000074,269.0050000000008,270.20900000000074,271.1930000000008,272.9650000000008,274.0780000000009,275.26300000000083,274.25800000000083,272.98400000000083,272.12700000000086,271.6600000000009,268.8890000000009,264.57500000000095,263.025000000001,260.228000000001,259.011000000001,258.713000000001,258.457000000001,258.63300000000106,258.63300000000106,259.2660000000011,259.8810000000011,262.9630000000011,263.2890000000011,263.86400000000117,262.9600000000012,262.7100000000012,262.4050000000012,261.25000000000125,260.0070000000012,258.41900000000123,252.98700000000122,251.58700000000124,247.8680000000012,247.6030000000012,243.2040000000012,242.70600000000115,235.22900000000118,231.90900000000113,230.71100000000115,226.0350000000011,224.35100000000114,222.66800000000114,221.2280000000011,221.07300000000112,220.47100000000114,220.68100000000118,221.49000000000115,219.0310000000012,218.3150000000012,216.02400000000114,214.59700000000112,209.7470000000011,205.4390000000011,204.69300000000112,204.4050000000011,205.91400000000112,206.24900000000116,211.22000000000116,212.73100000000113,213.05300000000113,213.29200000000117,212.9880000000012,211.56600000000117,211.09100000000115,209.8530000000011,210.74900000000105,209.80700000000104,207.03300000000104,205.857000000001,205.857000000001,204.92200000000105,201.222000000001,196.93600000000106,196.66600000000108,191.8480000000011,191.8480000000011,190.71100000000115,185.82100000000116,184.28500000000122,184.15900000000124,183.66000000000122,183.57700000000125,182.90800000000127,179.22100000000125,176.8730000000013,175.91500000000133,175.52100000000132,174.9740000000013,170.2090000000013,164.6660000000013,164.05300000000125,160.6130000000012,153.55400000000122,152.20000000000118,150.15200000000118,148.79300000000114,146.77000000000112,144.9530000000011,144.85100000000114,144.7760000000011,143.91100000000108,135.79900000000112,133.9150000000011,133.7130000000011,133.41700000000105,133.19200000000103,133.400000000001,133.79300000000103,134.366000000001,136.42500000000098,137.554000000001,138.79100000000096,137.81100000000094,136.650000000001,134.58500000000095,132.88700000000097,131.63900000000092,131.12400000000093,128.26300000000094,127.93200000000093,127.96300000000087,127.89100000000087,129.10400000000084,129.84500000000082,130.97200000000078,131.15700000000072,131.09200000000067,131.25100000000066,131.3940000000007,131.47800000000063,132.11200000000065,132.19300000000067,134.34800000000064,135.75900000000058,138.53400000000056,139.27000000000055,140.77900000000056,142.02200000000062,143.1140000000006,143.14500000000055,143.24100000000055,146.30800000000056,147.21100000000058,147.72800000000063,149.7010000000006,150.53600000000063,152.56300000000067,153.77600000000064,154.1910000000006,154.09400000000062,153.67500000000064,155.8350000000006,156.48100000000056,156.33800000000053,156.00000000000057,155.78800000000058,154.71300000000053,153.12000000000057,153.15900000000056,154.8390000000005,155.35500000000047,155.8200000000005,157.13600000000054,158.3630000000005,160.49700000000053,161.8870000000005,162.4500000000005,161.35300000000052,158.70600000000047,158.55400000000043,158.0310000000004,157.90200000000038,157.50800000000038,156.5450000000004,154.10000000000036,152.01800000000037,150.35000000000036,145.21200000000033,143.24000000000035,142.15000000000032,143.3810000000003,146.03600000000029,145.49300000000028,143.70300000000032,141.94300000000032,143.74100000000033,143.79200000000037,143.85100000000034,144.1850000000003,145.77800000000025,146.70100000000025,147.8140000000003,149.62500000000034,151.59200000000033,154.23100000000034,154.49600000000032,153.86100000000033,153.16200000000038,153.2330000000004,153.6270000000004,154.00900000000036,156.1220000000004,158.26100000000042,158.68800000000044,159.11000000000047,159.3720000000004,160.01400000000046,161.00600000000043,161.11100000000044,161.0120000000004,160.59300000000042,159.48400000000038,157.01400000000035,155.75400000000036,155.06800000000032,153.55700000000036,154.09600000000034,156.81200000000035,157.27900000000034,159.23100000000034,162.6840000000003,163.9590000000003,164.85900000000026,166.86500000000024,169.23000000000025,169.9770000000002,175.46000000000015,176.6840000000002,179.36100000000022,180.15300000000025,177.5450000000003,171.3340000000003,164.84500000000025,157.22900000000027,150.45100000000025,144.24300000000028,140.57200000000023,138.03200000000027,138.87900000000025,140.57200000000023,140.57200000000023,138.59900000000027,136.34000000000026,132.67600000000027,128.1600000000003,125.33500000000026,124.7710000000003,127.02700000000027,129.00800000000027,127.58900000000028,122.79600000000028,118.84200000000033,116.5880000000003,121.09700000000032,121.09700000000032,118.56200000000035,115.45800000000031,114.0450000000003,110.0930000000003,105.57800000000032,98.80400000000031,90.05600000000027,83.28200000000027,75.38300000000027,69.45300000000032,70.29900000000032,68.89000000000033,65.78200000000038,64.37400000000036,66.06800000000032,75.38300000000038,75.38300000000038,74.25100000000043,74.5360000000004,72.84300000000042,73.12400000000036,73.12400000000036,68.0410000000004,65.78200000000038,64.93600000000038,62.9640000000004,57.60100000000034,52.80700000000036,47.72200000000032,48.290000000000305,48.57000000000028,46.595000000000255,48.00300000000027,54.779000000000224,59.57400000000018,61.83500000000015,64.65800000000013,64.65800000000013,62.67900000000009,64.01100000000008,64.00900000000013,61.445000000000164,58.59300000000019,58.334000000000174,57.63700000000017,55.737000000000194,54.14300000000014,53.39800000000014,50.54000000000019,46.76900000000023,46.438000000000216,45.14100000000019,44.62400000000014,46.73400000000015,47.31900000000019,50.50500000000022,51.0300000000002,51.33700000000022,51.02400000000023,50.349000000000274,49.01800000000026,46.45900000000029,44.07600000000025,42.68700000000024,35.61800000000028,33.202000000000226,32.51400000000024,29.453000000000202,28.095000000000255,28.89500000000021,29.487000000000194,29.449000000000183,28.1550000000002,23.424000000000206,22.76600000000019,21.23400000000015,19.612000000000194,19.20400000000018,17.247000000000185,14.695000000000164,14.947000000000116,15.549000000000092,16.828000000000088,14.256000000000085,12.745000000000118,10.639000000000124,7.805000000000177,5.921000000000163,7.176000000000158,8.268000000000143,7.9340000000001965,5.606000000000222,4.5870000000002165,6.383000000000266,7.11400000000026,8.779000000000224,9.713000000000193,11.883000000000152,12.35300000000018,13.79700000000014,13.664000000000101,12.217000000000098,13.601000000000113,16.219000000000165,16.977000000000203,17.91900000000021,18.352000000000203,18.54000000000019,18.007000000000176,17.935000000000173,17.01200000000017,14.947000000000116,12.75500000000011,11.291000000000054,9.21300000000008,10.079000000000065,11.946000000000026,13.452999999999975,13.259000000000015,13.884000000000015,14.20799999999997,12.727999999999952,12.317999999999984,8.947999999999979,8.20799999999997,6.8940000000000055,4.671000000000049,4.254000000000019,3.3220000000000027,2.0810000000000173,0.42200000000002547,0.0,0.3990000000000009,0.3170000000000073,0.6789999999999736,1.891999999999939,2.74899999999991,5.378999999999905,6.760999999999854,6.945999999999799,7.093999999999824,6.736999999999853,6.416999999999803,9.058999999999855,9.614999999999895,9.712999999999852,9.923999999999864,10.031999999999812,9.782999999999788,9.276999999999816,8.284999999999854,7.410999999999831,6.251999999999839,5.763999999999783,4.951999999999771,3.6209999999997535,5.334999999999809,6.0899999999998045,6.514999999999759,6.35899999999981,6.371999999999844,8.066999999999894,8.61999999999989,10.017999999999915,10.825999999999908,11.236999999999853,12.013999999999896,12.579999999999927,12.843999999999937,14.718999999999937,16.284999999999968,17.365999999999985,17.552999999999997,17.653999999999996,18.270999999999958,17.310999999999922,15.557999999999879,13.96699999999987,14.78599999999983,15.225999999999885,15.579999999999927,17.195999999999913,18.81799999999987,19.603999999999814,22.490999999999758,23.462999999999738,23.622999999999706,23.08599999999967,23.535999999999717,23.52799999999968,23.86799999999971,23.868999999999687,24.832999999999743,24.852999999999724,25.26399999999967,25.119999999999663,25.03799999999967,23.250999999999635,22.70999999999958,21.132999999999583,18.239999999999554,15.710999999999558,13.96699999999953,12.612999999999488,12.797999999999433,11.690999999999462,10.453999999999496,10.034999999999513,9.274999999999523,8.681999999999562,9.848999999999592,11.626999999999612,12.423999999999637,13.948999999999614,17.135999999999626,18.204999999999586,21.05499999999961,21.577999999999633,22.802999999999656,22.927999999999656,22.9789999999997,27.404999999999745,29.29199999999969,29.247999999999706,28.892999999999688,28.153999999999655,27.155999999999608,24.676999999999566,24.545999999999594,23.479999999999563,20.731999999999516,20.300999999999476,19.83399999999949,19.390999999999508,20.49399999999946,20.630999999999403,23.73599999999942,27.404999999999404,30.78899999999942,32.20099999999945,32.20099999999945,33.327999999999406,37.2849999999994,39.53699999999935,39.2559999999994,41.80199999999945,44.61699999999951,46.8769999999995,46.31399999999951,51.10999999999956,55.343999999999596,56.753999999999564,59.29499999999962,61.83499999999958,68.0409999999996,71.14799999999957,72.67299999999955,72.80799999999954,73.90399999999954,74.41399999999953,77.18399999999951,77.50899999999956,79.14999999999952,80.84399999999948,80.88099999999952,82.30099999999948,83.7519999999995,85.72599999999954,86.73599999999954,87.0069999999995,87.35999999999945,90.76299999999947,91.9439999999995,92.78299999999956,93.04199999999958,93.72699999999952,94.75799999999947,96.96299999999951,97.73599999999954,97.76999999999953,98.0499999999995,99.6509999999995,100.09199999999953,102.03199999999958,104.07299999999964,105.1129999999996,106.5169999999996,109.58499999999958,111.61399999999958,112.1179999999996,116.02299999999957,118.92199999999957,118.6179999999996,114.46199999999965,113.81199999999967,111.86099999999965,107.5319999999997,105.40599999999972,104.66699999999969,100.87199999999973,96.92099999999971,94.65499999999975,93.4069999999997,93.27799999999968,92.93199999999968,92.40799999999967,92.29299999999967,89.60299999999961,87.87299999999959,86.57299999999964,85.04299999999967,84.08899999999971,82.82299999999975,84.93799999999976,85.43099999999981,84.72599999999977,83.04299999999978,81.99499999999978,81.63699999999983,81.2439999999998,80.60499999999979,80.32899999999984,79.78099999999984,81.65499999999986,83.26499999999987,83.40699999999993,85.64999999999998,87.86799999999994,88.77199999999993,88.03199999999993,87.12099999999998,87.24799999999993,89.85299999999995,91.77699999999993,95.3839999999999,99.93299999999988,100.49399999999991,102.00499999999988,104.13999999999987,113.45299999999986,121.03599999999983,122.37999999999988,128.14999999999986,132.52599999999984,133.30399999999986,133.12999999999988,134.6729999999999,135.9459999999999,138.4079999999999,138.4079999999999,139.16499999999985,141.88499999999988,142.43299999999988,142.88699999999983,140.88599999999985,138.8019999999999,136.68499999999995,135.94799999999998,133.82799999999997,131.55999999999995,131.10699999999997,132.10799999999995,134.1199999999999,134.25199999999984,135.92599999999982,139.01899999999978,140.13099999999974,140.9549999999997,142.4929999999997,144.5949999999997,148.14399999999966,146.4939999999997,144.3689999999997,144.58399999999972,147.56699999999967,148.65999999999963,148.78999999999962,149.98599999999965,151.5839999999996,152.8149999999996,151.96199999999965,152.87199999999962,154.78799999999967,155.17799999999966,157.0409999999997,159.6039999999997,164.9159999999997,166.37199999999973,174.10099999999977,176.84599999999978,183.6189999999998,189.29399999999976,190.1579999999998,194.89599999999984,195.50599999999986,197.5809999999999,198.0039999999999,198.5519999999999,200.4999999999999,203.1529999999999,204.70399999999995,205.16999999999996,205.25799999999992,205.13799999999992,205.12799999999993,205.1239999999999,206.50199999999995,207.32499999999993,208.3599999999999,208.4269999999999,208.71499999999992,210.6389999999999,211.2539999999999,212.2489999999999,215.5329999999999,216.1729999999999,216.63499999999988,218.21499999999992,222.16599999999994,222.7689999999999,224.03599999999994,223.85799999999995,222.5999999999999,224.00099999999986,226.28599999999983,229.9119999999998,230.2009999999998,230.7439999999998,230.99099999999976,230.65099999999973,229.58699999999976,228.70899999999972,230.44699999999978,231.37599999999975,232.02899999999977,239.2059999999998,243.20399999999984,245.25999999999988,245.92799999999988,246.41199999999992,245.3309999999999,244.59899999999993,244.8789999999999,246.25999999999988,248.02199999999982,252.48599999999988,253.54999999999984,255.3309999999998,258.12199999999984,260.90999999999985,263.14599999999984,266.2549999999999,267.11799999999994,268.24699999999996,267.6859999999999,266.6399999999999,269.2389999999999,270.0279999999999,270.67999999999995,273.049,273.119,277.043,277.793,285.443,286.903,286.803,287.84299999999996,288.2729999999999,289.71299999999997,291.8929999999999,292.1629999999999,295.0329999999999,295.4129999999999,298.4329999999999,299.37299999999993,299.37299999999993,298.23299999999995,298.24299999999994,300.313,302.023,303.87299999999993,307.273,307.87299999999993,308.25300000000004,312.793,313.3829999999999,314.01300000000003,316.073,318.6629999999999,322.2529999999998,330.6229999999997,330.94299999999964,333.7429999999996,336.5929999999995,338.6929999999994,340.7929999999993,340.88299999999924,342.7929999999993,341.87299999999925,341.5529999999993,340.9229999999992,342.5729999999993,343.9529999999994,343.38299999999947,343.29299999999955,344.3329999999995,347.4429999999994,351.8029999999993,353.85299999999927,354.4329999999992,357.64299999999923,358.38299999999924,360.10299999999927,362.6929999999992,363.5929999999993,367.00299999999936,367.62299999999925,369.73299999999915,371.46299999999917,372.1929999999992,374.5229999999991,375.0629999999991,374.5329999999991,374.00299999999913,373.47299999999916,377.09299999999905,379.662999999999,383.09299999999905,386.8029999999991,387.35299999999904,389.2929999999991,390.0329999999991,390.11299999999903,389.69299999999896,389.4929999999989,390.06299999999885,390.58299999999883,391.83299999999883,391.0029999999989,386.58299999999883,384.55299999999886,382.1229999999988,381.56299999999885,381.45299999999895,381.7629999999989,382.8629999999988,383.9729999999987,385.05299999999863,383.37299999999857,380.4229999999985,377.5429999999984,374.48299999999847,372.90299999999854,371.15299999999854,371.52299999999843,373.34299999999837,376.02299999999843,377.0629999999984,377.87299999999834,379.11299999999835,379.84299999999837,380.49299999999846,382.2229999999985,387.7829999999984,393.1829999999985,395.6129999999986,406.6029999999986,406.90299999999854,407.16299999999853,408.27299999999843,408.35299999999836,408.27299999999843,407.1829999999985,407.1929999999985,408.5429999999984,410.0729999999984,410.63299999999833,410.6729999999983,412.6529999999983,415.46299999999826,417.82299999999816,418.82299999999816,421.46299999999826,422.4129999999983,423.72299999999825,424.5529999999982,425.5229999999982,427.20299999999827,427.8029999999982,427.96299999999826,427.32299999999816,426.94299999999805,427.19299999999805,426.8629999999981,426.2729999999982,424.81299999999817,422.3829999999981,421.18299999999806,420.20299999999804,418.8729999999981,418.4129999999981,415.59299999999814,410.3029999999982,409.73299999999824,407.88299999999833,407.71299999999826,407.48299999999824,402.72299999999825,402.95299999999827,403.1729999999983,396.97299999999825,391.47299999999825,389.95299999999827,385.9329999999983,384.6829999999983,383.88299999999833,380.4329999999983,380.1729999999983,373.4429999999983,372.09299999999837,371.5829999999984,368.50299999999845,367.0529999999984,360.4229999999983,360.0829999999984,359.5529999999984,359.4729999999985,356.7829999999984,354.2929999999984,352.9329999999985,352.13299999999856,351.01299999999867,346.92299999999875,346.6229999999988,349.5129999999989,351.9929999999989,349.132999999999,348.86299999999903,349.00299999999913,349.10299999999904,351.412999999999,352.7529999999989,350.81299999999885,348.83299999999883,349.1029999999988,349.5929999999988,346.1329999999988,343.18299999999874,341.9729999999987,339.44299999999873,337.1329999999988,334.4629999999987,333.5029999999987,333.0729999999986,333.5829999999986,334.30299999999863,332.3129999999986,330.51299999999867,328.77299999999866,327.87299999999857,328.5929999999986,329.65299999999854,328.9729999999985,328.88299999999856,330.79299999999864,332.4829999999987,335.8729999999988,335.8729999999988,337.0029999999989,339.82299999999884,342.3629999999988,343.7729999999989,346.8829999999988,348.8529999999988,357.6029999999988,360.9929999999989,368.6029999999988,370.8729999999988,374.81299999999885,375.1029999999988,378.2029999999987,382.15299999999877,385.26299999999867,387.52299999999866,390.62299999999857,392.03299999999865,393.44299999999873,394.57299999999884,397.67299999999875,399.94299999999873,401.0629999999986,401.62299999999857,405.8629999999986,410.0929999999986,413.76299999999867,417.7129999999987,419.9729999999987,423.3629999999988,429.56299999999885,436.06299999999885,437.47299999999893,442.2729999999989,443.68299999999897,440.0129999999989,437.7529999999989,437.7529999999989,440.29299999999887,443.68299999999897,446.5029999999989,449.892999999999,454.402999999999,454.122999999999,456.10299999999904,457.50299999999913,458.9229999999992,464.00299999999913,467.6629999999992,469.63299999999924,471.9029999999992,475.00299999999913,475.57299999999907,473.30300000000136],\"y\":[347.53499999999997,347.53499999999997,356.009,361.087,363.063,365.66599999999994,365.93899999999996,366.726,368.823,373.466,375.36199999999997,378.76,382.26,382.44100000000003,385.654,387.432,390.75800000000004,398.17100000000005,399.50300000000004,402.2460000000001,403.0450000000001,410.2500000000001,415.12900000000013,417.55700000000013,418.03700000000015,418.03700000000015,418.6300000000001,418.6490000000001,418.80100000000016,419.6650000000002,422.36900000000014,424.50300000000016,424.62900000000013,425.88300000000015,427.8910000000002,431.19000000000017,433.6350000000002,435.5580000000002,438.5390000000002,439.64700000000016,443.6610000000002,444.3220000000001,447.9950000000001,449.1010000000001,453.7070000000001,455.00400000000013,458.0050000000001,460.1890000000001,463.16200000000003,464.4290000000001,465.93500000000006,469.1,469.42500000000007,469.3990000000001,469.3910000000001,470.0970000000001,470.7400000000001,472.74300000000017,476.0400000000002,479.87000000000023,484.5460000000003,485.1850000000003,490.95100000000025,498.41300000000024,502.0410000000003,506.1120000000003,507.9110000000003,511.27300000000025,512.0300000000002,512.0300000000002,519.3170000000002,522.1070000000002,525.4030000000002,526.7400000000002,531.6970000000001,538.5270000000002,539.6860000000001,539.7490000000001,539.8070000000001,544.0770000000001,546.8220000000001,547.1840000000002,547.1840000000002,547.1810000000002,547.2470000000001,546.1330000000002,545.8870000000002,544.9040000000002,544.7770000000002,545.3050000000002,545.7120000000002,546.9910000000002,548.1720000000001,549.2690000000001,550.7130000000002,550.7970000000001,551.1690000000001,551.1640000000002,551.1610000000002,552.2350000000001,553.4290000000002,554.1280000000002,554.1980000000002,554.2730000000001,554.3330000000002,554.3190000000002,554.3050000000002,555.1180000000002,560.1500000000001,560.4220000000001,560.6250000000001,565.2320000000002,566.7620000000002,569.4910000000001,570.259,572.4290000000001,572.671,574.6460000000002,577.469,579.806,579.7440000000001,576.2710000000001,576.8320000000001,577.655,576.224,574.702,574.1370000000001,571.7930000000001,573.066,577.3300000000002,578.6950000000002,578.6400000000001,578.5910000000001,578.613,581.0520000000001,581.9050000000002,581.9390000000001,581.5600000000002,580.6550000000002,580.8870000000002,583.9280000000001,585.4920000000002,586.0660000000003,586.8200000000002,586.8400000000001,586.9670000000002,587.2740000000002,587.4030000000002,587.4990000000003,588.2970000000003,589.6400000000003,590.2850000000003,590.6800000000003,590.2190000000003,589.2930000000002,589.0040000000002,588.9930000000002,590.0540000000002,591.6910000000003,591.7590000000002,591.6070000000002,590.7280000000002,590.6570000000002,591.7050000000002,590.5920000000001,587.2840000000001,586.9840000000002,586.8310000000001,586.0160000000001,587.0250000000001,590.7650000000001,590.7700000000002,591.9580000000001,595.6720000000001,596.2700000000002,597.6280000000002,597.7630000000001,597.6660000000002,597.5420000000001,598.0450000000001,598.3130000000001,598.3910000000001,599.0870000000001,599.2210000000001,599.3010000000002,599.4230000000001,599.7130000000002,599.1100000000001,598.6460000000002,598.5810000000001,599.0090000000001,599.5830000000001,601.8710000000001,601.9520000000002,604.0580000000002,604.1610000000002,605.8840000000002,607.5920000000002,607.5100000000002,607.4470000000002,609.1620000000003,610.9270000000001,610.7870000000003,610.6710000000003,610.3330000000002,611.0760000000002,611.7740000000001,614.1590000000001,614.3690000000001,614.6380000000001,616.8810000000001,620.1090000000002,620.6430000000001,620.7100000000002,620.7610000000002,620.0740000000001,619.2490000000001,618.0240000000001,614.8000000000002,613.3700000000001,613.8800000000001,614.7450000000001,612.3940000000001,610.3170000000001,609.4520000000001,609.2180000000001,609.1450000000002,609.3580000000002,609.6320000000002,608.0240000000001,605.1500000000001,605.0390000000002,604.5970000000002,603.2730000000001,599.9110000000001,597.6960000000001,597.6030000000001,597.815,597.7830000000001,597.6050000000001,596.6180000000002,594.488,593.8960000000002,593.6140000000001,593.6140000000001,592.9230000000002,591.3050000000002,588.3820000000002,588.2450000000001,587.9730000000002,586.4880000000002,584.7910000000002,584.0700000000002,583.5800000000002,585.2470000000001,585.9000000000001,586.2120000000002,586.0360000000002,586.6990000000002,586.1650000000002,586.0070000000002,585.8690000000001,583.4310000000003,583.1130000000003,583.4490000000003,583.6090000000003,583.9800000000002,586.1120000000003,590.0920000000003,593.2140000000003,593.6190000000003,593.9460000000003,595.1650000000002,596.3190000000002,597.9650000000003,598.7700000000002,598.7720000000003,598.6150000000002,598.9370000000004,599.3180000000002,599.2530000000003,598.6950000000003,598.5920000000003,598.4460000000003,598.6160000000002,599.7190000000003,601.3180000000002,601.1560000000003,596.7350000000004,593.5210000000003,592.7190000000003,587.4940000000003,585.6440000000002,585.2770000000003,581.9250000000002,580.7450000000002,576.1570000000002,576.0540000000002,575.2610000000002,575.1600000000002,573.6750000000002,572.5880000000002,571.1890000000002,571.2760000000002,572.0260000000002,573.1200000000001,572.9890000000003,572.7740000000002,571.5080000000003,570.2840000000002,568.7750000000002,568.5040000000001,568.2440000000001,566.0750000000003,567.2820000000002,567.5290000000002,566.9000000000002,566.4800000000002,564.0390000000002,563.4990000000003,563.1870000000001,562.9650000000001,562.5420000000001,562.1280000000002,562.4210000000003,562.8990000000002,562.1910000000003,561.9690000000003,561.4100000000002,561.4130000000002,561.4120000000003,561.4210000000003,561.4350000000002,559.4680000000003,555.9890000000003,555.1990000000003,555.4510000000002,556.1150000000002,556.2020000000002,556.1920000000002,554.4630000000002,553.7720000000003,551.5250000000003,551.7560000000003,553.1760000000003,554.3230000000003,554.8850000000002,555.1030000000003,554.6280000000003,553.2720000000003,553.6770000000002,556.4790000000003,557.4940000000003,557.7520000000002,558.8850000000002,560.6370000000002,559.8030000000002,555.4510000000002,555.1620000000003,555.9370000000002,557.9050000000002,558.2730000000003,560.5080000000003,562.2310000000002,564.4320000000002,567.5840000000003,569.5920000000003,569.7370000000003,574.1000000000003,579.1040000000003,579.7710000000002,585.8030000000002,586.7470000000003,587.3070000000002,587.0080000000003,587.6750000000002,589.8990000000002,591.9450000000002,592.2520000000002,591.9970000000003,591.2760000000003,591.1130000000003,590.3480000000002,589.8160000000003,590.7350000000002,593.7300000000002,595.8230000000003,597.5490000000002,598.5260000000003,601.2140000000002,602.8230000000002,603.3790000000001,601.2500000000002,598.7870000000001,597.7150000000001,595.1590000000001,594.2690000000002,593.6270000000002,593.5210000000002,593.4800000000002,594.5240000000001,594.7690000000002,593.8160000000003,591.3770000000002,591.0140000000001,590.2280000000002,590.2890000000002,590.3520000000001,590.2180000000001,588.0840000000001,586.4810000000001,583.7170000000001,583.729,586.3530000000001,586.9000000000001,589.9380000000001,591.5750000000002,592.3790000000001,594.0360000000001,593.3080000000001,592.3230000000001,591.6020000000001,591.8680000000002,593.4010000000001,593.5490000000002,594.6040000000002,597.2320000000002,597.5430000000001,598.2050000000002,597.8470000000001,596.5030000000002,594.5150000000001,594.6630000000001,594.9300000000001,596.0670000000001,596.1310000000001,598.9730000000002,605.5610000000001,608.7820000000002,610.2500000000002,612.1150000000002,612.7040000000002,612.7750000000002,613.0930000000002,615.3330000000002,620.6310000000002,623.4120000000003,624.1960000000001,622.7830000000001,620.7160000000001,622.1880000000001,624.2820000000002,624.3590000000002,626.6090000000002,629.4630000000002,628.7990000000002,625.6290000000001,623.8810000000001,623.7030000000002,625.9800000000001,626.6450000000002,626.6450000000002,624.6780000000001,623.1800000000002,623.7650000000001,625.5910000000001,627.5530000000001,629.4690000000002,630.2070000000001,630.5860000000002,631.7240000000002,631.7240000000002,631.5460000000002,631.2960000000002,631.7230000000002,632.7190000000002,632.1650000000002,632.0970000000002,632.0000000000002,630.6430000000003,630.8790000000001,631.5880000000002,632.8380000000002,635.6500000000002,639.0000000000002,639.0260000000003,638.9970000000003,638.9630000000002,640.1770000000002,641.3120000000002,643.1880000000002,644.3540000000003,645.0800000000002,646.0000000000002,644.9400000000003,641.2460000000002,639.4490000000002,631.6690000000002,625.3590000000002,623.9110000000003,622.4120000000003,618.6630000000002,618.5550000000002,619.0490000000002,622.6330000000003,622.9920000000002,626.6660000000002,626.9980000000002,627.1930000000002,628.6130000000002,628.3770000000002,626.2850000000002,626.5890000000002,627.8870000000002,628.3480000000002,628.7020000000002,628.6040000000002,628.5170000000002,628.5170000000002,627.0590000000002,621.9070000000002,621.2650000000001,619.7810000000002,614.9890000000003,612.8980000000001,610.4450000000002,609.3760000000002,608.8410000000001,607.7240000000002,605.5910000000001,604.4640000000002,604.5250000000001,604.3230000000001,602.1230000000002,600.6680000000001,599.8000000000002,597.8960000000002,594.5390000000002,593.7650000000001,593.8030000000001,593.8340000000002,593.6970000000001,593.5650000000002,595.1920000000002,598.8930000000003,597.6550000000002,595.2030000000002,592.3740000000003,592.1190000000001,591.3310000000001,591.3370000000002,591.3530000000002,591.3950000000002,591.4810000000002,591.3430000000002,591.2540000000001,590.0880000000002,588.6710000000003,587.8900000000002,587.3620000000002,586.5290000000002,586.1320000000002,585.4570000000001,584.5620000000001,580.1550000000002,580.1090000000002,580.0740000000002,579.8700000000001,578.5060000000002,577.7560000000002,578.4190000000002,579.7400000000002,580.0550000000003,579.7620000000002,577.1310000000003,574.9000000000003,573.7180000000003,569.5360000000003,568.6750000000002,567.3930000000003,565.9750000000003,566.8570000000002,567.1080000000002,566.2630000000001,565.6990000000002,564.5400000000002,562.4650000000001,559.9080000000001,559.8800000000001,559.9760000000001,560.4080000000001,561.0960000000002,560.7880000000002,560.5050000000001,559.3150000000002,557.6590000000001,553.3210000000001,552.1910000000001,548.8450000000001,547.0360000000001,547.2520000000002,547.373,547.1440000000001,546.8850000000001,546.931,546.1930000000001,545.6180000000002,542.9560000000001,540.3710000000001,542.8900000000001,545.1470000000002,543.7360000000001,542.3240000000002,543.4560000000001,546.8430000000002,541.1950000000002,532.7280000000002,525.1050000000002,520.5870000000002,516.0720000000002,519.4610000000002,520.0250000000003,521.9980000000003,525.3880000000003,522.2790000000002,517.4820000000002,516.3530000000003,514.0950000000003,508.7320000000002,507.88900000000024,511.8330000000002,515.7890000000002,516.3530000000003,521.1510000000003,526.7980000000002,529.3390000000002,533.0120000000002,533.8550000000002,533.5710000000003,532.1630000000002,529.9030000000002,531.0340000000002,529.3390000000002,523.6930000000002,520.0250000000002,518.0490000000002,515.7890000000002,509.01400000000024,502.5240000000002,502.23400000000026,499.9820000000003,494.8970000000003,491.2260000000002,488.4050000000002,482.7610000000002,473.1590000000002,463.8470000000002,455.65800000000024,448.0350000000002,444.65200000000016,445.7750000000002,446.9110000000002,445.2130000000002,440.97900000000016,439.0010000000002,436.7460000000002,431.9430000000002,429.4040000000002,429.1220000000002,430.53200000000015,424.89200000000017,420.08900000000017,413.8800000000002,412.61900000000026,412.6180000000003,411.5240000000002,409.1710000000003,408.57200000000023,408.31100000000026,407.7120000000002,404.9770000000002,403.4060000000002,402.7810000000002,399.82100000000014,399.8610000000001,399.0870000000001,397.4440000000001,395.1790000000001,394.7940000000001,392.24800000000005,391.61400000000003,391.231,390.552,389.46299999999997,387.121,384.81600000000003,386.904,386.648,383.35900000000004,382.135,382.44899999999996,384.264,383.351,381.35900000000004,380.466,380.33799999999997,381.1569999999999,383.34399999999994,383.29099999999994,383.14099999999996,383.72399999999993,384.72799999999995,386.972,385.92099999999994,384.3459999999999,383.59799999999984,381.88699999999983,382.8789999999998,383.91499999999974,382.3169999999998,381.0319999999998,379.56799999999976,376.8679999999997,375.33799999999974,375.0599999999997,373.36699999999973,371.8489999999997,372.20299999999975,372.25599999999974,371.9589999999997,369.27499999999975,365.7489999999998,365.5659999999998,364.9019999999998,364.78499999999985,362.8699999999999,360.5519999999999,356.7069999999999,354.9319999999999,352.71799999999985,351.23199999999986,346.7489999999999,342.8879999999999,340.99699999999996,339.842,337.827,334.456,332.19500000000005,327.274,325.996,325.47,325.75300000000004,325.61400000000003,324.9820000000001,324.3080000000001,323.9610000000001,323.80200000000013,321.05600000000015,320.1250000000001,319.33100000000013,316.1320000000002,315.30700000000013,316.4860000000001,318.12800000000016,317.37300000000016,314.60900000000015,312.81600000000014,311.5640000000002,309.0550000000002,308.57200000000023,308.6900000000003,309.0700000000003,309.26900000000023,309.3000000000002,309.2710000000002,308.43600000000015,305.99800000000016,304.7180000000002,304.6460000000002,303.2180000000002,301.52300000000014,300.10400000000016,300.01300000000015,299.9720000000001,300.05600000000004,300.1310000000001,299.74300000000005,298.4200000000001,296.0490000000001,294.9470000000001,292.9420000000001,292.6300000000001,292.45000000000016,291.56600000000014,288.5450000000002,287.51200000000017,287.4590000000002,287.69500000000016,287.8510000000001,287.5820000000001,285.9280000000001,284.32000000000016,282.7220000000002,280.49000000000024,280.18600000000026,280.32600000000025,280.3620000000002,280.10900000000015,278.9680000000002,278.0980000000002,277.0060000000002,274.8850000000002,271.1080000000002,270.57600000000014,269.9910000000001,268.9230000000001,269.16200000000015,269.25400000000013,266.7410000000001,265.3710000000001,263.4660000000001,258.2210000000001,257.64700000000016,257.6120000000002,257.32000000000016,257.3190000000002,256.4820000000002,256.5730000000002,256.19600000000025,255.97900000000027,255.8770000000003,254.2800000000003,254.46500000000026,254.95000000000027,252.41600000000028,250.70000000000027,249.90000000000032,244.7230000000003,244.34600000000034,243.67300000000034,241.7320000000003,239.94000000000028,238.04200000000026,232.5500000000003,229.88300000000027,226.4580000000003,225.74900000000036,222.9580000000003,217.5930000000003,216.68100000000027,215.19500000000028,215.2320000000003,215.36500000000035,215.36000000000035,214.57300000000032,211.55800000000033,210.88900000000035,209.7910000000004,206.9490000000004,204.50000000000045,203.96300000000042,200.84700000000043,199.65900000000045,197.04400000000044,192.70300000000043,191.41200000000038,190.04800000000034,188.18700000000035,188.9160000000004,188.31700000000035,184.0880000000003,182.67600000000027,179.56500000000028,176.4590000000003,174.76800000000026,171.37900000000025,166.29700000000025,163.1930000000002,160.93500000000017,158.39400000000012,156.9810000000001,160.09000000000015,162.62800000000016,162.90800000000013,160.6550000000001,156.13600000000008,155.8520000000001,155.8520000000001,154.15700000000004,154.72800000000007,156.34400000000005,155.341,156.591,157.18000000000006,157.79700000000003,157.75700000000006,157.3180000000001,156.57600000000014,155.1740000000001,151.55600000000004,150.389,149.22400000000005,149.788,149.962,149.68899999999996,146.36299999999994,146.79599999999994,147.4079999999999,147.26299999999992,146.9609999999999,146.75299999999993,147.64299999999992,148.12599999999986,148.14199999999983,147.78599999999983,146.39699999999982,146.21899999999982,145.69499999999982,146.5089999999998,147.06199999999978,146.22899999999981,144.48699999999985,143.39199999999983,143.00099999999986,141.26199999999983,139.69299999999987,139.3299999999998,133.53799999999978,131.2779999999998,127.22199999999975,124.42999999999972,120.90399999999977,119.5709999999998,115.79499999999985,107.85899999999981,101.95199999999977,98.3689999999998,96.48999999999978,92.35899999999981,87.56199999999978,87.4749999999998,83.48699999999974,79.89699999999971,77.73599999999976,74.42899999999975,72.46599999999978,65.63499999999976,60.69999999999982,59.8159999999998,57.016999999999825,52.72799999999984,48.374999999999886,45.90899999999988,45.32999999999993,40.108999999999924,38.347999999999956,37.344999999999914,30.792999999999893,27.55099999999993,26.60599999999988,25.09999999999991,26.422999999999888,27.437999999999874,26.27199999999982,24.919999999999845,23.05999999999983,21.759999999999877,22.189999999999827,24.12999999999988,26.36399999999992,24.999999999999886,22.719999999999914,22.569999999999936,24.899999999999977,28.23199999999997,27.67700000000002,24.200000000000045,24.690000000000055,24.82000000000005,25.600000000000023,28.411000000000058,28.684000000000083,27.583000000000084,26.936000000000035,26.936000000000035,29.554000000000087,30.828000000000088,32.62000000000012,34.30700000000013,34.871000000000095,33.60600000000011,32.85200000000009,32.287000000000035,33.259000000000015,35.68700000000001,37.15100000000007,40.40100000000007,41.05300000000011,41.53500000000008,42.585000000000036,43.03200000000004,41.694000000000074,40.02200000000005,42.18100000000004,39.992000000000075,38.72900000000004,36.68100000000004,35.00400000000002,33.88900000000001,34.004999999999995,34.02200000000005,33.4910000000001,32.86200000000008,33.68400000000008,36.55400000000009,36.08100000000013,32.92200000000014,31.235000000000127,30.44200000000012,31.282000000000153,33.0390000000001,32.88000000000011,30.117000000000075,29.12600000000009,25.980000000000132,18.19000000000017,18.130000000000223,20.000000000000227,20.190000000000282,19.000000000000227,18.52000000000021,18.86000000000024,20.08000000000027,19.560000000000286,20.210000000000264,21.85000000000025,21.84000000000026,22.800000000000296,22.86000000000024,22.890000000000214,26.236000000000217,26.469000000000165,26.06500000000017,25.350000000000136,22.40000000000009,21.520000000000095,21.57000000000005,21.760000000000105,22.22000000000014,22.1400000000001,21.12000000000012,18.40000000000009,16.690000000000055,16.760000000000105,14.46000000000015,13.260000000000105,10.190000000000055,8.120000000000005,7.560000000000059,9.660000000000082,9.950000000000045,9.629999999999995,8.090000000000032,6.360000000000014,3.4500000000000455,1.1300000000001091,0.0,0.14000000000010004,0.3200000000001637,4.820000000000164,9.46000000000015,12.0300000000002,13.470000000000255,18.400000000000205,19.890000000000214,22.11000000000024,23.36000000000024,22.43000000000029,22.270000000000323,24.340000000000373,25.0600000000004,24.500000000000455,23.270000000000437,22.000000000000455,21.240000000000464,22.230000000000473,22.46000000000049,21.88000000000045,20.96000000000049,19.090000000000487,18.170000000000528,18.18000000000052,18.18000000000052,15.080000000000496,14.760000000000446,11.660000000000423,11.690000000000396,13.750000000000341,14.260000000000332,13.390000000000327,12.050000000000296,11.830000000000268,11.320000000000277,13.130000000000223,13.500000000000227,15.950000000000273,15.930000000000291,15.380000000000337,15.150000000000318,19.90000000000032,18.530000000000314,18.570000000000277,21.280000000000314,21.22000000000037,21.140000000000327,22.020000000000323,24.1700000000003,25.820000000000277,27.994000000000256,28.065000000000282,28.098000000000297,27.95100000000025,27.77700000000027,28.806000000000267,31.756000000000313,31.734000000000265,31.3190000000003,30.894000000000347,30.67100000000039,30.894000000000347,30.91000000000031,31.82700000000034,34.58800000000031,35.09100000000035,39.01400000000035,40.891000000000304,42.35000000000025,39.60400000000027,38.17300000000023,37.660000000000196,38.55800000000022,39.46700000000021,38.87500000000023,37.781000000000176,34.02200000000016,33.75200000000018,33.316000000000145,34.81900000000019,35.92500000000018,38.22400000000016,38.29600000000016,38.479000000000156,37.882000000000176,36.63400000000013,34.04600000000016,33.76300000000015,33.239000000000146,32.737000000000194,30.81200000000024,27.26000000000022,25.200000000000273,22.720000000000255,21.870000000000232,21.810000000000286,23.11000000000024,24.04000000000019,26.86300000000017,27.971000000000117,29.32100000000014,32.28300000000013,32.871000000000095,38.53200000000004,40.08000000000004,44.537000000000035,43.84699999999998,42.535999999999945,43.7349999999999,44.049999999999955,46.07299999999998,48.03499999999997,49.918000000000006,56.61099999999999,59.71600000000001,63.40999999999997,67.02800000000002,70.02499999999998,70.70899999999995,72.52599999999995,74.73599999999999,76.298,78.67200000000003,81.34100000000001,82.58699999999999,82.75599999999997,82.73000000000002,82.70400000000006,83.44800000000009,88.2360000000001,89.6400000000001,90.19100000000014,98.38300000000015,101.72300000000018,104.26300000000015,107.90300000000013,108.15400000000011,108.40100000000007,112.66000000000008,113.01400000000012,113.72700000000009,115.30700000000013,116.07800000000009,116.11400000000003,114.77499999999998,113.99000000000001,113.18899999999996,112.16599999999994,110.32099999999991,110.64899999999989,112.71699999999987,114.49899999999991,115.46899999999994,118.4419999999999,120.75299999999993,125.18899999999996,126.09399999999994,128.38699999999994,130.082,133.88800000000003,135.11200000000008,137.67500000000007,141.70100000000002,142.53499999999997,142.37299999999993,142.1679999999999,142.20499999999993,145.14199999999994,148.67599999999993,148.76099999999997,147.05200000000002,146.65200000000004,146.82600000000002,149.42399999999998,150.41499999999996,153.596,159.98199999999997,160.27999999999997,162.49400000000003,166.94500000000005,168.66100000000006,170.14100000000008,174.17100000000005,174.4380000000001,178.21100000000013,178.04500000000007,177.9140000000001,177.32200000000012,178.42600000000016,183.9960000000002,184.12500000000023,187.8670000000002,189.85800000000017,192.59500000000014,199.18100000000015,200.1690000000002,200.8760000000002,205.4290000000002,207.40600000000018,209.87000000000023,212.21900000000028,213.63400000000024,213.63400000000024,213.76400000000024,214.87200000000018,215.14600000000019,219.4530000000002,222.8280000000002,224.59600000000023,225.76000000000022,226.17800000000022,228.0490000000002,230.28200000000015,231.73900000000015,232.6780000000001,234.1550000000001,236.0440000000001,238.6350000000001,239.1740000000001,240.26900000000012,242.27100000000007,245.59300000000007,247.22300000000007,247.96600000000012,248.88600000000008,249.86200000000008,250.87900000000013,252.1060000000001,255.47500000000014,255.65700000000015,256.3530000000002,252.9680000000002,251.55500000000018,249.29600000000016,247.88800000000015,246.75400000000013,253.81500000000017,257.1980000000002,259.4580000000002,262.5680000000002,264.82100000000025,266.51800000000026,266.79800000000023,264.82100000000025,267.9300000000003,272.7270000000003,273.29200000000037,273.8570000000004,276.6800000000004,281.2000000000004,280.3490000000004,284.0210000000004,287.1230000000004,284.29900000000043,283.17400000000043,285.4350000000004,289.10100000000045,292.2060000000005,292.7730000000005,293.05300000000045,294.4630000000004,294.4630000000004,296.4410000000004,301.2380000000004,302.36600000000044,306.32200000000046,308.5800000000005,310.27500000000055,313.6580000000006,316.2000000000006,317.89500000000066,320.7190000000006,322.4110000000006,321.0030000000006,321.28500000000065,321.84800000000064,318.74100000000067,314.79000000000065,313.0960000000007,310.27500000000066,307.44900000000064,305.4760000000007,307.7310000000007,313.94500000000073,321.28500000000076,334.2680000000007,340.1960000000007,347.53499999999997]},\"selected\":{\"id\":\"3408\"},\"selection_policy\":{\"id\":\"3407\"}},\"id\":\"3275\",\"type\":\"ColumnDataSource\"}],\"root_ids\":[\"3255\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n const render_items = [{\"docid\":\"6fc7af1d-9af6-47ac-a22f-005fa4aa52d5\",\"root_ids\":[\"3255\"],\"roots\":{\"3255\":\"5f9e8ed1-fd26-4727-a288-1c51a1cc95ad\"}}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { @@ -5678,32 +4789,7 @@ }, { "data": { - "application/javascript": [ - "(function(root) {\n", - " function embed_document(root) {\n", - " const docs_json = {\"c8c51752-0d39-4806-8171-76a8f630f801\":{\"version\":\"3.0.0.dev13\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"GridPlot\",\"id\":\"42916\",\"attributes\":{\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"42915\"},\"children\":[[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42906\",\"attributes\":{\"text\":\"
DIV
\"}},0,0],[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42907\",\"attributes\":{\"text\":\"
DIV
\"}},0,1],[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42908\",\"attributes\":{\"text\":\"
DIV
\"}},0,2],[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42909\",\"attributes\":{\"text\":\"
DIV
\"}},1,0],[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42910\",\"attributes\":{\"margin\":[10,20,30,40],\"text\":\"
DIV
\"}},1,1],[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42911\",\"attributes\":{\"text\":\"
DIV
\"}},1,2],[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42912\",\"attributes\":{\"text\":\"
DIV
\"}},2,0],[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42913\",\"attributes\":{\"text\":\"
DIV
\"}},2,1],[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42914\",\"attributes\":{\"text\":\"
DIV
\"}},2,2]],\"cols\":\"auto\",\"rows\":\"auto\"}}]}};\n", - " const render_items = [{\"docid\":\"c8c51752-0d39-4806-8171-76a8f630f801\",\"roots\":{\"42916\":\"3c9f3473-ef88-49cc-9a28-7c0423ed8a78\"},\"root_ids\":[\"42916\"]}];\n", - " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", - " }\n", - " if (root.Bokeh !== undefined) {\n", - " embed_document(root);\n", - " } else {\n", - " let attempts = 0;\n", - " const timer = setInterval(function(root) {\n", - " if (root.Bokeh !== undefined) {\n", - " clearInterval(timer);\n", - " embed_document(root);\n", - " } else {\n", - " attempts++;\n", - " if (attempts > 100) {\n", - " clearInterval(timer);\n", - " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", - " }\n", - " }\n", - " }, 10, root)\n", - " }\n", - "})(window);" - ], + "application/javascript": "(function(root) {\n function embed_document(root) {\n const docs_json = {\"c8c51752-0d39-4806-8171-76a8f630f801\":{\"version\":\"3.0.0.dev13\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"GridPlot\",\"id\":\"42916\",\"attributes\":{\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"42915\"},\"children\":[[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42906\",\"attributes\":{\"text\":\"
DIV
\"}},0,0],[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42907\",\"attributes\":{\"text\":\"
DIV
\"}},0,1],[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42908\",\"attributes\":{\"text\":\"
DIV
\"}},0,2],[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42909\",\"attributes\":{\"text\":\"
DIV
\"}},1,0],[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42910\",\"attributes\":{\"margin\":[10,20,30,40],\"text\":\"
DIV
\"}},1,1],[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42911\",\"attributes\":{\"text\":\"
DIV
\"}},1,2],[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42912\",\"attributes\":{\"text\":\"
DIV
\"}},2,0],[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42913\",\"attributes\":{\"text\":\"
DIV
\"}},2,1],[{\"type\":\"object\",\"name\":\"Div\",\"id\":\"42914\",\"attributes\":{\"text\":\"
DIV
\"}},2,2]],\"cols\":\"auto\",\"rows\":\"auto\"}}]}};\n const render_items = [{\"docid\":\"c8c51752-0d39-4806-8171-76a8f630f801\",\"roots\":{\"42916\":\"3c9f3473-ef88-49cc-9a28-7c0423ed8a78\"},\"root_ids\":[\"42916\"]}];\n root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n }\n if (root.Bokeh !== undefined) {\n embed_document(root);\n } else {\n let attempts = 0;\n const timer = setInterval(function(root) {\n if (root.Bokeh !== undefined) {\n clearInterval(timer);\n embed_document(root);\n } else {\n attempts++;\n if (attempts > 100) {\n clearInterval(timer);\n console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n }\n }\n }, 10, root)\n }\n})(window);", "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { diff --git a/docs/report.pdf b/docs/report.pdf new file mode 100644 index 0000000..9b73cb9 Binary files /dev/null and b/docs/report.pdf differ diff --git a/docs/test-local.sh b/docs/test-local.sh new file mode 100755 index 0000000..2a49642 --- /dev/null +++ b/docs/test-local.sh @@ -0,0 +1,169 @@ +#!/bin/bash +# Quick local testing script for Survey Dashboard +# Tests the Docker deployment setup before production deployment + +set -e # Exit on error + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Print colored message +print_status() { + echo -e "${BLUE}==>${NC} $1" +} + +print_success() { + echo -e "${GREEN}✓${NC} $1" +} + +print_error() { + echo -e "${RED}✗${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}⚠${NC} $1" +} + +# Banner +echo "" +echo "==========================================" +echo " Survey Dashboard - Local Testing" +echo "==========================================" +echo "" + +# Check if .env.local exists +if [ ! -f .env.local ]; then + print_warning ".env.local not found. Creating from template..." + if [ -f .env.local.example ]; then + cp .env.local.example .env.local + print_success "Created .env.local from .env.local.example" + else + print_error ".env.local.example not found!" + echo "Please create .env.local manually. See LOCAL_TESTING.md for details." + exit 1 + fi +fi + +# Check Docker is running +print_status "Checking Docker..." +if ! docker info > /dev/null 2>&1; then + print_error "Docker is not running!" + echo "Please start Docker and try again." + exit 1 +fi +print_success "Docker is running" + +# Check Docker Compose is installed +print_status "Checking Docker Compose..." +if ! command -v docker-compose &> /dev/null; then + print_error "Docker Compose is not installed!" + echo "Please install Docker Compose and try again." + exit 1 +fi +print_success "Docker Compose is installed" + +# Build and start containers +print_status "Building Docker images..." +if docker-compose --env-file .env.local build; then + print_success "Docker images built successfully" +else + print_error "Docker build failed!" + exit 1 +fi + +print_status "Starting containers..." +if docker-compose --env-file .env.local up -d; then + print_success "Containers started" +else + print_error "Failed to start containers!" + exit 1 +fi + +# Wait for containers to be ready +print_status "Waiting for containers to be ready..." +sleep 5 + +# Check container status +print_status "Checking container status..." +if docker-compose --env-file .env.local ps | grep -q "Up"; then + print_success "Containers are running" + docker-compose --env-file .env.local ps +else + print_error "Some containers are not running!" + docker-compose --env-file .env.local ps + exit 1 +fi + +echo "" +print_status "Running connectivity tests..." +echo "" + +# Read VIRTUAL_PATH from .env.local +VIRTUAL_PATH=$(grep VIRTUAL_PATH .env.local | cut -d= -f2) +if [ -z "$VIRTUAL_PATH" ]; then + VIRTUAL_PATH="/" + print_warning "VIRTUAL_PATH is empty, testing root path" +fi + +# Test 1: Dashboard path should work +print_status "Test 1: Testing dashboard path (http://localhost${VIRTUAL_PATH}/)..." +HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost${VIRTUAL_PATH}/") +if [ "$HTTP_CODE" == "200" ] || [ "$HTTP_CODE" == "302" ]; then + print_success "Dashboard is accessible (HTTP $HTTP_CODE)" +else + print_error "Dashboard returned HTTP $HTTP_CODE (expected 200 or 302)" +fi + +# Test 2: Root path should fail (if VIRTUAL_PATH is not root) +if [ "$VIRTUAL_PATH" != "/" ]; then + print_status "Test 2: Testing root path should be blocked (http://localhost/)..." + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost/") + if [ "$HTTP_CODE" == "404" ] || [ "$HTTP_CODE" == "503" ]; then + print_success "Root path is blocked (HTTP $HTTP_CODE)" + else + print_warning "Root path returned HTTP $HTTP_CODE (expected 404 or 503)" + fi +fi + +# Test 3: Check dashboard logs +print_status "Test 3: Checking dashboard logs..." +if docker-compose --env-file .env.local logs dashboard | grep -q "PRODUCTION mode"; then + print_success "Dashboard started in production mode" +else + print_warning "Could not verify production mode in logs" +fi + +if docker-compose --env-file .env.local logs dashboard | grep -q "Using URL prefix"; then + print_success "Dashboard is using URL prefix" +else + if [ "$VIRTUAL_PATH" != "/" ]; then + print_warning "Could not verify URL prefix in logs" + fi +fi + +# Summary +echo "" +echo "==========================================" +echo " Test Summary" +echo "==========================================" +echo "" +print_success "Docker setup is working!" +echo "" +echo "Next steps:" +echo " 1. Open browser: http://localhost${VIRTUAL_PATH}/" +echo " 2. Verify dashboard loads and is interactive" +echo " 3. Check browser console (F12) for errors" +echo " 4. Test WebSocket connections in Network tab" +echo "" +echo "View logs:" +echo " docker-compose --env-file .env.local logs -f" +echo "" +echo "Stop containers:" +echo " docker-compose --env-file .env.local down" +echo "" +echo "See LOCAL_TESTING.md for detailed testing scenarios" +echo "" diff --git a/nginx/vhost.d/default b/nginx/vhost.d/default new file mode 100644 index 0000000..9467d69 --- /dev/null +++ b/nginx/vhost.d/default @@ -0,0 +1,16 @@ +# Custom nginx configuration for Panel/Bokeh WebSocket support +# This file is automatically included by nginx-proxy for all virtual hosts +# +# IMPORTANT: WebSocket support is REQUIRED for Panel/Bokeh interactivity +# Without these settings, dashboard buttons, filters, and plots won't work + +# WebSocket support configuration +proxy_http_version 1.1; +proxy_set_header Upgrade $http_upgrade; +proxy_set_header Connection "upgrade"; + +# Timeout settings for long-lived WebSocket connections +# Panel/Bokeh maintains persistent connections for real-time updates +proxy_read_timeout 86400; # 24 hours - allows dashboard to stay open all day +proxy_connect_timeout 60; # 60 seconds to establish initial connection +proxy_send_timeout 60; # 60 seconds timeout for sending data diff --git a/poetry.lock b/poetry.lock index d24be8b..d9b7034 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,262 +1,560 @@ +# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand. + [[package]] -name = "astunparse" -version = "1.6.3" -description = "An AST unparser for Python" -category = "dev" +name = "anyio" +version = "4.10.0" +description = "High-level concurrency and networking framework on top of asyncio or Trio" optional = false -python-versions = "*" +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "anyio-4.10.0-py3-none-any.whl", hash = "sha256:60e474ac86736bbfd6f210f7a61218939c318f43f9972497381f1c5e930ed3d1"}, + {file = "anyio-4.10.0.tar.gz", hash = "sha256:3f3fae35c96039744587aa5b8371e7e8e603c0702999535961dd336026973ba6"}, +] [package.dependencies] -six = ">=1.6.1,<2.0" -wheel = ">=0.23.0,<1.0" - -[[package]] -name = "attrs" -version = "22.1.0" -description = "Classes Without Boilerplate" -category = "dev" -optional = false -python-versions = ">=3.5" +idna = ">=2.8" +sniffio = ">=1.1" +typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} [package.extras] -dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] -docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] -tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] -tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] +trio = ["trio (>=0.26.1)"] [[package]] name = "bleach" -version = "5.0.1" +version = "6.2.0" description = "An easy safelist-based HTML-sanitizing tool." -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "bleach-6.2.0-py3-none-any.whl", hash = "sha256:117d9c6097a7c3d22fd578fcd8d35ff1e125df6736f554da4e432fdd63f31e5e"}, + {file = "bleach-6.2.0.tar.gz", hash = "sha256:123e894118b8a599fd80d3ec1a6d4cc7ce4e5882b1317a7e1ba69b56e95f991f"}, +] [package.dependencies] -six = ">=1.9.0" webencodings = "*" [package.extras] -css = ["tinycss2 (>=1.1.0,<1.2)"] -dev = ["Sphinx (==4.3.2)", "black (==22.3.0)", "build (==0.8.0)", "flake8 (==4.0.1)", "hashin (==0.17.0)", "mypy (==0.961)", "pip-tools (==6.6.2)", "pytest (==7.1.2)", "tox (==3.25.0)", "twine (==4.0.1)", "wheel (==0.37.1)"] +css = ["tinycss2 (>=1.1.0,<1.5)"] [[package]] name = "bokeh" -version = "2.4.3" +version = "3.7.3" description = "Interactive plots and applications in the browser from Python" -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "bokeh-3.7.3-py3-none-any.whl", hash = "sha256:b0e79dd737f088865212e4fdcb0f3b95d087f0f088bf8ca186a300ab1641e2c7"}, + {file = "bokeh-3.7.3.tar.gz", hash = "sha256:70a89a9f797b103d5ee6ad15fb7944adda115cf0da996ed0b75cfba61cb12f2b"}, +] [package.dependencies] +contourpy = ">=1.2" Jinja2 = ">=2.9" -numpy = ">=1.11.3" +narwhals = ">=1.13" +numpy = ">=1.16" packaging = ">=16.8" +pandas = ">=1.2" pillow = ">=7.1.0" PyYAML = ">=3.10" -tornado = ">=5.1" -typing-extensions = ">=3.10.0" +tornado = {version = ">=6.2", markers = "sys_platform != \"emscripten\""} +xyzservices = ">=2021.09.1" [[package]] name = "certifi" -version = "2022.6.15.1" +version = "2025.8.3" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"}, + {file = "certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407"}, +] [[package]] name = "cfgv" -version = "3.3.1" +version = "3.4.0" description = "Validate configuration and produce human readable error messages." -category = "dev" optional = false -python-versions = ">=3.6.1" +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] [[package]] name = "charset-normalizer" -version = "2.1.1" +version = "3.4.3" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" optional = false -python-versions = ">=3.6.0" - -[package.extras] -unicode_backport = ["unicodedata2"] +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "charset_normalizer-3.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-win32.whl", hash = "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-win32.whl", hash = "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-win32.whl", hash = "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-win32.whl", hash = "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca"}, + {file = "charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a"}, + {file = "charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14"}, +] [[package]] name = "colorama" -version = "0.4.5" +version = "0.4.6" description = "Cross-platform colored terminal text." -category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main", "dev"] +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] +markers = {main = "platform_system == \"Windows\"", dev = "sys_platform == \"win32\""} + +[[package]] +name = "contourpy" +version = "1.3.3" +description = "Python library for calculating contours of 2D quadrilateral grids" +optional = false +python-versions = ">=3.11" +groups = ["main"] +files = [ + {file = "contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1"}, + {file = "contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381"}, + {file = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:929ddf8c4c7f348e4c0a5a3a714b5c8542ffaa8c22954862a46ca1813b667ee7"}, + {file = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e999574eddae35f1312c2b4b717b7885d4edd6cb46700e04f7f02db454e67c1"}, + {file = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf67e0e3f482cb69779dd3061b534eb35ac9b17f163d851e2a547d56dba0a3a"}, + {file = "contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db"}, + {file = "contourpy-1.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:598c3aaece21c503615fd59c92a3598b428b2f01bfb4b8ca9c4edeecc2438620"}, + {file = "contourpy-1.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:322ab1c99b008dad206d406bb61d014cf0174df491ae9d9d0fac6a6fda4f977f"}, + {file = "contourpy-1.3.3-cp311-cp311-win32.whl", hash = "sha256:fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff"}, + {file = "contourpy-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:3519428f6be58431c56581f1694ba8e50626f2dd550af225f82fb5f5814d2a42"}, + {file = "contourpy-1.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:15ff10bfada4bf92ec8b31c62bf7c1834c244019b4a33095a68000d7075df470"}, + {file = "contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb"}, + {file = "contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6"}, + {file = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7"}, + {file = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8"}, + {file = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea"}, + {file = "contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1"}, + {file = "contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7"}, + {file = "contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411"}, + {file = "contourpy-1.3.3-cp312-cp312-win32.whl", hash = "sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69"}, + {file = "contourpy-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b"}, + {file = "contourpy-1.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc"}, + {file = "contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5"}, + {file = "contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1"}, + {file = "contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286"}, + {file = "contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5"}, + {file = "contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67"}, + {file = "contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9"}, + {file = "contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659"}, + {file = "contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7"}, + {file = "contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d"}, + {file = "contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263"}, + {file = "contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9"}, + {file = "contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d"}, + {file = "contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216"}, + {file = "contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae"}, + {file = "contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20"}, + {file = "contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99"}, + {file = "contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b"}, + {file = "contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a"}, + {file = "contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e"}, + {file = "contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3"}, + {file = "contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8"}, + {file = "contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301"}, + {file = "contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a"}, + {file = "contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77"}, + {file = "contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5"}, + {file = "contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4"}, + {file = "contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36"}, + {file = "contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3"}, + {file = "contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b"}, + {file = "contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36"}, + {file = "contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d"}, + {file = "contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd"}, + {file = "contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339"}, + {file = "contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772"}, + {file = "contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77"}, + {file = "contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13"}, + {file = "contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe"}, + {file = "contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f"}, + {file = "contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0"}, + {file = "contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4"}, + {file = "contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f"}, + {file = "contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae"}, + {file = "contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc"}, + {file = "contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ed3657edf08512fc3fe81b510e35c2012fbd3081d2e26160f27ca28affec989"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:3d1a3799d62d45c18bafd41c5fa05120b96a28079f2393af559b843d1a966a77"}, + {file = "contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880"}, +] + +[package.dependencies] +numpy = ">=1.25" + +[package.extras] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] +mypy = ["bokeh", "contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.17.0)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist", "wurlitzer"] [[package]] name = "coverage" -version = "6.4.4" +version = "7.10.5" description = "Code coverage measurement for Python" -category = "dev" optional = false -python-versions = ">=3.7" - -[package.dependencies] -tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "coverage-7.10.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c6a5c3414bfc7451b879141ce772c546985163cf553f08e0f135f0699a911801"}, + {file = "coverage-7.10.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bc8e4d99ce82f1710cc3c125adc30fd1487d3cf6c2cd4994d78d68a47b16989a"}, + {file = "coverage-7.10.5-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:02252dc1216e512a9311f596b3169fad54abcb13827a8d76d5630c798a50a754"}, + {file = "coverage-7.10.5-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:73269df37883e02d460bee0cc16be90509faea1e3bd105d77360b512d5bb9c33"}, + {file = "coverage-7.10.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f8a81b0614642f91c9effd53eec284f965577591f51f547a1cbeb32035b4c2f"}, + {file = "coverage-7.10.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6a29f8e0adb7f8c2b95fa2d4566a1d6e6722e0a637634c6563cb1ab844427dd9"}, + {file = "coverage-7.10.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fcf6ab569436b4a647d4e91accba12509ad9f2554bc93d3aee23cc596e7f99c3"}, + {file = "coverage-7.10.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:90dc3d6fb222b194a5de60af8d190bedeeddcbc7add317e4a3cd333ee6b7c879"}, + {file = "coverage-7.10.5-cp310-cp310-win32.whl", hash = "sha256:414a568cd545f9dc75f0686a0049393de8098414b58ea071e03395505b73d7a8"}, + {file = "coverage-7.10.5-cp310-cp310-win_amd64.whl", hash = "sha256:e551f9d03347196271935fd3c0c165f0e8c049220280c1120de0084d65e9c7ff"}, + {file = "coverage-7.10.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c177e6ffe2ebc7c410785307758ee21258aa8e8092b44d09a2da767834f075f2"}, + {file = "coverage-7.10.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:14d6071c51ad0f703d6440827eaa46386169b5fdced42631d5a5ac419616046f"}, + {file = "coverage-7.10.5-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:61f78c7c3bc272a410c5ae3fde7792b4ffb4acc03d35a7df73ca8978826bb7ab"}, + {file = "coverage-7.10.5-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f39071caa126f69d63f99b324fb08c7b1da2ec28cbb1fe7b5b1799926492f65c"}, + {file = "coverage-7.10.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:343a023193f04d46edc46b2616cdbee68c94dd10208ecd3adc56fcc54ef2baa1"}, + {file = "coverage-7.10.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:585ffe93ae5894d1ebdee69fc0b0d4b7c75d8007983692fb300ac98eed146f78"}, + {file = "coverage-7.10.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b0ef4e66f006ed181df29b59921bd8fc7ed7cd6a9289295cd8b2824b49b570df"}, + {file = "coverage-7.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:eb7b0bbf7cc1d0453b843eca7b5fa017874735bef9bfdfa4121373d2cc885ed6"}, + {file = "coverage-7.10.5-cp311-cp311-win32.whl", hash = "sha256:1d043a8a06987cc0c98516e57c4d3fc2c1591364831e9deb59c9e1b4937e8caf"}, + {file = "coverage-7.10.5-cp311-cp311-win_amd64.whl", hash = "sha256:fefafcca09c3ac56372ef64a40f5fe17c5592fab906e0fdffd09543f3012ba50"}, + {file = "coverage-7.10.5-cp311-cp311-win_arm64.whl", hash = "sha256:7e78b767da8b5fc5b2faa69bb001edafcd6f3995b42a331c53ef9572c55ceb82"}, + {file = "coverage-7.10.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c2d05c7e73c60a4cecc7d9b60dbfd603b4ebc0adafaef371445b47d0f805c8a9"}, + {file = "coverage-7.10.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:32ddaa3b2c509778ed5373b177eb2bf5662405493baeff52278a0b4f9415188b"}, + {file = "coverage-7.10.5-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:dd382410039fe062097aa0292ab6335a3f1e7af7bba2ef8d27dcda484918f20c"}, + {file = "coverage-7.10.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7fa22800f3908df31cea6fb230f20ac49e343515d968cc3a42b30d5c3ebf9b5a"}, + {file = "coverage-7.10.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f366a57ac81f5e12797136552f5b7502fa053c861a009b91b80ed51f2ce651c6"}, + {file = "coverage-7.10.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f1dc8f1980a272ad4a6c84cba7981792344dad33bf5869361576b7aef42733a"}, + {file = "coverage-7.10.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2285c04ee8676f7938b02b4936d9b9b672064daab3187c20f73a55f3d70e6b4a"}, + {file = "coverage-7.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c2492e4dd9daab63f5f56286f8a04c51323d237631eb98505d87e4c4ff19ec34"}, + {file = "coverage-7.10.5-cp312-cp312-win32.whl", hash = "sha256:38a9109c4ee8135d5df5505384fc2f20287a47ccbe0b3f04c53c9a1989c2bbaf"}, + {file = "coverage-7.10.5-cp312-cp312-win_amd64.whl", hash = "sha256:6b87f1ad60b30bc3c43c66afa7db6b22a3109902e28c5094957626a0143a001f"}, + {file = "coverage-7.10.5-cp312-cp312-win_arm64.whl", hash = "sha256:672a6c1da5aea6c629819a0e1461e89d244f78d7b60c424ecf4f1f2556c041d8"}, + {file = "coverage-7.10.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ef3b83594d933020f54cf65ea1f4405d1f4e41a009c46df629dd964fcb6e907c"}, + {file = "coverage-7.10.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2b96bfdf7c0ea9faebce088a3ecb2382819da4fbc05c7b80040dbc428df6af44"}, + {file = "coverage-7.10.5-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:63df1fdaffa42d914d5c4d293e838937638bf75c794cf20bee12978fc8c4e3bc"}, + {file = "coverage-7.10.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8002dc6a049aac0e81ecec97abfb08c01ef0c1fbf962d0c98da3950ace89b869"}, + {file = "coverage-7.10.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:63d4bb2966d6f5f705a6b0c6784c8969c468dbc4bcf9d9ded8bff1c7e092451f"}, + {file = "coverage-7.10.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1f672efc0731a6846b157389b6e6d5d5e9e59d1d1a23a5c66a99fd58339914d5"}, + {file = "coverage-7.10.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:3f39cef43d08049e8afc1fde4a5da8510fc6be843f8dea350ee46e2a26b2f54c"}, + {file = "coverage-7.10.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2968647e3ed5a6c019a419264386b013979ff1fb67dd11f5c9886c43d6a31fc2"}, + {file = "coverage-7.10.5-cp313-cp313-win32.whl", hash = "sha256:0d511dda38595b2b6934c2b730a1fd57a3635c6aa2a04cb74714cdfdd53846f4"}, + {file = "coverage-7.10.5-cp313-cp313-win_amd64.whl", hash = "sha256:9a86281794a393513cf117177fd39c796b3f8e3759bb2764259a2abba5cce54b"}, + {file = "coverage-7.10.5-cp313-cp313-win_arm64.whl", hash = "sha256:cebd8e906eb98bb09c10d1feed16096700b1198d482267f8bf0474e63a7b8d84"}, + {file = "coverage-7.10.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0520dff502da5e09d0d20781df74d8189ab334a1e40d5bafe2efaa4158e2d9e7"}, + {file = "coverage-7.10.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d9cd64aca68f503ed3f1f18c7c9174cbb797baba02ca8ab5112f9d1c0328cd4b"}, + {file = "coverage-7.10.5-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0913dd1613a33b13c4f84aa6e3f4198c1a21ee28ccb4f674985c1f22109f0aae"}, + {file = "coverage-7.10.5-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1b7181c0feeb06ed8a02da02792f42f829a7b29990fef52eff257fef0885d760"}, + {file = "coverage-7.10.5-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36d42b7396b605f774d4372dd9c49bed71cbabce4ae1ccd074d155709dd8f235"}, + {file = "coverage-7.10.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b4fdc777e05c4940b297bf47bf7eedd56a39a61dc23ba798e4b830d585486ca5"}, + {file = "coverage-7.10.5-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:42144e8e346de44a6f1dbd0a56575dd8ab8dfa7e9007da02ea5b1c30ab33a7db"}, + {file = "coverage-7.10.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:66c644cbd7aed8fe266d5917e2c9f65458a51cfe5eeff9c05f15b335f697066e"}, + {file = "coverage-7.10.5-cp313-cp313t-win32.whl", hash = "sha256:2d1b73023854068c44b0c554578a4e1ef1b050ed07cf8b431549e624a29a66ee"}, + {file = "coverage-7.10.5-cp313-cp313t-win_amd64.whl", hash = "sha256:54a1532c8a642d8cc0bd5a9a51f5a9dcc440294fd06e9dda55e743c5ec1a8f14"}, + {file = "coverage-7.10.5-cp313-cp313t-win_arm64.whl", hash = "sha256:74d5b63fe3f5f5d372253a4ef92492c11a4305f3550631beaa432fc9df16fcff"}, + {file = "coverage-7.10.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:68c5e0bc5f44f68053369fa0d94459c84548a77660a5f2561c5e5f1e3bed7031"}, + {file = "coverage-7.10.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cf33134ffae93865e32e1e37df043bef15a5e857d8caebc0099d225c579b0fa3"}, + {file = "coverage-7.10.5-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ad8fa9d5193bafcf668231294241302b5e683a0518bf1e33a9a0dfb142ec3031"}, + {file = "coverage-7.10.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:146fa1531973d38ab4b689bc764592fe6c2f913e7e80a39e7eeafd11f0ef6db2"}, + {file = "coverage-7.10.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6013a37b8a4854c478d3219ee8bc2392dea51602dd0803a12d6f6182a0061762"}, + {file = "coverage-7.10.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:eb90fe20db9c3d930fa2ad7a308207ab5b86bf6a76f54ab6a40be4012d88fcae"}, + {file = "coverage-7.10.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:384b34482272e960c438703cafe63316dfbea124ac62006a455c8410bf2a2262"}, + {file = "coverage-7.10.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:467dc74bd0a1a7de2bedf8deaf6811f43602cb532bd34d81ffd6038d6d8abe99"}, + {file = "coverage-7.10.5-cp314-cp314-win32.whl", hash = "sha256:556d23d4e6393ca898b2e63a5bca91e9ac2d5fb13299ec286cd69a09a7187fde"}, + {file = "coverage-7.10.5-cp314-cp314-win_amd64.whl", hash = "sha256:f4446a9547681533c8fa3e3c6cf62121eeee616e6a92bd9201c6edd91beffe13"}, + {file = "coverage-7.10.5-cp314-cp314-win_arm64.whl", hash = "sha256:5e78bd9cf65da4c303bf663de0d73bf69f81e878bf72a94e9af67137c69b9fe9"}, + {file = "coverage-7.10.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:5661bf987d91ec756a47c7e5df4fbcb949f39e32f9334ccd3f43233bbb65e508"}, + {file = "coverage-7.10.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a46473129244db42a720439a26984f8c6f834762fc4573616c1f37f13994b357"}, + {file = "coverage-7.10.5-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1f64b8d3415d60f24b058b58d859e9512624bdfa57a2d1f8aff93c1ec45c429b"}, + {file = "coverage-7.10.5-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:44d43de99a9d90b20e0163f9770542357f58860a26e24dc1d924643bd6aa7cb4"}, + {file = "coverage-7.10.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a931a87e5ddb6b6404e65443b742cb1c14959622777f2a4efd81fba84f5d91ba"}, + {file = "coverage-7.10.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f9559b906a100029274448f4c8b8b0a127daa4dade5661dfd821b8c188058842"}, + {file = "coverage-7.10.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b08801e25e3b4526ef9ced1aa29344131a8f5213c60c03c18fe4c6170ffa2874"}, + {file = "coverage-7.10.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ed9749bb8eda35f8b636fb7632f1c62f735a236a5d4edadd8bbcc5ea0542e732"}, + {file = "coverage-7.10.5-cp314-cp314t-win32.whl", hash = "sha256:609b60d123fc2cc63ccee6d17e4676699075db72d14ac3c107cc4976d516f2df"}, + {file = "coverage-7.10.5-cp314-cp314t-win_amd64.whl", hash = "sha256:0666cf3d2c1626b5a3463fd5b05f5e21f99e6aec40a3192eee4d07a15970b07f"}, + {file = "coverage-7.10.5-cp314-cp314t-win_arm64.whl", hash = "sha256:bc85eb2d35e760120540afddd3044a5bf69118a91a296a8b3940dfc4fdcfe1e2"}, + {file = "coverage-7.10.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:62835c1b00c4a4ace24c1a88561a5a59b612fbb83a525d1c70ff5720c97c0610"}, + {file = "coverage-7.10.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5255b3bbcc1d32a4069d6403820ac8e6dbcc1d68cb28a60a1ebf17e47028e898"}, + {file = "coverage-7.10.5-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3876385722e335d6e991c430302c24251ef9c2a9701b2b390f5473199b1b8ebf"}, + {file = "coverage-7.10.5-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8048ce4b149c93447a55d279078c8ae98b08a6951a3c4d2d7e87f4efc7bfe100"}, + {file = "coverage-7.10.5-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4028e7558e268dd8bcf4d9484aad393cafa654c24b4885f6f9474bf53183a82a"}, + {file = "coverage-7.10.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:03f47dc870eec0367fcdd603ca6a01517d2504e83dc18dbfafae37faec66129a"}, + {file = "coverage-7.10.5-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2d488d7d42b6ded7ea0704884f89dcabd2619505457de8fc9a6011c62106f6e5"}, + {file = "coverage-7.10.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b3dcf2ead47fa8be14224ee817dfc1df98043af568fe120a22f81c0eb3c34ad2"}, + {file = "coverage-7.10.5-cp39-cp39-win32.whl", hash = "sha256:02650a11324b80057b8c9c29487020073d5e98a498f1857f37e3f9b6ea1b2426"}, + {file = "coverage-7.10.5-cp39-cp39-win_amd64.whl", hash = "sha256:b45264dd450a10f9e03237b41a9a24e85cbb1e278e5a32adb1a303f58f0017f3"}, + {file = "coverage-7.10.5-py3-none-any.whl", hash = "sha256:0be24d35e4db1d23d0db5c0f6a74a962e2ec83c426b5cac09f4234aadef38e4a"}, + {file = "coverage-7.10.5.tar.gz", hash = "sha256:f2e57716a78bc3ae80b2207be0709a3b2b63b9f2dcf9740ee6ac03588a2015b6"}, +] [package.extras] -toml = ["tomli"] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "cycler" -version = "0.11.0" +version = "0.12.1" description = "Composable style cycles" -category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, + {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, +] + +[package.extras] +docs = ["ipython", "matplotlib", "numpydoc", "sphinx"] +tests = ["pytest", "pytest-cov", "pytest-xdist"] [[package]] name = "distlib" -version = "0.3.6" +version = "0.4.0" description = "Distribution utilities" -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "docopt" -version = "0.6.1" -description = "Pythonic argument parser, that will make you smile" -category = "dev" optional = false python-versions = "*" +groups = ["dev"] +files = [ + {file = "distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16"}, + {file = "distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"}, +] [[package]] name = "filelock" -version = "3.8.0" +version = "3.19.1" description = "A platform independent file lock." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["furo (>=2022.6.21)", "sphinx (>=5.1.1)", "sphinx-autodoc-typehints (>=1.19.1)"] -testing = ["covdefaults (>=2.2)", "coverage (>=6.4.2)", "pytest (>=7.1.2)", "pytest-cov (>=3)", "pytest-timeout (>=2.1)"] - -[[package]] -name = "Flask" -version = "0.10.1" -description = "A microframework based on Werkzeug, Jinja2 and good intentions" -category = "dev" optional = false -python-versions = "*" - -[package.dependencies] -itsdangerous = ">=0.21" -Jinja2 = ">=2.4" -Werkzeug = ">=0.7" +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d"}, + {file = "filelock-3.19.1.tar.gz", hash = "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58"}, +] [[package]] name = "fonttools" -version = "4.37.1" +version = "4.59.1" description = "Tools to manipulate font files" -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "fonttools-4.59.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e90a89e52deb56b928e761bb5b5f65f13f669bfd96ed5962975debea09776a23"}, + {file = "fonttools-4.59.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d29ab70658d2ec19422b25e6ace00a0b0ae4181ee31e03335eaef53907d2d83"}, + {file = "fonttools-4.59.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94f9721a564978a10d5c12927f99170d18e9a32e5a727c61eae56f956a4d118b"}, + {file = "fonttools-4.59.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8c8758a7d97848fc8b514b3d9b4cb95243714b2f838dde5e1e3c007375de6214"}, + {file = "fonttools-4.59.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2aeb829ad9d41a2ef17cab8bb5d186049ba38a840f10352e654aa9062ec32dc1"}, + {file = "fonttools-4.59.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ac216a2980a2d2b3b88c68a24f8a9bfb203e2490e991b3238502ad8f1e7bfed0"}, + {file = "fonttools-4.59.1-cp310-cp310-win32.whl", hash = "sha256:d31dc137ed8ec71dbc446949eba9035926e6e967b90378805dcf667ff57cabb1"}, + {file = "fonttools-4.59.1-cp310-cp310-win_amd64.whl", hash = "sha256:5265bc52ed447187d39891b5f21d7217722735d0de9fe81326566570d12851a9"}, + {file = "fonttools-4.59.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4909cce2e35706f3d18c54d3dcce0414ba5e0fb436a454dffec459c61653b513"}, + {file = "fonttools-4.59.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:efbec204fa9f877641747f2d9612b2b656071390d7a7ef07a9dbf0ecf9c7195c"}, + {file = "fonttools-4.59.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39dfd42cc2dc647b2c5469bc7a5b234d9a49e72565b96dd14ae6f11c2c59ef15"}, + {file = "fonttools-4.59.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b11bc177a0d428b37890825d7d025040d591aa833f85f8d8878ed183354f47df"}, + {file = "fonttools-4.59.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b9b4c35b3be45e5bc774d3fc9608bbf4f9a8d371103b858c80edbeed31dd5aa"}, + {file = "fonttools-4.59.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:01158376b8a418a0bae9625c476cebfcfcb5e6761e9d243b219cd58341e7afbb"}, + {file = "fonttools-4.59.1-cp311-cp311-win32.whl", hash = "sha256:cf7c5089d37787387123f1cb8f1793a47c5e1e3d1e4e7bfbc1cc96e0f925eabe"}, + {file = "fonttools-4.59.1-cp311-cp311-win_amd64.whl", hash = "sha256:c866eef7a0ba320486ade6c32bfc12813d1a5db8567e6904fb56d3d40acc5116"}, + {file = "fonttools-4.59.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:43ab814bbba5f02a93a152ee61a04182bb5809bd2bc3609f7822e12c53ae2c91"}, + {file = "fonttools-4.59.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4f04c3ffbfa0baafcbc550657cf83657034eb63304d27b05cff1653b448ccff6"}, + {file = "fonttools-4.59.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d601b153e51a5a6221f0d4ec077b6bfc6ac35bfe6c19aeaa233d8990b2b71726"}, + {file = "fonttools-4.59.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c735e385e30278c54f43a0d056736942023c9043f84ee1021eff9fd616d17693"}, + {file = "fonttools-4.59.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1017413cdc8555dce7ee23720da490282ab7ec1cf022af90a241f33f9a49afc4"}, + {file = "fonttools-4.59.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5c6d8d773470a5107052874341ed3c487c16ecd179976d81afed89dea5cd7406"}, + {file = "fonttools-4.59.1-cp312-cp312-win32.whl", hash = "sha256:2a2d0d33307f6ad3a2086a95dd607c202ea8852fa9fb52af9b48811154d1428a"}, + {file = "fonttools-4.59.1-cp312-cp312-win_amd64.whl", hash = "sha256:0b9e4fa7eaf046ed6ac470f6033d52c052481ff7a6e0a92373d14f556f298dc0"}, + {file = "fonttools-4.59.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:89d9957b54246c6251345297dddf77a84d2c19df96af30d2de24093bbdf0528b"}, + {file = "fonttools-4.59.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8156b11c0d5405810d216f53907bd0f8b982aa5f1e7e3127ab3be1a4062154ff"}, + {file = "fonttools-4.59.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8387876a8011caec52d327d5e5bca705d9399ec4b17afb8b431ec50d47c17d23"}, + {file = "fonttools-4.59.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb13823a74b3a9204a8ed76d3d6d5ec12e64cc5bc44914eb9ff1cdac04facd43"}, + {file = "fonttools-4.59.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e1ca10da138c300f768bb68e40e5b20b6ecfbd95f91aac4cc15010b6b9d65455"}, + {file = "fonttools-4.59.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2beb5bfc4887a3130f8625349605a3a45fe345655ce6031d1bac11017454b943"}, + {file = "fonttools-4.59.1-cp313-cp313-win32.whl", hash = "sha256:419f16d750d78e6d704bfe97b48bba2f73b15c9418f817d0cb8a9ca87a5b94bf"}, + {file = "fonttools-4.59.1-cp313-cp313-win_amd64.whl", hash = "sha256:c536f8a852e8d3fa71dde1ec03892aee50be59f7154b533f0bf3c1174cfd5126"}, + {file = "fonttools-4.59.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:d5c3bfdc9663f3d4b565f9cb3b8c1efb3e178186435b45105bde7328cfddd7fe"}, + {file = "fonttools-4.59.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ea03f1da0d722fe3c2278a05957e6550175571a4894fbf9d178ceef4a3783d2b"}, + {file = "fonttools-4.59.1-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:57a3708ca6bfccb790f585fa6d8f29432ec329618a09ff94c16bcb3c55994643"}, + {file = "fonttools-4.59.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:729367c91eb1ee84e61a733acc485065a00590618ca31c438e7dd4d600c01486"}, + {file = "fonttools-4.59.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8f8ef66ac6db450193ed150e10b3b45dde7aded10c5d279968bc63368027f62b"}, + {file = "fonttools-4.59.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:075f745d539a998cd92cb84c339a82e53e49114ec62aaea8307c80d3ad3aef3a"}, + {file = "fonttools-4.59.1-cp314-cp314-win32.whl", hash = "sha256:c2b0597522d4c5bb18aa5cf258746a2d4a90f25878cbe865e4d35526abd1b9fc"}, + {file = "fonttools-4.59.1-cp314-cp314-win_amd64.whl", hash = "sha256:e9ad4ce044e3236f0814c906ccce8647046cc557539661e35211faadf76f283b"}, + {file = "fonttools-4.59.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:652159e8214eb4856e8387ebcd6b6bd336ee258cbeb639c8be52005b122b9609"}, + {file = "fonttools-4.59.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:43d177cd0e847ea026fedd9f099dc917da136ed8792d142298a252836390c478"}, + {file = "fonttools-4.59.1-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e54437651e1440ee53a95e6ceb6ee440b67a3d348c76f45f4f48de1a5ecab019"}, + {file = "fonttools-4.59.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6065fdec8ff44c32a483fd44abe5bcdb40dd5e2571a5034b555348f2b3a52cea"}, + {file = "fonttools-4.59.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:42052b56d176f8b315fbc09259439c013c0cb2109df72447148aeda677599612"}, + {file = "fonttools-4.59.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:bcd52eaa5c4c593ae9f447c1d13e7e4a00ca21d755645efa660b6999425b3c88"}, + {file = "fonttools-4.59.1-cp314-cp314t-win32.whl", hash = "sha256:02e4fdf27c550dded10fe038a5981c29f81cb9bc649ff2eaa48e80dab8998f97"}, + {file = "fonttools-4.59.1-cp314-cp314t-win_amd64.whl", hash = "sha256:412a5fd6345872a7c249dac5bcce380393f40c1c316ac07f447bc17d51900922"}, + {file = "fonttools-4.59.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1ab4c1fb45f2984b8b4a3face7cff0f67f9766e9414cbb6fd061e9d77819de98"}, + {file = "fonttools-4.59.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8ee39da0227950f88626c91e219659e6cd725ede826b1c13edd85fc4cec9bbe6"}, + {file = "fonttools-4.59.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:58a8844f96cff35860647a65345bfca87f47a2494bfb4bef754e58c082511443"}, + {file = "fonttools-4.59.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5f3f021cea6e36410874763f4a517a5e2d6ac36ca8f95521f3a9fdaad0fe73dc"}, + {file = "fonttools-4.59.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bf5fb864f80061a40c1747e0dbc4f6e738de58dd6675b07eb80bd06a93b063c4"}, + {file = "fonttools-4.59.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c29ea087843e27a7cffc78406d32a5abf166d92afde7890394e9e079c9b4dbe9"}, + {file = "fonttools-4.59.1-cp39-cp39-win32.whl", hash = "sha256:a960b09ff50c2e87864e83f352e5a90bcf1ad5233df579b1124660e1643de272"}, + {file = "fonttools-4.59.1-cp39-cp39-win_amd64.whl", hash = "sha256:e3680884189e2b7c3549f6d304376e64711fd15118e4b1ae81940cb6b1eaa267"}, + {file = "fonttools-4.59.1-py3-none-any.whl", hash = "sha256:647db657073672a8330608970a984d51573557f328030566521bc03415535042"}, + {file = "fonttools-4.59.1.tar.gz", hash = "sha256:74995b402ad09822a4c8002438e54940d9f1ecda898d2bb057729d7da983e4cb"}, +] [package.extras] -all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=14.0.0)", "xattr", "zopfli (>=0.1.4)"] +all = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\"", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0) ; python_version <= \"3.12\"", "xattr ; sys_platform == \"darwin\"", "zopfli (>=0.1.4)"] graphite = ["lz4 (>=1.7.4.2)"] -interpolatable = ["munkres", "scipy"] -lxml = ["lxml (>=4.0,<5)"] +interpolatable = ["munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\""] +lxml = ["lxml (>=4.0)"] pathops = ["skia-pathops (>=0.5.0)"] plot = ["matplotlib"] repacker = ["uharfbuzz (>=0.23.0)"] symfont = ["sympy"] -type1 = ["xattr"] -ufo = ["fs (>=2.2.0,<3)"] -unicode = ["unicodedata2 (>=14.0.0)"] -woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] - -[[package]] -name = "gitdb" -version = "4.0.9" -description = "Git Object Database" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -smmap = ">=3.0.1,<6" - -[[package]] -name = "GitPython" -version = "0.3.2.RC1" -description = "Python Git Library" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -gitdb = ">=0.5.1" +type1 = ["xattr ; sys_platform == \"darwin\""] +unicode = ["unicodedata2 (>=15.1.0) ; python_version <= \"3.12\""] +woff = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "zopfli (>=0.1.4)"] [[package]] name = "identify" -version = "2.5.5" +version = "2.6.13" description = "File identification library for Python" -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "identify-2.6.13-py2.py3-none-any.whl", hash = "sha256:60381139b3ae39447482ecc406944190f690d4a2997f2584062089848361b33b"}, + {file = "identify-2.6.13.tar.gz", hash = "sha256:da8d6c828e773620e13bfa86ea601c5a5310ba4bcd65edf378198b56a1f9fb32"}, +] [package.extras] license = ["ukkonen"] [[package]] name = "idna" -version = "3.3" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "importlib-metadata" -version = "4.12.0" -description = "Read metadata from Python packages" -category = "main" optional = false -python-versions = ">=3.7" - -[package.dependencies] -zipp = ">=0.5" +python-versions = ">=3.6" +groups = ["main"] +files = [ + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, +] [package.extras] -docs = ["jaraco.packaging (>=9)", "rst.linker (>=1.9)", "sphinx"] -perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] [[package]] name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" -category = "dev" +version = "2.1.0" +description = "brain-dead simple config-ini parsing" optional = false -python-versions = "*" - -[[package]] -name = "itsdangerous" -version = "2.1.2" -description = "Safely pass data to untrusted environments and back." -category = "dev" -optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, + {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, +] [[package]] -name = "Jinja2" -version = "3.1.2" +name = "jinja2" +version = "3.1.6" description = "A very fast and expressive template engine." -category = "main" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] +files = [ + {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, + {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, +] [package.dependencies] MarkupSafe = ">=2.0" @@ -266,544 +564,1385 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "kiwisolver" -version = "1.4.4" +version = "1.4.9" description = "A fast implementation of the Cassowary constraint solver" -category = "main" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "kiwisolver-1.4.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b4b4d74bda2b8ebf4da5bd42af11d02d04428b2c32846e4c2c93219df8a7987b"}, + {file = "kiwisolver-1.4.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fb3b8132019ea572f4611d770991000d7f58127560c4889729248eb5852a102f"}, + {file = "kiwisolver-1.4.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84fd60810829c27ae375114cd379da1fa65e6918e1da405f356a775d49a62bcf"}, + {file = "kiwisolver-1.4.9-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b78efa4c6e804ecdf727e580dbb9cba85624d2e1c6b5cb059c66290063bd99a9"}, + {file = "kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4efec7bcf21671db6a3294ff301d2fc861c31faa3c8740d1a94689234d1b415"}, + {file = "kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:90f47e70293fc3688b71271100a1a5453aa9944a81d27ff779c108372cf5567b"}, + {file = "kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8fdca1def57a2e88ef339de1737a1449d6dbf5fab184c54a1fca01d541317154"}, + {file = "kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9cf554f21be770f5111a1690d42313e140355e687e05cf82cb23d0a721a64a48"}, + {file = "kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fc1795ac5cd0510207482c3d1d3ed781143383b8cfd36f5c645f3897ce066220"}, + {file = "kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:ccd09f20ccdbbd341b21a67ab50a119b64a403b09288c27481575105283c1586"}, + {file = "kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:540c7c72324d864406a009d72f5d6856f49693db95d1fbb46cf86febef873634"}, + {file = "kiwisolver-1.4.9-cp310-cp310-win_amd64.whl", hash = "sha256:ede8c6d533bc6601a47ad4046080d36b8fc99f81e6f1c17b0ac3c2dc91ac7611"}, + {file = "kiwisolver-1.4.9-cp310-cp310-win_arm64.whl", hash = "sha256:7b4da0d01ac866a57dd61ac258c5607b4cd677f63abaec7b148354d2b2cdd536"}, + {file = "kiwisolver-1.4.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:eb14a5da6dc7642b0f3a18f13654847cd8b7a2550e2645a5bda677862b03ba16"}, + {file = "kiwisolver-1.4.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:39a219e1c81ae3b103643d2aedb90f1ef22650deb266ff12a19e7773f3e5f089"}, + {file = "kiwisolver-1.4.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2405a7d98604b87f3fc28b1716783534b1b4b8510d8142adca34ee0bc3c87543"}, + {file = "kiwisolver-1.4.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dc1ae486f9abcef254b5618dfb4113dd49f94c68e3e027d03cf0143f3f772b61"}, + {file = "kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a1f570ce4d62d718dce3f179ee78dac3b545ac16c0c04bb363b7607a949c0d1"}, + {file = "kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb27e7b78d716c591e88e0a09a2139c6577865d7f2e152488c2cc6257f460872"}, + {file = "kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:15163165efc2f627eb9687ea5f3a28137217d217ac4024893d753f46bce9de26"}, + {file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bdee92c56a71d2b24c33a7d4c2856bd6419d017e08caa7802d2963870e315028"}, + {file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:412f287c55a6f54b0650bd9b6dce5aceddb95864a1a90c87af16979d37c89771"}, + {file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2c93f00dcba2eea70af2be5f11a830a742fe6b579a1d4e00f47760ef13be247a"}, + {file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f117e1a089d9411663a3207ba874f31be9ac8eaa5b533787024dc07aeb74f464"}, + {file = "kiwisolver-1.4.9-cp311-cp311-win_amd64.whl", hash = "sha256:be6a04e6c79819c9a8c2373317d19a96048e5a3f90bec587787e86a1153883c2"}, + {file = "kiwisolver-1.4.9-cp311-cp311-win_arm64.whl", hash = "sha256:0ae37737256ba2de764ddc12aed4956460277f00c4996d51a197e72f62f5eec7"}, + {file = "kiwisolver-1.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ac5a486ac389dddcc5bef4f365b6ae3ffff2c433324fb38dd35e3fab7c957999"}, + {file = "kiwisolver-1.4.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2ba92255faa7309d06fe44c3a4a97efe1c8d640c2a79a5ef728b685762a6fd2"}, + {file = "kiwisolver-1.4.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a2899935e724dd1074cb568ce7ac0dce28b2cd6ab539c8e001a8578eb106d14"}, + {file = "kiwisolver-1.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f6008a4919fdbc0b0097089f67a1eb55d950ed7e90ce2cc3e640abadd2757a04"}, + {file = "kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:67bb8b474b4181770f926f7b7d2f8c0248cbcb78b660fdd41a47054b28d2a752"}, + {file = "kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2327a4a30d3ee07d2fbe2e7933e8a37c591663b96ce42a00bc67461a87d7df77"}, + {file = "kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a08b491ec91b1d5053ac177afe5290adacf1f0f6307d771ccac5de30592d198"}, + {file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8fc5c867c22b828001b6a38d2eaeb88160bf5783c6cb4a5e440efc981ce286d"}, + {file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:3b3115b2581ea35bb6d1f24a4c90af37e5d9b49dcff267eeed14c3893c5b86ab"}, + {file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:858e4c22fb075920b96a291928cb7dea5644e94c0ee4fcd5af7e865655e4ccf2"}, + {file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ed0fecd28cc62c54b262e3736f8bb2512d8dcfdc2bcf08be5f47f96bf405b145"}, + {file = "kiwisolver-1.4.9-cp312-cp312-win_amd64.whl", hash = "sha256:f68208a520c3d86ea51acf688a3e3002615a7f0238002cccc17affecc86a8a54"}, + {file = "kiwisolver-1.4.9-cp312-cp312-win_arm64.whl", hash = "sha256:2c1a4f57df73965f3f14df20b80ee29e6a7930a57d2d9e8491a25f676e197c60"}, + {file = "kiwisolver-1.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5d0432ccf1c7ab14f9949eec60c5d1f924f17c037e9f8b33352fa05799359b8"}, + {file = "kiwisolver-1.4.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efb3a45b35622bb6c16dbfab491a8f5a391fe0e9d45ef32f4df85658232ca0e2"}, + {file = "kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a12cf6398e8a0a001a059747a1cbf24705e18fe413bc22de7b3d15c67cffe3f"}, + {file = "kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b67e6efbf68e077dd71d1a6b37e43e1a99d0bff1a3d51867d45ee8908b931098"}, + {file = "kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5656aa670507437af0207645273ccdfee4f14bacd7f7c67a4306d0dcaeaf6eed"}, + {file = "kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bfc08add558155345129c7803b3671cf195e6a56e7a12f3dde7c57d9b417f525"}, + {file = "kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:40092754720b174e6ccf9e845d0d8c7d8e12c3d71e7fc35f55f3813e96376f78"}, + {file = "kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:497d05f29a1300d14e02e6441cf0f5ee81c1ff5a304b0d9fb77423974684e08b"}, + {file = "kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bdd1a81a1860476eb41ac4bc1e07b3f07259e6d55bbf739b79c8aaedcf512799"}, + {file = "kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e6b93f13371d341afee3be9f7c5964e3fe61d5fa30f6a30eb49856935dfe4fc3"}, + {file = "kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d75aa530ccfaa593da12834b86a0724f58bff12706659baa9227c2ccaa06264c"}, + {file = "kiwisolver-1.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:dd0a578400839256df88c16abddf9ba14813ec5f21362e1fe65022e00c883d4d"}, + {file = "kiwisolver-1.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:d4188e73af84ca82468f09cadc5ac4db578109e52acb4518d8154698d3a87ca2"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:5a0f2724dfd4e3b3ac5a82436a8e6fd16baa7d507117e4279b660fe8ca38a3a1"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1b11d6a633e4ed84fc0ddafd4ebfd8ea49b3f25082c04ad12b8315c11d504dc1"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61874cdb0a36016354853593cffc38e56fc9ca5aa97d2c05d3dcf6922cd55a11"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:60c439763a969a6af93b4881db0eed8fadf93ee98e18cbc35bc8da868d0c4f0c"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92a2f997387a1b79a75e7803aa7ded2cfbe2823852ccf1ba3bcf613b62ae3197"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a31d512c812daea6d8b3be3b2bfcbeb091dbb09177706569bcfc6240dcf8b41c"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:52a15b0f35dad39862d376df10c5230155243a2c1a436e39eb55623ccbd68185"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a30fd6fdef1430fd9e1ba7b3398b5ee4e2887783917a687d86ba69985fb08748"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cc9617b46837c6468197b5945e196ee9ca43057bb7d9d1ae688101e4e1dddf64"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:0ab74e19f6a2b027ea4f845a78827969af45ce790e6cb3e1ebab71bdf9f215ff"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dba5ee5d3981160c28d5490f0d1b7ed730c22470ff7f6cc26cfcfaacb9896a07"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-win_arm64.whl", hash = "sha256:0749fd8f4218ad2e851e11cc4dc05c7cbc0cbc4267bdfdb31782e65aace4ee9c"}, + {file = "kiwisolver-1.4.9-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:9928fe1eb816d11ae170885a74d074f57af3a0d65777ca47e9aeb854a1fba386"}, + {file = "kiwisolver-1.4.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d0005b053977e7b43388ddec89fa567f43d4f6d5c2c0affe57de5ebf290dc552"}, + {file = "kiwisolver-1.4.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2635d352d67458b66fd0667c14cb1d4145e9560d503219034a18a87e971ce4f3"}, + {file = "kiwisolver-1.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:767c23ad1c58c9e827b649a9ab7809fd5fd9db266a9cf02b0e926ddc2c680d58"}, + {file = "kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72d0eb9fba308b8311685c2268cf7d0a0639a6cd027d8128659f72bdd8a024b4"}, + {file = "kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f68e4f3eeca8fb22cc3d731f9715a13b652795ef657a13df1ad0c7dc0e9731df"}, + {file = "kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d84cd4061ae292d8ac367b2c3fa3aad11cb8625a95d135fe93f286f914f3f5a6"}, + {file = "kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a60ea74330b91bd22a29638940d115df9dc00af5035a9a2a6ad9399ffb4ceca5"}, + {file = "kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ce6a3a4e106cf35c2d9c4fa17c05ce0b180db622736845d4315519397a77beaf"}, + {file = "kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:77937e5e2a38a7b48eef0585114fe7930346993a88060d0bf886086d2aa49ef5"}, + {file = "kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:24c175051354f4a28c5d6a31c93906dc653e2bf234e8a4bbfb964892078898ce"}, + {file = "kiwisolver-1.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:0763515d4df10edf6d06a3c19734e2566368980d21ebec439f33f9eb936c07b7"}, + {file = "kiwisolver-1.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:0e4e2bf29574a6a7b7f6cb5fa69293b9f96c928949ac4a53ba3f525dffb87f9c"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d976bbb382b202f71c67f77b0ac11244021cfa3f7dfd9e562eefcea2df711548"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2489e4e5d7ef9a1c300a5e0196e43d9c739f066ef23270607d45aba368b91f2d"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e2ea9f7ab7fbf18fffb1b5434ce7c69a07582f7acc7717720f1d69f3e806f90c"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b34e51affded8faee0dfdb705416153819d8ea9250bbbf7ea1b249bdeb5f1122"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8aacd3d4b33b772542b2e01beb50187536967b514b00003bdda7589722d2a64"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7cf974dd4e35fa315563ac99d6287a1024e4dc2077b8a7d7cd3d2fb65d283134"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:85bd218b5ecfbee8c8a82e121802dcb519a86044c9c3b2e4aef02fa05c6da370"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0856e241c2d3df4efef7c04a1e46b1936b6120c9bcf36dd216e3acd84bc4fb21"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9af39d6551f97d31a4deebeac6f45b156f9755ddc59c07b402c148f5dbb6482a"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:bb4ae2b57fc1d8cbd1cf7b1d9913803681ffa903e7488012be5b76dedf49297f"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:aedff62918805fb62d43a4aa2ecd4482c380dc76cd31bd7c8878588a61bd0369"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1fa333e8b2ce4d9660f2cda9c0e1b6bafcfb2457a9d259faa82289e73ec24891"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32"}, + {file = "kiwisolver-1.4.9-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4d1d9e582ad4d63062d34077a9a1e9f3c34088a2ec5135b1f7190c07cf366527"}, + {file = "kiwisolver-1.4.9-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:deed0c7258ceb4c44ad5ec7d9918f9f14fd05b2be86378d86cf50e63d1e7b771"}, + {file = "kiwisolver-1.4.9-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0a590506f303f512dff6b7f75fd2fd18e16943efee932008fe7140e5fa91d80e"}, + {file = "kiwisolver-1.4.9-pp310-pypy310_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e09c2279a4d01f099f52d5c4b3d9e208e91edcbd1a175c9662a8b16e000fece9"}, + {file = "kiwisolver-1.4.9-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c9e7cdf45d594ee04d5be1b24dd9d49f3d1590959b2271fb30b5ca2b262c00fb"}, + {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:720e05574713db64c356e86732c0f3c5252818d05f9df320f0ad8380641acea5"}, + {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:17680d737d5335b552994a2008fab4c851bcd7de33094a82067ef3a576ff02fa"}, + {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85b5352f94e490c028926ea567fc569c52ec79ce131dadb968d3853e809518c2"}, + {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:464415881e4801295659462c49461a24fb107c140de781d55518c4b80cb6790f"}, + {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:fb940820c63a9590d31d88b815e7a3aa5915cad3ce735ab45f0c730b39547de1"}, + {file = "kiwisolver-1.4.9.tar.gz", hash = "sha256:c3b22c26c6fd6811b0ae8363b95ca8ce4ea3c202d3d0975b2914310ceb1bcc4d"}, +] + +[[package]] +name = "linkify-it-py" +version = "2.0.3" +description = "Links recognition library with FULL unicode support." optional = false python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "linkify-it-py-2.0.3.tar.gz", hash = "sha256:68cda27e162e9215c17d786649d1da0021a451bdc436ef9e0fa0ba5234b9b048"}, + {file = "linkify_it_py-2.0.3-py3-none-any.whl", hash = "sha256:6bcbc417b0ac14323382aef5c5192c0075bf8a9d6b41820a2b66371eac6b6d79"}, +] + +[package.dependencies] +uc-micro-py = "*" + +[package.extras] +benchmark = ["pytest", "pytest-benchmark"] +dev = ["black", "flake8", "isort", "pre-commit", "pyproject-flake8"] +doc = ["myst-parser", "sphinx", "sphinx-book-theme"] +test = ["coverage", "pytest", "pytest-cov"] [[package]] -name = "Markdown" -version = "3.4.1" -description = "Python implementation of Markdown." -category = "main" +name = "markdown" +version = "3.8.2" +description = "Python implementation of John Gruber's Markdown." optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "markdown-3.8.2-py3-none-any.whl", hash = "sha256:5c83764dbd4e00bdd94d85a19b8d55ccca20fe35b2e678a1422b380324dd5f24"}, + {file = "markdown-3.8.2.tar.gz", hash = "sha256:247b9a70dd12e27f67431ce62523e675b866d254f900c4fe75ce3dda62237c45"}, +] + +[package.extras] +docs = ["mdx_gh_links (>=0.2)", "mkdocs (>=1.6)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] +testing = ["coverage", "pyyaml"] + +[[package]] +name = "markdown-it-py" +version = "4.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147"}, + {file = "markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3"}, +] [package.dependencies] -importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} +mdurl = ">=0.1,<1.0" [package.extras] -testing = ["coverage", "pyyaml"] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "markdown-it-pyrs", "mistletoe (>=1.0,<2.0)", "mistune (>=3.0,<4.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins (>=0.5.0)"] +profiling = ["gprof2dot"] +rtd = ["ipykernel", "jupyter_sphinx", "mdit-py-plugins (>=0.5.0)", "myst-parser", "pyyaml", "sphinx", "sphinx-book-theme (>=1.0,<2.0)", "sphinx-copybutton", "sphinx-design"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions", "requests"] [[package]] -name = "MarkupSafe" -version = "2.1.1" +name = "markupsafe" +version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["main", "dev"] +files = [ + {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, + {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, +] [[package]] name = "matplotlib" -version = "3.5.3" +version = "3.10.6" description = "Python plotting package" -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "matplotlib-3.10.6-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:bc7316c306d97463a9866b89d5cc217824e799fa0de346c8f68f4f3d27c8693d"}, + {file = "matplotlib-3.10.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d00932b0d160ef03f59f9c0e16d1e3ac89646f7785165ce6ad40c842db16cc2e"}, + {file = "matplotlib-3.10.6-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8fa4c43d6bfdbfec09c733bca8667de11bfa4970e8324c471f3a3632a0301c15"}, + {file = "matplotlib-3.10.6-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea117a9c1627acaa04dbf36265691921b999cbf515a015298e54e1a12c3af837"}, + {file = "matplotlib-3.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:08fc803293b4e1694ee325896030de97f74c141ccff0be886bb5915269247676"}, + {file = "matplotlib-3.10.6-cp310-cp310-win_amd64.whl", hash = "sha256:2adf92d9b7527fbfb8818e050260f0ebaa460f79d61546374ce73506c9421d09"}, + {file = "matplotlib-3.10.6-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:905b60d1cb0ee604ce65b297b61cf8be9f4e6cfecf95a3fe1c388b5266bc8f4f"}, + {file = "matplotlib-3.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7bac38d816637343e53d7185d0c66677ff30ffb131044a81898b5792c956ba76"}, + {file = "matplotlib-3.10.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:942a8de2b5bfff1de31d95722f702e2966b8a7e31f4e68f7cd963c7cd8861cf6"}, + {file = "matplotlib-3.10.6-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a3276c85370bc0dfca051ec65c5817d1e0f8f5ce1b7787528ec8ed2d524bbc2f"}, + {file = "matplotlib-3.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9df5851b219225731f564e4b9e7f2ac1e13c9e6481f941b5631a0f8e2d9387ce"}, + {file = "matplotlib-3.10.6-cp311-cp311-win_amd64.whl", hash = "sha256:abb5d9478625dd9c9eb51a06d39aae71eda749ae9b3138afb23eb38824026c7e"}, + {file = "matplotlib-3.10.6-cp311-cp311-win_arm64.whl", hash = "sha256:886f989ccfae63659183173bb3fced7fd65e9eb793c3cc21c273add368536951"}, + {file = "matplotlib-3.10.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:31ca662df6a80bd426f871105fdd69db7543e28e73a9f2afe80de7e531eb2347"}, + {file = "matplotlib-3.10.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1678bb61d897bb4ac4757b5ecfb02bfb3fddf7f808000fb81e09c510712fda75"}, + {file = "matplotlib-3.10.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:56cd2d20842f58c03d2d6e6c1f1cf5548ad6f66b91e1e48f814e4fb5abd1cb95"}, + {file = "matplotlib-3.10.6-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:662df55604a2f9a45435566d6e2660e41efe83cd94f4288dfbf1e6d1eae4b0bb"}, + {file = "matplotlib-3.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:08f141d55148cd1fc870c3387d70ca4df16dee10e909b3b038782bd4bda6ea07"}, + {file = "matplotlib-3.10.6-cp312-cp312-win_amd64.whl", hash = "sha256:590f5925c2d650b5c9d813c5b3b5fc53f2929c3f8ef463e4ecfa7e052044fb2b"}, + {file = "matplotlib-3.10.6-cp312-cp312-win_arm64.whl", hash = "sha256:f44c8d264a71609c79a78d50349e724f5d5fc3684ead7c2a473665ee63d868aa"}, + {file = "matplotlib-3.10.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:819e409653c1106c8deaf62e6de6b8611449c2cd9939acb0d7d4e57a3d95cc7a"}, + {file = "matplotlib-3.10.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:59c8ac8382fefb9cb71308dde16a7c487432f5255d8f1fd32473523abecfecdf"}, + {file = "matplotlib-3.10.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:84e82d9e0fd70c70bc55739defbd8055c54300750cbacf4740c9673a24d6933a"}, + {file = "matplotlib-3.10.6-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25f7a3eb42d6c1c56e89eacd495661fc815ffc08d9da750bca766771c0fd9110"}, + {file = "matplotlib-3.10.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f9c862d91ec0b7842920a4cfdaaec29662195301914ea54c33e01f1a28d014b2"}, + {file = "matplotlib-3.10.6-cp313-cp313-win_amd64.whl", hash = "sha256:1b53bd6337eba483e2e7d29c5ab10eee644bc3a2491ec67cc55f7b44583ffb18"}, + {file = "matplotlib-3.10.6-cp313-cp313-win_arm64.whl", hash = "sha256:cbd5eb50b7058b2892ce45c2f4e92557f395c9991f5c886d1bb74a1582e70fd6"}, + {file = "matplotlib-3.10.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:acc86dd6e0e695c095001a7fccff158c49e45e0758fdf5dcdbb0103318b59c9f"}, + {file = "matplotlib-3.10.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e228cd2ffb8f88b7d0b29e37f68ca9aaf83e33821f24a5ccc4f082dd8396bc27"}, + {file = "matplotlib-3.10.6-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:658bc91894adeab669cf4bb4a186d049948262987e80f0857216387d7435d833"}, + {file = "matplotlib-3.10.6-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8913b7474f6dd83ac444c9459c91f7f0f2859e839f41d642691b104e0af056aa"}, + {file = "matplotlib-3.10.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:091cea22e059b89f6d7d1a18e2c33a7376c26eee60e401d92a4d6726c4e12706"}, + {file = "matplotlib-3.10.6-cp313-cp313t-win_amd64.whl", hash = "sha256:491e25e02a23d7207629d942c666924a6b61e007a48177fdd231a0097b7f507e"}, + {file = "matplotlib-3.10.6-cp313-cp313t-win_arm64.whl", hash = "sha256:3d80d60d4e54cda462e2cd9a086d85cd9f20943ead92f575ce86885a43a565d5"}, + {file = "matplotlib-3.10.6-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:70aaf890ce1d0efd482df969b28a5b30ea0b891224bb315810a3940f67182899"}, + {file = "matplotlib-3.10.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1565aae810ab79cb72e402b22facfa6501365e73ebab70a0fdfb98488d2c3c0c"}, + {file = "matplotlib-3.10.6-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3b23315a01981689aa4e1a179dbf6ef9fbd17143c3eea77548c2ecfb0499438"}, + {file = "matplotlib-3.10.6-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:30fdd37edf41a4e6785f9b37969de57aea770696cb637d9946eb37470c94a453"}, + {file = "matplotlib-3.10.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:bc31e693da1c08012c764b053e702c1855378e04102238e6a5ee6a7117c53a47"}, + {file = "matplotlib-3.10.6-cp314-cp314-win_amd64.whl", hash = "sha256:05be9bdaa8b242bc6ff96330d18c52f1fc59c6fb3a4dd411d953d67e7e1baf98"}, + {file = "matplotlib-3.10.6-cp314-cp314-win_arm64.whl", hash = "sha256:f56a0d1ab05d34c628592435781d185cd99630bdfd76822cd686fb5a0aecd43a"}, + {file = "matplotlib-3.10.6-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:94f0b4cacb23763b64b5dace50d5b7bfe98710fed5f0cef5c08135a03399d98b"}, + {file = "matplotlib-3.10.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cc332891306b9fb39462673d8225d1b824c89783fee82840a709f96714f17a5c"}, + {file = "matplotlib-3.10.6-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee1d607b3fb1590deb04b69f02ea1d53ed0b0bf75b2b1a5745f269afcbd3cdd3"}, + {file = "matplotlib-3.10.6-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:376a624a218116461696b27b2bbf7a8945053e6d799f6502fc03226d077807bf"}, + {file = "matplotlib-3.10.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:83847b47f6524c34b4f2d3ce726bb0541c48c8e7692729865c3df75bfa0f495a"}, + {file = "matplotlib-3.10.6-cp314-cp314t-win_amd64.whl", hash = "sha256:c7e0518e0d223683532a07f4b512e2e0729b62674f1b3a1a69869f98e6b1c7e3"}, + {file = "matplotlib-3.10.6-cp314-cp314t-win_arm64.whl", hash = "sha256:4dd83e029f5b4801eeb87c64efd80e732452781c16a9cf7415b7b63ec8f374d7"}, + {file = "matplotlib-3.10.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:13fcd07ccf17e354398358e0307a1f53f5325dca22982556ddb9c52837b5af41"}, + {file = "matplotlib-3.10.6-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:470fc846d59d1406e34fa4c32ba371039cd12c2fe86801159a965956f2575bd1"}, + {file = "matplotlib-3.10.6-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f7173f8551b88f4ef810a94adae3128c2530e0d07529f7141be7f8d8c365f051"}, + {file = "matplotlib-3.10.6-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f2d684c3204fa62421bbf770ddfebc6b50130f9cad65531eeba19236d73bb488"}, + {file = "matplotlib-3.10.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:6f4a69196e663a41d12a728fab8751177215357906436804217d6d9cf0d4d6cf"}, + {file = "matplotlib-3.10.6-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d6ca6ef03dfd269f4ead566ec6f3fb9becf8dab146fb999022ed85ee9f6b3eb"}, + {file = "matplotlib-3.10.6.tar.gz", hash = "sha256:ec01b645840dd1996df21ee37f208cd8ba57644779fa20464010638013d3203c"}, +] [package.dependencies] +contourpy = ">=1.0.1" cycler = ">=0.10" fonttools = ">=4.22.0" -kiwisolver = ">=1.0.1" -numpy = ">=1.17" +kiwisolver = ">=1.3.1" +numpy = ">=1.23" packaging = ">=20.0" -pillow = ">=6.2.0" -pyparsing = ">=2.2.1" +pillow = ">=8" +pyparsing = ">=2.3.1" python-dateutil = ">=2.7" -setuptools_scm = ">=4,<7" + +[package.extras] +dev = ["meson-python (>=0.13.1,<0.17.0)", "pybind11 (>=2.13.2,!=2.13.3)", "setuptools (>=64)", "setuptools_scm (>=7)"] [[package]] -name = "mypi" -version = "0.0.3" -description = "An api that can automatically build and serve python packages that are hosted on github" -category = "dev" +name = "mdit-py-plugins" +version = "0.5.0" +description = "Collection of plugins for markdown-it-py" optional = false -python-versions = "*" +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "mdit_py_plugins-0.5.0-py3-none-any.whl", hash = "sha256:07a08422fc1936a5d26d146759e9155ea466e842f5ab2f7d2266dd084c8dab1f"}, + {file = "mdit_py_plugins-0.5.0.tar.gz", hash = "sha256:f4918cb50119f50446560513a8e311d574ff6aaed72606ddae6d35716fe809c6"}, +] [package.dependencies] -docopt = "0.6.1" -Flask = "0.10.1" -GitPython = "0.3.2.RC1" -semantic_version = "2.3.0" +markdown-it-py = ">=2.0.0,<5.0.0" + +[package.extras] +code-style = ["pre-commit"] +rtd = ["myst-parser", "sphinx-book-theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + +[[package]] +name = "narwhals" +version = "2.2.0" +description = "Extremely lightweight compatibility layer between dataframe libraries" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "narwhals-2.2.0-py3-none-any.whl", hash = "sha256:2b5e3d61a486fa4328c286b0c8018b3e781a964947ff725d66ba12f6d5ca3d2a"}, + {file = "narwhals-2.2.0.tar.gz", hash = "sha256:f6a34f2699acabe2c17339c104f0bec28b9f7a55fbc7f8d485d49bea72d12b8a"}, +] + +[package.extras] +cudf = ["cudf (>=24.10.0)"] +dask = ["dask[dataframe] (>=2024.8)"] +duckdb = ["duckdb (>=1.0)"] +ibis = ["ibis-framework (>=6.0.0)", "packaging", "pyarrow-hotfix", "rich"] +modin = ["modin"] +pandas = ["pandas (>=1.1.3)"] +polars = ["polars (>=0.20.4)"] +pyarrow = ["pyarrow (>=13.0.0)"] +pyspark = ["pyspark (>=3.5.0)"] +pyspark-connect = ["pyspark[connect] (>=3.5.0)"] +sqlframe = ["sqlframe (>=3.22.0)"] [[package]] name = "nodeenv" -version = "1.7.0" +version = "1.9.1" description = "Node.js virtual environment builder" -category = "dev" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" - -[package.dependencies] -setuptools = "*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] +files = [ + {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, + {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, +] [[package]] name = "numpy" -version = "1.23.3" -description = "NumPy is the fundamental package for array computing with Python." -category = "main" -optional = false -python-versions = ">=3.8" +version = "2.3.2" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.11" +groups = ["main"] +files = [ + {file = "numpy-2.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:852ae5bed3478b92f093e30f785c98e0cb62fa0a939ed057c31716e18a7a22b9"}, + {file = "numpy-2.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7a0e27186e781a69959d0230dd9909b5e26024f8da10683bd6344baea1885168"}, + {file = "numpy-2.3.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:f0a1a8476ad77a228e41619af2fa9505cf69df928e9aaa165746584ea17fed2b"}, + {file = "numpy-2.3.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cbc95b3813920145032412f7e33d12080f11dc776262df1712e1638207dde9e8"}, + {file = "numpy-2.3.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f75018be4980a7324edc5930fe39aa391d5734531b1926968605416ff58c332d"}, + {file = "numpy-2.3.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20b8200721840f5621b7bd03f8dcd78de33ec522fc40dc2641aa09537df010c3"}, + {file = "numpy-2.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f91e5c028504660d606340a084db4b216567ded1056ea2b4be4f9d10b67197f"}, + {file = "numpy-2.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fb1752a3bb9a3ad2d6b090b88a9a0ae1cd6f004ef95f75825e2f382c183b2097"}, + {file = "numpy-2.3.2-cp311-cp311-win32.whl", hash = "sha256:4ae6863868aaee2f57503c7a5052b3a2807cf7a3914475e637a0ecd366ced220"}, + {file = "numpy-2.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:240259d6564f1c65424bcd10f435145a7644a65a6811cfc3201c4a429ba79170"}, + {file = "numpy-2.3.2-cp311-cp311-win_arm64.whl", hash = "sha256:4209f874d45f921bde2cff1ffcd8a3695f545ad2ffbef6d3d3c6768162efab89"}, + {file = "numpy-2.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bc3186bea41fae9d8e90c2b4fb5f0a1f5a690682da79b92574d63f56b529080b"}, + {file = "numpy-2.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f4f0215edb189048a3c03bd5b19345bdfa7b45a7a6f72ae5945d2a28272727f"}, + {file = "numpy-2.3.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:8b1224a734cd509f70816455c3cffe13a4f599b1bf7130f913ba0e2c0b2006c0"}, + {file = "numpy-2.3.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3dcf02866b977a38ba3ec10215220609ab9667378a9e2150615673f3ffd6c73b"}, + {file = "numpy-2.3.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:572d5512df5470f50ada8d1972c5f1082d9a0b7aa5944db8084077570cf98370"}, + {file = "numpy-2.3.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8145dd6d10df13c559d1e4314df29695613575183fa2e2d11fac4c208c8a1f73"}, + {file = "numpy-2.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:103ea7063fa624af04a791c39f97070bf93b96d7af7eb23530cd087dc8dbe9dc"}, + {file = "numpy-2.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc927d7f289d14f5e037be917539620603294454130b6de200091e23d27dc9be"}, + {file = "numpy-2.3.2-cp312-cp312-win32.whl", hash = "sha256:d95f59afe7f808c103be692175008bab926b59309ade3e6d25009e9a171f7036"}, + {file = "numpy-2.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:9e196ade2400c0c737d93465327d1ae7c06c7cb8a1756121ebf54b06ca183c7f"}, + {file = "numpy-2.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:ee807923782faaf60d0d7331f5e86da7d5e3079e28b291973c545476c2b00d07"}, + {file = "numpy-2.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c8d9727f5316a256425892b043736d63e89ed15bbfe6556c5ff4d9d4448ff3b3"}, + {file = "numpy-2.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:efc81393f25f14d11c9d161e46e6ee348637c0a1e8a54bf9dedc472a3fae993b"}, + {file = "numpy-2.3.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:dd937f088a2df683cbb79dda9a772b62a3e5a8a7e76690612c2737f38c6ef1b6"}, + {file = "numpy-2.3.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:11e58218c0c46c80509186e460d79fbdc9ca1eb8d8aee39d8f2dc768eb781089"}, + {file = "numpy-2.3.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5ad4ebcb683a1f99f4f392cc522ee20a18b2bb12a2c1c42c3d48d5a1adc9d3d2"}, + {file = "numpy-2.3.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:938065908d1d869c7d75d8ec45f735a034771c6ea07088867f713d1cd3bbbe4f"}, + {file = "numpy-2.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:66459dccc65d8ec98cc7df61307b64bf9e08101f9598755d42d8ae65d9a7a6ee"}, + {file = "numpy-2.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a7af9ed2aa9ec5950daf05bb11abc4076a108bd3c7db9aa7251d5f107079b6a6"}, + {file = "numpy-2.3.2-cp313-cp313-win32.whl", hash = "sha256:906a30249315f9c8e17b085cc5f87d3f369b35fedd0051d4a84686967bdbbd0b"}, + {file = "numpy-2.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:c63d95dc9d67b676e9108fe0d2182987ccb0f11933c1e8959f42fa0da8d4fa56"}, + {file = "numpy-2.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:b05a89f2fb84d21235f93de47129dd4f11c16f64c87c33f5e284e6a3a54e43f2"}, + {file = "numpy-2.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4e6ecfeddfa83b02318f4d84acf15fbdbf9ded18e46989a15a8b6995dfbf85ab"}, + {file = "numpy-2.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:508b0eada3eded10a3b55725b40806a4b855961040180028f52580c4729916a2"}, + {file = "numpy-2.3.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:754d6755d9a7588bdc6ac47dc4ee97867271b17cee39cb87aef079574366db0a"}, + {file = "numpy-2.3.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a9f66e7d2b2d7712410d3bc5684149040ef5f19856f20277cd17ea83e5006286"}, + {file = "numpy-2.3.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de6ea4e5a65d5a90c7d286ddff2b87f3f4ad61faa3db8dabe936b34c2275b6f8"}, + {file = "numpy-2.3.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3ef07ec8cbc8fc9e369c8dcd52019510c12da4de81367d8b20bc692aa07573a"}, + {file = "numpy-2.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:27c9f90e7481275c7800dc9c24b7cc40ace3fdb970ae4d21eaff983a32f70c91"}, + {file = "numpy-2.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:07b62978075b67eee4065b166d000d457c82a1efe726cce608b9db9dd66a73a5"}, + {file = "numpy-2.3.2-cp313-cp313t-win32.whl", hash = "sha256:c771cfac34a4f2c0de8e8c97312d07d64fd8f8ed45bc9f5726a7e947270152b5"}, + {file = "numpy-2.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:72dbebb2dcc8305c431b2836bcc66af967df91be793d63a24e3d9b741374c450"}, + {file = "numpy-2.3.2-cp313-cp313t-win_arm64.whl", hash = "sha256:72c6df2267e926a6d5286b0a6d556ebe49eae261062059317837fda12ddf0c1a"}, + {file = "numpy-2.3.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:448a66d052d0cf14ce9865d159bfc403282c9bc7bb2a31b03cc18b651eca8b1a"}, + {file = "numpy-2.3.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:546aaf78e81b4081b2eba1d105c3b34064783027a06b3ab20b6eba21fb64132b"}, + {file = "numpy-2.3.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:87c930d52f45df092f7578889711a0768094debf73cfcde105e2d66954358125"}, + {file = "numpy-2.3.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:8dc082ea901a62edb8f59713c6a7e28a85daddcb67454c839de57656478f5b19"}, + {file = "numpy-2.3.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af58de8745f7fa9ca1c0c7c943616c6fe28e75d0c81f5c295810e3c83b5be92f"}, + {file = "numpy-2.3.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed5527c4cf10f16c6d0b6bee1f89958bccb0ad2522c8cadc2efd318bcd545f5"}, + {file = "numpy-2.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:095737ed986e00393ec18ec0b21b47c22889ae4b0cd2d5e88342e08b01141f58"}, + {file = "numpy-2.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5e40e80299607f597e1a8a247ff8d71d79c5b52baa11cc1cce30aa92d2da6e0"}, + {file = "numpy-2.3.2-cp314-cp314-win32.whl", hash = "sha256:7d6e390423cc1f76e1b8108c9b6889d20a7a1f59d9a60cac4a050fa734d6c1e2"}, + {file = "numpy-2.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:b9d0878b21e3918d76d2209c924ebb272340da1fb51abc00f986c258cd5e957b"}, + {file = "numpy-2.3.2-cp314-cp314-win_arm64.whl", hash = "sha256:2738534837c6a1d0c39340a190177d7d66fdf432894f469728da901f8f6dc910"}, + {file = "numpy-2.3.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:4d002ecf7c9b53240be3bb69d80f86ddbd34078bae04d87be81c1f58466f264e"}, + {file = "numpy-2.3.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:293b2192c6bcce487dbc6326de5853787f870aeb6c43f8f9c6496db5b1781e45"}, + {file = "numpy-2.3.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:0a4f2021a6da53a0d580d6ef5db29947025ae8b35b3250141805ea9a32bbe86b"}, + {file = "numpy-2.3.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:9c144440db4bf3bb6372d2c3e49834cc0ff7bb4c24975ab33e01199e645416f2"}, + {file = "numpy-2.3.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f92d6c2a8535dc4fe4419562294ff957f83a16ebdec66df0805e473ffaad8bd0"}, + {file = "numpy-2.3.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cefc2219baa48e468e3db7e706305fcd0c095534a192a08f31e98d83a7d45fb0"}, + {file = "numpy-2.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:76c3e9501ceb50b2ff3824c3589d5d1ab4ac857b0ee3f8f49629d0de55ecf7c2"}, + {file = "numpy-2.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:122bf5ed9a0221b3419672493878ba4967121514b1d7d4656a7580cd11dddcbf"}, + {file = "numpy-2.3.2-cp314-cp314t-win32.whl", hash = "sha256:6f1ae3dcb840edccc45af496f312528c15b1f79ac318169d094e85e4bb35fdf1"}, + {file = "numpy-2.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:087ffc25890d89a43536f75c5fe8770922008758e8eeeef61733957041ed2f9b"}, + {file = "numpy-2.3.2-cp314-cp314t-win_arm64.whl", hash = "sha256:092aeb3449833ea9c0bf0089d70c29ae480685dd2377ec9cdbbb620257f84631"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:14a91ebac98813a49bc6aa1a0dfc09513dcec1d97eaf31ca21a87221a1cdcb15"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:71669b5daae692189540cffc4c439468d35a3f84f0c88b078ecd94337f6cb0ec"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:69779198d9caee6e547adb933941ed7520f896fd9656834c300bdf4dd8642712"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:2c3271cc4097beb5a60f010bcc1cc204b300bb3eafb4399376418a83a1c6373c"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8446acd11fe3dc1830568c941d44449fd5cb83068e5c70bd5a470d323d448296"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa098a5ab53fa407fded5870865c6275a5cd4101cfdef8d6fafc48286a96e981"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6936aff90dda378c09bea075af0d9c675fe3a977a9d2402f95a87f440f59f619"}, + {file = "numpy-2.3.2.tar.gz", hash = "sha256:e0486a11ec30cdecb53f184d496d1c6a20786c81e55e41640270130056f8ee48"}, +] [[package]] name = "packaging" -version = "21.3" +version = "25.0" description = "Core utilities for Python packages" -category = "main" optional = false -python-versions = ">=3.6" - -[package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, + {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, +] [[package]] name = "pandas" -version = "1.4.4" +version = "2.3.2" description = "Powerful data structures for data analysis, time series, and statistics" -category = "main" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pandas-2.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52bc29a946304c360561974c6542d1dd628ddafa69134a7131fdfd6a5d7a1a35"}, + {file = "pandas-2.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:220cc5c35ffaa764dd5bb17cf42df283b5cb7fdf49e10a7b053a06c9cb48ee2b"}, + {file = "pandas-2.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42c05e15111221384019897df20c6fe893b2f697d03c811ee67ec9e0bb5a3424"}, + {file = "pandas-2.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc03acc273c5515ab69f898df99d9d4f12c4d70dbfc24c3acc6203751d0804cf"}, + {file = "pandas-2.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d25c20a03e8870f6339bcf67281b946bd20b86f1a544ebbebb87e66a8d642cba"}, + {file = "pandas-2.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21bb612d148bb5860b7eb2c10faacf1a810799245afd342cf297d7551513fbb6"}, + {file = "pandas-2.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:b62d586eb25cb8cb70a5746a378fc3194cb7f11ea77170d59f889f5dfe3cec7a"}, + {file = "pandas-2.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1333e9c299adcbb68ee89a9bb568fc3f20f9cbb419f1dd5225071e6cddb2a743"}, + {file = "pandas-2.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:76972bcbd7de8e91ad5f0ca884a9f2c477a2125354af624e022c49e5bd0dfff4"}, + {file = "pandas-2.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b98bdd7c456a05eef7cd21fd6b29e3ca243591fe531c62be94a2cc987efb5ac2"}, + {file = "pandas-2.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d81573b3f7db40d020983f78721e9bfc425f411e616ef019a10ebf597aedb2e"}, + {file = "pandas-2.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e190b738675a73b581736cc8ec71ae113d6c3768d0bd18bffa5b9a0927b0b6ea"}, + {file = "pandas-2.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c253828cb08f47488d60f43c5fc95114c771bbfff085da54bfc79cb4f9e3a372"}, + {file = "pandas-2.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:9467697b8083f9667b212633ad6aa4ab32436dcbaf4cd57325debb0ddef2012f"}, + {file = "pandas-2.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fbb977f802156e7a3f829e9d1d5398f6192375a3e2d1a9ee0803e35fe70a2b9"}, + {file = "pandas-2.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b9b52693123dd234b7c985c68b709b0b009f4521000d0525f2b95c22f15944b"}, + {file = "pandas-2.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bd281310d4f412733f319a5bc552f86d62cddc5f51d2e392c8787335c994175"}, + {file = "pandas-2.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96d31a6b4354e3b9b8a2c848af75d31da390657e3ac6f30c05c82068b9ed79b9"}, + {file = "pandas-2.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:df4df0b9d02bb873a106971bb85d448378ef14b86ba96f035f50bbd3688456b4"}, + {file = "pandas-2.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:213a5adf93d020b74327cb2c1b842884dbdd37f895f42dcc2f09d451d949f811"}, + {file = "pandas-2.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:8c13b81a9347eb8c7548f53fd9a4f08d4dfe996836543f805c987bafa03317ae"}, + {file = "pandas-2.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0c6ecbac99a354a051ef21c5307601093cb9e0f4b1855984a084bfec9302699e"}, + {file = "pandas-2.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c6f048aa0fd080d6a06cc7e7537c09b53be6642d330ac6f54a600c3ace857ee9"}, + {file = "pandas-2.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0064187b80a5be6f2f9c9d6bdde29372468751dfa89f4211a3c5871854cfbf7a"}, + {file = "pandas-2.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ac8c320bded4718b298281339c1a50fb00a6ba78cb2a63521c39bec95b0209b"}, + {file = "pandas-2.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:114c2fe4f4328cf98ce5716d1532f3ab79c5919f95a9cfee81d9140064a2e4d6"}, + {file = "pandas-2.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:48fa91c4dfb3b2b9bfdb5c24cd3567575f4e13f9636810462ffed8925352be5a"}, + {file = "pandas-2.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:12d039facec710f7ba305786837d0225a3444af7bbd9c15c32ca2d40d157ed8b"}, + {file = "pandas-2.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c624b615ce97864eb588779ed4046186f967374185c047070545253a52ab2d57"}, + {file = "pandas-2.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0cee69d583b9b128823d9514171cabb6861e09409af805b54459bd0c821a35c2"}, + {file = "pandas-2.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2319656ed81124982900b4c37f0e0c58c015af9a7bbc62342ba5ad07ace82ba9"}, + {file = "pandas-2.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b37205ad6f00d52f16b6d09f406434ba928c1a1966e2771006a9033c736d30d2"}, + {file = "pandas-2.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:837248b4fc3a9b83b9c6214699a13f069dc13510a6a6d7f9ba33145d2841a012"}, + {file = "pandas-2.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d2c3554bd31b731cd6490d94a28f3abb8dd770634a9e06eb6d2911b9827db370"}, + {file = "pandas-2.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:88080a0ff8a55eac9c84e3ff3c7665b3b5476c6fbc484775ca1910ce1c3e0b87"}, + {file = "pandas-2.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d4a558c7620340a0931828d8065688b3cc5b4c8eb674bcaf33d18ff4a6870b4a"}, + {file = "pandas-2.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45178cf09d1858a1509dc73ec261bf5b25a625a389b65be2e47b559905f0ab6a"}, + {file = "pandas-2.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77cefe00e1b210f9c76c697fedd8fdb8d3dd86563e9c8adc9fa72b90f5e9e4c2"}, + {file = "pandas-2.3.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:13bd629c653856f00c53dc495191baa59bcafbbf54860a46ecc50d3a88421a96"}, + {file = "pandas-2.3.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:36d627906fd44b5fd63c943264e11e96e923f8de77d6016dc2f667b9ad193438"}, + {file = "pandas-2.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:a9d7ec92d71a420185dec44909c32e9a362248c4ae2238234b76d5be37f208cc"}, + {file = "pandas-2.3.2.tar.gz", hash = "sha256:ab7b58f8f82706890924ccdfb5f48002b83d2b5a3845976a9fb705d36c34dcdb"}, +] [package.dependencies] -numpy = [ - {version = ">=1.18.5", markers = "platform_machine != \"aarch64\" and platform_machine != \"arm64\" and python_version < \"3.10\""}, - {version = ">=1.19.2", markers = "platform_machine == \"aarch64\" and python_version < \"3.10\""}, - {version = ">=1.20.0", markers = "platform_machine == \"arm64\" and python_version < \"3.10\""}, - {version = ">=1.21.0", markers = "python_version >= \"3.10\""}, -] -python-dateutil = ">=2.8.1" +numpy = {version = ">=1.26.0", markers = "python_version >= \"3.12\""} +python-dateutil = ">=2.8.2" pytz = ">=2020.1" +tzdata = ">=2022.7" [package.extras] -test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] +aws = ["s3fs (>=2022.11.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] +compression = ["zstandard (>=0.19.0)"] +computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] +consortium-standard = ["dataframe-api-compat (>=0.1.7)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] +feather = ["pyarrow (>=10.0.1)"] +fss = ["fsspec (>=2022.11.0)"] +gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] +hdf5 = ["tables (>=3.8.0)"] +html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] +mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=10.0.1)"] +performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] +plot = ["matplotlib (>=3.6.3)"] +postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] +pyarrow = ["pyarrow (>=10.0.1)"] +spss = ["pyreadstat (>=1.2.0)"] +sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.9.2)"] [[package]] name = "panel" -version = "0.13.1" -description = "A high level app and dashboarding solution for Python." -category = "main" +version = "1.7.5" +description = "The powerful data exploration & web app framework for Python." optional = false -python-versions = ">=3.6" +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "panel-1.7.5-py3-none-any.whl", hash = "sha256:1c3b4a335d56d5aa0cf5d6e1c3684a297e24a62cf99345c5e9eb8552837b97c3"}, + {file = "panel-1.7.5.tar.gz", hash = "sha256:8bf5041174593fdb0e8c46bef3ade334ae7e97ef64f52c8955a1d7c62b5db18d"}, +] [package.dependencies] bleach = "*" -bokeh = ">=2.4.0,<2.5.0" +bokeh = ">=3.5.0,<3.8.0" +linkify-it-py = "*" markdown = "*" -param = ">=1.12.0" -pyct = ">=0.4.4" -pyviz-comms = ">=0.7.4" +markdown-it-py = "*" +mdit-py-plugins = "*" +packaging = "*" +pandas = ">=1.2" +param = ">=2.1.0,<3.0" +pyviz-comms = ">=2.0.0" requests = "*" -setuptools = "*" -tqdm = ">=4.48.0" +tqdm = "*" typing-extensions = "*" [package.extras] -all = ["aiohttp", "altair", "channels", "codecov", "croniter", "datashader", "django (<4)", "flake8", "folium", "graphviz", "holoviews", "holoviews (>1.14.1)", "hvplot", "ipyleaflet", "ipympl", "ipython (>=7.0)", "ipyvolume", "ipywidgets", "ipywidgets-bokeh", "jupyter-bokeh (>=3.0.2)", "lxml", "matplotlib (<3.4)", "nbsite (>=0.7.2rc2)", "nbval", "networkx (>=2.5)", "notebook (>=5.4)", "pandas (>=1.3)", "parameterized", "pillow", "plotly", "plotly (>=4.0)", "pydata-sphinx-theme", "pydeck", "pygraphviz", "pyinstrument (>=4.0)", "pytest", "pytest-cov", "python-graphviz", "pyvista (<0.33)", "scikit-learn", "scipy", "sphinx-copybutton", "streamz", "twine", "vega-datasets", "vtk (==9.0.1)", "xarray"] -build = ["bleach", "bokeh (>=2.0.0)", "param (>=1.9.2)", "pyct (>=0.4.4)", "pyviz-comms (>=0.6.0)", "rfc3986 (>=1.4.0)", "setuptools (>=42)", "tqdm", "twine"] -doc = ["graphviz", "holoviews (>1.14.1)", "lxml", "matplotlib (<3.4)", "nbsite (>=0.7.2rc2)", "notebook (>=5.4)", "pillow", "plotly", "pydata-sphinx-theme", "pydeck", "python-graphviz", "sphinx-copybutton"] -examples = ["aiohttp", "altair", "channels", "croniter", "datashader", "django (<4)", "folium", "graphviz", "hvplot", "ipyleaflet", "ipympl", "ipyvolume", "ipywidgets", "ipywidgets-bokeh", "jupyter-bokeh (>=3.0.2)", "networkx (>=2.5)", "plotly (>=4.0)", "pygraphviz", "pyinstrument (>=4.0)", "pyvista (<0.33)", "scikit-learn", "streamz", "vega-datasets", "vtk (==9.0.1)", "xarray"] -recommended = ["holoviews (>1.14.1)", "matplotlib (<3.4)", "notebook (>=5.4)", "pillow", "plotly"] -tests = ["codecov", "flake8", "folium", "holoviews", "ipympl", "ipython (>=7.0)", "nbval", "pandas (>=1.3)", "parameterized", "pytest", "pytest-cov", "scipy", "twine"] +dev = ["watchfiles"] +fastapi = ["bokeh-fastapi (>=0.1.2,<0.2.0)", "fastapi[standard]"] +mypy = ["mypy", "pandas-stubs", "types-bleach", "types-croniter", "types-markdown", "types-psutil", "types-requests", "types-tqdm", "typing-extensions"] +recommended = ["holoviews (>=1.18.0)", "jupyterlab", "matplotlib", "pillow", "plotly"] +tests = ["psutil", "pytest", "pytest-asyncio", "pytest-rerunfailures", "pytest-xdist"] [[package]] name = "param" -version = "1.12.2" +version = "2.2.1" description = "Make your Python code clearer and more reliable by declaring Parameters." -category = "main" optional = false -python-versions = ">=2.7" +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "param-2.2.1-py3-none-any.whl", hash = "sha256:e3a4ca7f3d7610615129a55dbde2e90eb67d11cef70936487b0a59717dba0bdc"}, + {file = "param-2.2.1.tar.gz", hash = "sha256:ba1f7cec6455ea8ad96f641f4082759bf1057dcbe629aa79d956b25973252422"}, +] [package.extras] -all = ["aiohttp", "flake8", "graphviz", "jinja2 (<3.1)", "myst-nb (==0.12.2)", "myst-parser", "nbconvert", "nbsite (>=0.7.1)", "pandas", "panel", "pydata-sphinx-theme (<0.9.0)", "pygraphviz", "pytest", "pytest-cov", "sphinx-copybutton"] -doc = ["aiohttp", "graphviz", "jinja2 (<3.1)", "myst-nb (==0.12.2)", "myst-parser", "nbconvert", "nbsite (>=0.7.1)", "pandas", "panel", "pydata-sphinx-theme (<0.9.0)", "pygraphviz", "sphinx-copybutton"] -tests = ["flake8", "pytest", "pytest-cov"] +all = ["aiohttp", "cloudpickle", "gmpy", "ipython", "jsonschema", "nbval", "nest-asyncio", "numpy", "odfpy", "openpyxl", "pandas", "panel", "pyarrow", "pytest", "pytest-asyncio", "pytest-xdist", "tables", "xlrd"] +examples = ["aiohttp", "pandas", "panel"] +tests = ["pytest", "pytest-asyncio"] +tests-deser = ["odfpy", "openpyxl", "pyarrow", "tables", "xlrd"] +tests-examples = ["aiohttp", "nbval", "pandas", "panel", "pytest", "pytest-asyncio", "pytest-xdist"] +tests-full = ["aiohttp", "cloudpickle", "gmpy", "ipython", "jsonschema", "nbval", "nest-asyncio", "numpy", "odfpy", "openpyxl", "pandas", "panel", "pyarrow", "pytest", "pytest-asyncio", "pytest-xdist", "tables", "xlrd"] [[package]] name = "pdoc" -version = "10.0.4" +version = "15.0.4" description = "API Documentation for Python Projects" -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pdoc-15.0.4-py3-none-any.whl", hash = "sha256:f9028e85e7bb8475b054e69bde1f6d26fc4693d25d9fa1b1ce9009bec7f7a5c4"}, + {file = "pdoc-15.0.4.tar.gz", hash = "sha256:cf9680f10f5b4863381f44ef084b1903f8f356acb0d4cc6b64576ba9fb712c82"}, +] [package.dependencies] -astunparse = {version = "*", markers = "python_version < \"3.9\""} Jinja2 = ">=2.11.0" -MarkupSafe = "*" -pygments = "*" - -[package.extras] -dev = ["flake8", "hypothesis", "mypy", "pytest", "pytest-cov", "pytest-timeout", "tox"] +MarkupSafe = ">=1.1.1" +pygments = ">=2.12.0" [[package]] -name = "Pillow" -version = "9.2.0" +name = "pillow" +version = "11.3.0" description = "Python Imaging Library (Fork)" -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pillow-11.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1b9c17fd4ace828b3003dfd1e30bff24863e0eb59b535e8f80194d9cc7ecf860"}, + {file = "pillow-11.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:65dc69160114cdd0ca0f35cb434633c75e8e7fad4cf855177a05bf38678f73ad"}, + {file = "pillow-11.3.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7107195ddc914f656c7fc8e4a5e1c25f32e9236ea3ea860f257b0436011fddd0"}, + {file = "pillow-11.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc3e831b563b3114baac7ec2ee86819eb03caa1a2cef0b481a5675b59c4fe23b"}, + {file = "pillow-11.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1f182ebd2303acf8c380a54f615ec883322593320a9b00438eb842c1f37ae50"}, + {file = "pillow-11.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4445fa62e15936a028672fd48c4c11a66d641d2c05726c7ec1f8ba6a572036ae"}, + {file = "pillow-11.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:71f511f6b3b91dd543282477be45a033e4845a40278fa8dcdbfdb07109bf18f9"}, + {file = "pillow-11.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:040a5b691b0713e1f6cbe222e0f4f74cd233421e105850ae3b3c0ceda520f42e"}, + {file = "pillow-11.3.0-cp310-cp310-win32.whl", hash = "sha256:89bd777bc6624fe4115e9fac3352c79ed60f3bb18651420635f26e643e3dd1f6"}, + {file = "pillow-11.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:19d2ff547c75b8e3ff46f4d9ef969a06c30ab2d4263a9e287733aa8b2429ce8f"}, + {file = "pillow-11.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:819931d25e57b513242859ce1876c58c59dc31587847bf74cfe06b2e0cb22d2f"}, + {file = "pillow-11.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1cd110edf822773368b396281a2293aeb91c90a2db00d78ea43e7e861631b722"}, + {file = "pillow-11.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c412fddd1b77a75aa904615ebaa6001f169b26fd467b4be93aded278266b288"}, + {file = "pillow-11.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1aa4de119a0ecac0a34a9c8bde33f34022e2e8f99104e47a3ca392fd60e37d"}, + {file = "pillow-11.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:91da1d88226663594e3f6b4b8c3c8d85bd504117d043740a8e0ec449087cc494"}, + {file = "pillow-11.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:643f189248837533073c405ec2f0bb250ba54598cf80e8c1e043381a60632f58"}, + {file = "pillow-11.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:106064daa23a745510dabce1d84f29137a37224831d88eb4ce94bb187b1d7e5f"}, + {file = "pillow-11.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cd8ff254faf15591e724dc7c4ddb6bf4793efcbe13802a4ae3e863cd300b493e"}, + {file = "pillow-11.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:932c754c2d51ad2b2271fd01c3d121daaa35e27efae2a616f77bf164bc0b3e94"}, + {file = "pillow-11.3.0-cp311-cp311-win32.whl", hash = "sha256:b4b8f3efc8d530a1544e5962bd6b403d5f7fe8b9e08227c6b255f98ad82b4ba0"}, + {file = "pillow-11.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:1a992e86b0dd7aeb1f053cd506508c0999d710a8f07b4c791c63843fc6a807ac"}, + {file = "pillow-11.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:30807c931ff7c095620fe04448e2c2fc673fcbb1ffe2a7da3fb39613489b1ddd"}, + {file = "pillow-11.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdae223722da47b024b867c1ea0be64e0df702c5e0a60e27daad39bf960dd1e4"}, + {file = "pillow-11.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:921bd305b10e82b4d1f5e802b6850677f965d8394203d182f078873851dada69"}, + {file = "pillow-11.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb76541cba2f958032d79d143b98a3a6b3ea87f0959bbe256c0b5e416599fd5d"}, + {file = "pillow-11.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:67172f2944ebba3d4a7b54f2e95c786a3a50c21b88456329314caaa28cda70f6"}, + {file = "pillow-11.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f07ed9f56a3b9b5f49d3661dc9607484e85c67e27f3e8be2c7d28ca032fec7"}, + {file = "pillow-11.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:676b2815362456b5b3216b4fd5bd89d362100dc6f4945154ff172e206a22c024"}, + {file = "pillow-11.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3e184b2f26ff146363dd07bde8b711833d7b0202e27d13540bfe2e35a323a809"}, + {file = "pillow-11.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6be31e3fc9a621e071bc17bb7de63b85cbe0bfae91bb0363c893cbe67247780d"}, + {file = "pillow-11.3.0-cp312-cp312-win32.whl", hash = "sha256:7b161756381f0918e05e7cb8a371fff367e807770f8fe92ecb20d905d0e1c149"}, + {file = "pillow-11.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a6444696fce635783440b7f7a9fc24b3ad10a9ea3f0ab66c5905be1c19ccf17d"}, + {file = "pillow-11.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:2aceea54f957dd4448264f9bf40875da0415c83eb85f55069d89c0ed436e3542"}, + {file = "pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:1c627742b539bba4309df89171356fcb3cc5a9178355b2727d1b74a6cf155fbd"}, + {file = "pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:30b7c02f3899d10f13d7a48163c8969e4e653f8b43416d23d13d1bbfdc93b9f8"}, + {file = "pillow-11.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7859a4cc7c9295f5838015d8cc0a9c215b77e43d07a25e460f35cf516df8626f"}, + {file = "pillow-11.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec1ee50470b0d050984394423d96325b744d55c701a439d2bd66089bff963d3c"}, + {file = "pillow-11.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7db51d222548ccfd274e4572fdbf3e810a5e66b00608862f947b163e613b67dd"}, + {file = "pillow-11.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2d6fcc902a24ac74495df63faad1884282239265c6839a0a6416d33faedfae7e"}, + {file = "pillow-11.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0f5d8f4a08090c6d6d578351a2b91acf519a54986c055af27e7a93feae6d3f1"}, + {file = "pillow-11.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c37d8ba9411d6003bba9e518db0db0c58a680ab9fe5179f040b0463644bc9805"}, + {file = "pillow-11.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13f87d581e71d9189ab21fe0efb5a23e9f28552d5be6979e84001d3b8505abe8"}, + {file = "pillow-11.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:023f6d2d11784a465f09fd09a34b150ea4672e85fb3d05931d89f373ab14abb2"}, + {file = "pillow-11.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:45dfc51ac5975b938e9809451c51734124e73b04d0f0ac621649821a63852e7b"}, + {file = "pillow-11.3.0-cp313-cp313-win32.whl", hash = "sha256:a4d336baed65d50d37b88ca5b60c0fa9d81e3a87d4a7930d3880d1624d5b31f3"}, + {file = "pillow-11.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bce5c4fd0921f99d2e858dc4d4d64193407e1b99478bc5cacecba2311abde51"}, + {file = "pillow-11.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:1904e1264881f682f02b7f8167935cce37bc97db457f8e7849dc3a6a52b99580"}, + {file = "pillow-11.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4c834a3921375c48ee6b9624061076bc0a32a60b5532b322cc0ea64e639dd50e"}, + {file = "pillow-11.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5e05688ccef30ea69b9317a9ead994b93975104a677a36a8ed8106be9260aa6d"}, + {file = "pillow-11.3.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1019b04af07fc0163e2810167918cb5add8d74674b6267616021ab558dc98ced"}, + {file = "pillow-11.3.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f944255db153ebb2b19c51fe85dd99ef0ce494123f21b9db4877ffdfc5590c7c"}, + {file = "pillow-11.3.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f85acb69adf2aaee8b7da124efebbdb959a104db34d3a2cb0f3793dbae422a8"}, + {file = "pillow-11.3.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05f6ecbeff5005399bb48d198f098a9b4b6bdf27b8487c7f38ca16eeb070cd59"}, + {file = "pillow-11.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a7bc6e6fd0395bc052f16b1a8670859964dbd7003bd0af2ff08342eb6e442cfe"}, + {file = "pillow-11.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:83e1b0161c9d148125083a35c1c5a89db5b7054834fd4387499e06552035236c"}, + {file = "pillow-11.3.0-cp313-cp313t-win32.whl", hash = "sha256:2a3117c06b8fb646639dce83694f2f9eac405472713fcb1ae887469c0d4f6788"}, + {file = "pillow-11.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:857844335c95bea93fb39e0fa2726b4d9d758850b34075a7e3ff4f4fa3aa3b31"}, + {file = "pillow-11.3.0-cp313-cp313t-win_arm64.whl", hash = "sha256:8797edc41f3e8536ae4b10897ee2f637235c94f27404cac7297f7b607dd0716e"}, + {file = "pillow-11.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d9da3df5f9ea2a89b81bb6087177fb1f4d1c7146d583a3fe5c672c0d94e55e12"}, + {file = "pillow-11.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0b275ff9b04df7b640c59ec5a3cb113eefd3795a8df80bac69646ef699c6981a"}, + {file = "pillow-11.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0743841cabd3dba6a83f38a92672cccbd69af56e3e91777b0ee7f4dba4385632"}, + {file = "pillow-11.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2465a69cf967b8b49ee1b96d76718cd98c4e925414ead59fdf75cf0fd07df673"}, + {file = "pillow-11.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41742638139424703b4d01665b807c6468e23e699e8e90cffefe291c5832b027"}, + {file = "pillow-11.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93efb0b4de7e340d99057415c749175e24c8864302369e05914682ba642e5d77"}, + {file = "pillow-11.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7966e38dcd0fa11ca390aed7c6f20454443581d758242023cf36fcb319b1a874"}, + {file = "pillow-11.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:98a9afa7b9007c67ed84c57c9e0ad86a6000da96eaa638e4f8abe5b65ff83f0a"}, + {file = "pillow-11.3.0-cp314-cp314-win32.whl", hash = "sha256:02a723e6bf909e7cea0dac1b0e0310be9d7650cd66222a5f1c571455c0a45214"}, + {file = "pillow-11.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:a418486160228f64dd9e9efcd132679b7a02a5f22c982c78b6fc7dab3fefb635"}, + {file = "pillow-11.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:155658efb5e044669c08896c0c44231c5e9abcaadbc5cd3648df2f7c0b96b9a6"}, + {file = "pillow-11.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:59a03cdf019efbfeeed910bf79c7c93255c3d54bc45898ac2a4140071b02b4ae"}, + {file = "pillow-11.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f8a5827f84d973d8636e9dc5764af4f0cf2318d26744b3d902931701b0d46653"}, + {file = "pillow-11.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ee92f2fd10f4adc4b43d07ec5e779932b4eb3dbfbc34790ada5a6669bc095aa6"}, + {file = "pillow-11.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c96d333dcf42d01f47b37e0979b6bd73ec91eae18614864622d9b87bbd5bbf36"}, + {file = "pillow-11.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c96f993ab8c98460cd0c001447bff6194403e8b1d7e149ade5f00594918128b"}, + {file = "pillow-11.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41342b64afeba938edb034d122b2dda5db2139b9a4af999729ba8818e0056477"}, + {file = "pillow-11.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:068d9c39a2d1b358eb9f245ce7ab1b5c3246c7c8c7d9ba58cfa5b43146c06e50"}, + {file = "pillow-11.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a1bc6ba083b145187f648b667e05a2534ecc4b9f2784c2cbe3089e44868f2b9b"}, + {file = "pillow-11.3.0-cp314-cp314t-win32.whl", hash = "sha256:118ca10c0d60b06d006be10a501fd6bbdfef559251ed31b794668ed569c87e12"}, + {file = "pillow-11.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8924748b688aa210d79883357d102cd64690e56b923a186f35a82cbc10f997db"}, + {file = "pillow-11.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:79ea0d14d3ebad43ec77ad5272e6ff9bba5b679ef73375ea760261207fa8e0aa"}, + {file = "pillow-11.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:48d254f8a4c776de343051023eb61ffe818299eeac478da55227d96e241de53f"}, + {file = "pillow-11.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7aee118e30a4cf54fdd873bd3a29de51e29105ab11f9aad8c32123f58c8f8081"}, + {file = "pillow-11.3.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:23cff760a9049c502721bdb743a7cb3e03365fafcdfc2ef9784610714166e5a4"}, + {file = "pillow-11.3.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6359a3bc43f57d5b375d1ad54a0074318a0844d11b76abccf478c37c986d3cfc"}, + {file = "pillow-11.3.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:092c80c76635f5ecb10f3f83d76716165c96f5229addbd1ec2bdbbda7d496e06"}, + {file = "pillow-11.3.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cadc9e0ea0a2431124cde7e1697106471fc4c1da01530e679b2391c37d3fbb3a"}, + {file = "pillow-11.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6a418691000f2a418c9135a7cf0d797c1bb7d9a485e61fe8e7722845b95ef978"}, + {file = "pillow-11.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:97afb3a00b65cc0804d1c7abddbf090a81eaac02768af58cbdcaaa0a931e0b6d"}, + {file = "pillow-11.3.0-cp39-cp39-win32.whl", hash = "sha256:ea944117a7974ae78059fcc1800e5d3295172bb97035c0c1d9345fca1419da71"}, + {file = "pillow-11.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:e5c5858ad8ec655450a7c7df532e9842cf8df7cc349df7225c60d5d348c8aada"}, + {file = "pillow-11.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:6abdbfd3aea42be05702a8dd98832329c167ee84400a1d1f61ab11437f1717eb"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3cee80663f29e3843b68199b9d6f4f54bd1d4a6b59bdd91bceefc51238bcb967"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b5f56c3f344f2ccaf0dd875d3e180f631dc60a51b314295a3e681fe8cf851fbe"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e67d793d180c9df62f1f40aee3accca4829d3794c95098887edc18af4b8b780c"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d000f46e2917c705e9fb93a3606ee4a819d1e3aa7a9b442f6444f07e77cf5e25"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:527b37216b6ac3a12d7838dc3bd75208ec57c1c6d11ef01902266a5a0c14fc27"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:be5463ac478b623b9dd3937afd7fb7ab3d79dd290a28e2b6df292dc75063eb8a"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:8dc70ca24c110503e16918a658b869019126ecfe03109b754c402daff12b3d9f"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7c8ec7a017ad1bd562f93dbd8505763e688d388cde6e4a010ae1486916e713e6"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9ab6ae226de48019caa8074894544af5b53a117ccb9d3b3dcb2871464c829438"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe27fb049cdcca11f11a7bfda64043c37b30e6b91f10cb5bab275806c32f6ab3"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:465b9e8844e3c3519a983d58b80be3f668e2a7a5db97f2784e7079fbc9f9822c"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5418b53c0d59b3824d05e029669efa023bbef0f3e92e75ec8428f3799487f361"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:504b6f59505f08ae014f724b6207ff6222662aab5cc9542577fb084ed0676ac7"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c84d689db21a1c397d001aa08241044aa2069e7587b398c8cc63020390b1c1b8"}, + {file = "pillow-11.3.0.tar.gz", hash = "sha256:3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523"}, +] [package.extras] -docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-issues (>=3.0.1)", "sphinx-removed-in", "sphinxext-opengraph"] -tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-autobuild", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] +test-arrow = ["pyarrow"] +tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "trove-classifiers (>=2024.10.12)"] +typing = ["typing-extensions ; python_version < \"3.10\""] +xmp = ["defusedxml"] [[package]] name = "platformdirs" -version = "2.5.2" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" +version = "4.3.8" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, + {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, +] [package.extras] -docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"] -test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.14.1)"] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.6.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, + {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, +] [package.extras] dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] +testing = ["coverage", "pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "2.20.0" +version = "4.3.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pre_commit-4.3.0-py2.py3-none-any.whl", hash = "sha256:2b0747ad7e6e967169136edffee14c16e148a778a54e4f967921aa1ebf2308d8"}, + {file = "pre_commit-4.3.0.tar.gz", hash = "sha256:499fe450cc9d42e9d58e606262795ecb64dd05438943c62b66f6a8673da30b16"}, +] [package.dependencies] cfgv = ">=2.0.0" identify = ">=1.0.0" nodeenv = ">=0.11.1" pyyaml = ">=5.1" -toml = "*" -virtualenv = ">=20.0.8" - -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[[package]] -name = "pyct" -version = "0.4.8" -description = "Python package common tasks for users (e.g. copy examples, fetch data, ...)" -category = "main" -optional = false -python-versions = ">=2.7" - -[package.dependencies] -param = ">=1.7.0" - -[package.extras] -build = ["param (>=1.7.0)", "setuptools"] -cmd = ["pyyaml", "requests"] -doc = ["nbsite", "sphinx-ioam-theme"] -tests = ["flake8", "pytest"] +virtualenv = ">=20.10.0" [[package]] -name = "Pygments" -version = "2.13.0" +name = "pygments" +version = "2.19.2" description = "Pygments is a syntax highlighting package written in Python." -category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, + {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, +] [package.extras] -plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pyparsing" -version = "3.0.9" +version = "3.2.3" description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "main" optional = false -python-versions = ">=3.6.8" +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf"}, + {file = "pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be"}, +] [package.extras] diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pytest" -version = "7.1.3" +version = "8.4.1" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7"}, + {file = "pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c"}, +] [package.dependencies] -attrs = ">=19.2.0" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -tomli = ">=1.0.0" +colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +iniconfig = ">=1" +packaging = ">=20" +pluggy = ">=1.5,<2" +pygments = ">=2.7.2" [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-cov" -version = "3.0.0" +version = "6.2.1" description = "Pytest plugin for measuring coverage." -category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5"}, + {file = "pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2"}, +] [package.dependencies] -coverage = {version = ">=5.2.1", extras = ["toml"]} -pytest = ">=4.6" +coverage = {version = ">=7.5", extras = ["toml"]} +pluggy = ">=1.2" +pytest = ">=6.2.5" [package.extras] -testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] [[package]] name = "python-dateutil" -version = "2.8.2" +version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] [package.dependencies] six = ">=1.5" [[package]] name = "pytz" -version = "2022.2.1" +version = "2025.2" description = "World timezone definitions, modern and historical" -category = "main" optional = false python-versions = "*" +groups = ["main"] +files = [ + {file = "pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00"}, + {file = "pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3"}, +] [[package]] name = "pyviz-comms" -version = "2.2.1" -description = "Bidirectional communication for the HoloViz ecosystem." -category = "main" +version = "3.0.6" +description = "A JupyterLab extension for rendering HoloViz content." optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "pyviz_comms-3.0.6-py3-none-any.whl", hash = "sha256:4eba6238cd4a7f4add2d11879ce55411785b7d38a7c5dba42c7a0826ca53e6c2"}, + {file = "pyviz_comms-3.0.6.tar.gz", hash = "sha256:73d66b620390d97959b2c4d8a2c0778d41fe20581be4717f01e46b8fae8c5695"}, +] [package.dependencies] param = "*" [package.extras] -all = ["flake8", "jupyter-packaging (>=0.7.9,<0.8.0)", "jupyterlab (>=3.0,<4.0)", "keyring", "pytest", "rfc3986", "setuptools (>=40.8.0,<61)", "twine"] -build = ["jupyter-packaging (>=0.7.9,<0.8.0)", "jupyterlab (>=3.0,<4.0)", "keyring", "rfc3986", "setuptools (>=40.8.0,<61)", "twine"] +all = ["flake8", "jupyterlab (>=4.0,<5.0)", "keyring", "pytest", "rfc3986", "setuptools (>=40.8.0)", "twine"] +build = ["jupyterlab (>=4.0,<5.0)", "keyring", "rfc3986", "setuptools (>=40.8.0)", "twine"] tests = ["flake8", "pytest"] [[package]] -name = "PyYAML" -version = "6.0" +name = "pyyaml" +version = "6.0.2" description = "YAML parser and emitter for Python" -category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, +] [[package]] name = "requests" -version = "2.28.1" +version = "2.32.5" description = "Python HTTP for Humans." -category = "main" optional = false -python-versions = ">=3.7, <4" +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"}, + {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"}, +] [package.dependencies] certifi = ">=2017.4.17" -charset-normalizer = ">=2,<3" +charset_normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" +urllib3 = ">=1.21.1,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "semantic-version" -version = "2.3.0" -description = "A library implementing the 'SemVer' scheme." -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "setuptools" -version = "65.3.0" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mock", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - -[[package]] -name = "setuptools-scm" -version = "6.4.2" -description = "the blessed package to manage your versions by scm tags" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -packaging = ">=20.0" -setuptools = "*" -tomli = ">=1.0.0" - -[package.extras] -test = ["pytest (>=6.2)", "virtualenv (>20)"] -toml = ["setuptools (>=42)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" description = "Python 2 and 3 compatibility utilities" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" - -[[package]] -name = "smmap" -version = "5.0.0" -description = "A pure Python implementation of a sliding window memory map manager" -category = "dev" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -category = "dev" optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] +files = [ + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, +] [[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -category = "main" +name = "sniffio" +version = "1.3.1" +description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, +] [[package]] name = "tornado" -version = "6.2" +version = "6.5.2" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -category = "main" optional = false -python-versions = ">= 3.7" +python-versions = ">=3.9" +groups = ["main"] +markers = "sys_platform != \"emscripten\"" +files = [ + {file = "tornado-6.5.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:2436822940d37cde62771cff8774f4f00b3c8024fe482e16ca8387b8a2724db6"}, + {file = "tornado-6.5.2-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:583a52c7aa94ee046854ba81d9ebb6c81ec0fd30386d96f7640c96dad45a03ef"}, + {file = "tornado-6.5.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0fe179f28d597deab2842b86ed4060deec7388f1fd9c1b4a41adf8af058907e"}, + {file = "tornado-6.5.2-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b186e85d1e3536d69583d2298423744740986018e393d0321df7340e71898882"}, + {file = "tornado-6.5.2-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e792706668c87709709c18b353da1f7662317b563ff69f00bab83595940c7108"}, + {file = "tornado-6.5.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:06ceb1300fd70cb20e43b1ad8aaee0266e69e7ced38fa910ad2e03285009ce7c"}, + {file = "tornado-6.5.2-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:74db443e0f5251be86cbf37929f84d8c20c27a355dd452a5cfa2aada0d001ec4"}, + {file = "tornado-6.5.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b5e735ab2889d7ed33b32a459cac490eda71a1ba6857b0118de476ab6c366c04"}, + {file = "tornado-6.5.2-cp39-abi3-win32.whl", hash = "sha256:c6f29e94d9b37a95013bb669616352ddb82e3bfe8326fccee50583caebc8a5f0"}, + {file = "tornado-6.5.2-cp39-abi3-win_amd64.whl", hash = "sha256:e56a5af51cc30dd2cae649429af65ca2f6571da29504a07995175df14c18f35f"}, + {file = "tornado-6.5.2-cp39-abi3-win_arm64.whl", hash = "sha256:d6c33dc3672e3a1f3618eb63b7ef4683a7688e7b9e6e8f0d9aa5726360a004af"}, + {file = "tornado-6.5.2.tar.gz", hash = "sha256:ab53c8f9a0fa351e2c0741284e06c7a45da86afb544133201c5cc8578eb076a0"}, +] [[package]] name = "tqdm" -version = "4.64.1" +version = "4.67.1" description = "Fast, Extensible Progress Meter" -category = "main" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2"}, + {file = "tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2"}, +] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} [package.extras] -dev = ["py-make (>=0.1.0)", "twine", "wheel"] +dev = ["nbval", "pytest (>=6)", "pytest-asyncio (>=0.24)", "pytest-cov", "pytest-timeout"] +discord = ["requests"] notebook = ["ipywidgets (>=6)"] slack = ["slack-sdk"] telegram = ["requests"] [[package]] name = "typing-extensions" -version = "4.3.0" -description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" +version = "4.14.1" +description = "Backported and Experimental Type Hints for Python 3.9+" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76"}, + {file = "typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36"}, +] + +[[package]] +name = "tzdata" +version = "2025.2" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +groups = ["main"] +files = [ + {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"}, + {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"}, +] + +[[package]] +name = "uc-micro-py" +version = "1.0.3" +description = "Micro subset of unicode data files for linkify-it-py projects." optional = false python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "uc-micro-py-1.0.3.tar.gz", hash = "sha256:d321b92cff673ec58027c04015fcaa8bb1e005478643ff4a500882eaab88c48a"}, + {file = "uc_micro_py-1.0.3-py3-none-any.whl", hash = "sha256:db1dffff340817673d7b466ec86114a9dc0e9d4d9b5ba229d9d60e5c12600cd5"}, +] + +[package.extras] +test = ["coverage", "pytest", "pytest-cov"] [[package]] name = "urllib3" -version = "1.26.12" +version = "2.5.0" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"}, + {file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"}, +] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.16.5" +version = "20.34.0" description = "Virtual Python Environment builder" -category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "virtualenv-20.34.0-py3-none-any.whl", hash = "sha256:341f5afa7eee943e4984a9207c025feedd768baff6753cd660c857ceb3e36026"}, + {file = "virtualenv-20.34.0.tar.gz", hash = "sha256:44815b2c9dee7ed86e387b842a84f20b93f7f417f95886ca1996a72a4138eb1a"}, +] [package.dependencies] -distlib = ">=0.3.5,<1" -filelock = ">=3.4.1,<4" -platformdirs = ">=2.4,<3" +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<5" [package.extras] -docs = ["proselint (>=0.13)", "sphinx (>=5.1.1)", "sphinx-argparse (>=0.3.1)", "sphinx-rtd-theme (>=1)", "towncrier (>=21.9)"] -testing = ["coverage (>=6.2)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=21.3)", "pytest (>=7.0.1)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.6.1)", "pytest-randomly (>=3.10.3)", "pytest-timeout (>=2.1)"] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"GraalVM\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] + +[[package]] +name = "watchfiles" +version = "1.1.0" +description = "Simple, modern and high performance file watching and code reload in python." +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "watchfiles-1.1.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:27f30e14aa1c1e91cb653f03a63445739919aef84c8d2517997a83155e7a2fcc"}, + {file = "watchfiles-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3366f56c272232860ab45c77c3ca7b74ee819c8e1f6f35a7125556b198bbc6df"}, + {file = "watchfiles-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8412eacef34cae2836d891836a7fff7b754d6bcac61f6c12ba5ca9bc7e427b68"}, + {file = "watchfiles-1.1.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df670918eb7dd719642e05979fc84704af913d563fd17ed636f7c4783003fdcc"}, + {file = "watchfiles-1.1.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d7642b9bc4827b5518ebdb3b82698ada8c14c7661ddec5fe719f3e56ccd13c97"}, + {file = "watchfiles-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:199207b2d3eeaeb80ef4411875a6243d9ad8bc35b07fc42daa6b801cc39cc41c"}, + {file = "watchfiles-1.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a479466da6db5c1e8754caee6c262cd373e6e6c363172d74394f4bff3d84d7b5"}, + {file = "watchfiles-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:935f9edd022ec13e447e5723a7d14456c8af254544cefbc533f6dd276c9aa0d9"}, + {file = "watchfiles-1.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8076a5769d6bdf5f673a19d51da05fc79e2bbf25e9fe755c47595785c06a8c72"}, + {file = "watchfiles-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:86b1e28d4c37e89220e924305cd9f82866bb0ace666943a6e4196c5df4d58dcc"}, + {file = "watchfiles-1.1.0-cp310-cp310-win32.whl", hash = "sha256:d1caf40c1c657b27858f9774d5c0e232089bca9cb8ee17ce7478c6e9264d2587"}, + {file = "watchfiles-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:a89c75a5b9bc329131115a409d0acc16e8da8dfd5867ba59f1dd66ae7ea8fa82"}, + {file = "watchfiles-1.1.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:c9649dfc57cc1f9835551deb17689e8d44666315f2e82d337b9f07bd76ae3aa2"}, + {file = "watchfiles-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:406520216186b99374cdb58bc48e34bb74535adec160c8459894884c983a149c"}, + {file = "watchfiles-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb45350fd1dc75cd68d3d72c47f5b513cb0578da716df5fba02fff31c69d5f2d"}, + {file = "watchfiles-1.1.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:11ee4444250fcbeb47459a877e5e80ed994ce8e8d20283857fc128be1715dac7"}, + {file = "watchfiles-1.1.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bda8136e6a80bdea23e5e74e09df0362744d24ffb8cd59c4a95a6ce3d142f79c"}, + {file = "watchfiles-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b915daeb2d8c1f5cee4b970f2e2c988ce6514aace3c9296e58dd64dc9aa5d575"}, + {file = "watchfiles-1.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed8fc66786de8d0376f9f913c09e963c66e90ced9aa11997f93bdb30f7c872a8"}, + {file = "watchfiles-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe4371595edf78c41ef8ac8df20df3943e13defd0efcb732b2e393b5a8a7a71f"}, + {file = "watchfiles-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b7c5f6fe273291f4d414d55b2c80d33c457b8a42677ad14b4b47ff025d0893e4"}, + {file = "watchfiles-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7738027989881e70e3723c75921f1efa45225084228788fc59ea8c6d732eb30d"}, + {file = "watchfiles-1.1.0-cp311-cp311-win32.whl", hash = "sha256:622d6b2c06be19f6e89b1d951485a232e3b59618def88dbeda575ed8f0d8dbf2"}, + {file = "watchfiles-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:48aa25e5992b61debc908a61ab4d3f216b64f44fdaa71eb082d8b2de846b7d12"}, + {file = "watchfiles-1.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:00645eb79a3faa70d9cb15c8d4187bb72970b2470e938670240c7998dad9f13a"}, + {file = "watchfiles-1.1.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9dc001c3e10de4725c749d4c2f2bdc6ae24de5a88a339c4bce32300a31ede179"}, + {file = "watchfiles-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d9ba68ec283153dead62cbe81872d28e053745f12335d037de9cbd14bd1877f5"}, + {file = "watchfiles-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130fc497b8ee68dce163e4254d9b0356411d1490e868bd8790028bc46c5cc297"}, + {file = "watchfiles-1.1.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:50a51a90610d0845a5931a780d8e51d7bd7f309ebc25132ba975aca016b576a0"}, + {file = "watchfiles-1.1.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc44678a72ac0910bac46fa6a0de6af9ba1355669b3dfaf1ce5f05ca7a74364e"}, + {file = "watchfiles-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a543492513a93b001975ae283a51f4b67973662a375a403ae82f420d2c7205ee"}, + {file = "watchfiles-1.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ac164e20d17cc285f2b94dc31c384bc3aa3dd5e7490473b3db043dd70fbccfd"}, + {file = "watchfiles-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7590d5a455321e53857892ab8879dce62d1f4b04748769f5adf2e707afb9d4f"}, + {file = "watchfiles-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:37d3d3f7defb13f62ece99e9be912afe9dd8a0077b7c45ee5a57c74811d581a4"}, + {file = "watchfiles-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7080c4bb3efd70a07b1cc2df99a7aa51d98685be56be6038c3169199d0a1c69f"}, + {file = "watchfiles-1.1.0-cp312-cp312-win32.whl", hash = "sha256:cbcf8630ef4afb05dc30107bfa17f16c0896bb30ee48fc24bf64c1f970f3b1fd"}, + {file = "watchfiles-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:cbd949bdd87567b0ad183d7676feb98136cde5bb9025403794a4c0db28ed3a47"}, + {file = "watchfiles-1.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:0a7d40b77f07be87c6faa93d0951a0fcd8cbca1ddff60a1b65d741bac6f3a9f6"}, + {file = "watchfiles-1.1.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5007f860c7f1f8df471e4e04aaa8c43673429047d63205d1630880f7637bca30"}, + {file = "watchfiles-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:20ecc8abbd957046f1fe9562757903f5eaf57c3bce70929fda6c7711bb58074a"}, + {file = "watchfiles-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2f0498b7d2a3c072766dba3274fe22a183dbea1f99d188f1c6c72209a1063dc"}, + {file = "watchfiles-1.1.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:239736577e848678e13b201bba14e89718f5c2133dfd6b1f7846fa1b58a8532b"}, + {file = "watchfiles-1.1.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eff4b8d89f444f7e49136dc695599a591ff769300734446c0a86cba2eb2f9895"}, + {file = "watchfiles-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12b0a02a91762c08f7264e2e79542f76870c3040bbc847fb67410ab81474932a"}, + {file = "watchfiles-1.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:29e7bc2eee15cbb339c68445959108803dc14ee0c7b4eea556400131a8de462b"}, + {file = "watchfiles-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9481174d3ed982e269c090f780122fb59cee6c3796f74efe74e70f7780ed94c"}, + {file = "watchfiles-1.1.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:80f811146831c8c86ab17b640801c25dc0a88c630e855e2bef3568f30434d52b"}, + {file = "watchfiles-1.1.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:60022527e71d1d1fda67a33150ee42869042bce3d0fcc9cc49be009a9cded3fb"}, + {file = "watchfiles-1.1.0-cp313-cp313-win32.whl", hash = "sha256:32d6d4e583593cb8576e129879ea0991660b935177c0f93c6681359b3654bfa9"}, + {file = "watchfiles-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:f21af781a4a6fbad54f03c598ab620e3a77032c5878f3d780448421a6e1818c7"}, + {file = "watchfiles-1.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:5366164391873ed76bfdf618818c82084c9db7fac82b64a20c44d335eec9ced5"}, + {file = "watchfiles-1.1.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:17ab167cca6339c2b830b744eaf10803d2a5b6683be4d79d8475d88b4a8a4be1"}, + {file = "watchfiles-1.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:328dbc9bff7205c215a7807da7c18dce37da7da718e798356212d22696404339"}, + {file = "watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7208ab6e009c627b7557ce55c465c98967e8caa8b11833531fdf95799372633"}, + {file = "watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a8f6f72974a19efead54195bc9bed4d850fc047bb7aa971268fd9a8387c89011"}, + {file = "watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d181ef50923c29cf0450c3cd47e2f0557b62218c50b2ab8ce2ecaa02bd97e670"}, + {file = "watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:adb4167043d3a78280d5d05ce0ba22055c266cf8655ce942f2fb881262ff3cdf"}, + {file = "watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5701dc474b041e2934a26d31d39f90fac8a3dee2322b39f7729867f932b1d4"}, + {file = "watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b067915e3c3936966a8607f6fe5487df0c9c4afb85226613b520890049deea20"}, + {file = "watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:9c733cda03b6d636b4219625a4acb5c6ffb10803338e437fb614fef9516825ef"}, + {file = "watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:cc08ef8b90d78bfac66f0def80240b0197008e4852c9f285907377b2947ffdcb"}, + {file = "watchfiles-1.1.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:9974d2f7dc561cce3bb88dfa8eb309dab64c729de85fba32e98d75cf24b66297"}, + {file = "watchfiles-1.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c68e9f1fcb4d43798ad8814c4c1b61547b014b667216cb754e606bfade587018"}, + {file = "watchfiles-1.1.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95ab1594377effac17110e1352989bdd7bdfca9ff0e5eeccd8c69c5389b826d0"}, + {file = "watchfiles-1.1.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fba9b62da882c1be1280a7584ec4515d0a6006a94d6e5819730ec2eab60ffe12"}, + {file = "watchfiles-1.1.0-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3434e401f3ce0ed6b42569128b3d1e3af773d7ec18751b918b89cd49c14eaafb"}, + {file = "watchfiles-1.1.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa257a4d0d21fcbca5b5fcba9dca5a78011cb93c0323fb8855c6d2dfbc76eb77"}, + {file = "watchfiles-1.1.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fd1b3879a578a8ec2076c7961076df540b9af317123f84569f5a9ddee64ce92"}, + {file = "watchfiles-1.1.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62cc7a30eeb0e20ecc5f4bd113cd69dcdb745a07c68c0370cea919f373f65d9e"}, + {file = "watchfiles-1.1.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:891c69e027748b4a73847335d208e374ce54ca3c335907d381fde4e41661b13b"}, + {file = "watchfiles-1.1.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:12fe8eaffaf0faa7906895b4f8bb88264035b3f0243275e0bf24af0436b27259"}, + {file = "watchfiles-1.1.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:bfe3c517c283e484843cb2e357dd57ba009cff351edf45fb455b5fbd1f45b15f"}, + {file = "watchfiles-1.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a9ccbf1f129480ed3044f540c0fdbc4ee556f7175e5ab40fe077ff6baf286d4e"}, + {file = "watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba0e3255b0396cac3cc7bbace76404dd72b5438bf0d8e7cefa2f79a7f3649caa"}, + {file = "watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4281cd9fce9fc0a9dbf0fc1217f39bf9cf2b4d315d9626ef1d4e87b84699e7e8"}, + {file = "watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d2404af8db1329f9a3c9b79ff63e0ae7131986446901582067d9304ae8aaf7f"}, + {file = "watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e78b6ed8165996013165eeabd875c5dfc19d41b54f94b40e9fff0eb3193e5e8e"}, + {file = "watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:249590eb75ccc117f488e2fabd1bfa33c580e24b96f00658ad88e38844a040bb"}, + {file = "watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d05686b5487cfa2e2c28ff1aa370ea3e6c5accfe6435944ddea1e10d93872147"}, + {file = "watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d0e10e6f8f6dc5762adee7dece33b722282e1f59aa6a55da5d493a97282fedd8"}, + {file = "watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:af06c863f152005c7592df1d6a7009c836a247c9d8adb78fef8575a5a98699db"}, + {file = "watchfiles-1.1.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:865c8e95713744cf5ae261f3067861e9da5f1370ba91fc536431e29b418676fa"}, + {file = "watchfiles-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:42f92befc848bb7a19658f21f3e7bae80d7d005d13891c62c2cd4d4d0abb3433"}, + {file = "watchfiles-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa0cc8365ab29487eb4f9979fd41b22549853389e22d5de3f134a6796e1b05a4"}, + {file = "watchfiles-1.1.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:90ebb429e933645f3da534c89b29b665e285048973b4d2b6946526888c3eb2c7"}, + {file = "watchfiles-1.1.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c588c45da9b08ab3da81d08d7987dae6d2a3badd63acdb3e206a42dbfa7cb76f"}, + {file = "watchfiles-1.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c55b0f9f68590115c25272b06e63f0824f03d4fc7d6deed43d8ad5660cabdbf"}, + {file = "watchfiles-1.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd17a1e489f02ce9117b0de3c0b1fab1c3e2eedc82311b299ee6b6faf6c23a29"}, + {file = "watchfiles-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da71945c9ace018d8634822f16cbc2a78323ef6c876b1d34bbf5d5222fd6a72e"}, + {file = "watchfiles-1.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:51556d5004887045dba3acdd1fdf61dddea2be0a7e18048b5e853dcd37149b86"}, + {file = "watchfiles-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04e4ed5d1cd3eae68c89bcc1a485a109f39f2fd8de05f705e98af6b5f1861f1f"}, + {file = "watchfiles-1.1.0-cp39-cp39-win32.whl", hash = "sha256:c600e85f2ffd9f1035222b1a312aff85fd11ea39baff1d705b9b047aad2ce267"}, + {file = "watchfiles-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:3aba215958d88182e8d2acba0fdaf687745180974946609119953c0e112397dc"}, + {file = "watchfiles-1.1.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3a6fd40bbb50d24976eb275ccb55cd1951dfb63dbc27cae3066a6ca5f4beabd5"}, + {file = "watchfiles-1.1.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9f811079d2f9795b5d48b55a37aa7773680a5659afe34b54cc1d86590a51507d"}, + {file = "watchfiles-1.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2726d7bfd9f76158c84c10a409b77a320426540df8c35be172444394b17f7ea"}, + {file = "watchfiles-1.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df32d59cb9780f66d165a9a7a26f19df2c7d24e3bd58713108b41d0ff4f929c6"}, + {file = "watchfiles-1.1.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0ece16b563b17ab26eaa2d52230c9a7ae46cf01759621f4fbbca280e438267b3"}, + {file = "watchfiles-1.1.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:51b81e55d40c4b4aa8658427a3ee7ea847c591ae9e8b81ef94a90b668999353c"}, + {file = "watchfiles-1.1.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2bcdc54ea267fe72bfc7d83c041e4eb58d7d8dc6f578dfddb52f037ce62f432"}, + {file = "watchfiles-1.1.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:923fec6e5461c42bd7e3fd5ec37492c6f3468be0499bc0707b4bbbc16ac21792"}, + {file = "watchfiles-1.1.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7b3443f4ec3ba5aa00b0e9fa90cf31d98321cbff8b925a7c7b84161619870bc9"}, + {file = "watchfiles-1.1.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7049e52167fc75fc3cc418fc13d39a8e520cbb60ca08b47f6cedb85e181d2f2a"}, + {file = "watchfiles-1.1.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54062ef956807ba806559b3c3d52105ae1827a0d4ab47b621b31132b6b7e2866"}, + {file = "watchfiles-1.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a7bd57a1bb02f9d5c398c0c1675384e7ab1dd39da0ca50b7f09af45fa435277"}, + {file = "watchfiles-1.1.0.tar.gz", hash = "sha256:693ed7ec72cbfcee399e92c895362b6e66d63dac6b91e2c11ae03d10d503e575"}, +] + +[package.dependencies] +anyio = ">=3.0.0" [[package]] name = "webencodings" version = "0.5.1" description = "Character encoding aliases for legacy web content" -category = "main" optional = false python-versions = "*" - -[[package]] -name = "Werkzeug" -version = "2.2.2" -description = "The comprehensive WSGI web application library." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -MarkupSafe = ">=2.1.1" - -[package.extras] -watchdog = ["watchdog"] - -[[package]] -name = "wheel" -version = "0.37.1" -description = "A built-package format for Python" -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" - -[package.extras] -test = ["pytest (>=3.0.0)", "pytest-cov"] +groups = ["main"] +files = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] [[package]] name = "wordcloud" -version = "1.8.2.2" +version = "1.9.4" description = "A little word cloud generator" -category = "main" optional = false -python-versions = "*" +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "wordcloud-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:61a84e7311fce8415943edcb7b2ba65b4bfec1dc6dff8fe5a8ea76e278447fb2"}, + {file = "wordcloud-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e8752750726f31385f364823d3ef1d9c8ec829e5c07706c36beb40679945c71"}, + {file = "wordcloud-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:990dfd6dd43a1c7fa156be865eb98aba167a986b65f56cbf50e24772107fcd70"}, + {file = "wordcloud-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a70fe8999cd63aec64daa0377b720be6e5ff344963b828caeb4c2a081599a3a0"}, + {file = "wordcloud-1.9.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:37dcd5500cc2ea02950739390e89e2efa6624c2f54b5e2df1ee961fce685b2d7"}, + {file = "wordcloud-1.9.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5cc5c902dc2492b9fc0e29a1f5c688422d7e6eb9e5c0e43f0331d1c8e1341ba"}, + {file = "wordcloud-1.9.4-cp310-cp310-win32.whl", hash = "sha256:c20fbb51af2046c940b4fead4bafffc30b4191f5fb477c3af844446d8956bfd4"}, + {file = "wordcloud-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:61a153e76d73c72f5cc6c89ee80ddad70758a207c3c6b1d86be8635ec70164f1"}, + {file = "wordcloud-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:af168eeaed67a675f35b5668a7804c4d64f8e4f62a273b909eb5cc39efc4c294"}, + {file = "wordcloud-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3092bf85cb20158c8b90d78650dc0226985109ac6fe13a0086ac47b9581b62ce"}, + {file = "wordcloud-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddfb852f551681f5e33feb934505e060952b6aa98aaa48c781cdbf101f84e7cc"}, + {file = "wordcloud-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57ad8064a634a4870fcd00a9694c0a7839c6dfbac3d32522c69d5e1e9cbfd911"}, + {file = "wordcloud-1.9.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ea14858973ad8561a20a5475eb8d7ad33622bc5f27c60206fbb3e10a036cee26"}, + {file = "wordcloud-1.9.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b27759f12dd235468ff8c1df875b106b23dbf2c74aae05cdcdc3ccd8e23ea89c"}, + {file = "wordcloud-1.9.4-cp311-cp311-win32.whl", hash = "sha256:0ac3d87627022fb8cce17297298be96c91185edd55ecf8906f89f981b55974f0"}, + {file = "wordcloud-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:85368249df056527f1b64e80e68636abb61f0f6bd2d1c430894d2af1feea7f73"}, + {file = "wordcloud-1.9.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3910494ce5acb27731fd5678d146e8aa8f588d5fdb455810c817ff4b84ee0f67"}, + {file = "wordcloud-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b1c29a0089ee90778700cc96305fa830a6a5bbb342eaaa59d6ac8d37a9b232f"}, + {file = "wordcloud-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f369ae7bef16341c2bb208e658d5e4c56517046eb6176f89ac95525eaf8ace09"}, + {file = "wordcloud-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9ec6ffba61ca20123e7c09103a5692bbc3163f75ee0bdc7893e80e0e2786ccd2"}, + {file = "wordcloud-1.9.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cdc4aac2bcce77fd91dbfe91db5a8c0cdc239e10d8954356d2ebf79a3b43646c"}, + {file = "wordcloud-1.9.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e4942fbed48a88a0c42c5b0a057651fc09d26b31be8b6c069adaaa5051836040"}, + {file = "wordcloud-1.9.4-cp312-cp312-win32.whl", hash = "sha256:96b801fe4b2aa39bb6c5e68b4a74c81fd8996dd5fb5cea31fda518dc5f77ad82"}, + {file = "wordcloud-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:360977705d0808a1795fcbe98afb5dc4833cb4bb8e421cbb10e93ef0bce816ff"}, + {file = "wordcloud-1.9.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:88c4c99f43b13df0e812fac0e4680cca2afd3ce16ade506812127ed7c7b9d132"}, + {file = "wordcloud-1.9.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2367ec70b2f195c278f91caf4674871ee9218eb57250e01a02b986d34e55f88e"}, + {file = "wordcloud-1.9.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6104a52936886dbc785844ab6986b5321a312238abb242ee4062c7b3fdcca7c"}, + {file = "wordcloud-1.9.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81bbe75b2725730bf5cbabfe86a5c38960e7ce1166f76ba7001964d8de50b3a7"}, + {file = "wordcloud-1.9.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a936b8e03c32cc84c99ad8f1bdaf261dfef6c44d31ca5b0c7d0df147220dbb3c"}, + {file = "wordcloud-1.9.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:046300566df97b48640bd3efd94957a56941ada98cc23f811bc3f9b6a0ac1350"}, + {file = "wordcloud-1.9.4-cp313-cp313-win32.whl", hash = "sha256:22357990a01d87579dbd38a06c2a5c7b601179c4e17517b1b8f73d25faa6a5ed"}, + {file = "wordcloud-1.9.4-cp313-cp313-win_amd64.whl", hash = "sha256:8c9a5af2fbcf029a19e827adbee58e86efe7536dca7a42380a8601113a86069b"}, + {file = "wordcloud-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:42affa75c1b033cb0a0afb674f653c4af16d51d97a0852c5770b659b903d9af5"}, + {file = "wordcloud-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0876722c35cf4d5d7717ab81ba98b946e07b0e869252248fdd9ea1fd6c977cc"}, + {file = "wordcloud-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:489079ef173fe83ccff8baffd7a3c2d5fedfd31221c25ad21b4de770ea37b49f"}, + {file = "wordcloud-1.9.4-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:3f3dc2dacca48eac9b130a8938b473db81cfbeeb1a738530a7098913941a8211"}, + {file = "wordcloud-1.9.4-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:2e509c4588ae2ce47ee5cc5cf353422e7f7ecc38f450998654ed50565c8a550d"}, + {file = "wordcloud-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:8009f53ba0c3b2d6f2b1dad83e0fb165ebcdfbd000ce62ebe0917106f51d975d"}, + {file = "wordcloud-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:30b1a59b9073eaaa4f2b0f27d5b6b6c3eb6aaa3a6e0b3dbb2220036b25b37dac"}, + {file = "wordcloud-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8a685babefe032716c1a00b7d8cec3f6bfdc1c89fd839578432fc53824a02fea"}, + {file = "wordcloud-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b78b9fb292a243cf8fcdf63b9cc1fd157ec6abbf1a6e675303668b85e948f616"}, + {file = "wordcloud-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f51ab42c00bc4782ab45701de45226a269ca0850df14e1bd63a60da73271724e"}, + {file = "wordcloud-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38ee69d9404504cf2419d60c3017af7ab9e88f4ba6cf47bc1c96b2d5e58ef513"}, + {file = "wordcloud-1.9.4-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9955223708f196c1e431ae3b86074409bc256c5868e4f50eb9c36c6f06f8b1a3"}, + {file = "wordcloud-1.9.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3585ab8f4f09f1508f2d351ed48f9b56472ae26eaf6e2d2e76e975abd715d7a2"}, + {file = "wordcloud-1.9.4-cp38-cp38-win32.whl", hash = "sha256:d7d0b89c2ada0e65d84a6ebbdd8d36876b5da1a143cce2f7dcdaff6714232d24"}, + {file = "wordcloud-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:bd7caefe91d4084c1608d816052eeb605d9a7aee0c908f3a9d7421ee6363bde0"}, + {file = "wordcloud-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e5b2f7195adef0a071dc24a568d8a7715bc5cf5d752b4560f51da3aa4467dcf8"}, + {file = "wordcloud-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:34843fa49135c4ed3739dea050696e707fd00e7335ee4ed62c33639589f90adf"}, + {file = "wordcloud-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6570cc4e48e8e951d24ef6599cd8bf7ff405fbe995ff6d596bcdfa290a6206a8"}, + {file = "wordcloud-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:17f944805a17b8343eb877c9aa1dc9e5339eb14c02dd00ec80feccea899bbf81"}, + {file = "wordcloud-1.9.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:7c1cd2a6ef876f5f9fe0255e44f131a6113f883447ed1cf8bdb86f569603bac9"}, + {file = "wordcloud-1.9.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2b129584327ba21d05869fcf9495f10f7b31a34a580c431c4942a71ce2317e79"}, + {file = "wordcloud-1.9.4-cp39-cp39-win32.whl", hash = "sha256:526dfd822600f158210a191a59cc4bdcaaa1ff05ab2aa199040d857a518b1db6"}, + {file = "wordcloud-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:ac32b851a19b7d2a9ee5e0aebc8210bf16eadc42c5c0da82e36d447552c8ec48"}, + {file = "wordcloud-1.9.4-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f733cca468eae79af83cdda1de2434f1799cefef461ed892e7679d5a4c929fa1"}, + {file = "wordcloud-1.9.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a99f96efe5983c6eed17abb8766ced713ddf18b26450da74addc91570922e62"}, + {file = "wordcloud-1.9.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80773ec6a9caa2048602bc347151e3b6e68e1d8fab148dfd0d2e7d4302ce5c01"}, + {file = "wordcloud-1.9.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ca95392bba150190cca8df4a97854b554bdeb28007f28bf4698bd7e1af91b310"}, + {file = "wordcloud-1.9.4-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:eed94b42676f4cfa9b9bdac777e3a1f046b16250216dd8ddcb583c4b6e4b1286"}, + {file = "wordcloud-1.9.4-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b38aae2ff7aa10ad00d57a5b87ed4a573ef04dbc9119d4a304349c9cb3e03b6e"}, + {file = "wordcloud-1.9.4-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3057be0d071afd57afb9be84fec767abdd78eac6396ead0f0f55c6775170945"}, + {file = "wordcloud-1.9.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:9c39351d2cffc15e3794f7afab78e9135d700f61c5b51904c55d9f3729d1a0df"}, + {file = "wordcloud-1.9.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:914745f0312d248c1a0e1f16ae7b3ce82f78924a2b050ca912d2453c62586da4"}, + {file = "wordcloud-1.9.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:885d51d20cc7b0dad2306fb76b867de20e759e005a1a6e183f3865b5e5f53985"}, + {file = "wordcloud-1.9.4-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:61fc126ed9ce8d55bf20acbdc00284f5a6da66900197a2dd7b62c5ac37585ac5"}, + {file = "wordcloud-1.9.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:c7b8536955f5026b0587ff829265392185b6b4bc923f2ed933c805fcac412b28"}, + {file = "wordcloud-1.9.4-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:6a30ed8aa50b98edb113f72ef619581c221ba3678adeeed88345263c90092561"}, + {file = "wordcloud-1.9.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a62627e5b081b23a4586104d4b01d064db7b53342ae123b511326585eaf7433c"}, + {file = "wordcloud-1.9.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e137493365770f59655c7308ff76addc95ada2c6bd50ac119e4c33091e2e4e08"}, + {file = "wordcloud-1.9.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:665f8e7de3dcc1e43aa5bdd9560d56ed51026ba638a33472eede2b9051108adb"}, + {file = "wordcloud-1.9.4.tar.gz", hash = "sha256:b273d8a5ded97d3ead904046b49464dcb71119ee79df875072a4c105cadd347a"}, +] [package.dependencies] matplotlib = "*" @@ -811,666 +1950,18 @@ numpy = ">=1.6.1" pillow = "*" [[package]] -name = "yapf" -version = "0.32.0" -description = "A formatter for Python code." -category = "dev" +name = "xyzservices" +version = "2025.4.0" +description = "Source of XYZ tiles providers" optional = false -python-versions = "*" - -[[package]] -name = "zipp" -version = "3.8.1" -description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx"] -testing = ["func-timeout", "jaraco.itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "xyzservices-2025.4.0-py3-none-any.whl", hash = "sha256:8d4db9a59213ccb4ce1cf70210584f30b10795bff47627cdfb862b39ff6e10c9"}, + {file = "xyzservices-2025.4.0.tar.gz", hash = "sha256:6fe764713648fac53450fbc61a3c366cb6ae5335a1b2ae0c3796b495de3709d8"}, +] [metadata] -lock-version = "1.1" -python-versions = "^3.8" -content-hash = "5741d4a52968cf73718a09bd924b33a609374fffab673f39055d9b6f33d7657d" - -[metadata.files] -astunparse = [ - {file = "astunparse-1.6.3-py2.py3-none-any.whl", hash = "sha256:c2652417f2c8b5bb325c885ae329bdf3f86424075c4fd1a128674bc6fba4b8e8"}, - {file = "astunparse-1.6.3.tar.gz", hash = "sha256:5ad93a8456f0d084c3456d059fd9a92cce667963232cbf763eac3bc5b7940872"}, -] -attrs = [ - {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, - {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, -] -bleach = [ - {file = "bleach-5.0.1-py3-none-any.whl", hash = "sha256:085f7f33c15bd408dd9b17a4ad77c577db66d76203e5984b1bd59baeee948b2a"}, - {file = "bleach-5.0.1.tar.gz", hash = "sha256:0d03255c47eb9bd2f26aa9bb7f2107732e7e8fe195ca2f64709fcf3b0a4a085c"}, -] -bokeh = [ - {file = "bokeh-2.4.3-py3-none-any.whl", hash = "sha256:104d2f0a4ca7774ee4b11e545aa34ff76bf3e2ad6de0d33944361981b65da420"}, - {file = "bokeh-2.4.3.tar.gz", hash = "sha256:ef33801161af379665ab7a34684f2209861e3aefd5c803a21fbbb99d94874b03"}, -] -certifi = [ - {file = "certifi-2022.6.15.1-py3-none-any.whl", hash = "sha256:43dadad18a7f168740e66944e4fa82c6611848ff9056ad910f8f7a3e46ab89e0"}, - {file = "certifi-2022.6.15.1.tar.gz", hash = "sha256:cffdcd380919da6137f76633531a5817e3a9f268575c128249fb637e4f9e73fb"}, -] -cfgv = [ - {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, - {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, -] -charset-normalizer = [ - {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, - {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, -] -colorama = [ - {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, - {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, -] -coverage = [ - {file = "coverage-6.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e7b4da9bafad21ea45a714d3ea6f3e1679099e420c8741c74905b92ee9bfa7cc"}, - {file = "coverage-6.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fde17bc42e0716c94bf19d92e4c9f5a00c5feb401f5bc01101fdf2a8b7cacf60"}, - {file = "coverage-6.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdbb0d89923c80dbd435b9cf8bba0ff55585a3cdb28cbec65f376c041472c60d"}, - {file = "coverage-6.4.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:67f9346aeebea54e845d29b487eb38ec95f2ecf3558a3cffb26ee3f0dcc3e760"}, - {file = "coverage-6.4.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42c499c14efd858b98c4e03595bf914089b98400d30789511577aa44607a1b74"}, - {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c35cca192ba700979d20ac43024a82b9b32a60da2f983bec6c0f5b84aead635c"}, - {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9cc4f107009bca5a81caef2fca843dbec4215c05e917a59dec0c8db5cff1d2aa"}, - {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f444627b3664b80d078c05fe6a850dd711beeb90d26731f11d492dcbadb6973"}, - {file = "coverage-6.4.4-cp310-cp310-win32.whl", hash = "sha256:66e6df3ac4659a435677d8cd40e8eb1ac7219345d27c41145991ee9bf4b806a0"}, - {file = "coverage-6.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:35ef1f8d8a7a275aa7410d2f2c60fa6443f4a64fae9be671ec0696a68525b875"}, - {file = "coverage-6.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c1328d0c2f194ffda30a45f11058c02410e679456276bfa0bbe0b0ee87225fac"}, - {file = "coverage-6.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61b993f3998ee384935ee423c3d40894e93277f12482f6e777642a0141f55782"}, - {file = "coverage-6.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d5dd4b8e9cd0deb60e6fcc7b0647cbc1da6c33b9e786f9c79721fd303994832f"}, - {file = "coverage-6.4.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7026f5afe0d1a933685d8f2169d7c2d2e624f6255fb584ca99ccca8c0e966fd7"}, - {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9c7b9b498eb0c0d48b4c2abc0e10c2d78912203f972e0e63e3c9dc21f15abdaa"}, - {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ee2b2fb6eb4ace35805f434e0f6409444e1466a47f620d1d5763a22600f0f892"}, - {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ab066f5ab67059d1f1000b5e1aa8bbd75b6ed1fc0014559aea41a9eb66fc2ce0"}, - {file = "coverage-6.4.4-cp311-cp311-win32.whl", hash = "sha256:9d6e1f3185cbfd3d91ac77ea065d85d5215d3dfa45b191d14ddfcd952fa53796"}, - {file = "coverage-6.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:e3d3c4cc38b2882f9a15bafd30aec079582b819bec1b8afdbde8f7797008108a"}, - {file = "coverage-6.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a095aa0a996ea08b10580908e88fbaf81ecf798e923bbe64fb98d1807db3d68a"}, - {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef6f44409ab02e202b31a05dd6666797f9de2aa2b4b3534e9d450e42dea5e817"}, - {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b7101938584d67e6f45f0015b60e24a95bf8dea19836b1709a80342e01b472f"}, - {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14a32ec68d721c3d714d9b105c7acf8e0f8a4f4734c811eda75ff3718570b5e3"}, - {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6a864733b22d3081749450466ac80698fe39c91cb6849b2ef8752fd7482011f3"}, - {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:08002f9251f51afdcc5e3adf5d5d66bb490ae893d9e21359b085f0e03390a820"}, - {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a3b2752de32c455f2521a51bd3ffb53c5b3ae92736afde67ce83477f5c1dd928"}, - {file = "coverage-6.4.4-cp37-cp37m-win32.whl", hash = "sha256:f855b39e4f75abd0dfbcf74a82e84ae3fc260d523fcb3532786bcbbcb158322c"}, - {file = "coverage-6.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ee6ae6bbcac0786807295e9687169fba80cb0617852b2fa118a99667e8e6815d"}, - {file = "coverage-6.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:564cd0f5b5470094df06fab676c6d77547abfdcb09b6c29c8a97c41ad03b103c"}, - {file = "coverage-6.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cbbb0e4cd8ddcd5ef47641cfac97d8473ab6b132dd9a46bacb18872828031685"}, - {file = "coverage-6.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6113e4df2fa73b80f77663445be6d567913fb3b82a86ceb64e44ae0e4b695de1"}, - {file = "coverage-6.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d032bfc562a52318ae05047a6eb801ff31ccee172dc0d2504614e911d8fa83e"}, - {file = "coverage-6.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e431e305a1f3126477abe9a184624a85308da8edf8486a863601d58419d26ffa"}, - {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cf2afe83a53f77aec067033199797832617890e15bed42f4a1a93ea24794ae3e"}, - {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:783bc7c4ee524039ca13b6d9b4186a67f8e63d91342c713e88c1865a38d0892a"}, - {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ff934ced84054b9018665ca3967fc48e1ac99e811f6cc99ea65978e1d384454b"}, - {file = "coverage-6.4.4-cp38-cp38-win32.whl", hash = "sha256:e1fabd473566fce2cf18ea41171d92814e4ef1495e04471786cbc943b89a3781"}, - {file = "coverage-6.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:4179502f210ebed3ccfe2f78bf8e2d59e50b297b598b100d6c6e3341053066a2"}, - {file = "coverage-6.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:98c0b9e9b572893cdb0a00e66cf961a238f8d870d4e1dc8e679eb8bdc2eb1b86"}, - {file = "coverage-6.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc600f6ec19b273da1d85817eda339fb46ce9eef3e89f220055d8696e0a06908"}, - {file = "coverage-6.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a98d6bf6d4ca5c07a600c7b4e0c5350cd483c85c736c522b786be90ea5bac4f"}, - {file = "coverage-6.4.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01778769097dbd705a24e221f42be885c544bb91251747a8a3efdec6eb4788f2"}, - {file = "coverage-6.4.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfa0b97eb904255e2ab24166071b27408f1f69c8fbda58e9c0972804851e0558"}, - {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fcbe3d9a53e013f8ab88734d7e517eb2cd06b7e689bedf22c0eb68db5e4a0a19"}, - {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:15e38d853ee224e92ccc9a851457fb1e1f12d7a5df5ae44544ce7863691c7a0d"}, - {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6913dddee2deff8ab2512639c5168c3e80b3ebb0f818fed22048ee46f735351a"}, - {file = "coverage-6.4.4-cp39-cp39-win32.whl", hash = "sha256:354df19fefd03b9a13132fa6643527ef7905712109d9c1c1903f2133d3a4e145"}, - {file = "coverage-6.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:1238b08f3576201ebf41f7c20bf59baa0d05da941b123c6656e42cdb668e9827"}, - {file = "coverage-6.4.4-pp36.pp37.pp38-none-any.whl", hash = "sha256:f67cf9f406cf0d2f08a3515ce2db5b82625a7257f88aad87904674def6ddaec1"}, - {file = "coverage-6.4.4.tar.gz", hash = "sha256:e16c45b726acb780e1e6f88b286d3c10b3914ab03438f32117c4aa52d7f30d58"}, -] -cycler = [ - {file = "cycler-0.11.0-py3-none-any.whl", hash = "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3"}, - {file = "cycler-0.11.0.tar.gz", hash = "sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f"}, -] -distlib = [ - {file = "distlib-0.3.6-py2.py3-none-any.whl", hash = "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e"}, - {file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"}, -] -docopt = [ - {file = "docopt-0.6.1.tar.gz", hash = "sha256:71ad940a773fbc23be6093e9476ad57b2ecec446946a28d30127501f3b29aa35"}, -] -filelock = [ - {file = "filelock-3.8.0-py3-none-any.whl", hash = "sha256:617eb4e5eedc82fc5f47b6d61e4d11cb837c56cb4544e39081099fa17ad109d4"}, - {file = "filelock-3.8.0.tar.gz", hash = "sha256:55447caa666f2198c5b6b13a26d2084d26fa5b115c00d065664b2124680c4edc"}, -] -Flask = [ - {file = "Flask-0.10.1.tar.gz", hash = "sha256:4c83829ff83d408b5e1d4995472265411d2c414112298f2eb4b359d9e4563373"}, -] -fonttools = [ - {file = "fonttools-4.37.1-py3-none-any.whl", hash = "sha256:fff6b752e326c15756c819fe2fe7ceab69f96a1dbcfe8911d0941cdb49905007"}, - {file = "fonttools-4.37.1.zip", hash = "sha256:4606e1a88ee1f6699d182fea9511bd9a8a915d913eab4584e5226da1180fcce7"}, -] -gitdb = [ - {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"}, - {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"}, -] -GitPython = [ - {file = "GitPython-0.3.2.RC1.tar.gz", hash = "sha256:fd6786684a0d0dd7ebb961da754e3312fafe0c8e88f55ceb09858aa0af6094e0"}, -] -identify = [ - {file = "identify-2.5.5-py2.py3-none-any.whl", hash = "sha256:ef78c0d96098a3b5fe7720be4a97e73f439af7cf088ebf47b620aeaa10fadf97"}, - {file = "identify-2.5.5.tar.gz", hash = "sha256:322a5699daecf7c6fd60e68852f36f2ecbb6a36ff6e6e973e0d2bb6fca203ee6"}, -] -idna = [ - {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, - {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, -] -importlib-metadata = [ - {file = "importlib_metadata-4.12.0-py3-none-any.whl", hash = "sha256:7401a975809ea1fdc658c3aa4f78cc2195a0e019c5cbc4c06122884e9ae80c23"}, - {file = "importlib_metadata-4.12.0.tar.gz", hash = "sha256:637245b8bab2b6502fcbc752cc4b7a6f6243bb02b31c5c26156ad103d3d45670"}, -] -iniconfig = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, -] -itsdangerous = [ - {file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"}, - {file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"}, -] -Jinja2 = [ - {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, - {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, -] -kiwisolver = [ - {file = "kiwisolver-1.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2f5e60fabb7343a836360c4f0919b8cd0d6dbf08ad2ca6b9cf90bf0c76a3c4f6"}, - {file = "kiwisolver-1.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:10ee06759482c78bdb864f4109886dff7b8a56529bc1609d4f1112b93fe6423c"}, - {file = "kiwisolver-1.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c79ebe8f3676a4c6630fd3f777f3cfecf9289666c84e775a67d1d358578dc2e3"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:abbe9fa13da955feb8202e215c4018f4bb57469b1b78c7a4c5c7b93001699938"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7577c1987baa3adc4b3c62c33bd1118c3ef5c8ddef36f0f2c950ae0b199e100d"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ad8285b01b0d4695102546b342b493b3ccc6781fc28c8c6a1bb63e95d22f09"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ed58b8acf29798b036d347791141767ccf65eee7f26bde03a71c944449e53de"}, - {file = "kiwisolver-1.4.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a68b62a02953b9841730db7797422f983935aeefceb1679f0fc85cbfbd311c32"}, - {file = "kiwisolver-1.4.4-cp310-cp310-win32.whl", hash = "sha256:e92a513161077b53447160b9bd8f522edfbed4bd9759e4c18ab05d7ef7e49408"}, - {file = "kiwisolver-1.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:3fe20f63c9ecee44560d0e7f116b3a747a5d7203376abeea292ab3152334d004"}, - {file = "kiwisolver-1.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ea21f66820452a3f5d1655f8704a60d66ba1191359b96541eaf457710a5fc6"}, - {file = "kiwisolver-1.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bc9db8a3efb3e403e4ecc6cd9489ea2bac94244f80c78e27c31dcc00d2790ac2"}, - {file = "kiwisolver-1.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d5b61785a9ce44e5a4b880272baa7cf6c8f48a5180c3e81c59553ba0cb0821ca"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c2dbb44c3f7e6c4d3487b31037b1bdbf424d97687c1747ce4ff2895795c9bf69"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6295ecd49304dcf3bfbfa45d9a081c96509e95f4b9d0eb7ee4ec0530c4a96514"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bd472dbe5e136f96a4b18f295d159d7f26fd399136f5b17b08c4e5f498cd494"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf7d9fce9bcc4752ca4a1b80aabd38f6d19009ea5cbda0e0856983cf6d0023f5"}, - {file = "kiwisolver-1.4.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d6601aed50c74e0ef02f4204da1816147a6d3fbdc8b3872d263338a9052c51"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:877272cf6b4b7e94c9614f9b10140e198d2186363728ed0f701c6eee1baec1da"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:db608a6757adabb32f1cfe6066e39b3706d8c3aa69bbc353a5b61edad36a5cb4"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5853eb494c71e267912275e5586fe281444eb5e722de4e131cddf9d442615626"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f0a1dbdb5ecbef0d34eb77e56fcb3e95bbd7e50835d9782a45df81cc46949750"}, - {file = "kiwisolver-1.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:283dffbf061a4ec60391d51e6155e372a1f7a4f5b15d59c8505339454f8989e4"}, - {file = "kiwisolver-1.4.4-cp311-cp311-win32.whl", hash = "sha256:d06adcfa62a4431d404c31216f0f8ac97397d799cd53800e9d3efc2fbb3cf14e"}, - {file = "kiwisolver-1.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:e7da3fec7408813a7cebc9e4ec55afed2d0fd65c4754bc376bf03498d4e92686"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:62ac9cc684da4cf1778d07a89bf5f81b35834cb96ca523d3a7fb32509380cbf6"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41dae968a94b1ef1897cb322b39360a0812661dba7c682aa45098eb8e193dbdf"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02f79693ec433cb4b5f51694e8477ae83b3205768a6fb48ffba60549080e295b"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d0611a0a2a518464c05ddd5a3a1a0e856ccc10e67079bb17f265ad19ab3c7597"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:db5283d90da4174865d520e7366801a93777201e91e79bacbac6e6927cbceede"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1041feb4cda8708ce73bb4dcb9ce1ccf49d553bf87c3954bdfa46f0c3f77252c"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-win32.whl", hash = "sha256:a553dadda40fef6bfa1456dc4be49b113aa92c2a9a9e8711e955618cd69622e3"}, - {file = "kiwisolver-1.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:03baab2d6b4a54ddbb43bba1a3a2d1627e82d205c5cf8f4c924dc49284b87166"}, - {file = "kiwisolver-1.4.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:841293b17ad704d70c578f1f0013c890e219952169ce8a24ebc063eecf775454"}, - {file = "kiwisolver-1.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f4f270de01dd3e129a72efad823da90cc4d6aafb64c410c9033aba70db9f1ff0"}, - {file = "kiwisolver-1.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f9f39e2f049db33a908319cf46624a569b36983c7c78318e9726a4cb8923b26c"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c97528e64cb9ebeff9701e7938653a9951922f2a38bd847787d4a8e498cc83ae"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d1573129aa0fd901076e2bfb4275a35f5b7aa60fbfb984499d661ec950320b0"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ad881edc7ccb9d65b0224f4e4d05a1e85cf62d73aab798943df6d48ab0cd79a1"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b428ef021242344340460fa4c9185d0b1f66fbdbfecc6c63eff4b7c29fad429d"}, - {file = "kiwisolver-1.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2e407cb4bd5a13984a6c2c0fe1845e4e41e96f183e5e5cd4d77a857d9693494c"}, - {file = "kiwisolver-1.4.4-cp38-cp38-win32.whl", hash = "sha256:75facbe9606748f43428fc91a43edb46c7ff68889b91fa31f53b58894503a191"}, - {file = "kiwisolver-1.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:5bce61af018b0cb2055e0e72e7d65290d822d3feee430b7b8203d8a855e78766"}, - {file = "kiwisolver-1.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8c808594c88a025d4e322d5bb549282c93c8e1ba71b790f539567932722d7bd8"}, - {file = "kiwisolver-1.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0a71d85ecdd570ded8ac3d1c0f480842f49a40beb423bb8014539a9f32a5897"}, - {file = "kiwisolver-1.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b533558eae785e33e8c148a8d9921692a9fe5aa516efbdff8606e7d87b9d5824"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:efda5fc8cc1c61e4f639b8067d118e742b812c930f708e6667a5ce0d13499e29"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7c43e1e1206cd421cd92e6b3280d4385d41d7166b3ed577ac20444b6995a445f"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc8d3bd6c72b2dd9decf16ce70e20abcb3274ba01b4e1c96031e0c4067d1e7cd"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ea39b0ccc4f5d803e3337dd46bcce60b702be4d86fd0b3d7531ef10fd99a1ac"}, - {file = "kiwisolver-1.4.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:968f44fdbf6dd757d12920d63b566eeb4d5b395fd2d00d29d7ef00a00582aac9"}, - {file = "kiwisolver-1.4.4-cp39-cp39-win32.whl", hash = "sha256:da7e547706e69e45d95e116e6939488d62174e033b763ab1496b4c29b76fabea"}, - {file = "kiwisolver-1.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:ba59c92039ec0a66103b1d5fe588fa546373587a7d68f5c96f743c3396afc04b"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:91672bacaa030f92fc2f43b620d7b337fd9a5af28b0d6ed3f77afc43c4a64b5a"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:787518a6789009c159453da4d6b683f468ef7a65bbde796bcea803ccf191058d"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da152d8cdcab0e56e4f45eb08b9aea6455845ec83172092f09b0e077ece2cf7a"}, - {file = "kiwisolver-1.4.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ecb1fa0db7bf4cff9dac752abb19505a233c7f16684c5826d1f11ebd9472b871"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:28bc5b299f48150b5f822ce68624e445040595a4ac3d59251703779836eceff9"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:81e38381b782cc7e1e46c4e14cd997ee6040768101aefc8fa3c24a4cc58e98f8"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2a66fdfb34e05b705620dd567f5a03f239a088d5a3f321e7b6ac3239d22aa286"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:872b8ca05c40d309ed13eb2e582cab0c5a05e81e987ab9c521bf05ad1d5cf5cb"}, - {file = "kiwisolver-1.4.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:70e7c2e7b750585569564e2e5ca9845acfaa5da56ac46df68414f29fea97be9f"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9f85003f5dfa867e86d53fac6f7e6f30c045673fa27b603c397753bebadc3008"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e307eb9bd99801f82789b44bb45e9f541961831c7311521b13a6c85afc09767"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1792d939ec70abe76f5054d3f36ed5656021dcad1322d1cc996d4e54165cef9"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6cb459eea32a4e2cf18ba5fcece2dbdf496384413bc1bae15583f19e567f3b2"}, - {file = "kiwisolver-1.4.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36dafec3d6d6088d34e2de6b85f9d8e2324eb734162fba59d2ba9ed7a2043d5b"}, - {file = "kiwisolver-1.4.4.tar.gz", hash = "sha256:d41997519fcba4a1e46eb4a2fe31bc12f0ff957b2b81bac28db24744f333e955"}, -] -Markdown = [ - {file = "Markdown-3.4.1-py3-none-any.whl", hash = "sha256:08fb8465cffd03d10b9dd34a5c3fea908e20391a2a90b88d66362cb05beed186"}, - {file = "Markdown-3.4.1.tar.gz", hash = "sha256:3b809086bb6efad416156e00a0da66fe47618a5d6918dd688f53f40c8e4cfeff"}, -] -MarkupSafe = [ - {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"}, - {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, -] -matplotlib = [ - {file = "matplotlib-3.5.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a206a1b762b39398efea838f528b3a6d60cdb26fe9d58b48265787e29cd1d693"}, - {file = "matplotlib-3.5.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cd45a6f3e93a780185f70f05cf2a383daed13c3489233faad83e81720f7ede24"}, - {file = "matplotlib-3.5.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d62880e1f60e5a30a2a8484432bcb3a5056969dc97258d7326ad465feb7ae069"}, - {file = "matplotlib-3.5.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ab29589cef03bc88acfa3a1490359000c18186fc30374d8aa77d33cc4a51a4a"}, - {file = "matplotlib-3.5.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2886cc009f40e2984c083687251821f305d811d38e3df8ded414265e4583f0c5"}, - {file = "matplotlib-3.5.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c995f7d9568f18b5db131ab124c64e51b6820a92d10246d4f2b3f3a66698a15b"}, - {file = "matplotlib-3.5.3-cp310-cp310-win32.whl", hash = "sha256:6bb93a0492d68461bd458eba878f52fdc8ac7bdb6c4acdfe43dba684787838c2"}, - {file = "matplotlib-3.5.3-cp310-cp310-win_amd64.whl", hash = "sha256:2e6d184ebe291b9e8f7e78bbab7987d269c38ea3e062eace1fe7d898042ef804"}, - {file = "matplotlib-3.5.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6ea6aef5c4338e58d8d376068e28f80a24f54e69f09479d1c90b7172bad9f25b"}, - {file = "matplotlib-3.5.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:839d47b8ead7ad9669aaacdbc03f29656dc21f0d41a6fea2d473d856c39c8b1c"}, - {file = "matplotlib-3.5.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3b4fa56159dc3c7f9250df88f653f085068bcd32dcd38e479bba58909254af7f"}, - {file = "matplotlib-3.5.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:94ff86af56a3869a4ae26a9637a849effd7643858a1a04dd5ee50e9ab75069a7"}, - {file = "matplotlib-3.5.3-cp37-cp37m-win32.whl", hash = "sha256:35a8ad4dddebd51f94c5d24bec689ec0ec66173bf614374a1244c6241c1595e0"}, - {file = "matplotlib-3.5.3-cp37-cp37m-win_amd64.whl", hash = "sha256:43e9d3fa077bf0cc95ded13d331d2156f9973dce17c6f0c8b49ccd57af94dbd9"}, - {file = "matplotlib-3.5.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:22227c976ad4dc8c5a5057540421f0d8708c6560744ad2ad638d48e2984e1dbc"}, - {file = "matplotlib-3.5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bf618a825deb6205f015df6dfe6167a5d9b351203b03fab82043ae1d30f16511"}, - {file = "matplotlib-3.5.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9befa5954cdbc085e37d974ff6053da269474177921dd61facdad8023c4aeb51"}, - {file = "matplotlib-3.5.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3840c280ebc87a48488a46f760ea1c0c0c83fcf7abbe2e6baf99d033fd35fd8"}, - {file = "matplotlib-3.5.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dacddf5bfcec60e3f26ec5c0ae3d0274853a258b6c3fc5ef2f06a8eb23e042be"}, - {file = "matplotlib-3.5.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b428076a55fb1c084c76cb93e68006f27d247169f056412607c5c88828d08f88"}, - {file = "matplotlib-3.5.3-cp38-cp38-win32.whl", hash = "sha256:874df7505ba820e0400e7091199decf3ff1fde0583652120c50cd60d5820ca9a"}, - {file = "matplotlib-3.5.3-cp38-cp38-win_amd64.whl", hash = "sha256:b28de401d928890187c589036857a270a032961411934bdac4cf12dde3d43094"}, - {file = "matplotlib-3.5.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3211ba82b9f1518d346f6309df137b50c3dc4421b4ed4815d1d7eadc617f45a1"}, - {file = "matplotlib-3.5.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6fe807e8a22620b4cd95cfbc795ba310dc80151d43b037257250faf0bfcd82bc"}, - {file = "matplotlib-3.5.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5c096363b206a3caf43773abebdbb5a23ea13faef71d701b21a9c27fdcef72f4"}, - {file = "matplotlib-3.5.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcdfcb0f976e1bac6721d7d457c17be23cf7501f977b6a38f9d38a3762841f7"}, - {file = "matplotlib-3.5.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1e64ac9be9da6bfff0a732e62116484b93b02a0b4d4b19934fb4f8e7ad26ad6a"}, - {file = "matplotlib-3.5.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:73dd93dc35c85dece610cca8358003bf0760d7986f70b223e2306b4ea6d1406b"}, - {file = "matplotlib-3.5.3-cp39-cp39-win32.whl", hash = "sha256:879c7e5fce4939c6aa04581dfe08d57eb6102a71f2e202e3314d5fbc072fd5a0"}, - {file = "matplotlib-3.5.3-cp39-cp39-win_amd64.whl", hash = "sha256:ab8d26f07fe64f6f6736d635cce7bfd7f625320490ed5bfc347f2cdb4fae0e56"}, - {file = "matplotlib-3.5.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:99482b83ebf4eb6d5fc6813d7aacdefdd480f0d9c0b52dcf9f1cc3b2c4b3361a"}, - {file = "matplotlib-3.5.3-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f814504e459c68118bf2246a530ed953ebd18213dc20e3da524174d84ed010b2"}, - {file = "matplotlib-3.5.3-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:57f1b4e69f438a99bb64d7f2c340db1b096b41ebaa515cf61ea72624279220ce"}, - {file = "matplotlib-3.5.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:d2484b350bf3d32cae43f85dcfc89b3ed7bd2bcd781ef351f93eb6fb2cc483f9"}, - {file = "matplotlib-3.5.3.tar.gz", hash = "sha256:339cac48b80ddbc8bfd05daae0a3a73414651a8596904c2a881cfd1edb65f26c"}, -] -mypi = [ - {file = "mypi-0.0.3.tar.gz", hash = "sha256:4f30dabdd0bb74124694d56354d45b6521c9de34845a1a001957ebb5398a9741"}, -] -nodeenv = [ - {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"}, - {file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"}, -] -numpy = [ - {file = "numpy-1.23.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c9f707b5bb73bf277d812ded9896f9512a43edff72712f31667d0a8c2f8e71ee"}, - {file = "numpy-1.23.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ffcf105ecdd9396e05a8e58e81faaaf34d3f9875f137c7372450baa5d77c9a54"}, - {file = "numpy-1.23.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ea3f98a0ffce3f8f57675eb9119f3f4edb81888b6874bc1953f91e0b1d4f440"}, - {file = "numpy-1.23.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:004f0efcb2fe1c0bd6ae1fcfc69cc8b6bf2407e0f18be308612007a0762b4089"}, - {file = "numpy-1.23.3-cp310-cp310-win32.whl", hash = "sha256:98dcbc02e39b1658dc4b4508442a560fe3ca5ca0d989f0df062534e5ca3a5c1a"}, - {file = "numpy-1.23.3-cp310-cp310-win_amd64.whl", hash = "sha256:39a664e3d26ea854211867d20ebcc8023257c1800ae89773cbba9f9e97bae036"}, - {file = "numpy-1.23.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1f27b5322ac4067e67c8f9378b41c746d8feac8bdd0e0ffede5324667b8a075c"}, - {file = "numpy-1.23.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ad3ec9a748a8943e6eb4358201f7e1c12ede35f510b1a2221b70af4bb64295c"}, - {file = "numpy-1.23.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdc9febce3e68b697d931941b263c59e0c74e8f18861f4064c1f712562903411"}, - {file = "numpy-1.23.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:301c00cf5e60e08e04d842fc47df641d4a181e651c7135c50dc2762ffe293dbd"}, - {file = "numpy-1.23.3-cp311-cp311-win32.whl", hash = "sha256:7cd1328e5bdf0dee621912f5833648e2daca72e3839ec1d6695e91089625f0b4"}, - {file = "numpy-1.23.3-cp311-cp311-win_amd64.whl", hash = "sha256:8355fc10fd33a5a70981a5b8a0de51d10af3688d7a9e4a34fcc8fa0d7467bb7f"}, - {file = "numpy-1.23.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc6e8da415f359b578b00bcfb1d08411c96e9a97f9e6c7adada554a0812a6cc6"}, - {file = "numpy-1.23.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:22d43376ee0acd547f3149b9ec12eec2f0ca4a6ab2f61753c5b29bb3e795ac4d"}, - {file = "numpy-1.23.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a64403f634e5ffdcd85e0b12c08f04b3080d3e840aef118721021f9b48fc1460"}, - {file = "numpy-1.23.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efd9d3abe5774404becdb0748178b48a218f1d8c44e0375475732211ea47c67e"}, - {file = "numpy-1.23.3-cp38-cp38-win32.whl", hash = "sha256:f8c02ec3c4c4fcb718fdf89a6c6f709b14949408e8cf2a2be5bfa9c49548fd85"}, - {file = "numpy-1.23.3-cp38-cp38-win_amd64.whl", hash = "sha256:e868b0389c5ccfc092031a861d4e158ea164d8b7fdbb10e3b5689b4fc6498df6"}, - {file = "numpy-1.23.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:09f6b7bdffe57fc61d869a22f506049825d707b288039d30f26a0d0d8ea05164"}, - {file = "numpy-1.23.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8c79d7cf86d049d0c5089231a5bcd31edb03555bd93d81a16870aa98c6cfb79d"}, - {file = "numpy-1.23.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5d5420053bbb3dd64c30e58f9363d7a9c27444c3648e61460c1237f9ec3fa14"}, - {file = "numpy-1.23.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5422d6a1ea9b15577a9432e26608c73a78faf0b9039437b075cf322c92e98e7"}, - {file = "numpy-1.23.3-cp39-cp39-win32.whl", hash = "sha256:c1ba66c48b19cc9c2975c0d354f24058888cdc674bebadceb3cdc9ec403fb5d1"}, - {file = "numpy-1.23.3-cp39-cp39-win_amd64.whl", hash = "sha256:78a63d2df1d947bd9d1b11d35564c2f9e4b57898aae4626638056ec1a231c40c"}, - {file = "numpy-1.23.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:17c0e467ade9bda685d5ac7f5fa729d8d3e76b23195471adae2d6a6941bd2c18"}, - {file = "numpy-1.23.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91b8d6768a75247026e951dce3b2aac79dc7e78622fc148329135ba189813584"}, - {file = "numpy-1.23.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:94c15ca4e52671a59219146ff584488907b1f9b3fc232622b47e2cf832e94fb8"}, - {file = "numpy-1.23.3.tar.gz", hash = "sha256:51bf49c0cd1d52be0a240aa66f3458afc4b95d8993d2d04f0d91fa60c10af6cd"}, -] -packaging = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, -] -pandas = [ - {file = "pandas-1.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:799e6a25932df7e6b1f8dabf63de064e2205dc309abb75956126a0453fd88e97"}, - {file = "pandas-1.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7cd1d69a387f7d5e1a5a06a87574d9ef2433847c0e78113ab51c84d3a8bcaeaa"}, - {file = "pandas-1.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:94f2ed1fd51e545ebf71da1e942fe1822ee01e10d3dd2a7276d01351333b7c6b"}, - {file = "pandas-1.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4591cadd06fbbbd16fafc2de6e840c1aaefeae3d5864b688004777ef1bbdede3"}, - {file = "pandas-1.4.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0022fe6a313df1c4869b5edc012d734c6519a6fffa3cf70930f32e6a1078e49"}, - {file = "pandas-1.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:785e878a6e6d8ddcdb8c181e600855402750052497d7fc6d6b508894f6b8830b"}, - {file = "pandas-1.4.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c4bb8b0ab9f94207d07e401d24baebfc63057246b1a5e0cd9ee50df85a656871"}, - {file = "pandas-1.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:51c424ca134fdaeac9a4acd719d1ab48046afc60943a489028f0413fdbe9ef1c"}, - {file = "pandas-1.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ce35f947202b0b99c660221d82beb91d2e6d553d55a40b30128204e3e2c63848"}, - {file = "pandas-1.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee6f1848148ed3204235967613b0a32be2d77f214e9623f554511047705c1e04"}, - {file = "pandas-1.4.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7cc960959be28d064faefc0cb2aef854d46b827c004ebea7e79b5497ed83e7d"}, - {file = "pandas-1.4.4-cp38-cp38-win32.whl", hash = "sha256:9d805bce209714b1c1fa29bfb1e42ad87e4c0a825e4b390c56a3e71593b7e8d8"}, - {file = "pandas-1.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:afbddad78a98ec4d2ce08b384b81730de1ccc975b99eb663e6dac43703f36d98"}, - {file = "pandas-1.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a08ceb59db499864c58a9bf85ab6219d527d91f14c0240cc25fa2c261032b2a7"}, - {file = "pandas-1.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0959c41004e3d2d16f39c828d6da66ebee329836a7ecee49fb777ac9ad8a7501"}, - {file = "pandas-1.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87b4194f344dcd14c0f885cecb22005329b38bda10f1aaf7b9596a00ec8a4768"}, - {file = "pandas-1.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d2a7a3c1fea668d56bd91edbd5f2732e0af8feb9d2bf8d9bfacb2dea5fa9536"}, - {file = "pandas-1.4.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a981cfabf51c318a562deb4ae7deec594c07aee7cf18b4594a92c23718ec8275"}, - {file = "pandas-1.4.4-cp39-cp39-win32.whl", hash = "sha256:050aada67a5ec6699a7879e769825b510018a95fb9ac462bb1867483d0974a97"}, - {file = "pandas-1.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:8d4d2fe2863ecddb0ba1979bdda26c8bc2ea138f5a979abe3ba80c0fa4015c91"}, - {file = "pandas-1.4.4.tar.gz", hash = "sha256:ab6c0d738617b675183e5f28db32b5148b694ad9bba0a40c3ea26d96b431db67"}, -] -panel = [ - {file = "panel-0.13.1-py2.py3-none-any.whl", hash = "sha256:d460b5d7d0147e6b1eddf8504314a2f5e0c9268ad8bedd8d784ed46351ab5b71"}, - {file = "panel-0.13.1.tar.gz", hash = "sha256:0e9008f0a851cbcffbce0273d62b5bc62644d9030cc68535c824381df52113af"}, -] -param = [ - {file = "param-1.12.2-py2.py3-none-any.whl", hash = "sha256:262bc328c49392cf8df3b773659b1b8e12ecf71377c16794fe36be7984e62a92"}, - {file = "param-1.12.2.tar.gz", hash = "sha256:f9ccc45c7f329150fc3dca517b4595859199aa08d9cda2ecdebc112bbe718c0f"}, -] -pdoc = [ - {file = "pdoc-10.0.4-py3-none-any.whl", hash = "sha256:39186fa0a12b903388fc6e8a85cbe682dc40de59ea97f2fa45ae316bdbad8d40"}, -] -Pillow = [ - {file = "Pillow-9.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:a9c9bc489f8ab30906d7a85afac4b4944a572a7432e00698a7239f44a44e6efb"}, - {file = "Pillow-9.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:510cef4a3f401c246cfd8227b300828715dd055463cdca6176c2e4036df8bd4f"}, - {file = "Pillow-9.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7888310f6214f19ab2b6df90f3f06afa3df7ef7355fc025e78a3044737fab1f5"}, - {file = "Pillow-9.2.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:831e648102c82f152e14c1a0938689dbb22480c548c8d4b8b248b3e50967b88c"}, - {file = "Pillow-9.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1cc1d2451e8a3b4bfdb9caf745b58e6c7a77d2e469159b0d527a4554d73694d1"}, - {file = "Pillow-9.2.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:136659638f61a251e8ed3b331fc6ccd124590eeff539de57c5f80ef3a9594e58"}, - {file = "Pillow-9.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:6e8c66f70fb539301e064f6478d7453e820d8a2c631da948a23384865cd95544"}, - {file = "Pillow-9.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:37ff6b522a26d0538b753f0b4e8e164fdada12db6c6f00f62145d732d8a3152e"}, - {file = "Pillow-9.2.0-cp310-cp310-win32.whl", hash = "sha256:c79698d4cd9318d9481d89a77e2d3fcaeff5486be641e60a4b49f3d2ecca4e28"}, - {file = "Pillow-9.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:254164c57bab4b459f14c64e93df11eff5ded575192c294a0c49270f22c5d93d"}, - {file = "Pillow-9.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:adabc0bce035467fb537ef3e5e74f2847c8af217ee0be0455d4fec8adc0462fc"}, - {file = "Pillow-9.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:336b9036127eab855beec9662ac3ea13a4544a523ae273cbf108b228ecac8437"}, - {file = "Pillow-9.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50dff9cc21826d2977ef2d2a205504034e3a4563ca6f5db739b0d1026658e004"}, - {file = "Pillow-9.2.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb6259196a589123d755380b65127ddc60f4c64b21fc3bb46ce3a6ea663659b0"}, - {file = "Pillow-9.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b0554af24df2bf96618dac71ddada02420f946be943b181108cac55a7a2dcd4"}, - {file = "Pillow-9.2.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:15928f824870535c85dbf949c09d6ae7d3d6ac2d6efec80f3227f73eefba741c"}, - {file = "Pillow-9.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:bdd0de2d64688ecae88dd8935012c4a72681e5df632af903a1dca8c5e7aa871a"}, - {file = "Pillow-9.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5b87da55a08acb586bad5c3aa3b86505f559b84f39035b233d5bf844b0834b1"}, - {file = "Pillow-9.2.0-cp311-cp311-win32.whl", hash = "sha256:b6d5e92df2b77665e07ddb2e4dbd6d644b78e4c0d2e9272a852627cdba0d75cf"}, - {file = "Pillow-9.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6bf088c1ce160f50ea40764f825ec9b72ed9da25346216b91361eef8ad1b8f8c"}, - {file = "Pillow-9.2.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:2c58b24e3a63efd22554c676d81b0e57f80e0a7d3a5874a7e14ce90ec40d3069"}, - {file = "Pillow-9.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eef7592281f7c174d3d6cbfbb7ee5984a671fcd77e3fc78e973d492e9bf0eb3f"}, - {file = "Pillow-9.2.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dcd7b9c7139dc8258d164b55696ecd16c04607f1cc33ba7af86613881ffe4ac8"}, - {file = "Pillow-9.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a138441e95562b3c078746a22f8fca8ff1c22c014f856278bdbdd89ca36cff1b"}, - {file = "Pillow-9.2.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:93689632949aff41199090eff5474f3990b6823404e45d66a5d44304e9cdc467"}, - {file = "Pillow-9.2.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:f3fac744f9b540148fa7715a435d2283b71f68bfb6d4aae24482a890aed18b59"}, - {file = "Pillow-9.2.0-cp37-cp37m-win32.whl", hash = "sha256:fa768eff5f9f958270b081bb33581b4b569faabf8774726b283edb06617101dc"}, - {file = "Pillow-9.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:69bd1a15d7ba3694631e00df8de65a8cb031911ca11f44929c97fe05eb9b6c1d"}, - {file = "Pillow-9.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:030e3460861488e249731c3e7ab59b07c7853838ff3b8e16aac9561bb345da14"}, - {file = "Pillow-9.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:74a04183e6e64930b667d321524e3c5361094bb4af9083db5c301db64cd341f3"}, - {file = "Pillow-9.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d33a11f601213dcd5718109c09a52c2a1c893e7461f0be2d6febc2879ec2402"}, - {file = "Pillow-9.2.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fd6f5e3c0e4697fa7eb45b6e93996299f3feee73a3175fa451f49a74d092b9f"}, - {file = "Pillow-9.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a647c0d4478b995c5e54615a2e5360ccedd2f85e70ab57fbe817ca613d5e63b8"}, - {file = "Pillow-9.2.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:4134d3f1ba5f15027ff5c04296f13328fecd46921424084516bdb1b2548e66ff"}, - {file = "Pillow-9.2.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:bc431b065722a5ad1dfb4df354fb9333b7a582a5ee39a90e6ffff688d72f27a1"}, - {file = "Pillow-9.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1536ad017a9f789430fb6b8be8bf99d2f214c76502becc196c6f2d9a75b01b76"}, - {file = "Pillow-9.2.0-cp38-cp38-win32.whl", hash = "sha256:2ad0d4df0f5ef2247e27fc790d5c9b5a0af8ade9ba340db4a73bb1a4a3e5fb4f"}, - {file = "Pillow-9.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:ec52c351b35ca269cb1f8069d610fc45c5bd38c3e91f9ab4cbbf0aebc136d9c8"}, - {file = "Pillow-9.2.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0ed2c4ef2451de908c90436d6e8092e13a43992f1860275b4d8082667fbb2ffc"}, - {file = "Pillow-9.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ad2f835e0ad81d1689f1b7e3fbac7b01bb8777d5a985c8962bedee0cc6d43da"}, - {file = "Pillow-9.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea98f633d45f7e815db648fd7ff0f19e328302ac36427343e4432c84432e7ff4"}, - {file = "Pillow-9.2.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7761afe0126d046974a01e030ae7529ed0ca6a196de3ec6937c11df0df1bc91c"}, - {file = "Pillow-9.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a54614049a18a2d6fe156e68e188da02a046a4a93cf24f373bffd977e943421"}, - {file = "Pillow-9.2.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:5aed7dde98403cd91d86a1115c78d8145c83078e864c1de1064f52e6feb61b20"}, - {file = "Pillow-9.2.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:13b725463f32df1bfeacbf3dd197fb358ae8ebcd8c5548faa75126ea425ccb60"}, - {file = "Pillow-9.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:808add66ea764ed97d44dda1ac4f2cfec4c1867d9efb16a33d158be79f32b8a4"}, - {file = "Pillow-9.2.0-cp39-cp39-win32.whl", hash = "sha256:337a74fd2f291c607d220c793a8135273c4c2ab001b03e601c36766005f36885"}, - {file = "Pillow-9.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:fac2d65901fb0fdf20363fbd345c01958a742f2dc62a8dd4495af66e3ff502a4"}, - {file = "Pillow-9.2.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ad2277b185ebce47a63f4dc6302e30f05762b688f8dc3de55dbae4651872cdf3"}, - {file = "Pillow-9.2.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c7b502bc34f6e32ba022b4a209638f9e097d7a9098104ae420eb8186217ebbb"}, - {file = "Pillow-9.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d1f14f5f691f55e1b47f824ca4fdcb4b19b4323fe43cc7bb105988cad7496be"}, - {file = "Pillow-9.2.0-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:dfe4c1fedfde4e2fbc009d5ad420647f7730d719786388b7de0999bf32c0d9fd"}, - {file = "Pillow-9.2.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:f07f1f00e22b231dd3d9b9208692042e29792d6bd4f6639415d2f23158a80013"}, - {file = "Pillow-9.2.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1802f34298f5ba11d55e5bb09c31997dc0c6aed919658dfdf0198a2fe75d5490"}, - {file = "Pillow-9.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17d4cafe22f050b46d983b71c707162d63d796a1235cdf8b9d7a112e97b15bac"}, - {file = "Pillow-9.2.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:96b5e6874431df16aee0c1ba237574cb6dff1dcb173798faa6a9d8b399a05d0e"}, - {file = "Pillow-9.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:0030fdbd926fb85844b8b92e2f9449ba89607231d3dd597a21ae72dc7fe26927"}, - {file = "Pillow-9.2.0.tar.gz", hash = "sha256:75e636fd3e0fb872693f23ccb8a5ff2cd578801251f3a4f6854c6a5d437d3c04"}, -] -platformdirs = [ - {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, - {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, -] -pluggy = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, -] -pre-commit = [ - {file = "pre_commit-2.20.0-py2.py3-none-any.whl", hash = "sha256:51a5ba7c480ae8072ecdb6933df22d2f812dc897d5fe848778116129a681aac7"}, - {file = "pre_commit-2.20.0.tar.gz", hash = "sha256:a978dac7bc9ec0bcee55c18a277d553b0f419d259dadb4b9418ff2d00eb43959"}, -] -py = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] -pyct = [ - {file = "pyct-0.4.8-py2.py3-none-any.whl", hash = "sha256:222e104d561b28cfdb56667d2ba10e5290b4466db66d0af38ab935577af85390"}, - {file = "pyct-0.4.8.tar.gz", hash = "sha256:23d7525b5a1567535c093aea4b9c33809415aa5f018dd77f6eb738b1226df6f7"}, -] -Pygments = [ - {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"}, - {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"}, -] -pyparsing = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, -] -pytest = [ - {file = "pytest-7.1.3-py3-none-any.whl", hash = "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"}, - {file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"}, -] -pytest-cov = [ - {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, - {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, -] -python-dateutil = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, -] -pytz = [ - {file = "pytz-2022.2.1-py2.py3-none-any.whl", hash = "sha256:220f481bdafa09c3955dfbdddb7b57780e9a94f5127e35456a48589b9e0c0197"}, - {file = "pytz-2022.2.1.tar.gz", hash = "sha256:cea221417204f2d1a2aa03ddae3e867921971d0d76f14d87abb4414415bbdcf5"}, -] -pyviz-comms = [ - {file = "pyviz_comms-2.2.1-py2.py3-none-any.whl", hash = "sha256:aba28430cf28b39f2605acb48f7fddf0e3025394a8286adfeb40d74b0ae0f4f9"}, - {file = "pyviz_comms-2.2.1.tar.gz", hash = "sha256:a26145b8ce43d2d934b3c6826d77b913ce105c528eb2e494c890b3e3525ddf33"}, -] -PyYAML = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, -] -requests = [ - {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, - {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, -] -semantic-version = [ - {file = "semantic_version-2.3.0.tar.gz", hash = "sha256:19723ccc0d7ac93fa5af5ce680e0ad0781350d3e17480da9655817bd52ce937c"}, -] -setuptools = [ - {file = "setuptools-65.3.0-py3-none-any.whl", hash = "sha256:2e24e0bec025f035a2e72cdd1961119f557d78ad331bb00ff82efb2ab8da8e82"}, - {file = "setuptools-65.3.0.tar.gz", hash = "sha256:7732871f4f7fa58fb6bdcaeadb0161b2bd046c85905dbaa066bdcbcc81953b57"}, -] -setuptools-scm = [ - {file = "setuptools_scm-6.4.2-py3-none-any.whl", hash = "sha256:acea13255093849de7ccb11af9e1fb8bde7067783450cee9ef7a93139bddf6d4"}, - {file = "setuptools_scm-6.4.2.tar.gz", hash = "sha256:6833ac65c6ed9711a4d5d2266f8024cfa07c533a0e55f4c12f6eff280a5a9e30"}, -] -six = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] -smmap = [ - {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, - {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, -] -toml = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] -tomli = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] -tornado = [ - {file = "tornado-6.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:20f638fd8cc85f3cbae3c732326e96addff0a15e22d80f049e00121651e82e72"}, - {file = "tornado-6.2-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:87dcafae3e884462f90c90ecc200defe5e580a7fbbb4365eda7c7c1eb809ebc9"}, - {file = "tornado-6.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba09ef14ca9893954244fd872798b4ccb2367c165946ce2dd7376aebdde8e3ac"}, - {file = "tornado-6.2-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8150f721c101abdef99073bf66d3903e292d851bee51910839831caba341a75"}, - {file = "tornado-6.2-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3a2f5999215a3a06a4fc218026cd84c61b8b2b40ac5296a6db1f1451ef04c1e"}, - {file = "tornado-6.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:5f8c52d219d4995388119af7ccaa0bcec289535747620116a58d830e7c25d8a8"}, - {file = "tornado-6.2-cp37-abi3-musllinux_1_1_i686.whl", hash = "sha256:6fdfabffd8dfcb6cf887428849d30cf19a3ea34c2c248461e1f7d718ad30b66b"}, - {file = "tornado-6.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:1d54d13ab8414ed44de07efecb97d4ef7c39f7438cf5e976ccd356bebb1b5fca"}, - {file = "tornado-6.2-cp37-abi3-win32.whl", hash = "sha256:5c87076709343557ef8032934ce5f637dbb552efa7b21d08e89ae7619ed0eb23"}, - {file = "tornado-6.2-cp37-abi3-win_amd64.whl", hash = "sha256:e5f923aa6a47e133d1cf87d60700889d7eae68988704e20c75fb2d65677a8e4b"}, - {file = "tornado-6.2.tar.gz", hash = "sha256:9b630419bde84ec666bfd7ea0a4cb2a8a651c2d5cccdbdd1972a0c859dfc3c13"}, -] -tqdm = [ - {file = "tqdm-4.64.1-py2.py3-none-any.whl", hash = "sha256:6fee160d6ffcd1b1c68c65f14c829c22832bc401726335ce92c52d395944a6a1"}, - {file = "tqdm-4.64.1.tar.gz", hash = "sha256:5f4f682a004951c1b450bc753c710e9280c5746ce6ffedee253ddbcbf54cf1e4"}, -] -typing-extensions = [ - {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"}, - {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"}, -] -urllib3 = [ - {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, - {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, -] -virtualenv = [ - {file = "virtualenv-20.16.5-py3-none-any.whl", hash = "sha256:d07dfc5df5e4e0dbc92862350ad87a36ed505b978f6c39609dc489eadd5b0d27"}, - {file = "virtualenv-20.16.5.tar.gz", hash = "sha256:227ea1b9994fdc5ea31977ba3383ef296d7472ea85be9d6732e42a91c04e80da"}, -] -webencodings = [ - {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, - {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, -] -Werkzeug = [ - {file = "Werkzeug-2.2.2-py3-none-any.whl", hash = "sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5"}, - {file = "Werkzeug-2.2.2.tar.gz", hash = "sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f"}, -] -wheel = [ - {file = "wheel-0.37.1-py2.py3-none-any.whl", hash = "sha256:4bdcd7d840138086126cd09254dc6195fb4fc6f01c050a1d7236f2630db1d22a"}, - {file = "wheel-0.37.1.tar.gz", hash = "sha256:e9a504e793efbca1b8e0e9cb979a249cf4a0a7b5b8c9e8b65a5e39d49529c1c4"}, -] -wordcloud = [ - {file = "wordcloud-1.8.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2a90f512c1c3c2a483d9d12b06a80124cecf813ec7a49b328dce6181c5440f2d"}, - {file = "wordcloud-1.8.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e6376f09543416d03844313d7e6e39eb0a42547e07001ac50be93fbd4c6c4431"}, - {file = "wordcloud-1.8.2.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:334318eb345eafc3494d81fbbe11823fc945833e6a77cf05c7a6a1b88c1e1db0"}, - {file = "wordcloud-1.8.2.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c162814bc0ca2f1436e553ef8c451009c689f5a3f04be8acb5f1df7389b2dbc2"}, - {file = "wordcloud-1.8.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:66bd735eb869a769806154067da01ecaeb4ce165d3c523c306e8ea7d376a1706"}, - {file = "wordcloud-1.8.2.2-cp310-cp310-win32.whl", hash = "sha256:7344df98ea8556a4f8e12924cf0b2e2d7055b1565440fd0c2a453c2b7e1e240b"}, - {file = "wordcloud-1.8.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:bc2974162313e3702cfd314401c943bb94add4ae64a4d7d4ecdf93863133b5e1"}, - {file = "wordcloud-1.8.2.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:90174d2154d554e186e4db14121315bb0e2cb4b0c88d0ca0f8f99831f672cfea"}, - {file = "wordcloud-1.8.2.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:948a947960ce688088e7617c9f82c26a0992c1e4e28a4de1f9a0afa736102556"}, - {file = "wordcloud-1.8.2.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52acd837fdd26239352f77be1491148b36e77f3c31ce7a9fe232664bfadd1a2c"}, - {file = "wordcloud-1.8.2.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:a17055e10baee8e5f19d2b72c474d59dfb45660f66b92d3468fef44f0cc67b37"}, - {file = "wordcloud-1.8.2.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:7b0a7e43b961ea7be13d7d7397fd131f8e795e1b36a23fdcab914a14d7c50def"}, - {file = "wordcloud-1.8.2.2-cp36-cp36m-win32.whl", hash = "sha256:3d4da63b8f315caf3f715b23ab0a05d43139b9395e5e78b7e12b7ed2701d3a8e"}, - {file = "wordcloud-1.8.2.2-cp36-cp36m-win_amd64.whl", hash = "sha256:ccd027f089df42d9d99f0a2d227823f1248d49826b82dc942e6066a16b825d99"}, - {file = "wordcloud-1.8.2.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:61b292af5d88e719a641bb832280b81902df24a39936e6cf87ae0b6ea7910262"}, - {file = "wordcloud-1.8.2.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43a71a15ac8f721f425d1030633f26a8037ddb767fe9bb45647fe5ed94b92eda"}, - {file = "wordcloud-1.8.2.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14f7d34c25ddad412fac32760bd5d6d1565a98821f6dd021cf6617203b0db5ae"}, - {file = "wordcloud-1.8.2.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:cf81862e9ff7c7abca1fb883ee60d3274b1ce1b30f99cd07cc29c5f5d95cbab8"}, - {file = "wordcloud-1.8.2.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3639eeb7c8b09f71376c6369277fb78d2dd8c96648034c3c25ee0f34f3e9249c"}, - {file = "wordcloud-1.8.2.2-cp37-cp37m-win32.whl", hash = "sha256:d2a966bdebdb4eab57ce4ce9a31e96b8772c0e5c46f7e334cb2e8afa59297d8a"}, - {file = "wordcloud-1.8.2.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b8fc88ce6bd9edb514473f10ea4fb14ef78fbd5266b56a614939c5a8a0256283"}, - {file = "wordcloud-1.8.2.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9595200d2e30ba161f585dfc5bf568010e76adc7c7bbc5d7149f0bf3b96996aa"}, - {file = "wordcloud-1.8.2.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b6573eaab49a3682822ea7208077ed5b81210daa3ddb41a9d4879f9803d7b6b"}, - {file = "wordcloud-1.8.2.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:55f6416f9958042fe92d751962a3dfd83e583828504d9f6e8f886e034b3354d0"}, - {file = "wordcloud-1.8.2.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4580f1cbf42b3a0565b140d580d6e249230373b8fa31e4491620af1caec45e92"}, - {file = "wordcloud-1.8.2.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3e3f01635def27b971f178b8bc3438f3be09d91f72ab3b51b90a1ae16e4028d8"}, - {file = "wordcloud-1.8.2.2-cp38-cp38-win32.whl", hash = "sha256:b4e4dcd8c1c2483c2c45082d1e9cd600924d84b52154324cce5579a3dac33c46"}, - {file = "wordcloud-1.8.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:31c09d77a01b3d5638f2e0e043cfcb0d90f1c8b4d12864132e1d421dc525467f"}, - {file = "wordcloud-1.8.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f6377f570838661ade045793e100f506a4e1f92ddac23455470a03617e30d2a8"}, - {file = "wordcloud-1.8.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b50378e7cb7b9a1990ff3a10dfcad968185a1fbfd99de68c436245bbd5cd669"}, - {file = "wordcloud-1.8.2.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d76e1939ca45907dcdf8b17fd64d5a392534f42a90b6194e806f08b65ed73948"}, - {file = "wordcloud-1.8.2.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c70fd9ff86a4370d0ba9aede977440635a859b3c6a86693e178f2ecb4369e153"}, - {file = "wordcloud-1.8.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c1fa72f4f94d7236eb6a1a86cfcfa6df292411047320c8deb173cac379a87c2a"}, - {file = "wordcloud-1.8.2.2-cp39-cp39-win32.whl", hash = "sha256:55224971bd7c3ba2a1038dd5aefa0559b3a320bf6f0b864c0469db5dfa7d587b"}, - {file = "wordcloud-1.8.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:a3e6c77da50d1f5263281c72db8c2cf5893b2dd624ce684910b7830eb7069163"}, - {file = "wordcloud-1.8.2.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:be045984d2cdb4f181c7aff24001a97ade10d04b1098ac5c859748e2802263f4"}, - {file = "wordcloud-1.8.2.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15da7c4ff531b19527fb605da11e747d418a4d81d78503c34fb11babf3196b7a"}, - {file = "wordcloud-1.8.2.2-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd6d3f253f163ce21f6efc2cc675caf16ce474977de925b0adcdae9b97fe8659"}, - {file = "wordcloud-1.8.2.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:47f329426a0952a4509d4d0c8b84867f8d11e65cb81ee852ebcfad588598cda8"}, - {file = "wordcloud-1.8.2.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:001a0b4483fe4ec26302b306c1590a4c44a99483c2da8232012ac62177296594"}, - {file = "wordcloud-1.8.2.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d512c9867a43cbbfa51661ea2d7e3e84c4309ef29ee1be3e10b64f9d3353bd70"}, - {file = "wordcloud-1.8.2.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c887681e9353e559f25421bfd3b358990ae80ed77c42f28eed810ab180047578"}, - {file = "wordcloud-1.8.2.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:aa0ddb25cde58232131072870f139d6c737d74d7a3b6a80fcb9721f3b9b2e7bb"}, - {file = "wordcloud-1.8.2.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:16ed864495573094e5b64f424d66d9030a638569182ad7c5b2c8e11ab78a2541"}, - {file = "wordcloud-1.8.2.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19c444200056b3d75b5d84a6cc018d6491da1841462546663ea3a88300db03f1"}, - {file = "wordcloud-1.8.2.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1dc69a57a349272119ae633b8d6bcc9cde600aeb4342261e12ce169badcd28ca"}, - {file = "wordcloud-1.8.2.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3c39bd66f172f56257f09cec8fe246cd11ef36e9e16eeabe88933788d983c6a1"}, - {file = "wordcloud-1.8.2.2.tar.gz", hash = "sha256:523db887e47e840eb5c2e60428243bb1d7439fdc60f89626b17bafa1be64459c"}, -] -yapf = [ - {file = "yapf-0.32.0-py2.py3-none-any.whl", hash = "sha256:8fea849025584e486fd06d6ba2bed717f396080fd3cc236ba10cb97c4c51cf32"}, - {file = "yapf-0.32.0.tar.gz", hash = "sha256:a3f5085d37ef7e3e004c4ba9f9b3e40c54ff1901cd111f05145ae313a7c67d1b"}, -] -zipp = [ - {file = "zipp-3.8.1-py3-none-any.whl", hash = "sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009"}, - {file = "zipp-3.8.1.tar.gz", hash = "sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2"}, -] +lock-version = "2.1" +python-versions = "^3.12.3" +content-hash = "9b6d2ff3def9898a3e18c3eb804ad9e24f9645e9a449c73cf67bbb76239b9e2b" diff --git a/pyproject.toml b/pyproject.toml index 9fc17dc..2d1ad4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ authors = [{name = "Jens Broeder", email = "j.broeder@fz-juelich.de"}, {name = "Silke Christine Gerlich", email = "s.gerlich@fz-juelich.de"}, {name = "Volker Hofmann", email = "v.hofmann@fz-juelich.de"}] readme = "README.md" -license = {file = "LICENSE.txt"} +license = {file = "LICENSE"} classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Information Technology", @@ -31,6 +31,8 @@ classifiers = [ keywords = ["dashboard", "data visualization", "survey data", "categorical data", "interactive visualization", "bokeh", "panel"] +[project.scripts] +survey-dashboard = "survey_dashboard.scripts:run_app" [tool.poetry] name = "survey-dashboard" @@ -67,17 +69,20 @@ keywords = ["dashboard", "data visualization", "survey data", "categorical data" [tool.poetry.dependencies] -python = "^3.8" -pandas = "^1.4.1" -bokeh = "^2.4.3" -wordcloud = "^1.8.2.2" -panel = "^0.13.1" +python = "^3.12.3" +panel = "^1.7.5" +watchfiles = "^1.1.0" +pandas = "^2.3.2" +wordcloud = "^1.9.4" +bokeh = "^3.7.3" +matplotlib = "^3.10.6" -[tool.poetry.dev-dependencies] -pre-commit = "^2.17.0" -pytest = "^7.0.1" -pytest-cov = "^3.0.0" -pdoc = "^10.0.3" + +[tool.poetry.group.dev.dependencies] +pre-commit = "^4.3.0" +pytest = "^8.4.1" +pytest-cov = "^6.2.1" +pdoc = "^15.0.4" [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/survey_dashboard/analysis.py b/survey_dashboard/analysis.py index 2f871d2..9b4be71 100644 --- a/survey_dashboard/analysis.py +++ b/survey_dashboard/analysis.py @@ -9,14 +9,23 @@ # For further information on the license, see the LICENSE file # ############################################################################### """ -This module contains some function to process survey data in certain way and +This module contains some function to process survey data in certain way and prepare the data for visualization """ + import math import pandas as pd from typing import List, Tuple +from .data.hcs_clean_dictionaries import HCS_colnamesDict + -def calculate_crosstab(df: pd.DataFrame, data_key1: str, data_key2: str, id_vars: str=None, astype: str="int") -> pd.DataFrame: +def calculate_crosstab( + df: pd.DataFrame, + data_key1: str, + data_key2: str, + id_vars: str = None, + astype: str = "int", +) -> pd.DataFrame: """Calulate the cross table for two keys in a given pandas data frame""" if id_vars is None: @@ -24,56 +33,90 @@ def calculate_crosstab(df: pd.DataFrame, data_key1: str, data_key2: str, id_vars cols = [data_key1, data_key2] - df0 = df[cols].dropna(how = "all", subset = cols).astype("category") + df0 = df[cols].dropna(how="all", subset=cols).astype("category") totals = dict(df0[data_key1].value_counts()) - df_crosstab = pd.crosstab(df[data_key1], df[data_key2], - margins = False).reset_index().melt(id_vars = [id_vars]) - + df_crosstab = ( + pd.crosstab(df[data_key1], df[data_key2], margins=False) + .reset_index() + .melt(id_vars=[id_vars]) + ) + # include total answers by career level in cross tab df_crosstab["total"] = df_crosstab[data_key1].map(totals).astype(astype) - + # calculate relative amount of answers by career level df_crosstab["percentage"] = (df_crosstab["value"] / df_crosstab["total"]) * 100 - + return df_crosstab -def filter_dataframe(df: pd.DataFrame, include: list=None, exclude: List[Tuple[str, list]]=None, - exclude_nan=True, exclude_anonymized=True, as_type="category") -> pd.DataFrame: +def filter_dataframe( + df: pd.DataFrame, + include: List[str] = None, + exclude: List[Tuple[str, List]] = None, + exclude_nan: bool = True, + exclude_anonymized: bool = True, + as_type: str = "object", +) -> pd.DataFrame: """ - Filter a pandas dataframe + Filter dataframe based on include/exclude criteria - example: - ``` - to_exclude = ['Other', 'Undergraduate / Masters student', 'Director (of the institute)'] - df = filter_dataframe(surveydata, include=["careerLevel", "docStructured", "researchArea"], exclude=[("careerLevel", to_exclude)]) + Args: + df: Input dataframe + include: List of columns to include + exclude: List of tuples (column, values_to_exclude) + exclude_nan: Whether to exclude rows with NaN values + exclude_anonymized: Whether to replace "Anonymized" with empty string + as_type: Data type to convert columns to - returns a dataFrame with columns ["careerLevel", "docStructured", "researchArea"], - where rows which contain to_exclude values in the "careerLevel" column are removed - ``` + Returns: + Filtered dataframe """ + # Check if the DataFrame has already been renamed (has human-readable column names) + # If it has renamed columns, don't try to convert back to original names + has_renamed_columns = any(col in df.columns for col in ['careerLevel', 'researchArea', 'centerAffiliation']) + + if include is not None: + if has_renamed_columns: + # DataFrame already has renamed columns, use them directly + include_columns = include + else: + # DataFrame has original column names, convert if needed + original_to_renamed = {v: k for k, v in HCS_colnamesDict.items()} + include_columns = [original_to_renamed.get(col, col) for col in include] + + df = ( + df[include_columns] + .dropna(how="all", subset=include_columns) + .astype(as_type) + ) + if exclude: + for key, val in exclude: + if has_renamed_columns: + # DataFrame already has renamed columns, use them directly + key_column = key + else: + # DataFrame has original column names, convert if needed + original_to_renamed = {v: k for k, v in HCS_colnamesDict.items()} + key_column = original_to_renamed.get(key, key) + + df = df.loc[~df[key_column].isin(val)] - if include is not None: - df = df[include].dropna(how = "all", subset = include).astype(as_type) - - for key, val in exclude: - #print(key, val) - df = df.loc[~df[key].isin(val)] - if exclude_nan: for key in df.keys(): df = df.loc[~df[key].isna()] if exclude_anonymized: - df = df.replace(to_replace="Anonymized", value="") + df = df.replace(to_replace="Anonymized", value="") return df + def get_all_values(df: pd.DataFrame, keylist: List[str], display_dict=None) -> dict: """ - Count all values of a given key from a key list in a data frame and + Count all values of a given key from a key list in a data frame and return these values in a dictionary sorted. """ @@ -81,15 +124,15 @@ def get_all_values(df: pd.DataFrame, keylist: List[str], display_dict=None) -> d key = keylist[0] all_areas = df[key].value_counts() all_areas = all_areas.sort_index() - data = {'All': all_areas.values, key:list(all_areas.keys())} - else: # multiple keys now the keys become the xticks + data = {"All": all_areas.values, key: list(all_areas.keys())} + else: # multiple keys now the keys become the xticks combined = {} for key in keylist: if display_dict is not None: xtick = display_dict[key] else: xtick = key - xtick = xtick.replace(' \n', '') + xtick = xtick.replace(" \n", "") temp = df[key] temp.replace(to_replace=True, value=xtick, inplace=True) temp.replace(to_replace=False, value=None, inplace=True) @@ -101,26 +144,32 @@ def get_all_values(df: pd.DataFrame, keylist: List[str], display_dict=None) -> d # there is a problem if df is empty, i.e temp.value_counts() True 0 for i, ke in enumerate(a.keys()): # because other can contain all... others.. - #ke = ke.lower() # sometimes there are mixed upper and lower case keys... - #ke = ke.replace(' \n', '') # some are with and without breaks + # ke = ke.lower() # sometimes there are mixed upper and lower case keys... + # ke = ke.replace(' \n', '') # some are with and without breaks temp_val = combined.get(ke, 0) temp_val = temp_val + a.values[i] combined[ke] = temp_val - #for i, ke in enumerate(a.keys()): + # for i, ke in enumerate(a.keys()): # ke = ke.lower() # sometimes there are mixed upper and lower case keys... # ke = ke.replace(' \n', '') # some are with and without breaks # temp_val = combined.get(ke, 0) # temp_val = temp_val + a.values[i] # combined[ke] = temp_val - data = {'All' : list(combined.values()), key:list(combined.keys())} + data = {"All": list(combined.values()), key: list(combined.keys())} return data -def prepare_data_research_field(df: pd.DataFrame, keylist:List[str], key2:str='researchArea', sort_as=None, display_dict= None):# -> dict, list: +def prepare_data_research_field( + df: pd.DataFrame, + keylist: List[str], + key2: str = "researchArea", + sort_as=None, + display_dict=None, +): # -> dict, list: """Creates a dict dictionary with data in the form needed by the plotting functions - - We prepare several outputs, i.e y_keys because they can have different length and one should be able to create a + + We prepare several outputs, i.e y_keys because they can have different length and one should be able to create a ColumnDataSource by ColumnDataSource(data=data) :param df: [description] :type df: pd.DataFrame @@ -156,13 +205,17 @@ def prepare_data_research_field(df: pd.DataFrame, keylist:List[str], key2:str='r """ research_areas = list(df[key2].value_counts().keys()) - y_keys = ['Cum. Sum'] + research_areas + y_keys = ["Cum. Sum"] + research_areas # Multiple columns will be combined. A single column will be treated differently if len(keylist) == 1: key = keylist[0] all_areas = df[key].value_counts() all_areas = all_areas.sort_index() - data = {'Cum. Sum': all_areas.values, key:list(all_areas.keys()), 'x_value': list(all_areas.keys())} + data = { + "Cum. Sum": all_areas.values, + key: list(all_areas.keys()), + "x_value": list(all_areas.keys()), + } for area in research_areas: area_counts = df[df[key2] == area][key].value_counts() area_counts = area_counts.sort_index() @@ -176,7 +229,7 @@ def prepare_data_research_field(df: pd.DataFrame, keylist:List[str], key2:str='r xtick = display_dict[key] else: xtick = key - xtick = xtick.replace(' \n', '') + xtick = xtick.replace(" \n", "") temp = df[key] temp.replace(to_replace=True, value=xtick, inplace=True) temp.replace(to_replace=False, value=None, inplace=True) @@ -185,40 +238,41 @@ def prepare_data_research_field(df: pd.DataFrame, keylist:List[str], key2:str='r # there is a problem if df is empty, i.e temp.value_counts() True 0 if a.empty: combined[xtick] = 0 - else: + else: for i, ke in enumerate(a.keys()): # because other can contain all... others.. - #ke = ke.lower() # sometimes there are mixed upper and lower case keys... - #ke = ke.replace(' \n', '') # some are with and without breaks + # ke = ke.lower() # sometimes there are mixed upper and lower case keys... + # ke = ke.replace(' \n', '') # some are with and without breaks temp_val = combined.get(ke, 0) temp_val = temp_val + a.values[i] combined[ke] = temp_val - + # now fill research area specifics for area in research_areas: - area_counts = df[df[key2] == area][key] + area_counts = df[df[key2] == area][key].copy() area_counts.replace(to_replace=True, value=xtick, inplace=True) area_counts.replace(to_replace=False, value=None, inplace=True) area_counts = area_counts.value_counts() area_counts = area_counts.sort_index() temp = data.get(area, []) - #print(area_counts) + # print(area_counts) if area_counts.empty: temp.append(0) else: temp.append(int(area_counts.values[0])) data[area] = temp - - data['Cum. Sum'] = list(combined.values()) - data['x_value'] = list(combined.keys()) + + data["Cum. Sum"] = list(combined.values()) + data["x_value"] = list(combined.keys()) return data, y_keys + ''' def prepare_data_research_field(df: pd.DataFrame, key:str, key2:str='researchArea', sort_as=None):# -> dict, list: """Creates a dict dictionary with data in the form needed by the plotting functions - - We prepare several outputs, i.e y_keys because they can have different length and one should be able to create a + + We prepare several outputs, i.e y_keys because they can have different length and one should be able to create a ColumnDataSource by ColumnDataSource(data=data) :param df: [description] :type df: pd.DataFrame @@ -262,7 +316,7 @@ def prepare_data_research_field(df: pd.DataFrame, key:str, key2:str='researchAre area_counts = df[df[key2] == area][key].value_counts() area_counts = area_counts.sort_index() data[area] = area_counts.values - + return data, y_keys ''' ''' @@ -282,16 +336,17 @@ def prepare_data_research_field(df: pd.DataFrame, key:str): area_counts = df[df["researchArea"] == area][key].value_counts() area_counts = area_counts.sort_index() data[area] = {'counts': area_counts.values, 'values': list(area_counts.keys())} - + return data ''' -def percentage_to_area(data: List[float], scale_m: float=1.0) -> List[float]: + +def percentage_to_area(data: List[float], scale_m: float = 1.0) -> List[float]: """ - Convert numbers in a given array to a radius, - - where a circle of with that radius is proportionate to the circle area + Convert numbers in a given array to a radius, + + where a circle of with that radius is proportionate to the circle area Useful for circle plots where the area should be proportional to the value """ - radius_data = [2*math.sqrt(val*scale_m/math.pi) for val in data] - return radius_data \ No newline at end of file + radius_data = [2 * math.sqrt(val * scale_m / math.pi) for val in data] + return radius_data diff --git a/survey_dashboard/app.py b/survey_dashboard/app.py new file mode 100644 index 0000000..9eedfd6 --- /dev/null +++ b/survey_dashboard/app.py @@ -0,0 +1,143 @@ +# -*- coding: utf-8 -*- +############################################################################### +# Copyright (c), Forschungszentrum Jülich GmbH, IAS-9, Germany. # +# All rights reserved. # +# This file is part of the survey_dashboard package. # +# # +# The code is hosted on GitHub at # +# https://github.com/Materials-Data-Science-and-Informatics/survey_dashboard # +# For further information on the license, see the LICENSE file # +############################################################################### +""" +Simplified entry point for the HMC Survey Dashboard. +This app.py orchestrates the creation of the dashboard using the new modular structure. +""" + +# Import core components +from survey_dashboard.core.data import DataProcessor +from survey_dashboard.core.charts import ChartManager + +# Import UI components +from survey_dashboard.ui.widgets import WidgetFactory +from survey_dashboard.ui.layout import LayoutManager +from survey_dashboard.ui.callbacks import CallbackManager + +# Initialize core components +data_processor = DataProcessor() +chart_manager = ChartManager(data_processor) + +# Initialize UI components +widget_factory = WidgetFactory(data_processor) +layout_manager = LayoutManager() +callback_manager = CallbackManager(data_processor, chart_manager, widget_factory) + +# Create all widgets +widgets = widget_factory.create_all_widgets() +control_groups = widget_factory.get_control_groups(widgets) + +# Get initial filter values +data_filters = widgets["global_filters"]["research_area"].value +data_filters_method = widgets["global_filters"]["method"].value + +# Create all visualizations using chart manager +overview_charts = chart_manager.create_overview_charts(data_filters, data_filters_method) +exploration_charts = chart_manager.create_exploration_charts( + widgets["exploration"]["question1"], + widgets["exploration"]["question2"], + data_filters, + data_filters_method +) +correlation_chart = chart_manager.create_correlation_chart( + widgets["exploration"]["question1"], + widgets["exploration"]["question2"], + data_filters, + data_filters_method +) +methods_tools_tabs, wordcloud_panes = chart_manager.create_wordcloud_tabs(data_filters, data_filters_method) + +# Create update callbacks +callbacks = callback_manager.create_update_callbacks(widgets) + +# Bind callbacks to widgets and charts +def bind_callbacks(): + """Bind all interactive callbacks to their respective widgets and charts.""" + # Global filter callbacks for overview charts + for i, chart_key in enumerate(['ov1', 'ov2', 'ov3', 'ov4']): + widgets["global_filters"]["research_area"].param.watch( + lambda event, target=overview_charts[chart_key], callback=callbacks["overview"][i]: callback(target, event), + "value" + ) + widgets["global_filters"]["method"].param.watch( + lambda event, target=overview_charts[chart_key], callback=callbacks["overview"][i]: callback(target, event), + "value" + ) + + # Exploration chart callbacks + for widget_key in ["question1", "question2", "chart_type1", "chart_type2"]: + callback_idx = 0 if "1" in widget_key else 1 + target_chart = exploration_charts[callback_idx] + widgets["exploration"][widget_key].param.watch( + lambda event, target=target_chart, callback=callbacks["exploration"][callback_idx]: callback(target, event), + "value" + ) + + # Global filter callbacks for exploration charts + for i, callback in enumerate(callbacks["exploration"]): + target_chart = exploration_charts[i] + widgets["global_filters"]["research_area"].param.watch( + lambda event, target=target_chart, callback=callback: callback(target, event), + "value" + ) + widgets["global_filters"]["method"].param.watch( + lambda event, target=target_chart, callback=callback: callback(target, event), + "value" + ) + + # Correlation chart callbacks + widgets["exploration"]["question1"].param.watch( + lambda event, target=correlation_chart[0], callback=callbacks["correlation"]: callback(target, event), + "value" + ) + widgets["exploration"]["question2"].param.watch( + lambda event, target=correlation_chart[0], callback=callbacks["correlation"]: callback(target, event), + "value" + ) + widgets["global_filters"]["research_area"].param.watch( + lambda event, target=correlation_chart[0], callback=callbacks["correlation"]: callback(target, event), + "value" + ) + widgets["global_filters"]["method"].param.watch( + lambda event, target=correlation_chart[0], callback=callbacks["correlation"]: callback(target, event), + "value" + ) + + # Word cloud callbacks + wordcloud_targets = [wordcloud_panes["methods"], wordcloud_panes["software"], wordcloud_panes["repositories"]] + for i, callback in enumerate(callbacks["wordclouds"]): + target = wordcloud_targets[i] + widgets["global_filters"]["research_area"].param.watch( + lambda event, target=target, callback=callback: callback(target, event), + "value" + ) + widgets["global_filters"]["method"].param.watch( + lambda event, target=target, callback=callback: callback(target, event), + "value" + ) + +# Create complete layout +layout = layout_manager.create_complete_layout( + control_groups=control_groups, + overview_charts=overview_charts, + exploration_charts=exploration_charts, + correlation_chart=correlation_chart, + methods_tools_tabs=methods_tools_tabs +) + +# Wire correlation_row to callbacks for visibility toggling +correlation_row = layout_manager.get_correlation_row() +callback_manager.set_correlation_row(correlation_row) + +# Setup template and make servable +template = layout_manager.setup_template_variables(layout) +bind_callbacks() +template = layout_manager.make_servable() \ No newline at end of file diff --git a/survey_dashboard/core/__init__.py b/survey_dashboard/core/__init__.py new file mode 100644 index 0000000..c47f08b --- /dev/null +++ b/survey_dashboard/core/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +""" +Core business logic for the survey dashboard. +""" \ No newline at end of file diff --git a/survey_dashboard/core/charts.py b/survey_dashboard/core/charts.py new file mode 100644 index 0000000..6c9fe56 --- /dev/null +++ b/survey_dashboard/core/charts.py @@ -0,0 +1,240 @@ +# -*- coding: utf-8 -*- +############################################################################### +# Copyright (c), Forschungszentrum Jülich GmbH, IAS-9, Germany. # +# All rights reserved. # +# This file is part of the survey_dashboard package. # +# # +# The code is hosted on GitHub at # +# https://github.com/Materials-Data-Science-and-Informatics/survey_dashboard # +# For further information on the license, see the LICENSE file # +############################################################################### +""" +Chart creation module for the survey dashboard. +Handles creation of all chart types and visualizations. +""" + +import panel as pn + +from survey_dashboard.plots import ( + bokeh_barchart, + bokeh_piechart, + bokeh_corr_plot, + create_legend_corr, + generate_wordcloud, + interactive_wordcloud, + DEFAULT_FIGURE_WIDTH, + DEFAULT_FIGURE_HEIGHT +) +from survey_dashboard.core.config import ( + DEFAULT_QUESTIONS, + ACCORDION_WIDTH, + OFFSET_HEIGHT_FOR_TABS, + WORDCLOUD_CONTENT, + SIZING_MODE, + LANGUAGE +) +from survey_dashboard.i18n.text_display import ( + md_text_tools_used, + md_text_tools_tabs +) + + +class ChartManager: + """Manages creation of all chart types.""" + + def __init__(self, data_processor): + """Initialize chart manager with data processor.""" + self.data_processor = data_processor + self.half_width = int(ACCORDION_WIDTH / 2) + + def create_overview_charts(self, data_filters, data_filters_method): + """Create all overview charts.""" + overview_charts = {} + + # Get overview question mappings + overview_questions = { + 'ov1': self.data_processor.map_qkey_to_question(DEFAULT_QUESTIONS["overview"]["ov1"]), + 'ov2': self.data_processor.map_qkey_to_question(DEFAULT_QUESTIONS["overview"]["ov2"]), + 'ov3': self.data_processor.map_qkey_to_question(DEFAULT_QUESTIONS["overview"]["ov3"]), + 'ov4': self.data_processor.map_qkey_to_question(DEFAULT_QUESTIONS["overview"]["ov4"]) + } + + # Create each overview chart + for key, question in overview_questions.items(): + start_display_data, ydata_spec, display_options = self.data_processor.select_data( + question, data_filters, data_filters_method + ) + y_keys = ydata_spec.data["y_keys"] + + overview_charts[key] = pn.pane.Bokeh( + bokeh_barchart( + start_display_data, + y=y_keys, + factors=y_keys, + legend_labels=y_keys, + fill_color=ydata_spec.data["colors"], + orientation="vertical", + **display_options, + ) + ) + + return overview_charts + + def create_exploration_charts(self, question_select, question_select2, data_filters, data_filters_method): + """Create exploration charts.""" + # First exploration chart + start_display_data, ydata_spec, display_options = self.data_processor.select_data( + question_select.value, data_filters, data_filters_method + ) + y_keys = ydata_spec.data["y_keys"] + fill_colors = ydata_spec.data["colors"] + + fig_exp1 = pn.pane.Bokeh( + bokeh_barchart( + start_display_data, + y=y_keys, + factors=y_keys, + legend_labels=y_keys, + fill_color=fill_colors, + orientation="vertical", + **display_options, + ) + ) + + # Second exploration chart + start_display_data, ydata_spec, display_options = self.data_processor.select_data( + question_select2.value, data_filters, data_filters_method + ) + y_keys = ydata_spec.data["y_keys"] + fill_colors = ydata_spec.data["colors"] + + fig_exp2 = pn.pane.Bokeh( + bokeh_barchart( + start_display_data, + y=y_keys, + factors=y_keys, + legend_labels=y_keys, + fill_color=fill_colors, + orientation="vertical", + **display_options, + ) + ) + + return fig_exp1, fig_exp2 + + def create_correlation_chart(self, question_select, question_select2, data_filters, data_filters_method): + """Create correlation chart with legend.""" + start_corr_data, display_options_corr, marker_scale = self.data_processor.select_data_corr( + question_select.value, question_select2.value, data_filters, data_filters_method + ) + fig_corr_1 = bokeh_corr_plot(start_corr_data, **display_options_corr) + fig_corr = pn.pane.Bokeh(fig_corr_1, align="center") + + leg_corr = pn.pane.Bokeh( + create_legend_corr( + fig_corr_1, colors=start_corr_data.data["color"], scale_m=marker_scale + ), + align="center", + ) + + return fig_corr, leg_corr + + def create_wordcloud_tabs(self, data_filters, data_filters_method): + """Create word cloud tabs for methods, software, and repositories.""" + wordcloud_panes = {} + + # Create word clouds for each content type + for content_type, content_fields in WORDCLOUD_CONTENT.items(): + text_list = self.data_processor.select_data_wordcloud( + data_filters, data_filters_method, content=content_fields + ) + wordcloud = generate_wordcloud( + text_list, height=DEFAULT_FIGURE_HEIGHT, width=ACCORDION_WIDTH + ) + wordcloud_panes[content_type] = pn.pane.Bokeh( + interactive_wordcloud(wordcloud), + width=wordcloud.width, + height=wordcloud.height + OFFSET_HEIGHT_FOR_TABS, + ) + + # Create tabs + methods_tabs = pn.Column( + md_text_tools_used[LANGUAGE], + pn.Tabs( + (md_text_tools_tabs["methods"][LANGUAGE], wordcloud_panes["methods"]), + (md_text_tools_tabs["software"][LANGUAGE], wordcloud_panes["software"]), + (md_text_tools_tabs["repositories"][LANGUAGE], wordcloud_panes["repositories"]), + ), + sizing_mode=SIZING_MODE, + ) + + return methods_tabs, wordcloud_panes + + def create_chart(self, question, data_filters, data_filters_method, chart_type): + """Create a chart of the specified type.""" + df, ydata_spec, display_options = self.data_processor.select_data( + question, data_filters, data_filters_method + ) + + y_keys = ydata_spec.data["y_keys"] + fill_colors = ydata_spec.data["colors"] + + if chart_type == "Vertical Bar chart": + fig = bokeh_barchart( + df, + y=y_keys, + factors=y_keys, + legend_labels=y_keys, + fill_color=fill_colors, + orientation="vertical", + **display_options, + ) + elif chart_type == "Horizontal Bar chart": + # Swap the ranges for horizontal orientation + y_range = display_options["y_range"] + display_options["y_range"] = display_options["x_range"] + display_options["x_range"] = y_range + + # Swap the labels for horizontal orientation + display_options["xlabel"] = "" # X axis lays vertically but shows categorical data + display_options["ylabel"] = "Number of Answers" # Y axis now lays horizontally but still shows numerical data + + fig = bokeh_barchart( + df, + y=y_keys, + factors=y_keys, + legend_labels=y_keys, + fill_color=fill_colors, + orientation="horizontal", + **display_options, + ) + elif chart_type == "Pie chart": + display_options.pop("x_range") + display_options.pop("y_range") + display_options.pop("width") + fig = bokeh_piechart( + df, + y=y_keys, + legend_labels=y_keys, + fill_color=fill_colors, + **display_options, + ) + + return fig + + def create_correlation_plot(self, question1, question2, data_filters, data_filters_method): + """Create correlation plot.""" + df, display_options, marker_scale = self.data_processor.select_data_corr( + question1, question2, data_filters, data_filters_method + ) + return bokeh_corr_plot(df, **display_options) + + def create_wordcloud(self, data_filters, data_filters_method, content): + """Create word cloud visualization.""" + text_list = self.data_processor.select_data_wordcloud( + data_filters, data_filters_method, content=content + ) + wordcloud = generate_wordcloud( + text_list, height=DEFAULT_FIGURE_HEIGHT, width=DEFAULT_FIGURE_WIDTH + ) + return interactive_wordcloud(wordcloud) \ No newline at end of file diff --git a/survey_dashboard/core/config.py b/survey_dashboard/core/config.py new file mode 100644 index 0000000..06e6a78 --- /dev/null +++ b/survey_dashboard/core/config.py @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- +############################################################################### +# Copyright (c), Forschungszentrum Jülich GmbH, IAS-9, Germany. # +# All rights reserved. # +# This file is part of the survey_dashboard package. # +# # +# The code is hosted on GitHub at # +# https://github.com/Materials-Data-Science-and-Informatics/survey_dashboard # +# For further information on the license, see the LICENSE file # +############################################################################### +""" +Configuration module for the survey dashboard. +Contains all global constants, paths, and configuration settings. +""" + +import os +from pathlib import Path + +from survey_dashboard.plots import DEFAULT_FIGURE_WIDTH +from survey_dashboard.data.hcs_clean_dictionaries import ( + HCSquestions, + HCS_colnamesDict, + HCS_MCsubquestions, +) +from survey_dashboard.hmc_layout.hmc_colordicts import ( + hubPalette, + get_hmc_colors +) + +# Global Configuration +LANGUAGE = os.environ.get("LANGUAGE_DASHBOARD", "EN") +ACCORDION_WIDTH = int(DEFAULT_FIGURE_WIDTH * 2) +SIZING_MODE = "stretch_width" + +# Data Configuration +def get_data_path(): + """Get the path to the data file relative to this module""" + this_folder = Path(__file__).parent.parent + return this_folder / "data" / "hmc_survey_2021_data.csv" + +DATAFILE_PATH = str(get_data_path()) + +# Filter Configuration +FILTER_BY = "researchArea" +FILTER_BY_2 = "dataGenMethod_" + +# Research Fields and Colors +RESEARCH_FIELDS = [ + "All", + "Cum. Sum", + "Chemistry", + "Earth Science", + "Engineering Science", + "Life Science", + "Mathematics", + "Other", + "Physics", + "Psychology" +] + +# Generate colors for research fields using HMC palette +RESEARCH_AREA_COLORS = { + field: get_hmc_colors(len(RESEARCH_FIELDS))[i] + for i, field in enumerate(RESEARCH_FIELDS) +} + +# HMC Color Configuration +HMC_CHART_COLORS = get_hmc_colors(10) # Default 10 colors for charts +HMC_HUB_COLORS = hubPalette # Research field specific colors + +# Default Questions for Startup +DEFAULT_QUESTIONS = { + "overview": { + "ov1": "fairFamiliarity", + "ov2": "yearsInResearch", + "ov3": "researchArea", + "ov4": "pubAmount" + }, + "exploration": { + "bar1": "careerLevel", + "bar2": "docStructured", + "corr1": "careerLevel", + "corr2": "docStructured" + } +} + +# Tooltips Configuration +TOOLTIPS = [("Title", "@title"), ("Answer", "@x"), ("Number of Answers", "@y")] + +# Widget Configuration +# Note: Pie chart removed due to data structure incompatibilities with multiple filters +CHART_TYPES = ['Vertical Bar chart', 'Horizontal Bar chart'] + +# Word Cloud Content Configuration +WORDCLOUD_CONTENT = { + "methods": ["dataGenMethodSpec_"], + "software": ["software_1", "software_2", "software_3"], + "repositories": ["pubRepo_1", "pubRepo_2", "pubRepo_3", "pubRepo_4", "pubRepo_5"] +} + +# Layout Configuration +HALF_WIDTH_OFFSET = 2 # ACCORDION_WIDTH / 2 +OFFSET_HEIGHT_FOR_TABS = 40 + +# Create reverse dictionaries for data mapping +HCS_COLNAMES_REVERT_DICT = {val: key for key, val in HCS_colnamesDict.items()} +HCS_QUESTIONS_REVERT = {} +HCS_QUESTIONS_REVERT[LANGUAGE] = { + val: key for key, val in HCSquestions[LANGUAGE].items() +} + +# Flatten MC subquestions for easier lookup +HCS_MCSUBQUESTIONS_FLATTENED = {} +for key, val in HCS_MCsubquestions.items(): + for ke, va in val.items(): + HCS_MCSUBQUESTIONS_FLATTENED[ke] = va + +# Panel Configuration +PANEL_CONFIG = { + "loading_spinner": "dots", + "loading_color": "#005AA0" +} + +# Template Configuration +def get_template_path(): + """Get the path to the template file based on language""" + this_folder = Path(__file__).parent.parent + return this_folder / f"hmc_layout/{LANGUAGE.lower()}_template.html" + +def get_assets_path(): + """Get the path to the assets folder""" + this_folder = Path(__file__).parent.parent + return this_folder / "hmc_layout" / "assets" diff --git a/survey_dashboard/core/data.py b/survey_dashboard/core/data.py new file mode 100644 index 0000000..09c3b97 --- /dev/null +++ b/survey_dashboard/core/data.py @@ -0,0 +1,467 @@ +# -*- coding: utf-8 -*- +############################################################################### +# Copyright (c), Forschungszentrum Jülich GmbH, IAS-9, Germany. # +# All rights reserved. # +# This file is part of the survey_dashboard package. # +# # +# The code is hosted on GitHub at # +# https://github.com/Materials-Data-Science-and-Informatics/survey_dashboard # +# For further information on the license, see the LICENSE file # +############################################################################### +""" +Data processing module for the survey dashboard. +Handles all survey data filtering, transformation, and preparation for visualization. +""" + +import pandas as pd +import numpy as np +from bokeh.models import ColumnDataSource + +from survey_dashboard.analysis import ( + calculate_crosstab, + prepare_data_research_field, + filter_dataframe, + percentage_to_area, + get_all_values +) +from survey_dashboard.data.hcs_clean_dictionaries import ( + HCSquestions, + HCS_orderedCats, + HCS_MCsubquestions, + HCS_colnamesDict, + HCS_MCList, + HCS_dtypesWOmc +) +from survey_dashboard.core.config import ( + LANGUAGE, + DATAFILE_PATH, + FILTER_BY, + FILTER_BY_2, + RESEARCH_FIELDS, + RESEARCH_AREA_COLORS, + HCS_COLNAMES_REVERT_DICT, + HCS_QUESTIONS_REVERT, + HCS_MCSUBQUESTIONS_FLATTENED +) + + +class DataProcessor: + """Handles all survey data operations and transformations.""" + + def __init__(self): + """Initialize the data processor with survey data.""" + # Read CSV, skipping comment lines that start with # + self.survey_data = pd.read_csv(DATAFILE_PATH, comment='#') + # Rename columns to human readable names + self.survey_data.rename(columns=HCS_colnamesDict, inplace=True) + + # Create data sources for different uses + self.source = ColumnDataSource(self.survey_data) + self.source_corr = ColumnDataSource(self.survey_data) + + def map_qkey_to_question(self, key: str, lang: str = LANGUAGE) -> str: + """ + Given a key return the full question to be displayed associated with the key for a given language + """ + mc_key = key + + if key in HCS_MCList: + # Multiple choice, all have the same question for now + mc_key = list(HCS_MCsubquestions[key].keys())[0] + index = HCS_COLNAMES_REVERT_DICT[mc_key].split("/")[0] + else: + index = HCS_COLNAMES_REVERT_DICT[mc_key] + + return HCSquestions[lang][index] + + def map_question_to_qkey(self, question: str, lang: str = LANGUAGE) -> list: + """ + Map a given question String to the corresponding columns keys in the dataframe + + usually this is one column, but for multiple choice this can be several columns. + Handles question strings with or without the ★ correlation indicator prefix. + """ + column_keys = [] + # Strip the ★ indicator if present (used to mark correlation-compatible questions) + clean_question = question.replace("★ ", "") + key = HCS_QUESTIONS_REVERT[lang][clean_question] + if key in HCS_MCList: + # for multiple choice this is a list of subquestions + key_s = key + "/" + for key in HCS_colnamesDict.keys(): + if key_s in key: + if not "other" in key: # for now, needs to be included in HCS_MCsubquestions + column_keys.append(HCS_colnamesDict[key]) + column_keys.sort() # Wrong sort... _1 _10 _2 ... + else: + column_keys.append(HCS_colnamesDict[key]) + return column_keys + + def select_data(self, question, data_filters, data_filters_method, filter_by=FILTER_BY): + """Select and transform data for visualization""" + + def get_real_research_areas(data_filters): + """ + Separate pseudo-categories (All, Cum. Sum) from real research area values. + + Args: + data_filters: List of selected filter values + + Returns: + tuple: (real_research_areas, pseudo_categories) + """ + pseudo_categories = {"All", "Cum. Sum"} + real_areas = [area for area in data_filters if area not in pseudo_categories] + pseudo_cats = [area for area in data_filters if area in pseudo_categories] + return real_areas, pseudo_cats + + q_index = self.map_question_to_qkey(question) + q_index_0 = q_index[0] + # Strip ★ indicator for cleaner chart titles + question_full = question.replace("★ ", "") + + # Clean up missing columns + q_index_clean = [] + keys = list(self.survey_data.keys()) + for key in q_index: + if key in keys: + q_index_clean.append(key) + + exclude_nan = True + if len(q_index) > 1: + exclude_nan = False + + # Process method filters + method_include = [] + method_exclude = [] + methods_dict = HCS_MCsubquestions[FILTER_BY_2] + for method in data_filters_method: + for key, val in methods_dict.items(): + if val == method: + method_include.append(key) + method_exclude.append((key, [False])) + + include_clean = list(set([FILTER_BY] + q_index_clean + method_include)) + + # Filter dataframe + df = filter_dataframe( + self.survey_data, + include=include_clean, + exclude=method_exclude, + exclude_nan=exclude_nan, + ) + + data_all = get_all_values( + df, q_index_clean, display_dict=HCS_MCSUBQUESTIONS_FLATTENED + ) + + # Separate real research areas from pseudo-categories + real_research_areas, pseudo_categories = get_real_research_areas(data_filters) + + # Handle data filtering based on what's selected + if "All" in data_filters and len(data_filters) == 1: + # Only "All" is selected - use the aggregated data from all research areas + if len(q_index_clean) == 1: + key = q_index_clean[0] + data = { + "All": data_all["All"], + key: data_all.get(key, []), + "x_value": data_all.get(key, []) + } + y_keys = ["All"] + else: + # Multiple columns case (multiple-choice questions) + data = data_all.copy() + # For multiple-choice, get_all_values returns {All: values, last_key: labels} + # We need to add x_value for the plotting code + # The last key in q_index_clean contains the x-axis labels + last_key = q_index_clean[-1] + if last_key in data_all and "x_value" not in data: + data["x_value"] = data_all[last_key] + y_keys = data_filters + else: + # Handle filtering based on real research areas (not pseudo-categories) + if real_research_areas: + # Real research areas are selected - filter the data to include only those + exclude = [] + for field in RESEARCH_FIELDS: + # Only exclude fields that are real research areas (not pseudo-categories) + if field not in {"All", "Cum. Sum"} and field not in real_research_areas: + exclude.append(field) + + for filter_key in exclude: + df = df[df[filter_by] != filter_key] + # else: Only pseudo-categories selected - df remains unfiltered + + # Special case: if we're querying the research area question itself, + # we need different logic to avoid double-grouping by research areas + if q_index_0 == filter_by: # This is the research area question + # For research area distribution, create data structure directly + data = {} + # Use the full research area list as x_value for proper positioning + data["x_value"] = data_all.get(q_index_0, []) + + # Create arrays for each real research area selected + for area in real_research_areas: + # Create array with value at correct position, zeros elsewhere + area_array = np.zeros(len(data["x_value"])) + if area in data["x_value"]: + position = data["x_value"].index(area) + area_count = len(df[df[filter_by] == area]) + area_array[position] = area_count + data[area] = area_array + + # Handle "Cum. Sum" pseudo-category if selected + if "Cum. Sum" in pseudo_categories: + # Add cumulative sum data (this will be the total across all areas) + data["Cum. Sum"] = data_all.get("All", []) + + # Set y_keys to include both real areas and pseudo-categories + y_keys = real_research_areas + [cat for cat in pseudo_categories if cat != "All"] + else: + # Normal case: use prepare_data_research_field for other questions + data, y_keys = prepare_data_research_field(df, q_index) + + # Add "All" data if it's selected in the pseudo-categories + if "All" in pseudo_categories: + all_data = data_all.get("All", []) + + # Special handling for research area question + if q_index_0 == filter_by: # This is the research area question + # Add "All" data to our research area structure + data["All"] = all_data + # Make sure "All" is in y_keys + if "All" not in y_keys: + y_keys = ["All"] + y_keys + elif "researchArea" in data: + # When "All" + specific filters are selected, expand to show all research areas + # Use full "All" data and expand x_value to all research areas + data["All"] = all_data + data["x_value"] = data_all["researchArea"] + + # Expand specific research area data to match full x_value length + for key in data_filters: + if key != "All" and key in data: + # Find position of this research area in full x_value + try: + position = data["x_value"].index(key) + # Create array with value at correct position, zeros elsewhere + new_array = np.zeros(len(data["x_value"]), dtype=data[key].dtype) + new_array[position] = data[key][0] # Use first (and only) value + data[key] = new_array + except ValueError: + # If not found, just pad with zeros + padding = [0] * (len(data["x_value"]) - len(data[key])) + data[key] = list(data[key]) + padding + else: + # For other questions: truncate to match x_value length + if len(all_data) > len(data["x_value"]): + data["All"] = all_data[:len(data["x_value"])] + else: + data["All"] = all_data + + # Also expand Cum. Sum to match the new x_value length + if "Cum. Sum" in data: + cum_sum_data = data["Cum. Sum"] + if len(cum_sum_data) < len(data["x_value"]): + # Pad with zeros to match new length + if isinstance(cum_sum_data, np.ndarray): + padding = np.zeros(len(data["x_value"]) - len(cum_sum_data), dtype=cum_sum_data.dtype) + data["Cum. Sum"] = np.concatenate([cum_sum_data, padding]) + else: + padding = [0] * (len(data["x_value"]) - len(cum_sum_data)) + data["Cum. Sum"] = list(cum_sum_data) + padding + + # Prepare display specifications + ydata_spec = {} + colors = [] + for key in y_keys: + colors.append(RESEARCH_AREA_COLORS[key]) + + # Determine axis configuration + xtype = None + if q_index_0 in HCS_dtypesWOmc.keys(): + xtype = HCS_dtypesWOmc[q_index_0] + + if len(q_index) > 1: # multiple choice case + # Defensive: ensure x_value exists, fallback to using q_index_0 data + x_range = data.get("x_value", data.get(q_index_0, [])) + width = 0.1 + elif xtype == "category": + x_range = HCS_orderedCats[q_index_0] + width = 0.1 + else: + x_range = None + width = 0.6 + y_range = None + + ydata_spec["y_keys"] = y_keys + ydata_spec["colors"] = colors + ydata_spec["legend_labels"] = y_keys + selected = ColumnDataSource(data=data) + ydata_spec = ColumnDataSource(data=ydata_spec) + + display_options = { + "x_range": x_range, + "y_range": y_range, + "title": f"{question_full}", + "width": width, + } + + return selected, ydata_spec, display_options + + def select_data_corr(self, question, question2, data_filters, data_filters_method): + """Select the data to display in the correlation vis""" + q1_key = self.map_question_to_qkey(question) + q2_key = self.map_question_to_qkey(question2) + q1_index_0 = q1_key[0] + q2_index_0 = q2_key[0] + + # Determine axis ranges and types + xtype = None + if q1_index_0 in HCS_dtypesWOmc.keys(): + xtype = HCS_dtypesWOmc[q1_index_0] + + if xtype == "category": + x_range = HCS_orderedCats[q1_index_0] + else: + x_range = None + + ytype = None + if q2_index_0 in HCS_dtypesWOmc.keys(): + ytype = HCS_dtypesWOmc[q2_index_0] + if ytype == "category": + y_range = HCS_orderedCats[q2_index_0] + else: + y_range = None + + # Clean up missing columns + q1_key_clean = [] + keys = list(self.survey_data.keys()) + for key in q1_key: + if key in keys: + q1_key_clean.append(key) + + q2_key_clean = [] + for key in q2_key: + if key in keys: + q2_key_clean.append(key) + + exclude_nan = True + if len(q1_key) > 1: + exclude_nan = False + + # Process method filters + method_include = [] + method_exclude = [] + methods_dict = HCS_MCsubquestions[FILTER_BY_2] + for method in data_filters_method: + for key, val in methods_dict.items(): + if val == method: + method_include.append(key) + method_exclude.append((key, [False])) + + include_clean = list( + set([FILTER_BY] + q2_key_clean + q1_key_clean + method_include) + ) + + # Filter dataframe + df = filter_dataframe( + self.survey_data, + include=include_clean, + exclude=method_exclude, + exclude_nan=exclude_nan, + ) + + # Calculate cross-tabulation + cross_tab = calculate_crosstab(df, q1_index_0, q2_index_0) + marker_scale = 20.0 + cross_tab["markersize"] = percentage_to_area( + cross_tab["percentage"], scale_m=marker_scale + ) + cross_tab["x_values"] = cross_tab[q1_index_0] + cross_tab["y_values"] = cross_tab[q2_index_0] + cross_tab["color"] = ["#A0235A" for i in cross_tab[q2_index_0]] + + # Configure tooltips + tooltips = [ + (f"{q1_key[0]}", "@x_values"), + (f"{q2_key[0]}", "@y_values"), + ("total", "@total"), + ("percentage", "@percentage"), + ] + + title = f"" + # Strip ★ indicator for cleaner axis labels + xlabel = f"{question.replace('★ ', '')}" + ylabel = f"{question2.replace('★ ', '')}" + + selected = ColumnDataSource(cross_tab) + + display_options = { + "x_range": x_range, + "y_range": y_range, + "xlabel": xlabel, + "ylabel": ylabel, + "title": title, + "tooltips": tooltips, + } + + return selected, display_options, marker_scale + + def select_data_wordcloud(self, data_filters, data_filters_method, content): + """Filter data for wordcloud from data filters""" + word_list = [] + + method_include = [] + method_exclude = [] + methods_dict = HCS_MCsubquestions[FILTER_BY_2] + method_keys = list(methods_dict.keys()) + for method in data_filters_method: + for key in method_keys: + if methods_dict[key] == method: + method_include.append(key) + method_exclude.append((key, [False])) + + if len(data_filters_method) == 0: + method_include = method_keys + method_exclude = [] + + # Process content specification + data_include = [] + if "dataGenMethodSpec_" in content: + for i, method in enumerate(method_include): + id_meth = method[-1] + if id_meth == "r": # From other + id_meth = i + 1 + data_include.append("dataGenMethodSpec_{}_1".format(id_meth)) + data_include.append("dataGenMethodSpec_{}_2".format(id_meth)) + data_include.append("dataGenMethodSpec_{}_3".format(id_meth)) + else: + data_include = content + + # Filter dataframe + df = filter_dataframe( + self.survey_data, + include=[FILTER_BY] + method_include + data_include, + exclude=method_exclude, + as_type="str", + ) + + # Filter by research areas + exclude = [] + for field in RESEARCH_FIELDS: + if field not in data_filters: + exclude.append(field) + if "All" in data_filters: + exclude = [] + for area in exclude: + df = df[df[FILTER_BY] != area] + + # Prepare word list + word_list = [] + for method in data_include: + w_list = [word for word in df[method] if str(word) != "nan"] + word_list = word_list + w_list + + return word_list \ No newline at end of file diff --git a/survey_dashboard/data/display_specifications/hmc_custom_layout.py b/survey_dashboard/data/display_specifications/hmc_custom_layout.py deleted file mode 100644 index fa7004a..0000000 --- a/survey_dashboard/data/display_specifications/hmc_custom_layout.py +++ /dev/null @@ -1,45 +0,0 @@ -hmc_custom_css_accordion =''' -.bk.card { - border: 1px solid rgba(0,0,0,.125); - border-radius: 0.25rem; -} -.bk.accordion { - border: 1px solid rgba(0,0,0,.125); -} -.bk.card-header { - align-items: center; - background-color: rgba(0, 0, 0, 0.03); - border-radius: 0.25rem; - display: inline-flex; - justify-content: start; - width: 100%; -} -.bk.accordion-header { - align-items: center; - background-color: rgba(0, 0, 0, 0.03); - border-radius: 0; - display: flex; - justify-content: start; - width: 100%; -} -.bk.card-button { - background-color: transparent; - margin-left: 0.5em; -} -.bk.card-header-row { - position: relative !important; -} -.bk.card-title { - align-items: left; - font-size: 1.4em; - font-weight: bold; - overflow-wrap: break-word; -} -.bk.card-header-row > .bk { - overflow-wrap: break-word; - text-align: left; -} -''' -#rgba(0, 0, 0, 0.03); -#"#005AA0" : rgba(0, 90, 160, 0.53); -# background-color: rgba(0, 90, 160, 0.53); diff --git a/survey_dashboard/data/generate_overview.py b/survey_dashboard/data/generate_overview.py deleted file mode 100644 index f0cf70e..0000000 --- a/survey_dashboard/data/generate_overview.py +++ /dev/null @@ -1,12 +0,0 @@ - - - -def generate_overview(): - - - data_overview = [] - return - -def generate_tools(): - - return \ No newline at end of file diff --git a/survey_dashboard/data/display_specifications/hcs_clean_dictionaries.py b/survey_dashboard/data/hcs_clean_dictionaries.py similarity index 97% rename from survey_dashboard/data/display_specifications/hcs_clean_dictionaries.py rename to survey_dashboard/data/hcs_clean_dictionaries.py index 1570340..21aafd6 100644 --- a/survey_dashboard/data/display_specifications/hcs_clean_dictionaries.py +++ b/survey_dashboard/data/hcs_clean_dictionaries.py @@ -15,9 +15,9 @@ ########################################## ############### DICTIONARY ############### ########## RENAME COLUMN NAMES ########### -########################################## +########################################## -# Dictionary to rename columns in df for better readability +# Dictionary to rename columns in df for better readability HCS_colnamesDict = { "PERBG1/_":"centerAffiliation", @@ -287,7 +287,7 @@ ########################################## ############### DICTIONARY ############### ###### DEFINE DATA TYPES OF COLUMNS ###### -########################################## +########################################## ### for categorical, numerical and string answers @@ -334,26 +334,26 @@ ############################################### #################### LIST ##################### ###### SPECIFY MULTIPLE CHOICE QUESTIONS ###### -############################################### +############################################### # List to specify all multiple choice questions # For MC question cleaning # List includes common strings of MC question column names HCS_MCList = [ - "dataGenMethod_", - "lsfIdent_", + "dataGenMethod_", + "lsfIdent_", "dataFormats_", - "pubMethod_", - "pubMotivation_", + "pubMethod_", + "pubMotivation_", "pubObstaclesA_", "pubObstaclesB_", - "pubMetadata_", - "docMethod_", - "docMetadata_", - "docMotivation_", - "docStandards_", - "docObstacles_", + "pubMetadata_", + "docMethod_", + "docMetadata_", + "docMotivation_", + "docStandards_", + "docObstacles_", "servNeeds_sub_", "RSDP2", "RSDP1c", @@ -377,7 +377,7 @@ ########################################## # Dictionary to convert MC answers to dtype = 'boolean' -# In this case, MC questions were exported with 'Yes'/'No' answers +# In this case, MC questions were exported with 'Yes'/'No' answers convertToBoolDict = { 'Y':True, @@ -439,7 +439,7 @@ ####################################################### # Dictionary specifying the subquestions of multiple choice questions - + HCS_MCsubquestions = { "dataFormats_":{"dataFormats_1":"archives", "dataFormats_2":"audiovisual \n formats", @@ -457,7 +457,7 @@ "dataFormats_14":"structured text", "dataFormats_15":"binary scientific \n formats" }, - + "dataGenMethod_":{'dataGenMethod_1':"imaging", 'dataGenMethod_2':"analytical methods", 'dataGenMethod_3':"simulations", @@ -466,13 +466,13 @@ 'dataGenMethod_6':"recordings", 'dataGenMethod_other':"other" }, - - "dataStorage_":{'dataStorage_0':"I don't know.", - 'dataStorage_1':"locally", + + "dataStorage_":{'dataStorage_0':"I don't know.", + 'dataStorage_1':"locally", 'dataStorage_2':"centrally \n (internal server)", 'dataStorage_3':"externally \n (servers / repositories)" }, - + "docMetadata_":{'docMetadata_2':"contextual information", 'docMetadata_3':"provenance of data", 'docMetadata_4':"information on data collection", @@ -482,13 +482,13 @@ 'docMetadata_8':"information on storage \n and long-term preservation", 'docMetadata_9':"access information" }, - - "docMethod_":{'docMethod_0':"no documentation", - 'docMethod_1':"pen and paper", - 'docMethod_2':"digital system", + + "docMethod_":{'docMethod_0':"no documentation", + 'docMethod_1':"pen and paper", + 'docMethod_2':"digital system", 'docMethod_3':"digital text" }, - + "docMotivation_":{'docMotivation_0':"no specific reason", 'docMotivation_1':"improved findability", 'docMotivation_2':"provide research \n data context", @@ -497,7 +497,7 @@ 'docMotivation_5':"scientific community \n recognition", 'docMotivation_6':"administrative guidelines" }, - + "docObstacles_":{'docObstacles_0':"no difficulties", 'docObstacles_1':"lack of resources", 'docObstacles_4':"lack of incentives", @@ -507,7 +507,7 @@ 'docObstacles_8':"no apparent benefits.", 'docObstacles_9':"lack of experience" }, - + "docStandards_":{'docStandards_1':"DataCite", 'docStandards_10':"MiAIRR", 'docStandards_11':"MIBBI", @@ -535,7 +535,7 @@ 'docStandards_8':"MIxS", 'docStandards_9':"Darwin Core" }, - + "lsfIdent_":{'lsfIdent_1':"LHC", 'lsfIdent_10':"SIS18", 'lsfIdent_11':"ESR", @@ -548,7 +548,7 @@ 'lsfIdent_8':"European XFEL", 'lsfIdent_9':"UNILAC" }, - + "pubMetadata_":{'pubMetadata_0':"none", 'pubMetadata_1':"all of them", 'pubMetadata_21':"name of data set", @@ -575,12 +575,12 @@ 'pubMetadata_92':"logs / statistics", 'pubMetadata_93':"registration procedures" }, - - "pubMethod_":{'pubMethod_1':"supplementary to \n journal publication", - 'pubMethod_2':"in repository", + + "pubMethod_":{'pubMethod_1':"supplementary to \n journal publication", + 'pubMethod_2':"in repository", 'pubMethod_3':"data journal" }, - + "pubMotivation_":{'pubMotivation_1':"reusability", 'pubMotivation_2':"visibility", 'pubMotivation_3':"publication statistics", @@ -589,8 +589,8 @@ 'pubMotivation_6':"collaboration", 'pubMotivation_7':"financial benefits" }, - - "pubObstaclesA_":{'pubObstaclesA_0':"no obstacles", + + "pubObstaclesA_":{'pubObstaclesA_0':"no obstacles", 'pubObstaclesA_1':"costs too high", 'pubObstaclesA_2':"lack of time / personnel", 'pubObstaclesA_3':"lack of incentives", @@ -599,7 +599,7 @@ 'pubObstaclesA_6':"legal / ethical concerns", 'pubObstaclesA_7':"technical support needed" }, - + "pubObstaclesB_":{'pubObstaclesB_0':"no data to publish", 'pubObstaclesB_1':"costs too high", 'pubObstaclesB_2':"lack of time / personnel", @@ -608,8 +608,8 @@ 'pubObstaclesB_5':"technical barriers", 'pubObstaclesB_6':"legal / ethical concerns", 'pubObstaclesB_7':"technical support needed" - }, - + }, + "servNeeds_sub_":{'servNeeds_sub_0':"no need for support", 'servNeeds_sub_1':"data publication", 'servNeeds_sub_2':"research data reuse", @@ -631,32 +631,32 @@ ####################################################### HCS_orderedCats = { - "yearsInResearch":['No degree', - 'Less than 1 year', - '1 to 3 years', - '4 to 6 years', - '7 to 10 years', + "yearsInResearch":['No degree', + 'Less than 1 year', + '1 to 3 years', + '4 to 6 years', + '7 to 10 years', 'More than 10 years'], - "careerLevel":['Student', - 'PhD candidate', 'Postdoc', - 'Research Associate', - 'Principal Investigator', - 'Technical Staff', + "careerLevel":['Student', + 'PhD candidate', 'Postdoc', + 'Research Associate', + 'Principal Investigator', + 'Technical Staff', 'Other'], "dataInPublication":['< 100 MB', - '100 MB - 1000 MB (1 GB)', - '1 GB - 10 GB', - '10 GB - 100 GB', + '100 MB - 1000 MB (1 GB)', + '1 GB - 10 GB', + '10 GB - 100 GB', '100 GB - 1000 GB (1 TB)', '> 1 TB', 'I don\'t know'], - "experimentDuration_sub":['Less', - 'As much', - 'More', + "experimentDuration_sub":['Less', + 'As much', + 'More', 'I don\'t know'], - "dataAnalDuration_sub":['Less', - 'As much', - 'More', + "dataAnalDuration_sub":['Less', + 'As much', + 'More', 'I don\'t know'], 'dataAmount_lsf': [0.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0, 65.0, 70.0, 75.0, 80.0, 85.0, 90.0, 95.0, 100.0], @@ -2193,7 +2193,7 @@ # This what will be displayed in selection widgets and titles HCSquestions_long = { - "EN" : { + "EN" : { "PERBG1/_":"Which Helmholtz center do you typically work in?", "PERBG2/_":"Please select the Helmholtz research field you associate yourself with.", "PERBG3/_":"Please select your principle research area.", @@ -2278,7 +2278,7 @@ } # These are used as displays on selection and for titles HCSquestions = { # shortened - "EN" : { + "EN" : { "PERBG1/_":"Helmholtz center participants typically work in", "PERBG2/_":"Helmholtz research field participants associate with.", "PERBG3/_":"Principle research area of participants.", @@ -2406,31 +2406,32 @@ "careerLevel", "orcid", "fairFamiliarity", -"dataAmount_lsf", "dataInPublication", -"dataGatherTime", "experimentDuration_sub", "dataAnalDuration_sub", "longtermStorage", -"pubAmount", "docStructured", -"docDefSchema"] +"docDefSchema", +] multi_chart_allowed = [ "dataGenMethod_", "lsfIdent_", -"dataFormats_", -"pubMethod_", -"pubMotivation_", -"pubObstacles_", -"pubMetadata_", -"pubStorage_", -"docMethod_", -"docMetadata_", -"docMotivation_", -"docStandards_", +"dataFormats_", +"pubMethod_", +"pubMotivation_", +"pubObstacles_", +"pubMetadata_", +"pubStorage_", +"docMethod_", +"docMetadata_", +"docMotivation_", +"docStandards_", "docObstacles_", "servNeeds_sub_" +"dataAmount_lsf", +"dataGatherTime", +"pubAmount", ] @@ -2481,11 +2482,11 @@ "Physics", "Psychology"], "CareerLevel" : - ['Student', - 'PhD candidate', - 'Postdoc', - 'Research Associate', - 'Principal Investigator', - 'Technical Staff', + ['Student', + 'PhD candidate', + 'Postdoc', + 'Research Associate', + 'Principal Investigator', + 'Technical Staff', 'Other'] } diff --git a/survey_dashboard/data/hmc_survey_2021_data.csv b/survey_dashboard/data/hmc_survey_2021_data.csv new file mode 100644 index 0000000..3057e65 --- /dev/null +++ b/survey_dashboard/data/hmc_survey_2021_data.csv @@ -0,0 +1,643 @@ +# Dataset: HMC Survey 2021 Data +# Title: Helmholtz Metadata Collaboration Survey 2021 +# Description: Survey data on research data management practices within the Helmholtz Association +# Year: 2021 +# Source: Helmholtz Metadata Collaboration +# License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/) +# Last Updated: 2021 +# Contact: For questions about this dataset, please refer to the project repository +# Format: CSV (Comma-Separated Values) +# Encoding: UTF-8 +# This dataset is identical to the following original publication: Arndt, W., Gerlich, S. C., Hofmann, V., Kubin, M., Kulla, L., Lemster, C., Mannix, O., Nolden, M., Rink, K., Schweikert, J., Shankar, S., Söding, E., Steinmeier, L., & Suess, W. (2022). HMC Community Survey 2021 (Version 1.0.0) [Data set]. GESIS, Cologne. https://doi.org/10.7802/2433. +"id","DTPUB1b/1","DTPUB1b/2","DTPUB1b/3","DTPUB1b/other","DTPUB3/1","DTPUB3/2","DTPUB3/3","DTPUB3/4","DTPUB3/5","DTPUB3/6","DTPUB3/7","DTPUB3/other","DTPUB4a/0","DTPUB4a/1","DTPUB4a/2","DTPUB4a/3","DTPUB4a/4","DTPUB4a/5","DTPUB4a/6","DTPUB4a/7","DTPUB4a/other","DTPUB4b/0","DTPUB4b/1","DTPUB4b/2","DTPUB4b/3","DTPUB4b/4","DTPUB4b/5","DTPUB4b/6","DTPUB4b/7","DTPUB4b/other","DTPUB5/1","DTPUB5/2","DTPUB5/3","DTPUB5/4","DTPUB5/5","DTPUB6/1","DTPUB7/1","DTPUB7/21","DTPUB7/22","DTPUB7/23","DTPUB7/24","DTPUB7/31","DTPUB7/32","DTPUB7/33","DTPUB7/41","DTPUB7/42","DTPUB7/43","DTPUB7/44","DTPUB7/51","DTPUB7/52","DTPUB7/61","DTPUB7/62","DTPUB7/71","DTPUB7/72","DTPUB7/81","DTPUB7/82","DTPUB7/83","DTPUB7/91","DTPUB7/92","DTPUB7/93","DTPUB7/other","DTPUB7/0","interviewtime/_","lastpage/_","PERBG1/_","PERBG1/other","PERBG2/_","PERBG3/_","PERBG3/other","PERBG3AGRI/_","PERBG3AGRI/other","PERBG3BIO/_","PERBG3BIO/other","PERBG3CHEM/_","PERBG3CHEM/other","PERBG3GEO/_","PERBG3GEO/other","PERBG3ING/_","PERBG3ING/other","PERBG3LIFE/_","PERBG3LIFE/other","PERBG3MATH/_","PERBG3MATH/other","PERBG3MED/_","PERBG3MED/other","PERBG3PHYS/_","PERBG3PHYS/other","PERBG3PSYCH/_","PERBG3PSYCH/other","PERBG4/_","PERBG6/_","PERBG6/other","PERBG7/_","PERBG8/_","RDMPR1/1","RDMPR1/2","RDMPR1/3","RDMPR1/0","RDMPR1/other","RDMPR10/1","RDMPR10/2","RDMPR10/3","RDMPR11/0","RDMPR11/1","RDMPR11/4","RDMPR11/5","RDMPR11/6","RDMPR11/7","RDMPR11/8","RDMPR11/9","RDMPR11/other","RDMPR12/1","RDMPR12/2","RDMPR12/3","RDMPR12/4","RDMPR12/5","RDMPR12/6","RDMPR12/0","RDMPR12/other","RDMPR3/1","RDMPR3/2","RDMPR3/3","RDMPR3/other","RDMPR3/0","RDMPR4/_","RDMPR5/_","RDMPR6/1","RDMPR6/2","RDMPR6/3","RDMPR6/4","RDMPR6/5","RDMPR6/6","RDMPR6/7","RDMPR6/8","RDMPR6/9","RDMPR6/10","RDMPR6/11","RDMPR6/12","RDMPR6/13","RDMPR6/14","RDMPR6/15","RDMPR6/16","RDMPR6/17","RDMPR6/18","RDMPR6/19","RDMPR6/20","RDMPR6/21","RDMPR6/22","RDMPR6/23","RDMPR6/24","RDMPR6/25","RDMPR6/26","RDMPR6/other","RDMPR7/2","RDMPR7/3","RDMPR7/4","RDMPR7/5","RDMPR7/6","RDMPR7/7","RDMPR7/8","RDMPR7/9","RDMPR7/other","RDMPR8/2","RDMPR8/3","RDMPR8/4","RDMPR8/5","RDMPR8/6","RDMPR8/7","RDMPR8/8","RDMPR8/9","RDMPR8/10","RDMPR9/2","RDMPR9/3","RDMPR9/4","RDMPR9/5","RDMPR9/6","RDMPR9/7","RDMPR9/8","RDMPR9/9","RDMPR9/10","RSDP1/1A2","RSDP1/3A4","RSDP10/_","RSDP11/_","RSDP1b/1","RSDP1c/1","RSDP1c/2","RSDP1c/3","RSDP1c/4","RSDP1c/5","RSDP1c/6","RSDP1c/7","RSDP1c/8","RSDP1c/9","RSDP1c/10","RSDP1c/11","RSDP1c/other","RSDP2/1","RSDP2/2","RSDP2/3","RSDP2/4","RSDP2/5","RSDP2/6","RSDP2/other","RSDP2b/1-1","RSDP2b/1-2","RSDP2b/1-3","RSDP2b/2-1","RSDP2b/2-2","RSDP2b/2-3","RSDP2b/3-1","RSDP2b/3-2","RSDP2b/3-3","RSDP2b/4-1","RSDP2b/4-2","RSDP2b/4-3","RSDP2b/5-1","RSDP2b/5-2","RSDP2b/5-3","RSDP2b/6-1","RSDP2b/6-2","RSDP2b/6-3","RSDP2b/7-1","RSDP2b/7-2","RSDP2b/7-3","RSDP3/1","RSDP3/2","RSDP3/3","RSDP3/4","RSDP3/5","RSDP3/6","RSDP3/7","RSDP3/8","RSDP3/9","RSDP3/10","RSDP3/11","RSDP3/12","RSDP3/13","RSDP3/14","RSDP3/15","RSDP3/other","RSDP4/_","RSDP7/_","RSDP8/_","SERVC1/1","SERVC1/2","SERVC1/3","SERVC1/4","SERVC1/5","SERVC1/6","SERVC1/7","SERVC1/8","SERVC1/9","SERVC1/other","SERVC1/0","SERVC2/1","SERVC2/2","SERVC2/3","SERVC2/4","SERVC2/5","SERVC2/6","submitdate/_" +"2","","True","","","True","","","True","True","","","","","","True","True","","","","True","","","","","","","","","","","Institutional Repository","","","","","75.0","","True","","True","True","True","True","","","","","","","","","","","","","","","","","","","","621.07","Completed the survey","Anonymized","Anonymized","Energy","Mathematics","","","","","","","","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","Principal Investigator","","Familiar with FAIR","","","","","Other","R","LaTeX","Office Software (unspecified)","","True","","True","True","","","","","","","","","","","","","","","","Source code and scripts","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","","","Some of them","Some of them","","","","Some of them","","","","None","None","","","","None","","","","Mostly simulated","Mostly reused","Not sure","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","True","True","True","","","","","","< 100 MB","","","","","True","True","True","","","True","","","very interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"3","True","","","","True","","","True","","","","","","","True","","","","","","","","","","","","","","","","","","","","","75.0","","True","","","","True","","","","","","","","","","","","","","","","","","","","","1238.44","Completed the survey","Anonymized","Anonymized","Energy","Chemistry","","","","","","","Radiochemie","","","","","","","","","","","","","","","More than 10 years","Research Associate","","","Apply FAIR","True","True","True","","","Anonymized","Anonymized","gnuplot","True","","","","","","","","","","","","","","","","Improved working with data","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","Some of them","Some of them","","","","","","","","None","None","","","","","","","","Mostly measured","Purely reused","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","","","< 100 MB","","","","True","","True","","","","True","","","very interested","very interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"4","True","True","","","True","True","","","","True","","","","","True","","","True","","True","","","","","","","","","","","Institutional Repository","","","","","35.0","","True","","True","True","True","","","True","True","","","","","","","","","","","","","","","","","408.27","Completed the survey","Anonymized","Anonymized","Energy","Earth Science","","","","","","","","","Geoanalytik","","","","","","","","","","","","","More than 10 years","Research Associate","","","Apply FAIR","True","","","","","OriginLab","Anonymized","Anonymized","","True","","True","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","Some of them","Some of them","","","","","","None","None","None","None","","","","","","Mostly measured","Equally generated and reused","Yes","","45.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","True","True","","True","","True","","True","True","","","1 GB - 10 GB","","","True","True","","True","True","","","True","","","very interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"7","True","","","","","True","","","True","True","","","","","","True","","True","True","","","","","","","","","","","","","","","","","5.0","","","","True","True","True","","","True","True","True","","","","","","","","","","","","","","","","496.93","Completed the survey","Anonymized","Anonymized","Energy","Earth Science","","","","","","","","","Geochemie","","","","","","","","","","","","","More than 10 years","Research Associate","","","Familiar with FAIR","","True","","","","Anonymized","R","Python","","True","","","","","","","","True","","","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","None","None","Some of them","Some of them","","","","","","None","None","None","None","","","","","","Purely measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","True","True","","True","","","","True","","","100 GB - 1000 GB (1 TB)","","True","","","True","True","","True","True","True","","","moderately interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"9","True","True","","","True","True","","","True","","","","True","","","","","","","","","","","","","","","","","","Institutional Repository","","","","","65.0","","","","","","","","","","","","True","","","True","True","","","","","","","","","","","2455.36","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","7 to 10 years","Postdoc","","","Not familiar with FAIR","","True","True","","","MATLAB / Simulink","OpenFOAM","Excel (Spreadsheets)","","True","True","","True","","","","","","","","","","","","","True","","","Other","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","Some of them","Some of them","Some of them","","All","","","","","None","None","None","","None","","","","","Equally measured and simulated","Purely generated","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","True","","","","","","10 GB - 100 GB","","","","True","True","","","","True","","","","moderately interested","very interested","not interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"10","True","","True","","","","True","True","True","","","","","","True","True","True","","","","","","","","","","","","","","","","","","","25.0","","","","True","True","True","","","","","","","","","","","","","","","","","","","","","468.87","Completed the survey","Anonymized","Anonymized","Energy","","Biowissenschaften","","","","","","","","","","","","","","","","","","","","","4 to 6 years","Research Associate","","","Not familiar with FAIR","","True","","","","Office Software (unspecified)","Anonymized","Anonymized","","True","","True","","","","","","True","True","True","True","","","","Improved collaborations","","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","Some of them","Some of them","","","","","","","","Purely measured","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","True","","","","","","True","","","","","","100 MB - 1000 MB (1 GB)","","True","True","True","True","True","","","","","","","very interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"12","True","","","In repository","True","True","","","","True","","","","","True","","","","True","True","","","","","","","","","","","","","","","","40.0","","","","True","True","True","","","True","True","True","","","","True","True","","","","","","","","","","","402.71","Completed the survey","Anonymized","Anonymized","Energy","Chemistry","","","","","","Geochemistry","","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","True","True","True","","","Database Management System","Anonymized","Anonymized","","True","","","True","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","All","All","Some of them","","All","","","","","Some of them","Some of them","None","","Some of them","","","","","Mostly measured","Purely reused","Yes","","5.0","","","","","","","","","","","","Anonymized","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","True","","True","","","","100 MB - 1000 MB (1 GB)","","","","True","","True","True","","","True","","","moderately interested","very interested","very interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"14","","True","","","","True","","","True","True","","","","","","True","","","","True","Legal / ethical concerns","","","","","","","","","","Institutional Repository","","","","","15.0","","True","True","True","True","True","","","","","","","True","","","","True","","","","","","","","","","759.6","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Process Engineering","","","","","","","","","","","","4 to 6 years","Postdoc","","","Familiar with FAIR","","True","","","","OpenFOAM","","","","","","","","","","","Lack of resources","","","","","","","","","","True","","Source code and scripts","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","True","","True","Instructions for reuse","All","All","","All","","All","","All","All","None","None","","None","","None","","","None","Mostly simulated","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","True","","","True","True","","","True","","","","1 GB - 10 GB","","True","","","","","True","","True","True","","","moderately interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"16","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","282.9","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Familiar with FAIR","","True","","","","Python","","","","True","True","True","True","","","True","","","","","","","","","","","","","GitLab","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","","","Some of them","All","","","","","","None","","None","None","","","","","","Mostly measured","Purely generated","Not sure","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","True","","","","","100 MB - 1000 MB (1 GB)","","True","True","True","True","","True","","True","","","","very interested","moderately interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"17","","","","In repository","True","True","","","True","","","","","","True","True","","","","","","","","","","","","","","","","","","","","95.0","","","","","","","","","","","True","","","","","","True","","","","","","","","","","404.09","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","Principal Investigator","","Apply FAIR","","True","","","","OpenFOAM","Paraview","Anonymized","","","","True","True","","","","","","","","","","","","","","","","GitLab","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","All","","","All","","","","","","All","","","All","","","","Purely simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","True","True","","","","","","","10 GB - 100 GB","","","","","","True","True","","","True","","","moderately interested","very interested","moderately interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"20","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","424.81","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","","Softwareentwicklung","","","","","","","","","","","7 to 10 years","Research Associate","","","Familiar with FAIR","","True","","","","Python","Git","","","True","","","True","True","","","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","Some of them","","","Some of them","","","","","","Some of them","","","Some of them","","","","","Purely simulated","Purely reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","True","True","True","","True","True","","","100 MB - 1000 MB (1 GB)","","","","","True","","","True","","True","","","very interested","very interested","moderately interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"21","","True","","","True","True","","True","","","","","","","True","True","","","","","","","","","","","","","","","Institutional Repository","","","","","30.0","","","","True","True","True","True","","True","True","True","True","","True","","","","","","","","","","","","","398.98","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Mechanical Engineering","","","","","","","","","","","","4 to 6 years","PhD candidate","","","Familiar with FAIR","","","True","","","Anonymized","Anonymized","LaTeX","","","","True","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","Some of them","Some of them","Some of them","Some of them","None","","","","","Purely measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","True","","","True","True","True","True","","","","> 1 TB","","","","True","","True","","","True","","","","very interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"23","","True","","","","","","True","True","True","","","","","True","True","True","","","","","","","","","","","","","","Institutional Repository","","","","","100.0","","","","True","True","True","True","True","True","True","True","True","","True","True","True","","","","","","","","","","","336.16","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Process Engineering","","","","","","","","","","","","4 to 6 years","PhD candidate","","","Familiar with FAIR","","True","True","","","ImageJ","MATLAB / Simulink","Mathematica","","True","True","True","","","","","","","","","","","","","","","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","Some of them","Some of them","None","None","","","","","Purely measured","Mostly generated","Yes","","30.0","","","","","","","","","","","","Anonymized","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","100 GB - 1000 GB (1 TB)","","","True","True","True","","","True","","True","","","very interested","very interested","very interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"25","","","","Other","","","","True","","","","","","","True","True","","","","","","","","","","","","","","","","","","","","10.0","","","","True","True","True","True","True","","","","","","","","","","","","","","","","","","","452.94","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","7 to 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","Excel (Spreadsheets)","ANSYS","","","True","","","","","","","","","","True","","","","","Use of Standard","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","Some of them","","","","","","","","None","None","","","","","","","","Equally measured and simulated","Equally generated and reused","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","True","True","","","","True","True","True","","","","I don't know","","","","","","","True","","True","","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"28","","True","","","","True","","True","","True","","","","","","","","","True","","","","","","","","","","","","Gitlab / GitHub","","","","","10.0","","","","","","","","","","","","","","","","","","","","","","","","","","","800.95","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Not familiar with FAIR","","","","","Centrally (internal server)","Python","Anonymized","","","","","","","True","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","","","All","Some of them","All","All","All","All","","","","None","None","None","None","Some of them","None","","","","","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","True","","","","","True","","","I don't know","","","True","True","True","","","True","True","True","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"31","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","955.93","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","","Umweltwissenschaften","","","","","","","","","","","7 to 10 years","Research Associate","","","Familiar with FAIR","","True","","","","Excel (Spreadsheets)","Python","Anonymized","True","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","None","None","","","","","","","","Purely simulated","Purely reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","True","True","","True","","","","100 MB - 1000 MB (1 GB)","","True","","","True","True","","True","True","","","","moderately interested","very interested","not interested","not interested","very interested","not interested","1980-01-01 00:00:00" +"33","True","True","","","","True","","","True","True","","","","","","True","","","","","","","","","","","","","","","OSF","","","","","80.0","","True","True","","","True","","","","","","","","","","","","","","","","","","","","","284.96","Completed the survey","Anonymized","Anonymized","Energy","","Umwelt","","","","","","","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Apply FAIR","True","","","","","R","Python","Java","","True","True","","True","","","","","True","","True","","","","","","","","","Digital text","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","All","None","","","","","","","None","None","None","","","","","","","Purely simulated","Purely reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","True","","","","","","","True","","","","100 MB - 1000 MB (1 GB)","","True","True","","","","True","","","","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"34","True","","","","","","","True","","","","","","","True","","","","","","","","","","","","","","","","","","","","","5.0","","True","True","","","True","","True","","","","","","","True","True","True","","","","","","","","","","665.26","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","Less than 1 year","PhD candidate","","","Familiar with FAIR","","True","","","","Jupyter","LaTeX","QGIS/GDAL","","","","True","","True","","","","","","","","","","","","","","","Source code and scripts","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","","","All","All","All","All","All","All","","","","None","Some of them","None","None","None","None","","","","Purely simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","","True","True","True","","True","","","","I don't know","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"36","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","573.3","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","4 to 6 years","PhD candidate","","","Not familiar with FAIR","True","True","","","","Python","OriginLab","Excel (Spreadsheets)","","True","True","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","None","","","","","","","","","Equally measured and simulated","Mostly generated","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","True","","True","","","","100 MB - 1000 MB (1 GB)","","","","","","","True","","","","","","moderately interested","very interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"37","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","431.07","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","7 to 10 years","Research Associate","","","Familiar with FAIR","True","True","","","","Anonymized","Python","Git","","True","True","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","","","","","","","","","None","","","","None","","","","","Mostly simulated","Purely reused","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","True","","","","","","1 GB - 10 GB","","","","","","","","","","","","","not interested","very interested","very interested","not interested","not interested","moderately interested","1980-01-01 00:00:00" +"38","True","True","","","True","","","","True","True","","","True","","","","","","","","","","","","","","","","","","Institutional Repository","","","","","10.0","","True","","True","True","True","","True","","","","","True","","True","","","","","","","","","","","","635.54","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","More than 10 years","Research Associate","","","Apply FAIR","","True","","","","Anonymized","Anonymized","LabVIEW","True","","","","","","","","","True","True","","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","","","","All","All","","None","All","","","","","None","All","","None","None","","","","","Mostly measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","","","","","","","< 100 MB","","","","","","True","","","True","","","","moderately interested","very interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"41","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1644.75","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","True","True","","","","Excel (Spreadsheets)","OriginLab","Python","","True","","True","","","","","","True","","","","","","","","","True","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","None","","","","","","","","Mostly measured","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","True","","True","","","","100 MB - 1000 MB (1 GB)","","","","True","","True","","","","","","","very interested","very interested","moderately interested","not interested","not interested","very interested","1980-01-01 00:00:00" +"43","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","371.98","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","","True","","","","","","","","","","","True","","","","","True","","True","True","","","","","","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","","All","All","","","All","","","","","Some of them","Some of them","","","Some of them","","","","","Mostly measured","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","True","True","","","","","True","","","","","","I don't know","","","","","","","","","","","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"44","True","","","","","True","","True","","","","","","True","True","","","True","True","True","","","","","","","","","","","","","","","","10.0","","","","True","True","True","True","","","","","","","","","","","","","","","","","","","","682.57","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","","Batteriematerialien","","","","","","","","","","","More than 10 years","Postdoc","","","Familiar with FAIR","","True","","","","IDL","MATLAB / Simulink","Python","","True","","","True","True","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","Some of them","Some of them","","","","","","","","None","None","","","","","","","","Mostly measured","Purely generated","Yes","","80.0","","True","True","","","True","","","","","","Anonymized","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","True","True","","","100 GB - 1000 GB (1 TB)","","True","True","","True","","","True","","","","","moderately interested","very interested","moderately interested","moderately interested","not interested","very interested","1980-01-01 00:00:00" +"46","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","Lack of incentives","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","2872.46","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Research Associate","","","Familiar with FAIR","True","True","","","","OriginLab","IGOR","Office Software (unspecified)","","True","","","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","Some of them","Some of them","Some of them","","","","","","","Mostly measured","Mostly generated","Yes","","10.0","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","","","100 MB - 1000 MB (1 GB)","","True","True","","","True","True","","True","True","","","very interested","very interested","very interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"47","","True","","","","","","","True","","","","","","True","True","","","","","","","","","","","","","","","Institutional Repository","Gitlab / GitHub","","","","15.0","","","","True","True","","","","","","","","","","","","","","","","","","","","","","723.36","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Nanotechnology","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","","True","","","","Anonymized","Python","OriginLab","","True","","True","","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","None","","","","","","","","","Equally measured and simulated","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","True","","","","1 GB - 10 GB","","True","","True","True","","True","","True","True","","","moderately interested","moderately interested","moderately interested","not interested","not interested","very interested","1980-01-01 00:00:00" +"49","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","497.41","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Apply FAIR","True","","","","","Python","Anonymized","Anonymized","","","","","True","","","","","","","","","","","","","True","","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","Some of them","","Some of them","Some of them","Some of them","","","","","None","","All","None","None","","","","","Mostly measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","True","","","","True","","","True","True","","","100 MB - 1000 MB (1 GB)","","","","","","","","","","True","","","not interested","very interested","very interested","very interested","not interested","very interested","1980-01-01 00:00:00" +"50","","True","","","True","True","","","","True","","","","","True","","","","","","","","","","","","","","","","Zenodo","Open Energy Platform","","","","40.0","","","","","","True","","","","","","","","","","","","","","","","","","","","","553.61","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","4 to 6 years","Research Associate","","","Apply FAIR","","True","","","","Anonymized","Python","Word","","True","True","","","","","","","True","","True","True","","","","","","","","","True","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","None","","","","","","","","Purely simulated","","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","1 GB - 10 GB","","","","","True","True","","","","","","","very interested","moderately interested","not interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"51","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","3028.66","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","True","True","","","","Office Software (unspecified)","OriginLab","MATLAB / Simulink","True","","","","","","","","","True","True","True","","","","","","True","True","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","All","","All","","All","","","","","All","","All","","All","","","","","Mostly measured","Equally generated and reused","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","","True","True","True","True","True","","","","1 GB - 10 GB","","","","","","","","","","","","True","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"52","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","261.06","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Apply FAIR","True","","","","","Python","Anonymized","Anonymized","","","True","","True","","","","","True","True","True","","","","","","True","","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","All","","All","All","Some of them","","","","","Some of them","","Some of them","Some of them","None","","","","","Mostly measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","True","","","","True","","","True","True","","","100 MB - 1000 MB (1 GB)","","","","","","True","","","","True","","","not interested","very interested","very interested","very interested","not interested","very interested","1980-01-01 00:00:00" +"53","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","Other","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","447.21","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","7 to 10 years","Postdoc","","","Familiar with FAIR","","True","","","","Linux","Python","Anonymized","","","True","","","","","","","","","","","","","","","","","","GitLab","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","All","","","","","Mostly simulated","","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","100 MB - 1000 MB (1 GB)","","","","","","","","","","","","True","moderately interested","not interested","not interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"54","","","True","","","True","","","True","","True","","","","True","True","","","","True","","","","","","","","","","","","","","","","10.0","","","","True","True","","","","True","True","","","","True","","","","","","","True","","","","","","639.98","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","1 to 3 years","PhD candidate","","","Not familiar with FAIR","True","True","","","","Office Software (unspecified)","MATLAB / Simulink","Python","","True","True","True","True","","True","True","","True","True","True","True","True","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","True","","","All","","All","All","","","All","","","None","","None","None","","","None","","","Purely measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","True","","","","","","1 GB - 10 GB","","True","True","True","True","True","True","","True","True","","","moderately interested","moderately interested","moderately interested","moderately interested","","moderately interested","1980-01-01 00:00:00" +"56","","","","","","","","True","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","25.0","","","","","","True","","","True","True","True","","True","","","","","","","","","","","","","","848.94","Completed the survey","Anonymized","Anonymized","Energy","Chemistry","","","","","","Physical Chemistry","","","","","","","","","","","","","","","","Less than 1 year","PhD candidate","","","Not familiar with FAIR","","","","True","","FactSage","Python","LaTeX","","","True","","","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","All","Some of them","All","All","","","","","None","None","Some of them","Some of them","None","","","","","Equally measured and simulated","Equally generated and reused","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","","","","","I don't know","","","True","","True","True","True","","","","","","very interested","very interested","not interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"57","True","","","","","True","True","","True","","","","True","","","","","","","","","","","","","","","","","","","","","","","25.0","","True","","True","True","True","True","True","True","True","True","","","","","","","","","","","","","","","","636.53","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Research Associate","","","Familiar with FAIR","True","True","","","","Anonymized","Anonymized","IDL","True","","","","","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","None","","","","","","","All","All","None","","","","","","","Purely measured","Purely generated","Yes","","100.0","","","True","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","True","","","10 GB - 100 GB","","","","True","True","True","True","","","True","","","moderately interested","very interested","very interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"59","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","578.68","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","7 to 10 years","Postdoc","","","Apply FAIR","","","","True","","FactSage","Office Software (unspecified)","Python","","","","","","","","True","","","","True","","","","","Provide research data context","True","True","True","","","Yes","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","No standard","True","True","True","True","True","","","","","All","Some of them","Some of them","Some of them","Some of them","","","","","None","None","None","None","None","","","","","Mostly measured","Mostly generated","Not sure","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","True","True","True","","","","","","< 100 MB","","","","","","","","True","","","","","moderately interested","moderately interested","moderately interested","not interested","very interested","not interested","1980-01-01 00:00:00" +"65","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","321.59","Completed the survey","Anonymized","Anonymized","Energy","Chemistry","","","","","","","","","","","","","","","","","","","","","","No degree","Student","","","Familiar with FAIR","True","True","","","","","","","","","","","True","","","","","True","True","True","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","Some of them","","All","","","","","","","None","","None","","","","","Purely measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","True","","","","I don't know","","True","","True","True","True","True","True","","True","","","moderately interested","very interested","very interested","not interested","very interested","very interested","1980-01-01 00:00:00" +"66","True","","","","True","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","10.0","","","","","True","True","True","True","True","True","True","","","","","","","","","","","","","","","","1028.28","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Familiar with FAIR","True","","","","","","","","True","","","","","","","","","True","","","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","All","All","","","","","","","Some of them","All","All","","","","","","","Mostly measured","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","True","","","","","","100 MB - 1000 MB (1 GB)","","","","True","True","True","True","True","","","","","moderately interested","very interested","not interested","not interested","very interested","not interested","1980-01-01 00:00:00" +"68","","True","","","True","True","","","True","","","","","","True","","","","True","True","","","","","","","","","","","Open Energy Platform","","","","","75.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","487.52","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","More than 10 years","Postdoc","","","Familiar with FAIR","","True","","","","Python","Git","Excel (Spreadsheets)","","True","True","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","All","Some of them","Some of them","","","","","","None","None","None","None","","","","","","Mostly simulated","Mostly reused","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","True","","","","True","True","","True","True","","","1 GB - 10 GB","","","","True","True","","True","True","","","","","moderately interested","moderately interested","very interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"69","","True","","","","","","True","","","","","","","","True","","","","True","","","","","","","","","","","Zenodo","","","","","10.0","","True","","","","","","","True","True","True","","","","True","","","","","","","","","","","","5817.71","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","","Not familiar with FAIR","True","True","","","","IGOR","Office Software (unspecified)","Python","","True","","","True","","","","","","","","","","","","","True","True","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","True","","All","All","All","Some of them","All","","","All","","Some of them","All","Some of them","All","Some of them","","","All","","Purely measured","Purely generated","Yes","","100.0","","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","True","","","","","","1 GB - 10 GB","","","","","","","","","","","","True","moderately interested","moderately interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"71","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","890.24","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Process Engineering","","","","","","","","","","","","No degree","Student","","","Not familiar with FAIR","","","True","","","Excel (Spreadsheets)","Anonymized","","True","","","","","","","","","True","True","True","True","","True","","","","True","","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","Some of them","All","","","","","","","Mostly measured","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","I don't know","","","","","","","","True","True","","","","moderately interested","moderately interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"72","True","","","","True","True","","","True","","","","","","","True","True","","","","","","","","","","","","","","","","","","","100.0","","","","True","True","","","","","","","","","","","","","","","","","","","","","","573.38","Completed the survey","Anonymized","Anonymized","Energy","Chemistry","","","","","","","Material chemistry","","","","","","","","","","","","","","","1 to 3 years","PhD candidate","","","Not familiar with FAIR","","True","","","","FactSage","Anonymized","Anonymized","","True","","","","","","","","","","","","","","","","True","True","True","Digital text","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","","Some of them","","","Some of them","Some of them","","","","","Some of them","","","Some of them","Some of them","","","","","Equally measured and simulated","Purely generated","Not sure","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","True","","True","","","","","","I don't know","","","","","","","","","True","True","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"76","True","","","","True","","","","True","True","","","","","True","","","True","","","","","","","","","","","","","","","","","","40.0","","","","True","True","","True","","","","","","","","","True","","","","","","","","","","","545.48","Completed the survey","Anonymized","Anonymized","Energy","Chemistry","","","","","","Polymer Research","","","","","","","","","","","","","","","","More than 10 years","Postdoc","","","Not familiar with FAIR","True","True","","","","Anonymized","OriginLab","Anonymized","","True","","","","","","","","True","","True","True","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","","All","All","","","All","","","","","None","None","","","None","","","","","Purely measured","Purely generated","Yes","","95.0","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","True","True","","","1 GB - 10 GB","","","True","True","","True","","True","","","","","very interested","moderately interested","moderately interested","not interested","not interested","very interested","1980-01-01 00:00:00" +"77","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","404.93","Completed the survey","Anonymized","Anonymized","Energy","Chemistry","","","","","","Physical Chemistry","","","","","","","","","","","","","","","","More than 10 years","Research Associate","","","Familiar with FAIR","True","True","","","","IGOR","OriginLab","LabVIEW","","True","True","True","","","","","","True","True","True","","","","","","True","True","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","None","Some of them","Some of them","","","","","","","None","Some of them","Some of them","","","","","","","Purely measured","Purely generated","Yes","","15.0","","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","True","","True","","","","","","100 MB - 1000 MB (1 GB)","","True","True","True","True","True","","","","","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"79","","","","","","","","","","","","","","","","","","","","","","True","","","True","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","467.42","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","Less than 1 year","Research Associate","","","Familiar with FAIR","True","True","","","","Python","Database Management System","Anonymized","","True","True","","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Purely simulated","Purely reused","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","True","","","True","","","","100 MB - 1000 MB (1 GB)","","True","True","","","","","","True","","","","very interested","moderately interested","","very interested","","moderately interested","1980-01-01 00:00:00" +"80","True","True","","","True","True","","","","True","","","True","","","","","","","","","","","","","","","","","","Gitlab / GitHub","Institutional Repository","","","","60.0","","True","","","","","","","","","","","","","","","True","","","","","","True","","","","2568.22","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","4 to 6 years","Postdoc","","","Familiar with FAIR","","True","","","","Visual Studio","Python","Excel (Spreadsheets)","","True","True","True","","","","True","","","","","","","","","","","","","Other","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","True","","True","","All","","","","","All","","All","","None","","","","","None","","Some of them","","Mostly simulated","Equally generated and reused","No","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","100 MB - 1000 MB (1 GB)","","","","","True","True","True","","True","True","","","very interested","moderately interested","moderately interested","moderately interested","moderately interested","not interested","1980-01-01 00:00:00" +"81","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","458.3","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","1 to 3 years","PhD candidate","","","Not familiar with FAIR","True","True","","","","MATLAB / Simulink","Python","","","True","","","","","","True","Lack of resources","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","All","","","","","","","None","None","None","","","","","","","Mostly measured","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","True","","","True","","","","1 GB - 10 GB","","","","True","True","True","","True","","True","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"82","","True","","","","","","True","True","","","","","","True","True","","","True","","","","","","","","","","","","Zenodo","","","","","5.0","","","","","","","","","","","","","True","True","","","","","","","","","","","","","341.35","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","7 to 10 years","Postdoc","","","Apply FAIR","","True","","","","Anonymized","Anonymized","","","True","","","","True","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","Some of them","","","","","","Purely simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","True","","","","True","True","","True","","","","10 GB - 100 GB","","","","","","True","","True","True","","","","very interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"83","","","True","","","","","True","True","True","","","","","True","True","","","True","","","","","","","","","","","","","","","","","30.0","","True","","True","True","True","True","True","","True","True","","","True","","","","","","","","","","","","","763.09","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","True","","","","","Anonymized","MATLAB / Simulink","Excel (Spreadsheets)","","True","True","","","","True","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","True","","True","","Some of them","Some of them","Some of them","Some of them","","Some of them","","","","None","None","None","None","","None","","None","","Mostly simulated","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","True","True","True","True","True","True","","","","100 MB - 1000 MB (1 GB)","","","","","","","","","","","","True","","moderately interested","","","moderately interested","","1980-01-01 00:00:00" +"86","","","","Other","True","True","","True","","","","","","","","True","","","True","","Legal / ethical concerns","","","","","","","","","","","","","","","25.0","","True","True","","","True","True","True","","","","","","","True","","","","","","","True","","","","","840.18","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","True","True","","","","Anonymized","Database Management System","Anonymized","","True","True","True","","True","","","","True","","","True","","True","","","","True","True","","","Yes","Yes","","True","","True","","","","","","","","","","","","True","","True","","","","","","","","","","True","True","","True","True","","","True","","Some of them","Some of them","","Some of them","All","","","All","","None","None","","None","Some of them","","","Some of them","","Mostly measured","Mostly reused","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","True","True","True","","","","True","","True","","Structured text","","< 100 MB","","True","","","True","True","True","True","True","True","","","very interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"88","","True","","","True","True","","","","True","","","","","True","","","True","","","","","","","","","","","","","Institutional Repository","","","","","50.0","","","","","True","","","","","","","","True","","","","","","","","","","","","","","457.77","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Mechanical Engineering","","","","","","","","","","","","4 to 6 years","Postdoc","","","Not familiar with FAIR","","True","True","","","","","","","True","True","True","True","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","Some of them","","","All","","","","","","None","","","Some of them","","","","","","Purely measured","Purely generated","No","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","True","","","True","","","","1 GB - 10 GB","","","","True","True","","True","","True","True","","","not interested","moderately interested","moderately interested","moderately interested","moderately interested","not interested","1980-01-01 00:00:00" +"89","","","","","","","","True","","True","","","","","","","","True","True","True","","","","","","","","","","","","","","","","20.0","","","True","True","","","True","True","","","","","","","True","","","","","","","","","","","","527.92","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","1 to 3 years","Research Associate","","","Familiar with FAIR","","True","","","","Anonymized","Database Management System","Anonymized","","True","","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","True","","Some of them","Some of them","","","All","","","All","","None","None","","","None","","","Some of them","","Mostly measured","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","","","True","","","","","","","True","True","True","True","True","True","True","","","","very interested","moderately interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"90","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","873.47","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","1 to 3 years","PhD candidate","","","Familiar with FAIR","","True","","","","MATLAB / Simulink","Visual Studio","","","","","","","","","True","","","","","","","","","","","True","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Purely simulated","Mostly generated","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","< 100 MB","","","","","","","","","","","","True","","","","","","","1980-01-01 00:00:00" +"92","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","8196.33","Completed the survey","Anonymized","Anonymized","Energy","Chemistry","","","","","","Theoretical Chemistry","","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Apply FAIR","True","True","","","","Anonymized","Anonymized","Anonymized","","True","True","","","","","","","True","","True","True","","","","","","","","Source code and scripts","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","Some of them","Some of them","","","","","","","","Some of them","Some of them","","","","","","Purely simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","","","True","True","True","","","","","","10 GB - 100 GB","","","","","","","True","","True","","","","moderately interested","very interested","moderately interested","not interested","not interested","very interested","1980-01-01 00:00:00" +"95","True","True","","","True","True","","","","True","","","","","True","","","","","","","","","","","","","","","","Zenodo","","","","","25.0","","","","","","True","","","","","","","True","True","","","","","","","","","","","","","498.29","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Meteorology","","","","7 to 10 years","Research Associate","","","Familiar with FAIR","","True","","","","Jupyter","Anonymized","Notepad++","","","True","","","","True","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","Some of them","","Some of them","","","","","","","None","","None","","","","","","Mostly simulated","Purely reused","No","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","10 GB - 100 GB","","","","True","True","","True","","","True","","","moderately interested","moderately interested","not interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"96","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1514.97","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","True","","","","","Tecplot","Python","CFD Software (e.g. TecPlot, ParaView)","","True","","True","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","","Some of them","All","","","All","","","","","None","Some of them","","","None","","","","","Equally measured and simulated","Purely generated","Yes","","90.0","","","","","","","","","","","","Anonymized","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","","","True","True","","","True","","","1 GB - 10 GB","","","","","True","True","True","True","True","True","","","moderately interested","moderately interested","moderately interested","very interested","moderately interested","not interested","1980-01-01 00:00:00" +"98","True","","True","","True","True","","","True","","","","","","","","","True","True","","","","","","","","","","","","","","","","","90.0","","True","","True","True","True","True","","","","","","","","","","True","","","","","","","","","","450.87","Completed the survey","Anonymized","Anonymized","Energy","","Informatik","","","","","","","","","","","","","","","","","","","","","1 to 3 years","PhD candidate","","","Not familiar with FAIR","","True","","","","R","Python","LaTeX","","True","","True","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","","","All","All","","","","All","","","","None","None","","","","None","","","","Mostly measured","Mostly reused","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","100 MB - 1000 MB (1 GB)","","","True","True","True","True","","True","True","","","","moderately interested","moderately interested","very interested","not interested","very interested","not interested","1980-01-01 00:00:00" +"99","True","","","","True","True","","True","","","","","True","","","","","","","","","","","","","","","","","","","","","","","10.0","","","","True","True","","","","True","True","True","True","","True","","","","","","","","","","","","","1049.39","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","","True","","","","Python","LaTeX","Office Software (unspecified)","","True","","","True","","","","","","","","","","","","","True","True","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","Some of them","","Some of them","All","","","","","","None","","None","None","","","","","","Mostly measured","Purely generated","Yes","","10.0","","True","True","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","True","","","","","","","","","","","100 MB - 1000 MB (1 GB)","","","","True","True","True","True","","","True","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"101","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","True","Insufficiently trained","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","832.19","Completed the survey","Anonymized","Anonymized","Energy","Chemistry","","","","","","Physical Chemistry","","","","","","","","","","","","","","","","7 to 10 years","Postdoc","","","Not familiar with FAIR","True","True","","","","COMSOL Multiphysics","MATLAB / Simulink","LabVIEW","","True","","True","True","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","Some of them","Some of them","","Some of them","","","","","","None","Some of them","","None","","","","","","Mostly simulated","Mostly generated","Not sure","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","True","","True","True","True","","True","","","","1 GB - 10 GB","","True","","True","True","","True","","","True","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"104","","","","Other","","True","","","","True","","","","","","","","True","","","Lack of incentives","","","","","","","","","","","","","","","70.0","","","","True","True","","","","True","True","True","","","True","","","","","","","","","","","","","917.99","Completed the survey","Anonymized","Anonymized","Energy","Chemistry","","","","","","Analytical Chemistry","","","","","","","","","","","","","","","","7 to 10 years","Postdoc","","","Not familiar with FAIR","True","True","","","","MATLAB / Simulink","Mathematica","Anonymized","","True","","","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","Some of them","","Some of them","Some of them","","","","","","Some of them","","Some of them","Some of them","","","","","","Mostly measured","Purely generated","Not sure","","30.0","","","True","","","True","","","","","","Anonymized","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","","","True","","","","10 GB - 100 GB","","True","","","True","True","True","","True","","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"105","True","","","","True","","","","True","True","","","","","True","True","","True","True","True","","","","","","","","","","","","","","","","15.0","","True","","","","True","","","","","","","True","","True","True","","","","","","","","","","","445.07","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Apply FAIR","","True","","","","Anonymized","","","","True","True","True","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","True","","","","Some of them","Some of them","","Some of them","Some of them","Some of them","","","","None","None","","None","None","None","","","","Purely simulated","","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","True","","","True","","True","","True","True","","","100 GB - 1000 GB (1 TB)","","True","True","True","True","True","","True","True","True","","","very interested","very interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"107","True","","","","True","True","","","True","","","","","","True","","","","True","True","","","","","","","","","","","","","","","","15.0","","","","","","","","","True","True","True","True","True","True","","","","","","","","","","","","","6548.97","Completed the survey","Anonymized","Anonymized","Energy","","Materials Science","","","","","","","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","","True","","","","OriginLab","Anonymized","Python","","","","True","","","","True","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","Some of them","","Some of them","All","","","","","","None","","None","None","","","","","","Mostly measured","Purely generated","Yes","","90.0","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","True","","","","","","","100 MB - 1000 MB (1 GB)","","True","","True","","","","","","True","","","moderately interested","very interested","","moderately interested","","very interested","1980-01-01 00:00:00" +"108","True","True","","","True","","","True","True","","","","","","True","True","","","True","","","","","","","","","","","","Institutional Repository","","","","","10.0","","True","True","","True","True","","","","","","","True","True","True","","","","","","","","","","","","814.9","Completed the survey","Anonymized","Anonymized","Energy","Earth Science","","","","","","","","Geology","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","","True","","","","R","Anonymized","LaTeX","","True","","True","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","True","","True","","All","Some of them","","All","All","Some of them","","Some of them","","None","None","","None","None","None","","None","","Mostly measured","Mostly reused","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","True","True","","","","","","","100 MB - 1000 MB (1 GB)","","True","","True","True","True","True","","","","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"109","True","","","","True","","","","True","True","","","True","","","","","","","","","","","","","","","","","","","","","","","50.0","","","","True","True","True","","","True","True","True","True","True","True","","","","","","","","","","","","","757.21","Completed the survey","Anonymized","Anonymized","Energy","Chemistry","","","","","","Technical Chemistry","","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","True","True","","","","FactSage","Office Software (unspecified)","OriginLab","True","","","","","","","","","True","True","True","True","","","","","True","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","All","Some of them","Some of them","","","","","","Some of them","Some of them","Some of them","Some of them","","","","","","Mostly measured","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","True","True","","True","","True","True","","","","","I don't know","","","","","","","","","","","","True","","","","","","","1980-01-01 00:00:00" +"110","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","2457.07","Completed the survey","Anonymized","Anonymized","Energy","Chemistry","","","","","","Technical Chemistry","","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","True","True","","","","Python","Python","Python","","True","","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","None","Some of them","Some of them","","","","","","","Mostly measured","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","","True","True","True","","True","True","","","1 GB - 10 GB","","True","","","","True","","","True","","","","moderately interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"111","","True","","","True","","","","True","True","","","","","True","","","","","","Technical barriers","","","","","","","","","","Gitlab / GitHub","Other","","","","5.0","","True","","True","True","True","","True","","","True","","","","","","True","","","","","","","","","","1709.48","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Thermodynamics","","","","7 to 10 years","Research Associate","","","Not familiar with FAIR","","True","True","","","Visual Studio","MATLAB / Simulink","Notepad++","","True","","","","","","","Relevant metadata is missing","","","","","","","","","","","","GitLab","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","True","","","","All","All","All","","","All","","","","None","All","All","","","All","","","","Purely simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","True","True","","","< 100 MB","","","","True","True","","True","True","True","","","","very interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"113","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","610.52","Completed the survey","Anonymized","Anonymized","Energy","","Informatik","","","","","","","","","","","","","","","","","","","","","4 to 6 years","PhD candidate","","","Familiar with FAIR","","True","","","","Python","Git","","","True","True","","True","True","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","True","","","","Some of them","Some of them","","","Some of them","Some of them","","","","None","None","","","None","None","","","","Mostly measured","Mostly reused","Not sure","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","True","","","True","","","","< 100 MB","","True","True","True","True","","True","True","True","True","","","moderately interested","moderately interested","very interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"116","True","","","","True","True","","","True","","","","True","","","","","","","","","","","","","","","","","","","","","","","50.0","","","","","","","","","True","True","","","","","","","","","","","","","","","","","881.63","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Soft Matter Physics","","","","4 to 6 years","Postdoc","","","Not familiar with FAIR","True","","","","","OriginLab","MATLAB / Simulink","IGOR","","True","True","","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","None","","","","","","","Purely measured","Purely generated","Yes","","10.0","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","True","","True","","","","100 MB - 1000 MB (1 GB)","","","","True","True","True","True","","True","","","","moderately interested","very interested","moderately interested","moderately interested","very interested","not interested","1980-01-01 00:00:00" +"119","True","","True","","True","True","","","","True","","","","","","True","","True","","","","","","","","","","","","","","","","","","25.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","672.91","Completed the survey","Anonymized","Anonymized","Energy","Earth Science","","","","","","","","Geology","","","","","","","","","","","","","","7 to 10 years","Postdoc","","","Apply FAIR","","True","","","","","","","","True","","","True","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","Some of them","Some of them","","Some of them","","","","","Purely measured","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","True","True","","","","True","","","10 GB - 100 GB","","","","","True","True","","True","","True","","","moderately interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"122","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","786.3","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","More than 10 years","Research Associate","","","Apply FAIR","True","True","","","","Python","LaTeX","Git","","True","","","True","","","","","True","True","True","True","","","","","","True","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","All","","","All","","","","","","None","","","Some of them","","","","","","Mostly measured","Mostly generated","Yes","","90.0","","","","","","","","","","","","Anonymized","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","True","True","","","1 GB - 10 GB","","True","","","True","","True","","True","True","","","moderately interested","very interested","","very interested","","moderately interested","1980-01-01 00:00:00" +"123","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1149.24","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","1 to 3 years","PhD candidate","","","Apply FAIR","","","","True","","Visual Studio","Python","PyTorch","","True","","True","True","","","","Lack of resources","True","True","","","True","","","","","True","True","","","Yes","Yes","","","","","","","","","","","","","","","True","","","","","","True","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Purely simulated","Mostly generated","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","True","True","","","","True","","","True","","Other","","100 GB - 1000 GB (1 TB)","","","True","","True","True","True","True","True","True","","","very interested","very interested","moderately interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"125","True","","","","","True","True","","True","","","","","","","","","True","","True","","","","","","","","","","","","","","","","95.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","485.59","Completed the survey","Anonymized","Anonymized","Energy","Life Science","","","","","","","","","","","","","","","","","","","","","","4 to 6 years","Postdoc","","","Not familiar with FAIR","True","","","","","GraphPad","FlowJo","ImageJ","","","","True","","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","Some of them","All","","","","","","","","None","Some of them","","","","","","Purely measured","Mostly generated","Not sure","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","True","","","","Binary scientific formats","","< 100 MB","","","","True","","True","","True","","","","","moderately interested","moderately interested","very interested","not interested","not interested","very interested","1980-01-01 00:00:00" +"128","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","413.14","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","7 to 10 years","Principal Investigator","","","Not familiar with FAIR","","True","","","","MATLAB / Simulink","Python","","","True","","","True","","","True","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","None","","Some of them","Some of them","","","","","None","None","None","None","None","","","","","Mostly measured","Mostly reused","No","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","True","","","","","","True","","True","True","","","","True","","","","very interested","very interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"129","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","3226.3","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","More than 10 years","Postdoc","","","Familiar with FAIR","True","True","","","","MATLAB / Simulink","Anonymized","OriginLab","True","","","","","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","Some of them","Some of them","","","","","","Some of them","Some of them","Some of them","","","","","","","","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","True","","","True","","","","100 MB - 1000 MB (1 GB)","","","","","","","","True","","","","","","","","","very interested","","1980-01-01 00:00:00" +"130","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","323.14","Completed the survey","Anonymized","Anonymized","Energy","Chemistry","","","","","","","Radiochemistry","","","","","","","","","","","","","","","7 to 10 years","Postdoc","","","Familiar with FAIR","","True","True","","","OriginLab","Anonymized","MATLAB / Simulink","","","","","","","","True","","True","True","True","True","True","","","","True","","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","None","","","","","","","","","Purely measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","True","","","","","True","","","","","","100 MB - 1000 MB (1 GB)","","","","","","","","","","","","True","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"131","True","True","","","True","True","","","True","","","","True","","","","","","","","","","","","","","","","","","FIZ Karlsruhe","","","","","50.0","","True","True","True","True","True","","","True","True","True","True","","True","True","","","","","","","","","","","","1069.66","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Apply FAIR","True","True","","","","Python","Anonymized","Machine Learning Libraries","","","","","True","True","","","","True","True","True","True","","","","","True","True","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","None","None","None","None","","","","","Equally measured and simulated","Equally generated and reused","Yes","","50.0","","True","","","","","","","","","","Anonymized","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","True","True","True","True","True","","","True","True","","","100 MB - 1000 MB (1 GB)","","True","True","","","","","True","","True","","","moderately interested","very interested","moderately interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"132","","True","","","","","","","","True","","","","","","","","","","","Technical support needed","","","","","","","","","","","","","","","5.0","","","","","","","","","","","","","","","","","","","","","","","","","","","981.18","Completed the survey","Anonymized","Anonymized","Energy","Earth Science","","","","","","","","Environmental Science","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","","True","","","","Anonymized","QGIS/GDAL","Anonymized","","","","","","True","","","","","","","","","","","Improved working with data","","True","","","","Yes","Yes","","","","True","","","","","","","","","","","","True","","True","True","True","","","True","","","","No standard","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","True","True","","Structured text","","> 1 TB","","","","","True","","","True","True","True","","","very interested","very interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"133","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","No value to others","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1128.46","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","1 to 3 years","PhD candidate","","","Apply FAIR","True","True","True","True","","OriginLab","LabVIEW","Excel (Spreadsheets)","","True","","True","True","","","","Commercial applications complicate standardized solutions","","","","","","","","","","","True","Other","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","All","All","","","","","","","","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","True","","","","","","100 MB - 1000 MB (1 GB)","","True","","","","","","","True","","","","very interested","moderately interested","moderately interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"135","True","","","","True","","","","True","","","","","","True","","True","True","","","","","","","","","","","","","","","","","","10.0","","","","True","True","","True","","","","","","True","True","","","","","","","","","","","","","1925.98","Completed the survey","Anonymized","Anonymized","Energy","","materials science","","","","","","","","","","","","","","","","","","","","","More than 10 years","Postdoc","","","Familiar with FAIR","","True","","","","Anonymized","MATLAB / Simulink","OriginLab","","True","","","","","","","Lack of technical solutions","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","All","Some of them","","Some of them","","","","","","All","All","","None","","","","","","Purely measured","Purely generated","Yes","","95.0","","True","True","","","","","","","","","Anonymized","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","True","","","","True","","","10 GB - 100 GB","","True","","True","","","","","True","True","","","moderately interested","very interested","moderately interested","moderately interested","very interested","not interested","1980-01-01 00:00:00" +"140","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","324.91","Completed the survey","Anonymized","Anonymized","Energy","","Energy system modeling","","","","","","","","","","","","","","","","","","","","","1 to 3 years","PhD candidate","","","Not familiar with FAIR","","True","","","","Python","Excel (Spreadsheets)","QGIS/GDAL","","True","","True","","","","","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","All","","","All","","","","","","All","","","All","","","","","Mostly simulated","Mostly generated","Not sure","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","Binary scientific formats","","> 1 TB","","","","","","","True","True","","","","","moderately interested","moderately interested","moderately interested","very interested","very interested","not interested","1980-01-01 00:00:00" +"141","","True","","","True","","True","","","True","","","","","True","","","","True","","","","","","","","","","","","Gitlab / GitHub","","","","","10.0","","True","","","","","","","","","True","","","","","","","","","","","","","","","","759.6","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","7 to 10 years","Principal Investigator","","","Familiar with FAIR","","True","","","","Python","Anonymized","","","True","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","Some of them","","Some of them","Some of them","","","","","","None","","None","None","","","","","","Purely simulated","Purely reused","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","True","","True","","","","100 MB - 1000 MB (1 GB)","","True","","","True","","","","","","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"142","True","True","","","True","","","","True","","","","","","True","","","","True","","","","","","","","","","","","Zenodo","Gitlab / GitHub","Gitlab / GitHub","","","55.0","","","","","","True","","True","","","","","","","","","True","","","","","","","","","","630.03","Completed the survey","Anonymized","Anonymized","Energy","","(Energie-)Wirtschaftswissenschaften","","","","","","","","","","","","","","","","","","","","","4 to 6 years","Research Associate","","","Familiar with FAIR","True","True","True","","","Anonymized","Anonymized","Excel (Spreadsheets)","","","","True","","True","","","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","All","","All","All","All","","","","","None","","None","None","None","","","","Mostly simulated","Purely reused","No","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","True","True","","True","","","","< 100 MB","","","","True","","","","True","","","","","very interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"143","True","True","","","True","True","","","","True","","","","","True","","True","","","True","","","","","","","","","","","Institutional Repository","","","","","10.0","","True","","","","True","","","","","","","","","","True","True","","","","","","","","","","461.71","Completed the survey","Anonymized","Anonymized","Energy","","Systemanalyse","","","","","","","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","","True","","","","Python","Excel (Spreadsheets)","Anonymized","","True","","True","","True","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","True","","","","Some of them","Some of them","","","Some of them","Some of them","","","","None","None","","","None","None","","","","Purely simulated","","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","True","True","","","True","","","1 GB - 10 GB","","True","","True","True","","","True","","","","","very interested","very interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"144","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1692.19","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","Less than 1 year","Research Associate","","","Familiar with FAIR","","True","","","","Python","Anonymized","QGIS/GDAL","","True","","","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","None","None","None","None","","","","","","Mostly simulated","Mostly reused","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","10 GB - 100 GB","","True","True","","True","","","","True","","","","moderately interested","moderately interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"145","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","808.05","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","1 to 3 years","PhD candidate","","","Familiar with FAIR","","True","","","","Python","","","","","","","","","","True","","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","None","Some of them","Some of them","","Some of them","","","","","None","Some of them","Some of them","","None","","","","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","< 100 MB","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"147","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","Insufficiently trained","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1384.99","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","Principal Investigator","","Familiar with FAIR","","True","","","","IGOR","Anonymized","Anonymized","","True","","True","True","","","","","True","","True","True","","","","","True","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","Some of them","Some of them","Some of them","","","","","","","Equally measured and simulated","Mostly generated","Yes","","10.0","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","True","True","","","True","True","True","","True","","","","100 MB - 1000 MB (1 GB)","","True","True","True","True","True","","True","","True","RDM software & tools","","moderately interested","very interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"148","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","578.03","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Industrial Engineering","","","","","","","","","","","","7 to 10 years","Principal Investigator","","","Not familiar with FAIR","True","","","","","MATLAB / Simulink","Excel (Spreadsheets)","Anonymized","","True","True","","","","True","","","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","Some of them","","Some of them","","","","","","","None","","None","","","","","","","Mostly simulated","Mostly generated","No","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","True","True","True","","True","","","","< 100 MB","","","","","","","","","","","","True","not interested","moderately interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"149","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","387.63","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Process Engineering","","","","","","","","","","","","4 to 6 years","Postdoc","","","Not familiar with FAIR","","True","","","","Excel (Spreadsheets)","Python","Aspen Custom Modeler","","","","","","","","True","","True","True","True","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","All","Some of them","Some of them","","All","","","","","None","Some of them","All","","None","","","","","Mostly measured","Mostly reused","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","True","True","","True","True","","","","< 100 MB","","True","","","","","True","","","True","","","very interested","moderately interested","not interested","not interested","very interested","not interested","1980-01-01 00:00:00" +"151","True","","","","True","True","","True","","","","","True","","","","","","","","","","","","","","","","","","","","","","","25.0","","","","","","","","","","","","","True","","","","","","","","","","","","","","701.59","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","Less than 1 year","PhD candidate","","","Not familiar with FAIR","","True","","","","Python","Anonymized","ANSYS","","","","True","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","None","","","","","","Mostly simulated","Mostly generated","Yes","","50.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","True","True","","","","","I don't know","","","","","","","","True","","","","","moderately interested","moderately interested","not interested","very interested","not interested","not interested","1980-01-01 00:00:00" +"153","True","","","","True","","","","True","True","","","","","","","True","True","","","","","","","","","","","","","","","","","","70.0","","","","","","True","","","","","True","","","","","","","","","","","","","","","","479.0","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Process Engineering","","","","","","","","","","","","Less than 1 year","PhD candidate","","","Familiar with FAIR","","True","","","","Aspen Custom Modeler","Python","Excel (Spreadsheets)","","","","","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","Some of them","","","","","","","None","None","None","","","","","","","Purely simulated","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","100 MB - 1000 MB (1 GB)","","","","True","True","True","","","True","","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"155","True","","","","","","","","True","","","","","","True","True","True","","","","","","","","","","","","","","","","","","","35.0","","","","True","True","True","","","","","True","","","","","","","","","","","","","","","","274.76","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","More than 10 years","Postdoc","","","Not familiar with FAIR","","True","","","","COMSOL Multiphysics","OriginLab","Word","","","True","","","True","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","All","Some of them","","","","","","","None","None","None","","","","","","","Mostly measured","Purely generated","Not sure","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","True","","","","","True","True","","","","","100 MB - 1000 MB (1 GB)","","","","","","","","True","True","True","","","very interested","moderately interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"156","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","25.0","","","","","","","","","","","","","","","","","","","","","","","","","","","329.38","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","Less than 1 year","Student","","","Not familiar with FAIR","","","","True","","Python","Python","Excel (Spreadsheets)","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Purely measured","Purely reused","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","True","True","","True","True","","","","","","","","","","","","","","","","","","","","","","1980-01-01 00:00:00" +"158","True","","","","True","True","","","","True","","","","","True","","","True","True","","","","","","","","","","","","","","","","","15.0","","True","","True","True","True","","","","","","","","True","","True","","","","","","","","","","","760.21","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","7 to 10 years","Principal Investigator","","","Familiar with FAIR","True","True","","","","Excel (Spreadsheets)","Anonymized","Anonymized","","True","","True","True","True","","","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","","","","All","All","","All","All","","","","","None","None","","None","None","","","","","Purely simulated","Purely reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","","True","","True","","","","","","100 MB - 1000 MB (1 GB)","","True","True","","True","True","True","True","True","True","","","moderately interested","very interested","very interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"160","True","","","","","True","","","","True","","","","","True","True","True","","","","","","","","","","","","","","","","","","","5.0","","","","","True","","","","","","","","","","","","","","","","","","","","","","517.9","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","","True","","","","Anonymized","Excel (Spreadsheets)","LabVIEW","","","True","True","","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","","None","","","Some of them","Some of them","","","","","None","","","None","Some of them","","","","","Purely measured","Purely generated","No","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","True","","","","","","< 100 MB","","True","","","","","","True","True","True","","","not interested","moderately interested","moderately interested","not interested","very interested","not interested","1980-01-01 00:00:00" +"162","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","669.35","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","More than 10 years","Research Associate","","","Familiar with FAIR","True","True","","","","Python","LabVIEW","OriginLab","","True","True","","True","","","","","","","","","","","","","True","True","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","","","Some of them","","","","","","","Mostly measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","True","True","","","100 MB - 1000 MB (1 GB)","","","","","","","","True","True","True","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","","1980-01-01 00:00:00" +"164","True","","","","True","True","","","","True","","","","","True","True","","","","","","","","","","","","","","","","","","","","20.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","837.07","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","4 to 6 years","Postdoc","","","Familiar with FAIR","True","True","","","","Python","Excel (Spreadsheets)","OriginLab","True","","","","","","","","","True","True","True","True","","","","","","","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","Some of them","Some of them","All","","","","","All","All","All","All","All","","","","","Equally measured and simulated","Purely generated","Yes","","30.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","True","True","","True","True","True","True","True","","","","1 GB - 10 GB","","True","","True","","True","","True","True","","","","very interested","very interested","not interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"166","","","","","","","True","","True","","","","","","","","True","True","","","","","","","","","","","","","","","","","","15.0","","","","","","True","","","True","","","","","","","","","","","","","","","","","","407.08","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Nanotechnology","","","","1 to 3 years","PhD candidate","","","Not familiar with FAIR","True","True","","","","Anonymized","OriginLab","Anonymized","","","","","","","","","Other","","","","","","","","","True","True","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","Some of them","Some of them","","","","","","","","Some of them","All","","","","","","","Mostly measured","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","1 GB - 10 GB","","","","","","True","","","True","","","","moderately interested","moderately interested","","","moderately interested","moderately interested","1980-01-01 00:00:00" +"168","True","","","","","","","","True","","","","True","","","","","","","","","","","","","","","","","","","","","","","10.0","","","","","","","","","","","","","","","","True","","","","","","","","","","","1280.43","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Research Associate","","","Familiar with FAIR","True","True","","","","LabVIEW","Delphi","Anonymized","","","","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","All","","","","","Purely measured","Mostly generated","Yes","","95.0","","True","True","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","","","100 MB - 1000 MB (1 GB)","","","","","","True","","","","","","","moderately interested","very interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"175","True","","","","","True","","","True","True","","","","","","","True","True","True","True","","","","","","","","","","","","","","","","30.0","","True","","","True","True","True","True","True","True","True","","","","","","","","","","","","","","","","3638.51","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Nanotechnology","","","","More than 10 years","Research Associate","","","Familiar with FAIR","True","True","","","","Anonymized","Anonymized","IGOR","","True","","True","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","Some of them","All","All","","","","","","None","None","None","None","","","","","","Purely measured","Purely generated","Yes","","100.0","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Application-specific formats","","1 GB - 10 GB","","True","True","True","True","True","True","True","True","True","","","moderately interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"178","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1940.69","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","Excel (Spreadsheets)","Anonymized","MATLAB / Simulink","","True","True","","","","","True","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","Some of them","","Some of them","","All","","","","","None","","None","","Some of them","","","","","Mostly simulated","Mostly reused","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","","","True","","","","1 GB - 10 GB","","","","","True","True","","","","True","","","very interested","very interested","moderately interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"179","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","445.47","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","","True","","","","Anonymized","C/C++","Python","","True","True","","","","","True","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","True","","","","","","","","","","","","","","","","","","","","","","Mostly simulated","Mostly reused","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","True","","","","True","","","","100 MB - 1000 MB (1 GB)","","","","","","","","","","","","True","moderately interested","not interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"181","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","484.43","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","7 to 10 years","Postdoc","","","Familiar with FAIR","True","True","","","","IGOR","OriginLab","Anonymized","","True","True","True","True","","","True","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","Some of them","None","Some of them","Some of them","","","","","All","All","Some of them","Some of them","All","","","","","Purely measured","Purely generated","Yes","","30.0","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","True","True","True","","","","True","","","","","","1 GB - 10 GB","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"182","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","486.14","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","4 to 6 years","Postdoc","","","Not familiar with FAIR","","True","","","","Python","Excel (Spreadsheets)","OriginLab","","True","","True","True","","","","","True","True","True","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","All","All","Some of them","","All","","","","","None","None","None","","None","","","","","Mostly measured","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","True","","True","","","","1 GB - 10 GB","","","","True","","True","True","True","True","True","","","very interested","very interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"183","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","802.15","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","True","True","","","","IGOR","Python","Anonymized","True","","","","","","","","","True","","","","","","","Improved working with data","True","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","All","","","","","","","None","Some of them","Some of them","","","","","","","Mostly measured","Mostly generated","Yes","","70.0","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","","","True","True","","","1 GB - 10 GB","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"185","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","606.16","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","Principal Investigator","","Familiar with FAIR","","True","","","","Python","MATLAB / Simulink","LabVIEW","","True","","True","","","","","","True","True","True","True","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","Some of them","All","","All","","","","","","Some of them","Some of them","","All","","","","","Equally measured and simulated","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","True","True","","","","","","1 GB - 10 GB","","True","True","True","True","True","True","True","True","True","","","moderately interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"187","","True","","","","","","True","","","","","","","","True","True","","","","","","","","","","","","","","Institutional Repository","","","","","10.0","","","","","True","","","","True","True","True","","","","","","","","","","","","","","","","1231.91","Completed the survey","Anonymized","Anonymized","Energy","Chemistry","","","","","","Biomimetic Chemistry","","","","","","","","","","","","","","","","1 to 3 years","PhD candidate","","","Familiar with FAIR","","","","True","","Excel (Spreadsheets)","MATLAB / Simulink","","","True","","True","True","","","","","","","","","","","","","","","","","True","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","Some of them","Some of them","None","","Some of them","","","","","All","Some of them","None","","Some of them","","","","","Mostly measured","Purely generated","No","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","True","","","True","True","True","","True","","","","100 MB - 1000 MB (1 GB)","","","True","","","","True","","True","True","","","very interested","moderately interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"188","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1570.2","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Process Engineering","","","","","","","","","","","","4 to 6 years","PhD candidate","","","Not familiar with FAIR","","True","True","","","OriginLab","R","","","","","","","","","True","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","Some of them","","Some of them","Some of them","","","","","","Purely measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","True","","","","True","True","","True","","","","I don't know","","True","","","","","","True","True","","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"193","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","993.05","Completed the survey","Anonymized","Anonymized","Information","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","No degree","Student","","No","","True","","","","","Python","R","Command line (scripts)","","","","","","","","True","","True","True","True","True","","","","","","True","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","All","Some of them","Some of them","None","None","","","","","Purely measured","Purely reused","No","I don't know","","","","","","","","","","","","","","","True","","","","","","","","","Next Generation Sequencing","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","","","","","","","10.0","10 GB - 100 GB","I don't know","","True","","True","","True","True","True","","","","very interested","very interested","not interested","moderately interested","very interested","not interested","1980-01-01 00:00:00" +"194","True","True","","","True","","","True","","True","","","True","","","","","","","","","","","","","","","","","","Institutional Repository","Gitlab / GitHub","","","","95.0","","True","True","","","True","True","True","","","","","","","","","True","","","","","","","","Others","","2690.7","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","No degree","Student","","Yes","","","","","True","","","","","True","","","","","","","","","","","","True","","","","","","True","True","","","Yes","Yes","True","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","True","","Some of them","All","","","","All","","All","","None","Some of them","","","","None","","None","","Mostly simulated","Purely generated","Not sure","Less","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","True","","","True","","","","< 100 MB","I don't know","","","","True","","","","True","","","","moderately interested","not interested","not interested","moderately interested","very interested","not interested","1980-01-01 00:00:00" +"199","","True","","","True","True","","","","True","","","","","True","","True","True","True","","","","","","","","","","","","Gitlab / GitHub","Gitlab / GitHub","","","","40.0","","True","","True","","True","","","","","True","","","","True","True","","True","","","","True","","","","","1030.24","Completed the survey","Anonymized","Anonymized","Information","Earth Science","","","","","","","","Environmental Science","","","","","","","","","","","","","","4 to 6 years","Research Associate","","No","","","True","True","","","Git","Visual Studio","Anonymized","","True","","","True","True","","","","True","True","True","True","","","","","","","True","Digital text","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","True","","All","All","All","All","All","All","","All","","","","","","","","","","","Mostly measured","Purely reused","No","I don't know","","","","","","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","True","","","True","","","","< 100 MB","I don't know","","","","","True","","True","True","","","","moderately interested","very interested","","","very interested","moderately interested","1980-01-01 00:00:00" +"202","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1005.79","Completed the survey","Anonymized","Anonymized","Information","","Informatik","","","","","","","","","","","","","","","","","","","","","Less than 1 year","Research Associate","","No","","","","True","","","Jupyter","","","","True","","True","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","","All","All","All","","","","","None","All","None","Some of them","None","","","","","Purely measured","Mostly generated","Yes","Less","","","","","","","","","","","","","","","","","","True","True","","","","","","","","","","","","","","Umfrage zu erfahrenen Szenarios einer Studie (Likert Skala)","","","","","","","","","","","True","","","","True","","","","","True","","","","","3.0","< 100 MB","Less","","","True","","True","True","True","True","True","","","very interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"203","","True","","","True","True","","","True","","","","True","","","","","","","","","","","","","","","","","","Zenodo","","","","","100.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","575.62","Completed the survey","Anonymized","Anonymized","Information","","Computer Science","","","","","","","","","","","","","","","","","","","","","More than 10 years","PhD candidate","","Yes","","","","True","","","Jupyter","Anonymized","Anonymized","","True","","","True","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","True","","All","All","All","All","All","All","","All","","Some of them","Some of them","All","All","All","All","","Some of them","","Purely measured","Mostly generated","Yes","More","","","","","","","","","","","","","","","True","","","True","","","","","","Software repository mining","","","","","","","","","Surveys","","","","","","","","","True","","True","","","","True","","","True","True","","","True","","","9.0","< 100 MB","Less","True","","","True","True","","","","True","","","moderately interested","very interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"204","True","","","","True","","","","True","","","","","","","","True","","True","","","","","","","","","","","","","","","","","45.0","","True","","True","True","True","","True","True","True","True","True","True","","","","","","","","","","True","","","","1128.14","Completed the survey","Anonymized","Anonymized","Information","","Informatik","","","","","","","","","","","","","","","","","","","","","7 to 10 years","Research Associate","","Yes","","","True","","","","Anonymized","Python","Linux","","True","True","","","","","","","","","","","","","True","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","True","","All","All","All","All","","","","All","","None","None","None","None","","","","None","","Purely simulated","Purely generated","Yes","As much","","","","","","","","","","","","","","True","True","True","","True","","","Segmentierung","Objekterkennung","Farbanalyse","Aggregation","Mathematische Modelle","Voting","Multi-Agenten-Simulationen","Evolutionäre Algorithmen","Game Engines","","","","Umfragen","Interviews","Voting","","","","","","","True","True","True","True","True","True","True","True","True","True","True","True","True","True","True","","12.0","100 MB - 1000 MB (1 GB)","As much","True","","","True","","","True","True","","","","moderately interested","moderately interested","moderately interested","not interested","very interested","very interested","1980-01-01 00:00:00" +"206","","","True","","True","","True","True","","","","","True","","","","","","","","","","","","","","","","","","","","","","","25.0","","","","","True","True","True","True","","","","","","","","True","","","","","","","","","","","1566.49","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","More than 10 years","Research Associate","","Yes","","","True","","","","Anonymized","ANSYS","MATLAB / Simulink","","True","","True","","","","","","True","","True","True","True","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","True","True","","","Some of them","All","","","Some of them","Some of them","All","","","None","Some of them","","","Some of them","","None","","","Mostly simulated","Purely reused","Yes","More","","","","","","","","","","","","","","","","True","","","","","","","","","","","eigene Skripte","","","","","","","","","","","","","","","True","","True","","","","True","","","","True","","","True","True","","6.0","100 MB - 1000 MB (1 GB)","More","","True","","True","","","True","True","","","","moderately interested","moderately interested","not interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"209","","","","","","","","","","","","","","","","","","","","","","True","","","","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","4286.03","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","Less than 1 year","PhD candidate","","No","","","True","","","","Python","Anonymized","Anonymized","","","","True","True","","","True","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","Some of them","","","Some of them","Some of them","","","","","None","","None","None","None","","","","","Mostly simulated","Mostly generated","No","I don't know","","","","","","","","","","","","","","","","True","","","True","","","","","","","","Physical models","","","","","","","","","","","","","","","True","","","","","","","","","","","","","True","True","","1.0","10 GB - 100 GB","I don't know","","","True","","True","","True","True","True","","","moderately interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"210","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","750.19","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","4 to 6 years","PhD candidate","","Yes","","","True","","","","Python","Python","Linux","","","","","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","True","","All","","All","","","","","All","","Some of them","","Some of them","","","","","None","","Mostly measured","Purely generated","Yes","As much","","","","","","","","","","","","","","","","True","","","True","","","","","","","","Monta-Carlo Simulationen","","","","","","","","","","","","","","","","","","True","","","","","","","True","","","True","","Other","18.0","100 GB - 1000 GB (1 TB)","More","","","True","True","","","True","True","True","","","very interested","very interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"211","","True","True","","True","True","","","True","","","","","","","","","","","","","","","","","","","","","","Gitlab / GitHub","","","","","100.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","507.41","Completed the survey","Anonymized","Anonymized","Information","","Informatik","","","","","","","","","","","","","","","","","","","","","1 to 3 years","Research Associate","","Yes","","True","True","True","","","Anonymized","Python","Machine Learning Libraries","","","","","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","Some of them","Some of them","Some of them","Some of them","","","","Purely simulated","Mostly generated","Yes","I don't know","","","","","","","","","","","","","","","","True","","","","","","","","","","","BlenderProc","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","3.0","100 GB - 1000 GB (1 TB)","I don't know","True","","","","True","","True","True","","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"213","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","No value to others","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1356.25","Completed the survey","Anonymized","Anonymized","Information","","Transportation","","","","","","","","","","","","","","","","","","","","","1 to 3 years","Research Associate","","Yes","","True","True","","","","Python","Database Management System","Anonymized","","True","","True","True","","","","","","","","","","","","","","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","None","None","None","None","","","","","Mostly simulated","Mostly generated","Not sure","I don't know","","","","","","","","","","","","","","","","True","","","True","","","","","","","","simulation for transport mobility","","","","","","","","","","","","","","","True","","","","","","","","","","True","","","True","True","","8.0","1 GB - 10 GB","I don't know","","True","True","True","True","","","True","","","","very interested","very interested","moderately interested","very interested","moderately interested","not interested","1980-01-01 00:00:00" +"226","True","","","","True","","","True","True","","","","True","","","","","","","","","","","","","","","","","","","","","","","90.0","","","","","","","","","True","True","True","","","","","","","","","","","","","","","","704.11","Completed the survey","Anonymized","Anonymized","Information","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Research Associate","","Yes","","","True","","","","Python","MATLAB / Simulink","Visual Studio","","True","True","","","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","Some of them","","","","","","","Mostly simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Deep Learning","","","","","","","","","","","","","","","True","","True","","","","True","","","","True","","","","True","","","10 GB - 100 GB","","","","","True","","","","True","","","","moderately interested","moderately interested","moderately interested","moderately interested","not interested","moderately interested","1980-01-01 00:00:00" +"230","","True","","","True","","","","True","","","Guidelines / policies of publishers","True","","","","","","","","","","","","","","","","","","Zenodo","","","","","80.0","","True","","","","","","","","","","","True","True","True","True","","","","","","","","","","","316.52","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","4 to 6 years","Postdoc","","Yes","","True","","","","","Python","Java","Linux","","","","","True","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","","","","All","All","","All","All","","","","","None","None","","None","None","","","","","Purely simulated","Mostly generated","No","I don't know","","","","","","","","","","","","","","","","True","","","","","","","","","","","Erzeugen von Objekten mit einer Wahrscheinlichkeitsverteilung auf möglichen Parametern","","","","","","","","","","","","","","","True","","True","","","","True","","","","True","","","True","","","3.0","100 MB - 1000 MB (1 GB)","I don't know","","","","True","","","","True","","","","moderately interested","very interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"236","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","331.56","Completed the survey","Anonymized","Anonymized","Information","Physics","","","","","","","","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","","","True","True","True","","","","","","","","","","","","True","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Purely simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","","","","","","","100 MB - 1000 MB (1 GB)","","","","","","","","","","","","True","not interested","not interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"237","True","True","","","","","","True","True","True","","","","True","True","True","True","True","True","","","","","","","","","","","","Materials Cloud","Zenodo","","","","60.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","538.71","Completed the survey","Anonymized","Anonymized","Information","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","4 to 6 years","Postdoc","","Yes","","True","True","True","","","AiiDA","Anonymized","Python","","True","True","True","","","","True","","","","","","","","","","True","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","True","","","Some of them","All","All","All","Some of them","","None","","","Some of them","All","All","All","Some of them","","None","","","Mostly simulated","Mostly generated","Yes","More","","","","","","","","","","","","","","","","True","","","","","","","","","","","HPC","HTC","density functional theory","","","","","","","","","","","","","True","","True","True","True","","True","","","","True","True","","True","True","","6.0","10 GB - 100 GB","I don't know","","True","True","True","True","True","","True","True","","","very interested","moderately interested","not interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"243","True","True","","","","","","","","","","Other","","","","","","","","True","","","","","","","","","","","Zenodo","","","","","15.0","","True","True","True","True","True","True","True","True","True","True","True","True","","True","","True","True","","","","","True","","","","743.99","Completed the survey","Anonymized","Anonymized","Information","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","1 to 3 years","Research Associate","","Yes","","","","","True","","Python","Git","","True","","","","","","","","","True","True","True","True","True","","","","","True","","","","Yes","Yes","","","","","","","","","","True","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","True","True","","All","Some of them","Some of them","Some of them","Some of them","","Some of them","All","","Some of them","Some of them","Some of them","All","All","","Some of them","All","","Purely measured","Purely reused","Not sure","I don't know","","","","","","","","","","","","","","","True","","","","","","","","","Flow cytometry","single cell sequencing ","","","","","","","","","","","","","","","","","True","","True","","","","True","","","","True","","","True","True","","12.0","100 MB - 1000 MB (1 GB)","I don't know","","","True","True","","","","True","True","","","very interested","very interested","moderately interested","very interested","moderately interested","very interested","1980-01-01 00:00:00" +"244","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","350.34","Completed the survey","Anonymized","Anonymized","Information","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","1 to 3 years","Research Associate","","Yes","","","True","","","","","","","","True","","True","True","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","All","","","","","","","","","","","","","Mostly simulated","Purely reused","","","","","","","","","","","","","","","","True","","True","","","","","Ptychography","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","True","","","","True","","","True","True","","","10 GB - 100 GB","","","","","True","","","","True","True","","","moderately interested","very interested","not interested","moderately interested","moderately interested","","1980-01-01 00:00:00" +"246","True","","","","","","","","True","True","","","","","","","","True","True","","","","","","","","","","","","","","","","","45.0","","","","","","","","","","","","","","","True","","","","","","","True","True","","","","609.84","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","7 to 10 years","Postdoc","","Yes","","True","True","","","","C/C++","Python","MATLAB / Simulink","","","True","","","True","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","All","","","All","","","","","","Some of them","","","Some of them","","Mostly measured","Purely generated","Yes","As much","","","","","","","","","","","","","","True","","","","True","True","","Kamerabilder","Tiefenbilder ","","","","","","","","","","","standardisierte Fragebögen","","","","","","","","","","","True","","True","","True","","","","True","","","True","","","3.0","100 MB - 1000 MB (1 GB)","As much","","","","","True","","True","True","True","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"247","True","True","","","","True","","True","True","","","","","True","True","","","","","True","","","","","","","","","","","RCSB PDB","EMDB","EMPIAR","","","80.0","","True","","True","True","True","True","True","True","True","True","True","True","True","","","","","","","","","","","","","1291.98","Completed the survey","Anonymized","Anonymized","Information","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","7 to 10 years","Postdoc","","Yes","","True","True","True","","Centrally (internal server)","Anonymized","Anonymized","Python","","True","True","","","","","","","True","True","True","True","True","True","","","True","True","True","Digital system","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","Some of them","Some of them","Some of them","Some of them","","","","","","Mostly measured","Purely generated","Yes","As much","","","","","","","","","","","","","","True","True","True","","","","","Cryoelectron Microscopy","Fluorescence Microscopy","","FPLC","SDS-PAGE","Immunoblotting","Single Particle Analysis","Atomic model building","MD and QM simulations","","","","","","","","","","","","","True","","True","True","True","True","True","","","","True","True","","True","","","24.0","> 1 TB","As much","","","","True","","True","True","","True","","","moderately interested","not interested","not interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"251","True","True","","","True","True","","","True","","","","","","True","","","","","","","","","","","","","","","","FAIRDOMHub","","","","","95.0","","","True","","True","True","","","","","","True","True","True","","","True","","","","","","","","","","512.55","Completed the survey","Anonymized","Anonymized","Information","Chemistry","","","","","","Biochemistry","","","","","","","","","","","","","","","","7 to 10 years","Postdoc","","Yes","","","","True","","","Python","Anonymized","","","True","","True","True","","","","","","","","","","","","","True","","True","Source code and scripts","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","True","","","","None","None","None","Some of them","","None","","","","None","None","None","Some of them","","None","","","","Mostly simulated","Purely generated","Yes","More","","","","","","","","","","","","","","","True","True","","","","","","","","UV-Vis Spektrophotometrie","Isothermale Titrationskalorimetrie","NMR","Molecular Dynamics","","","","","","","","","","","","","","","","","","","True","","","","","True","True","True","","True","","","3.0","1 GB - 10 GB","I don't know","","","","","","","","","","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"252","True","","","","","","","","True","","","","True","","","","","","","","","","","","","","","","","","","","","","","20.0","","","","True","True","","","","True","","","","","","","","","","","","","","","","","","716.89","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Mechanical Engineering","","","","","","","","","","","","More than 10 years","Postdoc","","Yes","","True","True","","","","ANSYS","Python","ZEMAX","","True","True","","","","","","","","","","","","","","","True","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","None","None","None","","","","","","","","","No","As much","","","","","","","","","","","","","","True","","True","","","True","","Lichtmikroskopie","Elektronenmikroskopie","Bildverarbeitung von mir vorigen Methoden erfassten Daten","","","","FEm-Simulation (Mechanik/Fluidik)","Optische Simulation","","","","","","","","","","","","","","","","True","","True","","True","","","True","True","True","","","","","2.0","100 MB - 1000 MB (1 GB)","As much","","True","True","True","True","True","","","True","","","moderately interested","moderately interested","moderately interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"255","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","388.47","Completed the survey","Anonymized","Anonymized","Information","Life Science","","","","","","","","","","","","Medicine","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","","","True","","","","Anonymized","Anonymized","MATLAB / Simulink","","True","","True","True","True","","","","True","","True","True","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","","","All","All","All","All","All","All","","","","None","None","None","None","None","None","","","","Purely measured","Mostly generated","Yes","As much","","","","","","","","","","","","","","True","True","","","True","True","","PET","MRI","","HPLC","","","","","","","","","Survey","","","","","","","","","True","True","True","True","True","","True","True","True","True","True","True","True","True","True","","36.0","10 GB - 100 GB","As much","","True","","","True","True","True","","True","","","moderately interested","very interested","moderately interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"269","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","904.16","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","Yes","","","True","","","","OriginLab","LabVIEW","Word","","True","","","","","","True","","True","","True","","","True","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","All","","All","","","","","","","None","","None","","","","","","","Purely measured","Purely generated","Yes","Less","","","","","","","","","","","","","","True","True","","","","True","","Bildauswertung","Grauwertkorrelation","","Spektroskopie","Diffraktometrie","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","True","","True","","","6.0","100 MB - 1000 MB (1 GB)","As much","","True","","True","","","","True","True","","","moderately interested","moderately interested","not interested","","","","1980-01-01 00:00:00" +"274","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","870.73","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","1 to 3 years","Research Associate","","Yes","","True","True","","","","Anonymized","Python","Excel (Spreadsheets)","","","True","","","","","","","True","True","True","","","","","","True","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","True","True","","All","All","All","Some of them","Some of them","All","All","All","","Some of them","Some of them","Some of them","None","None","None","None","Some of them","","Mostly measured","Purely reused","No","","","","","","","","","","","","","","","True","True","True","","","True","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","True","","","True","True","True","","True","","","","","","","True","True","","","","True","True","","","","very interested","moderately interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"275","True","True","","","True","True","","True","","","","","","","True","","","","","","","","","","","","","","","","ProteomeXchange","ProteomeXchange","","","","30.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","702.19","Completed the survey","Anonymized","Anonymized","Information","Life Science","","","","","","","","","","","","Health Science","","","","","","","","","","More than 10 years","Postdoc","","Yes","","","True","","","","Anonymized","Anonymized","Anonymized","","True","","True","True","","","","","True","","","True","","True","","","","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","Some of them","","","","","","None","","Some of them","Some of them","","","","","","Purely measured","Purely generated","Yes","","","","","","","","","","","","","","","True","True","","","","","","Microscopy","","","Mass Spectrometry","Flow Cytometry","","","","","","","","","","","","","","","","","True","True","","","True","True","","True","","","","True","","","","","12.0","> 1 TB","","","True","True","True","","True","","","True","","","moderately interested","very interested","moderately interested","","","moderately interested","1980-01-01 00:00:00" +"276","True","True","","","","True","","True","True","","","","","","True","","","True","","","","","","","","","","","","","Institutional Repository","ePrints Soton","","","","30.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","659.8","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","7 to 10 years","Principal Investigator","","Yes","","True","True","","","","MATLAB / Simulink","Anonymized","COMSOL Multiphysics","","True","","","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","All","","All","All","All","","","","","None","","Some of them","None","None","","","","","Equally measured and simulated","Purely generated","Yes","I don't know","","","","","","","","","","","","","","True","","True","","","True","","Synchrotron microCT","Synchrotron nanoCT","Neutron microCT","","","","FE modelling","Machine learning models","","","","","","","","","","","","","","True","","","","True","","","","","True","True","True","True","True","True","","12.0","10 GB - 100 GB","As much","True","True","True","True","True","True","","","","","","very interested","moderately interested","moderately interested","not interested","not interested","moderately interested","1980-01-01 00:00:00" +"278","","True","","","","","","","","","","Guidelines/policies of institute/funder","","","True","","","","","","","","","","","","","","","","figshare","","","","","20.0","","True","","True","True","True","","","True","True","True","","","True","","","","","","","","","","","","","1200.02","Completed the survey","Anonymized","Anonymized","Information","Chemistry","","","","","","","Electrochemistry","","","","","","","","","","","","","","","4 to 6 years","Postdoc","","Yes","","True","","","","","OriginLab","Anonymized","Word","","","","","","","","","Lack of resources","","","","","","","","","True","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","None","None","Some of them","None","","","","","","Purely measured","Purely generated","Not sure","Less","","","","","","","","","","","","","","True","True","","","","True","","Microscopy","","","Spectroscopy","","","","","","","","","","","","","","","","","","True","True","True","","True","True","True","","","","","True","","","","","18.0","1 GB - 10 GB","Less","","","True","","True","True","True","","True","","","moderately interested","moderately interested","moderately interested","not interested","not interested","moderately interested","1980-01-01 00:00:00" +"279","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","50.0","","","","True","True","True","True","True","True","True","True","True","True","True","","","","","","","","","","","","","5595.69","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","","True","True","True","","","Word","Excel (Spreadsheets)","PowerPoint","","True","","True","True","","","","","True","True","True","True","","True","","","True","True","True","","","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","Some of them","Some of them","Some of them","","","","","","None","None","None","None","","","","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","True","True","True","","","True","","yes","","","numerous","","","limited","","","","","","","","","","","","","","","True","True","True","True","True","","True","","True","True","","True","True","True","","","","","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"283","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","No value to others","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1363.32","Completed the survey","Anonymized","Anonymized","Information","Physics","","","","","","","","","","","","","","","","","","Polymer Physics","","","","7 to 10 years","Research Associate","","Yes","","","True","","","","Anonymized","Anonymized","Anonymized","","True","","True","True","","","","","True","True","True","","","","","","True","True","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","Some of them","All","","","","","","","None","None","None","","","","","","","Purely measured","Mostly generated","Yes","Less","","","","","","","","","","","","","","True","","","","","","","REM","TEM","AFM","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","1.0","1 GB - 10 GB","Less","","","","True","","True","","True","True","","","very interested","very interested","very interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"288","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","944.28","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","4 to 6 years","Postdoc","","No","","True","True","","","","Python","PyTorch","Jupyter","","True","","","","","","","Lack of technical solutions","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","All","","All","All","All","","","","","None","","Some of them","Some of them","Some of them","","","","","Equally measured and simulated","Purely reused","Yes","I don't know","","","","","","","","","","","","","","True","","True","","","","","Tomographie (CT/MR)","Histologie","XRD, SAXS","","","","Deep Learning Modelle","","","","","","","","","","","","","","","","","","","True","","","True","","","True","","","True","True","","18.0","10 GB - 100 GB","More","","","","","","","","True","","","","","moderately interested","","","","","1980-01-01 00:00:00" +"292","True","","","","","True","","","True","True","","","","","True","True","","True","","True","","","","","","","","","","","","","","","","5.0","","True","","True","","True","True","True","","","","","True","","","","True","True","","","","","","","","","989.06","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","More than 10 years","","","Yes","","","True","","True","","Anonymized","PyTorch","Anonymized","","True","True","True","True","","","True","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","True","","","","None","All","","Some of them","","None","","","","None","All","","All","","None","","","","Purely measured","Purely generated","Not sure","Less","","","","","","","","","","","","","","True","True","","","","True","","Tomography","","","Spectroscopy","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","True","True","","","True","True","","18.0","10 GB - 100 GB","As much","True","True","True","True","True","True","True","True","True","","","very interested","very interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"303","","","True","","","","True","","True","True","","","","","True","","","","","","","","","","","","","","","","","","","","","50.0","","","","True","True","","","","","True","","","True","","","","","","","","","","","","","","793.09","Completed the survey","Anonymized","Anonymized","Information","Chemistry","","","","","","","Radiation Chemistry","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","Principal Investigator","Not sure","","True","True","","","","Anonymized","","","","","","True","True","","","","","","","","","","","","","","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","Some of them","Some of them","All","All","","","","","","Equally measured and simulated","Mostly generated","Not sure","As much","","","","","","","","","","","","","","","True","","","","","","","","","GC/MS ","HPLC","LSC","","","","","","","","","","","","","","","","True","True","","","True","","","","","","","True","","","","","","> 1 TB","More","","","True","","True","","","","True","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"304","True","","","","","","","","True","","","","","","True","True","","","","","","","","","","","","","","","","","","","","20.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","628.81","Completed the survey","Anonymized","Anonymized","Information","Chemistry","","","","","","Polymer Research","","","","","","","","","","","","","","","","7 to 10 years","Research Associate","","No","","","True","","","","Excel (Spreadsheets)","Word","PowerPoint","","","","","True","","","","","True","True","True","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","Some of them","","Some of them","","","","","","","None","","None","","","","","","","Mostly measured","Mostly generated","Yes","As much","","","","","","","","","","","","","","True","True","True","","","True","","Mikroskopie","","","Spektroskopie","","","CFD","","","","","","","","","","","","","","","","","","","","","True","","","","","True","","","","","12.0","1 GB - 10 GB","As much","","","True","","","","","","","","","very interested","very interested","very interested","very interested","not interested","not interested","1980-01-01 00:00:00" +"305","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Other","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","532.67","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","Yes","","True","True","","","","MATLAB / Simulink","Mathematica","C/C++","","","","","","","","True","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Mostly simulated","Purely generated","Yes","Less","","","","","","","","","","","","","","","True","True","","","","","","","","From analytical model trace is generated","","","Simulating a system with relevant effects is then used to generate the trace","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","True","","1.0","< 100 MB","Less","True","","True","","True","True","","","True","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"309","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","732.23","Completed the survey","Anonymized","Anonymized","Information","Psychology","","","","","","","","","","","","","","","","","","","","","Kognitive Psychologie","4 to 6 years","Postdoc","","Yes","","","True","","","","Anonymized","Anonymized","Office Software (unspecified)","","True","","","","","","True","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","None","","None","Some of them","","","","","","None","","None","None","","","","","","Purely measured","Purely reused","Yes","I don't know","","","","","","","","","","","","","","True","","","","","","Cohort studies","Strukturelle Magnetresonanztomographie (MRT)","Computertomographie (CT)","","","","","","","","","","","","","","Neuropsychologische Tests","Klinische Tests","Experimente","","","","","","","True","","","","True","True","","","True","","","","","12.0","I don't know","I don't know","","","True","True","True","","True","True","True","","","very interested","moderately interested","very interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"310","","","True","","True","True","","","","True","","","True","","","","","","","","","","","","","","","","","","","","","","","70.0","","","","","True","","","","","","","","","","","","","","","","","","","","","","1497.93","Completed the survey","Anonymized","Anonymized","Information","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","7 to 10 years","Research Associate","Research Associate","","","","","","","","FLUKA","Anonymized","","","","","","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","","","","","","","","","","Mostly simulated","Purely generated","No","More","","","","","","","","","","","","","","","True","True","","","","","","","","Analytical code","","","Monte Carlo simulation","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","","","3.0","100 MB - 1000 MB (1 GB)","More","True","","","True","True","","","","","","","very interested","very interested","","moderately interested","","moderately interested","1980-01-01 00:00:00" +"313","True","","","","","","","","True","","","","","","True","True","","True","","True","","","","","","","","","","","","","","","","10.0","","","","True","True","","","","True","True","","","","","","","","","","","","","","","","","685.04","Completed the survey","Anonymized","Anonymized","Information","Chemistry","","","","","","Polymer Research","","","","","","","","","","","","","","","","7 to 10 years","Postdoc","","No","","","True","","","","Python","Office Software (unspecified)","OriginLab","","True","True","True","True","","","","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","All","","","","","","","None","None","All","","","","","","","Purely measured","Mostly generated","Yes","More","","","","","","","","","","","","","","True","True","","","","","","REM","","","IR Spektroskopie","Strömungspotential-Messungen","Permeationsmessungen","","","","","","","","","","","","","","","","","","","","True","","True","","","","","True","","","","","12.0","100 MB - 1000 MB (1 GB)","As much","True","True","True","True","True","True","True","True","True","","","very interested","very interested","moderately interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"315","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","No value to others","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","645.95","Completed the survey","Anonymized","Anonymized","Information","Physics","","","","","","","","","","","","","","","","","","Nanotechnology","","","","More than 10 years","Postdoc","","Yes","","","True","","","","Python","IDL","Office Software (unspecified)","","True","True","True","True","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","All","All","","","","","","","Some of them","All","All","","","","","","","Equally measured and simulated","Purely generated","Yes","More","","","","","","","","","","","","","","True","True","True","","","","","Mikroskopie","","","Röntgenfluoreszenz","Röntgenreflekotmetrie","","Finite-Elemente Methoden","Monte-Carlo Simulationen","","","","","","","","","","","","","","True","","","","True","True","","","","","True","True","","","True","","3.0","1 GB - 10 GB","More","True","True","True","","True","","True","True","","","","moderately interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"318","True","","","","","","","","True","","","","","","","True","","","","","","","","","","","","","","","","","","","","20.0","","","","True","True","","","","","","","True","","","","","","","","","","","","","","","934.3","Completed the survey","Anonymized","Anonymized","Information","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","7 to 10 years","Research Associate","","Yes","","True","True","","","","Python","Mathematica","LaTeX","","","True","","True","","","True","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","All","","All","","","","","","","Some of them","","Some of them","","","","","","","Mostly simulated","Mostly generated","Not sure","As much","","","","","","","","","","","","","","","","True","","","","","","","","","","","Optimierung","HPC","","","","","","","","","","","","","","","","True","","","","","","","","True","","","","True","Other","12.0","1 GB - 10 GB","More","True","","True","True","True","","","True","","","","very interested","very interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"321","True","True","","","True","True","","","True","","","","","","True","","True","","","","","","","","","","","","","","Zenodo","","","","","5.0","","True","True","True","True","","","","True","True","True","True","True","True","","","","","","","","","","","","","547.01","Completed the survey","Anonymized","Anonymized","Information","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Postdoc","","Yes","","","True","","","","Anonymized","","","","True","","True","True","","","","","True","","True","True","True","","","","","True","True","","","Yes","Yes","","","","","True","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","Some of them","","Some of them","Some of them","Some of them","","","","","Some of them","","Some of them","Some of them","None","","","","","Mostly measured","Mostly generated","Yes","As much","","","","","","","","","","","","","","","True","True","","","True","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","True","True","","24.0","10 GB - 100 GB","As much","","True","","","True","True","","","","","","very interested","very interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"324","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","802.49","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Postdoc","","Yes","","","True","","","Most data is lost","","","","","","True","","True","","","True","","","","","","","","","","","","True","Source code and scripts","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","Some of them","","Some of them","","","","","","","Some of them","","Some of them","","","","","Purely simulated","Purely generated","No","More","","","","","","","","","","","","","","","","True","","","","","","","","","","","HPC","","","","","","","","","","","","","","","","","True","","","","","","","True","True","","","","True","","24.0","10 GB - 100 GB","As much","","","True","","True","","","","","","","very interested","very interested","moderately interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"326","True","","","","","","","True","","True","","","","","","True","True","True","","True","","","","","","","","","","","","","","","","15.0","","","","","","","","","","","","","","","","","","","","","","","","","","","273.68","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","Yes","","","True","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","True","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Mostly simulated","Mostly generated","No","I don't know","","","","","","","","","","","","","","True","","True","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","True","","True","","2.0","100 MB - 1000 MB (1 GB)","I don't know","","","True","True","True","True","","","True","","","very interested","moderately interested","","","moderately interested","","1980-01-01 00:00:00" +"327","True","","","","True","True","","","True","","","","","","","","","","True","","","","","","","","","","","","","","","","","55.0","","","","True","True","True","","True","True","","True","True","","True","","True","","","","","","","","","","","1467.91","Completed the survey","Anonymized","Anonymized","Information","","Informatik","","","","","","","","","","","","","","","","","","","","","7 to 10 years","Research Associate","","Yes","","True","True","","","","","","","","True","True","","True","True","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","","","All","All","All","All","All","All","","","","None","None","None","None","None","None","","","","Mostly measured","","","I don't know","","","","","","","","","","","","","","","","","","True","True","","","","","","","","","","","","","","Interviews (Audio, schriftliche Notizen)","Fragebögen (Online-Umfrage-tools wie Lime-Survey, Papierfragebögen, E-Mail-Fragebögen)","Videoaufzeichnungen","","","","","","","True","True","","","True","True","True","","True","","True","True","","True","","","","","I don't know","True","True","","","True","","True","True","","","","very interested","very interested","","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"328","True","","","","True","True","","True","","","","","","","True","","","","","True","","","","","","","","","","","","","","","","55.0","","","","","True","","","","True","True","True","","","True","","","","","","","","","","","","","1264.2","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Process Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","Yes","","","True","","","","Office Software (unspecified)","OriginLab","Aspen Custom Modeler","","True","","True","","","","","","True","","True","True","","True","","","True","","True","","","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","All","All","All","Some of them","","","","","None","All","Some of them","Some of them","Some of them","","","","","Equally measured and simulated","Mostly generated","Yes","More","","","","","","","","","","","","","","True","True","True","","","True","","Mikroskpie","","","Spektoskopie","Chromatographie","","Theoretische Modelle","Numerische Modelle","","","","","","","","","","","","","","","","","","True","","True","","","","True","True","","True","","","10.0","1 GB - 10 GB","More","","","","","True","True","True","","True","","","moderately interested","moderately interested","","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"329","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","291.9","Completed the survey","Anonymized","Anonymized","Information","","Data Science","","","","","","","","","","","","","","","","","","","","","1 to 3 years","Research Associate","","Yes","","True","True","","","","Python","Excel (Spreadsheets)","Notepad++","","True","","","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","Some of them","","","","","","","","","Equally measured and simulated","Equally generated and reused","Not sure","I don't know","","","","","","","","","","","","","","","","","","","","Simulations","","","","","","","","","","","","","","","","Algorithmically","","","","","","","","","","True","","","","","","","True","","","","Other","12.0","100 MB - 1000 MB (1 GB)","I don't know","True","","","True","","","True","True","","","","moderately interested","moderately interested","not interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"330","True","","","","True","","","","True","True","","","","","True","True","","","True","","","","","","","","","","","","","","","","","70.0","","","","","","True","","True","","","","","True","True","","True","","","","","","","","","","","812.27","Completed the survey","Anonymized","Anonymized","Information","Mathematics","","","","","","","","","","","","","","Statistics","","","","","","","","4 to 6 years","Postdoc","","Yes","","True","True","","","","R","Python","Excel (Spreadsheets)","","True","","","","","","","","","","","","","","","","","","","Source code and scripts","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","None","","None","None","","","","","Mostly simulated","Purely reused","","I don't know","","","","","","","","","","","","","","","True","True","","True","","","","","","RNA Sequencing","","","Simulations on R","","","","","","Food Frequency Questionnaire","","","","","","","","","","","","","","","True","","","","True","True","","","","","","100 MB - 1000 MB (1 GB)","Less","True","","True","","True","","True","True","","","","moderately interested","very interested","very interested","not interested","very interested","not interested","1980-01-01 00:00:00" +"333","True","","","","True","True","","","True","","","","","","True","True","","","True","","","","","","","","","","","","","","","","","60.0","","True","True","","","","","","","","","True","True","True","True","True","","","","","","","","","","","532.49","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","4 to 6 years","Research Associate","","Yes","","True","True","","","","Python","Visual Studio","Git","","True","True","","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","True","","Some of them","","Some of them","All","Some of them","","","None","","Some of them","","Some of them","All","None","","","None","","Equally measured and simulated","Purely reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","True","","","True","","","True","","","","","","","","","True","True","True","True","True","","","","very interested","very interested","not interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"340","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","514.81","Completed the survey","Anonymized","Anonymized","Information","","Data Science","","","","","","","","","","","","","","","","","","","","","Less than 1 year","Research Associate","","No","","True","True","","","","Python","Anonymized","","","","","","","","","True","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","All","All","All","","All","","","","","None","None","None","","None","","","","","Mostly simulated","","Yes","I don't know","","","","","","","","","","","","","","","","True","","","True","","","","","","","","Flight simulation software","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","3.0","100 MB - 1000 MB (1 GB)","I don't know","True","True","","True","True","True","True","True","True","","","very interested","moderately interested","very interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"341","True","","True","","","","","True","True","True","","","","","True","True","","","","","","","","","","","","","","","","","","","","20.0","","True","True","","","True","","True","","","","True","","","","True","","","","","","","","","","","980.37","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","","Materialwissenschaften","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","","","True","","","","Anonymized","Anonymized","","True","","","","","","","","","True","True","True","True","True","True","","","True","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","True","","All","All","All","All","All","","","All","","All","All","All","All","None","","","All","","Purely simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","True","True","","True","True","","","6.0","10 GB - 100 GB","","","","True","","","True","","True","","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"343","","","","","","True","","","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","100.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","426.74","Completed the survey","Anonymized","Anonymized","Information","","Bioinformatics","","","","","","","","","","","","","","","","","","","","","1 to 3 years","PhD candidate","","No","","True","True","","","","Command line (scripts)","R","Python","True","","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","Some of them","","","","","","Mostly measured","Mostly generated","Not sure","As much","","","","","","","","","","","","","","","","","","","","Analytical methods","","","","","","","","","","","","","","","","Tomo-Seq","","","","","","True","","True","","","","True","","","","True","","","","","","12.0","10 GB - 100 GB","As much","True","","True","","True","","","","True","","","","moderately interested","moderately interested","","moderately interested","very interested","1980-01-01 00:00:00" +"350","True","True","","","True","True","","","True","","","","","True","","True","","True","","","","","","","","","","","","","Zenodo","","","","","100.0","","True","True","True","","True","True","True","True","","","","","","True","True","True","","","","","","","","","","365.98","Completed the survey","Anonymized","Anonymized","Information","Earth Science","","","","","","","","","Remote Sensing","","","","","","","","","","","","","1 to 3 years","PhD candidate","","Yes","","","True","True","","","Python","QGIS/GDAL","Google Earth Engine","","True","True","","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","","","All","All","All","All","All","All","","","","None","All","All","None","None","None","","","","Purely simulated","Mostly reused","Yes","Less","","","","","","","","","","","","","","True","","","","","","","Satellite","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","","","","","","True","True","","3.0","10 GB - 100 GB","As much","True","","","","","","True","","","","","not interested","very interested","moderately interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"352","True","","","","","","","","True","","","","True","","","","","","","","","","","","","","","","","","","","","","","5.0","","","","","","","","","True","","","","","True","","","","","","","","","","","","","2114.86","Completed the survey","Anonymized","Anonymized","Information","Physics","","","","","","","","","","","","","","","","","","","Quanteninformation","","","More than 10 years","Postdoc","","Yes","","","True","","","","Anonymized","Git","","","True","","","","","","","","","","","","","","","","","True","","GitLab","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","All","","","","","","","Some of them","Some of them","Some of them","","","","","","Mostly measured","Purely generated","No","","","","","","","","","","","","","","","","","True","","","True","","","","","","","","qutip","c3 (PGI-FZJ)","juqcs (JSC-FZJ)","","","","","","","","","","","","","","","","True","","","","","","","True","","","","True","","6.0","1 GB - 10 GB","","","","True","","True","","","","","","","moderately interested","very interested","not interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"353","","","True","","","","True","True","","","","","","","True","","True","","","True","","","","","","","","","","","","","","","","75.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","294.45","Completed the survey","Anonymized","Anonymized","Information","Psychology","","","","","","","","","","","","","","","","","","","","","Engineering Psychology / Human Factors","1 to 3 years","PhD candidate","","Yes","","True","True","","","","SPSS","R","","","True","","True","","True","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","True","","All","","","","","","","All","","All","","","","","","","All","","Mostly measured","Mostly generated","No","As much","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","Online survey","Laboratory studies in Virtual Reality","Neurophysical measurements","","","","","","","","","True","","","","","","True","","","","","","","","12.0","100 MB - 1000 MB (1 GB)","More","","","","","True","True","","True","","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"363","","True","","","True","","","True","True","","","","","","","","True","","","True","","","","","","","","","","","Institutional Repository","","","","","100.0","","True","True","True","True","True","","True","True","True","True","True","True","True","True","True","","","","","","","","","","","471.36","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Industrial Engineering","","","","","","","","","","","","1 to 3 years","PhD candidate","","","Not familiar with FAIR","","True","True","","","MATLAB / Simulink","","","","True","True","True","","","","","","","True","","True","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","","","All","Some of them","All","All","All","","","","","None","None","None","None","None","None","","","","Mostly measured","Purely generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","","","","I don't know","","True","True","True","True","True","","True","","","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"364","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","613.09","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","True","True","","","","Anonymized","Anonymized","MATLAB / Simulink","","True","True","True","","","True","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","","","","","","","","","","Purely simulated","Mostly generated","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","I don't know","","","True","","","","True","","","","","","moderately interested","very interested","not interested","very interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"365","True","True","","","True","True","","","True","","","","","True","True","","","True","","","","","","","","","","","","","Institutional Repository","","","","","5.0","","","","","","","","","True","True","True","True","","","","","","","","","","","","","","","355.08","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Mathematics","","","","","","","","","","","","","","Applied Mathematics","","","","","","","","7 to 10 years","Postdoc","","","Familiar with FAIR","True","","True","","","Paraview","LaTeX","Visual Studio","","True","","","True","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","Some of them","","","","","","","Purely simulated","Purely generated","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","True","","","True","True","","True","True","True","","","100 MB - 1000 MB (1 GB)","","True","True","True","True","True","True","","True","","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"366","True","","","","","","","True","","","","","","","True","True","","True","True","True","","","","","","","","","","","","","","","","10.0","","","","True","True","True","True","True","True","True","True","True","","True","","","","","","","","","","","","","2597.89","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","MATLAB / Simulink","Python","Anonymized","","True","True","True","True","True","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","Some of them","None","None","None","","","","","Equally measured and simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","True","","","","100 MB - 1000 MB (1 GB)","","True","True","True","True","","True","True","True","True","","","moderately interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"367","","True","","","True","True","","","","True","","","","","True","True","","","","","","","","","","","","","","","Institutional Repository","Institutional Repository","ESA Data Archive","TERENO","","85.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","1452.98","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","","True","","","Centrally (internal server)","","","","","True","","","","","","","","True","True","","True","","","","","","","True","","","Yes","Yes","","True","","True","","","","","","","","","","","","","","","","","","","","","True","","","True","True","True","True","True","True","","","","All","All","All","All","All","All","","","","Some of them","All","All","All","All","All","","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","","","","True","","True","True","","","10 GB - 100 GB","","","","","","","","","","","","True","moderately interested","moderately interested","not interested","very interested","very interested","not interested","1980-01-01 00:00:00" +"368","True","True","","","True","","","","True","True","","","","","True","True","","True","","","","","","","","","","","","","Zenodo","Gitlab / GitHub","","","","25.0","","True","True","","","","","","","","","","True","True","","","True","","","","","True","","","","","1523.25","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","More than 10 years","Research Associate","","","Apply FAIR","","True","True","","","Git","Python","Python","","True","True","","","True","","","","","","","","","","","","True","True","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","True","","True","","All","","Some of them","Some of them","","All","","Some of them","","","","Some of them","Some of them","","Some of them","","Some of them","","Mostly measured","Equally generated and reused","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","True","","","True","","","","100 MB - 1000 MB (1 GB)","","","","True","True","","","","True","True","","","very interested","very interested","very interested","very interested","moderately interested","very interested","1980-01-01 00:00:00" +"369","","","","Other","True","True","","","True","","","","","","","","","","","","Legal / ethical concerns","","","","","","","","","","","","","","","5.0","","","","","","","","","","","","","","","","","","","","","","","","","","","808.73","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","7 to 10 years","Research Associate","","","Apply FAIR","","True","","","","Python","Anonymized","","","","","","","","","True","","","","","","","","","","","True","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","Some of them","Some of them","All","","","","","","","","","","","","","","Purely measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","True","","","True","","","","10 GB - 100 GB","","","True","","","","","True","True","","","","very interested","not interested","very interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"370","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","No value to others","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","6556.1","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","Principal Investigator","","Familiar with FAIR","True","","","","","Anonymized","OpenCV","Excel (Spreadsheets)","","True","True","","True","","","","Heterogeneous workflows complicate standardized solutions","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","Description of data structure","Some of them","","","","","","","","All","None","","","","","","","","Some of them","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","True","True","","True","True","True","True","True","True","","","100 MB - 1000 MB (1 GB)","","","","","","","","","","","","True","not interested","moderately interested","not interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"373","","","True","","","True","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","10.0","","","","","","True","True","True","","","","","","","True","","","","","","","","","","","","934.71","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Physics","","","","","","","","","","","","","","","","","","Astrophysics and Astronomy","","","","More than 10 years","Principal Investigator","","","Not familiar with FAIR","","True","","","","Anonymized","Anonymized","","True","","","","","","","","","True","True","True","True","","True","","","","True","True","","","Yes","Yes","","","","True","","","","","","","","","","","","","","","","","","","","","","","Others","","True","True","True","True","","","","","","All","All","All","All","","","","","","All","All","All","All","","","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","True","","","True","True","","","True","","","","> 1 TB","","","","","","","","","","","","True","very interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"374","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","Legal / ethical concerns","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","992.82","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","4 to 6 years","Principal Investigator","","","Not familiar with FAIR","","True","True","","","","Jupyter","Office Software (unspecified)","","True","True","True","True","True","","","","","","","","","True","","","","True","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","True","","","","All","All","","","Some of them","All","","","","None","None","","","None","None","","","","Mostly simulated","Equally generated and reused","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","True","True","","","","","100 MB - 1000 MB (1 GB)","","","True","True","","","","True","True","True","","","moderately interested","very interested","not interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"375","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","520.2","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","","Materialwissenschaften","","","","","","","","","","","","","","","","","","","","","7 to 10 years","Research Associate","","","Familiar with FAIR","True","True","","","","ImageJ","OriginLab","Anonymized","","True","","True","","","","","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","None","None","None","","","","","","","None","Some of them","None","","","","","","","Purely measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","True","","True","","","","10 GB - 100 GB","","","","True","True","True","","","True","True","","","moderately interested","very interested","not interested","moderately interested","very interested","not interested","1980-01-01 00:00:00" +"377","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","475.82","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","True","True","","","","Linux","Visual Studio","Office Software (unspecified)","","True","","True","True","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","None","Some of them","All","All","","","","","","None","None","","Some of them","","","","","","Mostly simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","True","","","","True","True","True","True","True","","","100 GB - 1000 GB (1 TB)","","True","","True","True","","True","True","True","True","","","very interested","very interested","not interested","not interested","very interested","not interested","1980-01-01 00:00:00" +"379","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","635.72","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","","Transportation","","","","","","","","","","","","","","","","","","","","","More than 10 years","Postdoc","","","Not familiar with FAIR","","True","","","","Python","","","","True","","","","","","","","True","","True","","","True","","","","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","All","All","","All","","","","","","None","None","","All","","","","","","Purely measured","Purely reused","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","100 MB - 1000 MB (1 GB)","","","","True","","","","","","","","","very interested","very interested","","","very interested","","1980-01-01 00:00:00" +"381","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","382.16","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","4 to 6 years","Research Associate","","","Not familiar with FAIR","True","","","","","Python","LabVIEW","Anonymized","","True","True","","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","None","None","None","","","","","","","Purely measured","Mostly generated","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","True","","","","True","","","","","","","I don't know","","","","","","","","","","","","","very interested","very interested","not interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"384","True","","","","","True","True","","True","","","","","","True","True","True","","","","","","","","","","","","","","","","","","","75.0","","","","True","True","","","","","","","","True","True","","","","","","","","","","","","","722.17","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Mechanical Engineering","","","","","","","","","","","","Less than 1 year","Research Associate","","","Not familiar with FAIR","","True","","","","Python","Excel (Spreadsheets)","SPSS","","","True","","","True","","","","True","True","True","","True","","","","","","True","","","Yes","Yes","","","","True","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","","","","Some of them","Some of them","","Some of them","Some of them","","","","","None","None","","","","","","","","Equally measured and simulated","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","< 100 MB","","","","","","","","","","","","True","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"385","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","435.97","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","4 to 6 years","Research Associate","","","Not familiar with FAIR","","","","True","","Tecplot","TRACE","","","","","","True","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","","All","All","","","","","","","None","None","None","","","","","","Mostly simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","True","","","","True","","","10 GB - 100 GB","","","True","True","","True","True","","True","True","","","very interested","very interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"386","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","634.86","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","","Robotik","","","","","","","","","","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","","True","","","","Anonymized","C/C++","Python","","","True","","","","","","","","","True","","","","","","","","True","","","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","True","","","","All","All","","","","All","","","","","All","","","","","","","","Mostly simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","10 GB - 100 GB","","","","","","","","","True","","","","moderately interested","very interested","very interested","","","moderately interested","1980-01-01 00:00:00" +"387","True","True","","In repository","True","","","True","True","","","","","","True","True","True","True","","True","","","","","","","","","","","Zenodo","WDCC","","","","5.0","","True","True","True","","True","","","","","True","","","","","","","","","","","","","","","","2162.23","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","More than 10 years","Research Associate","","","Apply FAIR","","","","","Centrally (internal server)","Anonymized","cdo","Python","","True","","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","Some of them","All","","","","","","Some of them","Some of them","Some of them","Some of them","","","","","","Purely simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","True","","","","True","","","> 1 TB","","True","","True","True","True","True","","","True","","","moderately interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"388","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","443.37","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","","True","","","","Dymola","Python","MATLAB / Simulink","","True","","True","True","True","","","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","None","None","None","","","","","","Equally measured and simulated","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","True","True","","True","True","","","1 GB - 10 GB","","","","True","True","True","True","True","True","True","","","very interested","very interested","moderately interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"389","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","749.86","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","True","","","","","LabVIEW","Tecplot","Fortran","","True","","True","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","Some of them","Some of them","All","Some of them","","","","","None","Some of them","Some of them","Some of them","None","","","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","True","","","","","True","","","True","","","100 MB - 1000 MB (1 GB)","","True","True","","True","True","True","","","","","","moderately interested","very interested","moderately interested","","moderately interested","not interested","1980-01-01 00:00:00" +"390","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","415.2","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Familiar with FAIR","","True","","","","Python","Excel (Spreadsheets)","Database Management System","","True","","True","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","All","","","","","","","Some of them","Some of them","Some of them","","","","","","","Purely measured","Purely generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","True","True","","True","","","","< 100 MB","","","","","","True","True","","","","","","very interested","very interested","very interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"393","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","375.87","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","4 to 6 years","Research Associate","","","Not familiar with FAIR","True","True","","","","MATLAB / Simulink","Python","Office Software (unspecified)","","True","True","True","True","","","","","","","","","","","","","True","","True","Digital system","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","Some of them","","","","","","","","","Mostly measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","","","True","True","","True","True","Binary non-scientific formats","","10 GB - 100 GB","","","True","True","True","","True","","True","True","","","very interested","very interested","very interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"394","","","","","","True","","","","True","","","","","True","","","","","","","","","","","","","","","","","","","","","5.0","","","","True","True","","","","True","True","","True","","True","","","","","","","","","","","","","479.91","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","4 to 6 years","Research Associate","","","Not familiar with FAIR","","True","","","","ZEMAX","Altium Designer","Anonymized","","True","","","True","","","","","True","","True","","","","","","","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","None","","Some of them","Some of them","","","","","","Purely measured","Purely generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","True","True","True","","","","","10 GB - 100 GB","","","","","","","","","","True","","","very interested","very interested","moderately interested","moderately interested","not interested","very interested","1980-01-01 00:00:00" +"395","","True","","","","","","True","True","True","","","","","True","","True","True","","","","","","","","","","","","","","","","","","5.0","","True","","","","","","","True","","","","","","","","","","","","","","","","","","367.04","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","7 to 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","","","","","True","","True","True","","","","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","","","Some of them","","","","","","","","","","","","","","","Purely measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","","","","","True","True","","True","","","","10 GB - 100 GB","","True","True","True","","","True","True","","","","","very interested","very interested","moderately interested","not interested","very interested","not interested","1980-01-01 00:00:00" +"396","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","293.73","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","7 to 10 years","Principal Investigator","","","Familiar with FAIR","","True","","","","MATLAB / Simulink","LabVIEW","","","True","","True","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","All","","All","All","All","","","","","Some of them","","Some of them","Some of them","Some of them","","","","","Equally measured and simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","True","","","True","","","True","True","","","100 GB - 1000 GB (1 TB)","","True","","True","True","True","","True","True","True","","","moderately interested","moderately interested","not interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"397","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","386.03","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Not familiar with FAIR","","True","","","","MATLAB / Simulink","Python","Anonymized","","","True","","True","","","True","","","","","","","","","","True","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","None","None","None","","","","","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","","","","","","","True","","Binary non-scientific formats","","1 GB - 10 GB","","True","","True","True","True","","","True","True","","","very interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"398","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","2731.22","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","","True","","","","MATLAB / Simulink","LaTeX","","True","","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","All","","","","","","","None","None","None","","","","","","","Equally measured and simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","10 GB - 100 GB","","","","","","","","","","","","True","not interested","not interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"400","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","416.39","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Not familiar with FAIR","","True","","","","Python","MATLAB / Simulink","LaTeX","","True","","","True","","","","","True","True","True","","","True","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","None","","None","None","","","","","","Equally measured and simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","True","","","","","","1 GB - 10 GB","","","","True","","True","","True","True","True","","","moderately interested","very interested","very interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"403","","True","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","25.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","220.69","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","MATLAB / Simulink","C/C++","Python","","True","","","","","","","","","","","","","","","","True","","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","","","","","","","","Equally measured and simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","True","True","","","","True","True","","","","","","1 GB - 10 GB","","","","","","","True","True","True","True","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"404","","True","","","True","True","","","True","","","","","","","","","","","","Other","","","","","","","","","","Gitlab / GitHub","","","","","10.0","","True","","True","True","True","","","","","True","","","","","","True","","","","","","","","","","540.36","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","4 to 6 years","Research Associate","","","Not familiar with FAIR","True","True","","","","Anonymized","Anonymized","Anonymized","","","","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","True","","","","Some of them","All","Some of them","","","All","","","","None","None","None","","","None","","","","Purely simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","True","True","True","True","True","True","","","1 GB - 10 GB","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"405","","","","In repository","True","True","","","True","","","","","True","True","True","True","True","True","True","Legal / ethical concerns","","","","","","","","","","","","","","","80.0","","","","","","","","","","","","","","","","","","","","","","","","","Others","","2212.37","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Earth Science","","","","","","","","Geophysics","","","","","","","","","","","","","","More than 10 years","Research Associate","","","","True","True","","","","MATLAB / Simulink","Excel (Spreadsheets)","","","True","True","True","True","True","","","Heterogeneous workflows complicate standardized solutions","","","","","","","","","True","","True","Digital text","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","","","","","","","","","","None","None","None","","None","","","","","Equally measured and simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","True","","","True","True","True","","True","True","Other","","1 GB - 10 GB","","True","","True","True","True","True","True","","True","","","not interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"406","","True","","","True","","","","","True","","","","","True","","","True","","","","","","","","","","","","","Institutional Repository","Institutional Repository","","","","10.0","","","","True","","","","","True","","","True","","True","True","True","","","","","","","","","","","682.96","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","Fortran","Excel (Spreadsheets)","","","True","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","All","","All","Some of them","All","","","","","None","","None","None","None","","","","","Equally measured and simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","True","True","","","True","","","< 100 MB","","True","True","True","","True","","True","","True","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"408","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","50.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","807.53","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","","","","","","","","","","","","","Less than 1 year","PhD candidate","","","Not familiar with FAIR","True","True","","","","MATLAB / Simulink","Excel (Spreadsheets)","Anonymized","","True","","","","","","True","","","True","","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","None","None","None","None","","","","","Equally measured and simulated","Mostly reused","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","True","","","","True","True","","True","","","","I don't know","","","","True","True","True","True","True","","","","","very interested","very interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"409","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","752.26","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Systems Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","","True","True","","","Anonymized","Python","Excel (Spreadsheets)","","","True","","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","None","None","","","","","","","","Mostly simulated","Purely reused","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","100 MB - 1000 MB (1 GB)","","True","","","","","","","True","","","","moderately interested","not interested","not interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"415","True","","","","True","True","","","True","","","","","","True","True","","","","True","","","","","","","","","","","","","","","","10.0","","","","True","True","True","True","True","True","True","True","","","","","True","","","","","","","","","","","714.12","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Psychology","","","","","","","","","","","","","","","","","","","","","Ingenieurpsychologie","More than 10 years","Principal Investigator","","","Familiar with FAIR","True","True","","","","SPSS","Anonymized","Anonymized","","True","","True","","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","None","Some of them","None","Some of them","Some of them","","","","","None","None","None","None","None","","","","","Mostly measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","True","","True","","","","","Other","","10 GB - 100 GB","","True","","True","","True","","","True","True","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"419","","","","","","","","","","","","","","","","True","","True","True","","","","","","","","","","","","","","","","","5.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","437.06","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","4 to 6 years","Research Associate","","","Familiar with FAIR","","True","","","","MATLAB / Simulink","Python","","","True","","","True","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","All","","All","","","","","","","All","","All","","","","","Equally measured and simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","True","True","","","1 GB - 10 GB","","","","True","True","","","","True","True","","","moderately interested","very interested","moderately interested","moderately interested","very interested","","1980-01-01 00:00:00" +"420","True","","","","","","","True","True","True","","","","","","True","True","","True","","","","","","","","","","","","","","","","","10.0","","","","","True","","","","","True","True","True","","","","","","","","","","","","","","","471.71","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","","True","","","","MATLAB / Simulink","Paraview","Anonymized","","True","True","","True","True","","","","","","","","","","","","","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","All","All","All","","All","","","","","Some of them","All","Some of them","","Some of them","","","","","Mostly simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","True","True","","","Binary scientific formats","","1 GB - 10 GB","","True","","True","","","","True","","","","","very interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"421","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","196.12","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","True","True","","","","Altium Designer","MATLAB / Simulink","","","","","","","","","True","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","Some of them","","","","","","","","None","None","None","","","","","","","Purely measured","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","True","","","","","","","","","","moderately interested","moderately interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"422","","True","","","True","","","","","","","Good scientific practice","","True","True","","","","","","","","","","","","","","","","Institutional Repository","","","","","35.0","","","True","True","True","True","","","","","","","True","True","","","","","","","","","","","Others","","729.52","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","True","","","","","Fortran","Python","Excel (Spreadsheets)","","True","","True","","","","","Relevant metadata is missing","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","","","","All","All","","All","All","","","","","None","None","","None","None","","","","","Equally measured and simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","True","","","","True","True","True","True","","","","100 MB - 1000 MB (1 GB)","","True","","","","","","","","","","","very interested","moderately interested","very interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"423","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","380.46","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","4 to 6 years","Research Associate","","","Not familiar with FAIR","True","True","","","","Tecplot","TRACE","","","","","","True","","","True","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","Some of them","","Some of them","Some of them","","","","","","None","","Some of them","Some of them","","","","","","Mostly simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","True","","","","True","","","10 GB - 100 GB","","","True","True","True","True","","","True","","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"425","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","312.95","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","1 to 3 years","PhD candidate","","","Not familiar with FAIR","","True","","","","Python","MATLAB / Simulink","LaTeX","","True","","True","True","","","True","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","Some of them","Some of them","Some of them","","All","","","","","None","None","Some of them","","Some of them","","","","","Mostly simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","","","True","True","","","True","","","","1 GB - 10 GB","","True","True","True","","","","","True","","","","very interested","moderately interested","moderately interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"426","True","","","","True","True","","","True","","","","","","","","","True","","","","","","","","","","","","","","","","","","25.0","","True","","True","","","","","","","True","True","","","True","True","","","","","","","","","","","363.56","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Not familiar with FAIR","","True","","","","Excel (Spreadsheets)","Python","MATLAB / Simulink","","True","True","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","All","","All","","All","","","","","None","","Some of them","","Some of them","","","","","Mostly simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","True","","","True","","","","< 100 MB","","True","True","True","","","","True","True","True","","","moderately interested","very interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"427","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","665.75","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","7 to 10 years","Research Associate","","","Not familiar with FAIR","True","","","","","TRACE","Tecplot","Anonymized","","True","True","","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","None","","","","","","","","","Purely simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","True","","","100 GB - 1000 GB (1 TB)","","True","True","True","True","True","True","True","True","True","","","","","","","","","1980-01-01 00:00:00" +"429","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","580.98","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Psychology","","","","","","","","","","","","","","","","","","","","","Ingenieurspsychologie","More than 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","SPSS","Excel (Spreadsheets)","Anonymized","","True","","","","","","","","True","True","","True","","True","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","Some of them","None","Some of them","None","","","","","Purely measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","True","","","","","","< 100 MB","","","","True","True","","","","True","","","","very interested","not interested","moderately interested","moderately interested","moderately interested","not interested","1980-01-01 00:00:00" +"430","True","","","","True","","","","True","","","","","","True","","","","True","","","","","","","","","","","","","","","","","5.0","","","","","","","","","","","","","","","","","","","","","","","","","","","366.12","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","","","","","","","","","","","","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","True","","","","","","","","","True","","","True","","","","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","Purely measured","Mostly generated","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","True","","","","< 100 MB","","True","True","","","","","True","","","","","very interested","very interested","moderately interested","moderately interested","not interested","moderately interested","1980-01-01 00:00:00" +"431","","True","","","True","","","","True","","","","","True","True","True","","True","True","True","","","","","","","","","","","CDDIS","Other","BKG","","","20.0","","","","","","True","True","True","True","","","","","","","","","","","","","","","","","","1702.06","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Earth Science","","","","","","","","","Geodäsie","","","","","","","","","","","","","More than 10 years","Research Associate","","","Familiar with FAIR","True","","","","","Anonymized","Anonymized","MATLAB / Simulink","","True","True","","True","","","","","","","","","","","","","","True","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","","","","","","","","","All","All","","","","","","","Purely measured","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","True","","","True","","","","True","","","> 1 TB","","","","","","","","","","","Technical aspects of RDM","","moderately interested","very interested","not interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"434","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","512.11","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","MATLAB / Simulink","","","","","","True","True","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","All","Some of them","Some of them","All","","","","","None","None","None","None","Some of them","","","","","Mostly measured","Purely reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","","1 GB - 10 GB","","","True","","","True","","","True","","","","very interested","very interested","moderately interested","moderately interested","moderately interested","not interested","1980-01-01 00:00:00" +"435","True","","","","","True","","","True","True","","","True","","","","","","","","","","","","","","","","","","","","","","","5.0","","","","True","True","True","","","True","True","True","","","","","True","","","","","","","","","","","585.88","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","No degree","Student","","","Familiar with FAIR","","True","","","","OriginLab","Excel (Spreadsheets)","ImageJ","","","","True","","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","Some of them","All","Some of them","","All","","","","","None","None","None","","Some of them","","","","","Purely measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","","True","","True","","","","I don't know","","","","","","True","","","","","","","moderately interested","very interested","very interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"441","","","","","True","True","","","","True","","","","","","","","","True","True","","","","","","","","","","","","","","","","10.0","","","","","","","","","","","","","","","","","","","","","","","","","","","483.09","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","7 to 10 years","Research Associate","","","Familiar with FAIR","","True","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","","","","","","","","","","","","","","","","","","Mostly simulated","Mostly reused","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","True","","","True","True","True","","True","True","","","","","True","True","","","","","True","True","","","","moderately interested","moderately interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"446","","True","True","","True","True","","","True","","","","","","True","True","","","","","","","","","","","","","","","Zenodo","Gitlab / GitHub","","","","35.0","","","","True","True","","","","","","","","True","","","","","","","","","","","","","","758.57","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","7 to 10 years","Postdoc","","","Not familiar with FAIR","","True","","","","Anonymized","Python","ANSYS","","True","True","","","","","","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","","Some of them","","","Some of them","Some of them","","","","","None","","","None","Some of them","","","","","Purely simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","True","","","True","True","","","1 GB - 10 GB","","","","True","True","True","","","","","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"448","","","","","","","","","","","","","","","","","","","","","","True","","True","","","True","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","509.41","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","4 to 6 years","Research Associate","","","Apply FAIR","","True","","","","Git","","Python","","True","","True","True","True","","True","","","","","","","","","","True","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","","Some of them","All","","","All","","","","","None","Some of them","","","Some of them","","","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","True","True","","True","True","True","","True","","","","I don't know","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"449","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","547.11","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","4 to 6 years","Research Associate","","","Not familiar with FAIR","","True","","","","","","","","True","","","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","All","","","","","","","None","None","None","","","","","","","Equally measured and simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","True","","","","","","100 MB - 1000 MB (1 GB)","","","","","","True","","","True","","","","moderately interested","moderately interested","not interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"450","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","446.59","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Psychology","","","","","","","","","","","","","","","","","","","","Industrial and Organisational Psychology","","More than 10 years","Principal Investigator","","","Not familiar with FAIR","","True","","","","R","Python","Anonymized","","","True","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","Some of them","Some of them","Some of them","All","","","","","None","Some of them","None","None","None","","","","","Mostly measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","True","","True","","True","True","","True","","","","10 GB - 100 GB","","","","","","True","True","","","True","","","very interested","very interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"451","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","987.28","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Familiar with FAIR","","True","","","","MATLAB / Simulink","C/C++","","","True","True","","True","True","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","Some of them","","Some of them","","Some of them","","","","","None","","Some of them","","Some of them","","","","","Purely simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","True","","","< 100 MB","","True","True","","True","True","True","True","True","True","","","moderately interested","moderately interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"452","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","394.47","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","MATLAB / Simulink","Office Software (unspecified)","Anonymized","","True","","","","","","True","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","Some of them","Some of them","","Some of them","","","","","","None","None","","None","","","","","Mostly simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","Other","","I don't know","","","","","","","","True","True","True","","","moderately interested","very interested","moderately interested","not interested","very interested","not interested","1980-01-01 00:00:00" +"454","True","","","","","","","True","True","","","","","","True","True","","","True","","","","","","","","","","","","","","","","","15.0","","","","True","True","","","","","","","","","","True","True","","","","","","","","","","","3134.61","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","True","True","","","","Anonymized","gcc","Anonymized","True","","","","","","","","","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","Some of them","","","","All","","","","","None","","","","None","","","","","Mostly simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","True","True","True","","","True","","","I don't know","","","","","","","","","","","","True","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"458","True","","","","","True","True","","True","","","","","True","","True","True","True","","","","","","","","","","","","","","","","","","30.0","","","","","True","","","","","","","","True","","","True","","","","","","","","","","","570.44","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","4 to 6 years","Postdoc","","","Not familiar with FAIR","","True","True","","","Paraview","CFD Software (e.g. TecPlot, ParaView)","Anonymized","","","True","","True","","","","","True","True","True","True","","","","","","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","","All","","","Some of them","All","","","","","","","","","","","","","","Purely simulated","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","True","","True","","","","","> 1 TB","","True","True","","","","","","","","","","moderately interested","very interested","very interested","very interested","very interested","","1980-01-01 00:00:00" +"459","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","No value to others","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","479.06","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","","","","","Most data is lost","gcc","Visual Studio","Anonymized","True","","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","All","All","","","","","","","Mostly measured","Purely generated","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","","","","","","1 GB - 10 GB","","","","","","","","","","","","True","not interested","not interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"461","True","True","","","True","","","","True","","","","","True","True","True","True","True","","","","","","","","","","","","","Gitlab / GitHub","Gitlab / GitHub","","","","5.0","","","","","","","","","True","True","True","True","","","True","True","","","","","","","","","","","1571.26","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","More than 10 years","Postdoc","","","Not familiar with FAIR","True","True","","","","Anonymized","Anonymized","Paraview","","True","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","Some of them","","Some of them","","Some of them","","","","","None","","None","","None","","","","","Mostly measured","Mostly reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","True","True","","","True","True","True","","True","True","","","100 MB - 1000 MB (1 GB)","","","","","","","","True","True","True","","","very interested","very interested","not interested","moderately interested","moderately interested","not interested","1980-01-01 00:00:00" +"462","True","","","","True","","","True","","True","","","","True","","","","True","True","","","","","","","","","","","","","","","","","30.0","","","","True","","","","","","","","","","","","","","","","","","","","","","","505.9","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Mathematics","","","","","","","","","","","","","","Applied Mathematics","","","","","","","","More than 10 years","Postdoc","","","Not familiar with FAIR","","","","True","","MATLAB / Simulink","Python","C/C++","","True","","","","","True","","","","","","","","","","","","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","None","Some of them","","","","","","","","Mostly simulated","Equally generated and reused","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","True","","","","True","","","","","","","","","","","True","","","","","moderately interested","moderately interested","not interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"463","True","True","","In repository","True","True","","","","True","","","","","True","True","","","","","","","","","","","","","","","Gitlab / GitHub","","","","","10.0","","True","","","","True","True","True","","","","","","","","","True","True","","","","True","","","","","4307.58","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","7 to 10 years","Research Associate","","","Familiar with FAIR","True","True","","","","QGIS/GDAL","Database Management System","Java","","True","True","","","","","","Lack of technical solutions","True","True","True","","True","","","","","True","True","","","Yes","Yes","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","True","","All","All","","","","All","","All","","None","None","","","","None","","None","","Mostly measured","Mostly reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","True","","True","True","True","","","< 100 MB","","True","","True","True","","","True","True","","","","very interested","not interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"466","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","10.0","","","","","","","","","","","","","","","","","","","","","","","","","","","530.17","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Physics","","","","","","","","","","","","","","","","","","Astrophysics and Astronomy","","","","More than 10 years","Research Associate","","","Familiar with FAIR","","","","True","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","Purely measured","Purely generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","100 GB - 1000 GB (1 TB)","","","","","","","","","","","","","","","","","","","1980-01-01 00:00:00" +"469","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1051.25","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","4 to 6 years","Postdoc","","","Not familiar with FAIR","","True","","","","C/C++","Tecplot","Python","","","True","True","True","","","","","True","","","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","None","","None","None","","","","","","Purely simulated","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","","","","True","","","True","True","","","10 GB - 100 GB","","True","","","True","True","","True","True","True","","","very interested","very interested","moderately interested","not interested","not interested","moderately interested","1980-01-01 00:00:00" +"470","True","True","","","True","True","","","True","","","","True","","","","","","","","","","","","","","","","","","Zenodo","","","","","10.0","","","","","","True","","True","","","","","True","","","","True","","","","","","","","","","333.96","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","","Informatik","","","","","","","","","","","","","","","","","","","","","More than 10 years","Research Associate","","","Familiar with FAIR","True","True","","","","Anonymized","Python","Anonymized","","True","","","","","","","","","","","","","","","","True","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","All","","All","","Some of them","","","","","Some of them","","All","","None","","","","Equally measured and simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","True","True","","True","True","True","True","True","True","","","1 GB - 10 GB","","","","","","","","","","","","True","not interested","very interested","not interested","moderately interested","moderately interested","not interested","1980-01-01 00:00:00" +"471","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","652.49","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","7 to 10 years","Principal Investigator","","","Apply FAIR","True","True","","","","","","","","True","","","","","","","","True","True","True","True","","True","","","","","True","","","Yes","Yes","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","True","","","","","Some of them","","","Some of them","Some of them","","","","","","","","","","","","","Mostly measured","Purely generated","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","< 100 MB","","True","True","True","True","","True","True","True","True","","","moderately interested","very interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"472","True","","","","","","","","","True","","","","","","","","True","","","Legal / ethical concerns","","","","","","","","","","","","","","","35.0","","True","","True","True","True","True","True","True","True","","","","True","","","True","","","","","","","","","","556.38","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Not familiar with FAIR","","True","True","","","MATLAB / Simulink","Anonymized","Anonymized","","True","","True","True","","","","","","","","","","","","","","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","True","","","","Some of them","All","Some of them","Some of them","","Some of them","","","","None","None","None","None","","None","","","","Equally measured and simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","True","True","","","True","True","True","","True","","","","1 GB - 10 GB","","","True","True","True","True","True","True","True","True","","","very interested","very interested","moderately interested","not interested","not interested","very interested","1980-01-01 00:00:00" +"474","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","2595.99","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Apply FAIR","True","True","True","","","Jupyter","Anonymized","Anonymized","","True","","True","True","","","","","True","True","True","True","True","True","","Improved working with data","True","True","True","","","Yes","Yes","True","True","","True","","","","","","","","","","","","","","","","","","","","","","","PubData","True","True","True","True","True","","","True","","All","All","All","All","All","","","All","","None","Some of them","Some of them","Some of them","Some of them","","","Some of them","","Equally measured and simulated","Purely reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","True","","","True","True","True","","True","","","","10 GB - 100 GB","","","True","","","True","","","","","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"475","True","","","","","","","","True","","","","","","True","","","","","","","","","","","","","","","","","","","","","5.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","1015.01","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Systems Engineering","","","","","","","","","","","","1 to 3 years","Principal Investigator","","","Not familiar with FAIR","","True","","","","COMSOL Multiphysics","LabVIEW","MATLAB / Simulink","","","","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","All","Some of them","Some of them","All","","","","","None","None","None","None","None","","","","","Equally measured and simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","True","","","True","True","True","True","","","","","1 GB - 10 GB","","","","True","True","","","True","True","True","","","moderately interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"476","","","True","","","","","","","","","Reusability","","","True","","","True","","","Legal / ethical concerns","","","","","","","","","","","","","","","15.0","","True","","True","","","","","","","","","","","True","True","","","","","","","","","","","402.67","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","","Robotik","","","","","","","","","","","4 to 6 years","Research Associate","","","Not familiar with FAIR","","True","True","","","Python","Anonymized","","True","","","","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","All","","","","All","","","","","","","","","","","","","","Equally measured and simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","True","","","","True","","","10 GB - 100 GB","","","","","","","","","True","True","","","moderately interested","moderately interested","not interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"477","","","","Other","","True","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","5.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","573.69","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Physics","","","","","","","","","","","","","","","","","","Meteorology","","","","More than 10 years","Postdoc","","","Familiar with FAIR","","","","True","","Python","LabVIEW","Anonymized","","True","","","True","","","","","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","None","","","","","","","Equally measured and simulated","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","True","","","","True","","","","True","","","10 GB - 100 GB","","True","True","True","True","True","True","True","True","True","","","moderately interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"482","","True","","","True","","","","True","True","","","","True","True","","","True","","True","","","","","","","","","","","WDCC","Zenodo","","","","20.0","","True","True","True","True","","","","","","True","","","","True","True","","","","","","","","","","","476.25","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Apply FAIR","","","True","","","emacs","Anonymized","cdo","","True","","","True","","","","","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","None","Some of them","Some of them","Some of them","Some of them","","","","","Purely simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","True","True","","","","True","","","> 1 TB","","True","","True","True","True","True","","True","True","","","moderately interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"483","","True","","","","True","","","True","True","","","","","True","","","True","True","","","","","","","","","","","","","","","","","50.0","","","","","","","","","","","","","","","","True","","","","","","","","","","","2554.45","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Chemistry","","","","","","","","","","","","","","","","","","","","","","1 to 3 years","PhD candidate","","","Not familiar with FAIR","","True","","","","","","","","","","True","","True","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","Some of them","","","","Some of them","","","","","Some of them","","","","Some of them","","","","","Mostly simulated","Mostly reused","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","< 100 MB","","","","","","","","True","True","","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"485","True","","","","","","","True","","","","","","","True","","","","","","","","","","","","","","","","","","","","","90.0","","","","","","","","True","True","True","","","","","","","","","","","","","","","","","346.56","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","1 to 3 years","PhD candidate","","","Not familiar with FAIR","","True","","","","Python","Fortran","LaTeX","","True","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","","","","","","","","","None","All","","","","","","","Purely simulated","Purely generated","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","True","","","","True","","","> 1 TB","","","True","","True","","","","","","","","moderately interested","very interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"486","","True","","","True","True","","","True","","","","","","","True","","True","","","","","","","","","","","","","Zenodo","Gitlab / GitHub","","","","30.0","","True","","","","True","","","","","True","","","","True","True","","","","","","","","","","","443.33","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","Python","Fortran","Office Software (unspecified)","","True","True","","","","","","","True","True","True","True","","","","","","","True","","","Yes","Yes","","","","","","","","","","","","","","","","","","","","","","True","","","","","CF Metadata Conventions","True","True","True","","True","","","","","Some of them","All","All","","All","","","","","Some of them","Some of them","All","","All","","","","","Purely simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","True","True","","True","True","","","100 GB - 1000 GB (1 TB)","","","","","","","","True","","","","","moderately interested","moderately interested","not interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"487","","True","","","True","","","","True","","","Guidelines / policies of publishers","","","True","","","True","","True","","","","","","","","","","","","","","","","20.0","","","","","","True","","","","","","","","","","","","","","","","","","","","","1109.26","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","More than 10 years","Research Associate","","","Familiar with FAIR","","True","True","","","Fortran","Anonymized","Anonymized","","True","","True","True","","","","","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","None","","","","","","","","","None","","","","","","","","Mostly simulated","Mostly generated","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","100 GB - 1000 GB (1 TB)","","True","","","","True","","","True","True","","","moderately interested","","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"489","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","604.5","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","No degree","Student","","","Not familiar with FAIR","","True","","","","Python","Command line (scripts)","","","","","","","","","True","","","True","","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","None","","","","","","","","None","None","","","","","","","","Purely simulated","Purely reused","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","I don't know","","","","","","","","","","","","","moderately interested","very interested","very interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"491","","","","","","","","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","","25.0","","","","","","","","","","","","","","","","","","","","","","","","","","","485.4","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Physics","","","","","","","","","","","","","","","","","","Meteorology","","","","More than 10 years","Postdoc","","","Familiar with FAIR","True","True","","","","Fortran","Anonymized","","","True","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","None","","","","","","","","","Purely simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","True","","","","10 GB - 100 GB","","True","","","","","","True","True","","","","moderately interested","moderately interested","not interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"492","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","651.56","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Physics","","","","","","","","","","","","","","","","","","Meteorology","","","","1 to 3 years","PhD candidate","","","Not familiar with FAIR","","True","True","","","Fortran","Git","Python","","True","","","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","All","","","","","","","All","All","All","","","","","","","Purely simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","True","","","","True","","","> 1 TB","","True","","","","True","","","True","","","","moderately interested","very interested","very interested","moderately interested","very interested","","1980-01-01 00:00:00" +"493","True","","","","True","","","","True","","","Guidelines / policies of publishers","","","True","True","","True","","","","","","","","","","","","","","","","","","10.0","","True","","True","True","","True","True","","","","","","","","","","","","","","","","","","","790.7","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Physics","","","","","","","","","","","","","","","","","","Meteorology","","","","7 to 10 years","Postdoc","","","Not familiar with FAIR","True","True","","","","Python","Notepad++","ZEMAX","","True","True","","","","","","","","","","","","","","","","","","Source code and scripts","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","All","Some of them","","","","","","","None","All","Some of them","","","","","","","Equally measured and simulated","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","True","","","True","True","True","","True","True","Other","","> 1 TB","","True","","","","True","","","True","True","","","moderately interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"494","","True","","","True","True","","","True","","","","","","True","","","True","True","","","","","","","","","","","","WDCC","","","","","30.0","","","","","","True","","True","","","","","","","","","","","","","","","","","","","978.28","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","More than 10 years","Research Associate","","","Apply FAIR","","True","","","","","","","","True","True","","","","","","","","","","","","","","","True","","True","Other","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","All","","All","","","","","","","All","","Some of them","","","","","","Purely simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","> 1 TB","","True","","True","True","True","True","","","True","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"495","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","580.58","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","More than 10 years","Research Associate","","","Familiar with FAIR","","True","","","","Anonymized","Anonymized","Python","","True","","True","","","","","","True","","True","True","True","","","","","","True","","","Yes","Yes","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","True","True","True","","True","","","","","All","Some of them","Some of them","","All","","","","","All","Some of them","Some of them","","All","","","","Purely simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","100 GB - 1000 GB (1 TB)","","True","","True","","","","","True","","","","very interested","very interested","not interested","","very interested","moderately interested","1980-01-01 00:00:00" +"496","True","","","","True","","","","True","","","Guidelines / policies of publishers","","","True","","","True","","","","","","","","","","","","","","","","","","20.0","","True","","True","True","","","","","","","","","","","","","","","","","","","","","","974.56","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","7 to 10 years","Research Associate","","","Familiar with FAIR","","True","","","","cdo","Python","","","True","","","True","True","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","True","","","All","","","All","","","All","","","Some of them","","","Some of them","","","None","","","Purely simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","True","","","","True","","","10 GB - 100 GB","","True","","True","","","","True","True","","","","very interested","very interested","moderately interested","very interested","very interested","not interested","1980-01-01 00:00:00" +"498","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","726.38","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","True","True","","","","Python","Anonymized","Excel (Spreadsheets)","","True","","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","Some of them","Some of them","","","","","","","","Some of them","Some of them","","","","","","Purely simulated","Purely generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","100 MB - 1000 MB (1 GB)","","","","True","","","","","True","True","","","very interested","moderately interested","moderately interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"499","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Competition","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","902.64","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Life Science","","","","","","","","","","","","Medicine","","","","","","","","","","More than 10 years","Principal Investigator","Principal Investigator","","Familiar with FAIR","","True","","","","Excel (Spreadsheets)","SAS","PowerPoint","True","","","","","","","","","True","True","","True","","","","Improved collaborations","True","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","Some of them","Some of them","All","All","","","","","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","Purely measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","10 GB - 100 GB","","","","","","","","","","","","True","moderately interested","moderately interested","moderately interested","not interested","very interested","not interested","1980-01-01 00:00:00" +"500","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","561.54","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","4 to 6 years","Research Associate","","","Not familiar with FAIR","","True","","","","Anonymized","","","","","True","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","True","","","Some of them","Some of them","","Some of them","Some of them","","Some of them","","","None","None","","None","Some of them","","Some of them","","Purely simulated","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","< 100 MB","","True","True","True","True","True","True","True","True","True","","","not interested","very interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"501","True","True","","","","","","","True","True","","","","","","True","","True","True","","","","","","","","","","","","Gitlab / GitHub","Zenodo","","","","90.0","","True","True","True","","","","","","","","","True","","","True","True","","","","","","","","","","430.94","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","More than 10 years","Research Associate","","","Apply FAIR","","","True","","","Anonymized","","","","","True","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","True","","","","All","","","Some of them","All","All","","","","None","","","Some of them","None","None","","","","Equally measured and simulated","Purely reused","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","","True","","","","< 100 MB","","","","","","","","True","","True","","","moderately interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"502","True","","","","","","","","True","True","","","","","","True","","True","","True","","","","","","","","","","","","","","","","10.0","","","","True","True","","","","","","","","","","","","","","","","","","","","","","2088.62","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Familiar with FAIR","True","","","","","Anonymized","Paraview","ANSYS","","True","True","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","None","","","","","","","","","Purely simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","True","True","True","True","True","","","> 1 TB","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","moderately interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"503","","","","Supplementary to journal publication","True","","","","True","","","","","","True","","","True","","","","","","","","","","","","","","","","","","10.0","","","","","","True","True","","True","True","","","","","","","","","","","","","","","","","605.66","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Physics","","","","","","","","","","","","","","","","","","Soft Matter Physics","","","","More than 10 years","Research Associate","","","Familiar with FAIR","","True","","","","IDL","Python","Anonymized","","True","","","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","True","","","","Some of them","Some of them","All","","","All","","","","None","Some of them","None","","","None","","","Mostly measured","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","True","","","","","","","","10 GB - 100 GB","","True","","","True","","True","","True","","","","moderately interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"507","","True","","","","","","","","","","Guidelines / policies of publishers","","","True","True","True","True","True","True","","","","","","","","","","","Institutional Repository","","","","","50.0","","","","","","","","","","","","","","","","True","","","","","","","","","","","1312.49","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","More than 10 years","Postdoc","","","Not familiar with FAIR","True","True","True","","","Python","Anonymized","LabVIEW","","True","","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","None","","","","","Mostly measured","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","True","","","< 100 MB","","True","True","True","True","True","True","True","","True","","","moderately interested","very interested","moderately interested","very interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"509","True","True","","","True","","","","True","","","","","True","True","True","True","True","","","","","","","","","","","","","Zenodo","","","","","10.0","","True","","","True","","","","","","","","","","","","","","","","","","","","","","360.19","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Physics","","","","","","","","","","","","","","","","","","Meteorology","","","","7 to 10 years","Postdoc","","","Not familiar with FAIR","","True","True","","","Anonymized","Python","Anonymized","","True","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","All","All","Some of them","Some of them","","","","","","Purely simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","> 1 TB","","True","","True","True","","","","","","","","moderately interested","very interested","very interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"510","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","455.95","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","7 to 10 years","Research Associate","","","Familiar with FAIR","True","True","","","","TRACE","Tecplot","Anonymized","","True","","","True","","","","","True","","True","","","","","Improved working with data","","True","","Source code and scripts","","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","All","All","","","","","","","","Purely simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","True","","","10 GB - 100 GB","","True","","True","True","True","","","True","","","","very interested","very interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"511","","True","","","True","True","","","True","","","","","True","True","True","","","","","","","","","","","","","","","","","","","","10.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","496.6","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","MATLAB / Simulink","C/C++","","","True","True","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","None","","","","","Mostly simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","< 100 MB","","True","","","","True","","","True","","","","moderately interested","","","","","","1980-01-01 00:00:00" +"513","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","413.9","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","True","","","","","","","","","","True","True","True","","","","","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","Some of them","","","","Some of them","","","","","None","","","","None","","","","","Equally measured and simulated","Purely generated","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","True","","","I don't know","","","True","True","True","True","True","True","True","True","","","very interested","very interested","moderately interested","","very interested","moderately interested","1980-01-01 00:00:00" +"514","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","487.72","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Industrial Engineering","","","","","","","","","","","","More than 10 years","PhD candidate","","","Familiar with FAIR","","True","True","","","Python","Database Management System","Anonymized","","True","","True","","True","","","","True","True","True","","","","","","","","True","","","Yes","Yes","","","","True","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","Equally measured and simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","","True","True","True","True","True","True","","","1 GB - 10 GB","","True","True","","True","True","True","","","True","","","moderately interested","moderately interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"515","True","","","","True","True","","","True","","","","","True","True","True","","True","","True","","","","","","","","","","","","","","","","20.0","","","","True","True","True","","","True","True","","","True","","","","","","","","","","","","","","903.67","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Postdoc","","","Not familiar with FAIR","","True","","","","Office Software (unspecified)","Python","","","True","True","True","True","","","","","","","","","","","","","True","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","True","","","Some of them","Some of them","Some of them","Some of them","","","","","","None","None","None","None","","","None","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","True","True","True","","","","100 MB - 1000 MB (1 GB)","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"516","True","","","","True","","","","","","","","","True","True","","","","","","","","","","","","","","","","","","","","","10.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","596.33","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","True","True","","","","Python","Office Software (unspecified)","CFD Software (e.g. TecPlot, ParaView)","","True","","","","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","Some of them","All","Some of them","Some of them","","","","","None","None","Some of them","Some of them","None","","","","","Equally measured and simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","True","","","","True","True","True","True","True","","","1 GB - 10 GB","","","","","True","","","","","","","","","moderately interested","","","","","1980-01-01 00:00:00" +"517","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1193.75","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","Anonymized","Anonymized","Python","","True","True","","True","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","None","None","None","None","","","","","Mostly simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","True","True","True","","True","True","","","1 GB - 10 GB","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","not interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"518","","","True","","","True","True","","True","","","","","","True","","True","","","","","","","","","","","","","","","","","","","25.0","","True","True","True","True","True","True","True","True","True","True","True","","","True","True","","","","","True","","","","","","578.95","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Mechanical Engineering","","","","","","","","","","","","Less than 1 year","Research Associate","","","Not familiar with FAIR","","True","","","","Anonymized","CATIA CAD-software","Excel (Spreadsheets)","","","","True","","","True","True","","True","True","","","","","","","","","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","True","","","All","All","All","","All","","All","","","","","","","","","","","","Mostly simulated","Mostly reused","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","True","True","","","","","100 MB - 1000 MB (1 GB)","","","","","","","","","True","True","","","moderately interested","not interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"519","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","30.0","","True","","True","","True","True","True","","True","True","","","","","","","","","","","","","","","","779.08","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Mechanical Engineering","","","","","","","","","","","","7 to 10 years","Research Associate","","","Familiar with FAIR","True","True","","","","MATLAB / Simulink","LabVIEW","Python","","True","True","True","","","","","","True","","True","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","Some of them","Some of them","Some of them","","","","","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","Other","","1 GB - 10 GB","","","","True","","True","","","True","","","","very interested","very interested","not interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"520","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","437.23","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","","True","","","","MATLAB / Simulink","Python","Git","","","","","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","All","","","All","","","","","","None","","","None","","","","","","Mostly simulated","Equally generated and reused","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","True","","True","","","","100 MB - 1000 MB (1 GB)","","True","","True","True","","","True","True","","","","very interested","moderately interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"521","","True","","","","True","True","True","","","","","","","True","True","","","","","","","","","","","","","","","","","","","","25.0","","","","True","True","","","","True","True","True","","","","","","","","","","","","","","","","621.55","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","Excel (Spreadsheets)","Word","PowerPoint","","","True","","","","","","","","","","","","True","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","None","","None","None","","","","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","100 MB - 1000 MB (1 GB)","","","","","","","","","","","","True","moderately interested","moderately interested","moderately interested","very interested","very interested","not interested","1980-01-01 00:00:00" +"522","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","507.48","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","","Fahrzeugtechnik","","","","","","","","","","","Less than 1 year","Research Associate","","","Not familiar with FAIR","","True","","","","Python","Excel (Spreadsheets)","PowerPoint","","True","True","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","All","All","","","","","","","","Mostly simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","True","","True","","","","100 MB - 1000 MB (1 GB)","","True","","True","True","","","","","","","","very interested","very interested","moderately interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"523","True","","","","","True","","True","True","","","","","","True","True","True","","","","","","","","","","","","","","","","","","","70.0","","","","True","True","True","True","True","","","","","True","True","","","","","","","","","","","","","356.17","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","","Technology Assessment","","","","","","","","","","","","","","","","","","","","","More than 10 years","Research Associate","","","Apply FAIR","","True","","","","Office Software (unspecified)","Python","Database Management System","","True","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","None","None","Some of them","None","","","","","Mostly simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","True","True","","True","","","","< 100 MB","","True","","","True","True","True","","True","","","","very interested","not interested","not interested","moderately interested","very interested","not interested","1980-01-01 00:00:00" +"524","","True","","","True","","","True","True","","","","","","","True","","","True","","","","","","","","","","","","WDCC","","","","","10.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","1819.67","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Physics","","","","","","","","","","","","","","","","","","Meteorology","","","","4 to 6 years","Postdoc","","","Not familiar with FAIR","","","True","","","Python","Anonymized","emacs","","","","","","","","","Lack of technical solutions","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","All","All","All","","All","","","","","All","All","All","","All","","","","Mostly simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","True","","","","True","","","True","True","","","> 1 TB","","True","","","","True","","True","","True","","","moderately interested","very interested","very interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"526","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","640.92","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","7 to 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","Anonymized","Tecplot","ANSYS","","True","True","","","","","","","True","True","True","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","","All","All","","","All","","","","","Some of them","Some of them","","","Some of them","","","","","Mostly simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","True","True","","","True","True","","","> 1 TB","","","","True","True","True","","","True","","","","moderately interested","moderately interested","not interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"527","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","Legal / ethical concerns","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","649.25","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Life Science","","","","","","","","","","","","","Verkehrsforschung","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","R","Python","","","","","","","","","True","","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","All","","","All","","","","","","Some of them","","","Some of them","","","","","","Purely simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","1 GB - 10 GB","","","","","True","","","True","","","","","moderately interested","moderately interested","very interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"528","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","673.85","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","7 to 10 years","PhD candidate","","","Not familiar with FAIR","True","True","","","","Python","LaTeX","Anonymized","","","True","True","","","","True","","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","","","All","All","","","","","","None","","None","None","","","","","","Mostly measured","Equally generated and reused","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","","","","< 100 MB","","True","","","","True","True","True","True","","","","very interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"529","True","","","","True","True","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","50.0","","","","True","True","","","","True","True","True","","True","True","","","","","","","","","","","","","274.34","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","Less than 1 year","Research Associate","","","Not familiar with FAIR","True","","","","","","","","","","","","True","","","True","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","Some of them","","Some of them","Some of them","Some of them","","","","","All","","All","Some of them","None","","","","","Mostly measured","Equally generated and reused","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","True","","","True","True","","True","","","","I don't know","","True","True","","True","True","","","","","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"530","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","333.23","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Mechanical Engineering","","","","","","","","","","","","Less than 1 year","PhD candidate","","","Not familiar with FAIR","","True","","","","Dymola","ANSYS","CATIA CAD-software","","","","","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","Some of them","","","","","","","","","Equally measured and simulated","Equally generated and reused","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","True","","","","","100 MB - 1000 MB (1 GB)","","","","True","True","True","True","","True","True","","","moderately interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"531","","","","","","","","True","","","","","","","True","","","","","","","","","","","","","","","","","","","","","15.0","","True","","True","True","","True","","","","","","True","","","True","","","","","","","","","","","675.48","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","7 to 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","ANSYS","CATIA CAD-software","Excel (Spreadsheets)","","True","True","","","True","","True","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","","","","Some of them","Some of them","","Some of them","Some of them","","","","","None","None","","None","None","","","","","Equally measured and simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","","","","","True","True","True","True","","","","10 GB - 100 GB","","True","","True","True","True","True","True","True","","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"532","","True","","","True","True","","","","","","","","","True","","","","","","","","","","","","","","","","GLIMS","","","","","90.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","562.65","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Earth Science","","","","","","","","Geography","","","","","","","","","","","","","","More than 10 years","Research Associate","","","Apply FAIR","True","","","","","Python","MATLAB / Simulink","ArcGIS","","True","","True","","","","","","True","","True","True","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","True","","","All","All","All","All","All","","All","","","None","None","None","None","None","","None","","","Equally measured and simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","10 GB - 100 GB","","","","True","","True","","","","True","","","very interested","very interested","not interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"535","","","","Supplementary to journal publication","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","10.0","","","","","","","","","","","","","","","","","","","","","","","","","","","333.81","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Industrial Engineering","","","","","","","","","","","","4 to 6 years","Research Associate","","","Not familiar with FAIR","True","True","","","","Excel (Spreadsheets)","Python","","","","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","True","","","","All","All","","","All","All","","","","Some of them","Some of them","","","None","None","","","","Mostly simulated","Mostly reused","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","True","","","","True","True","","True","","","","< 100 MB","","","","","True","True","True","True","True","","","","moderately interested","very interested","very interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"537","True","True","","","True","True","","","True","","","","True","","","","","","","","","","","","","","","","","","Zenodo","","","","","95.0","","True","","","","","","","","","","","","","","","","","","","","","","","","","1211.02","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Physics","","","","","","","","","","","","","","","","","","","space physics","","","7 to 10 years","Postdoc","","","Familiar with FAIR","","True","","","","Python","","","","True","True","","True","","","","","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","","","","","","","","","","Purely measured","Mostly generated","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","True","","","True","True","","","100 MB - 1000 MB (1 GB)","","True","","","","","","","","","","","moderately interested","moderately interested","","","","","1980-01-01 00:00:00" +"538","True","","True","","","True","","True","","","","Guidelines / policies of publishers","","","","","","True","","True","","","","","","","","","","","","","","","","75.0","","","","","","","","","","True","True","","True","True","True","True","","","","","","","","","","","800.45","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Physics","","","","","","","","","","","","","","","","","","","Space Weather","","","More than 10 years","Principal Investigator","","","Not familiar with FAIR","","True","","","","Python","C/C++","Office Software (unspecified)","","True","","","","","","","","True","True","","","","True","","","","","True","GitLab","","Yes","Yes","","","","True","","","","","","","","","","","","","","","","","","True","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","All","","","","","","","Some of them","All","All","","","","","Mostly measured","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","","","","True","True","","True","True","","","10 GB - 100 GB","","True","True","","","","","True","","","","","moderately interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"543","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","10.0","","True","","True","True","","","","","","","","","","","True","","","","","","","","","","","319.03","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","Less than 1 year","Student","","","Not familiar with FAIR","","True","","","","CATIA CAD-software","Anonymized","Tecplot","","","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","All","","","","All","","","","","All","","","","Some of them","","","","","Purely simulated","Mostly generated","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","10 GB - 100 GB","","","True","","","","","","True","","","","very interested","moderately interested","not interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"544","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","642.02","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","","True","","","","Visual Studio","Anonymized","Excel (Spreadsheets)","","","","","","","","True","","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","All","","","","","","","","Purely simulated","Purely generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","True","","","","100 MB - 1000 MB (1 GB)","","","","True","True","True","True","","True","True","","","moderately interested","very interested","not interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"547","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","316.93","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","","True","","","","Python","Tecplot","Anonymized","","","True","","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","True","","","All","","Some of them","Some of them","","","","","","Some of them","","None","None","","","","","Equally measured and simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","True","","","","","True","","","True","","","100 GB - 1000 GB (1 TB)","","","","True","True","","","","True","True","","","moderately interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"548","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","873.84","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","4 to 6 years","Research Associate","","","Not familiar with FAIR","True","True","","","","Python","Anonymized","Anonymized","True","","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","","","","All","All","","All","All","","","","","None","Some of them","","All","None","","","","","Mostly simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","True","True","True","True","","","10 GB - 100 GB","","True","","","","True","","True","True","","","","very interested","very interested","moderately interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"550","True","","","","","True","","","True","","","","","","","True","","","","","","","","","","","","","","","","","","","","35.0","","True","","True","True","True","","True","","","","True","","","","","","","","","","","","","","","1233.01","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Industrial Engineering","","","","","","","","","","","","7 to 10 years","Principal Investigator","","","Not familiar with FAIR","","True","","","","Word","Excel (Spreadsheets)","Anonymized","","","","","","","","","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","True","","","","","","","","","","","","","","","","","","","","","","Equally measured and simulated","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","< 100 MB","","","","True","","","","True","True","","","","very interested","moderately interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"551","True","","","","","","True","True","True","","","","","","","True","","","","","","","","","","","","","","","","","","","","5.0","","","","True","True","True","True","","True","True","True","","","True","","","","","","","","","","","","","1031.77","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","7 to 10 years","Principal Investigator","","","Not familiar with FAIR","True","True","","","","Anonymized","Python","Excel (Spreadsheets)","","True","True","","True","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","None","Some of them","Some of them","Some of them","Some of them","","","","","","Some of them","Some of them","","","","","","","Mostly simulated","Mostly generated","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","True","","True","","","","","","1 GB - 10 GB","","True","True","True","","True","True","","True","","","","very interested","very interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"553","","True","","","True","True","","","","","","","","","True","True","","","","","","","","","","","","","","","Gitlab / GitHub","","","","","10.0","","","","","","","","","","","True","True","True","True","","","","","","","","","","","","","417.76","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","7 to 10 years","Research Associate","","","Not familiar with FAIR","","True","True","","","Python","Anonymized","","","","True","True","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","Some of them","","Some of them","All","","","","","","Purely simulated","Mostly generated","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","1 GB - 10 GB","","","","","True","True","","","","True","","","very interested","moderately interested","moderately interested","not interested","not interested","moderately interested","1980-01-01 00:00:00" +"555","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","433.29","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","4 to 6 years","Research Associate","","","Not familiar with FAIR","","True","","","","MATLAB / Simulink","Excel (Spreadsheets)","Anonymized","","True","True","","True","","","","","True","True","True","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","Some of them","","Some of them","","","","","","","None","","None","","","","","","","Purely measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","True","","","","","","","","","","","1 GB - 10 GB","","True","","True","True","","","True","True","","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"560","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","661.8","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","7 to 10 years","PhD candidate","","","Not familiar with FAIR","True","True","","","","ANSYS","MATLAB / Simulink","Word","True","","","","","","","","","True","True","True","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","True","","","All","All","All","All","All","","All","","","None","None","None","Some of them","None","","Some of them","","","Purely simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","True","","","True","True","True","True","True","","","","1 GB - 10 GB","","True","True","True","True","True","","True","True","True","","","moderately interested","moderately interested","moderately interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"561","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","793.78","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Apply FAIR","","True","","","","Anonymized","Anonymized","Anonymized","","True","","","","True","","","","","","","","","","","","","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","All","All","All","","All","","","","","Some of them","Some of them","Some of them","","Some of them","","","","","Mostly simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","True","True","True","True","True","True","","","100 MB - 1000 MB (1 GB)","","True","","","","","True","True","","","","","moderately interested","","","moderately interested","","","1980-01-01 00:00:00" +"564","","","","In repository","True","True","","","","","","","","","True","True","True","","True","","","","","","","","","","","","","","","","","80.0","","","","True","True","","","","True","True","","True","","","True","","","","","","","","","","","","504.94","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","7 to 10 years","Principal Investigator","","","Not familiar with FAIR","True","","","","","Anonymized","Anonymized","Tecplot","True","","","","","","","","","True","True","True","True","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","All","","All","","All","","","","","None","","All","","All","","","","","Mostly measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","True","True","","","True","True","True","True","True","","","100 GB - 1000 GB (1 TB)","","","","","","","","","","","","True","not interested","not interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"565","","","","","","","","","","True","","","True","","","","","","","","","","","","","","","","","","","","","","","60.0","","","","True","True","","True","True","True","True","","","","","","","","","","","","","","","","","561.95","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Familiar with FAIR","","True","","","","MATLAB / Simulink","Python","Office Software (unspecified)","","True","True","","","","","","","True","True","True","True","","True","","","","","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","Some of them","","","","","","","Some of them","All","Some of them","","","","","","","Purely measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","","","True","","","","1 GB - 10 GB","","","","True","","","","","","","","","moderately interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"567","","","","Other","True","True","","","","True","","","","","True","","True","","True","","","","","","","","","","","","","","","","","5.0","","True","True","True","True","True","True","True","True","True","True","True","","","","","","True","","","","","True","","","","1393.94","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","7 to 10 years","Research Associate","","","Apply FAIR","","True","","","","Python","C/C++","MATLAB / Simulink","","True","","","True","True","","","","True","True","","","","","","","","","True","","","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","True","","True","","All","All","Some of them","","","All","","Some of them","","None","None","None","","","None","","None","","Mostly measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","True","","","True","True","","True","","","","100 GB - 1000 GB (1 TB)","","","","True","","True","","True","True","True","","","moderately interested","very interested","","very interested","moderately interested","very interested","1980-01-01 00:00:00" +"568","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","Legal / ethical concerns","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","638.34","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","Excel (Spreadsheets)","Python","Anonymized","True","","","","","","","","","True","True","True","True","","True","","","True","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","None","None","None","All","","","","","Purely measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","True","","","True","True","True","","True","","","","10 GB - 100 GB","","","","","","","","True","","","","","very interested","not interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"569","True","","","","True","","","","","True","","Guidelines / policies of publishers","","True","True","","","True","","","","","","","","","","","","","","","","","","10.0","","","","True","True","","","","True","True","","","","","","True","","","","","","","","","","","760.58","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","PhD candidate","","","Not familiar with FAIR","True","True","","","","CATIA CAD-software","Office Software (unspecified)","Anonymized","","True","","True","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","All","Some of them","Some of them","","Some of them","","","","","Some of them","Some of them","None","","Some of them","","","","","Mostly simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","True","True","","","","True","True","True","","","","100 MB - 1000 MB (1 GB)","","True","","","True","True","","","","","","","very interested","moderately interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"570","True","","","","True","","","","True","True","","","","","True","True","","True","","True","","","","","","","","","","","","","","","","10.0","","True","True","True","True","True","True","True","True","True","True","True","","True","True","True","","","","","","","","","","","759.78","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","","","","","","","","","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Not familiar with FAIR","","True","","","","R","Anonymized","Python","","","True","","True","","","","","True","True","True","True","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","","","All","All","All","All","All","Some of them","","","","Some of them","Some of them","Some of them","None","Some of them","None","","","","Mostly measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","True","True","True","True","True","True","","True","True","","","100 GB - 1000 GB (1 TB)","","True","","True","True","True","","","True","","","","moderately interested","very interested","very interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"574","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","645.69","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","Less than 1 year","Student","","","Not familiar with FAIR","True","True","","","","Python","Anonymized","LabVIEW","","True","True","True","True","","","True","","True","True","True","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","None","Some of them","","","","","","","","Equally measured and simulated","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","True","","","True","True","","","True","","","","moderately interested","moderately interested","not interested","moderately interested","very interested","not interested","1980-01-01 00:00:00" +"576","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","357.65","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Mathematics","","","","","","","","","","","","","","","Data Science","","","","","","","Less than 1 year","Research Associate","","","Not familiar with FAIR","","True","","","","Python","Git","Anonymized","","","","","True","","","","","","","","","","True","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","","","All","All","","","","All","","","","None","None","","","","None","","","","Purely measured","Purely reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","True","True","","","","","","","","","True","True","True","True","True","","","very interested","very interested","moderately interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"577","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1181.02","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","","Verkehrswissenschaften","","","","","","","","","","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","True","True","","","","Python","Visual Studio","Database Management System","True","","","","","","","","","","","","","","","","","","True","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","All","","All","","","","","","","All","","All","","","","","","Purely measured","Mostly reused","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","","","True","","","True","True","","","1 GB - 10 GB","","True","True","True","","","","True","True","True","","","very interested","very interested","very interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"578","","True","","","","","","","True","","","Guidelines / policies of publishers","","","True","True","","True","True","True","","","","","","","","","","","Zenodo","","","","","50.0","","","","","","","","","","","True","True","True","True","","","","","","","","","","","","","812.26","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Physics","","","","","","","","","","","","","","","","","","Meteorology","","","","More than 10 years","Research Associate","","","Apply FAIR","","True","","","","","","","","True","True","True","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","None","","None","None","","","","","","Mostly simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","True","True","","","True","Binary non-scientific formats","","> 1 TB","","True","True","True","True","True","True","True","True","","","","very interested","moderately interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"579","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","329.92","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Systems Engineering","","","","","","","","","","","","4 to 6 years","Research Associate","","","Familiar with FAIR","","","","True","","Python","QGIS/GDAL","Visual Studio","","","True","True","True","","","","","","","","","","","","","True","True","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","","","","","","","","","","","","","","","","Mostly measured","Mostly reused","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","10 GB - 100 GB","","True","True","True","","True","","","","","","","moderately interested","very interested","not interested","moderately interested","moderately interested","not interested","1980-01-01 00:00:00" +"580","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","568.68","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Industrial Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","Principal Investigator","","Not familiar with FAIR","","True","","","","Excel (Spreadsheets)","Anonymized","Word","","True","","True","","True","","","","True","","","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","","","All","All","","","","All","","","","None","None","","","","None","","","","Equally measured and simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","True","","True","","","","I don't know","","","","","","","","","","","","True","not interested","not interested","moderately interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"581","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","10.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","338.03","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Psychology","","","","","","","","","","","","","","","","","","","","","Human Factors","More than 10 years","Principal Investigator","Principal Investigator","","Not familiar with FAIR","","True","","","","","","","","True","True","","","True","","","","","True","True","True","True","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","None","None","None","None","","","","","Purely measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","True","","","True","","True","","","","1 GB - 10 GB","","","","","","","","","","","","","","","","","","","1980-01-01 00:00:00" +"588","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","520.38","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","True","True","","","","MATLAB / Simulink","Python","Excel (Spreadsheets)","","True","True","","True","True","","True","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","","Some of them","Some of them","","","All","","","","","None","None","","","None","","","","","Mostly measured","Purely generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","True","True","True","","","True","","","1 GB - 10 GB","","True","True","True","","","","True","True","True","","","moderately interested","very interested","moderately interested","very interested","not interested","moderately interested","1980-01-01 00:00:00" +"590","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","420.62","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","","Logistik/Verkehr","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","True","True","","","","Python","Anonymized","Anonymized","","True","True","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","None","All","None","None","","","","","","Purely simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","True","","","","True","True","","True","","","","1 GB - 10 GB","","True","","","True","True","True","True","True","","","","moderately interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"591","","","","","","","","","","","","","","","","","","","","","","True","","True","","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","331.1","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","","True","","","","CATIA CAD-software","Python","ANSYS","True","","","","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","Some of them","Some of them","","","","","","","","Some of them","Some of them","","","","","","","","Equally measured and simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","True","True","True","","","","","1 GB - 10 GB","","True","True","","","","","","","","","","moderately interested","moderately interested","not interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"595","True","","","","True","","True","","True","","","","","True","True","True","","","","","Technical support needed","","","","","","","","","","","","","","","10.0","","","","","True","True","","","","","","","","","","","","","","","","","","","","","521.88","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Psychology","","","","","","","","","","","","","","","","","","","","Industrial and Organisational Psychology","","More than 10 years","Principal Investigator","Principal Investigator","","Not familiar with FAIR","","True","","","","R","Python","SPSS","","True","True","True","","","","","","","","","","","","","","True","True","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","Some of them","Some of them","","Some of them","","","","","","Some of them","Some of them","","Some of them","","","","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","True","True","True","","","","","","","10 GB - 100 GB","","True","True","True","True","","True","True","True","","","","very interested","very interested","very interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"596","True","","","","","","","True","True","True","","","","","True","True","","","","","","","","","","","","","","","","","","","","85.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","605.52","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Psychology","","","","","","","","","","","","","","","","","","","","","","1 to 3 years","PhD candidate","","","Not familiar with FAIR","","True","","","","","","","","","","True","True","True","","","","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","None","","","","","","","","","Purely measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","True","","True","","True","True","True","True","","","","1 GB - 10 GB","","","","","","","","","","","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"597","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1816.81","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","True","True","","","","","","","","","","True","True","","","","","True","True","True","","","","","","","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","Some of them","Some of them","","","","","","","","Mostly measured","Equally generated and reused","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","True","","","","","","","True","True","True","","","True","True","True","","","","very interested","very interested","very interested","very interested","very interested","","1980-01-01 00:00:00" +"599","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1876.88","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","Principal Investigator","","Not familiar with FAIR","","True","","","","MATLAB / Simulink","Anonymized","Anonymized","","True","","","True","","","","","True","","True","True","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","All","All","All","","All","","","","","Some of them","Some of them","Some of them","","Some of them","","","","","Equally measured and simulated","Purely reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","","True","True","True","","","True","","","100 MB - 1000 MB (1 GB)","","","True","True","","True","","True","True","","","","not interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"600","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","617.02","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Not familiar with FAIR","True","True","","","","MATLAB / Simulink","","","True","","","","","","","","","True","True","True","True","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","All","","All","","","","","","","Some of them","","Some of them","","","","","","","Equally measured and simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","True","","","","","","100 MB - 1000 MB (1 GB)","","","","","","","","","","","","True","moderately interested","moderately interested","not interested","not interested","not interested","moderately interested","1980-01-01 00:00:00" +"601","True","","","","True","True","","","","True","","","","","True","","","True","","True","","","","","","","","","","","","","","","","10.0","","","","","","","True","True","","True","","","","","","","","","","","","","","","","","913.81","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Physics","","","","","","","","","","","","","","","","","","Meteorology","","","","4 to 6 years","Research Associate","","","Familiar with FAIR","True","True","","","","Python","MATLAB / Simulink","C/C++","","True","","","True","","","","","True","True","True","True","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","True","","","All","All","","All","","","All","","","All","All","","All","","","All","","Equally measured and simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","True","True","","True","True","","","10 GB - 100 GB","","","True","","","","","","","True","","","not interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"602","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","344.9","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","1 to 3 years","PhD candidate","","","Not familiar with FAIR","","True","","","","MATLAB / Simulink","Anonymized","Anonymized","","True","","","","","","","","","","","","","","","","True","True","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","None","","","","Some of them","","","","","Some of them","","Some of them","","None","","","","","Mostly simulated","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","True","True","True","True","","","","100 MB - 1000 MB (1 GB)","","","","","","","","True","True","","","","not interested","not interested","moderately interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"605","True","True","","","True","True","","","True","","","","","True","","","","True","","","","","","","","","","","","","","","","","","100.0","","True","True","True","True","True","True","True","True","True","True","True","True","True","True","True","","","True","","","","","","","","619.07","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","","","","True","True","","","Anonymized","","","","True","","","True","","","","","True","True","True","True","","","","","True","","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","True","","","All","All","All","All","All","","All","","","All","All","","All","All","","All","","","Mostly simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","True","","True","","","","100 MB - 1000 MB (1 GB)","","","","","","","","","","","","","moderately interested","moderately interested","not interested","very interested","moderately interested","very interested","1980-01-01 00:00:00" +"606","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","Legal / ethical concerns","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","499.52","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","","Verkehrswesen","","","","","","","","","","","More than 10 years","Research Associate","","","Apply FAIR","True","","","","","R","Python","C/C++","","","","","","","True","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","","","","All","All","","All","All","","","","","None","Some of them","","None","Some of them","","","","","Mostly simulated","Purely reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","True","","True","True","","True","True","","","1 GB - 10 GB","","True","","","","","","","","","","","moderately interested","very interested","not interested","moderately interested","moderately interested","not interested","1980-01-01 00:00:00" +"615","","","","","","","","","","","","","","","","True","","True","True","True","","","","","","","","","","","","","","","","10.0","","","","","","","","","","","","","","","","","","","","","","","","","","","482.36","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","","","","","","","","","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","Principal Investigator","","Not familiar with FAIR","","True","True","","","Anonymized","Java","Word","","True","True","","True","True","","","","","","True","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Mostly measured","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","Other","","< 100 MB","","","","","","","","True","True","True","","","not interested","moderately interested","very interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"616","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","321.25","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Psychology","","","","","","","","","","","","","","","","","","","","","Verkehrspsychologie","Less than 1 year","Research Associate","","","Not familiar with FAIR","","True","","","","R","Excel (Spreadsheets)","SPSS","","True","True","","True","True","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","None","None","","","","","","","","Mostly measured","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","True","","True","True","","","","","","100 MB - 1000 MB (1 GB)","","True","","True","True","","True","True","True","","","","very interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"617","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","586.22","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Psychology","","","","","","","","","","","","","","","","","","","","","Experimentelle Psychologie","More than 10 years","Postdoc","","","Not familiar with FAIR","","True","","","","R","Notepad++","Anonymized","","True","True","","True","True","","True","","","","","","","","","","","True","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","","","Some of them","All","","","","Some of them","","","","None","None","","","","None","","","","Purely measured","Purely generated","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","1 GB - 10 GB","","True","True","True","True","","True","True","True","","","","moderately interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"618","","","","","","","","","","","","","","","","","","","","","","True","","","True","","True","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","498.1","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","","True","","","","MATLAB / Simulink","MATLAB / Simulink","Excel (Spreadsheets)","","True","True","True","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","None","None","","","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","True","True","","True","","Other","","1 GB - 10 GB","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"619","True","","","","True","","","","True","True","","","","","","","","","True","True","","","","","","","","","","","","","","","","100.0","","","","","","","","","","","","","","","","","","","","","","","","","Others","","624.83","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","More than 10 years","Principal Investigator","","","Not familiar with FAIR","True","","True","","","MATLAB / Simulink","Anonymized","Anonymized","True","","","","","","","","","","","","","","","","","","","","","True","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","","","","","","","","","","","","","","","","","","","","","Equally measured and simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","True","","True","","","","","> 1 TB","","","","","","","","True","","","","","not interested","not interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"620","True","","","","","True","","","True","True","","","","","True","True","True","","True","","","","","","","","","","","","","","","","","20.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","382.72","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Systems Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Familiar with FAIR","True","True","","","","Anonymized","Anonymized","PowerPoint","","True","True","","","True","","","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","True","","","","Some of them","","","Some of them","","Some of them","","","","None","","","None","","None","","","","Equally measured and simulated","Purely reused","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","True","True","True","","True","True","True","","True","True","","","100 MB - 1000 MB (1 GB)","","","","True","True","True","","True","True","","","","moderately interested","very interested","very interested","not interested","very interested","very interested","1980-01-01 00:00:00" +"621","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","557.01","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Psychology","","","","","","","","","","","","","","","","","","","","","Human Factors","4 to 6 years","Research Associate","","","Not familiar with FAIR","True","True","","","","SPSS","Office Software (unspecified)","R","","True","","True","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","None","None","None","None","","","","","Purely measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","< 100 MB","","","True","True","","True","","True","True","","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"622","True","","","","True","True","","","","True","","","","","True","","","","","","","","","","","","","","","","","","","","","30.0","","True","","True","","True","","","","","","","","","","","","","","","","","","","","","434.95","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Physics","","","","","","","","","","","","","","","","","","Astrophysics and Astronomy","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","True","","","","","MATLAB / Simulink","Word","Anonymized","","","","","","","","True","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","Some of them","All","","","","","","","","None","None","","","","","","","","Equally measured and simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","","","","","","< 100 MB","","","","","","","","","","True","","","not interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"627","True","True","","","True","","","True","True","","","","True","","","","","","","","","","","","","","","","","","ProteomeXchange","","","","","80.0","","True","True","True","True","","","","True","True","True","True","","True","","True","","","","","","","","","","","560.23","Completed the survey","Anonymized","Anonymized","Earth and Environment","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","4 to 6 years","Postdoc","","Yes","","","True","","","","","","","","","","True","","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","All","","All","Some of them","All","","","","","None","","Some of them","Some of them","Some of them","","","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","True","True","True","","","","","Microscopy","","","MS","","","Speciation calculations","","","","","","","","","","","","","","","","","","","True","","True","","","","","True","","","","","","< 100 MB","","True","","True","","True","","","","","","","very interested","moderately interested","moderately interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"628","True","","","","True","","","True","True","","","","","","","True","","True","","","","","","","","","","","","","","","","","","10.0","","","","","","","True","True","","","","True","True","","","","","","","","","","","","","","800.02","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Geology","","","","","","","","","","","","","","More than 10 years","Research Associate","","Yes","Apply FAIR","True","True","","","","Python","","","","","True","True","True","","","","","","","","","","","","","","","","Source code and scripts","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","All","","","","","","","None","None","None","","","","","","Equally measured and simulated","Mostly generated","Yes","","","","","","","","","","","","","","","True","","","","","","","digital processing","Machine learning","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","True","","","1 GB - 10 GB","","True","","","True","True","","True","True","True","","","moderately interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"630","","True","","","True","","True","","","True","","","","","","True","","True","True","","","","","","","","","","","","PANGAEA","","","","","90.0","","True","True","","True","True","True","True","True","True","True","True","True","True","","","True","True","","","","","True","","Scope of data set","","615.87","Completed the survey","Anonymized","Anonymized","Earth and Environment","","Computer Science","","","","","","","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","True","","","","","OpenCV","Jupyter","QGIS/GDAL","","True","True","","True","True","","","","True","True","True","","True","","","","","","True","","","Yes","Yes","","True","","True","","","","","True","","","","","","","","","","","","","","","","","","iFDO","True","True","True","True","","True","","True","","Some of them","Some of them","Some of them","Some of them","","Some of them","","Some of them","","Some of them","Some of them","Some of them","Some of them","","Some of them","","Some of them","","Purely measured","Mostly generated","No","","","","","","","","","","","","","","","True","","","","","","","Underwater photo / video by marine robots","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","True","","","","True","","","True","","","","> 1 TB","","","","True","True","True","","True","True","True","","","moderately interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"632","True","","","","","True","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","85.0","","","","True","True","","","","True","","True","","","","","","","","","","","","","","","","608.74","Completed the survey","Anonymized","Anonymized","Earth and Environment","","Biologie","","","","","","","","","","","","","","","","","","","","","4 to 6 years","Postdoc","","Yes","Familiar with FAIR","True","","","","","Office Software (unspecified)","R","","","","","True","","","","","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","All","","All","","","","","","","None","","None","","","","","","","Purely measured","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","Other","","","","","","","","","","","","","","","","Fangnetze","GIS","","","","","","","","","","","","","","","","True","","True","","","","100 MB - 1000 MB (1 GB)","","True","","True","","","","","","","","","very interested","moderately interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"634","","True","","","True","","","","True","","","","","","","","","","","True","","","","","","","","","","","DataONE","","","","","75.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","917.82","Completed the survey","Anonymized","Anonymized","Earth and Environment","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","More than 10 years","Postdoc","","Yes","Apply FAIR","","","True","","","R","Office Software (unspecified)","","","","","","True","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","","All","All","","","All","","","","","All","All","","","All","","","","","Mostly measured","Purely reused","Yes","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","field-based monitoring","environemntal data from GIS, shared field-based environmental data","","","","","","","","","True","","","True","True","True","","","","","","","True","","","","I don't know","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"635","True","True","","","True","","","True","True","","","","True","","","","","","","","","","","","","","","","","","Institutional Repository","","","","","40.0","","","","True","True","True","True","","True","True","True","True","True","True","","True","","","","","","","","","","","965.31","Completed the survey","Anonymized","Anonymized","Earth and Environment","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","More than 10 years","Research Associate","","Yes","Familiar with FAIR","True","True","True","","","Office Software (unspecified)","Anonymized","Anonymized","True","","","","","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","All","None","None","All","","","","","Mostly measured","Mostly reused","Yes","","","","","","","","","","","","","","","True","True","","","","","","(Fluoreszenz)mikroskopie","Elektronenmikroskopie","Heliumionenmikroskopie","UV/VIS-Spektroskopie","Elementanalytik","Massenspektrometrie","","","","","","","","","","","","","","","","True","","True","","True","","True","","","","","True","","True","","","","1 GB - 10 GB","","","","True","","True","","","","True","","","very interested","very interested","very interested","very interested","very interested","","1980-01-01 00:00:00" +"637","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","423.36","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Environmental Science","","","","","","","","","","","","","","Less than 1 year","PhD candidate","","No","Not familiar with FAIR","","","","True","","Python","Google Earth Engine","","","True","","","","","","","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","None","","","","","","","","","Purely measured","Purely reused","","","","","","","","","","","","","","","","True","","","","","","","synthetic aperture radar signal processing","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Other","","100 GB - 1000 GB (1 TB)","","","","","","","","True","True","","","","moderately interested","very interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"639","","True","","","","","","True","True","","","Guidelines / policies of publishers","","","True","","","","","True","","","","","","","","","","","Zenodo","PANGAEA","","","","90.0","","True","","True","True","True","True","True","True","","","","","","","True","","","","","","","","","","","581.39","Completed the survey","Anonymized","Anonymized","Earth and Environment","Physics","","","","","","","","","","","","","","","","","","Meteorology","","","","7 to 10 years","Postdoc","","Yes","Not familiar with FAIR","True","","True","","","MATLAB / Simulink","Python","Word","","","","","True","","True","","","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","Some of them","All","Some of them","","All","","","","","None","None","None","","None","","","","","Mostly measured","Mostly generated","No","","","","","","","","","","","","","","","","True","","","","","","","","","Spektroskopie","Massenspektrometrie","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","True","","","100 MB - 1000 MB (1 GB)","","","True","","True","","","","True","True","","","moderately interested","very interested","not interested","not interested","very interested","not interested","1980-01-01 00:00:00" +"640","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1621.58","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Geography","","","","","","","","","","","","","","More than 10 years","Research Associate","","Yes","Not familiar with FAIR","","True","","","","Anonymized","Python","Anonymized","","True","True","","True","True","","","","","","","","","","","","True","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","Some of them","Some of them","","","","","","All","","Some of them","Some of them","","","","","Mostly measured","Mostly reused","Yes","","","","","","","","","","","","","","","True","","True","","","","","Satellitenbilder","Luftbilder","","","","","Wasserverteilung in Geländemodellen","Sichtbarkeit/Abschattung in Geländemodellen","Temperaturverläufe Tag/Monat/Jahr","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","1 GB - 10 GB","","True","True","","True","","True","True","True","True","","","moderately interested","moderately interested","not interested","very interested","moderately interested","not interested","1980-01-01 00:00:00" +"641","True","True","","","True","","","True","","True","","","","","True","","","True","","True","","","","","","","","","","","Copernicus Open Access Hub","","","","","50.0","","True","","","True","True","True","True","","","True","True","True","True","","True","True","","","","","","","","","","446.03","Completed the survey","Anonymized","Anonymized","Earth and Environment","","Energieforschung","","","","","","","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","","True","True","","","Fortran","IDL","Python","","","","","True","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","True","","All","All","All","All","All","All","","All","","All","All","All","All","All","All","","None","","","Mostly reused","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","numerische Modelle","","","","","","","","","","","","","","","True","","True","","True","","","","","","True","","","True","True","","","> 1 TB","","","","True","","","True","True","True","True","","","not interested","moderately interested","moderately interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"642","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","65.0","","","","","","","","","","","","","","","","","","","","","","","","","","","142.54","Completed the survey","Anonymized","Anonymized","Earth and Environment","Psychology","","","","","","","","","","","","","","","","","","","","","","7 to 10 years","","","","Apply FAIR","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","1980-01-01 00:00:00" +"645","","True","","","True","","","","","True","","","","","","True","","","","","","","","","","","","","","","Institutional Repository","","","","","30.0","","True","","","True","True","","","","","","","","","True","True","","","","","","","","","","","944.92","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","More than 10 years","Postdoc","","","Familiar with FAIR","","True","","","","Python","Fortran","","","","","True","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","","Some of them","Some of them","","","All","","","","","None","None","","","None","","","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","","True","True","","","","","","","","Preprocessing Remote sensing data","","","RTM","","","","","","","","","","","","","","","","","","","True","","True","","","True","True","True","","","True","","","","","","True","True","True","True","True","","True","True","","","very interested","very interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"647","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","70.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","784.58","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","More than 10 years","Research Associate","","Yes","Apply FAIR","True","True","True","","","Jupyter","Command line (scripts)","Fortran","","True","","True","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","All","All","","All","","","","","","All","All","","All","","","","","Mostly simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Verwendung von Wettermodellen","Lagrangesche Transportmodelle","Machine Learning und Klimadaten","","","","","","","","","","","","","","","","","","True","True","","","","True","","","","True","","","> 1 TB","","","","","True","True","True","","True","True","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"650","","True","True","","True","True","","","True","","","","","","True","","","True","","","","","","","","","","","","","OSF","figshare","","","","50.0","","","","","","","","","","","","","","","","","","","","","","","","","","","782.05","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","","Klimatologie","","","","","","","","","","","","","More than 10 years","Postdoc","Postdoc","Yes","Apply FAIR","True","","True","True","","R","Command line (scripts)","Excel (Spreadsheets)","","True","True","True","True","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","None","Purely simulated","Mostly reused","Not sure","","","","","","","","","","","","","","","","","True","","","","Other","","","","","","","Klimasimulation","Statistische Modelle","Empirische Modelle","","","","","","","Statistische Analysen","","","","","","","","True","True","","","True","","True","True","True","True","","True","True","","","1 GB - 10 GB","","","True","True","True","True","True","True","True","True","","","moderately interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"651","True","","","","","","","","","","","Guidelines / policies of publishers","","","","True","","","","","","","","","","","","","","","","","","","","5.0","","","","","","","","","","","","","","","","","","","","","","","","","","","880.17","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","More than 10 years","Research Associate","","Yes","Not familiar with FAIR","True","True","","","","","","","","","","","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Mostly measured","Mostly reused","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","True","","","10 GB - 100 GB","","","","","","","","","","","","","","","","","","","1980-01-01 00:00:00" +"652","","True","","","","","","True","True","","","","","","True","","","True","","","","","","","","","","","","","PANGAEA","Institutional Repository","","","","30.0","","True","True","True","True","True","True","True","True","True","","","","","True","True","True","","","","","","","","","","944.13","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Geophysics","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","","True","True","","","Python","Anonymized","Command line (scripts)","","True","","","True","","","","","","","","True","","True","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","True","","","","All","All","Some of them","","All","All","","","","None","None","None","","None","None","","","","Purely measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","Analytical methods","","","","","","","","","","","","","","","","Geophysikalische Messungen","","","","","","","","True","","","","True","True","","","True","","","","True","","","100 GB - 1000 GB (1 TB)","","","","","","","","","","","","True","","","","","","","1980-01-01 00:00:00" +"653","True","True","True","","True","True","True","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","50.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","411.28","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Soil Science","","","","","","","","","","","","","","7 to 10 years","Postdoc","","Yes","Apply FAIR","","True","","","","Office Software (unspecified)","R","","True","","","","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","True","","","","","","","","","","","","","","","","","","","","","Equally measured and simulated","Equally generated and reused","No","","","","","","","","","","","","","","","","","True","","","","Other","","","","","","","Modeling","","","","","","","","","Sensors","","","","","","","","","","True","","True","","","True","","True","","True","True","","","1 GB - 10 GB","","","","","","","","","","","","True","","","","","","","1980-01-01 00:00:00" +"654","True","True","","","True","","","","True","","","","","","True","True","","True","","","","","","","","","","","","","ENA","SRA","PANGAEA","","","90.0","","True","True","","","True","","True","","","","","","","","","","","","","","","","","","","1556.37","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Environmental Science","","","","","","","","","","","","","","7 to 10 years","Postdoc","","Yes","Apply FAIR","True","True","","","","","","","","True","","","True","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","Some of them","Some of them","","","","","","","","None","None","","","","","","","","Mostly measured","Equally generated and reused","Yes","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","True","","","True","","True","","True","True","","","1 GB - 10 GB","","True","True","True","True","True","True","True","","","","","very interested","moderately interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"655","True","True","","","True","True","","","","True","","","","","True","","True","","","","","","","","","","","","","","Institutional Repository","","","","","15.0","","True","True","","","True","","","","","","","","","","True","","","","","","","","","","","681.85","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Geography","","","","","","","","","","","","","","4 to 6 years","Research Associate","","Yes","Familiar with FAIR","True","","","","","R","QGIS/GDAL","QGIS/GDAL","","","","True","True","","","True","","","","","","","","","","","True","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","","Some of them","Some of them","","","Some of them","","","","","None","None","","","None","","","","","Equally measured and simulated","Equally generated and reused","Not sure","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Geoinformationsverarbeitumg","Statistische Modellierungen ","","","","","","","","","","","","","","","","True","","True","True","True","","","True","True","","","","","","","10 GB - 100 GB","","","","","True","True","True","","","True","","","very interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"657","True","","True","","True","","","True","","True","","","","","True","","","True","","True","","","","","","","","","","","","","","","","10.0","","","","","","","","","True","True","","","","","True","","","","","","","","","","","","851.15","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","True","","True","","","Fortran","Python","C/C++","","True","","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","Some of them","","Some of them","","","","","","","All","","All","","","","","Purely measured","Mostly generated","Yes","","","","","","","","","","","","","","","True","True","","","","","","Wetterradar","Niederschlagsverteilung","","Spektralanalyse Dopplerspektrum","Polarimetrie","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","True","True","","","100 MB - 1000 MB (1 GB)","","True","","","","","","","","True","","","moderately interested","very interested","very interested","moderately interested","not interested","moderately interested","1980-01-01 00:00:00" +"659","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1057.65","Completed the survey","Anonymized","Anonymized","Earth and Environment","Chemistry","","","","","","","","","","","","","","","","","","","","","","No degree","Student","","No","Familiar with FAIR","","True","","","","Anonymized","Anonymized","","","","","","True","","","","","True","True","True","","","","","","True","","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","None","","","","","","","Purely measured","Purely generated","Yes","","","","","","","","","","","","","","","True","True","","True","","","","AFM","","","XRD","Cyclic voltammetry","Chronopotntiometry","","","","PLD","","","","","","","","","","","","","","","","True","","True","","","","","","","","","Plain text","","","","True","True","True","True","True","True","True","","True","","","very interested","very interested","very interested","not interested","very interested","very interested","1980-01-01 00:00:00" +"661","True","True","","","True","","","True","True","","","","","","True","True","","","","","","","","","","","","","","","Institutional Repository","Zenodo","B2SHARE","","","10.0","","True","True","True","True","True","","True","True","True","","","","","True","True","","","","","","","","","","","1097.7","Completed the survey","Anonymized","Anonymized","Earth and Environment","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","More than 10 years","Research Associate","","Yes","Familiar with FAIR","","True","","","","Database Management System","Python","OpenCV","","True","True","","","","","","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","","All","Some of them","Some of them","Some of them","","","","","Mostly measured","Mostly reused","Yes","","","","","","","","","","","","","","","True","True","","","","","","RGB-Kameras","PAM-Fluorometer","NMR-System","Sequencing","Feinwaagen","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","True","","","True","","","","1 GB - 10 GB","","","","","True","True","True","True","True","True","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"662","True","True","","","True","","","True","","True","","","","","","True","","True","","","","","","","","","","","","","Institutional Repository","","","","","90.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","1047.61","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","","True","","","","","cdo","Anonymized","","True","","","","","","","","True","","","True","True","True","","","","","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","True","","","","Some of them","Some of them","Some of them","","All","All","","","","Some of them","Some of them","Some of them","","All","Some of them","","","","Mostly simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","Reanalysis data","NWP model data","Climate model data","","","","script-based postprocessing ","manipulation of netCDF and grib data","","","","","","","","True","","True","True","True","True","True","","","","True","True","","True","True","","","> 1 TB","","True","","","","True","","True","","","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"663","True","True","","","True","True","","","True","","","","","","True","","","True","","True","","","","","","","","","","","Institutional Repository","","","","","50.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","583.84","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","True","True","","","","Anonymized","Anonymized","","","","","","True","","","","","True","","True","","True","","","","","","True","","","Yes","Yes","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","True","","True","True","","","","","","Some of them","","All","All","","","","","","Some of them","","Some of them","Some of them","","","","","Equally measured and simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","chemistry transport models","","","","","","regression analysis","","","","","","","","","","","","","True","True","True","","","","True","","","","True","","","> 1 TB","","True","","","","True","","True","True","True","","","moderately interested","very interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"666","","True","","","True","","","True","","True","","","","True","True","","","True","","True","","","","","","","","","","","","","","","","95.0","","True","","","True","True","True","True","True","","","","True","","True","True","True","True","","","","","","","","","496.08","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Environmental Science","","","","","","","","","","","","","","More than 10 years","Postdoc","","Yes","Apply FAIR","","","","True","","Python","QGIS/GDAL","PowerPoint","","True","","","True","True","","","","","","True","","","","","","","","True","","","Yes","Yes","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","","","Some of them","All","Some of them","Some of them","All","All","","","","None","None","None","None","None","None","","","","Purely measured","Purely reused","No","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","True","True","","","","","","","","","","","","","True","","","moderately interested","very interested","not interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"667","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","Legal / ethical concerns","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","499.74","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","More than 10 years","Postdoc","","No","Familiar with FAIR","","True","","","","MATLAB / Simulink","Command line (scripts)","Python","","True","True","True","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","Some of them","Some of them","","Some of them","","","","","","None","None","","None","","","","","","Equally measured and simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","True","","","","Other","","","","","","","Risikomodelle","Wettermodelle","","","","","","","","Radarmessungen","","","","","","","","","","True","","True","","","","True","","","True","True","","","10 GB - 100 GB","","True","","","True","True","","True","True","","","","very interested","very interested","not interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"675","","","","Other","","","","True","","True","","","","","True","","","","","","","","","","","","","","","","","","","","","100.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","1046.5","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Oceanography","","","","","","","","","","","","","","More than 10 years","Other","Other","Yes","Familiar with FAIR","","","True","","","","Database Management System","Anonymized","","True","","","","","","","","True","True","","","True","","","","","","","Digital system","","Yes","Yes","","","","True","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","All","All","","All","","","","","","Some of them","Some of them","","Some of them","","","","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","","True","","","","","Recordings","","","","HF radar","satellite spectroscopy","","","","","","","","","","","FerryBox","Under water nodes","","","","","","","","True","","","","","","","","","","","True","","","100 GB - 1000 GB (1 TB)","","","","","","","","","","","","True","not interested","not interested","not interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"681","","True","","","True","True","","","","True","","","True","","","","","","","","","","","","","","","","","","Institutional Repository","Institutional Repository","","","","100.0","","","True","","","","","","","","","","","","","","","","","","","","","","","","785.68","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Geophysics","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","","","True","","","Anonymized","Anonymized","","True","","","","","","","","","","","","","","","True","","","","True","","","Yes","Yes","True","","","","","","","","","","","","","","","","","","","","","","","","","","Others","True","True","True","","","True","","","","All","Some of them","All","","","All","","","","All","Some of them","All","","","All","","","","Mostly simulated","Mostly reused","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","True","","","","True","True","","","1 GB - 10 GB","","","","","","True","","True","","","Best practices","","very interested","not interested","not interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"687","True","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","60.0","","","","","True","","","","True","True","","True","","","","","","","","","","","","","","","3757.31","Completed the survey","Anonymized","Anonymized","Earth and Environment","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","1 to 3 years","PhD candidate","","No","Not familiar with FAIR","True","True","","","","Anonymized","ImageJ","OriginLab","True","","","","","","","","","True","","","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","Some of them","","Some of them","","","","","","","Some of them","","Some of them","","","","","","","Purely measured","Purely generated","Not sure","","","","","","","","","","","","","","","True","True","","","","","","Fluorescence Microscopy","","","Colorimetric methods (ELISA, MTT)","Atomic Absorption Spectrscopy","","","","","","","","","","","","","","","","","True","","","","True","","True","","","","","True","","","","","","1 GB - 10 GB","","","","True","True","True","","True","","","","","moderately interested","very interested","","not interested","very interested","not interested","1980-01-01 00:00:00" +"688","True","","","","True","True","","","True","","","","","True","True","","True","","","True","","","","","","","","","","","","","","","","30.0","","","","True","True","","","True","True","True","True","","True","True","","True","","","","","","","","","","","849.98","Completed the survey","Anonymized","Anonymized","Earth and Environment","Life Science","","Plant Breeding","","","","","","","","","","Agriculture","","","","","","","","","","7 to 10 years","Postdoc","","Yes","Apply FAIR","True","","","","","Excel (Spreadsheets)","R","ImageJ","","True","True","True","","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","All","All","Some of them","Some of them","","","","","None","None","None","None","None","","","","","Purely measured","Mostly generated","Yes","","","","","","","","","","","","","","","True","True","","","True","","","Image analysis of photographs","","","NIRS","TD-NMR","RNAseq","","","","","","","Manual measurements/observations in the field","Interviews with target consumers","","","","","","","","True","","","","True","","","","","","","True","","","","","","< 100 MB","","True","True","True","True","True","True","True","","True","","","very interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"689","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","416.13","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Environmental Science","","","","","","","","","","","","","","No degree","Student","","No","Familiar with FAIR","","True","","","","Excel (Spreadsheets)","Anonymized","R","","","","","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","None","None","None","","","","","","","Purely measured","Mostly generated","Yes","","","","","","","","","","","","","","","","True","","","","","","","","","ICP-MS/MS","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","I don't know","","","","","","","True","","","True","","","moderately interested","moderately interested","not interested","not interested","very interested","not interested","1980-01-01 00:00:00" +"690","","True","","","True","","","True","","True","","","True","","","","","","","","","","","","","","","","","","Institutional Repository","","","","","75.0","","True","True","True","True","True","","True","True","True","","","","","","True","True","True","","","","","","","","","472.18","Completed the survey","Anonymized","Anonymized","Earth and Environment","Chemistry","","","","","","Analytical Chemistry","","","","","","","","","","","","","","","","1 to 3 years","PhD candidate","","No","Familiar with FAIR","","True","","","","Excel (Spreadsheets)","OriginLab","Anonymized","True","","","","","","","","","True","","","True","","True","","","True","","","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","True","","","","All","All","All","","All","All","","","","None","None","None","","None","None","","","","Purely measured","Purely generated","Yes","","","","","","","","","","","","","","","","True","","","","","","","","","ICP-MS","Titration","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","100 MB - 1000 MB (1 GB)","","","","","","","True","True","","","","","very interested","moderately interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"691","","True","","","","","","True","True","","","","","","True","True","True","True","True","","","","","","","","","","","","Gitlab / GitHub","","","","","15.0","","","","","","True","True","True","","","","","True","","","","","","","","","","","","","","12489.4","Completed the survey","Anonymized","Anonymized","Earth and Environment","","Ecologie","","","","","","","","","","","","","","","","","","","","","1 to 3 years","PhD candidate","","Not sure","Familiar with FAIR","","True","","","","MATLAB / Simulink","Anonymized","Excel (Spreadsheets)","","True","","True","True","True","True","True","","","","","","","","","","","","True","Source code and scripts","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","Some of them","Some of them","","All","","","","","","None","None","","None","","","","","","","Mostly reused","Not sure","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","Szenario-Berechungen","","","","","","","","","","","","","","","True","","True","","True","","True","","","True","True","True","","True","True","","","> 1 TB","","","","","True","True","","","","True","","","not interested","moderately interested","moderately interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"692","True","","","","True","True","","","","True","","","","","","","True","True","","","Competition","","","","","","","","","","","","","","","5.0","","","","True","","","","","True","","","","","","","True","","","","","","","","","","","859.55","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","More than 10 years","Research Associate","","Yes","Not familiar with FAIR","True","True","","","","Python","IDL","Fortran","","","True","True","True","","","True","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","Some of them","","Some of them","","Some of them","","","","","None","","None","","None","","","","","Equally measured and simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","True","","","","Recordings","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","True","","","10 GB - 100 GB","","True","","True","True","True","True","","True","","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"693","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","415.44","Completed the survey","Anonymized","Anonymized","Earth and Environment","Engineering Science","","","","","","","","","","Industrial Engineering","","","","","","","","","","","","No degree","Student","","No","Not familiar with FAIR","True","","","","","Excel (Spreadsheets)","Python","ArcGIS","","","True","True","","","","","","True","True","True","","","","","","True","","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","None","","","","","","","","","Mostly simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","True","","","","","","I don't know","","","","","","True","","","","","","","moderately interested","very interested","moderately interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"695","","True","","","","","","True","","","","","","","","","True","","","","","","","","","","","","","","Institutional Repository","","","","","30.0","","","","","True","True","","","True","","","","","","True","","","","","","","","","","","","458.02","Completed the survey","Anonymized","Anonymized","Earth and Environment","Physics","","","","","","","","","","","","","","","","","","Meteorology","","","","1 to 3 years","PhD candidate","","Yes","Not familiar with FAIR","","True","","","","Python","","","True","","","","","","","","","","","","","","","","","True","","","Source code and scripts","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","None","None","None","None","","","","","Equally measured and simulated","Mostly reused","Not sure","","","","","","","","","","","","","","","","True","True","","","","","","","","Lidar","","","Reanalyse","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","True","","","10 GB - 100 GB","","","","","","","","","","","","True","moderately interested","moderately interested","not interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"698","True","True","","","True","True","","","","True","","","","","True","True","","True","True","","","","","","","","","","","","Gitlab / GitHub","","","","","80.0","","","","","","","","","True","","True","","","","","","","","","","","","","","","","557.3","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Water Research","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","","True","","","","Python","Command line (scripts)","Google Earth Engine","","True","True","","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","Mostly reused","Yes","","","","","","","","","","","","","","","True","","True","","","","Other","Satellitendaten","UAV Daten","","","","","Hydrologische Modelle","Klimamodelle","","","","","","","","Stationsdaten","Smartphone Daten","","","","","","","","True","","","","","","","True","","","True","True","","","1 GB - 10 GB","","","","","","True","","","","True","","","","very interested","moderately interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"699","True","True","","","True","","","","True","True","","","True","","","","","","","","","","","","","","","","","","Institutional Repository","NSSDC","","","","10.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","609.62","Completed the survey","Anonymized","Anonymized","Earth and Environment","Physics","","","","","","","","","","","","","","","","","","Meteorology","","","","7 to 10 years","Postdoc","","Yes","Apply FAIR","","True","","","","IDL","Linux","LaTeX","True","","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","All","All","","","","","","","","Mostly measured","Purely generated","Yes","","","","","","","","","","","","","","","True","","","","","","","Lidar","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","","100 MB - 1000 MB (1 GB)","","","","True","","True","","","True","","","","very interested","moderately interested","not interested","moderately interested","very interested","not interested","1980-01-01 00:00:00" +"700","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","4865.31","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Water Research","","","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","","","","True","","QGIS/GDAL","Python","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Mostly simulated","Equally generated and reused","","","","","","","","","","","","","","","","True","","True","","","","","Satellitendaten(Höhenmodelle, Landuse etc.)","","","","","","Automatisierte Planungsunterstützung für Abwassernetzwerke","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","True","True","Application-specific formats","","","","","","","","","","","","","","","","","","","","","1980-01-01 00:00:00" +"703","","True","","","","","","","True","True","","","","","","","True","","","","","","","","","","","","","","Institutional Repository","","","","","10.0","","True","","","True","True","True","True","True","","True","True","True","","","True","","","","","","","","","","","593.26","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","7 to 10 years","Research Associate","","Yes","Familiar with FAIR","True","True","","","","Python","","","","","","True","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","All","All","All","All","All","","","","","Purely measured","Purely reused","Yes","","","","","","","","","","","","","","","True","","","","","","Other","Tomographie","","","","","","","","","","","","","","","LIDAR","IR Interferometrie","","","","","","","","","","","","","","","","","","","True","","","100 GB - 1000 GB (1 TB)","","","","True","True","True","","True","","","","","very interested","very interested","not interested","moderately interested","very interested","not interested","1980-01-01 00:00:00" +"708","True","","","","","","","","","","","Guidelines / policies of publishers","","","","","","","True","","","","","","","","","","","","","","","","","25.0","","True","","True","True","True","True","True","","","True","","","","","","","","","","","","","","","","831.32","Completed the survey","Anonymized","Anonymized","Earth and Environment","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","More than 10 years","Research Associate","","Yes","Familiar with FAIR","","True","","","","R","Excel (Spreadsheets)","Database Management System","","True","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","","","","All","","","","","","None","None","None","None","","","","","","Mostly simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","True","","","","Other","","","","","","","numerische Modelle","weitere Statistische Modelle","","","","","","","","","","","","","","","","","True","","","True","","","","","True","","True","","","","100 MB - 1000 MB (1 GB)","","","","","","","","True","True","","","","moderately interested","moderately interested","moderately interested","not interested","very interested","not interested","1980-01-01 00:00:00" +"709","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1199.29","Completed the survey","Anonymized","Anonymized","Earth and Environment","Life Science","","","","","","","","","","","","","Biotechnology + Automation","","","","","","","","","1 to 3 years","PhD candidate","","Not sure","Familiar with FAIR","True","True","","","Externally (servers / repositories)","Anonymized","Excel (Spreadsheets)","Anonymized","","","","","","","True","True","","True","True","True","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","None","Some of them","Some of them","None","","","","","","Purely measured","Purely generated","Not sure","","","","","","","","","","","","","","","True","True","","","","","Other","Microscopy","Fotography","","Enzymatic Assays (determine enzyme activity or sugar concentration)","Gravimetry (cell dry weight determination)","chromatography ","","","","","","","","","","scattered light measurement (measure for biomass development)","pH and dissolved oxygen measurement via optodes","","","","","True","","True","","True","True","","","","True","True","True","","True","True","","","10 GB - 100 GB","","","","","","","True","","True","","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"710","True","","","In repository","","True","","","True","True","","","","","True","True","","True","","","","","","","","","","","","","","","","","","40.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","1041.29","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Geology","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","","True","","","","Anonymized","MATLAB / Simulink","R","","True","","","","","","","Relevant metadata is missing","True","True","True","True","True","","","","","","True","","","Yes","Yes","","True","","True","","","","","","","","","","","","","","","","","","","True","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","None","All","Some of them","All","","","","","","Equally measured and simulated","Purely reused","No","","","","","","","","","","","","","","","True","","True","","","","","remote sensing, air borne, satellite","","","","","","modelling","","","","","","","","","","","","","","","True","","True","True","True","","","","True","True","","True","","True","True","","","100 MB - 1000 MB (1 GB)","","","","True","True","True","","True","","","","","moderately interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"712","","True","","","","True","","","","True","","","","","True","","","","","True","","","","","","","","","","","Institutional Repository","","","","","25.0","","","","","","","","","","","True","","True","True","True","True","","","","","","","","","","","1642.48","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Oceanography","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","True","True","True","","","Fortran","MATLAB / Simulink","","","True","","True","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","All","","All","All","All","","","","","None","","None","None","None","","","","","Mostly simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","numersches Modell","statistisch-analytische Methoden","","","","","","","","","","","","","","","","True","","True","","","","","True","True","True","","True","True","","","10 GB - 100 GB","","True","True","True","","True","True","","","True","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"713","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","912.35","Completed the survey","Anonymized","Anonymized","Earth and Environment","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","More than 10 years","Research Associate","","Yes","Familiar with FAIR","","True","","","","R","ArcGIS","Database Management System","","","","","True","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","True","","All","All","All","Some of them","All","","","All","","None","All","None","None","None","","","Some of them","","Purely measured","Mostly reused","Yes","","","","","","","","","","","","","","","","","","","","","Cohort studies","","","","","","","","","","","","","","","","standardisierte Zählmethoden (Biodiversitätserhebungen)","passive Fallen (Biodiversitätserhebungen)","","","","","True","","","True","","","True","","","","","True","","True","","","","100 MB - 1000 MB (1 GB)","","","","True","True","True","True","","","True","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"714","","True","","","True","","","","True","True","","","","","True","","","True","","True","","","","","","","","","","","Zenodo","PANGAEA","WDCC","","","100.0","","True","","","","True","","True","","","","","","","","True","True","","","","","","","","","","1083.49","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","4 to 6 years","Research Associate","","Yes","Apply FAIR","","True","","","","Python","Anonymized","Command line (scripts)","","True","True","True","True","","","","","True","True","True","True","True","","","","","","","GitLab","","Yes","Yes","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","True","True","","True","True","","","","All","All","None","","Some of them","All","","","","Some of them","All","None","","All","All","","","","Mostly simulated","Purely reused","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Regionale Klimamodelle","Globale Erdsystem-Modelle (ESM)","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","10 GB - 100 GB","","True","","True","True","True","True","True","True","True","","","moderately interested","very interested","very interested","very interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"717","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","309.72","Completed the survey","Anonymized","Anonymized","Earth and Environment","Physics","","","","","","","","","","","","","","","","","","Astrophysics and Astronomy","","","","Less than 1 year","PhD candidate","","Not sure","Not familiar with FAIR","","","","","","Python","Anonymized","Jupyter","","","","","","","","True","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","All","","Some of them","Some of them","All","","","","","None","","None","None","None","","","","","Mostly simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Numeric models","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","True","","","I don't know","","True","","True","True","True","","","","","","","very interested","moderately interested","not interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"719","True","","True","","True","True","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","30.0","","","True","","True","True","True","True","True","True","","True","True","","","","","","","","","","","","","","582.35","Completed the survey","Anonymized","Anonymized","Earth and Environment","Chemistry","","","","","","Analytical Chemistry","","","","","","","","","","","","","","","","4 to 6 years","PhD candidate","","Yes","Apply FAIR","","True","True","","","Excel (Spreadsheets)","Word","OriginLab","True","","","","","","","","","True","True","True","","","True","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","All","All","Some of them","","","","","","Some of them","Some of them","Some of them","Some of them","","","","","","Mostly measured","Purely generated","Yes","","","","","","","","","","","","","","","","True","","","True","","","","","","ICP-MS/MS","MC ICP MS","","","","","","","","Multivariate cluster analysis","","","","","","","","","","","","","True","","","","","","","True","","","","","","< 100 MB","","True","","","","True","","","","","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"720","","True","","","True","True","","","True","","","","","","True","","","","","","","","","","","","","","","","PANGAEA","","","","","90.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","704.03","Completed the survey","Anonymized","Anonymized","Earth and Environment","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","More than 10 years","Research Associate","","Yes","Apply FAIR","","True","","","","Office Software (unspecified)","R","Anonymized","True","","","","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","True","","","","All","All","All","","All","All","","","","None","None","None","","None","None","","","","Purely measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","Other","","","","","","","","","","","","","","","","kombinierte Flugfallen (Insekten; jährlich)","Vogelerfassung (Punkt-Stopp-methode; alle 3 Jahre)","","","","","","","","True","","","","","","","","True","","True","","","","< 100 MB","","","","","True","","","True","True","","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"722","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","449.72","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","4 to 6 years","PhD candidate","","Yes","Not familiar with FAIR","True","True","","","","","","","","True","","True","True","True","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","True","","","All","All","All","","","","Some of them","","","","","","","","","","","","Purely simulated","Equally generated and reused","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","","","","True","True","","","True","","","10 GB - 100 GB","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","moderately interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"723","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Legal / ethical concerns","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","541.39","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","","Fernerkundung","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Not familiar with FAIR","","True","","","","Python","Anonymized","C/C++","True","","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","None","","Some of them","None","","","","","","","","Yes","","","","","","","","","","","","","","","True","","True","","","","","Fernerkundungssensoren","","","","","","Renderverfahren","","","","","","","","","","","","","","","True","","","","True","","","","","","","","True","True","","","","1 GB - 10 GB","","","","","","","","True","","","","","very interested","very interested","moderately interested","very interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"726","True","True","True","","True","","","","True","True","","","","","True","","","","","","","","","","","","","","","","Zenodo","","","","","40.0","","True","","True","True","True","True","True","True","","","","True","True","True","True","","","","","","","","","","","1337.05","Completed the survey","Anonymized","Anonymized","Earth and Environment","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","More than 10 years","Principal Investigator","Principal Investigator","Yes","Familiar with FAIR","True","True","","","","R","Database Management System","","","True","","","","","","","","","","","","","","","","","","","Source code and scripts","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","None","None","None","None","","","","","Mostly measured","","Yes","","","","","","","","","","","","","","","","","","","","","Other","","","","","","","","","","","","","","","","Ich gehe raus","Ich schaue","Ich schreibe auf (OK, es gibt eine Reihe von Standards und Methoden, für die der Platz nicht reicht)","","","","","","","True","","","","","","","True","True","","True","","","","100 MB - 1000 MB (1 GB)","","","","True","True","","","","","","","","very interested","moderately interested","moderately interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"727","True","True","","","True","True","","","True","","","","","","","","","","","","Lack of time / personnel","","","","","","","","","","WDCC","","","","","40.0","","","","","","True","","","","","","","","","","","","","","","","","","","","","1477.46","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Oceanography","","","","","","","","","","","","","","More than 10 years","Research Associate","Research Associate","Yes","Apply FAIR","True","True","True","","","Fortran","R","Command line (scripts)","","True","","","","True","","","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","","","","","","","","","","","","","","","","","","Mostly simulated","","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Modellrechnungen","","","","","","","","","","","","","","","True","True","","","True","","","","","","","","","","True","","","> 1 TB","","","","","","","","True","True","True","","","","","","","","very interested","1980-01-01 00:00:00" +"728","True","","","In repository","True","True","","","","True","","","","","True","","","","","","","","","","","","","","","","","","","","","25.0","","True","True","True","True","True","True","True","True","True","","","","","True","","True","","","","","","","","","","1207.8","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","","Erdbeobachtung","","","","","","","","","","","","","More than 10 years","Principal Investigator","Principal Investigator","No","Apply FAIR","","True","","","","","","","","True","","","True","","","","","True","","True","True","","","","","","True","","","","Yes","Yes","True","True","","True","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","True","","Some of them","All","","","All","All","","All","","","All","Some of them","","Some of them","Some of them","","Some of them","","Purely measured","Purely reused","Yes","","","","","","","","","","","","","","","True","","","","","","","Satellitendaten","aus Satellitendaten abgeleitete Daten","OpenStreetMap (Crowd-source)","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","","","","","True","","","","","","","True","","True","True","","","","","","very interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"729","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","455.78","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Geography","","","","","","","","","","","","","","7 to 10 years","Postdoc","","Yes","Not familiar with FAIR","True","True","","","","R","ArcGIS","QGIS/GDAL","","True","True","","","","True","True","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","All","Some of them","Some of them","Some of them","","","","","None","Some of them","None","None","None","","","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","True","","True","","","","","satellitengestützte Erdbeobachtung","Luftbilddaten","terrestrische Bilddaten","","","","maschinelle Lernverfahren","statistische Modelle","","","","","","","","","","","","","","True","","","","True","","","","","","True","","","True","","","","10 GB - 100 GB","","","True","","","","","True","True","","","","moderately interested","not interested","not interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"730","","True","","In repository","True","True","","","True","","","","","","","","","True","","","","","","","","","","","","","figshare","Institutional Repository","","","","70.0","","","","","","True","True","True","","","","","","True","True","True","","","","","","","","","","","2945.73","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Geography","","","","","","","","","","","","","","More than 10 years","Research Associate","","Yes","Not familiar with FAIR","","True","","","","QGIS/GDAL","Command line (scripts)","Anonymized","","True","","","True","","","","","","","","","","","","","","True","True","GitLab","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","Some of them","","","","","","All","Some of them","Some of them","None","","","","","Purely measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","Other","","","","","","","","","","","","","","","","sateliite aquisitions","airial photography","","","","","","","","","True","","True","","","","True","","","True","True","","","> 1 TB","","","","","True","True","","","","True","","","moderately interested","very interested","not interested","moderately interested","moderately interested","not interested","1980-01-01 00:00:00" +"733","","","","","","","","","","","","","","","","","","","","","","True","","","","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","838.26","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Geography","","","","","","","","","","","","","","Less than 1 year","PhD candidate","","Yes","Not familiar with FAIR","True","True","","","","QGIS/GDAL","Python","Office Software (unspecified)","True","","","","","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","None","None","None","None","","","","","","Purely measured","Equally generated and reused","No","","","","","","","","","","","","","","","True","","","","","","","satellite-based imaging","","","","","","","","","","","","","","","","","","","","","True","","","","True","","True","","","","True","True","","","True","","","","","","","","","","","True","True","True","","","moderately interested","very interested","not interested","","very interested","moderately interested","1980-01-01 00:00:00" +"737","","","","In repository","","True","","True","","True","","","","","True","","","","","","","","","","","","","","","","","","","","","20.0","","True","True","True","True","True","True","True","","","","","","","True","","","","","","","","","","","","1297.35","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Environmental Science","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","No","Familiar with FAIR","","True","","","","R","Google Earth Engine","Anonymized","","True","","","","","","","","","","","","","","","","","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","True","Others","All","All","All","All","All","","","","Some of them","None","None","None","None","None","","","None","None","Mostly measured","","Yes","","","","","","","","","","","","","","","True","","","","","","","SAR Satellitendaten","Multispektrale Satellitendaten","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","True","","","","True","True","","True","True","","","10 GB - 100 GB","","","","","","True","","","","","","","not interested","very interested","not interested","not interested","very interested","not interested","1980-01-01 00:00:00" +"738","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","414.4","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Geography","","","","","","","","","","","","","","More than 10 years","Research Associate","","No","Not familiar with FAIR","True","","","","","C/C++","R","IDL","","True","","True","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","None","","","","","","","","","Purely measured","Equally generated and reused","Yes","","","","","","","","","","","","","","","True","","","","","","","remote sensing","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","True","","","100 GB - 1000 GB (1 TB)","","True","","","","","True","True","","","","","moderately interested","very interested","very interested","moderately interested","very interested","not interested","1980-01-01 00:00:00" +"742","True","","","","","True","True","","True","","","","","","","","","True","","","","","","","","","","","","","","","","","","10.0","","","","True","True","","","","True","","","True","","True","","","","","","","","","","","","","539.21","Completed the survey","Anonymized","Anonymized","Earth and Environment","Physics","","","","","","","","","","","","","","","","","","","Atmosphere","","","7 to 10 years","Postdoc","","No","Familiar with FAIR","True","True","True","","","R","C/C++","OpenCV","","True","","","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","All","","All","All","","","","","","Purely measured","Purely generated","Yes","","","","","","","","","","","","","","","True","","","","","","","Instrument","Image Processing","","","","","","","","","","","","","","","","","","","","True","","True","","True","","True","","","","True","","","True","","","","> 1 TB","","","","","","","","","True","True","","","moderately interested","not interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"744","True","True","True","","True","True","","","","True","","","True","","","","","","","","","","","","","","","","","","PANGAEA","Zenodo","Other","","","95.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","568.6","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Environmental Science","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","","True","True","","","Anonymized","Anonymized","Python","True","","","","","","","","","True","True","True","","","","","","","True","True","","","Yes","Yes","","","","True","","","","","","","","","","","","","","","","","","True","","","","","","True","True","True","True","True","True","","","","All","All","All","All","All","All","","","","None","Some of them","Some of them","All","All","Some of them","","","","Mostly simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Numerical models","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","True","True","","","> 1 TB","","","","","","","","True","True","","","","not interested","moderately interested","not interested","not interested","not interested","moderately interested","1980-01-01 00:00:00" +"745","True","","","","True","True","","","True","","","","","","True","","","","","True","","","","","","","","","","","","","","","","85.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","473.18","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","","Planetenforschung","","","","","","","","","","","","","More than 10 years","Postdoc","","Yes","Familiar with FAIR","True","","","","","Anonymized","Database Management System","","","True","","True","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","All","","","","All","","","","","None","","","","None","","","","","Equally measured and simulated","Purely reused","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","","True","","Structured text","","< 100 MB","","","","True","True","","True","True","","","","","very interested","very interested","not interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"747","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","4207.46","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","","Erdbeobachtung","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","","True","","","","Anonymized","","","","","True","","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","True","","All","All","","Some of them","","","","Some of them","","","Some of them","","None","","","","None","","Mostly measured","Purely reused","Yes","","","","","","","","","","","","","","","True","","","","True","","","Statistische Verfahren","","","","","","","","","","","","Statistische Verfahren","","","","","","","","","True","","","","True","True","","","","","","","","","","","","I don't know","","True","","","True","True","True","","","","","","moderately interested","moderately interested","","very interested","","","1980-01-01 00:00:00" +"748","","","","Other","True","True","","","","True","","","","","True","True","","","","","","","","","","","","","","","","","","","","10.0","","","","","","","True","True","True","True","","","","","","","","","","","","","","","","","776.59","Completed the survey","Anonymized","Anonymized","Earth and Environment","Physics","","","","","","","","","","","","","","","","","","Meteorology","","","","7 to 10 years","Research Associate","","Yes","Not familiar with FAIR","","True","","","","Python","Anonymized","Git","","True","","","","","","","","","","","","","","","","","","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","Some of them","Some of them","","","","","","","","","","","","","","","","Equally measured and simulated","Mostly generated","Yes","","","","","","","","","","","","","","","True","","True","","","","","Satellite images processing","","","","","","Heliosat Method for solar irradiance forecast","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","True","","","10 GB - 100 GB","","True","","True","True","True","","True","True","","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"749","True","","","","True","","","","","True","","","","","True","","","","","True","","","","","","","","","","","","","","","","5.0","","","","","True","","True","True","True","True","","","","","","","","","","","","","","","","","937.03","Completed the survey","Anonymized","Anonymized","Earth and Environment","Physics","","","","","","","","","","","","","","","","","","Meteorology","","","","4 to 6 years","Research Associate","","No","","True","True","","","","Python","MATLAB / Simulink","C/C++","","True","","","True","","","","","True","True","True","True","","","","","True","True","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","All","None","None","None","All","","","","","Equally measured and simulated","Purely generated","Yes","","","","","","","","","","","","","","","True","True","True","","","","","IR Tomographie","","","UV/vis/IR Spektroskopie","","","Monte-Carlo Verfahren","Strahlungstransportmodelle","","","","","","","","","","","","","","","","True","True","True","True","True","","","","True","True","","True","True","","","100 GB - 1000 GB (1 TB)","","","","","","","","","","True","","","not interested","very interested","very interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"751","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","697.43","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","1 to 3 years","Research Associate","","Yes","Not familiar with FAIR","True","True","","","","Jupyter","Anonymized","PowerPoint","","True","","True","","True","","","","","","True","True","True","","","","","","True","","","Yes","Yes","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","True","","True","True","","","","","All","All","","Some of them","Some of them","","","","","None","None","","None","None","","","","","","Purely reused","Yes","","","","","","","","","","","","","","","True","","True","","","","","Remote sensing","","","","","","Chemical transport modellling","","","","","","","","","","","","","","","","","","","True","","","","","","","","","True","True","","","1 GB - 10 GB","","True","True","True","","","","True","True","","","","very interested","","","","very interested","very interested","1980-01-01 00:00:00" +"752","True","True","True","","True","True","","","True","","","","","","","","","","","","Technical barriers","","","","","","","","","","Zenodo","MetaboLights","","","","25.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","805.55","Completed the survey","Anonymized","Anonymized","Earth and Environment","Chemistry","","","","","","Cheminformatics","","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","","True","True","","","R","Anonymized","Anonymized","True","","","","","","","","","True","True","True","True","True","","","","True","True","True","","","Yes","Yes","True","True","","","","","","","True","","","","","","","","","","","","","","","","","","","True","True","True","True","","True","","","","Some of them","Some of them","Some of them","All","","All","","","","None","Some of them","None","All","","All","","","","Purely measured","","Yes","","","","","","","","","","","","","","","","True","","","","","","","","","High Resolution Mass Spectrometry","Low Resolution Mass Spectrometry","","","","","","","","","","","","","","","","","True","","","","","","True","","","True","True","True","","True","","","","100 GB - 1000 GB (1 TB)","","","","","","","","","","","","True","moderately interested","moderately interested","moderately interested","","very interested","not interested","1980-01-01 00:00:00" +"753","","True","","","True","","","True","True","","","","","","True","","","","","","","","","","","","","","","","Copernicus Open Access Hub","","","","","50.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","684.92","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","Atmospheric Science","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Not familiar with FAIR","","True","","","","emacs","Jupyter","Anonymized","True","","","","","","","","","","","True","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","Some of them","","","All","","","","","","Some of them","","","All","","","","","","Purely measured","Mostly generated","Yes","","","","","","","","","","","","","","","","True","","","","","","","","","Optimal estimation","Non-linear fitting","Radiative Transfer Models","","","","","","","","","","","","","","","","True","","","True","","","True","","","","True","","","True","True","","","I don't know","","","","","True","","True","","","True","","","moderately interested","moderately interested","not interested","moderately interested","very interested","not interested","1980-01-01 00:00:00" +"759","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","391.45","Completed the survey","Anonymized","Anonymized","Earth and Environment","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","1 to 3 years","PhD candidate","","No","Not familiar with FAIR","","True","","","","","","","","True","True","","","","","","","True","True","True","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","None","","Some of them","Some of them","","","","","","Purely measured","Purely generated","Yes","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","True","","True","","","","1 GB - 10 GB","","","True","","True","","True","","True","","","","moderately interested","very interested","moderately interested","not interested","moderately interested","","1980-01-01 00:00:00" +"760","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","839.8","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Chemical Biology","","","","","","","","Biology","","","","","","","","","","","Principal Investigator","Principal Investigator","","Familiar with FAIR","True","True","","","","Excel (Spreadsheets)","GraphPad","","True","","","","","","","","","","","","","","","","","True","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","None","None","None","None","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","True","True","","","","","","Fluoreszenz-Mikroskopie","Western Blot","","optische Messungen: Absorption, Fluoreszenz, Lumineszenz","Durchflusszytometrie","PCR-Methoden","","","","","","","","","","","","","","","","","True","","","True","","","True","","","","True","","","","","","< 100 MB","","","","True","","True","","","True","True","","","very interested","moderately interested","moderately interested","not interested","not interested","moderately interested","1980-01-01 00:00:00" +"763","","True","","","True","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","100.0","","","","","","","","","","","True","","True","","","","","","","","","","","","","","340.76","Completed the survey","Anonymized","Anonymized","Health","Physics","","","","","","","","","","","","","","","","","","","Medical physics","","","","Student","","","Not familiar with FAIR","","True","","","","Python","Anonymized","FLUKA","True","","","","","","","","","","","","","","","","","","True","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","None","None","","","","","","Equally measured and simulated","Purely generated","","","","","","","","","","","","","","","","True","","True","","","","","CCD camera","","","","","","TOPAS ","Fluka","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","","","","1 GB - 10 GB","","","","True","","True","True","","","","","","very interested","very interested","","","","very interested","1980-01-01 00:00:00" +"765","","True","","","","","","True","","","","","True","","","","","","","","","","","","","","","","","","","","","","","50.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","416.9","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Health Science","","","","","","","","","","","Research Associate","","","Not familiar with FAIR","True","True","","","","","","","True","","","","","","","","","True","True","True","True","","","","","True","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","Some of them","Some of them","Some of them","","","","","","None","None","","None","","","","","","Purely measured","","","","","","","","","","","","","","","","","True","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","True","","","","","","I don't know","","","","","","","","","True","","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"768","True","","","","","","","True","","","","","","","","True","","True","True","","","","","","","","","","","","","","","","","75.0","","","","True","True","","","","True","True","True","","","","","","","","","","","","","","","","503.08","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Health Science","","","","","","","","","","","Research Associate","","","Not familiar with FAIR","","True","","","","GraphPad","Excel (Spreadsheets)","AiiDA","","True","True","","","","True","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","Some of them","","Some of them","Some of them","","","","","","None","","None","None","","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","True","True","","True","","","","Fluoreszenzmikroskopie","PET","","Massenspektrometrie","Zellstudien","","","","","Radiomarkierung","","","","","","","","","","","","","","","","True","","","True","","","","True","","","","","","1 GB - 10 GB","","","","","","","","","","","","True","very interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"769","True","","","","","True","","","True","","","","","","","True","","True","True","","","","","","","","","","","","","","","","","10.0","","","","","True","","","","True","True","True","True","True","True","","","","","","","","","","","","","6888.24","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Chemical Biology","","","","","","","","Biology","","","","","","","","","","","Research Associate","","","Not familiar with FAIR","","True","","","","Anonymized","Excel (Spreadsheets)","Anonymized","","","True","","","","","","","True","","True","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","Some of them","Some of them","Some of them","","","","","","None","Some of them","None","None","","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","True","True","","","","","","MRI","Optical Imaging ","Microscopy","Photometrie ","","","","","","","","","","","","","","","","","","","","","","True","","","True","","True","","True","","","","","","100 MB - 1000 MB (1 GB)","","","","","","True","","","True","True","","","moderately interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"771","True","","","","","","","True","","","","","","","True","","","True","","True","","","","","","","","","","","","","","","","40.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","444.05","Completed the survey","Anonymized","Anonymized","Health","Chemistry","","","","","","","","","","","","","","","","","","","","","","","PhD candidate","","","Not familiar with FAIR","","True","","","","","","","","True","","True","True","","","","","","","True","","","","","","True","","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","None","","","","","","","","","None","","","","","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","True","","","","True","True","","","","","1 GB - 10 GB","","","","","","True","","","","","","","very interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"772","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","454.61","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Health Science","","","","","","","","","","","Research Associate","","","Not familiar with FAIR","","True","","","","R","Python","Anonymized","","True","","","True","True","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","Some of them","","Some of them","","","","","","","Some of them","","Some of them","","","","","","","Purely measured","Mostly generated","","","","","","","","","","","","","","","","True","","","","True","","","pQCT","DEXA","Ultraschall","","","","","","","","","","Leitfrageninterview","Fragebögen","","","","","","","","","","","","","","True","True","","","","","True","True","","","","< 100 MB","","","True","True","True","True","","True","","","","","very interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"773","True","","","","True","True","","","","True","","","","","True","","","True","","True","","","","","","","","","","","","","","","","90.0","","","","True","True","True","True","True","True","True","True","True","True","True","","","","","","","","","","","","","1187.47","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Cardiology","","","","","","","Principal Investigator","Principal Investigator","","Familiar with FAIR","","True","","","","Anonymized","Anonymized","Python","","True","","True","","True","","","","True","True","True","True","True","True","","","","True","","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","True","True","","All","Some of them","Some of them","Some of them","","","Some of them","Some of them","","All","Some of them","Some of them","Some of them","","","Some of them","Some of them","","Purely measured","Purely generated","","","","","","","","","","","","","","","","True","","","","","","Other","MRT","Ultraschall","PET","","","","","","","","","","","","","EKG","Blutdruck","Mikroneurographie","","","","","","","","","","","True","","","","","","True","","","","10 GB - 100 GB","","","","True","True","True","True","","","","","","moderately interested","very interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"775","True","","","","True","","","","True","True","","","","","True","True","","True","","","","","","","","","","","","","","","","","","20.0","","True","","True","True","True","True","","True","True","True","True","True","","","","","","","","","","","","","","906.4","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Biochemistry","","","","","","","","Biology","","","","","","","","","","","Principal Investigator","Principal Investigator","","Not familiar with FAIR","","True","True","","","Anonymized","Anonymized","ImageJ","","True","","","True","","","","","True","True","True","True","True","","","","True","True","True","","","Yes","Yes","","","","True","","","","","","","","","","","","","","","","","","","","","True","","","True","True","True","True","","","","True","","Some of them","Some of them","Some of them","All","","","","Some of them","","Some of them","All","Some of them","All","","","","Some of them","","Mostly measured","Mostly reused","","","","","","","","","","","","","","","","True","True","True","","","","","Röntgendiffraktion","cryo-EM","Lichtmikroskopie","Massenspktrometrie","Plasmonresonanzspektroskopie","UV-vis Spektroskopie","AlphaFold","Phoenix","Rosetta","","","","","","","","","","","","","True","True","True","True","True","","","True","","True","True","True","","True","","","","10 GB - 100 GB","","","","True","","","","","","True","","","moderately interested","very interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"779","True","","","","","","","","True","","","Guidelines / policies of publishers","","","True","","","","True","","Insufficiently trained","","","","","","","","","","","","","","","50.0","","","","","","","","","","","","","","","","True","","","","","","","","","","","1281.56","Completed the survey","Anonymized","Anonymized","Health","Psychology","","","","","","","","","","","","","","","","","","","","","","","Research Associate","","","Familiar with FAIR","","True","","","","Anonymized","SPSS","Anonymized","","True","","True","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","None","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","Befragungen (Online-Umfragen, Fragebogenstudien, Interviews)","Verhaltensexperimente","Beobachtungen","","","","","","","","","","","","","","","True","","","True","","True","","","","< 100 MB","","True","True","True","True","True","","True","","True","","","very interested","moderately interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"780","","True","","","True","True","","","","True","","","","","","","","","True","","","","","","","","","","","","Zenodo","Gitlab / GitHub","","","","60.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","569.68","Completed the survey","Anonymized","Anonymized","Health","Psychology","","","","","","","","","","","","","","","","","","","","","","","PhD candidate","","","Familiar with FAIR","","True","True","","","R","MATLAB / Simulink","Anonymized","","","","True","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","True","","","","All","","All","All","All","All","","","","Some of them","","Some of them","Some of them","Some of them","Some of them","","","","Mostly simulated","Purely reused","","","","","","","","","","","","","","","","True","","","","","","","MRI","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","True","","","True","True","","True","","","","1 GB - 10 GB","","","","True","","True","","True","","","","","very interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"782","","True","","","True","True","","","True","","","","","","","","","True","","","","","","","","","","","","","OSF","Zenodo","figshare","Institutional Repository","GIN","100.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","397.01","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Health Science","","","","","","","","","","","PhD candidate","","","Apply FAIR","True","True","True","","","Git","Anonymized","Python","","","","","True","","","","","","","True","True","","","","","","True","True","GitLab","","Yes","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","BIDS","True","True","True","True","True","True","","","","All","All","All","All","All","All","","","","None","All","All","All","Some of them","None","","","","Mostly measured","Equally generated and reused","","","","","","","","","","","","","","","","True","","","","True","","","fMRI","MEG","eyetracking","","","","","","","","","","Statistical analyses","","","","","","","","","True","True","True","","True","","True","True","","True","True","","","True","True","","","100 GB - 1000 GB (1 TB)","","","","","","","True","","","","","","","very interested","","","","","1980-01-01 00:00:00" +"783","","True","","","","True","","","True","True","","","","","True","","","","","True","Lack of time / personnel","","","","","","","","","","Zenodo","iReceptor","Gitlab / GitHub","","","90.0","","True","True","","","True","","True","True","True","","True","True","True","","","True","True","","","","","","","","","1544.52","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","Immunology","","","","","","","Biology","","","","","","","","","","","Principal Investigator","","","Apply FAIR","","True","True","","","Database Management System","Python","","","True","","","True","","","","","","True","True","","True","","","","","","True","","","Yes","Yes","","","","","","","True","True","","True","","","","","","","","","","","","","","True","","","MIFlowCyt","True","True","True","True","","True","","True","","All","All","All","All","","All","","Some of them","","None","Some of them","All","All","","All","","Some of them","","Purely measured","Mostly generated","","","","","","","","","","","","","","","","","True","","","","","","","","","DNA sequencing","cytometry","","","","","","","","","","","","","","","","","True","","True","True","True","True","True","True","","","True","True","","True","True","","","10 GB - 100 GB","","","","","","","","","True","","","","moderately interested","moderately interested","not interested","very interested","not interested","moderately interested","1980-01-01 00:00:00" +"784","True","True","","","","True","","","True","True","","","","","True","","","","","True","Lack of time / personnel","","","","","","","","","","Zenodo","iReceptor","Gitlab / GitHub","","","90.0","","True","True","","","True","","True","True","True","","True","True","","","","True","True","","","","","","","","","419.83","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","Immunology","","","","","","","Biology","","","","","","","","","","","Principal Investigator","","","Apply FAIR","","True","True","","","Database Management System","Python","","","True","","","","","","","","","True","True","","True","","","","","True","True","","","Yes","Yes","","","","","","","True","True","","True","","","","","","","","","","","","","","True","","","MIFlowCyt","True","True","True","True","","True","","True","","All","All","All","All","","All","","All","","None","Some of them","All","All","","All","","Some of them","","Purely measured","Mostly generated","","","","","","","","","","","","","","","","","True","","","","","","","","","DNA sequencing ","Cytometry","","","","","","","","","","","","","","","","","True","","True","True","True","True","True","","","","True","True","","True","True","","","10 GB - 100 GB","","","","","","","","","True","","","","moderately interested","moderately interested","not interested","very interested","not interested","moderately interested","1980-01-01 00:00:00" +"785","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1266.4","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Medical Informatics","","","","","","","Technical Staff","Technical Staff","","Not familiar with FAIR","","True","","","","SAS","Python","Anonymized","","","","","","","","True","","True","True","True","","","","","","","","True","","","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","All","","All","","All","","","","","None","","None","","None","","","Purely measured","Purely reused","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","Befragung im Interview, selbstauszufüllende Fragebögen","Messungen am TeilnehmerIn, Messstationen","Beauftragen von Drfittinstituten","","","","","","","True","","","True","True","","True","","True","True","","True","","","","","","I don't know","","","","","","","","","True","","","","moderately interested","moderately interested","not interested","moderately interested","not interested","not interested","1980-01-01 00:00:00" +"789","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","50.0","","","","","","","","","","","","","","True","","","","","","","","","","","","","297.26","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Health Science","","","","","","","","","","","PhD candidate","","","Not familiar with FAIR","","True","","","","R","","","","","","True","True","","","","","True","True","True","","","","","","","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","All","","","","","","Equally measured and simulated","Equally generated and reused","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","True","","True","True","","","","","","1 GB - 10 GB","","","True","","True","True","True","","","True","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"790","","True","","","True","True","","","True","","","","","","True","","","True","","","","","","","","","","","","","","","","","","100.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","593.72","Completed the survey","Anonymized","Anonymized","Health","Psychology","","","","","","","","","","","","","","","","","","","","","","","PhD candidate","","","Apply FAIR","","True","","","","Python","Anonymized","Anonymized","True","","","","","","","","","True","True","True","True","","","","","True","","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","","","All","All","All","All","All","All","","","","Some of them","Some of them","Some of them","Some of them","Some of them","Some of them","","","","Purely measured","Equally generated and reused","","","","","","","","","","","","","","","","True","","","","True","","","MRI","","","","","","","","","","","","Questionnaires","Tests","","","","","","","","","True","True","","","","","True","","","True","True","","True","","","","100 GB - 1000 GB (1 TB)","","True","","","","","True","True","","","","","moderately interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"798","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","356.12","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Psychiatry","","","","","","","PhD candidate","","","Familiar with FAIR","","","True","","","Python","Anonymized","Anonymized","","","","","","","","","Relevant metadata is missing","","","","","","","","","","","True","Source code and scripts","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","All","All","","","","","","","Some of them","All","All","","","","","Purely measured","Purely reused","","","","","","","","","","","","","","","","True","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","True","","","","1 GB - 10 GB","","","","","","","","True","","","","","moderately interested","very interested","very interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"807","","True","True","","","True","","","True","True","","","","","","True","","","True","","","","","","","","","","","","ENA","SRA","Zenodo","AIRR Data Commons (ADC)","","35.0","","True","","True","","True","","True","True","","","","True","True","","","","","","","","","","","","","607.27","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","Immunology","","","","","","","Biology","","","","","","","","","","","PhD candidate","","","Apply FAIR","True","True","True","","","R","Python","Database Management System","","True","","","True","","","","","","True","","","True","","","","True","","True","","","Yes","Yes","","","","","","True","True","True","","True","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","All","All","All","","","","","","None","None","All","All","","","","","","Mostly measured","Mostly reused","","","","","","","","","","","","","","","","","True","","","","","","","","","High-throughput sequencing","","","","","","","","","","","","","","","","","","True","","","True","","","True","","","","True","","","True","True","","","1 GB - 10 GB","","","True","","","","","True","True","","","","very interested","moderately interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"808","","True","","","","","","","","","","Guidelines / policies of publishers","","","True","True","","","True","","","","","","","","","","","","Zenodo","","","","","5.0","","","","True","True","True","True","True","","True","True","True","","","","True","","","","","","","","","","","845.56","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Neurology","","","","","","","Principal Investigator","Principal Investigator","","Not familiar with FAIR","True","True","","","","Anonymized","MATLAB / Simulink","SPSS","","True","True","","","True","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","","","","","","","","","","None","None","None","","None","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","True","","","","True","","","MR-Tomographie","PET","","","","","","","","","","","Fragebögen, Scores","","","","","","","","","","True","","True","","","True","True","True","","True","True","","","","","","1 GB - 10 GB","","","True","","","","True","True","","True","","","moderately interested","moderately interested","","","moderately interested","moderately interested","1980-01-01 00:00:00" +"817","True","","","","True","","","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","","90.0","","","","","","","","","","","","","","","","","","","","","","","","","","","436.35","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Microbiology","","","","","","","","Biology","","","","","","","","","","","PhD candidate","","","Familiar with FAIR","","True","","","","Office Software (unspecified)","GraphPad","Anonymized","","True","","","True","","","","","True","True","True","","","","","","True","","True","","","Yes","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","True","","","","True","True","","True","","","","","","True","","","","True","True","","","","","","moderately interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"825","True","","","","","True","True","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","25.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","554.35","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Infectious Disease Medicine","","","","","","","Principal Investigator","","","Not familiar with FAIR","","True","","","","Word","GraphPad","","","","","","True","","","","","True","","","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","None","","","","","","","","","Purely measured","Equally generated and reused","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","","","","","","True","","True","","","","1 GB - 10 GB","","","","True","","True","","True","","","","","very interested","moderately interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"830","","True","","","True","True","","True","","","","","","","","","","","","","","","","","","","","","","","Other","","","","","50.0","","","","","","","","","","","","","True","","","","","","","","","","","","","","434.72","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","","PhD candidate","","","Not familiar with FAIR","","True","True","","","","","","","True","","","","","","","","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","All","","","","","","Purely measured","Mostly generated","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","True","","","","True","True","","True","True","","","1 GB - 10 GB","","","","True","True","","True","True","True","True","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"831","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","2545.06","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Infectious Disease Medicine","","","","","","","","","","Familiar with FAIR","","True","","","","Anonymized","Anonymized","Office Software (unspecified)","","True","","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","None","","None","None","","","","","Purely measured","Mostly generated","","","","","","","","","","","","","","","","","","","","True","","Other","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","True","","True","True","","True","","","","I don't know","","True","True","True","True","True","True","True","True","True","","","moderately interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"832","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","215.13","Completed the survey","Anonymized","Anonymized","Health","Mathematics","","","","","","","","","","","","","","","","","","","","","","","Research Associate","","","Familiar with FAIR","True","","","","","R","","","","","","","","","","True","","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Purely measured","Mostly reused","","","","","","","","","","","","","","","","","True","","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","100 MB - 1000 MB (1 GB)","","","","True","","True","","True","True","True","","","moderately interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"833","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","70.0","","","","","","","","","","","","","","","","","","","","","","","","","","","387.29","Completed the survey","Anonymized","Anonymized","Health","","Epidemiology","","","","","","","","","","","","","","","","","","","","","","Research Associate","","","Familiar with FAIR","","","","","","Anonymized","R","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Mostly measured","Mostly generated","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","digital long-term surveys","","","","","","","","","","","True","","True","True","","","True","","","True","","True","","","","I don't know","","","","","","","","","","","","","","","","","","","1980-01-01 00:00:00" +"834","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","832.12","Completed the survey","Anonymized","Anonymized","Health","","Epidemiologie","","","","","","","","","","","","","","","","","","","","","","Principal Investigator","","","Familiar with FAIR","","True","","","","R","QGIS/GDAL","Office Software (unspecified)","","True","True","True","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","","","Some of them","Some of them","","","","Some of them","","","","None","None","","","","None","","","","Mostly measured","Purely reused","","","","","","","","","","","","","","","","","","","","True","","Other","","","","","","","","","","","","","Interview","Selbstausfüller","Probandenuntersuchungen","Landnutzungsmodelle ","","","","","","True","","","","True","","True","","True","","","True","","True","","","","10 GB - 100 GB","","True","","","","","True","True","True","True","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"835","True","True","","","True","True","","","True","","","","","","True","True","","","","True","","","","","","","","","","","","","","","","20.0","","True","","True","True","","","","True","","True","True","True","True","","","","","","","","","","","","","673.64","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Human Biology","","","","","","","","Biology","","","","","","","","","","","Principal Investigator","","","Apply FAIR","","True","","","","FlowJo","R","Anonymized","","True","True","True","","True","","","","True","True","True","True","True","","","","True","True","","","","Yes","Yes","","","","","","","","","","True","","","","","","","","","","","","","","","","","","True","","True","True","True","True","","","","Some of them","","Some of them","Some of them","Some of them","Some of them","","","","","","","","","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","True","True","","","","","","microscopy","","","sequence data","adaptative immune receptor repertoire data","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","","","","","","< 100 MB","","","True","","True","","True","True","","","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"840","True","","","","True","","","","True","","","","","","","","","","","True","","","","","","","","","","","","","","","","50.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","1011.75","Completed the survey","Anonymized","Anonymized","Health","Chemistry","","","","","","","","","","","","","","","","","","","","","","","Postdoc","","","Not familiar with FAIR","","True","","","","Anonymized","Anonymized","Anonymized","","","","True","True","","","","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","","","","","","","","","","Equally measured and simulated","Equally generated and reused","","","","","","","","","","","","","","","","","True","","True","","","","","","","HPLC","NMR","","","","","Extraction","","","","","","","","","","","","True","","","True","True","","","","","","","True","","True","","","","I don't know","","","","True","","True","True","True","True","","","","very interested","very interested","very interested","very interested","not interested","very interested","1980-01-01 00:00:00" +"841","True","","","","True","","","True","","True","","","","","True","True","","","","","","","","","","","","","","","","","","","","30.0","","","","True","True","True","","","","","","","","","","","","","","","","","","","","","1376.22","Completed the survey","Anonymized","Anonymized","Health","","","","","","","","","","","","","","","","","","","","","","","","Postdoc","","","Apply FAIR","","True","","","","R","QGIS/GDAL","Database Management System","","True","","True","","","","","Relevant metadata is missing","","","","","","","","","","","True","Digital text","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","True","","","","All","All","","","All","All","","","","None","None","","","None","None","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Land use regression model","Other regression-based hybrid model","","","","","","","","","","","","","","","","","","True","","","","","","","","","","True","Other","","1 GB - 10 GB","","","","","","","","","True","True","","","very interested","moderately interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"845","True","True","","","True","True","True","","","","","","True","","","","","","","","","","","","","","","","","","GEO","","","","","25.0","","","","True","True","True","","","True","True","True","True","True","True","","","","","","","","","","","","","1154.16","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Health Science","","","","","","","","","","","Research Associate","Research Associate","","Not familiar with FAIR","","True","","","","R","Excel (Spreadsheets)","Word","","","","","","True","","","","True","","True","True","","","","","True","","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","","","","","","None","None","Some of them","Some of them","Some of them","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","","True","","","","","","","","","Molekularbiologische Analysen","Sequenzierung","Bioinformatik","","","","","","","","","","","","","","","","True","","","True","True","True","True","True","True","","True","True","","True","","","","100 GB - 1000 GB (1 TB)","","","","","","","","True","","","","","moderately interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"847","True","True","","","True","True","","","True","","","","","","","","","True","True","True","","","","","","","","","","","GEO","ArrayExpress","","","","70.0","","True","True","True","True","True","","True","True","True","True","True","True","True","True","True","","","","","","","","","","","632.0","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Computational Biology","","","","","","","","Biology","","","","","","","","","","","Postdoc","","","Familiar with FAIR","","True","True","","","R","Command line (scripts)","Office Software (unspecified)","","True","","","True","","","","","","","","","","","","","","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","True","","","All","All","All","All","All","","All","","","Some of them","Some of them","Some of them","Some of them","Some of them","","None","","","Mostly measured","Equally generated and reused","","","","","","","","","","","","","","","","True","True","","","True","","","Microscopy","","","RNA/DNA sequencing","Mass spectrometry proteomics","","","","","","","","Cohort analysis","","","","","","","","","True","","True","","True","True","True","","","","True","True","","True","True","","","10 GB - 100 GB","","","","True","True","","","","","","","","moderately interested","very interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"848","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","428.08","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Molecular Biology","","","","","","","","Biology","","","","","","","","","","","PhD candidate","","","Not familiar with FAIR","","True","","","","ImageJ","GraphPad","Office Software (unspecified)","","True","","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","Some of them","Some of them","","","","","","None","","None","None","","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","True","True","","","","","","Fluoreszenzmikroskopie","","","Affinitätschromatographie","Größenausschlusschromatographie","","","","","","","","","","","","","","","","","","","","","True","","","","","True","","","","True","","","","","","","","True","True","True","","","","True","","","very interested","very interested","not interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"852","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","580.18","Completed the survey","Anonymized","Anonymized","Health","","Datenwissenschaften","","","","","","","","","","","","","","","","","","","","","","Postdoc","","","Familiar with FAIR","","True","","","","Python","Machine Learning Libraries","Python","","True","True","","","","","","","True","","True","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","None","","","","","","","","","Purely measured","Purely reused","","","","","","","","","","","","","","","","True","","","","","","","Fluoreszenzmikroskopie","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","100 GB - 1000 GB (1 TB)","","","","","","","","","","","","True","moderately interested","moderately interested","not interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"853","","True","","","True","True","True","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","15.0","","","True","True","True","","","","True","","True","","","","","","","","","","","","","","","","13818.4","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Oncology","","","","","","","Principal Investigator","","","Familiar with FAIR","","True","","","","FlowJo","Excel (Spreadsheets)","GraphPad","","","True","","True","","","","","","","","","","","","","","True","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","None","","None","None","","","","","","Mostly measured","Purely generated","","","","","","","","","","","","","","","","True","True","","True","","","","FACS","Mikroskopie","","PCR","Western Blotting","HPLC-MS","","","","Synthese von Peptiden","","","","","","","","","","","","","","","True","True","True","","","True","","","True","True","","","","","100 MB - 1000 MB (1 GB)","","True","","True","True","True","","","","True","","","moderately interested","very interested","very interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"855","True","","","","True","True","","","","","","Good scientific practice","","","","True","","True","","","","","","","","","","","","","","","","","","25.0","","","","","","","","","","","","","True","","","","","","","","","","","","","","535.59","Completed the survey","Anonymized","Anonymized","Health","Physics","","","","","","","","","","","","","","","","","","","Medical","","","","Postdoc","","","Not familiar with FAIR","True","","","","","Anonymized","Python","Anonymized","","","True","","","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","Some of them","","","All","","","","","","None","","","None","","","","","","Mostly simulated","Purely generated","","","","","","","","","","","","","","","","True","","True","","","","","MRI","","","","","","Commercial electromagnetic solvers","","","","","","","","","","","","","","","","","True","","","","True","True","","True","True","True","True","","True","","","1 GB - 10 GB","","True","","","","","","","","","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","not interested","1980-01-01 00:00:00" +"856","True","True","True","","True","","","","True","True","","","","","","","","True","True","","","","","","","","","","","","","","","","","25.0","","","","","True","True","","True","","","True","True","True","True","True","True","","True","","","True","","","","","","362.88","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Computational Biology","","","","","","","","Biology","","","","","","","","","","","Student","","","Not familiar with FAIR","","True","True","","","R","Visual Studio","Anonymized","","","","","","True","","","","True","True","True","True","","","","","True","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","True","","","","","","","","","","","","None","None","None","None","None","None","None","","","Purely measured","Mostly generated","","","","","","","","","","","","","","","","","True","","","","","","","","","NGS Sequencing","Methylation Array","RNA Sequencing","","","","","","","","","","","","","","","","True","","","","","","True","","","True","True","True","","True","True","","","> 1 TB","","","","","","","","True","","True","","","very interested","not interested","moderately interested","not interested","very interested","very interested","1980-01-01 00:00:00" +"857","True","","","","True","True","True","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","60.0","","True","","True","True","True","True","True","","","","","","True","","","","","","","","","","","","","1447.89","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Health Science","","","","","","","","","","","Postdoc","","","Not familiar with FAIR","True","True","","","","Anonymized","Excel (Spreadsheets)","Word","","True","","","","","","","Lack of technical solutions","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","All","Some of them","","Some of them","","","","","","","","","","","","","","","Mostly measured","Purely reused","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","statistical testing","survival analysis","","","","","","","","","","True","True","True","","True","","True","","","True","","True","","","","100 MB - 1000 MB (1 GB)","","","","True","","","","","","","","","very interested","very interested","moderately interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"867","","","","","True","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","5.0","","","","","","","","","","","","","","","","","","","","","","","","","","","454.09","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Cell Biology","","","","","","","","Biology","","","","","","","","","","","PhD candidate","","","Apply FAIR","","True","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","","","","","","","","","","","","","","","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","True","True","","","","","","western blot, microscopy","","","mass spectrometry","","","","","","","","","","","","","","","","","","True","","","","True","","True","","","","","True","","","","","","10 GB - 100 GB","","","","True","True","","","","True","True","","","very interested","very interested","not interested","","moderately interested","moderately interested","1980-01-01 00:00:00" +"873","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","547.08","Completed the survey","Anonymized","Anonymized","Health","","Medizin","","","","","","","","","","","","","","","","","","","","","","PhD candidate","","","Not familiar with FAIR","","True","","","","Anonymized","Excel (Spreadsheets)","GraphPad","","","","","","","","True","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","None","None","None","","","","","","","Purely measured","Mostly generated","","","","","","","","","","","","","","","","True","True","","","","","Sample synthesis and preparation","Mikroskopie","Fotografie","","Säulenchromatographie","","","","","","","","","","","","Western Blot","RNA-Sequencing","PCR","","","","True","","","","True","","","True","","","","True","","","","","","I don't know","","","","","","","","","True","","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"874","True","","","","","True","","True","True","","","","","","True","True","","True","True","","","","","","","","","","","","","","","","","10.0","","","","","True","","","","True","True","True","True","","","","","","","","","","","","","","","323.49","Completed the survey","Anonymized","Anonymized","Health","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","","PhD candidate","","","Familiar with FAIR","True","True","","","","","","","","True","True","","True","True","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","Some of them","","Some of them","Some of them","","","","","","None","","None","None","","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","True","","","","","","","1 GB - 10 GB","","","True","True","True","","","","True","","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"875","True","True","","","True","","","","True","True","","","","","True","True","True","True","True","","","","","","","","","","","","","","","","","20.0","","","","True","True","","","","True","True","True","True","True","","True","True","","","","","","","","","","","580.52","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Biomedical Science","","","","","","","","Biology","","","","","","","","","","","Principal Investigator","","","Familiar with FAIR","True","True","","","","","","","","True","True","","True","True","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","None","None","None","None","None","","","","","Mostly measured","Equally generated and reused","","","","","","","","","","","","","","","","","True","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","1 GB - 10 GB","","True","True","","","True","","True","True","","","","moderately interested","very interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"876","","","","Other","True","","","","True","True","","","","","","","","","True","","","","","","","","","","","","","","","","","100.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","1233.42","Completed the survey","Anonymized","Anonymized","Health","","Medizininformatik","","","","","","","","","","","","","","","","","","","","","","PhD candidate","","","Apply FAIR","","True","","","","emacs","Anonymized","Anonymized","","True","","","","","","","","","","True","","","","","","","","True","GitLab","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","True","","All","All","All","All","All","","","All","","None","All","None","None","None","","","None","","Mostly measured","Purely reused","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","Sortierung durch statische, nicht-lernende Algorithmen (z.B. string matching mit regexp)","Manuelles Annotieren von Freitextdaten nach Ontologien, um diese maschinenlesbar zu machen","","","","","","","","","","","True","","True","True","","","","True","","","True","","","","100 GB - 1000 GB (1 TB)","","","","","","","","","","","RDM software & tools","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"878","True","True","","","True","","","True","True","","","","","","True","","","","True","","","","","","","","","","","","ENA","","","","","10.0","","True","True","True","True","True","True","True","True","True","True","","True","True","","","","","","","","","","","","","1189.49","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Ecology","","","","","","","","Biology","","","","","","","","","","","Principal Investigator","","","Familiar with FAIR","True","","","","","R","Anonymized","Anonymized","","","","True","True","","","","","","","","","","","","","True","","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","True","","","None","All","None","All","","","All","","","None","None","None","All","","","None","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","True","True","","","","","","Mikroskopie","MRT","","Spektroskopie","Chromatographie","","","","","","","","","","","","","","","","","True","","","","True","","True","True","True","","","True","True","True","","","","> 1 TB","","True","","True","True","True","","True","","True","","","very interested","very interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"881","True","True","","","","","","True","","True","","","","","True","True","","","True","","","","","","","","","","","","EGA","dbGAP","","","","10.0","","","","","True","","True","True","True","True","True","True","True","True","","","","","","","","","","","","","744.71","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Genetics","","","","","","","","Biology","","","","","","","","","","","Principal Investigator","","","Familiar with FAIR","True","True","","","","Anonymized","Anonymized","R","","True","","True","True","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","All","All","All","","","","","","None","None","None","None","","","","","","Mostly measured","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","Genotyping","Sequencing","","Polygenic risk scores","","","","","","Statistical techniques for association analysis","","","","","","","","","True","","","","True","True","True","","","True","","True","","True","True","","","100 MB - 1000 MB (1 GB)","","","","","True","","","True","","","","","very interested","moderately interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"886","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","5.0","","","","","","","","","","","","","","","","","","","","","","","","","","","146.1","Completed the survey","Anonymized","Anonymized","Health","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","1980-01-01 00:00:00" +"891","True","","","","True","True","True","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","20.0","","True","True","True","True","","","","True","","True","True","True","True","","","","","","","","","","","","","1338.29","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","Genomik","","","","","","","Biology","","","","","","","","","","","Principal Investigator","","","Apply FAIR","","True","","","","Excel (Spreadsheets)","Anonymized","ImageJ","","","","True","True","","","","","True","True","True","True","","","","","True","True","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","None","","None","Some of them","","","","","","Mostly measured","Mostly generated","","","","","","","","","","","","","","","","True","True","","","","","Other","Hochdurchsatz-Mikroskopie von fixierten Zellen","Mikroskopie von Geweben","Mikroskopie von Drosophila (in vivo)","Hochdurchsatz-Screening: Auslesen von Lumineszenz","RNA- und DNA-Sequenzierung","Molekularbiologische Methoden wie Western Blot, qPCR","","","","","","","","","","in vivo Screening von Drosophila (Auszählen / Beobachten von Drosophila)","CRISPR Screening (Sequenzierung und Datenauswertung)","Bioinformatische Datenanalyse von Hochdurchsatz-Experimenten","","","","","","True","True","True","","True","","","","True","True","","True","","","","10 GB - 100 GB","","","","True","True","True","","True","True","True","","","very interested","very interested","","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"893","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1142.7","Completed the survey","Anonymized","Anonymized","Health","","Epidemiology","","","","","","","","","","","","","","","","","","","","","","Postdoc","","","Familiar with FAIR","","True","","","","SAS","R","Office Software (unspecified)","","","","","","","","","","True","True","True","True","","","","","","","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","True","","","All","All","All","All","All","All","All","","","None","None","None","None","None","None","None","","","Purely measured","Purely reused","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","Interviews and questionnaires","Examinations","Laboratory measurements","","","","","","","","","","","","","","","True","","","True","","","","","","","","","","True","True","True","True","True","True","True","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"896","True","True","","","True","","","","True","True","","","","","","","","True","","True","","","","","","","","","","","EGA","GEO","","","","60.0","","True","True","True","True","True","True","True","True","True","True","True","True","True","True","","","","","","","","","","","","714.56","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Pediatrics","","","","","","","Postdoc","","","Familiar with FAIR","","True","","","","R","Adobe Illustrator","Excel (Spreadsheets)","","True","","","","True","","","","True","","True","True","","","","","","","True","","","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","","","","","","","","","","","","","","","","","","","Mostly measured","Mostly reused","","","","","","","","","","","","","","","","","True","","","","","","","","","Illumina EPIC DNA Methylation Array","NGS","Krankenhausinformationssysteme","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","","","100 GB - 1000 GB (1 TB)","","","True","True","True","","","True","True","True","","","moderately interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"897","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","494.88","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Oncology","","","","","","","Research Associate","","","Not familiar with FAIR","","True","","","","Machine Learning Libraries","PyTorch","Anonymized","","","","","","","","","Lack of technical solutions","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","All","","","","","","","All","All","All","","","","","","","Equally measured and simulated","Mostly reused","","","","","","","","","","","","","","","","True","","","","","","","MRT","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","True","","","10 GB - 100 GB","","","","","","","","","","","","True","not interested","not interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"900","True","","","","True","","","","True","True","","","True","","","","","","","","","","","","","","","","","","","","","","","80.0","","","","True","True","","","","True","True","True","True","True","True","","","","","","","","","","","","","2485.29","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Molecular Biology","","","","","","","","Biology","","","","","","","","","","","PhD candidate","","","Not familiar with FAIR","True","True","","","","R","Excel (Spreadsheets)","ImageJ","","","","","","","","True","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","None","Some of them","Some of them","","","","","","None","Some of them","Some of them","None","","","","","","Mostly measured","Equally generated and reused","","","","","","","","","","","","","","","","True","","","","True","","Other","Mikroskopie","","","","","","","","","","","","statistische Analyse von Messwerten","","","Sequenzierung & bioinformatische Auswertung","qPCR","Zellkultur","","","","","","","","True","","","","","","True","","","True","","","","I don't know","","True","True","True","True","","","","","","","","very interested","moderately interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"902","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","427.02","Completed the survey","Anonymized","Anonymized","Health","Physics","","","","","","","","","","","","","","","","","","","Medizinische Physik","","","","Postdoc","","","Not familiar with FAIR","","True","","","","Python","R","","","True","","","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","None","None","None","None","","","","","Mostly measured","","","","","","","","","","","","","","","","","True","","","","","","","MRT","PET","CT","","","","","","","","","","","","","","","","","","","True","","","","","","","True","","","","","","","","","","10 GB - 100 GB","","","True","True","True","True","","","","","","","very interested","moderately interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"904","True","","","","","True","","","True","","","","True","","","","","","","","","","","","","","","","","","","","","","","5.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","671.29","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Pharmacy","","","","","","","Research Associate","","","","True","True","","","","Anonymized","Excel (Spreadsheets)","Word","","True","","","","","","","","True","True","True","True","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","None","","","","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","True","True","","True","","","","PET","","","HPLC","GC","TLC","","","","Radiochemie","organische Chemie","Peptidsynthese","","","","","","","","","","","","","","True","","","True","","","","True","","","","","","100 MB - 1000 MB (1 GB)","","True","","True","True","True","","","","","","","very interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"908","","True","","","","True","","True","True","","","","True","","","","","","","","","","","","","","","","","","ArrayExpress","ENA","Zenodo","","","100.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","757.1","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Health Science","","","","","","","","","","","Principal Investigator","","","Apply FAIR","","True","True","","","R","Anonymized","Adobe Illustrator","","True","True","True","","","","","","","","","True","","True","","","","True","True","","","Yes","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","MIAME","True","True","True","","True","True","","","","All","All","All","","All","All","","","","Some of them","Some of them","Some of them","","Some of them","Some of them","","","","Purely measured","Mostly generated","","","","","","","","","","","","","","","","True","True","","","","","","Microscopy","","","Genomic sequencing","","","","","","","","","","","","","","","","","","True","","","","","","","","True","","True","","","True","True","Binary scientific formats","","10 GB - 100 GB","","True","","","","","","","","","","","not interested","moderately interested","not interested","moderately interested","not interested","not interested","1980-01-01 00:00:00" +"910","","True","","","True","","","True","True","","","","","","True","","","","","","","","","","","","","","","","GEO","ENA","ProteomeXchange","","","40.0","","True","True","","","","","","True","","True","True","True","True","","","","","","","","","","","","","641.71","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Bioinformatics","","","","","","","","Biology","","","","","","","","","","","Postdoc","","","Not familiar with FAIR","","True","True","","","R","Office Software (unspecified)","Python","","True","True","True","","","","","","True","True","True","True","True","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","None","","Some of them","Some of them","","","","","","Mostly simulated","Mostly reused","","","","","","","","","","","","","","","","","True","","","","","","","","","Next Generation Sequencing","Massenspektrometrie","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","","","","","","10 GB - 100 GB","","","","True","True","","","","","","","","very interested","very interested","moderately interested","not interested","very interested","very interested","1980-01-01 00:00:00" +"911","True","True","","","","True","","True","True","","","","","","True","True","","","","","Competition","","","","","","","","","","","","","","","100.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","546.7","Completed the survey","Anonymized","Anonymized","Health","","Biomedical Engineering","","","","","","","","","","","","","","","","","","","","","","Principal Investigator","","","Familiar with FAIR","","True","","","","Python","Git","LaTeX","","True","True","True","True","True","","","Relevant metadata is missing","True","True","True","","","","","","","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","","","All","All","All","All","All","All","","","","Some of them","Some of them","Some of them","All","Some of them","Some of them","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","True","True","","","True","","","Reflectance imaging","Fluorescence imaging","Multispectral fluorescence","Optical absorbance spectroscopy","Fluoresence spectroscopy","Excitation spectroscopy","","","","","","","User experience surveys","","","","","","","","","","True","True","","True","","","True","","","True","True","","True","","","","100 MB - 1000 MB (1 GB)","","True","","","","True","","True","","True","","","moderately interested","very interested","moderately interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"914","True","","","","True","","","True","True","","","","","","","","","","True","","Legal / ethical concerns","","","","","","","","","","","","","","","20.0","","","","","","","","","","","","","","","","","","","","","","","","","","","848.39","Completed the survey","Anonymized","Anonymized","Health","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","","Principal Investigator","","","Familiar with FAIR","","True","","","","Python","Anonymized","MITK","","True","True","","True","","","","","","True","True","","","","","","","True","True","","","Yes","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","DICOM","True","True","True","True","","True","","","","Some of them","Some of them","Some of them","Some of them","","Some of them","","","","Some of them","Some of them","Some of them","Some of them","","None","","","","Mostly measured","Mostly reused","","","","","","","","","","","","","","","","True","","True","","","","","MRI","CT","US","","","","Monte Carlo","","","","","","","","","","","","","","","True","True","True","","","","","True","","True","True","","","True","True","","","100 GB - 1000 GB (1 TB)","","","True","","True","","","","True","True","","","moderately interested","moderately interested","very interested","very interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"916","True","True","","","True","True","","","","True","","","","","True","True","","","","","Lack of time / personnel","","","","","","","","","","Institutional Repository","","","","","40.0","","True","True","","","","","","","","","","True","True","","","True","True","","","","","","","","","496.39","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Radiobiology","","","","","","","Postdoc","","","Familiar with FAIR","","True","True","","","Fiji","Excel (Spreadsheets)","MITK","","True","True","True","True","","","","","True","True","True","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","True","","True","","Some of them","","","All","","All","","All","","None","","","None","","None","","Some of them","","Mostly measured","Purely generated","","","","","","","","","","","","","","","","True","","","","","","","Mikroskopie","MRT","CT","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","True","True","","True","","","","10 GB - 100 GB","","True","True","True","True","True","True","","","True","","","very interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"917","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","50.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","659.93","Completed the survey","Anonymized","Anonymized","Health","","","","","","","","","","","","","","","","","","","","","","","","","","","Familiar with FAIR","","True","True","","","","","","True","","","","","","","","","","","","","","","","","","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","Some of them","All","All","Some of them","","","","","None","None","None","None","None","","","","","Mostly generated","","","","","","","","","","","","","","","","True","","","","True","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","True","","True","True","","","True","","True","","","","","","","True","True","","True","","True","","True","","","very interested","moderately interested","","","moderately interested","very interested","1980-01-01 00:00:00" +"918","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","383.86","Completed the survey","Anonymized","Anonymized","Health","","Computer Science","","","","","","","","","","","","","","","","","","","","","","PhD candidate","","","Familiar with FAIR","True","True","True","","","MITK","Python","","True","","True","","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","Some of them","Some of them","","All","","","","","","Some of them","All","","Some of them","","","","","","Purely measured","Purely reused","","","","","","","","","","","","","","","","True","","","","","","","CT","MRT","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","True","","","","","","","100 GB - 1000 GB (1 TB)","","","True","","","True","True","","True","","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"922","True","","","","","","","","True","","","","","","True","True","True","True","","True","","","","","","","","","","","","","","","","30.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","395.74","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Oncology","","","","","","","PhD candidate","","","Familiar with FAIR","True","True","","","","Excel (Spreadsheets)","GraphPad","FlowJo","","True","True","True","","","","","","","","","","","","","","True","","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","All","None","","","","","","","None","None","None","","","","","","","Purely measured","Mostly generated","","","","","","","","","","","","","","","","","True","","","","","","","","","FACS","qPCR","Deep sequencing","","","","","","","","","","","","","","","","True","","","","True","","","","","True","","True","","True","","","","I don't know","","True","True","True","","","True","","","","","","very interested","very interested","moderately interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"924","True","","","","","True","","True","","True","","","True","","","","","","","","","","","","","","","","","","","","","","","40.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","421.93","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Molecular Biology","","","","","","","","Biology","","","","","","","","","","","PhD candidate","","","Not familiar with FAIR","True","True","","","","Anonymized","Anonymized","Excel (Spreadsheets)","","","","True","","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","None","","","","","","","","","Mostly measured","Mostly generated","","","","","","","","","","","","","","","","","True","","True","","","","","","","Mass spectrometry","","","","","","Cloning","","","","","","","","","","","","","","","","True","","True","True","True","","","True","","True","","","","1 GB - 10 GB","","True","","True","","True","True","","True","True","","","very interested","very interested","very interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"927","True","","","","","True","","","True","True","","","","","True","True","","","","True","","","","","","","","","","","","","","","","5.0","","","","","","True","","","","","","","","","","","","","","","","","","","","","416.66","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Structural Biology","","","","","","","","Biology","","","","","","","","","","","Technical Staff","Technical Staff","","Not familiar with FAIR","True","True","","","","Anonymized","Excel (Spreadsheets)","Fiji","","","True","True","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","True","","","None","Some of them","","","","","All","","","","","","","","","","","","Purely measured","Mostly generated","","","","","","","","","","","","","","","","True","True","","","","","","confokale Mikroskopie","","","Spektroskopie","Chromatographie","","","","","","","","","","","","","","","","","True","True","","","True","True","True","","","","True","True","","True","","","","> 1 TB","","","","True","","True","","","True","","","","very interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"930","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1635.11","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Neurology","","","","","","","Postdoc","","","Not familiar with FAIR","","True","","","","SPSS","GraphPad","","","True","True","","True","True","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","True","","","","","","","","","","","","","None","","","","","None","","","","Purely measured","Mostly generated","","","","","","","","","","","","","","","","","True","","","","","","","","","Immunoassays","Proteomics","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","< 100 MB","","","","True","True","True","","True","","True","Financial resources for RDM","","not interested","moderately interested","not interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"931","True","True","","","True","True","","True","","","","","","","","","","True","","","","","","","","","","","","","BMRB","","","","","80.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","734.97","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Biophysics","","","","","","","","Biology","","","","","","","","","","","Postdoc","","","Not familiar with FAIR","True","True","","","","Excel (Spreadsheets)","IGOR","Anonymized","","","","","","","","True","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","All","None","","","","","","Mostly measured","Purely generated","","","","","","","","","","","","","","","","","True","","","","","","","","","Plate reader","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","< 100 MB","","True","True","","","","","","","","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"932","True","True","","","True","","","","True","","","Guidelines / policies of publishers","","","","","","True","True","","","","","","","","","","","","GEO","figshare","Zenodo","","","95.0","","True","","True","True","True","","","True","True","True","","True","True","True","","","","","","","","","","","","603.4","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Bioinformatics","","","","","","","","Biology","","","","","","","","","","","Postdoc","","","Familiar with FAIR","","True","True","","","Python","Office Software (unspecified)","Adobe Illustrator","","","","","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","Some of them","","","","","None","All","Some of them","None","None","","","","","Mostly measured","Mostly reused","","","","","","","","","","","","","","","","","True","True","","","","","","","","single-cell RNA-sequencing","cell sorting","","custom Python scripts","","","","","","","","","","","","","","","True","","","","","","","","","","True","True","","","True","","","10 GB - 100 GB","","","True","","True","True","","","","","","","very interested","very interested","not interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"933","True","True","","","True","True","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","25.0","","","","True","True","","","","","True","True","","","","","","","","","","","","","","","","420.82","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Cell Biology","","","","","","","","Biology","","","","","","","","","","","PhD candidate","","","Not familiar with FAIR","","True","","","","Fiji","Excel (Spreadsheets)","Anonymized","True","","","","","","","","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","None","All","","","","","","All","","All","All","","","","","","Purely measured","Mostly generated","","","","","","","","","","","","","","","","True","True","","","","","","Fluorescence Microscopy","Light microscopy","Live cell microscopy","Mass spectrometry","RNAseq","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","True","True","","","","","> 1 TB","","","","","","","","","","","","True","moderately interested","moderately interested","not interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"938","True","True","","","True","","","True","True","","","","","","","","","True","","True","","","","","","","","","","","","","","","","30.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","504.2","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","Neurobiologie","","","","","","","Biology","","","","","","","","","","","","","","Apply FAIR","","True","True","","","","","","","","","True","True","","","","","True","True","True","True","True","","","","","True","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","True","","","","Some of them","","Some of them","","All","Some of them","","","","Some of them","","Some of them","","Some of them","","","","","Mostly measured","Mostly generated","","","","","","","","","","","","","","","","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","True","True","","","True","","","> 1 TB","","True","","True","","True","","True","","True","","","moderately interested","very interested","very interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"939","True","","","","True","","True","True","","","","","True","","","","","","","","","","","","","","","","","","","","","","","40.0","","","","","","True","True","True","True","True","True","True","","","","","","","","","","","","","","","587.91","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Health Science","","","","","","","","","","","Technical Staff","Technical Staff","","Not familiar with FAIR","","True","True","","","Anonymized","Anonymized","Anonymized","","","","True","","","","True","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","Some of them","","","","","","","None","None","None","","","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","Library preparation","DNA sequencing","qPCR","","","","","","","","","","True","","","","True","","","","","","","True","","","","","","> 1 TB","","","","","","True","True","","True","","","","very interested","very interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"940","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","5.0","","","","","","","","","","","","","","","","","","","","","","","","","","","134.39","Completed the survey","Anonymized","Anonymized","Health","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","1980-01-01 00:00:00" +"944","","True","","","","","","True","","","","","","True","True","True","","True","True","True","","","","","","","","","","","EudraCT","ClinicalTrials.gov","","","","5.0","","","","True","True","","True","True","True","True","True","","","True","","","","","","","","","","","","","861.9","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Neurology","","","","","","","Principal Investigator","","","Familiar with FAIR","","True","","","","Excel (Spreadsheets)","GraphPad","R","","True","True","True","","True","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","Some of them","Some of them","Some of them","","","","","","None","Some of them","Some of them","Some of them","","","","","","Mostly measured","Mostly generated","","","","","","","","","","","","","","","","True","True","","","True","","","MRT","PET","","ELISA","Mass Spectrometry","","","","","","","","Clinician Ratings","Patient/Caregiver Questionnairs","Neuropsychology","","","","","","","","True","","","True","True","","True","True","","True","True","","","","","","100 MB - 1000 MB (1 GB)","","True","True","True","True","True","True","True","True","True","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"946","","True","","","","","","True","True","","","","","","True","","","True","","","","","","","","","","","","","Gitlab / GitHub","","","","","50.0","","","","","","","","","","","","","","","","","","","","","","","","","","","860.4","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Physiology","","","","","","","","Biology","","","","","","","","","","","Postdoc","","","Not familiar with FAIR","True","True","","","","Python","MATLAB / Simulink","Anonymized","","","","","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","","All","Some of them","","","Some of them","","","","","","","","","","","","","","Purely measured","Mostly reused","","","","","","","","","","","","","","","","True","","","","","","Recordings","electron microscopy","confocal microscopy","","","","","","","","","","","","","","in vivo recordings (for example with silicon probes)","patch clamp and field recording in vitro","","","","","","","","","True","","","","","","True","","","True","","","","1 GB - 10 GB","","","","","","","","","","","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"947","True","","","","","True","","True","True","","","","","","True","True","","","True","","","","","","","","","","","","","","","","","15.0","","","","","True","","True","True","","True","True","","True","True","","","","","","","","","","","","","387.91","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Health Science","","","","","","","","","","","Research Associate","","","Apply FAIR","","True","","","","Anonymized","R","Anonymized","","","True","","","True","","","","True","","True","True","","","","","","True","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","None","Some of them","Some of them","Some of them","","","","","Mostly measured","Mostly reused","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","Regressionsmodelle","","","","","","LimeSurvey","","","","","","","","","","","","True","","","","","True","","True","","","","","","","1 GB - 10 GB","","True","","True","True","","","True","True","","","","moderately interested","very interested","not interested","moderately interested","moderately interested","not interested","1980-01-01 00:00:00" +"953","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","318.09","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Gynecology","","","","","","","Postdoc","","","Familiar with FAIR","True","","","","","Office Software (unspecified)","","","","","","","True","True","","","","True","","","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","Standardized interviews","","","","","","","","","","","","","","","True","","","","","","","","","","","< 100 MB","","","","","","","","True","","","","","not interested","moderately interested","not interested","moderately interested","moderately interested","not interested","1980-01-01 00:00:00" +"954","True","","","","True","True","","True","","","","","","","","True","","True","","True","","","","","","","","","","","","","","","","15.0","True","","","","","","","","","","","","","","","","","","","","","","","","","","451.43","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Physiology","","","","","","","","Biology","","","","","","","","","","","Postdoc","","","Familiar with FAIR","","True","","","","Python","MATLAB / Simulink","Fiji","","True","True","True","","","","","","","","True","","True","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","None","None","All","All","","","","","Mostly measured","","","","","","","","","","","","","","","","","True","","","","","","","2P calcium imaging","behaviour","1P calcium imaging","","","","","","","","","","","","","","","","","","","","True","","","True","","","True","","","True","True","","True","True","","","> 1 TB","","","","True","True","","","","True","True","","","moderately interested","very interested","moderately interested","moderately interested","not interested","very interested","1980-01-01 00:00:00" +"955","True","","","","","","","","True","","","Guidelines / policies of publishers","","True","True","","","True","","True","","","","","","","","","","","","","","","","5.0","","","","True","True","","","","True","True","True","True","True","True","","","","","","","","","","","","","1209.13","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Physiology","","","","","","","","Biology","","","","","","","","","","","Principal Investigator","","","Apply FAIR","","True","","","","Anonymized","Python","MATLAB / Simulink","","True","","True","True","","","","","True","True","","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","Some of them","All","All","","","","","","None","None","Some of them","None","","","","","","Mostly measured","Purely generated","","","","","","","","","","","","","","","","True","","","","","","","Multiphotonen Mikroskopie","Elektrophysiologie","Super-resolution Microscopy","","","","","","","","","","","","","","","","","","","True","True","","","True","","","True","","","True","","","True","","","","100 GB - 1000 GB (1 TB)","","True","True","True","","True","True","","","True","","","moderately interested","very interested","moderately interested","not interested","very interested","very interested","1980-01-01 00:00:00" +"961","","True","","","True","","","True","True","","","","","","True","","","True","","","","","","","","","","","","","GEO","","","","","90.0","","","True","True","True","","","","True","True","True","True","True","True","","","","","","","","","","","","","682.37","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Systems Biology","","","","","","","","Biology","","","","","","","","","","","Postdoc","","","Not familiar with FAIR","","True","True","","","R","Python","Anonymized","","True","True","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","Some of them","Some of them","All","All","","","","","None","None","None","Some of them","All","","","","","Purely measured","Mostly generated","","","","","","","","","","","","","","","","","True","","","","","","","","","Sequencing","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","True","True","","","> 1 TB","","True","","","True","","","","","","","","moderately interested","moderately interested","not interested","not interested","not interested","very interested","1980-01-01 00:00:00" +"963","True","","","","","","","True","","","","","","","","","","True","","","","","","","","","","","","","","","","","","50.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","353.76","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Hematology","","","","","","","PhD candidate","","","Apply FAIR","","True","","","","","","","","","","True","True","","","","","","","","","","","","","","True","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","","","","","","","","","","Mostly measured","Purely generated","","","","","","","","","","","","","","","","","True","","","","","","","","","scATAC-seq","RNA-seq ","","","","","","","","","","","","","","","","","","","","True","","","","","","","True","True","","True","","","","I don't know","","","True","True","True","","True","True","","True","","","very interested","very interested","very interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"964","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","541.02","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Health Science","","","","","","","","","","","PhD candidate","","","Familiar with FAIR","True","True","True","","","Adobe Illustrator","GraphPad","R","","","","True","","True","","","","True","True","True","True","","","","","","True","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","True","","All","All","All","All","","","","All","","Some of them","All","All","All","","","","All","","Mostly measured","Mostly generated","","","","","","","","","","","","","","","","True","True","","","","","","microscopy","","","","Size exclussion chromatography","Sequencing ","","","","","","","","","","","","","","","","True","","","","True","True","True","","","","True","True","","","True","","","100 GB - 1000 GB (1 TB)","","True","","True","","","True","True","True","True","","","very interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"965","","True","","","True","True","","","True","","","","","","","","","True","","","","","","","","","","","","","","","","","","100.0","","True","","","True","","","","","","","True","True","True","","","","True","","","","True","","","","","513.7","Completed the survey","Anonymized","Anonymized","Health","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","","Research Associate","","","Familiar with FAIR","","True","","","","Fiji","Anonymized","Anonymized","","True","","","","","","","","True","","True","","True","","","","","","","GitLab","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","True","","True","","All","None","Some of them","Some of them","","All","","All","","Some of them","Some of them","Some of them","Some of them","","Some of them","","Some of them","","Purely simulated","Mostly reused","","","","","","","","","","","","","","","","True","","","","","","","microscopy","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","True","True","True","","True","True","True","","True","True","","","100 GB - 1000 GB (1 TB)","","","","","","","","","","","","True","moderately interested","moderately interested","not interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"968","True","True","","","True","","","True","","True","","","True","","","","","","","","","","","","","","","","","","GEO","4DN","","","","90.0","","","","","","True","","","","","","","True","True","True","True","","","","","","","","","","","665.73","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Systems Biology","","","","","","","","Biology","","","","","","","","","","","Research Associate","","","Familiar with FAIR","","True","","","","","","","True","","","","","","","","","True","","True","True","","True","","","True","True","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","All","","All","All","","","","","","All","","Some of them","Some of them","","","","","Mostly measured","Mostly generated","","","","","","","","","","","","","","","","True","","","True","","","","Confocal microscopy","Flurescent microscopy","","","","","","","","Illumina sequencing","PCR","","","","","","","","","","","True","","","","","","","","","","True","True","","True","","","","1 GB - 10 GB","","","True","","","","","","","True","","","very interested","very interested","","moderately interested","not interested","moderately interested","1980-01-01 00:00:00" +"971","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","24949.6","Completed the survey","Anonymized","Anonymized","Health","","Data management","","","","","","","","","","","","","","","","","","","","","","Research Associate","","","Familiar with FAIR","","","","True","","Visual Studio","MITK","Anonymized","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Equally measured and simulated","Purely reused","","","","","","","","","","","","","","","","True","True","True","","","","","MRI","CT","X-ray","Single-cell sequencing","Whole genome sequencing","","Pytorch models","Custom deep learning models","","","","","","","","","","","","","","True","","True","True","True","True","True","True","","True","True","True","","True","","","","I don't know","","True","True","","","True","True","True","","","","","moderately interested","very interested","very interested","not interested","not interested","very interested","1980-01-01 00:00:00" +"972","","","True","","","True","","","True","","","","","","","","","","","True","","","","","","","","","","","","","","","","50.0","","","","True","True","","","","","","","","","","","","","","","","","","","","","","349.62","Completed the survey","Anonymized","Anonymized","Health","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","","Research Associate","","","","True","","","","","MATLAB / Simulink","Git","","","","","","","","","True","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","All","","Some of them","","Some of them","","","","","Some of them","","Some of them","","Some of them","","","","","Equally measured and simulated","Mostly reused","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","True","","True","","","","","","1 GB - 10 GB","","","","","","","","","True","","","","moderately interested","very interested","very interested","very interested","moderately interested","very interested","1980-01-01 00:00:00" +"973","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","464.94","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Medicine","","","","Neurology","","","","","","","Postdoc","","","Familiar with FAIR","","True","","","","MATLAB / Simulink","SPSS","Python","","True","","True","","","","True","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","All","","Some of them","Some of them","All","","","","","None","","None","None","None","","","","","Purely measured","Mostly generated","","","","","","","","","","","","","","","","True","","","","","","","PET","MRT","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","True","","","","","","1 GB - 10 GB","","","","True","True","True","True","True","True","True","","","very interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"976","True","True","True","","True","","","True","True","","","","","","True","","","True","","","","","","","","","","","","","PUBLISSO","","Gitlab / GitHub","","","90.0","","","","","","True","","True","","","","","True","True","","","","","","","","","","","","","6080.4","Completed the survey","Anonymized","Anonymized","Health","","Bioinformatics","","","","","","","","","","","","","","","","","","","","","","PhD candidate","","","Apply FAIR","","True","","","","Anonymized","Command line (scripts)","Anonymized","","True","True","","True","","","","","","True","True","","","True","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","All","","All","","","","","","","Some of them","","All","","","","","","Equally measured and simulated","Mostly reused","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Metagenomic read simulation","","","","","","","","","","","","","","","True","","True","","","","True","","","","True","True","","True","","","","100 GB - 1000 GB (1 TB)","","True","","","True","","","True","","","","","moderately interested","not interested","moderately interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"983","True","","","","True","True","","","True","","","","True","","","","","","","","","","","","","","","","","","","","","","","10.0","","","","","True","True","","","True","True","True","True","","","","","","","","","","","","","","","664.9","Completed the survey","Anonymized","Anonymized","Health","Chemistry","","","","","","","","","","","","","","","","","","","","","","","Postdoc","","","Not familiar with FAIR","True","True","","","","Office Software (unspecified)","Anonymized","Anonymized","","True","","","True","","","","Lack of technical knowledge","True","True","True","True","True","","","Provide research data context","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","None","","","","","","","Some of them","Some of them","All","","","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","True","True","","True","","","","MRT","CT","Photoakkustik","NMR","MS","HPLC","","","","Organische Chemie","Anorganische Chemie","","","","","","","","","","","","","","","True","True","","True","","","","True","","","","","","100 MB - 1000 MB (1 GB)","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"984","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","520.35","Completed the survey","Anonymized","Anonymized","Health","Physics","","","","","","","","","","","","","","","","","","","medical physics","","","","Principal Investigator","","","Familiar with FAIR","","True","","","","","","","","True","","","","True","","","","","","","","","","","","True","True","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","Some of them","","Some of them","Some of them","Some of them","","","","","None","","None","None","None","","","","","Equally measured and simulated","Mostly generated","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","True","","","","","","","","","","","","","","","","very interested","moderately interested","not interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"987","True","","","","True","True","True","","","","","","","","","True","True","","","True","","","","","","","","","","","","","","","","25.0","","","","","","","","True","","","","","","True","","True","","","","","","","","","","","837.88","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Biomedical Science","","","","","","","","Biology","","","","","","","","","","","Principal Investigator","","","Familiar with FAIR","True","","","","","Anonymized","Anonymized","Anonymized","","True","True","","","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","Some of them","","All","Some of them","","","","","","None","","Some of them","Some of them","","","","","Purely measured","Mostly generated","","","","","","","","","","","","","","","","True","True","","","","","","Immunfluorescence microscopy","X-ray","histo-morphology","gene expression","genotyping","proteomics, mass-spectroscopy","","","","","","","","","","","","","","","","","","","","True","","True","","True","True","","True","","True","","Plain text","","100 MB - 1000 MB (1 GB)","","","True","True","","True","","","","","","","very interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"988","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","435.22","Completed the survey","Anonymized","Anonymized","Health","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","","PhD candidate","","","Not familiar with FAIR","","True","True","","","","","","","","","","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","","","","","","","","","","","","","","","","","","","Purely measured","Purely reused","","","","","","","","","","","","","","","","True","","","","","","","MRI","X-ray","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","True","","","True","","Plain text","","1 GB - 10 GB","","","","","","","","","","","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"989","True","True","","","True","True","","","True","","","","","","","True","True","","","","","","","","","","","","","","GEO","Gitlab / GitHub","UCSC Genome Browser","","","80.0","","True","","","True","True","","","True","","True","True","True","True","True","","","","","","","","","","","","2259.29","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Bioinformatics","","","","","","","","Biology","","","","","","","","","","","PhD candidate","","","Not familiar with FAIR","","True","","","","R","Adobe Illustrator","","","","True","","","","","","","True","","True","True","","","","","","True","","Digital system","","Yes","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","Others","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","Some of them","Some of them","None","None","","","","","Mostly measured","Purely reused","","","","","","","","","","","","","","","","True","True","True","","","","","Microscopy","","","Next generation sequencing","","","Polymer modeling","","","","","","","","","","","","","","","True","","True","","True","True","True","","","","True","True","","","","","","100 GB - 1000 GB (1 TB)","","","","","","","","True","","","","","moderately interested","moderately interested","very interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"992","","True","","","True","True","","True","","","","","","","True","","","","","","","","","","","","","","","","IMPC","GenTaR","","","","75.0","","True","True","True","True","True","True","True","True","True","True","True","","","True","","","","","","","","","","","","1883.74","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Health Science","","","","","","","","","","","Postdoc","","","Familiar with FAIR","True","True","True","","","Database Management System","Excel (Spreadsheets)","Python","","","True","True","True","","","","","True","True","True","True","True","True","","","True","True","","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","Some of them","","","","","","Some of them","Some of them","Some of them","None","","","","","Mostly measured","Mostly reused","","","","","","","","","","","","","","","","True","True","","","","","Other","µCT","OCT","DXA","Chemische Analysen von Blutproben","","","","","","","","","","","","EKG","Histopathologie","Verhaltens- und Neurologische Tests","","","","True","True","","True","True","True","True","True","","True","True","True","True","True","","","","10 GB - 100 GB","","","True","True","True","True","True","","True","True","","","moderately interested","very interested","very interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"993","True","True","","","True","True","","","","True","","","","","","","","True","","True","","","","","","","","","","","OpenOrganelle","","","","","70.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","392.28","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Cell Biology","","","","","","","","Biology","","","","","","","","","","","Postdoc","","","Familiar with FAIR","True","","","","","Fiji","Anonymized","Anonymized","","True","","True","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","Some of them","Some of them","","","","","","","","","","","","","","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","True","","","","","","","Transmissionselektronenmikroskopie","Focused ion beam electron microscopy","Fluoreszenzmikroskopie","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","","True","","","100 GB - 1000 GB (1 TB)","","True","True","True","True","True","True","","True","","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"994","True","","","","True","","","","True","True","","","","","","","","","","","Insufficiently trained","","","","","","","","","","","","","","","20.0","","","","True","True","","","","True","True","True","True","True","True","","","","","","","","","","","","","543.25","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","Radiobiology","","","","","","","","Biology","","","","","","","","","","","PhD candidate","","","Familiar with FAIR","True","True","","","","Excel (Spreadsheets)","GraphPad","Fiji","","","","True","True","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","True","","","All","","Some of them","Some of them","","","All","","","None","","Some of them","None","","","None","","","Mostly measured","Mostly generated","","","","","","","","","","","","","","","","True","True","","","","","","phase-contrast","Immunofluorescence","","qPCR","viability assays","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","True","","","","","","10 GB - 100 GB","","","","True","True","True","True","True","True","True","","","very interested","very interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"997","True","True","","","True","True","","","","True","","","","","","","True","True","","True","","","","","","","","","","","Institutional Repository","Institutional Repository","Institutional Repository","","","25.0","","","","","","","True","True","True","True","","True","","","True","True","","","","","","","","","","","3490.49","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","More than 10 years","Research Associate","","Yes","Not familiar with FAIR","","True","True","","","ROOT framework","Database Management System","LabVIEW","","","","","True","","","","","True","True","True","True","","","","","","","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","All","All","","All","","","","","","Some of them","Some of them","","Some of them","","","","","Equally measured and simulated","Mostly generated","Yes","","100.0","","","","","","","","","","True","","","","True","True","","","","","","","","calorimeters ","spectrometers","counters","transport models","","","","","","","","","","","","","","","","","True","True","True","True","True","","","True","True","","True","True","True","","","100 GB - 1000 GB (1 TB)","","","","","","True","","","","True","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","not interested","1980-01-01 00:00:00" +"998","True","True","","","True","","","","True","True","","","","","True","","","True","","","","","","","","","","","","","Zenodo","HEASARC","","","","25.0","","True","True","True","","True","","True","True","","","","True","","True","","True","","","","","","","","","","568.88","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Astrophysics and Astronomy","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","","","True","","","Anonymized","ROOT framework","Anonymized","","True","","True","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","","","All","All","Some of them","Some of them","All","Some of them","","","","Some of them","Some of them","Some of them","Some of them","Some of them","None","","","","Equally measured and simulated","Equally generated and reused","Yes","","95.0","","","","","","","","","","","","Anonymized","","True","True","","","","","","","","Likelihood methods applying spatial, temporal, and spectral models","Machine learning methods for signal/background separation","Machine learning methods for regression","MC Event Generators for instrument development","Toy MC for evaluation of statistical uncertainties for time series and spectral analysis","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","> 1 TB","","True","","","","","","True","","True","","","very interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1000","True","True","","","True","","","","True","True","","","","","True","True","","True","","","","","","","","","","","","","Institutional Repository","","","","","25.0","","True","","","","True","True","True","True","True","True","","","","","","","","","","","","","","","","1654.76","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","More than 10 years","Research Associate","","No","Apply FAIR","","True","True","","","Anonymized","Anonymized","MATLAB / Simulink","","True","","","True","","","","","True","","True","","","","","","","","True","Source code and scripts","","Yes","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","No standard","True","True","True","True","True","","","","","All","All","All","All","All","","","","","Some of them","All","All","Some of them","All","","","","","Mostly simulated","","Yes","","80.0","","","","","","","","","","","","Anonymized","","","True","","","","","","","","","","","Markov Chain Monte Carlo","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Binary non-scientific formats","","> 1 TB","","","True","True","True","True","True","","True","True","","","very interested","very interested","moderately interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1001","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","No value to others","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","528.87","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Research Associate","","Yes","Not familiar with FAIR","","True","","","","Excel (Spreadsheets)","","","","","","","","","","True","","True","True","True","True","True","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","Some of them","All","All","","","","","","None","Some of them","None","Some of them","","","","","","Purely measured","Mostly generated","Yes","","0.0","","","","","","","","","","","","","True","","","True","","","","Mikroskopie","REM","Weißlichtchromatigrafie","","","","","","","PVD","","","","","","","","","","","","","","","True","True","","","True","","","","","","","","","","< 100 MB","","","","","","","","","","","","True","moderately interested","not interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1002","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","10.0","","","","True","True","True","","","","","","","","","","","","","","","","","","","","","1018.9","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","More than 10 years","","","","Not familiar with FAIR","True","True","","","","C/C++","ROOT framework","LaTeX","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","True","","","All","All","","","All","","Some of them","","","","","","","","","","","","Purely simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Quantenmolekulardynamik","Analytische Berechnungen","","","","","","","","","","","","","","True","","True","","True","","True","","","True","True","","","","","","","100 MB - 1000 MB (1 GB)","","True","","True","","True","","True","","True","","","very interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"1004","True","","","","True","","","True","True","","","","","","True","True","","True","","True","","","","","","","","","","","","","","","","10.0","","","","","","","","","True","True","","","","","","","","","","","","","","","","","405.18","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","7 to 10 years","Postdoc","","Yes","Familiar with FAIR","True","True","","","","","","","","True","True","","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","None","Some of them","Some of them","","","","","","","None","Some of them","Some of them","","","","","","","Mostly measured","Purely generated","Yes","","90.0","","","","","","","","","","","","Anonymized","True","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","True","","","","100 MB - 1000 MB (1 GB)","","","","","True","","","","","","","","not interested","moderately interested","moderately interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"1008","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","105.7","Completed the survey","Anonymized","Anonymized","Matter","Psychology","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","not interested","not interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"1009","True","","","","","True","","True","True","","","","True","","","","","","","","","","","","","","","","","","","","","","","15.0","","","","","","","","","","","True","","","","","","","","","","","","","","","","476.56","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","1 to 3 years","PhD candidate","","Not sure","Not familiar with FAIR","","True","","","","Anonymized","Anonymized","Anonymized","","True","True","","","","","","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","All","","All","","","","","","","None","","Some of them","","","","","","","Mostly simulated","Purely generated","Yes","","15.0","","","","","True","","","True","","","","","","","True","","","","","","","","","","","Particle-In-Cell (PIC)","Magnetohydrodynamics (MHD)","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","> 1 TB","","","","","","","","True","True","","","","moderately interested","not interested","moderately interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"1013","","True","","","True","","","True","True","","","","True","","","","","","","","","","","","","","","","","","Institutional Repository","","","","","40.0","","True","","True","True","","","","","","","","","","","","","","","","","","","","","","2004.01","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","","True","True","","","OriginLab","MATLAB / Simulink","Python","","","","True","True","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","Some of them","","All","","Some of them","","","","","None","","Some of them","","None","","","","","Mostly measured","Mostly generated","Yes","","15.0","","","","","True","","","","","","","","","True","True","","","","","","","","optical pump-probe spectroscopy","time-domain THz spectroscopy","FTIR spectroscopy and Raman","Matlab","Comsol","NextNano","","","","","","","","","","","","","True","","","","True","","","","","True","True","","","","","","","< 100 MB","","","","","","True","","","True","True","","","moderately interested","very interested","very interested","moderately interested","not interested","not interested","1980-01-01 00:00:00" +"1015","","","","In repository","","","","True","True","True","","","","True","True","True","True","True","True","True","","","","","","","","","","","","","","","","15.0","","True","","","","True","","True","","","","","","","True","True","","","","","","","","","","","1754.54","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","4 to 6 years","Postdoc","","Yes","Familiar with FAIR","True","True","True","","","LabVIEW","Anonymized","","","True","True","True","True","True","True","True","","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","None","Some of them","Some of them","Some of them","None","","","","","Mostly measured","Mostly generated","Not sure","","70.0","","","","","True","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","","True","","","True","","","","1 GB - 10 GB","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"1017","True","True","","","True","","","","True","True","","","","","True","True","True","","","","Other","","","","","","","","","","Institutional Repository","","","","","30.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","850.89","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","More than 10 years","Research Associate","","Yes","Apply FAIR","","True","True","","","FLUKA","ROOT framework","","","True","True","","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","True","","Some of them","","Some of them","Some of them","","","","Some of them","","None","","None","Some of them","","","","None","","Mostly simulated","Equally generated and reused","Yes","","100.0","","","","","True","","","","","","","Anonymized","","","True","","","","Analytical methods","","","","","","","Monte-Carlo","","","","","","","","","Typische DAQ-Systeme (NIM, Digitizer, etc.)","","","","","","True","","","","","","True","","","True","True","","","","True","Other","","100 GB - 1000 GB (1 TB)","","","","","","","","","","","","True","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1018","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","771.77","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","","Materialanalyse","","","More than 10 years","Research Associate","","Yes","Familiar with FAIR","","True","","","","Anonymized","Anonymized","Anonymized","","True","","","True","","","","","True","True","True","","","","","","True","","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","Some of them","","","Some of them","","","","","","None","","","None","","","","","","Purely measured","Purely generated","Yes","","100.0","","","","","","","","","","","","Anonymized","","True","","","","","","","","","Ion Beam Analysis","","","","","","","","","","","","","","","","","","","","True","","","","","True","","True","","True","","","","","","< 100 MB","","","","","True","True","","","","True","","","very interested","moderately interested","not interested","","very interested","moderately interested","1980-01-01 00:00:00" +"1019","","True","","","True","","","True","","","","","","","True","","","","","True","","","","","","","","","","","Institutional Repository","","","","","15.0","","","","","True","","","","True","True","True","","True","","","","","","","","","","","","","","420.0","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","1 to 3 years","PhD candidate","","Yes","Not familiar with FAIR","","True","True","","","Anonymized","Jupyter","Anonymized","","","","","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","True","","Some of them","","All","All","","","","Some of them","","None","","All","None","","","","None","","Mostly measured","Purely generated","Not sure","","0.0","","","","","","","","","","","","","","True","True","","","","","","","","Brillouin Lichtstreuung","","","Mikromagnetische Simulationen (Mumax3)","","","","","","","","","","","","","","","","","True","","True","","","","","","True","","","","True","Other","","10 GB - 100 GB","","","","True","True","True","","True","True","True","","","moderately interested","very interested","moderately interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"1022","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","Lack of incentives","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","578.32","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","","True","","","","MATLAB / Simulink","OriginLab","Anonymized","","True","","True","True","","","","Lack of technical solutions","True","True","True","","","","","","","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","True","","","All","All","All","","","","All","","","Some of them","All","All","","","","All","","","Mostly measured","Mostly generated","Yes","","5.0","","","","","","","","","","","","Anonymized","","True","True","","","","","","","","Ferromagnetische Resonanz","SQUID/VSM","XRD/XRR","Mikromagnetische Simulationen","","","","","","","","","","","","","","","True","","True","","True","","True","","","True","","","","","","","","1 GB - 10 GB","","True","","True","","True","","True","True","True","","","very interested","very interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"1023","","True","","","","","","True","True","","","","","","","","","","","","No value to others","","","","","","","","","","Institutional Repository","","","","","20.0","","","","True","True","True","","","True","True","True","","True","True","","","","","","","","","","","","","1209.7","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Postdoc","","Yes","Not familiar with FAIR","","True","","","","OriginLab","Anonymized","MATLAB / Simulink","True","","","","","","","","","True","True","True","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","Some of them","Some of them","All","","","","","","None","Some of them","None","Some of them","","","","","","Equally measured and simulated","Purely generated","Yes","","25.0","","True","True","","","","","","","","","Anonymized","True","","True","True","","","","AFM","SEM","GISAXS","","","","numerische Integration","","","Oberflächenmodifikation mit Ionenstrahlen","Dünnschichtabscheidung","","","","","","","","","","","","","True","","True","","True","True","","","","True","","","","","","100 MB - 1000 MB (1 GB)","","","","True","","True","","","","True","","","very interested","moderately interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"1024","True","","","","","","","True","True","","","","","","","","","True","","","","","","","","","","","","","","","","","","5.0","","","","","True","","","","","","","","","","","","","","","","","","","","","","627.87","Completed the survey","Anonymized","Anonymized","Matter","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","","True","","","","OriginLab","MATLAB / Simulink","COMSOL Multiphysics","","True","True","","","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","Some of them","Some of them","","","","","","","","Some of them","Some of them","","","","","","","","Mostly measured","Equally generated and reused","Yes","","10.0","","True","","","","","","","","","","","True","True","","True","","","","SEM","TEM","EBSD","XRD","Reciprocal Space Mapping","VSM","","","","Sputterdeposition","PLD","","","","","","","","","","","","","","","True","","","","True","","","","","True","","","","100 MB - 1000 MB (1 GB)","","True","","True","","True","","True","True","","","","very interested","very interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"1025","","True","","","True","","","True","True","","","","","","","","","","True","","","","","","","","","","","","Institutional Repository","","","","","40.0","","","","True","True","True","True","True","True","","True","","True","True","","","","","","","","","","","","","1309.22","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Not familiar with FAIR","","True","","","","LabVIEW","OriginLab","Office Software (unspecified)","","True","","","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","Some of them","None","Some of them","Some of them","Some of them","","","","","Mostly measured","Purely generated","Yes","","95.0","","","","","True","","","","","","","","","True","True","","","","","","","","pump-probe","spectroscopy","various optical and electrical measurements","simulation and fitting of measured data","","","","","","","","","","","","","","","True","","True","","True","","True","True","","True","True","True","True","True","True","","","100 MB - 1000 MB (1 GB)","","","","True","True","True","True","True","True","True","","","moderately interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"1026","True","","","","True","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","5.0","","","","","","","","","","","","","","","","","","","","","","","","","","","804.02","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","Less than 1 year","PhD candidate","","Not sure","Not familiar with FAIR","True","","","","","Anonymized","Anonymized","Anonymized","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Purely simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Density functional theory","Molecular dynamics","","","","","","","","","","","","","","","True","True","","True","","True","","","","True","","","","","","","100 MB - 1000 MB (1 GB)","","True","","","","","","","","","","","very interested","very interested","moderately interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"1027","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","939.39","Completed the survey","Anonymized","Anonymized","Matter","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","More than 10 years","","","No","Not familiar with FAIR","","True","","","","LabVIEW","Excel (Spreadsheets)","Git","","","","","","","","","","","","","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","Some of them","","","","","","","","None","Some of them","","","","","","","","Purely measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","Other","","","","","","","","","","","","","","","","A/D-Wandlung","Schnittstellen (Busse, Geräte)","","","","","","","True","","","","True","","","","","","","True","","","","","","","","","True","","","","","","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","not interested","1980-01-01 00:00:00" +"1028","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","No value to others","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","737.65","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","More than 10 years","Research Associate","","Yes","Not familiar with FAIR","True","True","","","","C/C++","Anonymized","OriginLab","True","","","","","","","","","True","True","True","","","","","","","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","Some of them","None","Some of them","None","Some of them","","","","","Mostly measured","Purely generated","Yes","","95.0","","","","","True","","","","","","","","","True","True","","","","","","","","Aufnahme von List-Mode-Daten","Aufnahme von Signalformen","","Monte Carlo Simulationen","","","","","","","","","","","","","","","","","True","","","","","","","True","True","","","","","Binary non-scientific formats","","100 GB - 1000 GB (1 TB)","","","","","","True","True","","","","","","very interested","moderately interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"1029","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","496.43","Completed the survey","Anonymized","Anonymized","Matter","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","1 to 3 years","PhD candidate","","Yes","Not familiar with FAIR","True","","","","","LabVIEW","OriginLab","Anonymized","","","","","","","","True","","True","True","True","","","","","","True","","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","None","None","None","","","","","","","None","None","None","","","","","","","Purely measured","Purely generated","Not sure","","20.0","","True","","","","","","","","","","","True","","","True","","","","Scanning Electron Microscopy","Optical Microscopy","Process cameras","","","","","","","3D-printing","","","","","","","","","","","","","","","","True","","True","","","","","","","True","","","","100 MB - 1000 MB (1 GB)","","","","","True","True","True","True","","True","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1039","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","3159.0","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Nanotechnology","","","","More than 10 years","Research Associate","","Yes","Familiar with FAIR","","True","","","","Anonymized","MATLAB / Simulink","OriginLab","","True","","True","True","True","","","","True","True","True","","","True","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","Some of them","","Some of them","Some of them","","","","","","None","","None","None","","","","","","Mostly measured","Mostly reused","Yes","","5.0","","","True","","","","","","","","","","True","True","","","","","","AFM","Mikroskopie","REM","Reflektometrie","Beugungssimulation","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","True","","","","Other","","I don't know","","","True","True","True","True","","","","True","","","moderately interested","very interested","moderately interested","not interested","very interested","very interested","1980-01-01 00:00:00" +"1040","True","","True","","","True","","True","True","","","","","True","True","","","True","","","","","","","","","","","","","","","","","","20.0","","","","True","True","True","True","","True","True","True","True","True","True","","","","","","","","","","","","","477.84","Completed the survey","Anonymized","Anonymized","Matter","Engineering Science","","","","","","","","","","Energy Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","Yes","Apply FAIR","","True","","","","","","","","True","","","True","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","None","Some of them","None","None","","","","","","Purely measured","Purely generated","Yes","","90.0","","True","True","","","True","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","True","","","True","","","100 GB - 1000 GB (1 TB)","","True","True","","","","","","","True","","","very interested","moderately interested","moderately interested","very interested","not interested","moderately interested","1980-01-01 00:00:00" +"1041","True","","","","True","","","True","True","","","","","True","True","","","True","","","","","","","","","","","","","","","","","","50.0","","","","True","True","True","True","True","True","True","","","True","","","","","","","","","","","","","","429.35","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","True","True","","","","OriginLab","Python","ImageJ","","True","True","","","","","","","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","Some of them","Some of them","","","","","","None","None","None","None","","","","","","Mostly measured","Equally generated and reused","Yes","","25.0","","","True","","","","","","","","","","True","True","","","","","","Mikroskopie","Tomographie","","Fluoreszenzspektroskopie","Absorptionsspektrokopie","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","True","True","","","True","","","10 GB - 100 GB","","True","","","","","","True","True","True","","","moderately interested","very interested","very interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"1043","","True","","","True","","","","","True","","","","","","True","","","","","","","","","","","","","","","Gitlab / GitHub","Zenodo","","","","30.0","","","","","True","True","","True","","","","","","","","","True","","","","","","","","","","622.02","Completed the survey","Anonymized","Anonymized","Matter","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","7 to 10 years","Postdoc","","Yes","","True","True","True","","","emacs","Git","Jupyter","","","","","","","","","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","","","Some of them","Some of them","","","","All","","","","None","None","","","","All","","","","Purely simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Numerical analysis","Finite element method","Mesoscopic simulation","","","","","","","","","","","","","","","True","","","","True","","","","True","","","","True","","","1 GB - 10 GB","","","","","","","","","","","","True","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"1044","True","True","","","","","","True","","","","","","","","True","True","","True","","","","","","","","","","","","Zenodo","","","","","5.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","774.7","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Soft Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","True","","","","","Anonymized","OriginLab","Delphi","","","","","","","","True","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","None","None","None","","","","","","","None","None","None","","","","","","","Mostly measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","Analytical methods","","","","","","","","","","","","","","","","Statische und dynamische Lichtstreuung ","Evaneszente Lichtstreuung","","","","","","","","","","","True","","","","","","","","","","","< 100 MB","","True","","","True","True","","","True","","","","","very interested","","","","","1980-01-01 00:00:00" +"1046","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Other","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","601.98","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","4 to 6 years","PhD candidate","","Yes","Familiar with FAIR","","True","","","Locally","Python","Anonymized","gnuplot","","","","True","True","","","","","","","","","","","","","","","True","GitLab","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","All","","","","All","","","","","None","","","","None","","","","","Mostly simulated","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","","","","","","","100 MB - 1000 MB (1 GB)","","True","True","","True","True","","True","True","True","","","moderately interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"1047","True","","","","True","","","True","True","","","","","","","True","True","","True","","","","","","","","","","","","","","","","","40.0","","","","True","True","","","","True","True","","","","","","","","","","","","","","","","","1387.01","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Research Associate","","Yes","Familiar with FAIR","True","True","","","","OriginLab","Anonymized","Python","","True","True","True","","","","","","","","","","","","","","True","","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","Some of them","","Some of them","","","","","","","None","","None","","","","","","","Purely measured","Mostly generated","Yes","","65.0","","","","","","True","","","","","","Anonymized","","True","","","","","Analytical methods","","","","individual measurements","bulk measurements: magnetization","","","","","","","","","","","individual or large area scans","elastic or inelastic measurements","","","","","True","","","","","True","True","","","","","","","","True","","","100 MB - 1000 MB (1 GB)","","","","True","","","","True","","True","","","moderately interested","moderately interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"1048","","","True","","","","","","True","","","","","","True","","True","","","","","","","","","","","","","","","","","","","5.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","1148.93","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Research Associate","","Yes","Apply FAIR","","True","","","","Anonymized","Anonymized","Anonymized","","True","","","True","","","","","True","","True","True","","","","","True","True","True","","","Yes","Yes","","","","","True","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","True","True","","Some of them","All","Some of them","Some of them","All","","All","All","","Some of them","Some of them","Some of them","Some of them","All","","All","All","","Purely measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","True","","True","","True","True","","","1 GB - 10 GB","","","","","","","","True","","True","","","moderately interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"1050","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","70.0","","","","True","True","True","","","True","","True","","True","","","","","","","","","","","","","","667.25","Completed the survey","Anonymized","Anonymized","Matter","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","4 to 6 years","Research Associate","","No","Not familiar with FAIR","True","True","True","","","OriginLab","MATLAB / Simulink","Anonymized","","","","","","","","","","","True","True","","","","","","","","True","","","Yes","Yes","","","","True","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","True","","","","","","Some of them","","All","All","","","","","","Some of them","","All","All","","","","","","","Mostly generated","Yes","","","","","","","","","","","","","","","True","True","True","","True","","","SEM","LSM","","Nanoindentation","","","Monte Carlo","","","","","","Weibull statistics","","","","","","","","","","","True","","True","True","","","","True","True","True","","","","","","100 MB - 1000 MB (1 GB)","","True","True","","True","True","True","","","","","","very interested","moderately interested","moderately interested","moderately interested","very interested","","1980-01-01 00:00:00" +"1051","True","","","","","True","","","True","","","","","","","True","","True","","","","","","","","","","","","","","","","","","5.0","","","","True","True","","True","","True","True","True","True","","True","","","","","","","True","","","","","","1847.39","Completed the survey","Anonymized","Anonymized","Matter","Chemistry","","","","","","Physical Chemistry","","","","","","","","","","","","","","","","More than 10 years","Postdoc","","Yes","Familiar with FAIR","","True","","","","MATLAB / Simulink","Anonymized","OriginLab","","","","","True","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","True","","","All","All","All","All","","","All","","","Some of them","Some of them","All","All","","","None","","","Mostly measured","Mostly generated","Yes","","95.0","","","True","","","","","","","","","","","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","","True","True","","","","","","","100 MB - 1000 MB (1 GB)","","","","","True","True","","","","True","","","moderately interested","very interested","moderately interested","not interested","very interested","very interested","1980-01-01 00:00:00" +"1052","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Other","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1154.85","Completed the survey","Anonymized","Anonymized","Matter","","Beschleunigerphysik","","","","","","","","","","","","","","","","","","","","","More than 10 years","Research Associate","","No","Familiar with FAIR","True","True","","","","Anonymized","Jupyter","","","","True","True","True","","","True","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","None","","","None","","","","","","None","","","None","","","","","","Equally measured and simulated","Purely generated","Yes","","30.0","","","True","","","","","","","","","Anonymized","True","","True","","","","Other","Kameras","","","","","","Tracking Rechnungen","","","","","","","","","Strahlmessungen wie Größe, Länge ect","","","","","","True","","True","True","True","","","","","True","True","","True","","","","","100 MB - 1000 MB (1 GB)","","","","","True","True","","","True","True","","","moderately interested","very interested","moderately interested","very interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1053","True","True","","","","True","","","True","True","","","","","True","True","","","","","","","","","","","","","","","Materials Cloud","","","","","85.0","","True","True","","True","True","True","","","True","True","True","","","","","True","","","","","","","","","","10957.7","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","4 to 6 years","Postdoc","","Yes","Apply FAIR","","True","True","","","Anonymized","Anonymized","AiiDA","","True","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","True","","","","Some of them","All","All","","","Some of them","","","","Some of them","All","All","","","Some of them","","","","Purely simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","density functional theory","Spin dynamics","","","","","","","","","","","","","","True","","True","True","","","True","","","True","True","","","True","True","","","100 MB - 1000 MB (1 GB)","","","True","True","","","","True","True","","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1058","True","","True","","","","True","","True","True","","","","","","","True","True","True","","","","","","","","","","","","","","","","","25.0","","","","True","True","","","","True","True","","","True","True","","","","","","","","","","","","","665.75","Completed the survey","Anonymized","Anonymized","Matter","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","More than 10 years","Research Associate","","Yes","Not familiar with FAIR","True","True","","","","Office Software (unspecified)","Anonymized","Anonymized","","","","","","True","","True","","True","","True","True","","True","","","True","","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","Some of them","","All","All","","","","","","Some of them","","All","All","","","","","","Purely measured","Purely generated","Yes","","100.0","","","","","","","","","","","","Anonymized","True","","","","","","Analytical methods","transmission electron microscopy","","","","","","","","","","","","","","","small angle neutron scattering","quasielastic neutron scattering","","","","","True","","True","","True","True","True","True","","","True","True","","","True","","","100 MB - 1000 MB (1 GB)","","","True","","","","","True","True","","","","very interested","very interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"1059","","","True","","","True","True","","","","","","","","True","","","True","","","","","","","","","","","","","","","","","","60.0","","","","True","True","","","","True","","True","","","","","","","","","","","","","","","","777.5","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Research Associate","","Yes","Not familiar with FAIR","True","True","","","","MATLAB / Simulink","OriginLab","","","True","","","","","","","","True","","","True","","","","","True","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","Some of them","","Some of them","All","Some of them","","","","","None","","All","None","None","","","","","Purely measured","","Yes","","80.0","","","True","","","","","","","","","","True","True","","","","","","Photoemissionsmkroskopie","Rasterkraftmikroskopie","","Spektroskopie","","","","","","","","","","","","","","","","","","True","","","","True","","True","True","","","True","True","","","","","","100 GB - 1000 GB (1 TB)","","True","","","","","","","","","","","moderately interested","moderately interested","","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"1061","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","6434.83","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Research Associate","","Yes","Not familiar with FAIR","True","True","","","","IGOR","Python","Anonymized","","","","","","","True","True","","","","","","","","","","True","","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","None","","","","","","","","","Mostly measured","Purely generated","Yes","","90.0","","True","True","","","","","","","","","Anonymized","True","True","True","","","","","Photoemissionsmikroskopie (PEEM)","","","Photoelektronen-Spektroskopie (PES)","Röntgenabsorbtionsspektroskopie (XAS)","","SESSA","","","","","","","","","","","","","","","","","True","","True","","True","","","","","","","","","","","1 GB - 10 GB","","True","","","","True","","","True","True","","","very interested","very interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"1062","","","True","","","","","True","True","True","","","","","True","","True","","","","","","","","","","","","","","","","","","","25.0","","True","","True","True","True","True","True","","","","","True","True","True","True","","","","","","","","","","","983.9","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Soft Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","True","True","","","","Office Software (unspecified)","Anonymized","Anonymized","","","True","","","","","","","","","","","","","","","True","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","","","","All","Some of them","","Some of them","All","","","","","Some of them","Some of them","","Some of them","Some of them","","","","","","Purely generated","Yes","","","","","","","","","","","","","","","True","True","True","True","","","","Light microscope","Transmission Electron Microscope","","Small Angle Neutron Scattering ","Neutron Spin Echo Spectroscopy","Neutron Backscattering","Analytic Models with Numeric Solutions","Ray Tracing Neutron Instrumentation","Molecular Dynamics Simulations","Mixing / Cleaning Chemicals","Lipid extraction","","","","","","","","","","","True","True","True","","True","True","True","","","","True","True","","","","","","< 100 MB","","True","","","","","","True","","True","","","moderately interested","very interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"1063","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","780.32","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Polymer Physics","","","","More than 10 years","Research Associate","","Yes","Familiar with FAIR","","True","","","","Fortran","","","True","","","","","","","","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","None","None","None","","","","","","","None","None","None","","","","","","","Purely measured","Purely generated","Yes","","80.0","","","","","","","","","","","","Anonymized","","","","","","","Analytical methods","","","","","","","","","","","","","","","","neutronenstreruung","roentgenstreiing","rheologie","","","","","","","","True","","True","","","","","","","","True","","","10 GB - 100 GB","","","","","","","","","","","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1065","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","949.43","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Soft Matter Physics","","","","More than 10 years","Research Associate","","Yes","Familiar with FAIR","True","True","True","","","Anonymized","Anonymized","Anonymized","","True","","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","All","All","All","Some of them","","","","","","Mostly measured","","Yes","","100.0","","","","","","","","","","","","Anonymized","","True","","","","","Analytical methods","","","","NMR","","","","","","","","","","","","NSE","SANS","","","","","","","","","","","True","","","","","","","","","","","100 MB - 1000 MB (1 GB)","","","","","","","","","","True","","","not interested","moderately interested","moderately interested","moderately interested","very interested","","1980-01-01 00:00:00" +"1067","","","","In repository","","","","True","True","","","","","","","","True","","","","","","","","","","","","","","","","","","","5.0","","","","","True","True","True","","True","","","","","","","","","","","","","","","","","","833.29","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","True","True","","","","Anonymized","","","","","","","","","","","","True","","","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","All","","","","","","","All","All","All","","","","","","","Mostly measured","Purely generated","Yes","","95.0","","True","","","","","","","","","","Anonymized","","","","","","","Analytical methods","","","","","","","","","","","","","","","","small-angle scattering","total scattering","diffraction","","","","True","","","","","","","","","True","","","","","True","","","100 MB - 1000 MB (1 GB)","","","","True","True","True","","","","","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","not interested","1980-01-01 00:00:00" +"1068","True","True","","","","","","","","","","Guidelines / policies of publishers","","","True","","","True","True","True","","","","","","","","","","","","","","","","20.0","","True","","","","True","","","","True","True","True","","","True","","","","","","","","","","","","1069.52","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Biophysics","","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","True","","","","","Anonymized","gnuplot","Adobe Illustrator","","True","","True","True","","","","Other","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","All","All","All","","All","","","","","Some of them","Some of them","All","","None","","","","","Purely simulated","Purely generated","No","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Molecular Dynamics","Brownian Dynamics","Monte Carlo","","","","","","","","","","","","","True","","True","","True","","True","","","","True","","","True","","","","> 1 TB","","True","","True","True","True","True","True","True","True","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"1069","True","True","","","True","","","","True","True","","","","","","","","True","","","","","","","","","","","","","Institutional Repository","Zenodo","","","","10.0","","True","True","","","True","True","","","","True","True","True","","True","True","True","","","","","","","","","","1528.1","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","4 to 6 years","PhD candidate","","Yes","Apply FAIR","","True","","","Centrally (internal server)","Anonymized","Jupyter","Anonymized","","True","","","True","","","","","","True","True","","True","","","","True","True","True","","","Yes","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","openPMD","True","True","True","True","True","True","","","","All","Some of them","Some of them","Some of them","Some of them","Some of them","","","","Some of them","Some of them","None","None","Some of them","Some of them","","","","Purely simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Particle-in-Cell","","","","","","","","","","","","","","","","","True","","True","","","","","","True","True","","True","True","","","> 1 TB","","True","","True","","True","","","","","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1070","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Technical support needed","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1466.79","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","7 to 10 years","Research Associate","","Yes","Familiar with FAIR","","True","","","","IGOR","","","","True","","","True","","","","Lack of technical solutions","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Information on data collection","","","","","","","","","Some of them","","","","","","","","","Some of them","Purely measured","Purely generated","Yes","","100.0","","","True","","","","","","","","","","","True","","","","","","","","","Photoelektronenspektroskopie","NEXAFS","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Binary non-scientific formats","","1 GB - 10 GB","","","","","","","","","","","Metadata enrichment of research data","","not interested","very interested","moderately interested","moderately interested","not interested","moderately interested","1980-01-01 00:00:00" +"1072","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","921.58","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","","True","True","","","Anonymized","LabVIEW","Delphi","","","","","True","","","","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","Some of them","All","","","","","","","","None","Some of them","","","","","","","","Purely measured","Purely generated","Yes","","95.0","","True","True","","","True","","","","","","","","True","","True","","","","","","","Photonenstrueung","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","100 MB - 1000 MB (1 GB)","","","","","","","","","","","","True","moderately interested","very interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"1073","","True","","","","","","True","True","","","","","","True","True","","","","","","","","","","","","","","","Institutional Repository","","","","","5.0","","","","","","","","True","","","","","","","True","True","","","","","","","","","","","840.48","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","True","True","","","","Anonymized","Python","Anonymized","","","","","True","","","","","","","","","","","","","True","","True","Source code and scripts","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","Some of them","","","Some of them","","","","","","Some of them","","","Some of them","","","","","Purely measured","Purely generated","Yes","","95.0","","True","True","","","","True","True","","","","Anonymized","","True","","","","","","","","","Röntgenabsorptionsspektroskopie","Resonante Beugung","Reflektometrie","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","True","True","","","1 GB - 10 GB","","True","True","True","True","True","True","True","","True","","","moderately interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"1074","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","50.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1390.78","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","","Student","","Not sure","Familiar with FAIR","","True","","","","AiiDA","AiiDA","Git","","","","","","","","","","True","","True","","","True","","","","True","","","","Yes","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","","","Purely simulated","Purely generated","Not sure","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Density Functional Theory","","","","","","","","","","","","","","","","","","True","","","","","","True","True","","","True","","","","100 GB - 1000 GB (1 TB)","","","","","","","","","","","","","very interested","","","","","very interested","1980-01-01 00:00:00" +"1078","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","836.16","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","","True","","","","Jupyter","Anonymized","gnuplot","True","","","","","","","","","True","True","True","True","","","","","True","True","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","Some of them","All","","","","","","","Some of them","None","Some of them","","","","","","","","Mostly reused","Yes","","","","","","","","","","","","","","","","True","True","","","","","","","","Neutronen Spektroskopie","Physikalische Eigenschaften","Röntgen und Neutronen-Diffraktion","Mont Carlo Simulationen","","","","","","","","","","","","","","","True","","","","","","True","","","","True","","True","True","True","","","100 MB - 1000 MB (1 GB)","","True","True","True","True","True","","","True","True","","","very interested","very interested","very interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1080","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1024.11","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","1 to 3 years","Postdoc","","Yes","Not familiar with FAIR","True","","","","","Mathematica","Fortran","gnuplot","","","","","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","None","","","","","","Purely simulated","Purely generated","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Tight binding model","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","100 MB - 1000 MB (1 GB)","","","","","","","","","","","","True","moderately interested","moderately interested","moderately interested","","","","1980-01-01 00:00:00" +"1081","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1203.18","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","7 to 10 years","Research Associate","","Yes","Familiar with FAIR","","True","","","","ROOT framework","R","Excel (Spreadsheets)","","True","","","True","","","","","True","True","","True","","","","","True","True","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","All","Some of them","Some of them","Some of them","","","","","None","All","Some of them","None","Some of them","","","","","Mostly measured","Mostly generated","Yes","","90.0","","","","","","","","","","True","","","","True","","","","","","","","","Beschleunigerspektometrie","Massenspektrometie","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","True","","","","1 GB - 10 GB","","","","","","True","","True","","True","","","moderately interested","moderately interested","moderately interested","not interested","very interested","very interested","1980-01-01 00:00:00" +"1083","True","","","","","True","","True","","","","","","","","","","","True","True","","","","","","","","","","","","","","","","10.0","","","","True","True","","","","True","","","","True","True","","","","","","","","","","","","","610.76","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","True","","","","","OriginLab","","","","True","True","","","","","","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","Some of them","","Some of them","Some of them","","","","","","Some of them","","Some of them","Some of them","","","","","","Mostly measured","Purely generated","Yes","","90.0","","","","","","True","","","","","","Anonymized","","True","","","","","","","","","small angel scattering","reflectometry","neutron spectroscopy","","","","","","","","","","","","","","","","True","","","","True","","","","","","","True","","","True","","","1 GB - 10 GB","","True","True","","True","True","True","","","","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1086","True","","","","","","","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","","5.0","","","","True","True","","","","","","","","","","","","","","","","","","","","","","465.62","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Postdoc","","Yes","Familiar with FAIR","","True","","","","LabVIEW","IGOR","LaTeX","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","Some of them","Some of them","Some of them","","","","","","","Purely measured","Purely generated","Yes","","100.0","","","True","","","","","","","","","","","True","","","","","","","","","Spektroskopie","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","1 GB - 10 GB","","","","","","","","","","","","","not interested","very interested","very interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"1087","","True","","","","","","","","True","","","","True","True","","","True","","True","","","","","","","","","","","IRRMC","","","","","5.0","","","","","","","","True","True","","","","True","","","","","","","","","","","","","","442.45","Completed the survey","Anonymized","Anonymized","Matter","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","7 to 10 years","Postdoc","","Yes","Not familiar with FAIR","True","True","","","","Anonymized","Anonymized","Anonymized","","True","","True","True","","True","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","Some of them","","","","","","","Some of them","Some of them","Some of them","","","","","","Purely measured","Purely generated","","","100.0","","","True","","","","","","","","","","True","","","","","","","Proteinkristallographie","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","100 GB - 1000 GB (1 TB)","","True","","","","","","True","","","","","moderately interested","moderately interested","very interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1088","True","","","","","","True","","True","True","","","","","True","","","True","","","","","","","","","","","","","","","","","","75.0","","","","True","True","True","True","","True","True","True","","True","True","","","","","","","","","","","","","739.42","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Nanotechnology","","","","More than 10 years","Postdoc","","Yes","Not familiar with FAIR","True","","","","","Anonymized","Python","OriginLab","","True","True","True","True","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","Some of them","None","None","Some of them","Some of them","","","","","Purely measured","Purely generated","Yes","","100.0","","True","","","","","","","","","","Anonymized","","True","","True","","","","","","","SAXS","GISAXS","GIWAXS","","","","Spray","Spattering","Colloid preparation","","","","","","","","","","True","","","","True","","True","","","","True","True","","","True","","","1 GB - 10 GB","","","","True","","True","True","","True","","","","moderately interested","very interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"1089","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","433.09","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","1 to 3 years","PhD candidate","","Yes","Not familiar with FAIR","True","","","","","","","","True","","","","","","","","","True","True","True","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","None","None","None","None","","","","","Equally measured and simulated","Purely generated","Yes","","0.0","","","","","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","True","True","","","","True","","","I don't know","","","","","","","","","","","","True","not interested","not interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"1094","True","","","","","True","","","","True","","","True","","","","","","","","","","","","","","","","","","","","","","","85.0","","","","","","True","","","True","True","","","","","","","","","","","","","","","","","547.43","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Biophysics","","","","1 to 3 years","PhD candidate","","No","Familiar with FAIR","True","","","","","Python","Anonymized","Fiji","","","","True","True","","","","","","True","True","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","Some of them","All","","","","","","","","None","None","","","","","","","Mostly measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","True","True","","True","","","","Confocal Microscopy","TIRF","Ultrafast imaging 2000 fps","PIV ","Own python codes (cross corolation)","Image proccessing using sci py skiimage ","","","","SLE","CAD/CAM","","","","","","","","","","","","","","","True","","","","","","True","True","True","","True","","","100 GB - 1000 GB (1 TB)","","","","","True","True","True","","","True","","","moderately interested","very interested","very interested","moderately interested","","moderately interested","1980-01-01 00:00:00" +"1096","True","","","","","","","","True","","","","True","","","","","","","","","","","","","","","","","","","","","","","50.0","","","","True","True","","","","","","","","","","","True","","","","","","","","","","","551.1","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","","X-ray Imaging","","","Less than 1 year","PhD candidate","","No","Not familiar with FAIR","","True","","","","Anonymized","Anonymized","Anonymized","","","","","True","","","","","","","","","","","","","","True","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","All","","","","All","","","","","Some of them","","","","Some of them","","","","","Mostly measured","Equally generated and reused","Yes","","100.0","","True","","","","","","","","","","","True","","","","","","","Three-Dimensional X-ray Diffraction","Ptychography","Tomography","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","100 GB - 1000 GB (1 TB)","","","True","","True","","True","","","","","","moderately interested","moderately interested","moderately interested","very interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1098","True","","","","True","","","","","True","","","","","True","True","True","","","","","","","","","","","","","","","","","","","5.0","","","","True","True","True","True","True","True","True","","True","","True","","","","","","","","","","","","","1721.4","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","7 to 10 years","Research Associate","","Yes","Familiar with FAIR","True","True","","","","LabVIEW","Anonymized","Python","","True","","True","","","","","","True","True","True","True","","","","","True","","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","Some of them","Some of them","Some of them","","","","","","Some of them","Some of them","Some of them","Some of them","","","","","","Mostly measured","Mostly generated","Yes","","95.0","","","True","","","","","","","","","","","True","True","True","","","","","","","Röntgenabsorptionsspektroskopie","Massenspektroskopie","","quantenchemische Rechnungen - ORCA","","","Probenpräparation durch Magnetronsputtering","Probenpräparation durch Electrospray Ionisation","","","","","","","","","","","","","","","","","True","","","","","","","","","","","10 GB - 100 GB","","","","","True","True","","","","True","","","not interested","very interested","moderately interested","not interested","not interested","moderately interested","1980-01-01 00:00:00" +"1099","True","","","","True","True","","","","True","","","","","True","","","","","","","","","","","","","","","","","","","","","5.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","729.61","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","","Accelerator physics","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","","","","True","","MATLAB / Simulink","Excel (Spreadsheets)","Mathematica","","True","","","","","","","","True","True","","","","","","","","True","True","Digital system","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","","","","","","","","","","","","","","","","","","","Equally measured and simulated","Mostly generated","Yes","","5.0","","","","","","","True","True","","","","","True","","True","","","","","Filtering","Deconvolution","","","","","ODE","","","","","","","","","","","","","","","","","","","True","","","","","True","True","True","","","","","","100 MB - 1000 MB (1 GB)","","","","","","","","","True","","","","moderately interested","very interested","moderately interested","","","","1980-01-01 00:00:00" +"1101","","True","","","True","","","","True","True","","","","","","True","","True","","","","","","","","","","","","","","","","","","90.0","","True","True","True","True","True","","True","True","True","True","True","True","True","True","","True","","","","","","","","","","534.78","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","7 to 10 years","Postdoc","","No","Not familiar with FAIR","True","True","","","","","","","True","","","","","","","","","True","","True","True","True","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","","","All","All","All","All","All","Some of them","","","","None","None","None","None","None","None","","","","Purely simulated","Purely reused","Not sure","","","","","","","","","","","","","","","True","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","True","","","","True","","","True","True","","","100 MB - 1000 MB (1 GB)","","True","True","True","True","True","True","","True","True","","","very interested","very interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"1104","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1746.06","Completed the survey","Anonymized","Anonymized","Matter","Chemistry","","","","","","Physical Chemistry","","","","","","","","","","","","","","","","More than 10 years","Postdoc","","Yes","Familiar with FAIR","True","","","","","Anonymized","OriginLab","","","","","","","","","True","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","Some of them","","Some of them","","All","","","","","None","","Some of them","","Some of them","","","","","Purely measured","Purely generated","Yes","","90.0","","","True","","","","","","","","","","","True","","","","","","","","","Resonant inelastic X-ray spectroscoy","X-ray absorption spectroscopy","X-ray photoemission spectroscopy","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","True","","","","10 GB - 100 GB","","","","True","","True","","","True","True","","","very interested","moderately interested","moderately interested","moderately interested","very interested","not interested","1980-01-01 00:00:00" +"1107","True","","","","True","True","","","","","","Reusability","","","","","True","","True","","","","","","","","","","","","","","","","","60.0","","","","True","True","True","","","True","True","True","","True","True","","","","","","","","","","","","","2032.21","Completed the survey","Anonymized","Anonymized","Matter","Engineering Science","","","","","","","","","","Materials Engineering","","","","","","","","","","","","1 to 3 years","PhD candidate","","Yes","Not familiar with FAIR","True","True","","","","OriginLab","Word","Excel (Spreadsheets)","","","","","","","","","","True","True","","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","None","None","None","None","None","","","","","Purely measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","True","True","","","","","","SEM","Laser Microscopy","AFM","Indentation","Bendingtest","FIB","","","","","","","","","","","","","","","","","","","","True","","True","","","","","True","True","True","","","","I don't know","","","True","True","","True","","True","","True","","","very interested","very interested","not interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"1110","True","","","","","","","True","True","True","","","","","","True","","","True","","","","","","","","","","","","","","","","","10.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","950.66","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","","Quantum Information","","","1 to 3 years","Research Associate","","Yes","Familiar with FAIR","True","True","","","","Python","Anonymized","Java","","","True","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","None","Some of them","None","","","","","","","Equally measured and simulated","Purely generated","Not sure","","0.0","","","","","","","","","","","","","","True","True","","","","","","","","Spectroscopy","RF measurements","","Numeric models","","","","","","","","","","","","","","","","","True","True","True","","","","","","True","","","","True","","","100 MB - 1000 MB (1 GB)","","","","","","","True","True","True","True","","","very interested","moderately interested","moderately interested","very interested","very interested","not interested","1980-01-01 00:00:00" +"1111","True","","","","","","","","True","","","","","","","","","True","","","","","","","","","","","","","","","","","","40.0","","","","True","True","","","","True","True","True","","True","","","","","","","","","","","","","","1022.67","Completed the survey","Anonymized","Anonymized","Matter","Chemistry","","","","","","","","","","","","","","","","","","","","","","7 to 10 years","Technical Staff","Technical Staff","Yes","Not familiar with FAIR","True","True","","","","Anonymized","Office Software (unspecified)","","","","","True","True","","","","","True","True","True","True","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","Some of them","Some of them","Some of them","","","","","","None","None","None","None","","","","","","Purely measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","True","True","","","","","","Rasterelektronenmikroskopie","Lichtmikroskopie","Transmissionselektronenmikroskopie","Energiedispersive Röntgenspektroskopie","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","True","","","","","","1 GB - 10 GB","","","","","","","","","","True","","","moderately interested","very interested","very interested","","","","1980-01-01 00:00:00" +"1112","True","","","","","True","","","True","True","","","True","","","","","","","","","","","","","","","","","","","","","","","5.0","","","","","True","True","","","True","","","","True","","","","","","","","","","","","","","654.52","Completed the survey","Anonymized","Anonymized","Matter","Engineering Science","","","","","","","","","","Process Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Not familiar with FAIR","","True","","","","COMSOL Multiphysics","OpenFOAM","","True","","","","","","","","","True","True","True","","","","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","All","All","All","","","","","","","","","","","","","","Purely simulated","","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","CFD","","","","","","","","","","","","","","","","","True","","","","True","","","","True","","","","True","","","1 GB - 10 GB","","True","","","","","","","","","","","moderately interested","moderately interested","moderately interested","","very interested","moderately interested","1980-01-01 00:00:00" +"1113","","True","","","True","","","True","True","","","","","","True","","True","True","True","True","","","","","","","","","","","Institutional Repository","","","","","40.0","","","","True","True","","","","","","","","","","","","","","","","","","","","","","817.1","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","","Angewandte Kernphysik","","","More than 10 years","Research Associate","","Yes","Familiar with FAIR","","True","True","","","Excel (Spreadsheets)","Anonymized","Anonymized","","True","","True","True","True","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","True","","","","","","","","","","","","","None","","","","","None","","","","Purely measured","Mostly generated","Yes","","100.0","","","","","","","","","","","","Anonymized","","True","","","","","","","","","Accelerator Mass Spectrometry","","","","","","","","","","","","","","","","","","","","True","","","","True","True","","","","True","","","","","","1 GB - 10 GB","","","True","","True","True","True","True","","True","","","","moderately interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"1116","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1031.28","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","","Beschleuniger","","","More than 10 years","Research Associate","","Yes","Familiar with FAIR","","True","","","","ZEMAX","Excel (Spreadsheets)","OriginLab","","","True","True","","","","","","","","","","","","","","True","True","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","Some of them","","","Some of them","","","","","","None","","","Some of them","","","","","","Mostly measured","Purely generated","Yes","","5.0","","","","","","","True","True","","","","","True","","True","","","","Recordings","Kamera snapshots","","","","","","Ray tracing","","","","","","","","","Aufnahme von Messreihen","","","","","","","","True","","True","","True","","","True","","True","","True","","","","1 GB - 10 GB","","True","","","True","True","True","","True","True","","","very interested","very interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"1118","","","True","","","True","True","","True","","","","True","","","","","","","","","","","","","","","","","","","","","","","80.0","","","","True","True","","","","True","True","","True","","","","","","","","","","","","","","","501.08","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Biophysics","","","","1 to 3 years","PhD candidate","","Yes","Not familiar with FAIR","True","","","","","Python","Excel (Spreadsheets)","FLUKA","","","","True","","","","","","","","","","","","","","True","","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","All","","Some of them","","","","","","","","","","","","","","","","Equally measured and simulated","Purely generated","Not sure","","0.0","","","","","","","","","","","","","","","True","True","","","","","","","","","","FLUKA","","","Excel","","","","","","","","","","","","","","","","True","True","","","","","True","True","True","","","","","I don't know","","","","","","True","","","","True","","","not interested","very interested","very interested","not interested","not interested","very interested","1980-01-01 00:00:00" +"1119","","","","","","","","","","","","","","","True","True","True","","","","","","","","","","","","","","","","","","","10.0","","","","","","","True","True","","","","","","","","True","","","","","","","","","","","685.01","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","4 to 6 years","PhD candidate","","No","Not familiar with FAIR","","True","","","","Anonymized","ROOT framework","","","True","True","True","","","","","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","Some of them","","","All","","","","","","Some of them","","","Some of them","","","","","Mostly simulated","Purely generated","Not sure","","0.0","","","","","","","","","","","","","","True","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","","","True","","","","1 GB - 10 GB","","","","","True","True","","","True","True","","","very interested","moderately interested","moderately interested","moderately interested","very interested","not interested","1980-01-01 00:00:00" +"1120","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","2133.5","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","7 to 10 years","Postdoc","","Yes","","True","True","","","","gcc","Python","Anonymized","True","","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","","","Some of them","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","","","","","","","","","Purely simulated","Purely generated","No","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Output from numerical simulations","Postprocessing of the results of the numerical simulations","Plots of the final results","","","","","","","","","","","","","True","","True","","True","True","True","","","True","True","","True","True","True","","","> 1 TB","","True","","","","","","True","","","","","moderately interested","very interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"1123","True","True","","","True","True","","","","True","","","","True","True","True","","True","True","","","","","","","","","","","","Gitlab / GitHub","Gitlab / GitHub","","","","10.0","","True","","True","True","True","True","True","True","True","True","True","True","True","","","","","","","","","","","","","946.09","Completed the survey","Anonymized","Anonymized","Matter","Chemistry","","","","","","Physical Chemistry","","","","","","","","","","","","","","","","7 to 10 years","Postdoc","","Yes","Not familiar with FAIR","","True","","","","Python","OriginLab","LabVIEW","","True","","True","True","True","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","True","","Some of them","Some of them","Some of them","Some of them","Some of them","","","Some of them","","Some of them","Some of them","Some of them","Some of them","Some of them","","","Some of them","","Purely measured","Purely generated","Yes","","95.0","","True","True","","","True","","","","","","","True","True","True","True","","","","STXM","TEM","SEM","SAXS","SANS","XAS","DFT (ORCA)","","","Nasschemische Mikrowellensynthese","Sputtering","","","","","","","","","","","True","","","","True","","True","True","","","True","","True","","True","","","10 GB - 100 GB","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","moderately interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"1126","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","True","No value to others","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","432.26","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","","True","True","","","Linux","Anonymized","LaTeX","","True","True","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","All","","All","","All","","","","","None","","None","","None","","","","","Purely simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Monte Carlo Modelle","Numerische Lösungen","","","","","","","","","","","","","","","","True","","True","True","True","","","","True","True","","","True","","","100 GB - 1000 GB (1 TB)","","","","","True","True","True","","True","","","","moderately interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"1127","","True","","","","","","True","True","","","","True","","","","","","","","","","","","","","","","","","Institutional Repository","","","","","20.0","","True","","","True","True","","True","True","True","","","","","","","","","","","","","","","","","462.05","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Nanotechnology","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","True","True","","","","Fiji","Anonymized","Python","","True","","","True","","","","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","Some of them","None","None","","","","","","","Purely measured","Mostly generated","Yes","","90.0","","","","","","","","","","","","Anonymized","True","True","","","","","","Helium Ionen Mikroskopie","Elektronenmikroskopie","Rasterkraftmethoden","SIMS","SAM","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","True","","","","< 100 MB","","True","","True","True","True","","","True","True","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1128","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","50.0","","","","","","","","","","","","","True","True","","","","","","","","","","","","","1978.29","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Soft Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","True","True","True","","","Anonymized","Anonymized","OriginLab","","True","","","True","","","True","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","None","","","","","","Purely measured","Mostly generated","Yes","","75.0","","","","","","","","","","","","Anonymized","","True","","","","","","","","","neutron scattering spectroscopy","PFG NMR","small angle X-ray scattering","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","","< 100 MB","","","","","True","","True","True","","True","","","very interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1130","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","50.0","","","","","","","True","True","","","","","True","","","","","","","","","","","","","","441.54","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","","Multiple areas crossing over physics, biology and material science","","","More than 10 years","Principal Investigator","","No","Familiar with FAIR","True","True","True","","","gcc","Python","IDL","","","","","","","","","Lack of technical solutions","","","","","","","","","","True","True","Digital text","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","Mostly measured","Equally generated and reused","","","100.0","","True","","","","","","True","","","","Anonymized","True","True","","","","","","Crystallography/diffraction/MX","Coherent imaging/diffraction","Tomography/ptychography","XES","XAS","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","True","","","> 1 TB","","True","","True","True","True","True","True","","","","","","","","","","","1980-01-01 00:00:00" +"1132","True","","","","True","True","","","True","","","","","","True","True","","","","","","","","","","","","","","","","","","","","5.0","","","","True","True","True","True","True","True","","","","","","","","","","","","","","","","","","875.78","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","4 to 6 years","Postdoc","","Yes","Not familiar with FAIR","","True","","","","Python","ImageJ","Anonymized","","","True","","","","","","","","","","","","","","","","True","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","All","Some of them","Some of them","","","","","","Some of them","All","None","None","","","","","","","Mostly generated","Yes","","","","","","","","","","","","","","","True","","True","","","","","X-ray Coherent Imaging","Ptychography","X-ray Scanning Microscopy","","","","Wavepropagation","Raytracing","","","","","","","","","","","","","","","","True","","True","True","","","","","True","","","True","True","","","100 GB - 1000 GB (1 TB)","","","","","","","","True","True","True","","","very interested","moderately interested","not interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1134","","True","","","True","True","","","True","","","","True","","","","","","","","","","","","","","","","","","RCSB PDB","","","","","50.0","","True","True","True","True","True","True","True","True","True","True","True","True","","","","","","","","","","","","","","1259.3","Completed the survey","Anonymized","Anonymized","Matter","Life Science","","","","","","","","","","","","","Biochemie","","","","","","","","","More than 10 years","Postdoc","","Yes","Apply FAIR","True","True","","","","Anonymized","Anonymized","Anonymized","","","","","True","","","","","","","","","","","","","True","","True","Digital system","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","Some of them","Some of them","Some of them","","","","","","None","Some of them","Some of them","Some of them","","","","","","Purely measured","Mostly generated","Not sure","","100.0","","True","","","","","","True","","","","","True","","","","","","","Röntgendiffraktion","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","","","","True","Plain text","","I don't know","","","","","True","","","","True","","","","moderately interested","","moderately interested","very interested","","","1980-01-01 00:00:00" +"1136","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","True","No value to others","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","650.26","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","","True","","","","MATLAB / Simulink","Python","","","True","","","True","","True","","Heterogeneous workflows complicate standardized solutions","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Purely measured","Purely generated","Yes","","95.0","","True","","","","","","","","","","","","True","","","","","","","","","x-ray diffraction","x-ray photoelecectron spectroscopy","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","True","","","1 GB - 10 GB","","True","","True","True","True","","True","","True","","","moderately interested","moderately interested","not interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"1138","","True","","","True","True","","","","True","","","","","","True","","True","","","","","","","","","","","","","Institutional Repository","CDMS","","","","30.0","","True","","True","True","True","True","","True","True","","","","","","","","","","","","","","","","","1077.08","Completed the survey","Anonymized","Anonymized","Matter","Chemistry","","","","","","Physical Chemistry","","","","","","","","","","","","","","","","4 to 6 years","Postdoc","","","Not familiar with FAIR","True","True","","","","Anonymized","Anonymized","OriginLab","True","","","","","","","","","","","","","","","","","True","True","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","Some of them","","","","","","","All","Some of them","None","","","","","","","Mostly measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","","True","True","","","","","","","","spectroscopy","","","quantum chemical calculations","","","","","","","","","","","","","","","True","","","","True","","True","","","","True","True","","True","","","","< 100 MB","","","","","","","","","","","","True","not interested","moderately interested","moderately interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"1143","True","","","","","True","","True","True","","","","","","True","True","True","True","True","True","","","","","","","","","","","","","","","","25.0","","","True","","","True","True","","True","True","","","","","","","","","","","","","","","","","1226.33","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","More than 10 years","Postdoc","","Yes","Not familiar with FAIR","","True","","","","Python","OriginLab","ROOT framework","","True","True","True","True","","","","","","","","","","","","","","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","Some of them","Some of them","Some of them","","","","","","","Mostly measured","Mostly generated","Yes","","90.0","","","","","","","True","True","","","","Anonymized","True","True","","","","","","coherent diffraction imaging (CDI)","optical microscopy","","Ion and electron time of flight (TOF)","Velocity map imaging (VMI)","COLTRIMS / REMI","","","","","","","","","","","","","","","","True","","True","","True","","True","","","","True","True","True","True","True","","","> 1 TB","","","","True","True","True","True","","True","True","","","moderately interested","very interested","moderately interested","very interested","very interested","","1980-01-01 00:00:00" +"1144","","","","Other","True","","","","","True","","","","","True","True","True","","","True","","","","","","","","","","","","","","","","5.0","","","","","True","","","","True","True","","True","","True","","","","","","","","","","","","","967.93","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","4 to 6 years","PhD candidate","","Yes","Familiar with FAIR","","True","","","","OriginLab","LabVIEW","Python","","","True","","","","","","","","","","","","","","","","True","","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","None","All","Some of them","None","","","","","","Mostly measured","Purely generated","Yes","","0.0","","","","","","","","","","","","","True","True","True","","","","","Beam-characterization of electron-sources using screens & cameras","THz source characterization","Home-built electron energy spectrometers","Pump-probe experiments","Home-built optical spectrometers","Home-built electron energy spectrometers","Self-developed Python code","CST","ASTRA","","","","","","","","","","","","","","","True","","True","True","True","","","True","True","","","","","","","100 MB - 1000 MB (1 GB)","","True","","","True","True","","","True","","","","very interested","very interested","very interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"1146","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1990.34","Completed the survey","Anonymized","Anonymized","Matter","","material science","","","","","","","","","","","","","","","","","","","","","More than 10 years","Research Associate","Research Associate","Yes","Not familiar with FAIR","","True","","","","Python","Office Software (unspecified)","","True","","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","Some of them","Some of them","None","","","","","Mostly measured","Mostly generated","Yes","","80.0","","True","","","","","","","","","","","","True","","True","","","","","","","scattereing and diffraction","spectroscopy","","","","","thin film deposition","wet chemistry","","","","","","","","","","","","","True","","True","","True","","","","True","True","","","","","","10 GB - 100 GB","","","","True","True","True","","","True","True","","","very interested","very interested","very interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"1147","True","","","","True","True","","","True","","","","","","","","True","True","True","True","","","","","","","","","","","","","","","","30.0","","","","True","True","","True","","","","","","","True","","","","","","","","","","","","","443.33","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","","True","","","","Jupyter","IGOR","Python","","True","","","True","","","","","","True","True","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","Some of them","All","All","","","","","","Some of them","Some of them","Some of them","All","","","","","","Purely measured","Purely generated","Yes","","100.0","","True","True","","","","True","True","","","","","","True","True","","","","","","","","XAS","RIXS","XPS","Numeric model","Quantum chemistry","","","","","","","","","","","","","","","","True","","","","","","","True","True","","","","True","","","10 GB - 100 GB","","True","","True","True","True","","True","True","True","","","very interested","very interested","moderately interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1150","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","10596.1","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","7 to 10 years","Postdoc","","Yes","Familiar with FAIR","True","True","","","","Anonymized","Python","MATLAB / Simulink","","True","True","","True","","","","Heterogeneous workflows complicate standardized solutions","","","","","","","","","","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","Data processing and analysis","Some of them","All","All","All","All","","","","All","None","All","Some of them","Some of them","Some of them","","","","Some of them","Mostly measured","Purely generated","Yes","","10.0","","","","","","","True","","","","","Anonymized","True","True","True","","","","","Velocity map imaging (VMI)","Computing the covariance images/maps between VMI and mass spectrum","","Photoelectron spectroscopy","Mass spectrometry","Time resolved by pump--probe delay (electron and mass spectroscopies)","Electron or ion trajectories for design/evaluation of electrostatic spectrometers","Fitting/comparing analytic curve models to pump--probe scan data","","","","","","","","","","","","","","","","True","","True","","True","","","","True","True","","True","True","Image formats","","10 GB - 100 GB","","","","True","","True","","","True","True","Financial resources for RDM","","moderately interested","very interested","moderately interested","very interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1151","","True","","","True","True","True","","","","","","","","True","True","","True","","","","","","","","","","","","","Zenodo","","","","","10.0","","","","","True","True","True","True","True","True","","","","","","","","","","","","","","","","","605.18","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","True","","","","","Anonymized","Anonymized","Anonymized","","True","True","True","True","","","True","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","None","Some of them","Some of them","","","","","","","Equally measured and simulated","Mostly generated","Yes","","95.0","","True","","","","","","","","","","Anonymized","","True","True","","","","","","","","Quasielastic Neutron Scattering","Diffraction","","Molecular Dynamics","Monte Carlo","","","","","","","","","","","","","","","","True","","True","","True","","","True","True","","","","True","","","1 GB - 10 GB","","True","True","","True","","","","","","","","not interested","moderately interested","very interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"1152","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","441.32","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Soft Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","","True","","","","MATLAB / Simulink","Python","","","True","True","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","Some of them","","Some of them","","","","","","","Some of them","","Some of them","","","","","","","Mostly measured","Purely generated","Yes","","95.0","","True","","","","","","True","","","","Anonymized","True","True","","","","","","CDI","","","XPCS","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","True","True","","","100 GB - 1000 GB (1 TB)","","","","True","True","","","","","","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1153","True","","","","","True","","","","True","","","","","True","True","","True","","","","","","","","","","","","","","","","","","80.0","","","","","","","","","True","True","True","","True","True","","","","","","","","","","","","","790.65","Completed the survey","Anonymized","Anonymized","Matter","Earth Science","","","","","","","","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Not familiar with FAIR","True","True","","","","Anonymized","Anonymized","","","True","","","True","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","All","","","","","","","None","None","None","","","","","Purely measured","Purely generated","Yes","","100.0","","True","","","","","","True","","","","","True","","","","","","Analytical methods","PCI","CDI","","","","","","","","","","","","","","single crystal","powder","PDF","","","","","","True","","True","","","","","","","True","","True","True","","","100 GB - 1000 GB (1 TB)","","True","True","True","True","True","True","","","True","","","","very interested","moderately interested","not interested","not interested","very interested","1980-01-01 00:00:00" +"1154","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","482.47","Completed the survey","Anonymized","Anonymized","Matter","Chemistry","","","","","","Physical Chemistry","","","","","","","","","","","","","","","","More than 10 years","Research Associate","Research Associate","Yes","Not familiar with FAIR","True","","True","","","Python","Anonymized","LaTeX","","True","True","True","True","","","True","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","None","Some of them","Some of them","","","","","","","Purely measured","Purely generated","Yes","","100.0","","","True","","","","","","","","","","","True","","","","","","","","","NEXAFS","RIXS","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","100 MB - 1000 MB (1 GB)","","","","True","","","","True","True","True","","","very interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"1155","True","","","","True","","","True","True","","","","","","","","","True","","True","","","","","","","","","","","","","","","","5.0","","True","","True","","True","True","","","","","","True","True","","","","","","","","","","","","","360.27","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","7 to 10 years","Postdoc","","Yes","Familiar with FAIR","","True","","","","Python","Anonymized","Anonymized","","","True","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","All","All","","All","","","","","","All","All","","All","","","","","","Purely measured","Mostly reused","Yes","","100.0","","True","","","","","","","","","","Anonymized","True","","","","","","","Full-field X-ray tomography","Transmission X-ray microscopy","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","True","True","","","100 GB - 1000 GB (1 TB)","","True","True","True","","True","","True","","","","","moderately interested","very interested","not interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1156","True","","","","True","","","","True","True","","","True","","","","","","","","","","","","","","","","","","","","","","","30.0","","","","True","True","True","","","","","","","True","True","","True","","","","","","","","","","","980.62","Completed the survey","Anonymized","Anonymized","Matter","Earth Science","","","","","","","","","","","","","","","","","","","","","","7 to 10 years","Postdoc","","Yes","Familiar with FAIR","True","","","","","Python","Anonymized","Anonymized","","True","True","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","","","","All","All","","All","All","","","","","None","Some of them","","Some of them","Some of them","","","","","Equally measured and simulated","Equally generated and reused","Yes","","0.0","","","","","","","","","","","","","","","True","","","","","","","","","","","numerische Modelle","thermodynamische Berechnungen ","","","","","","","","","","","","","","","","True","","True","","True","","","","True","True","","","","","","100 MB - 1000 MB (1 GB)","","","","","","True","","","True","True","","","moderately interested","moderately interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"1159","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","4501.73","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","","Accelerator physics","","","1 to 3 years","PhD candidate","","Yes","Familiar with FAIR","","True","","","","Anonymized","Anonymized","","","True","","","","","","","","","","","","","","","","True","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","Some of them","Some of them","","Some of them","","","","","","All","Some of them","","None","","","","","Mostly measured","Mostly generated","Not sure","","35.0","","","","","","","","","","","","Anonymized","True","","True","","","","","Electron imaging on screen","","","","","","ASTRA simulations","Geneis 1.3 simulations","","","","","","","","","","","","","","","","True","","True","","True","","","","True","","","True","True","","","100 MB - 1000 MB (1 GB)","","True","","True","","True","","True","True","","","","moderately interested","very interested","moderately interested","","very interested","moderately interested","1980-01-01 00:00:00" +"1161","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","375.06","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","4 to 6 years","","","","Familiar with FAIR","True","True","","","","IGOR","","","","True","","True","True","","","","","","","","","","","","","True","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","None","All","Some of them","","","","","","","None","None","Some of them","","","","","","","Purely measured","Purely generated","Yes","","100.0","","","True","","","","","","","","","","","True","","","","","","","","","XPS","ARPES","NEXAFS","","","","","","","","","","","","","","","","True","","","","True","","True","","","","","","","","True","","","10 GB - 100 GB","","","","True","True","True","True","","","","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"1165","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","30.0","","","","","","","","","","","","","","","","","","","","","","","","","","","150.66","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","4 to 6 years","Postdoc","","Yes","Apply FAIR","","","","","","Python","Python","ROOT framework","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Equally measured and simulated","Mostly generated","","","95.0","True","","","","","","","","","","","","True","","True","","","","","ATLAS detector","","","","","","MC simulation","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","True","Other","","> 1 TB","","","","","","","","","","","","","","","","","","","1980-01-01 00:00:00" +"1166","True","True","","","True","","","","True","True","","","","","True","","","True","True","","","","","","","","","","","","","","","","","10.0","","True","True","True","True","True","True","True","True","True","True","True","True","True","True","True","","","","","","","","","","","388.86","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Astrophysics and Astronomy","","","","More than 10 years","Postdoc","","Yes","Apply FAIR","","True","True","","","Python","ROOT framework","Anonymized","","True","","","True","","","","","True","True","","","","","","","","True","","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","","","Yes","","","","","","","","","","","","","","","True","True","True","True","True","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","True","True","","","","True","","","True","True","","","1 GB - 10 GB","","True","True","True","","","","","True","","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1167","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","547.43","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","More than 10 years","Postdoc","","Yes","Not familiar with FAIR","","True","True","","","Git","LabVIEW","Anonymized","","","","","","","","True","","","","True","","","","","","","","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","True","","All","All","All","All","All","All","","All","","None","None","None","None","None","None","","None","","Mostly measured","Mostly reused","Yes","","95.0","True","","","","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","True","","","","True","True","","True","","","","> 1 TB","","True","","True","","True","","True","","","","","moderately interested","moderately interested","very interested","moderately interested","not interested","not interested","1980-01-01 00:00:00" +"1168","True","","","","True","True","","","","","","","","","","","True","True","","","Legal / ethical concerns","","","","","","","","","","","","","","","5.0","","","","","","","","","","","","","","","","","","","","","","","","","","True","1334.89","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","7 to 10 years","Postdoc","","Yes","Not familiar with FAIR","","True","","","","ROOT framework","Anonymized","Python","","True","True","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","All","All","All","All","","","","","","Mostly measured","Mostly reused","Yes","","95.0","True","","","","","","","","","","","","","True","True","","","","","","","","Particle Detectors","","","Monte Carlo Simulations","","","","","","","","","","","","","","","","","True","","","","True","","","True","True","","","True","True","","","> 1 TB","","True","","","","","","True","True","","","","not interested","not interested","very interested","very interested","not interested","very interested","1980-01-01 00:00:00" +"1169","True","True","","","True","","","True","True","","","","","","True","","","","","","","","","","","","","","","","HEPData","","","","","50.0","","","","","","True","True","True","True","True","","","True","","","","","","","","","","","","","","468.42","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","7 to 10 years","Postdoc","","Yes","Familiar with FAIR","True","True","","","","ROOT framework","Python","Anonymized","","True","","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","Some of them","","","","","","","All","All","Some of them","","","","","","Mostly simulated","Equally generated and reused","Not sure","","100.0","True","","","","","","","","","","","","","","True","","","","","","","","","","","Particle collisions","Monte Carlo simulations","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","Other","","> 1 TB","","True","True","True","","","","","","","","","not interested","moderately interested","not interested","not interested","not interested","moderately interested","1980-01-01 00:00:00" +"1172","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","No value to others","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","581.03","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","4 to 6 years","Postdoc","","Yes","Not familiar with FAIR","True","True","","","","ROOT framework","Anonymized","Anonymized","","True","True","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","True","","Some of them","","All","All","All","","","Some of them","","Some of them","","None","None","Some of them","","","Some of them","","Equally measured and simulated","Purely generated","Not sure","","10.0","","","","","","","","","","","","Anonymized","","True","True","","","","","","","","Particle interactions in sensors","","","GEANT4-based simulations of particle interactions","MOnte Carlo methods","","","","","","","","","","","","","","","","True","","True","","True","","","True","True","True","","True","True","","","100 GB - 1000 GB (1 TB)","","True","","True","True","True","True","","True","True","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1175","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","447.84","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","More than 10 years","Postdoc","","Yes","Not familiar with FAIR","True","True","","","","Python","","","","","True","","","","","","","","","","","","","","","","","","","True","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Mostly measured","Purely generated","Yes","","100.0","","True","True","","","","","","","","","","","True","","","","","","","","","Röntgenspektroskopie","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","True","","","","10 GB - 100 GB","","","","","","","True","","","","","","moderately interested","moderately interested","moderately interested","moderately interested","very interested","not interested","1980-01-01 00:00:00" +"1177","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","Legal / ethical concerns","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","918.39","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","4 to 6 years","Postdoc","","No","Not familiar with FAIR","","","True","","","ROOT framework","Python","Anonymized","","","","","","","","True","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Equally measured and simulated","Purely reused","Yes","","100.0","","","","","","","","","","","","Anonymized","","","","","","","Other","","","","","","","","","","","","","","","","Electron positron collision","Simulation","","","","","","","","","","","","","","","","","","","","Other","","> 1 TB","","","","","","","","","","","Technical aspects of RDM","","moderately interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"1178","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","594.21","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Familiar with FAIR","","True","","","","IGOR","Anonymized","Anonymized","","True","","","","","","","Lack of technical solutions","","","","","","","","","","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","Information on data collection","Some of them","Some of them","Some of them","","","","","","All","Some of them","Some of them","Some of them","","","","","","All","Mostly measured","Purely generated","Yes","","100.0","","","True","","","","","","","","","","","True","","","","","","","","","XPS","NEXAFS","time resolved XPS","","","","","","","","","","","","","","","","True","","True","","","","True","","","True","","","","","","","","100 GB - 1000 GB (1 TB)","","True","","True","True","True","","True","True","True","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"1180","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1637.55","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","Apply FAIR","","True","","","","IGOR","Python","","","True","True","","True","True","True","True","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","None","Some of them","All","All","All","","","","","None","Some of them","All","All","All","","","","","Mostly measured","Purely generated","Yes","","95.0","","","True","","","","","","","","","","True","","True","","","","","Photoemissions Elektronen Mikroskopie","","","","","","Boris computational spintronics","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","","True","","","10 GB - 100 GB","","True","","","","True","","True","","True","","","moderately interested","very interested","not interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"1183","","","","Other","True","","","True","","True","","","","","True","","True","True","","True","Lack of time / personnel","","","","","","","","","","","","","","","5.0","","","","","","True","True","True","True","True","True","","True","","True","","","","","","","","","","","","664.62","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","More than 10 years","Principal Investigator","","No","Familiar with FAIR","","True","True","","Locally","ROOT framework","Anonymized","Anonymized","","True","True","","True","","","","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","Some of them","Some of them","All","All","","","","","Mostly measured","Mostly generated","Yes","","100.0","","","","","","","","","","True","","","","True","","","","","","","","","Spektroskopie","Teilchenverfolgung","Simulation der Daten","","","","","","","","","","","","","","","","","","True","","","True","True","","","","True","","","","","Other","","> 1 TB","","","","","True","True","","True","","True","","","moderately interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"1184","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1357.88","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Research Associate","","Yes","Familiar with FAIR","True","True","True","","","Delphi","Anonymized","LabVIEW","","","","","","","","","Lack of technical solutions","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","True","","","","","Some of them","Some of them","None","","All","","","","","Some of them","Some of them","None","","All","","","","","Purely measured","Mostly generated","Yes","","10.0","","","True","","","True","","","","","","Anonymized","","True","","","","","","","","","Wärmekapazität","Magnetokalorischer Effekt","Neutronenstreuung","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","","","","","","< 100 MB","","True","","True","True","True","True","True","True","True","","","moderately interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"1185","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","2511.89","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","","Accelerator Physics","","","More than 10 years","Postdoc","","Not sure","Familiar with FAIR","True","","","","","Python","LabVIEW","","","","True","True","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","None","Some of them","None","","","","","","","None","None","None","","","","","","","Equally measured and simulated","Mostly generated","Yes","","100.0","","","True","","","","","","","","","","","","True","","","","Other","","","","","","","Python Models","","","","","","","","","Magnetic Field Measurement 2D and 3D","","","","","","","","","","","","True","","","","True","","","True","True","","","10 GB - 100 GB","","True","","True","True","True","","True","","","","","moderately interested","very interested","very interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"1186","True","","","","","True","True","True","","","","","","","True","True","","","","True","","","","","","","","","","","","","","","","20.0","","","","","True","","","","True","True","True","","","True","","","","","","","","","","","","","4119.5","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","More than 10 years","Research Associate","","Yes","Not familiar with FAIR","True","","","","","LabVIEW","ROOT framework","Anonymized","","True","","True","True","","","True","","True","True","True","True","","","","","True","","True","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","Some of them","","All","All","Some of them","","","","","","","All","Some of them","","","","","","Mostly measured","Mostly generated","Yes","","5.0","","","","","","","","","","True","True","","","True","True","","","","","","","","Spektroskopie","","","Monte Carlo","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","1 GB - 10 GB","","True","","","","True","","","","","","","","very interested","moderately interested","","","moderately interested","1980-01-01 00:00:00" +"1187","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","603.01","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","More than 10 years","Research Associate","Research Associate","Yes","Not familiar with FAIR","True","","","","","ROOT framework","Anonymized","","","","","","","","","True","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","Some of them","","Some of them","","","","","","","None","","None","","","","","Purely measured","Purely generated","Not sure","","0.0","","","","","","","","","","","","","","","","","","","Other","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","I don't know","","","","","","","","","","","","True","not interested","not interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"1191","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","374.35","Completed the survey","Anonymized","Anonymized","Matter","Engineering Science","","","","","","","","","","Electrical Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","","","True","","","","","","","","","","","","","","True","","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","1980-01-01 00:00:00" +"1192","","True","","","True","True","True","","","","","","","","","","","True","","True","","","","","","","","","","","RCSB PDB","","","","","25.0","","","","","True","True","True","True","True","True","True","","True","","True","","","","","","","","","","","","688.64","Completed the survey","Anonymized","Anonymized","Matter","Life Science","","","","","","","","","","","","Health Science","","","","","","","","","","More than 10 years","Research Associate","","Yes","Familiar with FAIR","","True","","","","Anonymized","Anonymized","","","True","","","True","","","","","","True","","True","","","","","","","True","","","Yes","Yes","","","","","","","","","","","","","","","","","","","","","","","","","True","","PDBx/mmCIF","True","True","True","True","True","","","","","All","All","All","All","All","","","","","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","Purely measured","Purely generated","No","","100.0","","","True","","","","","","","","","","","True","","","","","","","","","Röntgendiffraktion","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","100 GB - 1000 GB (1 TB)","","","","","","","True","","","True","","","moderately interested","very interested","very interested","","","","1980-01-01 00:00:00" +"1197","True","","","","","True","","","","True","","","","","True","","True","","","","","","","","","","","","","","","","","","","40.0","","","","","","","","","","","","","","","","True","","","","","","","","","","","886.44","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","Not familiar with FAIR","True","","","","","Excel (Spreadsheets)","Mathematica","OriginLab","","True","","","True","","","","","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","Some of them","","","","","Mostly measured","","","","80.0","","","","","","","","","True","True","True","","True","","","","","","","screencopy","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","True","","","","1 GB - 10 GB","","True","","","","","True","","","","","","moderately interested","very interested","very interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"1198","True","","","","","","","True","True","","","","True","","","","","","","","","","","","","","","","","","","","","","","5.0","","","","","True","True","","","True","True","True","","True","","","","","","","","","","","","","","1192.53","Completed the survey","Anonymized","Anonymized","Matter","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","More than 10 years","Research Associate","","Yes","Not familiar with FAIR","","True","","","","Excel (Spreadsheets)","ImageJ","Anonymized","True","","","","","","","","","True","","True","","","","","","True","","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","True","","","","Some of them","Some of them","Some of them","Some of them","","All","","","","None","None","None","None","","None","","","","Purely measured","Mostly generated","Yes","","100.0","","","","","","","","","True","True","","","True","True","","","","","","Flluoreszenz-Mikroskopie, Lebendzellmikroskopie","Durchflusszytometrie","","Immunoblotting","Immunopräzipitation","Überlebenskurven","","","","","","","","","","","","","","","","","","","","True","","","True","","","","True","","True","","","","10 GB - 100 GB","","","","","","True","","True","","","","","very interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"1200","","True","","","","True","","True","","","","","","","True","","True","True","","True","","","","","","","","","","","Institutional Repository","","","","","10.0","","","","","","","","","True","True","","","True","","True","True","","","","","","","","","","","750.85","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","More than 10 years","Principal Investigator","Principal Investigator","Yes","Apply FAIR","","","True","","","ROOT framework","Machine Learning Libraries","Python","","True","","","True","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","All","","","","","","","Some of them","Some of them","Some of them","","","","","Equally measured and simulated","Purely reused","Yes","","100.0","True","","","","","","","","","","","","","","True","","","","Analytical methods","","","","","","","Physics generators (PYTHIA, HIJING, etc): event-by-event computer intensive computation on HPC","Fast simulation employing simplified models","","","","","","","","Experiment raw data are calibrated and reconstructed on the GRID (WLCG)","Analysis level data are produced by user code running on the GRID and extracting smaller samples for end analysis","Machine learning and neural network techniques on local farm (or laptop, sometimes)","","","","","","","","","","","","","","True","","","","","Other","","> 1 TB","","True","","","","True","True","","True","","","","moderately interested","moderately interested","not interested","moderately interested","","moderately interested","1980-01-01 00:00:00" +"1202","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","531.06","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","4 to 6 years","Postdoc","","No","Not familiar with FAIR","True","True","True","","","ROOT framework","Anonymized","Python","","","","True","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","Some of them","All","","","","","","","","Some of them","All","","","","","","Equally measured and simulated","Equally generated and reused","Yes","","90.0","True","","","","","","","","","","","","","","True","","","","","","","","","","","State-of-the-art event generators","Specific numerical model calculations","","","","","","","","","","","","","","","","","","","","True","","","True","True","","","True","","","","100 GB - 1000 GB (1 TB)","","True","","","","","","","","","","","not interested","moderately interested","not interested","not interested","moderately interested","not interested","1980-01-01 00:00:00" +"1204","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","Legal / ethical concerns","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","790.4","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","7 to 10 years","Postdoc","","Yes","Not familiar with FAIR","True","True","","","","Anonymized","Python","","","","","","","","","True","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","All","","","All","","","","","","None","","","None","","","","","","Equally measured and simulated","Purely reused","Yes","","100.0","True","","","","","","","","","","","","","True","True","","","","","","","","Teilchenspur-Rekonstruktion","machinelles Lernen","","Monte Carlo Teilchensimulationen (z.B. PYTHIA)","","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","Other","","> 1 TB","","","","","True","","","","True","","","","not interested","moderately interested","moderately interested","very interested","very interested","not interested","1980-01-01 00:00:00" +"1208","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","615.23","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","More than 10 years","Research Associate","","Yes","Familiar with FAIR","","True","","","","Python","MATLAB / Simulink","","","True","","","True","","","","","True","","True","","","","","","","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","Some of them","Some of them","","","","","","","Some of them","Some of them","Some of them","","","","","Mostly measured","Mostly generated","Yes","","100.0","","","","","","","True","","","","","","","True","True","","","","","","","","Photoelektronenspektroskopie","","","FEL Simulationen","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","10 GB - 100 GB","","","","","","","True","","","","","","moderately interested","very interested","moderately interested","not interested","moderately interested","","1980-01-01 00:00:00" +"13","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","22964.8","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Mechanical Engineering","","","","","","","","","","","","No degree","Technical Staff","Technical Staff","","Familiar with FAIR","True","True","","","","PTC Creo","Altium Designer","EPLAN","","True","","","True","","","","","True","True","True","","","True","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","True","True","","All","All","All","All","All","All","All","All","","","","","","","","","","","Purely simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","True","","","","True","True","True","True","","","","> 1 TB","","","True","True","True","True","True","True","","True","","","very interested","very interested","not interested","","","very interested","1980-01-01 00:00:00" +"26","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","3302.71","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Meteorology","","","","More than 10 years","Principal Investigator","","","Not familiar with FAIR","","True","","","","Anonymized","","","","True","","","","","","","","","","","","","","","","","True","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","Some of them","Some of them","","","","","","","","Some of them","Some of them","","","","","","Mostly measured","Mostly reused","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","True","","","> 1 TB","","True","True","True","True","True","","","","","","","moderately interested","moderately interested","","not interested","","","1980-01-01 00:00:00" +"67","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","2192.73","Completed the survey","Anonymized","Anonymized","Energy","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Research Associate","","","Apply FAIR","True","","","","","Anonymized","OriginLab","MATLAB / Simulink","","True","","","","","","","","True","True","True","True","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","Some of them","Some of them","Some of them","","","","","","Some of them","Some of them","Some of them","Some of them","","","","","","Equally measured and simulated","Purely generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","True","","","","True","True","","","1 GB - 10 GB","","","True","True","True","True","True","","","","Best practices","","very interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"186","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","387.36","Completed the survey","Anonymized","Anonymized","Energy","Engineering Science","","","","","","","","","","Process Engineering","","","","","","","","","","","","More than 10 years","Postdoc","","","Not familiar with FAIR","","True","","","","Anonymized","Excel (Spreadsheets)","LabVIEW","","True","","","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","None","Some of them","None","None","None","","","","","Mostly measured","Mostly generated","Yes","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","True","","True","","","","","True","","","","","","100 MB - 1000 MB (1 GB)","","True","","True","","True","True","","True","","","","very interested","very interested","very interested","very interested","moderately interested","very interested","1980-01-01 00:00:00" +"192","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","23094.7","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Mechanical Engineering","","","","","","","","","","","","No degree","Technical Staff","Technical Staff","No","","True","True","","","","PTC Creo","Altium Designer","EPLAN","","True","","","True","","","","","True","True","True","","","True","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","True","True","","All","All","All","All","All","All","All","All","","All","All","Some of them","Some of them","Some of them","None","None","Some of them","","Purely simulated","Mostly generated","Yes","As much","","","","","","","","","","","","","","","","True","","","","","","","","","","","Finite Element Analysis","Computational Fluid Dynamics","Fluid-Structure Interaction","","","","","","","","","","","","","True","True","True","True","True","","True","","","","True","True","True","True","","","48.0","> 1 TB","As much","","True","True","True","True","True","True","","True","","","very interested","very interested","not interested","","","very interested","1980-01-01 00:00:00" +"196","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","776.23","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","1 to 3 years","PhD candidate","","Yes","","","","","","Externally (servers / repositories)","Anonymized","Git","Visual Studio","","","True","","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","All","All","","","","","","","","None","Some of them","","","","","","Purely simulated","Purely generated","Not sure","Less","","","","","","","","","","","","","","","","True","","","","","","","","","","","laufzeitmessungen","nsight compute","","","","","","","","","","","","","","","","True","","","","True","","","True","True","","","","","","1.0","< 100 MB","Less","","","","","","","","True","","","","moderately interested","moderately interested","not interested","very interested","moderately interested","very interested","1980-01-01 00:00:00" +"224","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1838.54","Completed the survey","Anonymized","Anonymized","Information","Physics","","","","","","","","","","","","","","","","","","Soft Matter Physics","","","","More than 10 years","Principal Investigator","","Yes","","True","","","","","Anonymized","OriginLab","Anonymized","True","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","","","","","","","","","","Purely measured","Purely generated","Yes","As much","","","","","","","","","","","","","","True","True","","","","","","konfokales Mikroskop","","","Erzwungene Streumethoden","Isotherme Titrationskalorimetrie","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","","","","True","","9.0","100 GB - 1000 GB (1 TB)","As much","True","","","","","True","True","","","","","moderately interested","very interested","moderately interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"253","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","786.04","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Mechanical Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","Yes","","","True","","","","Mathematica","Anonymized","ANSYS","","True","","","True","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","None","None","None","Some of them","","","","","","Mostly simulated","Mostly generated","Yes","Less","","","","","","","","","","","","","","True","","True","","","","","Mikroskopie","taktil","Interferometrie","","","","Numerisch","physikalisch/theoretisch","","","","","","","","","","","","","","","","","","True","","","True","","True","True","","","","","","6.0","1 GB - 10 GB","I don't know","","","","","","","","","","","True","moderately interested","very interested","moderately interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"286","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","880.29","Completed the survey","Anonymized","Anonymized","Information","Engineering Science","","","","","","","","","","Process Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","","Not sure","","","True","","","","Aspen Custom Modeler","Excel (Spreadsheets)","LabVIEW","","True","","True","True","","","","","","","","","","","","","True","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","Some of them","","All","All","","","","","","None","","None","None","","","","","","Equally measured and simulated","Mostly generated","Yes","More","","","","","","","","","","","","","","","True","True","","","True","","","","","Gas chromatography","Scanning elctron microscopy","","Numerical models (solution of PDAE systems)","","","","","","","","","","","","","","","","","True","","True","","True","","","True","True","True","True","","","","3.0","1 GB - 10 GB","More","","","True","True","","True","","","","","","very interested","moderately interested","very interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"351","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1775.7","Completed the survey","Anonymized","Anonymized","Information","Physics","","","","","","","","","","","","","","","","","","Particles, Nuclei and Fields","","","","4 to 6 years","PhD candidate","","Not sure","","True","True","True","","","Anonymized","Anonymized","Anonymized","","","","","","","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","All","All","Some of them","All","All","","","","","","","","","","","","","","","Equally generated and reused","Yes","I don't know","","","","","","","","","","","","","","","","True","","","True","","","","","","","","Programm zur Verfügung gestellt von E.F.","neue Analyse der Daten von F.S.","","","","","","","","","","","","","","True","","True","","True","","True","","","","True","","True","","","","12.0","I don't know","I don't know","True","","True","True","True","","","True","","","","moderately interested","moderately interested","not interested","moderately interested","moderately interested","not interested","1980-01-01 00:00:00" +"382","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","455.48","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","Less than 1 year","PhD candidate","","","Not familiar with FAIR","","","","True","","CFD Software (e.g. TecPlot, ParaView)","Machine Learning Libraries","CFD Software (e.g. TecPlot, ParaView)","","True","True","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","True","","","","All","","All","","","All","","","","All","","None","","","All","","Purely simulated","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","True","True","True","True","True","True","","","1 GB - 10 GB","","","","True","True","True","True","True","True","True","","","moderately interested","very interested","moderately interested","very interested","very interested","moderately interested","1980-01-01 00:00:00" +"392","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1375.6","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Computer Science","","","","","","","","","","","","More than 10 years","Research Associate","","","Familiar with FAIR","","True","","","","Anonymized","Git","PowerPoint","","","","","","True","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","All","","All","","Some of them","","","","","None","","None","","Some of them","","","","Mostly simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","True","","","","","","","True","True","","","100 MB - 1000 MB (1 GB)","","","","","","","","True","True","","","","moderately interested","moderately interested","very interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"407","","","","","","","","","","","","","","","","","","","","","","","","True","","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","732.69","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","","","","","","","","","","","","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","True","True","","","","MATLAB / Simulink","LabVIEW","Python","","","","","","","","True","","","","","","","","","","True","True","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","Some of them","Some of them","Some of them","","","","","","","None","Some of them","None","","","","","","","Mostly measured","Mostly reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","True","True","","True","True","","","1 GB - 10 GB","","","","","True","True","True","True","True","True","","","moderately interested","moderately interested","very interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"410","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","817.5","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Principal Investigator","Principal Investigator","","Familiar with FAIR","True","True","","","","Anonymized","Anonymized","Tecplot","","","","","True","","","","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","None","","","","","","","","","Mostly simulated","Purely generated","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","True","True","","","True","","","10 GB - 100 GB","","","True","True","True","True","","","","True","","","very interested","very interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"444","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","635.95","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","4 to 6 years","Principal Investigator","","","Not familiar with FAIR","True","True","","","","LabVIEW","Python","Excel (Spreadsheets)","","True","","True","True","True","","True","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","","","","","All","All","","","All","","","","","Some of them","Some of them","","","Some of them","","","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","True","","","","","1 GB - 10 GB","","","","True","","True","","True","","","","","moderately interested","moderately interested","not interested","not interested","moderately interested","very interested","1980-01-01 00:00:00" +"481","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","629.16","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Systems Engineering","","","","","","","","","","","","7 to 10 years","Research Associate","","","Not familiar with FAIR","","True","","","","Dymola","MATLAB / Simulink","MATLAB / Simulink","","True","","","","","","","","","","","","","","","","True","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","Some of them","","","","Some of them","","","","","None","","","","None","","","","","Mostly simulated","Mostly generated","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","True","True","","True","","","","1 GB - 10 GB","","True","True","True","True","True","True","True","True","True","","","very interested","very interested","very interested","very interested","moderately interested","very interested","1980-01-01 00:00:00" +"484","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1110.64","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Physics","","","","","","","","","","","","","","","","","","","","","","4 to 6 years","Research Associate","","","Not familiar with FAIR","","","","True","","","","","True","","","","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","Purely simulated","Purely reused","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","True","","","","True","","","","True","","","I don't know","","","","","","","","","","","","","","","","","","","1980-01-01 00:00:00" +"497","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","425.95","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","","Not familiar with FAIR","","True","","","","Anonymized","Anonymized","Anonymized","","","True","","","","","True","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","All","","All","","","","","","","None","","None","","","","","","","Mostly measured","Mostly generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","","True","","","","","10 GB - 100 GB","","","","","","","","","","","","True","very interested","very interested","moderately interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"533","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1481.79","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Mechanical Engineering","","","","","","","","","","","","7 to 10 years","PhD candidate","","","Not familiar with FAIR","True","True","","","","CATIA CAD-software","Anonymized","Excel (Spreadsheets)","","True","","","","","","","","True","","True","","","","","","","","","","True","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","Some of them","","","","","","","","","Mostly measured","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","True","True","True","True","","","","1 GB - 10 GB","","","True","","True","True","True","","","","","","not interested","moderately interested","not interested","not interested","not interested","not interested","1980-01-01 00:00:00" +"542","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","634.84","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","More than 10 years","Research Associate","","","Not familiar with FAIR","True","True","","","","Anonymized","Anonymized","Tecplot","","True","","","","","","","","True","","","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","Some of them","","","","","","","","","Purely simulated","Purely generated","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","True","","","True","True","","True","","","","","100 GB - 1000 GB (1 TB)","","","","","","","","","","","","","very interested","moderately interested","moderately interested","not interested","very interested","not interested","1980-01-01 00:00:00" +"557","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","984.18","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Mathematics","","","","","","","","","","","","","","Applied Mathematics","","","","","","","","7 to 10 years","Postdoc","","","Not familiar with FAIR","True","True","","","","Anonymized","LaTeX","Anonymized","","","True","","","True","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","All","All","All","All","","","","","","All","All","All","All","","","","","","Equally measured and simulated","Purely reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","True","True","","","True","True","True","","True","True","","","1 GB - 10 GB","","","","","True","True","True","True","True","","","","very interested","moderately interested","moderately interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"558","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","877.33","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","No degree","Research Associate","","","Not familiar with FAIR","","True","","","","CATIA CAD-software","","","True","","","","","","","","","True","True","","","","","","","True","","","","","Yes","Yes","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","None","","","","","","","","Mostly simulated","Equally generated and reused","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","","","","True","True","","","","","1 GB - 10 GB","","","","","","True","","","True","","","","very interested","very interested","moderately interested","not interested","not interested","moderately interested","1980-01-01 00:00:00" +"612","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","498.14","Completed the survey","Anonymized","Anonymized","Aeronautics, Space and Transportation","Engineering Science","","","","","","","","","","Aerospace Engineering","","","","","","","","","","","","4 to 6 years","PhD candidate","","","Not familiar with FAIR","True","","","","","Dymola","MATLAB / Simulink","Python","","","","True","","","","","","","","","","","","","","","","True","","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","Some of them","","","","","","","","","None","","","","","Mostly simulated","Mostly generated","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","","","","","1 GB - 10 GB","","","","True","","True","","","","","","","moderately interested","very interested","very interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"743","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","441.64","Completed the survey","Anonymized","Anonymized","Earth and Environment","Earth Science","","","","","","","","","Urban","","","","","","","","","","","","","4 to 6 years","PhD candidate","","Yes","Not familiar with FAIR","","True","","","","ArcGIS","QGIS/GDAL","QGIS/GDAL","","True","","True","","","","","","","True","True","True","True","","","","","","True","","","Yes","Yes","","","","True","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","True","","","","","All","","All","All","All","","","","","None","","None","None","Some of them","","","","","Mostly simulated","Mostly reused","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Manually","Collection from 3rd Party resources","Automatic straction with no validation","","","","","","","","","","","","","True","","","True","True","","True","","","True","True","True","","True","","","","100 GB - 1000 GB (1 TB)","","True","","","","","","True","","","","","very interested","moderately interested","moderately interested","very interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"766","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","23065.8","Completed the survey","Anonymized","Anonymized","Health","Engineering Science","","","","","","","","","","Mechanical Engineering","","","","","","","","","","","","","Technical Staff","Technical Staff","","Familiar with FAIR","True","True","","","","PTC Creo","Altium Designer","EPLAN","","True","","","True","","","","","True","True","True","","","True","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","True","True","","All","All","All","All","All","All","All","All","","All","All","Some of them","Some of them","Some of them","None","None","Some of them","","Purely simulated","Mostly generated","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Finite Element Analysis","Computational Fluid Dynamics","Fluid-Structure Interaction","","","","","","","","","","","","","True","True","True","True","True","True","True","","","","","True","True","True","","","","> 1 TB","","","True","True","True","True","True","True","","True","","","very interested","very interested","not interested","","","very interested","1980-01-01 00:00:00" +"836","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","931.13","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Health Science","","","","","","","","","","","Research Associate","","","Familiar with FAIR","","True","","","","Anonymized","","","True","","","","","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","","","","All","All","All","All","All","All","","","","None","None","None","None","None","None","","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","Erhebung mit Applikation","","","","","","","","","","","","","True","","","","","","","True","","","","","","100 MB - 1000 MB (1 GB)","","True","","True","True","True","","","True","","","","very interested","very interested","moderately interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" +"839","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","662.62","Completed the survey","Anonymized","Anonymized","Health","","MTRA","","","","","","","","","","","","","","","","","","","","","","Technical Staff","Technical Staff","","Not familiar with FAIR","","","True","","","MATLAB / Simulink","Linux","","","","","True","","","","","","","True","","","","","","","","True","","","","Yes","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","All","","","","","","","","","Some of them","","","","","","","Mostly measured","Equally generated and reused","","","","","","","","","","","","","","","","True","","","","","","","matlap","Linux","","","","","","","","","","","","","","","","","","","","True","","True","","","","","True","","","","","","","","","","1 GB - 10 GB","","","","","","True","","","","","","","very interested","very interested","very interested","moderately interested","very interested","moderately interested","1980-01-01 00:00:00" +"844","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","511.26","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Biology","","","","","","","","","","","PhD candidate","","","","True","True","","","","Anonymized","Anonymized","Anonymized","True","","","","","","","","","","","","","","","","","True","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","True","","","All","Some of them","All","","","","Some of them","","","None","None","None","","","","None","","","Purely measured","Purely generated","","","","","","","","","","","","","","","","True","True","","","","","","Bright field color & fluorescent","","","Genomics tools","Sequencing","Standard molecular & cell biology tools","","","","","","","","","","","","","","","","","","True","","True","True","","True","","","","True","","True","","","","100 GB - 1000 GB (1 TB)","","","True","","","","","","","","","","not interested","moderately interested","not interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"978","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1231.89","Completed the survey","Anonymized","Anonymized","Health","Life Science","","","","","","","","","","","","Health Science","","","","","","","","","","","Postdoc","","","Familiar with FAIR","","True","","","","SAS","R","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","True","","","","","","","","","","","","","","","","","","","","","Mostly measured","Purely reused","","","","","","","","","","","","","","","","","","","","True","","Other","","","","","","","","","","","","","face-to-face interviews","web-based questionnaires","calculation of usual dietary intakes (NIH SAS algorithms considering intra-individual variation)","inflammatory biomarkers in serum samples","microbiome data from fecal samples","metabolic markers in blood (glucose metabolism, lipoproteins and triglycerides)","","","","","","","","","","","","True","","","","","","","","","I don't know","","True","","","","True","True","","True","","","","moderately interested","not interested","not interested","not interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1010","","","","","","","","","","","","","","","","","","","","","","","True","True","","","True","True","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","23346.7","Completed the survey","Anonymized","Anonymized","Matter","Engineering Science","","","","","","","","","","Mechanical Engineering","","","","","","","","","","","","No degree","Technical Staff","Technical Staff","No","Familiar with FAIR","True","True","","","","PTC Creo","Altium Designer","EPLAN","","True","","","True","","","","","True","True","True","","","True","","","True","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","True","True","True","","All","All","All","All","All","All","All","All","","All","All","Some of them","Some of them","Some of them","None","None","Some of them","","Purely simulated","Mostly generated","Yes","","","","","","","","","","","","","","","","","True","","","","","","","","","","","Finite Element Analysis","Computational Fluid Dynamics","Fluid-Structure Interaction","","","","","","","","","","","","","True","True","True","True","True","True","True","","","","True","True","True","True","","","","> 1 TB","","","True","True","True","True","True","True","","True","","","very interested","very interested","not interested","","","very interested","1980-01-01 00:00:00" +"1021","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","678.26","Completed the survey","Anonymized","Anonymized","Matter","Engineering Science","","","","","","","","","","Process Engineering","","","","","","","","","","","","More than 10 years","Postdoc","","Yes","Not familiar with FAIR","True","True","","","","Excel (Spreadsheets)","Anonymized","R","","True","","","True","","","","","","","","","","","","","","","True","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","All","","","","","","","None","None","None","","","","","","","Mostly measured","Mostly generated","Yes","","0.0","","","","","","","","","","","","","True","True","","True","","","Other","Digitalfotografie, Kameras","REM-Messungen","AFM-Messungen","MLA-Messung","chemische Analysen (XRF","XRD","","","","Probenahme","Probenteilung","Zerkleinern, Fest-Flüssig-Trennung, Trocknen","","","","Leistungsaufnahme","Temperatur, Druck im Prozessraum","Massestrom","","","","","True","True","","True","","","","","","","True","","","","","","100 MB - 1000 MB (1 GB)","","True","True","True","True","True","True","","True","True","","","very interested","very interested","very interested","very interested","very interested","very interested","1980-01-01 00:00:00" +"1032","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","684.84","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Thermodynamics","","","","Less than 1 year","PhD candidate","","No","Not familiar with FAIR","True","True","","","","Python","","","","","","","","","","","","","","","","","","","","","True","True","Source code and scripts","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","Some of them","All","","All","","","","","","Some of them","All","","All","","","","","","Mostly measured","Purely generated","","","0.0","","","","","","","","","","","","","True","True","True","","","","","X-ray imagry","","","SEM","","","Independent programming","","","","","","","","","","","","","","","","","","","True","","","","","","True","","","","True","","","10 GB - 100 GB","","","","","","","","","","","","","","","","","","","1980-01-01 00:00:00" +"1035","","","","","","","","","","","","","","","","","","","","","","","","","True","","True","True","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1192.85","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","More than 10 years","Research Associate","","Yes","Familiar with FAIR","True","","","","","Anonymized","IGOR","Jupyter","","True","","","True","","","","","","","","","","","","","True","","","","","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","Mostly measured","Purely generated","Yes","","90.0","","True","True","","","","","","","","","Anonymized","","True","","","","","","","","","NEXAFS","RIXS","","","","","","","","","","","","","","","","","True","","","","True","","True","","","","True","","","","True","","","1 GB - 10 GB","","","","","True","","","","","","","","","very interested","moderately interested","not interested","","moderately interested","1980-01-01 00:00:00" +"1038","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","958.45","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","","Beschleunigerphysik","","","More than 10 years","Principal Investigator","Principal Investigator","Yes","Familiar with FAIR","","True","","","","MATLAB / Simulink","Excel (Spreadsheets)","Word","","","","","True","","","","","True","True","True","","","","","","","True","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","","","","","","Some of them","Some of them","Some of them","Some of them","","","","","","None","None","Some of them","Some of them","","","","","","Mostly measured","Mostly reused","Yes","","100.0","","","","","","","True","True","","","","Anonymized","","","True","","","","Analytical methods","","","","","","","Strahldynamik","EM-Felder","","","","","","","","Strahlparameter, Strahltransport","Vermessung von Hohlraumresonatoren","","","","","","","True","True","True","","","","","True","True","True","","","","","","I don't know","","","","","","","","","True","","","","moderately interested","very interested","very interested","very interested","moderately interested","very interested","1980-01-01 00:00:00" +"1060","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","965.27","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","No degree","Student","","Yes","Apply FAIR","","True","True","","","AiiDA","Anonymized","Machine Learning Libraries","","True","True","","True","","","","","","","","","","","","","","True","True","GitLab","","Not sure","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","True","","Some of them","All","All","All","All","","","Some of them","","None","All","All","All","All","","","None","","Purely simulated","Purely generated","Not sure","","","","","","","","","","","","","","","","","True","","","","","","","","","","","density functional theory","machine learning","","","","","","","","","","","","","","True","","True","","","","","","","","True","","","True","True","","","10 GB - 100 GB","","True","","True","","","","","True","","","","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1066","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","True","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","822.54","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","","Röntgenoptik","","","More than 10 years","Principal Investigator","Principal Investigator","Yes","Apply FAIR","","True","","","","Python","IDL","Anonymized","","True","True","True","True","","","","","True","True","True","","","","","","True","True","","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","True","True","","","","","Some of them","Some of them","Some of them","Some of them","Some of them","","","","","None","Some of them","Some of them","Some of them","Some of them","","","","","Mostly measured","Purely generated","Yes","","80.0","","True","True","","","","True","True","","","","Anonymized","True","True","True","","","","","Röntgen-Holografie","Röntgen-Mikroskopie","","Elektronen-Spektroskopie","Röntgen-Spektroskopie","Reflektometrie","Ray-Tracing","","","","","","","","","","","","","","","","","True","","True","","True","","","","True","","","True","True","","","100 GB - 1000 GB (1 TB)","","True","True","True","True","True","True","","True","True","","","very interested","moderately interested","very interested","moderately interested","very interested","very interested","1980-01-01 00:00:00" +"1079","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","493.04","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Condensed Matter Physics","","","","More than 10 years","Principal Investigator","Principal Investigator","Not sure","Familiar with FAIR","","True","","","","Python","LabVIEW","","True","","","","","","","","","","","","","","","","","","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","All","","","","","","","None","None","None","","","","","","","Mostly measured","","Yes","","80.0","","","","","","","","","","","","Anonymized","","True","","","","","","","","","","","","","","","","","","","","","","","","","","","True","","","","","","True","True","","","","","","True","","","","","","","","True","True","","","","","","","","very interested","moderately interested","moderately interested","moderately interested","moderately interested","moderately interested","1980-01-01 00:00:00" +"1129","","","","","","","","","","","","","","","","","","","","","","","","True","True","","True","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1054.42","Completed the survey","Anonymized","Anonymized","Matter","Engineering Science","","","","","","","","","","Mechanical Engineering","","","","","","","","","","","","1 to 3 years","Research Associate","","Not sure","Familiar with FAIR","True","True","","","","Anonymized","OriginLab","Excel (Spreadsheets)","","","","","True","","","","Heterogeneous workflows complicate standardized solutions","True","True","","True","","","","","True","","True","","","Yes","","","","","","","","","","","","","","","","","","","","","","","","","","","","","True","True","True","","","","","","","All","All","Some of them","","","","","","","None","Some of them","Some of them","","","","","","","Equally measured and simulated","Mostly generated","Not sure","","0.0","","","","","","","","","","","","","True","","True","","","","Other","Lichtmikroskopie","Laserscanningmikroskop","EBSD","","","","(thermo)mechanische numerische Modelle","","","","","","","","","Sensoren, Thermokameras, Maschinenprotokolle","Zugversuche, Stauchversuche","Härteprüfungen","","","","True","","True","","True","","True","True","","","True","True","","","","","","10 GB - 100 GB","","","","True","","","True","True","","True","","","very interested","very interested","very interested","moderately interested","moderately interested","very interested","1980-01-01 00:00:00" +"1201","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","0.0","","","","","","","","","","","","","","","","","","","","","","","","","","","1013.21","Completed the survey","Anonymized","Anonymized","Matter","Physics","","","","","","","","","","","","","","","","","","Atomic, Molecular, Optical and Plasma Physics","","","","No degree","Student","","No","Not familiar with FAIR","True","","","","","ROOT framework","Anonymized","","","","","","","","","True","","True","","","","","","","","","","True","","","Yes","No","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Purely measured","Purely reused","","","75.0","","","","","","","","","","","","Anonymized","True","","","","","","","Pixel Detetors","Scintillator pulses","","","","","","","","","","","","","","","","","","","","","","True","","","","True","","","","True","","","","","","","1 GB - 10 GB","","","","","","","","","","","","True","not interested","very interested","very interested","not interested","very interested","moderately interested","1980-01-01 00:00:00" diff --git a/survey_dashboard/description.html b/survey_dashboard/description.html deleted file mode 100644 index 97cb8d9..0000000 --- a/survey_dashboard/description.html +++ /dev/null @@ -1,39 +0,0 @@ - - - -

The HMC Survey explorer

- -

-

-

-
\ No newline at end of file diff --git a/survey_dashboard/data/germany_map.svg b/survey_dashboard/hmc_layout/assets/germany_map.svg similarity index 100% rename from survey_dashboard/data/germany_map.svg rename to survey_dashboard/hmc_layout/assets/germany_map.svg diff --git a/survey_dashboard/hmc_layout/assets/institute.svg b/survey_dashboard/hmc_layout/assets/institute.svg new file mode 100644 index 0000000..9d646cd --- /dev/null +++ b/survey_dashboard/hmc_layout/assets/institute.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/survey_dashboard/hmc_layout/assets/people.svg b/survey_dashboard/hmc_layout/assets/people.svg new file mode 100644 index 0000000..d2f2af1 --- /dev/null +++ b/survey_dashboard/hmc_layout/assets/people.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/survey_dashboard/hmc_layout/assets/quiz_black_48dp.svg b/survey_dashboard/hmc_layout/assets/quiz_black_48dp.svg new file mode 100644 index 0000000..33e1832 --- /dev/null +++ b/survey_dashboard/hmc_layout/assets/quiz_black_48dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/survey_dashboard/hmc_layout/de_template.html b/survey_dashboard/hmc_layout/de_template.html new file mode 100644 index 0000000..eac3003 --- /dev/null +++ b/survey_dashboard/hmc_layout/de_template.html @@ -0,0 +1,2061 @@ +{% extends base %} + +{% block postamble %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{% endblock %} + + {% block inner_body %} +

+
+
+ + + +
+
+ +
+ + + + +
+
+
+ +

+ Wer sind die Datenstakeholder in Helmholtz? Welche Tools nutzen sie? Welche Hindernisse liegen auf dem Weg zu besseren Metadaten? + Dies sind nur einige der Fragen, die wir mit unserem HMC Community Survey 2021 adressiert haben. Auf dieser Seite können Sie die Ergebnisse der Umfrage interaktiv erforschen und einen tieferen Einblick in die Daten erlangen. +

+ +

+ Filtern Sie die angezeigten Daten unter Globale Datafilter und erforschen Sie +

    +
  • die Communityprofile unserer Datenstakeholder
  • +
  • Methoden, Tools und Software, die für Datengenerierung und -verarbeitung genutzt werden
  • +
  • Antworten und ihren Bezug untereinander im Umfrage-Explorer
  • +
+

+
+ +
+
+ 49 +
+
+ Fragen umfasste die Umfrage insgesamt +
+
+ +
+
+ 631 +
+
+ Forschende haben an der Umfrage teilgenommen +
+
+ + + +
+
+
+ +

+ DISCLAIMER
Die angezeigten Daten sind mit Sorgfalt zu betrachten. Einige Antworten könnten losgelöst vom Kontext + Verzerrungen ausgesetzt sein. Einige Fragen wurden abhängig vom Forschungsbereich der Befragten gestellt. + Für nähere Informationen beachten Sie bitte unsere + Umfragepublikation. +

+ +
+ +
+ +
+
+ +
+
+ {% block contents %} +
+
+ {% for doc in docs %} + {{ embed(doc) if doc.elementid }} + {% for root in doc.roots %} + {{ embed(root) | indent(10) }} + {% endfor %} + {% endfor %} + {{ plot_script | indent(8) }} +
+
+
+ {{ embed(roots.App) }} +
+
+
+ {% endblock %} +
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + {% endblock %} diff --git a/survey_dashboard/hmc_layout/en_template.html b/survey_dashboard/hmc_layout/en_template.html new file mode 100644 index 0000000..adfb37d --- /dev/null +++ b/survey_dashboard/hmc_layout/en_template.html @@ -0,0 +1,2057 @@ +{% extends base %} + +{% block postamble %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{% endblock %} + + {% block inner_body %} +
+
+ +
+ +
+ + +
+
+
+ +

+ Who are the data stakeholders in Helmholtz? What tools do they use? What are the roadblocks to better metadata? + These were some of the questions that we investigated with our HMC community survey in 2021. Here you can browse the results interactively and dive deeper into the data! +

+ +

+ Refine the displayed data with Global Data Filters and explore +

    +
  • the community profiles of our data stakeholders
  • +
  • the methods, tools and software used for data generation and handling
  • +
  • responses and how they compare to each other between different quesitons in the Survey Data Explorer
  • +
+

+
+ +
+
+ 49 +
+
+ questions were included in the survey design +
+
+ +
+
+ 631 +
+
+ researchers took part in the survey +
+
+ + + +
+
+
+ +

+ DISCLAIMER
Displayed data should be interpreted with care. Responses might be subject to sample bias and some + questions were specific to the research field of participants. + Check our written publication for further details. +

+ +
+ +
+ +
+
+ +
+
+ {% block contents %} +
+
+ {% for doc in docs %} + {{ embed(doc) if doc.elementid }} + {% for root in doc.roots %} + {{ embed(root) | indent(10) }} + {% endfor %} + {% endfor %} + + + + + + + + + + + {{ plot_script | indent(8) }} +
+
+
+ {{ embed(roots.App) }} +
+
+
+ {% endblock %} +
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + {% endblock %} diff --git a/survey_dashboard/data/display_specifications/hmc_colordicts.py b/survey_dashboard/hmc_layout/hmc_colordicts.py similarity index 55% rename from survey_dashboard/data/display_specifications/hmc_colordicts.py rename to survey_dashboard/hmc_layout/hmc_colordicts.py index 79c33b2..21b604e 100644 --- a/survey_dashboard/data/display_specifications/hmc_colordicts.py +++ b/survey_dashboard/hmc_layout/hmc_colordicts.py @@ -9,17 +9,13 @@ # For further information on the license, see the LICENSE file # ############################################################################### """ -This file contains color palets which are HMC specific +This file contains color palettes which are HMC specific @author: s.gerlich """ -import matplotlib.pyplot as plt -import cmasher as cmr -colors = cmr.take_cmap_colors(HMCRamp, None, cmap_range=(0.2, 0.8), return_fmt='hex') +from typing import Optional, List, Any - - -# Dictionary of HMC hub colors +# Dictionary of HMC hub colors hubPalette = { "Information":"#A0235A", "Health":"#D23264", @@ -43,7 +39,7 @@ "#3F5704" ] -# List of Hub Info color Palette +# List of Hub Info color Palette hubInfoPalette = [ "#005AA0", "#0A2D6E", @@ -56,28 +52,28 @@ "#470723" ] -# create color ramps for continuous data out of color palettes -# function to create ramp: make_ramp() -def make_Ramp( ramp_colors ): - from colour import Color - from matplotlib.colors import LinearSegmentedColormap - - color_ramp = LinearSegmentedColormap.from_list( 'my_list', [ Color( c1 ).rgb for c1 in ramp_colors ] ) - plt.figure( figsize = (15,3)) - plt.imshow( [list(np.arange(0, len( ramp_colors ) , 0.1)) ] , interpolation='nearest', origin='lower', cmap= color_ramp ) - plt.xticks([]) - plt.yticks([]) - return color_ramp +# Create color ramps for continuous data out of color palettes +def make_Ramp(ramp_colors: List[str]) -> Optional[Any]: + """Create a matplotlib colormap from a list of colors.""" + try: + from colour import Color # type: ignore[import-untyped] + from matplotlib.colors import LinearSegmentedColormap # type: ignore[import-untyped] + color_ramp = LinearSegmentedColormap.from_list('hmc_colormap', [Color(c1).rgb for c1 in ramp_colors]) + return color_ramp + except ImportError: + # Fallback if optional dependencies aren't available + return None -# to be used in matplotlib: cmap -# equivalent of plotnine: scale_color_cmap() -# continuous color scale based on HMC color palette +# Create color ramps (only if dependencies are available) HMCRamp = make_Ramp(HMCPalette) -#cmr.view_cmap(HMCRamp) - -# continuous color scale based on Hub Info color palette hubInfoRamp = make_Ramp(hubInfoPalette) -#cmr.view_cmap(hubInfoRamp) - +# Generate HMC color samples for Bokeh (fallback to basic colors if dependencies fail) +def get_hmc_colors(n_colors: int = 10) -> List[str]: + """Get n_colors from the HMC palette, cycling if needed.""" + if len(HMCPalette) >= n_colors: + return HMCPalette[:n_colors] + else: + # Cycle through colors if we need more than available + return [HMCPalette[i % len(HMCPalette)] for i in range(n_colors)] diff --git a/survey_dashboard/hmc_layout/hmc_custom_layout.py b/survey_dashboard/hmc_layout/hmc_custom_layout.py new file mode 100644 index 0000000..fbdfacc --- /dev/null +++ b/survey_dashboard/hmc_layout/hmc_custom_layout.py @@ -0,0 +1,252 @@ +hmc_custom_css_accordion =''' +.bk.card { + border: 1px solid rgba(0,0,0,.125); + border-radius: 0.25rem; +} +.bk.accordion { + border: 1px solid rgba(0,0,0,.125); +} +.bk.card-header { + align-items: center; + background-color: rgba(0, 0, 0, 0.03); + border-radius: 0.25rem; + display: inline-flex; + justify-content: start !important; + width: 100%; +} +.bk.accordion-header { + align-items: center; + background-color: rgba(0, 0, 0, 0.03); + border-radius: 0; + display: flex; + justify-content: flex-start; + width: 100%; +} +.bk.card-button { + background-color: transparent; + margin-left: 0.5em; + flex-basis: content; + padding: 16px 24px !important; + box-sizing: border-box; + display: flex !important; + align-items: center !important; +} +.bk.card-header-row { + position: relative !important; +} +.bk.card-title { + align-items: left; + font-size: 1.4em; + font-weight: bold; + overflow-wrap: break-word; +} +.bk.card-header-row > .bk { + overflow-wrap: break-word; + text-align: left; +} + +/* Fix scrolling issues without breaking Panel layout */ +body { + overflow-y: auto; + overflow-x: auto; +} + +#app { + overflow: visible; + width: 100%; + max-width: 100%; +} + +/* Ensure Panel accordion sections stack properly and span full width */ +.bk-panel-models-accordion { + overflow: visible; + width: 100% !important; + max-width: 100% !important; +} + +.bk-panel-models-accordion .bk-panel-models-card { + position: relative; + margin-bottom: 8px; + width: 100% !important; +} + +/* Ensure all accordion headers have consistent width */ +.bk-panel-models-accordion .bk-panel-models-card-header { + width: 100% !important; + min-width: 100% !important; + box-sizing: border-box; +} + +/* Add consistent padding to all accordion content */ +.bk-panel-models-accordion .bk-panel-models-card-content { + padding: 24px !important; + box-sizing: border-box; +} + +/* Ensure accordion button spans full header width */ +.bk-panel-models-accordion .bk-panel-models-card-button { + width: 100% !important; + text-align: left; + padding: 16px 24px !important; + box-sizing: border-box; + display: flex !important; + justify-content: space-between !important; + align-items: center !important; +} + +/* Target the actual Panel accordion structure */ +.bk-panel-models-accordion .bk-panel-models-card-header { + display: flex !important; + justify-content: flex-start !important; + align-items: center !important; + width: 100% !important; + gap: 0 !important; +} + +/* Fix the text and icon positioning in Panel accordion headers */ +.bk-panel-models-accordion .bk-panel-models-card-header > *:first-child { + flex: 1 !important; + text-align: left !important; + order: 1 !important; +} + +.bk-panel-models-accordion .bk-panel-models-card-header > *:last-child { + flex-shrink: 0 !important; + margin-left: auto !important; + order: 2 !important; +} + +/* Alternative approach: target Panel's internal structure */ +.bk-panel-models-accordion .bk-panel-models-card-header .bk-panel-models-markup-html { + order: 1 !important; + flex: 1 !important; + text-align: left !important; +} + +.bk-panel-models-accordion .bk-panel-models-card-header .bk-panel-models-icon { + order: 2 !important; + margin-left: 0 !important; + flex-shrink: 0 !important; +} + +/* Also target the legacy Panel classes */ +.bk-panel-models-accordion .bk-panel-models-card-header .bk-panel-models-markup { + order: 1 !important; + flex: 1 !important; + text-align: left !important; +} + +.bk-panel-models-accordion .bk-panel-models-card-header .bk-panel-models-icon { + order: 2 !important; + margin-left: auto !important; + flex-shrink: 0 !important; +} + +/* Target Panel's actual accordion button structure */ +.bk-panel-models-accordion .bk-panel-models-card-header button { + display: flex !important; + justify-content: flex-start !important; + align-items: center !important; + width: 100% !important; + text-align: left !important; + gap: 0 !important; +} + +/* Ensure the text content is on the left */ +.bk-panel-models-accordion .bk-panel-models-card-header button > *:first-child { + order: 1 !important; + flex: 1 !important; + text-align: left !important; +} + +/* Ensure the icon is on the right */ +.bk-panel-models-accordion .bk-panel-models-card-header button > *:last-child { + order: 2 !important; + margin-left: 0 !important; + flex-shrink: 0 !important; +} + +/* Additional targeting for Panel's internal structure */ +.bk-panel-models-accordion .bk-panel-models-card-header .bk-panel-models-markup-html, +.bk-panel-models-accordion .bk-panel-models-card-header .bk-panel-models-markup { + order: 1 !important; + flex: 1 !important; + text-align: left !important; +} + +.bk-panel-models-accordion .bk-panel-models-card-header .bk-panel-models-icon, +.bk-panel-models-accordion .bk-panel-models-card-header .bk-panel-models-markup-icon { + order: 2 !important; + margin-left: 0 !important; + flex-shrink: 0 !important; +} + +/* Ensure all Panel layout containers span full width */ +.bk-panel-models-layout-Column, +.bk-panel-models-layout-row { + width: 100% !important; + max-width: 100% !important; +} + +.bk-Row { /* Row is the main container for the layout -- dont remove this */ +padding: 20px; +} + +/* Fix carousel overflow issues */ +.carousel__viewport { + overflow: hidden; +} + +/* Ensure proper spacing between accordion sections */ +.bk-panel-models-accordion .bk-panel-models-card + .bk-panel-models-card { + margin-top: 8px; +} + +/* Consistent spacing for accordion content */ +.bk-panel-models-accordion .bk-panel-models-card-content > * { + margin-bottom: 16px; +} + +.bk-panel-models-accordion .bk-panel-models-card-content > *:last-child { + margin-bottom: 0; +} + +/* Make sure the main container spans full viewport */ +.bk-root { + width: 100% !important; + max-width: 100% !important; +} + +/* Ensure consistent accordion appearance */ +.bk-panel-models-accordion .bk-panel-models-card { + border: 1px solid rgba(0, 0, 0, 0.125); + border-radius: 0.25rem; + overflow: hidden; +} + +/* Smooth transitions for accordion interactions */ +.bk-panel-models-accordion .bk-panel-models-card-content { + transition: all 0.3s ease; +} + +/* Remove spacing between text and icon in accordion headers */ +.bk-panel-models-accordion .bk-panel-models-card-header * { + margin: 0 !important; + padding: 0 !important; +} + +.bk-panel-models-accordion .bk-panel-models-card-header button { + padding: 16px 24px !important; +} + +.bk-panel-models-accordion .bk-panel-models-card-header button > *:first-child { + margin-right: 8px !important; +} + +.bk-panel-models-accordion .bk-panel-models-card-header button > *:last-child { + margin-left: 8px !important; +} +''' +#rgba(0, 0, 0, 0.03); +#"#005AA0" : rgba(0, 90, 160, 0.53); +# background-color: rgba(0, 90, 160, 0.53); diff --git a/survey_dashboard/hmc_layout/static/en_files/623c39184ca97bb437e258ef(1).html b/survey_dashboard/hmc_layout/static/en_files/623c39184ca97bb437e258ef(1).html new file mode 100644 index 0000000..a4a1eda --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/623c39184ca97bb437e258ef(1).html @@ -0,0 +1,3 @@ + + +cables HMC Animation




Cables Logo


\ No newline at end of file diff --git a/survey_dashboard/hmc_layout/static/en_files/623c39184ca97bb437e258ef.html b/survey_dashboard/hmc_layout/static/en_files/623c39184ca97bb437e258ef.html new file mode 100644 index 0000000..74f9fe0 --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/623c39184ca97bb437e258ef.html @@ -0,0 +1,3 @@ + + +cables




Cables Logo


\ No newline at end of file diff --git a/survey_dashboard/hmc_layout/static/en_files/Banner.png b/survey_dashboard/hmc_layout/static/en_files/Banner.png new file mode 100644 index 0000000..e79f97f Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/Banner.png differ diff --git a/survey_dashboard/hmc_layout/static/en_files/Banner2.png b/survey_dashboard/hmc_layout/static/en_files/Banner2.png new file mode 100644 index 0000000..794a4f4 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/Banner2.png differ diff --git a/survey_dashboard/hmc_layout/static/en_files/SurveyExplorerIcon.png b/survey_dashboard/hmc_layout/static/en_files/SurveyExplorerIcon.png new file mode 100644 index 0000000..51d8bf5 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/SurveyExplorerIcon.png differ diff --git a/survey_dashboard/hmc_layout/static/en_files/SurveyExplorerIcon16.png b/survey_dashboard/hmc_layout/static/en_files/SurveyExplorerIcon16.png new file mode 100644 index 0000000..69a7755 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/SurveyExplorerIcon16.png differ diff --git a/survey_dashboard/hmc_layout/static/en_files/SurveyExplorerLogoInverted.png b/survey_dashboard/hmc_layout/static/en_files/SurveyExplorerLogoInverted.png new file mode 100644 index 0000000..5e31f26 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/SurveyExplorerLogoInverted.png differ diff --git a/survey_dashboard/hmc_layout/static/en_files/app.css b/survey_dashboard/hmc_layout/static/en_files/app.css new file mode 100644 index 0000000..716cba9 --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/app.css @@ -0,0 +1,2326 @@ +@charset "UTF-8"; +/*! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com*/ +*, +:after, +:before { + border: 0 solid #ebecec; + box-sizing: border-box; +} +:after, +:before { + --tw-content: ""; +} +html { + -webkit-text-size-adjust: 100%; + font-feature-settings: normal; + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, + Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, + Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji; + line-height: 1.5; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; +} +body { + line-height: inherit; + margin: 0; +} +hr { + border-top-width: 1px; + color: inherit; + height: 0; +} +abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} +a { + color: inherit; + text-decoration: inherit; +} +b, +strong { + font-weight: bolder; +} +code, +kbd, +pre, +samp { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, + Liberation Mono, Courier New, monospace; + font-size: 1em; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sub { + bottom: -0.25em; +} +sup { + top: -0.5em; +} +table { + border-collapse: collapse; + border-color: inherit; + text-indent: 0; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; + font-family: inherit; + font-size: 100%; + font-weight: inherit; + line-height: inherit; + margin: 0; + padding: 0; +} +button, +select { + text-transform: none; +} +[type="button"], +[type="reset"], +[type="submit"], +button { + -webkit-appearance: button; + background-color: transparent; + background-image: none; +} +:-moz-focusring { + outline: auto; +} +:-moz-ui-invalid { + box-shadow: none; +} +progress { + vertical-align: baseline; +} +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} +[type="search"] { + -webkit-appearance: textfield; + outline-offset: -2px; +} +::-webkit-search-decoration { + -webkit-appearance: none; +} +::-webkit-file-upload-button { + -webkit-appearance: button; + font: inherit; +} +summary { + display: list-item; +} +blockquote, +dd, +dl, +figure, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +p, +pre { + margin: 0; +} +fieldset { + margin: 0; +} +fieldset, +legend { + padding: 0; +} +menu, +ol, +ul { + list-style: none; + margin: 0; + padding: 0; +} +textarea { + resize: vertical; +} +input::-moz-placeholder, +textarea::-moz-placeholder { + color: #7b878b; + opacity: 1; +} +input::placeholder, +textarea::placeholder { + color: #7b878b; + opacity: 1; +} +[role="button"], +button { + cursor: pointer; +} +:disabled { + cursor: default; +} +audio, +canvas, +embed, +iframe, +img, +object, +svg, +video { + display: block; + vertical-align: middle; +} +img, +video { + height: auto; + max-width: 100%; +} +[hidden] { + display: none; +} +*, +:after, +:before { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgba(59, 130, 246, 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} +::backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgba(59, 130, 246, 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} +.container { + margin-left: auto; + margin-right: auto; + padding-left: 20px; + padding-right: 20px; + width: 100%; +} +@media (min-width: 640px) { + .container { + max-width: 640px; + padding-left: 20px; + padding-right: 20px; + } +} +@media (min-width: 768px) { + .container { + max-width: 768px; + padding-left: 24px; + padding-right: 24px; + } +} +@media (min-width: 1024px) { + .container { + max-width: 1024px; + } +} +@media (min-width: 1280px) { + .container { + max-width: 1280px; + } +} +@media (min-width: 1536px) { + .container { + max-width: 1536px; + } +} +.pointer-events-none { + pointer-events: none; +} +.pointer-events-auto { + pointer-events: auto; +} +.visible { + visibility: visible; +} +.static { + position: static; +} +.fixed { + position: fixed; +} +.absolute { + position: absolute; +} +.relative { + position: relative; +} +.sticky { + position: sticky; +} +.top-0 { + top: 0; +} +.left-0 { + left: 0; +} +.top-8 { + top: 2rem; +} +.right-0 { + right: 0; +} +.left-1\/2 { + left: 50%; +} +.top-full { + top: 100%; +} +.bottom-0 { + bottom: 0; +} +.top-1\/2 { + top: 50%; +} +.right-6 { + right: 1.5rem; +} +.bottom-11 { + bottom: 2.75rem; +} +.z-40 { + z-index: 40; +} +.z-10 { + z-index: 10; +} +.z-20 { + z-index: 20; +} +.z-30 { + z-index: 30; +} +.z-50 { + z-index: 50; +} +.order-2 { + order: 2; +} +.order-1 { + order: 1; +} +.col-span-full { + grid-column: 1/-1; +} +.mx-0\.5 { + margin-left: 0.125rem; + margin-right: 0.125rem; +} +.mx-0 { + margin-left: 0; + margin-right: 0; +} +.mx-2 { + margin-left: 0.5rem; + margin-right: 0.5rem; +} +.mx-auto { + margin-left: auto; + margin-right: auto; +} +.mx-3 { + margin-left: 0.75rem; + margin-right: 0.75rem; +} +.mx-1 { + margin-left: 0.25rem; + margin-right: 0.25rem; +} +.my-10 { + margin-bottom: 2.5rem; + margin-top: 2.5rem; +} +.my-6 { + margin-bottom: 1.5rem; + margin-top: 1.5rem; +} +.my-20 { + margin-bottom: 5rem; + margin-top: 5rem; +} +.mb-12 { + margin-bottom: 3rem; +} +.mb-8 { + margin-bottom: 2rem; +} +.mb-4 { + margin-bottom: 1rem; +} +.mt-0 { + margin-top: 0; +} +.-ml-1 { + margin-left: -0.25rem; +} +.mb-1 { + margin-bottom: 0.25rem; +} +.-mb-2 { + margin-bottom: -0.5rem; +} +.mt-auto { + margin-top: auto; +} +.mb-10 { + margin-bottom: 2.5rem; +} +.mt-8 { + margin-top: 2rem; +} +.mr-2 { + margin-right: 0.5rem; +} +.mb-auto { + margin-bottom: auto; +} +.mb-2 { + margin-bottom: 0.5rem; +} +.ml-auto { + margin-left: auto; +} +.mb-3 { + margin-bottom: 0.75rem; +} +.mr-12 { + margin-right: 3rem; +} +.mb-16 { + margin-bottom: 4rem; +} +.mt-2 { + margin-top: 0.5rem; +} +.mb-6 { + margin-bottom: 1.5rem; +} +.mb-5 { + margin-bottom: 1.25rem; +} +.mb-\[60px\] { + margin-bottom: 60px; +} +.mr-4 { + margin-right: 1rem; +} +.mb-24 { + margin-bottom: 6rem; +} +.mb-20 { + margin-bottom: 5rem; +} +.mt-20 { + margin-top: 5rem; +} +.-mt-2 { + margin-top: -0.5rem; +} +.-ml-3 { + margin-left: -0.75rem; +} +.ml-2 { + margin-left: 0.5rem; +} +.mt-1 { + margin-top: 0.25rem; +} +.mr-auto { + margin-right: auto; +} +.mt-10 { + margin-top: 2.5rem; +} +.mb-2\.5 { + margin-bottom: 0.625rem; +} +.mb-\[40px\] { + margin-bottom: 40px; +} +.mb-0 { + margin-bottom: 0; +} +.mb-14 { + margin-bottom: 3.5rem; +} +.mr-3 { + margin-right: 0.75rem; +} +.mt-0\.5 { + margin-top: 0.125rem; +} +.box-border { + box-sizing: border-box; +} +.block { + display: block; +} +.inline-block { + display: inline-block; +} +.flex { + display: flex; +} +.inline-flex { + display: inline-flex; +} +.table { + display: table; +} +.grid { + display: grid; +} +.hidden { + display: none; +} +.h-full { + height: 100%; +} +.h-8 { + height: 2rem; +} +.h-fit { + height: -moz-fit-content; + height: fit-content; +} +.h-32 { + height: 8rem; +} +.h-4 { + height: 1rem; +} +.h-16 { + height: 4rem; +} +.h-\[320px\] { + height: 320px; +} +.h-px { + height: 1px; +} +.h-6 { + height: 1.5rem; +} +.max-h-90 { + max-height: 90vh; +} +.max-h-\[54px\] { + max-height: 54px; +} +.max-h-75 { + max-height: 75vh; +} +.min-h-\[60px\] { + min-height: 60px; +} +.min-h-\[80px\] { + min-height: 80px; +} +.w-full { + width: 100%; +} +.w-\[300px\] { + width: 300px; +} +.w-10 { + width: 2.5rem; +} +.w-\[258px\] { + width: 258px; +} +.w-\[1000px\] { + width: 1000px; +} +.w-screen { + width: 100vw; +} +.w-1\/3 { + width: 33.333333%; +} +.w-1\/2 { + width: 50%; +} +.w-11\/12 { + width: 91.666667%; +} +.w-2\/3 { + width: 66.666667%; +} +.w-3\/4 { + width: 75%; +} +.w-1\/4 { + width: 25%; +} +.w-6 { + width: 1.5rem; +} +.min-w-fit { + min-width: -moz-fit-content; + min-width: fit-content; +} +.max-w-\[700px\] { + max-width: 700px; +} +.max-w-max { + max-width: -moz-max-content; + max-width: max-content; +} +.max-w-full { + max-width: 100%; +} +.max-w-\[321px\] { + max-width: 321px; +} +.max-w-6xl { + max-width: 72rem; +} +.max-w-screen-lg { + max-width: 1024px; +} +.max-w-\[692px\] { + max-width: 692px; +} +.flex-shrink { + flex-shrink: 1; +} +.flex-shrink-0 { + flex-shrink: 0; +} +.flex-grow { + flex-grow: 1; +} +.origin-center { + transform-origin: center; +} +.origin-left { + transform-origin: left; +} +.-translate-x-1\/2 { + --tw-translate-x: -50%; +} +.-translate-x-1\/2, +.-translate-y-1\/2 { + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) + rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) + scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.-translate-y-1\/2 { + --tw-translate-y: -50%; +} +.translate-y-px { + --tw-translate-y: 1px; +} +.rotate-180, +.translate-y-px { + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) + rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) + scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.rotate-180 { + --tw-rotate: 180deg; +} +.rotate-90 { + --tw-rotate: 90deg; +} +.-rotate-90, +.rotate-90 { + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) + rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) + scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.-rotate-90 { + --tw-rotate: -90deg; +} +.scale-75 { + --tw-scale-x: 0.75; + --tw-scale-y: 0.75; +} +.scale-50, +.scale-75 { + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) + rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) + scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.scale-50 { + --tw-scale-x: 0.5; + --tw-scale-y: 0.5; +} +.transform { + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) + rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) + scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.cursor-pointer { + cursor: pointer; +} +.grid-flow-row { + grid-auto-flow: row; +} +.grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} +.grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); +} +.grid-cols-12 { + grid-template-columns: repeat(12, minmax(0, 1fr)); +} +.flex-row { + flex-direction: row; +} +.flex-row-reverse { + flex-direction: row-reverse; +} +.flex-col { + flex-direction: column; +} +.flex-wrap { + flex-wrap: wrap; +} +.items-start { + align-items: flex-start; +} +.items-end { + align-items: flex-end; +} +.items-center { + align-items: center; +} +.justify-end { + justify-content: flex-end; +} +.justify-center { + justify-content: center; +} +.justify-between { + justify-content: space-between; +} +.gap-2 { + gap: 0.5rem; +} +.gap-\[45px\] { + gap: 45px; +} +.gap-3 { + gap: 0.75rem; +} +.gap-4 { + gap: 1rem; +} +.gap-6 { + gap: 1.5rem; +} +.gap-2\.5 { + gap: 0.625rem; +} +.gap-20 { + gap: 5rem; +} +.gap-5 { + gap: 1.25rem; +} +.gap-x-\[60px\] { + -moz-column-gap: 60px; + column-gap: 60px; +} +.gap-y-\[70px\] { + row-gap: 70px; +} +.space-x-1 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-left: calc(0.25rem * (1 - var(--tw-space-x-reverse))); + margin-right: calc(0.25rem * var(--tw-space-x-reverse)); +} +.space-x-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-left: calc(1rem * (1 - var(--tw-space-x-reverse))); + margin-right: calc(1rem * var(--tw-space-x-reverse)); +} +.space-x-2 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-left: calc(0.5rem * (1 - var(--tw-space-x-reverse))); + margin-right: calc(0.5rem * var(--tw-space-x-reverse)); +} +.overflow-hidden { + overflow: hidden; +} +.overflow-y-auto { + overflow-y: auto; +} +.overflow-x-hidden { + overflow-x: hidden; +} +.overflow-y-hidden { + overflow-y: hidden; +} +.overflow-x-visible { + overflow-x: visible; +} +.whitespace-nowrap { + white-space: nowrap; +} +.break-words { + overflow-wrap: break-word; +} +.rounded-full { + border-radius: 9999px; +} +.rounded-lg { + border-radius: 0.5rem; +} +.rounded-md { + border-radius: 0.375rem; +} +.rounded-\[10px\] { + border-radius: 10px; +} +.rounded { + border-radius: 0.25rem; +} +.rounded-r-\[10px\] { + border-bottom-right-radius: 10px; + border-top-right-radius: 10px; +} +.border { + border-width: 1px; +} +.border-0 { + border-width: 0; +} +.border-t { + border-top-width: 1px; +} +.border-b { + border-bottom-width: 1px; +} +.border-t-4 { + border-top-width: 4px; +} +.border-b-4 { + border-bottom-width: 4px; +} +.border-gray-300 { + --tw-border-opacity: 1; + border-color: rgb(200 212 216 / var(--tw-border-opacity)); +} +.border-blue { + --tw-border-opacity: 1; + border-color: rgb(0 40 100 / var(--tw-border-opacity)); +} +.border-blue-light { + --tw-border-opacity: 1; + border-color: rgb(20 200 255 / var(--tw-border-opacity)); +} +.border-gray-200 { + --tw-border-opacity: 1; + border-color: rgb(235 236 236 / var(--tw-border-opacity)); +} +.border-green { + --tw-border-opacity: 1; + border-color: rgb(140 214 0 / var(--tw-border-opacity)); +} +.border-purple { + --tw-border-opacity: 1; + border-color: rgb(157 17 96 / var(--tw-border-opacity)); +} +.border-red { + --tw-border-opacity: 1; + border-color: rgb(210 50 100 / var(--tw-border-opacity)); +} +.border-orange { + --tw-border-opacity: 1; + border-color: rgb(240 120 30 / var(--tw-border-opacity)); +} +.border-yellow { + --tw-border-opacity: 1; + border-color: rgb(255 210 40 / var(--tw-border-opacity)); +} +.border-turquoise { + --tw-border-opacity: 1; + border-color: rgb(80 200 170 / var(--tw-border-opacity)); +} +.border-darkgreen { + --tw-border-opacity: 1; + border-color: rgb(50 100 105 / var(--tw-border-opacity)); +} +.border-blueviolet { + --tw-border-opacity: 1; + border-color: rgb(150 120 210 / var(--tw-border-opacity)); +} +.border-lightblue { + --tw-border-opacity: 1; + border-color: rgb(20 200 255 / var(--tw-border-opacity)); +} +.border-violet { + --tw-border-opacity: 1; + border-color: rgb(94 59 153 / var(--tw-border-opacity)); +} +.border-gray-400 { + --tw-border-opacity: 1; + border-color: rgb(123 135 139 / var(--tw-border-opacity)); +} +.border-gray-500 { + --tw-border-opacity: 1; + border-color: rgb(88 102 106 / var(--tw-border-opacity)); +} +.bg-blue, +.bg-blue-dark { + --tw-bg-opacity: 1; + background-color: rgb(0 40 100 / var(--tw-bg-opacity)); +} +.bg-blue-light { + --tw-bg-opacity: 1; + background-color: rgb(20 200 255 / var(--tw-bg-opacity)); +} +.bg-gray-100 { + --tw-bg-opacity: 1; + background-color: rgb(247 247 247 / var(--tw-bg-opacity)); +} +.bg-gray-500 { + --tw-bg-opacity: 1; + background-color: rgb(88 102 106 / var(--tw-bg-opacity)); +} +.bg-purple { + --tw-bg-opacity: 1; + background-color: rgb(157 17 96 / var(--tw-bg-opacity)); +} +.bg-red { + --tw-bg-opacity: 1; + background-color: rgb(210 50 100 / var(--tw-bg-opacity)); +} +.bg-orange { + --tw-bg-opacity: 1; + background-color: rgb(240 120 30 / var(--tw-bg-opacity)); +} +.bg-yellow { + --tw-bg-opacity: 1; + background-color: rgb(255 210 40 / var(--tw-bg-opacity)); +} +.bg-turquoise { + --tw-bg-opacity: 1; + background-color: rgb(80 200 170 / var(--tw-bg-opacity)); +} +.bg-darkgreen { + --tw-bg-opacity: 1; + background-color: rgb(50 100 105 / var(--tw-bg-opacity)); +} +.bg-green { + --tw-bg-opacity: 1; + background-color: rgb(140 214 0 / var(--tw-bg-opacity)); +} +.bg-blueviolet { + --tw-bg-opacity: 1; + background-color: rgb(150 120 210 / var(--tw-bg-opacity)); +} +.bg-violet { + --tw-bg-opacity: 1; + background-color: rgb(94 59 153 / var(--tw-bg-opacity)); +} +.bg-white { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); +} +.bg-gray-200 { + --tw-bg-opacity: 1; + background-color: rgb(235 236 236 / var(--tw-bg-opacity)); +} +.bg-transparent { + background-color: transparent; +} +.bg-gray-300 { + --tw-bg-opacity: 1; + background-color: rgb(200 212 216 / var(--tw-bg-opacity)); +} +.bg-opacity-20 { + --tw-bg-opacity: 0.2; +} +.bg-gradient-to-t { + background-image: linear-gradient(to top, var(--tw-gradient-stops)); +} +.from-white { + --tw-gradient-from: #fff; + --tw-gradient-to: hsla(0, 0%, 100%, 0); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} +.fill-blue { + fill: #002864; +} +.object-contain { + -o-object-fit: contain; + object-fit: contain; +} +.object-right-top { + -o-object-position: right top; + object-position: right top; +} +.p-4 { + padding: 1rem; +} +.p-5 { + padding: 1.25rem; +} +.p-\[50px\] { + padding: 50px; +} +.p-2 { + padding: 0.5rem; +} +.p-8 { + padding: 2rem; +} +.p-6 { + padding: 1.5rem; +} +.py-2 { + padding-bottom: 0.5rem; + padding-top: 0.5rem; +} +.px-4 { + padding-left: 1rem; + padding-right: 1rem; +} +.px-3 { + padding-left: 0.75rem; + padding-right: 0.75rem; +} +.py-1 { + padding-bottom: 0.25rem; + padding-top: 0.25rem; +} +.py-3 { + padding-bottom: 0.75rem; + padding-top: 0.75rem; +} +.py-5 { + padding-bottom: 1.25rem; + padding-top: 1.25rem; +} +.px-2 { + padding-left: 0.5rem; + padding-right: 0.5rem; +} +.px-5 { + padding-left: 1.25rem; + padding-right: 1.25rem; +} +.py-4 { + padding-bottom: 1rem; + padding-top: 1rem; +} +.py-20 { + padding-bottom: 5rem; + padding-top: 5rem; +} +.py-6 { + padding-bottom: 1.5rem; + padding-top: 1.5rem; +} +.pr-4 { + padding-right: 1rem; +} +.pb-4 { + padding-bottom: 1rem; +} +.pl-4 { + padding-left: 1rem; +} +.pb-20 { + padding-bottom: 5rem; +} +.pt-10 { + padding-top: 2.5rem; +} +.pt-3 { + padding-top: 0.75rem; +} +.pt-6 { + padding-top: 1.5rem; +} +.pt-8 { + padding-top: 2rem; +} +.pb-0 { + padding-bottom: 0; +} +.pb-3 { + padding-bottom: 0.75rem; +} +.pb-6 { + padding-bottom: 1.5rem; +} +.pb-8 { + padding-bottom: 2rem; +} +.pb-10 { + padding-bottom: 2.5rem; +} +.pt-1\.5 { + padding-top: 0.375rem; +} +.pb-2 { + padding-bottom: 0.5rem; +} +.pt-1 { + padding-top: 0.25rem; +} +.pb-\[30px\] { + padding-bottom: 30px; +} +.pl-3 { + padding-left: 0.75rem; +} +.pt-2 { + padding-top: 0.5rem; +} +.pr-6 { + padding-right: 1.5rem; +} +.pb-3\.5 { + padding-bottom: 0.875rem; +} +.pl-1 { + padding-left: 0.25rem; +} +.pb-16 { + padding-bottom: 4rem; +} +.pr-12 { + padding-right: 3rem; +} +.pb-12 { + padding-bottom: 3rem; +} +.pt-4 { + padding-top: 1rem; +} +.pr-8 { + padding-right: 2rem; +} +.text-left { + text-align: left; +} +.text-center { + text-align: center; +} +.text-right { + text-align: right; +} +.font-body { + font-family: 'HIFIS DIN', -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; +} +.font-display { + font-family: 'HIFIS DIN', -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; +} +.text-sm { + font-size: 15px; + line-height: 22px; +} +.text-2xl { + font-size: 32px; + line-height: 46px; +} +.text-xl { + font-size: 25px; + line-height: 34px; +} +.text-lg { + font-size: 20px; + line-height: 28px; +} +.text-base { + font-size: 17px; + line-height: 24px; +} +.text-xs { + font-size: 13px; + line-height: 16px; +} +.font-bold { + font-weight: 700; +} +.uppercase { + text-transform: uppercase; +} +.leading-9 { + line-height: 2.25rem; +} +.leading-8 { + line-height: 2rem; +} +.leading-7 { + line-height: 1.75rem; +} +.leading-none { + line-height: 1; +} +.leading-6 { + line-height: 1.5rem; +} +.tracking-widest { + letter-spacing: 0.1em; +} +.text-blue { + --tw-text-opacity: 1; + color: rgb(0 40 100 / var(--tw-text-opacity)); +} +.text-white { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} +.text-blue-dark { + --tw-text-opacity: 1; + color: rgb(0 40 100 / var(--tw-text-opacity)); +} +.text-gray-900 { + --tw-text-opacity: 1; + color: rgb(22 22 22 / var(--tw-text-opacity)); +} +.text-gray-400 { + --tw-text-opacity: 1; + color: rgb(123 135 139 / var(--tw-text-opacity)); +} +.text-gray-500 { + --tw-text-opacity: 1; + color: rgb(88 102 106 / var(--tw-text-opacity)); +} +.text-gray-100 { + --tw-text-opacity: 1; + color: rgb(247 247 247 / var(--tw-text-opacity)); +} +.text-purple { + --tw-text-opacity: 1; + color: rgb(157 17 96 / var(--tw-text-opacity)); +} +.text-red { + --tw-text-opacity: 1; + color: rgb(210 50 100 / var(--tw-text-opacity)); +} +.text-orange { + --tw-text-opacity: 1; + color: rgb(240 120 30 / var(--tw-text-opacity)); +} +.text-yellow { + --tw-text-opacity: 1; + color: rgb(255 210 40 / var(--tw-text-opacity)); +} +.text-turquoise { + --tw-text-opacity: 1; + color: rgb(80 200 170 / var(--tw-text-opacity)); +} +.text-darkgreen { + --tw-text-opacity: 1; + color: rgb(50 100 105 / var(--tw-text-opacity)); +} +.text-blue-light { + --tw-text-opacity: 1; + color: rgb(20 200 255 / var(--tw-text-opacity)); +} +.text-green { + --tw-text-opacity: 1; + color: rgb(140 214 0 / var(--tw-text-opacity)); +} +.text-blueviolet { + --tw-text-opacity: 1; + color: rgb(150 120 210 / var(--tw-text-opacity)); +} +.text-violet { + --tw-text-opacity: 1; + color: rgb(94 59 153 / var(--tw-text-opacity)); +} +.\!text-blue-light { + --tw-text-opacity: 1 !important; + color: rgb(20 200 255 / var(--tw-text-opacity)) !important; +} +.\!text-blue { + --tw-text-opacity: 1 !important; + color: rgb(0 40 100 / var(--tw-text-opacity)) !important; +} +.text-gray-800 { + --tw-text-opacity: 1; + color: rgb(63 69 71 / var(--tw-text-opacity)); +} +.antialiased { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.opacity-50 { + opacity: 0.5; +} +.opacity-0 { + opacity: 0; +} +.opacity-100 { + opacity: 1; +} +.opacity-75 { + opacity: 0.75; +} +.opacity-25 { + opacity: 0.25; +} +.shadow { + --tw-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1); + --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), + 0 1px 2px -1px var(--tw-shadow-color); +} +.shadow, +.shadow-xl { + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), + var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} +.shadow-xl { + --tw-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), + 0 8px 10px -6px rgba(0, 0, 0, 0.1); + --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), + 0 8px 10px -6px var(--tw-shadow-color); +} +.shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), + 0 2px 4px -2px rgba(0, 0, 0, 0.1); + --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), + 0 2px 4px -2px var(--tw-shadow-color); +} +.shadow-lg, +.shadow-md { + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), + var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} +.shadow-lg { + --tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), + 0 4px 6px -4px rgba(0, 0, 0, 0.1); + --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), + 0 4px 6px -4px var(--tw-shadow-color); +} +.outline-none { + outline: 2px solid transparent; + outline-offset: 2px; +} +.outline { + outline-style: solid; +} +.grayscale { + --tw-grayscale: grayscale(100%); +} +.filter, +.grayscale { + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) + var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) + var(--tw-sepia) var(--tw-drop-shadow); +} +.transition { + transition-duration: 0.15s; + transition-property: color, background-color, border-color, + text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, + -webkit-backdrop-filter; + transition-property: color, background-color, border-color, + text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, + backdrop-filter; + transition-property: color, background-color, border-color, + text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, + backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); +} +.transition-transform { + transition-duration: 0.15s; + transition-property: transform; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); +} +.transition-all { + transition-duration: 0.15s; + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); +} +.transition-opacity { + transition-duration: 0.15s; + transition-property: opacity; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); +} +.duration-200 { + transition-duration: 0.2s; +} +.duration-300 { + transition-duration: 0.3s; +} +.duration-150 { + transition-duration: 0.15s; +} +.duration-500 { + transition-duration: 0.5s; +} +.ease-out { + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); +} +.ease-in { + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); +} +.will-change-transform { + will-change: transform; +} +/* HIFIS DIN Font Family - Standard */ +@font-face { + font-family: 'HIFIS DIN'; + src: url(./fonts/hifis-din.woff2) format('woff2'), + url(./fonts/hifis-din.woff) format('woff'); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'HIFIS DIN'; + src: url(./fonts/hifis-din-bold.woff2) format('woff2'), + url(./fonts/hifis-din-bold.woff) format('woff'); + font-weight: bold; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'HIFIS DIN'; + src: url(./fonts/hifis-din-italic.woff2) format('woff2'), + url(./fonts/hifis-din-italic.woff) format('woff'); + font-weight: normal; + font-style: italic; + font-display: swap; +} + +/* HIFIS DIN Font Family - Expanded */ +@font-face { + font-family: 'HIFIS DIN Expanded'; + src: url(./fonts/hifis-din-exp.woff2) format('woff2'), + url(./fonts/hifis-din-exp.woff) format('woff'); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'HIFIS DIN Expanded'; + src: url(./fonts/hifis-din-exp-bold.woff2) format('woff2'), + url(./fonts/hifis-din-exp-bold.woff) format('woff'); + font-weight: bold; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'HIFIS DIN Expanded'; + src: url(./fonts/hifis-din-exp-italic.woff2) format('woff2'), + url(./fonts/hifis-din-exp-italic.woff) format('woff'); + font-weight: normal; + font-style: italic; + font-display: swap; +} + +/* HIFIS DIN Font Family - Condensed */ +@font-face { + font-family: 'HIFIS DIN Condensed'; + src: url(./fonts/hifis-din-condensed.woff2) format('woff2'), + url(./fonts/hifis-din-condensed.woff) format('woff'); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'HIFIS DIN Condensed'; + src: url(./fonts/hifis-din-condensed-bold.woff2) format('woff2'), + url(./fonts/hifis-din-condensed-bold.woff) format('woff'); + font-weight: bold; + font-style: normal; + font-display: swap; +} +.h1, +h1 { + font-size: 32px; + line-height: 46px; + line-height: 2.25rem; + margin-bottom: 3rem; + max-width: 700px; +} +.h1, +.h2, +h1, +h2 { + --tw-text-opacity: 1; + color: rgb(0 40 100 / var(--tw-text-opacity)); +} +.h2, +h2 { + font-size: 25px; + line-height: 34px; + line-height: 2rem; + margin-bottom: 2rem; + padding-right: 5rem; +} +.h3, +h3 { + --tw-text-opacity: 1; + color: rgb(0 40 100 / var(--tw-text-opacity)); + font-size: 20px; + line-height: 28px; + line-height: 1.75rem; + margin-bottom: 1rem; + padding-right: 1rem; +} +.h4, +h4 { + color: rgb(0 40 100 / var(--tw-text-opacity)); +} +.h4, +h4, +p { + --tw-text-opacity: 1; + font-size: 17px; + line-height: 24px; + margin-bottom: 1rem; +} +p { + color: rgb(22 22 22 / var(--tw-text-opacity)); + line-height: 1.75rem; +} +p a { + --tw-border-opacity: 1; + background-repeat: no-repeat; + border-bottom-width: 1px; + border-color: rgb(20 200 255 / var(--tw-border-opacity)); + color: rgb(0 40 100 / var(--tw-text-opacity)); + font-size: 17px; + line-height: 24px; + padding-bottom: 2px; + transition: all 0.3s; +} +p a, +p a:hover { + --tw-text-opacity: 1; +} +p a:hover { + color: rgb(20 200 255 / var(--tw-text-opacity)); + padding-bottom: 0; +} +.contact-wysiwyg p { + --tw-text-opacity: 1; + color: rgb(123 135 139 / var(--tw-text-opacity)); + font-size: 15px; + line-height: 22px; +} +.contact-wysiwyg ul { + margin-bottom: 10px; +} +.contact-wysiwyg ul li p { + display: inline-block; + margin-bottom: 10px; + padding-left: 16px; + position: relative; +} +.contact-wysiwyg ul li p:before { + --tw-bg-opacity: 1; + background-color: rgb(20 200 255 / var(--tw-bg-opacity)); + border-radius: 4px; + content: ""; + display: block; + height: 5px; + left: 2px; + position: absolute; + top: 8px; + width: 5px; +} +a.hmc-link { + --tw-border-opacity: 1; + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='10' height='7' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m6 1 3 2.684-3 2.684M1 1l3 2.647-3 2.647' stroke='%2314C8FF'/%3E%3C/svg%3E"); + background-position: 0; + background-repeat: no-repeat; + border-bottom-width: 1px; + border-color: rgb(20 200 255 / var(--tw-border-opacity)); + color: rgb(0 40 100 / var(--tw-text-opacity)); + font-size: 17px; + line-height: 24px; + max-width: -moz-max-content; + max-width: max-content; + padding-bottom: 2px; + padding-left: 1rem; + transition: all 0.3s; +} +a.hmc-link, +a.hmc-link:hover { + --tw-text-opacity: 1; +} +a.hmc-link:hover { + color: rgb(20 200 255 / var(--tw-text-opacity)); + padding-bottom: 0; +} +a.hmc-link_sm { + --tw-border-opacity: 1; + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='10' height='7' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m6 1 3 2.684-3 2.684M1 1l3 2.647-3 2.647' stroke='%2314C8FF'/%3E%3C/svg%3E"); + background-position: 0; + background-repeat: no-repeat; + border-bottom-width: 1px; + border-color: rgb(20 200 255 / var(--tw-border-opacity)); + color: rgb(0 40 100 / var(--tw-text-opacity)); + font-size: 15px; + line-height: 22px; + max-width: -moz-max-content; + max-width: max-content; + padding-bottom: 2px; + padding-left: 1rem; + transition: all 0.3s; +} +a.hmc-link_sm, +a.hmc-link_sm:hover { + --tw-text-opacity: 1; +} +a.hmc-link_sm:hover { + color: rgb(20 200 255 / var(--tw-text-opacity)); +} +article ul, +section ul { + margin-bottom: 10px; +} +article ul li p, +section ul li p { + display: inline-block; + line-height: 1.75rem; + margin-bottom: 10px; + padding-left: 24px; + position: relative; +} +article ul li p:before, +section ul li p:before { + --tw-bg-opacity: 1; + background-color: rgb(20 200 255 / var(--tw-bg-opacity)); + border-radius: 4px; + content: ""; + display: block; + height: 6px; + left: 0; + position: absolute; + top: 11px; + width: 6px; +} +.hmc-btn-outline { + --tw-border-opacity: 1; + --tw-text-opacity: 1; + border-color: rgb(0 40 100 / var(--tw-border-opacity)); + border-radius: 9999px; + border-width: 1px; + color: rgb(0 40 100 / var(--tw-text-opacity)); + display: inline-block; + font-size: 15px; + letter-spacing: 0.05em; + line-height: 22px; + padding: 0.5rem 1rem; + text-transform: uppercase; + transition: all 0.3s; +} +.hmc-btn-outline:hover { + --tw-bg-opacity: 1; + --tw-text-opacity: 1; + background-color: rgb(0 40 100 / var(--tw-bg-opacity)); +} +.hmc-btn, +.hmc-btn-outline:hover { + color: rgb(255 255 255 / var(--tw-text-opacity)); +} +.hmc-btn { + background-color: rgb(20 200 255 / var(--tw-bg-opacity)); + border-color: rgb(20 200 255 / var(--tw-border-opacity)); + border-radius: 9999px; + border-width: 1px; + display: inline-block; + font-size: 15px; + letter-spacing: 0.05em; + line-height: 22px; + padding: 0.5rem 1rem; + transition: all 0.3s; +} +.hmc-btn, +.hmc-btn:hover { + --tw-border-opacity: 1; + --tw-bg-opacity: 1; + --tw-text-opacity: 1; +} +.hmc-btn:hover { + background-color: rgb(0 40 100 / var(--tw-bg-opacity)); + border-color: rgb(0 40 100 / var(--tw-border-opacity)); + color: rgb(255 255 255 / var(--tw-text-opacity)); +} +.test { + color: #000; +} +.modal { + font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, + helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif; +} +.modal__overlay { + align-items: center; + background: rgba(0, 0, 0, 0.6); + bottom: 0; + display: flex; + justify-content: center; + left: 0; + position: fixed; + right: 0; + top: 0; + z-index: 2001; +} +.modal__container { + background-color: #fff; + border-radius: 4px; + box-sizing: border-box; + max-height: 100vh; + overflow-y: auto; + padding: 30px; +} +.modal__header { + align-items: center; + display: flex; + justify-content: space-between; +} +.modal__title { + box-sizing: border-box; + color: #00449e; + font-size: 1.25rem; + font-weight: 600; + line-height: 1.25; + margin-bottom: 0; + margin-top: 0; +} +.modal__close { + background: transparent; + border: 0; + min-width: 25px; +} +.modal__header .modal__close:before { + content: "✕"; +} +.modal__content { + color: rgba(0, 0, 0, 0.8); + line-height: 1.5; + margin-bottom: 2rem; + margin-top: 2rem; +} +.modal__btn { + -moz-osx-font-smoothing: grayscale; + -webkit-appearance: button; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + background-color: #e6e6e6; + border-radius: 0.25rem; + border-style: none; + border-width: 0; + color: rgba(0, 0, 0, 0.8); + cursor: pointer; + font-size: 0.875rem; + line-height: 1.15; + margin: 0; + overflow: visible; + padding: 0.5rem 1rem; + text-transform: none; + transform: translateZ(0); + transition: transform 0.25s ease-out; + will-change: transform; +} +.modal__btn:focus, +.modal__btn:hover { + transform: scale(1.05); +} +.modal__btn-primary { + background-color: #00449e; + color: #fff; +} +@keyframes mmfadeIn { + 0% { + opacity: 0; + } + to { + opacity: 1; + } +} +@keyframes mmfadeOut { + 0% { + opacity: 1; + } + to { + opacity: 0; + } +} +@keyframes mmslideIn { + 0% { + transform: translateY(15%); + } + to { + transform: translateY(0); + } +} +@keyframes mmslideOut { + 0% { + transform: translateY(0); + } + to { + transform: translateY(-10%); + } +} +.micromodal-slide { + display: none; +} +.micromodal-slide.is-open { + display: block; +} +.micromodal-slide[aria-hidden="false"] .modal__overlay { + animation: mmfadeIn 0.3s cubic-bezier(0, 0, 0.2, 1); +} +.micromodal-slide[aria-hidden="false"] .modal__container { + animation: mmslideIn 0.3s cubic-bezier(0, 0, 0.2, 1); +} +.micromodal-slide[aria-hidden="true"] .modal__overlay { + animation: mmfadeOut 0.3s cubic-bezier(0, 0, 0.2, 1); +} +.micromodal-slide[aria-hidden="true"] .modal__container { + animation: mmslideOut 0.3s cubic-bezier(0, 0, 0.2, 1); +} +.micromodal-slide .modal__container, +.micromodal-slide .modal__overlay { + will-change: transform; +} +.embla { + overflow: hidden; +} +.embla__container { + display: flex; + margin-left: -24px; +} +.embla__slide { + cursor: grab; + flex: 0 0 100%; + padding-left: 24px; + position: relative; +} +@media (min-width: 1024px) { + .embla { + overflow: hidden; + } + .embla__container { + display: flex; + margin-left: -24px; + transform: none !important; + } + .embla__slide { + cursor: grab; + flex: 0 0 100%; + left: 0; + opacity: 0; + padding-left: 24px; + position: absolute; + right: 0; + top: 0; + transition: opacity 1s; + } + .embla__slide.is-selected { + opacity: 1; + transition: opacity 1s; + transition-delay: 1s; + z-index: 1; + } +} +.embla__viewport:before { + content: '{ "loop": false, "align": "start", "slidesToScroll": 1, }'; + display: none; +} +.embla__button { + fill: #005799; + align-items: center; + background-color: #fff; + border: 0; + border-radius: 100%; + cursor: pointer; + display: flex; + height: 40px; + justify-content: center; + outline: 0; + padding: 0; + touch-action: manipulation; + transform: translateY(-50%); + width: 40px; + z-index: 1; +} +.embla__button:disabled { + cursor: default; + opacity: 0.5; +} +.embla__button--prev .embla__button__svg { + height: 30%; + margin-right: 2px; + width: 30%; +} +.embla__button--next .embla__button__svg { + height: 30%; + margin-left: 2px; + width: 30%; +} +.embla__dots { + align-items: center; + display: flex; + height: 100%; + justify-content: center; + list-style: none; +} +@media (min-width: 768px) { + .embla__dots { + justify-content: flex-end; + } +} +.embla__dot { + align-items: center; + background-color: transparent; + border: 0; + border-radius: 999px; + cursor: pointer; + display: flex; + height: 8px; + margin-left: 7.5px; + margin-right: 7.5px; + outline: 0; + padding: 0; + position: relative; + width: 8px; +} +.embla__dot:after { + background-color: #fff; + border-radius: 999px; + content: ""; + height: 100%; + opacity: 0.3; + width: 100%; +} +.embla__dot.is-selected:after { + background-color: #fff; + opacity: 1; +} +body { + --tw-bg-opacity: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + background-color: rgb(0 40 100 / var(--tw-bg-opacity)); + box-sizing: border-box; + font-family: 'HIFIS DIN', -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; +} +@media (min-width: 768px) { + .container { + padding-left: 3rem; + padding-right: 3rem; + } +} +.multiply { + mix-blend-mode: multiply; +} +.greyscale-100 { + filter: grayscale(100%); +} +.bg-gradient { + background-image: linear-gradient( + 270deg, + rgba(0, 147, 202, 0) 1%, + currentColor + ); +} +.embed-responsive { + height: auto; + overflow: hidden; + padding-bottom: 56.25%; + position: relative; +} +.embed-responsive iframe { + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 100%; +} +.line-clamp { + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + display: -webkit-box; +} +.card-text > p { + margin-bottom: 6px !important; +} +section table th { + padding-bottom: 1rem; + padding-right: 1rem; + vertical-align: top; +} +section table td { + --tw-border-opacity: 1; + border-color: rgb(200 212 216 / var(--tw-border-opacity)); + border-top-width: 1px; + padding-bottom: 0.5rem; + padding-right: 1rem; + padding-top: 0.5rem; + vertical-align: top; +} +.placeholder\:text-gray-400::-moz-placeholder { + --tw-text-opacity: 1; + color: rgb(123 135 139 / var(--tw-text-opacity)); +} +.placeholder\:text-gray-400::placeholder { + --tw-text-opacity: 1; + color: rgb(123 135 139 / var(--tw-text-opacity)); +} +.last\:border-white:last-child { + --tw-border-opacity: 1; + border-color: rgb(255 255 255 / var(--tw-border-opacity)); +} +.hover\:bg-gray-300:hover { + --tw-bg-opacity: 1; + background-color: rgb(200 212 216 / var(--tw-bg-opacity)); +} +.hover\:text-blue-light:hover { + --tw-text-opacity: 1; + color: rgb(20 200 255 / var(--tw-text-opacity)); +} +.hover\:opacity-100:hover { + opacity: 1; +} +.focus\:outline-none:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} +.focus\:ring:focus { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 + var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 + calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), + var(--tw-shadow, 0 0 #0000); +} +.focus\:ring-blue:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(0 40 100 / var(--tw-ring-opacity)); +} +.focus\:ring-opacity-30:focus { + --tw-ring-opacity: 0.3; +} +@media (min-width: 640px) { + .sm\:max-h-75 { + max-height: 75vh; + } + .sm\:text-3xl { + font-size: 40px; + line-height: 54px; + } +} +@media (min-width: 768px) { + .md\:right-12 { + right: 3rem; + } + .md\:m-3 { + margin: 0.75rem; + } + .md\:flex { + display: flex; + } + .md\:hidden { + display: none; + } + .md\:h-\[500px\] { + height: 500px; + } + .md\:w-2\/3 { + width: 66.666667%; + } + .md\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .md\:justify-between { + justify-content: space-between; + } + .md\:p-16 { + padding: 4rem; + } +} +@media (min-width: 1024px) { + .lg\:order-1 { + order: 1; + } + .lg\:order-2 { + order: 2; + } + .lg\:col-span-7 { + grid-column: span 7 / span 7; + } + .lg\:col-span-4 { + grid-column: span 4 / span 4; + } + .lg\:col-start-9 { + grid-column-start: 9; + } + .lg\:-ml-3 { + margin-left: -0.75rem; + } + .lg\:mb-0 { + margin-bottom: 0; + } + .lg\:flex { + display: flex; + } + .lg\:hidden { + display: none; + } + .lg\:w-min { + width: -moz-min-content; + width: min-content; + } + .lg\:w-2\/3 { + width: 66.666667%; + } + .lg\:w-1\/2 { + width: 50%; + } + .lg\:w-1\/3 { + width: 33.333333%; + } + .lg\:w-1\/4 { + width: 25%; + } + .lg\:w-2\/4 { + width: 50%; + } + .lg\:w-full { + width: 100%; + } + .lg\:w-3\/12 { + width: 25%; + } + .lg\:w-9\/12 { + width: 75%; + } + .lg\:w-8\/12 { + width: 66.666667%; + } + .lg\:w-56 { + width: 14rem; + } + .lg\:w-\[223px\] { + width: 223px; + } + .lg\:max-w-\[200px\] { + max-width: 200px; + } + .lg\:scale-90 { + --tw-scale-x: 0.9; + --tw-scale-y: 0.9; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) + rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) + scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + } + .lg\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + .lg\:grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + .lg\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .lg\:flex-row { + flex-direction: row; + } + .lg\:items-center { + align-items: center; + } + .lg\:justify-between { + justify-content: space-between; + } + .lg\:space-x-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-left: calc(1rem * (1 - var(--tw-space-x-reverse))); + margin-right: calc(1rem * var(--tw-space-x-reverse)); + } + .lg\:space-x-8 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-left: calc(2rem * (1 - var(--tw-space-x-reverse))); + margin-right: calc(2rem * var(--tw-space-x-reverse)); + } + .lg\:pt-20 { + padding-top: 5rem; + } + .lg\:pt-0 { + padding-top: 0; + } + .lg\:pt-6 { + padding-top: 1.5rem; + } + .lg\:pt-12 { + padding-top: 3rem; + } + .lg\:pt-16 { + padding-top: 4rem; + } + .lg\:pb-0 { + padding-bottom: 0; + } + .lg\:pb-6 { + padding-bottom: 1.5rem; + } + .lg\:pb-12 { + padding-bottom: 3rem; + } + .lg\:pb-16 { + padding-bottom: 4rem; + } + .lg\:pb-20 { + padding-bottom: 5rem; + } + .lg\:pr-20 { + padding-right: 5rem; + } + .lg\:pr-12 { + padding-right: 3rem; + } + .lg\:pr-4 { + padding-right: 1rem; + } + .lg\:pl-4 { + padding-left: 1rem; + } +} +@media (min-width: 1280px) { + .xl\:block { + display: block; + } + .xl\:flex { + display: flex; + } + .xl\:hidden { + display: none; + } + .xl\:scale-110 { + --tw-scale-x: 1.1; + --tw-scale-y: 1.1; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) + rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) + scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + } + .xl\:grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + .xl\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + .xl\:items-center { + align-items: center; + } + .xl\:justify-end { + justify-content: flex-end; + } + .xl\:pr-20 { + padding-right: 5rem; + } +} diff --git a/survey_dashboard/hmc_layout/static/en_files/app.js b/survey_dashboard/hmc_layout/static/en_files/app.js new file mode 100644 index 0000000..0e7f3bc --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/app.js @@ -0,0 +1,2 @@ +/*! For license information please see app.js.LICENSE.txt */ +(()=>{var e,t={669:(e,t,n)=>{e.exports=n(609)},448:(e,t,n)=>{"use strict";var r=n(867),o=n(26),i=n(372),l=n(327),a=n(97),s=n(109),c=n(985),u=n(61),f=n(655),p=n(263);e.exports=function(e){return new Promise((function(t,n){var d,h=e.data,m=e.headers,v=e.responseType;function g(){e.cancelToken&&e.cancelToken.unsubscribe(d),e.signal&&e.signal.removeEventListener("abort",d)}r.isFormData(h)&&delete m["Content-Type"];var y=new XMLHttpRequest;if(e.auth){var _=e.auth.username||"",b=e.auth.password?unescape(encodeURIComponent(e.auth.password)):"";m.Authorization="Basic "+btoa(_+":"+b)}var w=a(e.baseURL,e.url);function x(){if(y){var r="getAllResponseHeaders"in y?s(y.getAllResponseHeaders()):null,i={data:v&&"text"!==v&&"json"!==v?y.response:y.responseText,status:y.status,statusText:y.statusText,headers:r,config:e,request:y};o((function(e){t(e),g()}),(function(e){n(e),g()}),i),y=null}}if(y.open(e.method.toUpperCase(),l(w,e.params,e.paramsSerializer),!0),y.timeout=e.timeout,"onloadend"in y?y.onloadend=x:y.onreadystatechange=function(){y&&4===y.readyState&&(0!==y.status||y.responseURL&&0===y.responseURL.indexOf("file:"))&&setTimeout(x)},y.onabort=function(){y&&(n(u("Request aborted",e,"ECONNABORTED",y)),y=null)},y.onerror=function(){n(u("Network Error",e,null,y)),y=null},y.ontimeout=function(){var t=e.timeout?"timeout of "+e.timeout+"ms exceeded":"timeout exceeded",r=e.transitional||f.transitional;e.timeoutErrorMessage&&(t=e.timeoutErrorMessage),n(u(t,e,r.clarifyTimeoutError?"ETIMEDOUT":"ECONNABORTED",y)),y=null},r.isStandardBrowserEnv()){var k=(e.withCredentials||c(w))&&e.xsrfCookieName?i.read(e.xsrfCookieName):void 0;k&&(m[e.xsrfHeaderName]=k)}"setRequestHeader"in y&&r.forEach(m,(function(e,t){void 0===h&&"content-type"===t.toLowerCase()?delete m[t]:y.setRequestHeader(t,e)})),r.isUndefined(e.withCredentials)||(y.withCredentials=!!e.withCredentials),v&&"json"!==v&&(y.responseType=e.responseType),"function"==typeof e.onDownloadProgress&&y.addEventListener("progress",e.onDownloadProgress),"function"==typeof e.onUploadProgress&&y.upload&&y.upload.addEventListener("progress",e.onUploadProgress),(e.cancelToken||e.signal)&&(d=function(e){y&&(n(!e||e&&e.type?new p("canceled"):e),y.abort(),y=null)},e.cancelToken&&e.cancelToken.subscribe(d),e.signal&&(e.signal.aborted?d():e.signal.addEventListener("abort",d))),h||(h=null),y.send(h)}))}},609:(e,t,n)=>{"use strict";var r=n(867),o=n(849),i=n(321),l=n(185);var a=function e(t){var n=new i(t),a=o(i.prototype.request,n);return r.extend(a,i.prototype,n),r.extend(a,n),a.create=function(n){return e(l(t,n))},a}(n(655));a.Axios=i,a.Cancel=n(263),a.CancelToken=n(972),a.isCancel=n(502),a.VERSION=n(288).version,a.all=function(e){return Promise.all(e)},a.spread=n(713),a.isAxiosError=n(268),e.exports=a,e.exports.default=a},263:e=>{"use strict";function t(e){this.message=e}t.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")},t.prototype.__CANCEL__=!0,e.exports=t},972:(e,t,n)=>{"use strict";var r=n(263);function o(e){if("function"!=typeof e)throw new TypeError("executor must be a function.");var t;this.promise=new Promise((function(e){t=e}));var n=this;this.promise.then((function(e){if(n._listeners){var t,r=n._listeners.length;for(t=0;t{"use strict";e.exports=function(e){return!(!e||!e.__CANCEL__)}},321:(e,t,n)=>{"use strict";var r=n(867),o=n(327),i=n(782),l=n(572),a=n(185),s=n(875),c=s.validators;function u(e){this.defaults=e,this.interceptors={request:new i,response:new i}}u.prototype.request=function(e){"string"==typeof e?(e=arguments[1]||{}).url=arguments[0]:e=e||{},(e=a(this.defaults,e)).method?e.method=e.method.toLowerCase():this.defaults.method?e.method=this.defaults.method.toLowerCase():e.method="get";var t=e.transitional;void 0!==t&&s.assertOptions(t,{silentJSONParsing:c.transitional(c.boolean),forcedJSONParsing:c.transitional(c.boolean),clarifyTimeoutError:c.transitional(c.boolean)},!1);var n=[],r=!0;this.interceptors.request.forEach((function(t){"function"==typeof t.runWhen&&!1===t.runWhen(e)||(r=r&&t.synchronous,n.unshift(t.fulfilled,t.rejected))}));var o,i=[];if(this.interceptors.response.forEach((function(e){i.push(e.fulfilled,e.rejected)})),!r){var u=[l,void 0];for(Array.prototype.unshift.apply(u,n),u=u.concat(i),o=Promise.resolve(e);u.length;)o=o.then(u.shift(),u.shift());return o}for(var f=e;n.length;){var p=n.shift(),d=n.shift();try{f=p(f)}catch(e){d(e);break}}try{o=l(f)}catch(e){return Promise.reject(e)}for(;i.length;)o=o.then(i.shift(),i.shift());return o},u.prototype.getUri=function(e){return e=a(this.defaults,e),o(e.url,e.params,e.paramsSerializer).replace(/^\?/,"")},r.forEach(["delete","get","head","options"],(function(e){u.prototype[e]=function(t,n){return this.request(a(n||{},{method:e,url:t,data:(n||{}).data}))}})),r.forEach(["post","put","patch"],(function(e){u.prototype[e]=function(t,n,r){return this.request(a(r||{},{method:e,url:t,data:n}))}})),e.exports=u},782:(e,t,n)=>{"use strict";var r=n(867);function o(){this.handlers=[]}o.prototype.use=function(e,t,n){return this.handlers.push({fulfilled:e,rejected:t,synchronous:!!n&&n.synchronous,runWhen:n?n.runWhen:null}),this.handlers.length-1},o.prototype.eject=function(e){this.handlers[e]&&(this.handlers[e]=null)},o.prototype.forEach=function(e){r.forEach(this.handlers,(function(t){null!==t&&e(t)}))},e.exports=o},97:(e,t,n)=>{"use strict";var r=n(793),o=n(303);e.exports=function(e,t){return e&&!r(t)?o(e,t):t}},61:(e,t,n)=>{"use strict";var r=n(481);e.exports=function(e,t,n,o,i){var l=new Error(e);return r(l,t,n,o,i)}},572:(e,t,n)=>{"use strict";var r=n(867),o=n(527),i=n(502),l=n(655),a=n(263);function s(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new a("canceled")}e.exports=function(e){return s(e),e.headers=e.headers||{},e.data=o.call(e,e.data,e.headers,e.transformRequest),e.headers=r.merge(e.headers.common||{},e.headers[e.method]||{},e.headers),r.forEach(["delete","get","head","post","put","patch","common"],(function(t){delete e.headers[t]})),(e.adapter||l.adapter)(e).then((function(t){return s(e),t.data=o.call(e,t.data,t.headers,e.transformResponse),t}),(function(t){return i(t)||(s(e),t&&t.response&&(t.response.data=o.call(e,t.response.data,t.response.headers,e.transformResponse))),Promise.reject(t)}))}},481:e=>{"use strict";e.exports=function(e,t,n,r,o){return e.config=t,n&&(e.code=n),e.request=r,e.response=o,e.isAxiosError=!0,e.toJSON=function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:this.config,code:this.code,status:this.response&&this.response.status?this.response.status:null}},e}},185:(e,t,n)=>{"use strict";var r=n(867);e.exports=function(e,t){t=t||{};var n={};function o(e,t){return r.isPlainObject(e)&&r.isPlainObject(t)?r.merge(e,t):r.isPlainObject(t)?r.merge({},t):r.isArray(t)?t.slice():t}function i(n){return r.isUndefined(t[n])?r.isUndefined(e[n])?void 0:o(void 0,e[n]):o(e[n],t[n])}function l(e){if(!r.isUndefined(t[e]))return o(void 0,t[e])}function a(n){return r.isUndefined(t[n])?r.isUndefined(e[n])?void 0:o(void 0,e[n]):o(void 0,t[n])}function s(n){return n in t?o(e[n],t[n]):n in e?o(void 0,e[n]):void 0}var c={url:l,method:l,data:l,baseURL:a,transformRequest:a,transformResponse:a,paramsSerializer:a,timeout:a,timeoutMessage:a,withCredentials:a,adapter:a,responseType:a,xsrfCookieName:a,xsrfHeaderName:a,onUploadProgress:a,onDownloadProgress:a,decompress:a,maxContentLength:a,maxBodyLength:a,transport:a,httpAgent:a,httpsAgent:a,cancelToken:a,socketPath:a,responseEncoding:a,validateStatus:s};return r.forEach(Object.keys(e).concat(Object.keys(t)),(function(e){var t=c[e]||i,o=t(e);r.isUndefined(o)&&t!==s||(n[e]=o)})),n}},26:(e,t,n)=>{"use strict";var r=n(61);e.exports=function(e,t,n){var o=n.config.validateStatus;n.status&&o&&!o(n.status)?t(r("Request failed with status code "+n.status,n.config,null,n.request,n)):e(n)}},527:(e,t,n)=>{"use strict";var r=n(867),o=n(655);e.exports=function(e,t,n){var i=this||o;return r.forEach(n,(function(n){e=n.call(i,e,t)})),e}},655:(e,t,n)=>{"use strict";var r=n(155),o=n(867),i=n(16),l=n(481),a={"Content-Type":"application/x-www-form-urlencoded"};function s(e,t){!o.isUndefined(e)&&o.isUndefined(e["Content-Type"])&&(e["Content-Type"]=t)}var c,u={transitional:{silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},adapter:(("undefined"!=typeof XMLHttpRequest||void 0!==r&&"[object process]"===Object.prototype.toString.call(r))&&(c=n(448)),c),transformRequest:[function(e,t){return i(t,"Accept"),i(t,"Content-Type"),o.isFormData(e)||o.isArrayBuffer(e)||o.isBuffer(e)||o.isStream(e)||o.isFile(e)||o.isBlob(e)?e:o.isArrayBufferView(e)?e.buffer:o.isURLSearchParams(e)?(s(t,"application/x-www-form-urlencoded;charset=utf-8"),e.toString()):o.isObject(e)||t&&"application/json"===t["Content-Type"]?(s(t,"application/json"),function(e,t,n){if(o.isString(e))try{return(t||JSON.parse)(e),o.trim(e)}catch(e){if("SyntaxError"!==e.name)throw e}return(n||JSON.stringify)(e)}(e)):e}],transformResponse:[function(e){var t=this.transitional||u.transitional,n=t&&t.silentJSONParsing,r=t&&t.forcedJSONParsing,i=!n&&"json"===this.responseType;if(i||r&&o.isString(e)&&e.length)try{return JSON.parse(e)}catch(e){if(i){if("SyntaxError"===e.name)throw l(e,this,"E_JSON_PARSE");throw e}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*"}}};o.forEach(["delete","get","head"],(function(e){u.headers[e]={}})),o.forEach(["post","put","patch"],(function(e){u.headers[e]=o.merge(a)})),e.exports=u},288:e=>{e.exports={version:"0.24.0"}},849:e=>{"use strict";e.exports=function(e,t){return function(){for(var n=new Array(arguments.length),r=0;r{"use strict";var r=n(867);function o(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}e.exports=function(e,t,n){if(!t)return e;var i;if(n)i=n(t);else if(r.isURLSearchParams(t))i=t.toString();else{var l=[];r.forEach(t,(function(e,t){null!=e&&(r.isArray(e)?t+="[]":e=[e],r.forEach(e,(function(e){r.isDate(e)?e=e.toISOString():r.isObject(e)&&(e=JSON.stringify(e)),l.push(o(t)+"="+o(e))})))})),i=l.join("&")}if(i){var a=e.indexOf("#");-1!==a&&(e=e.slice(0,a)),e+=(-1===e.indexOf("?")?"?":"&")+i}return e}},303:e=>{"use strict";e.exports=function(e,t){return t?e.replace(/\/+$/,"")+"/"+t.replace(/^\/+/,""):e}},372:(e,t,n)=>{"use strict";var r=n(867);e.exports=r.isStandardBrowserEnv()?{write:function(e,t,n,o,i,l){var a=[];a.push(e+"="+encodeURIComponent(t)),r.isNumber(n)&&a.push("expires="+new Date(n).toGMTString()),r.isString(o)&&a.push("path="+o),r.isString(i)&&a.push("domain="+i),!0===l&&a.push("secure"),document.cookie=a.join("; ")},read:function(e){var t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove:function(e){this.write(e,"",Date.now()-864e5)}}:{write:function(){},read:function(){return null},remove:function(){}}},793:e=>{"use strict";e.exports=function(e){return/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(e)}},268:e=>{"use strict";e.exports=function(e){return"object"==typeof e&&!0===e.isAxiosError}},985:(e,t,n)=>{"use strict";var r=n(867);e.exports=r.isStandardBrowserEnv()?function(){var e,t=/(msie|trident)/i.test(navigator.userAgent),n=document.createElement("a");function o(e){var r=e;return t&&(n.setAttribute("href",r),r=n.href),n.setAttribute("href",r),{href:n.href,protocol:n.protocol?n.protocol.replace(/:$/,""):"",host:n.host,search:n.search?n.search.replace(/^\?/,""):"",hash:n.hash?n.hash.replace(/^#/,""):"",hostname:n.hostname,port:n.port,pathname:"/"===n.pathname.charAt(0)?n.pathname:"/"+n.pathname}}return e=o(window.location.href),function(t){var n=r.isString(t)?o(t):t;return n.protocol===e.protocol&&n.host===e.host}}():function(){return!0}},16:(e,t,n)=>{"use strict";var r=n(867);e.exports=function(e,t){r.forEach(e,(function(n,r){r!==t&&r.toUpperCase()===t.toUpperCase()&&(e[t]=n,delete e[r])}))}},109:(e,t,n)=>{"use strict";var r=n(867),o=["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"];e.exports=function(e){var t,n,i,l={};return e?(r.forEach(e.split("\n"),(function(e){if(i=e.indexOf(":"),t=r.trim(e.substr(0,i)).toLowerCase(),n=r.trim(e.substr(i+1)),t){if(l[t]&&o.indexOf(t)>=0)return;l[t]="set-cookie"===t?(l[t]?l[t]:[]).concat([n]):l[t]?l[t]+", "+n:n}})),l):l}},713:e=>{"use strict";e.exports=function(e){return function(t){return e.apply(null,t)}}},875:(e,t,n)=>{"use strict";var r=n(288).version,o={};["object","boolean","number","function","string","symbol"].forEach((function(e,t){o[e]=function(n){return typeof n===e||"a"+(t<1?"n ":" ")+e}}));var i={};o.transitional=function(e,t,n){function o(e,t){return"[Axios v"+r+"] Transitional option '"+e+"'"+t+(n?". "+n:"")}return function(n,r,l){if(!1===e)throw new Error(o(r," has been removed"+(t?" in "+t:"")));return t&&!i[r]&&(i[r]=!0,console.warn(o(r," has been deprecated since v"+t+" and will be removed in the near future"))),!e||e(n,r,l)}},e.exports={assertOptions:function(e,t,n){if("object"!=typeof e)throw new TypeError("options must be an object");for(var r=Object.keys(e),o=r.length;o-- >0;){var i=r[o],l=t[i];if(l){var a=e[i],s=void 0===a||l(a,i,e);if(!0!==s)throw new TypeError("option "+i+" must be "+s)}else if(!0!==n)throw Error("Unknown option "+i)}},validators:o}},867:(e,t,n)=>{"use strict";var r=n(849),o=Object.prototype.toString;function i(e){return"[object Array]"===o.call(e)}function l(e){return void 0===e}function a(e){return null!==e&&"object"==typeof e}function s(e){if("[object Object]"!==o.call(e))return!1;var t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}function c(e){return"[object Function]"===o.call(e)}function u(e,t){if(null!=e)if("object"!=typeof e&&(e=[e]),i(e))for(var n=0,r=e.length;n{"use strict";var r=n(821);const o={itemsToShow:1,itemsToScroll:1,modelValue:0,transition:300,autoplay:0,snapAlign:"center",wrapAround:!1,pauseAutoplayOnHover:!1,mouseDrag:!0,touchDrag:!0,dir:"ltr",breakpoints:void 0},i={itemsToShow:{default:o.itemsToShow,type:Number},itemsToScroll:{default:o.itemsToScroll,type:Number},wrapAround:{default:o.wrapAround,type:Boolean},snapAlign:{default:o.snapAlign,validator:e=>["start","end","center","center-even","center-odd"].includes(e)},transition:{default:o.transition,type:Number},breakpoints:{default:o.breakpoints,type:Object},autoplay:{default:o.autoplay,type:Number},pauseAutoplayOnHover:{default:o.pauseAutoplayOnHover,type:Boolean},modelValue:{default:void 0,type:Number},mouseDrag:{default:o.mouseDrag,type:Boolean},touchDrag:{default:o.touchDrag,type:Boolean},dir:{default:o.dir,validator:e=>["rtl","ltr"].includes(e)},settings:{default:()=>({}),type:Object}};function l(e,t,n,r){return e.wrapAround?t:Math.min(Math.max(t,r),n)}var a=(0,r.defineComponent)({name:"Carousel",props:i,setup(e,{slots:t,emit:n,expose:a}){var s;const c=(0,r.ref)(null),u=(0,r.ref)([]),f=(0,r.ref)([]),p=(0,r.ref)(0),d=(0,r.ref)(1);let h,m,v=(0,r.ref)({}),g=Object.assign({},o);const y=(0,r.reactive)(Object.assign({},g)),_=(0,r.ref)(null!==(s=y.modelValue)&&void 0!==s?s:0),b=(0,r.ref)(0),w=(0,r.ref)(0),x=(0,r.ref)(0),k=(0,r.ref)(0);function S(){const t=Object.assign(Object.assign({},e),e.settings);v=(0,r.ref)(Object.assign({},t.breakpoints)),g=Object.assign(Object.assign({},t),{settings:void 0,breakpoints:void 0}),C(g)}function E(){const e=Object.keys(v.value).map((e=>Number(e))).sort(((e,t)=>+t-+e));let t=Object.assign({},g);e.some((e=>!!window.matchMedia(`(min-width: ${e}px)`).matches&&(t=Object.assign(Object.assign({},t),v.value[e]),!0))),C(t)}function C(e){for(let t in e)y[t]=e[t]}(0,r.provide)("config",y),(0,r.provide)("slidesBuffer",f),(0,r.provide)("slidesCount",d),(0,r.provide)("currentSlide",_),(0,r.provide)("maxSlide",x),(0,r.provide)("minSlide",k);const T=function(e,t){let n;return function(...r){n&&clearTimeout(n),n=setTimeout((()=>{e(...r),n=null}),t)}}((()=>{v.value&&(E(),L()),N()}),16);function N(){if(!c.value)return;const e=c.value.getBoundingClientRect();p.value=e.width/y.itemsToShow}function L(){d.value=Math.max(u.value.length,1),d.value<=0||(w.value=Math.ceil((d.value-1)/2),x.value=function(e,t){if(e.wrapAround)return t-1;switch(e.snapAlign){case"start":return t-e.itemsToShow;case"end":return t-1;case"center":case"center-odd":case"center-even":return t-Math.ceil(e.itemsToShow/2);default:return 0}}(y,d.value),k.value=function(e){if(e.wrapAround)return 0;switch(e.snapAlign){case"start":default:return 0;case"end":return e.itemsToShow-1;case"center":case"center-odd":return Math.floor((e.itemsToShow-1)/2);case"center-even":return Math.floor((e.itemsToShow-2)/2)}}(y),_.value=l(y,_.value,x.value,k.value))}function O(){const e=[...Array(d.value).keys()];if(y.wrapAround&&y.itemsToShow+1<=d.value){let t=(1!==y.itemsToShow?Math.round((d.value-y.itemsToShow)/2):0)-_.value;if("end"===y.snapAlign?t+=Math.floor(y.itemsToShow-1):"center"!==y.snapAlign&&"center-odd"!==y.snapAlign||t++,t<0)for(let n=t;n<0;n++)e.push(Number(e.shift()));else for(let n=0;n{v.value&&(E(),L()),(0,r.nextTick)((()=>setTimeout(N,16))),$(),window.addEventListener("resize",T,{passive:!0})})),(0,r.onUnmounted)((()=>{m&&clearTimeout(m),h&&clearInterval(h)}));let A=!1;const P={x:0,y:0},I={x:0,y:0},R=(0,r.reactive)({x:0,y:0}),F=(0,r.ref)(!1),M=()=>{F.value=!0},B=()=>{F.value=!1};function j(e){A="touchstart"===e.type,!A&&0!==e.button||W.value||(A||e.preventDefault(),P.x=A?e.touches[0].clientX:e.clientX,P.y=A?e.touches[0].clientY:e.clientY,document.addEventListener(A?"touchmove":"mousemove",V,!0),document.addEventListener(A?"touchend":"mouseup",D,!0))}const V=function(e,t){let n;return function(...r){const o=this;n||(e.apply(o,r),n=!0,setTimeout((()=>n=!1),t))}}((e=>{I.x=A?e.touches[0].clientX:e.clientX,I.y=A?e.touches[0].clientY:e.clientY;const t=I.x-P.x,n=I.y-P.y;R.y=n,R.x=t}),16);function D(){const e="rtl"===y.dir?-1:1,t=.4*Math.sign(R.x),n=Math.round(R.x/p.value+t)*e;let r=l(y,_.value-n,x.value,k.value);if(n&&!A){const e=t=>{t.stopPropagation(),window.removeEventListener("click",e,!0)};window.addEventListener("click",e,!0)}H(r),R.x=0,R.y=0,document.removeEventListener(A?"touchmove":"mousemove",V,!0),document.removeEventListener(A?"touchend":"mouseup",D,!0)}function $(){!y.autoplay||y.autoplay<=0||(h=setInterval((()=>{y.pauseAutoplayOnHover&&F.value||z()}),y.autoplay))}function U(){h&&(clearInterval(h),h=null),$()}const W=(0,r.ref)(!1);function H(e,t=!1){if(_.value===e||W.value)return;U();return e>d.value-1?H(e-d.value):e<0?H(e+d.value):(W.value=!0,b.value=_.value,_.value=e,t||n("update:modelValue",_.value),void(m=setTimeout((()=>{y.wrapAround&&O(),W.value=!1}),y.transition)))}function z(){let e=_.value+y.itemsToScroll;y.wrapAround||(e=Math.min(e,x.value)),H(e)}function G(){let e=_.value-y.itemsToScroll;y.wrapAround||(e=Math.max(e,k.value)),H(e)}const q={slideTo:H,next:z,prev:G};(0,r.provide)("nav",q);const J=(0,r.computed)((()=>function({slidesBuffer:e,currentSlide:t,snapAlign:n,itemsToShow:r,wrapAround:o,slidesCount:i}){let l=e.indexOf(t);if(-1===l&&(l=e.indexOf(Math.ceil(t))),"center"===n||"center-odd"===n?l-=(r-1)/2:"center-even"===n?l-=(r-2)/2:"end"===n&&(l-=r-1),!o){const e=i-r,t=0;l=Math.max(Math.min(l,e),t)}return l}({slidesBuffer:f.value,itemsToShow:y.itemsToShow,snapAlign:y.snapAlign,wrapAround:Boolean(y.wrapAround),currentSlide:_.value,slidesCount:d.value})));(0,r.provide)("slidesToScroll",J);const K=(0,r.computed)((()=>{const e="rtl"===y.dir?-1:1,t=J.value*p.value*e;return{transform:`translateX(${R.x-t}px)`,transition:`${W.value?y.transition:0}ms`}}));function Y(){S()}function Z(){S(),E(),L(),O(),N(),U()}function X(){L(),O()}Object.keys(i).forEach((t=>{["modelValue"].includes(t)||(0,r.watch)((()=>e[t]),Z)})),Y(),(0,r.watchEffect)((()=>{const t=d.value!==u.value.length;void 0!==e.modelValue&&_.value!==e.modelValue&&H(Number(e.modelValue),!0),t&&X()}));const Q={config:y,slidesBuffer:f,slidesCount:d,slideWidth:p,currentSlide:_,maxSlide:x,minSlide:k,middleSlide:w};a({updateBreakpointsConfigs:E,updateSlidesData:L,updateSlideWidth:N,updateSlidesBuffer:O,initCarousel:Y,restartCarousel:Z,updateCarousel:X,slideTo:H,next:z,prev:G,nav:q,data:Q});const ee=t.default||t.slides,te=t.addons,ne=(0,r.reactive)(Q);return()=>{const e=function(e){var t,n,r;return e?"CarouselSlide"===(null===(n=null===(t=e[0])||void 0===t?void 0:t.type)||void 0===n?void 0:n.name)?e:(null===(r=e[0])||void 0===r?void 0:r.children)||[]:[]}(null==ee?void 0:ee(ne)),t=(null==te?void 0:te(ne))||[];u.value=e,e.forEach(((e,t)=>e.props.index=t));const n=(0,r.h)("ol",{class:"carousel__track",style:K.value,onMousedown:y.mouseDrag?(0,r.withModifiers)(j,["capture"]):null,onTouchstart:y.touchDrag?(0,r.withModifiers)(j,["capture"]):null},e),o=(0,r.h)("div",{class:"carousel__viewport"},n);return(0,r.h)("section",{ref:c,class:{carousel:!0,"carousel--rtl":"rtl"===y.dir},dir:y.dir,"aria-label":"Gallery",onMouseenter:M,onMouseleave:B},[o,t])}}});const s={arrowUp:"M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z",arrowDown:"M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z",arrowRight:"M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z",arrowLeft:"M15.41 16.59L10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z"},c=e=>{const t=e.name;if(!t||"string"!=typeof t)return;const n=s[t],o=(0,r.h)("path",{d:n}),i=e.title||t,l=(0,r.h)("title",i);return(0,r.h)("svg",{class:"carousel__icon",viewBox:"0 0 24 24",role:"img",ariaLabel:i},[l,o])};c.props={name:String,title:String};const u=(e,{slots:t,attrs:n})=>{const{next:i,prev:l}=t||{},a=(0,r.inject)("config",(0,r.reactive)(Object.assign({},o))),s=(0,r.inject)("maxSlide",(0,r.ref)(1)),u=(0,r.inject)("minSlide",(0,r.ref)(1)),f=(0,r.inject)("currentSlide",(0,r.ref)(1)),p=(0,r.inject)("nav",{}),d="rtl"===a.dir;return[(0,r.h)("button",{type:"button",class:["carousel__prev",!a.wrapAround&&f.value<=u.value&&"carousel__prev--in-active",null==n?void 0:n.class],"aria-label":"Navigate to previous slide",onClick:p.prev},(null==l?void 0:l())||(0,r.h)(c,{name:d?"arrowRight":"arrowLeft"})),(0,r.h)("button",{type:"button",class:["carousel__next",!a.wrapAround&&f.value>=s.value&&"carousel__next--in-active",null==n?void 0:n.class],"aria-label":"Navigate to next slide",onClick:p.next},(null==i?void 0:i())||(0,r.h)(c,{name:d?"arrowLeft":"arrowRight"}))]};var f=(0,r.defineComponent)({name:"CarouselSlide",props:{index:{type:Number,default:1}},setup(e,{slots:t}){const n=(0,r.inject)("config",(0,r.reactive)(Object.assign({},o))),i=(0,r.inject)("slidesBuffer",(0,r.ref)([])),l=(0,r.inject)("currentSlide",(0,r.ref)(0)),a=(0,r.inject)("slidesToScroll",(0,r.ref)(0)),s=(0,r.ref)(e.index);function c(){s.value=i.value.indexOf(e.index)}n.wrapAround&&(c(),(0,r.watch)(i,c));const u=(0,r.computed)((()=>({width:1/n.itemsToShow*100+"%",order:s.value.toString()}))),f=()=>{const t=Math.ceil(a.value),r=Math.floor(a.value+n.itemsToShow);return i.value.slice(t,r).includes(e.index)};return()=>{var o;return(0,r.h)("li",{style:u.value,class:{carousel__slide:!0,"carousel__slide--active":e.index===l.value,"carousel__slide--visible":f(),"carousel__slide--prev":e.index===i.value[Math.ceil(a.value)-1],"carousel__slide--next":e.index===i.value[Math.floor(a.value+n.itemsToShow)]}},null===(o=t.default)||void 0===o?void 0:o.call(t))}}});const p=()=>{const e=(0,r.inject)("maxSlide",(0,r.ref)(1)),t=(0,r.inject)("minSlide",(0,r.ref)(1)),n=(0,r.inject)("currentSlide",(0,r.ref)(1)),o=(0,r.inject)("nav",{});const i=r=>{const o=n.value;return o===r||o>e.value&&r>=e.value||o{return e=n,void o.slideTo(e);var e}}),t=(0,r.h)("li",{class:"carousel__pagination-item",key:n},e);l.push(t)}return(0,r.h)("ol",{class:"carousel__pagination"},l)};var d={key:0,class:"w-full"},h={class:"flex flex-col w-full h-full bg-white shadow md:m-3"},m={key:0},v=["href"],g=["src"],y=["href"],_=["src"],b={class:"flex flex-col items-start w-full h-full p-4"},w={key:0,class:"flex flex-wrap gap-2 mt-0 mb-4 -ml-1"},x=["href"],k={class:"inline-block mb-1 text-sm text-gray-500"},S={class:"-mb-2"},E={key:0},C=["href"],T=["href"];const N={__name:"NewsCarouselNext",props:{slides:{type:Array,required:!0}},setup:function(e){var t=function(e){return e.filter((function(e){return 1==e.visible}))},n={itemsToShow:1,wrapAround:!1,touchDrag:!0,mouseDrag:!0,itemsToScroll:1,transition:400,snapAlign:"start"},o={768:{itemsToShow:2,itemsToScroll:2,snapAlign:"start"},1024:{itemsToShow:3,itemsToScroll:3,snapAlign:"start"},1280:{itemsToShow:4,itemsToScroll:4,snapAlign:"start"}};return function(i,l){return e.slides.length>0?((0,r.openBlock)(),(0,r.createElementBlock)("div",d,[(0,r.createVNode)((0,r.unref)(a),{snapAlign:"start",settings:n,breakpoints:o},{addons:(0,r.withCtx)((function(e){return[e.slidesCount>1?((0,r.openBlock)(),(0,r.createBlock)((0,r.unref)(u),{key:0})):(0,r.createCommentVNode)("",!0),(0,r.createVNode)((0,r.unref)(p))]})),default:(0,r.withCtx)((function(){return[((0,r.openBlock)(!0),(0,r.createElementBlock)(r.Fragment,null,(0,r.renderList)(e.slides,(function(e){return(0,r.openBlock)(),(0,r.createBlock)((0,r.unref)(f),{key:e},{default:(0,r.withCtx)((function(){return[(0,r.createElementVNode)("div",h,[e.image?((0,r.openBlock)(),(0,r.createElementBlock)("div",m,[e.url?((0,r.openBlock)(),(0,r.createElementBlock)("a",{key:1,class:"w-full",href:e.url},[(0,r.createElementVNode)("img",{src:e.image.conversion_urls.md,alt:"",class:"w-full"},null,8,_)],8,y)):((0,r.openBlock)(),(0,r.createElementBlock)("a",{key:0,class:"w-full",href:e.route_url},[(0,r.createElementVNode)("img",{src:e.image.conversion_urls.md,alt:"",class:"w-full"},null,8,g)],8,v))])):(0,r.createCommentVNode)("",!0),(0,r.createElementVNode)("div",b,[t(e.tags).length>0?((0,r.openBlock)(),(0,r.createElementBlock)("div",w,[((0,r.openBlock)(!0),(0,r.createElementBlock)(r.Fragment,null,(0,r.renderList)(t(e.tags),(function(e){return(0,r.openBlock)(),(0,r.createElementBlock)("div",null,[e.visible?((0,r.openBlock)(),(0,r.createElementBlock)("a",{key:0,href:e.route,class:(0,r.normalizeClass)(["inline-flex items-center justify-center px-3 pt-1.5 pb-2 text-sm leading-none rounded-lg bg-opacity-20",e.color?"bg-".concat(e.color," text-").concat(e.color):"bg-blue text-blue"])},(0,r.toDisplayString)(e.title),11,x)):(0,r.createCommentVNode)("",!0)])})),256))])):(0,r.createCommentVNode)("",!0),(0,r.createElementVNode)("span",k,(0,r.toDisplayString)(e.published_at),1),(0,r.createElementVNode)("h3",S,[(0,r.createTextVNode)((0,r.toDisplayString)(e.title.replace(/^(.{60}[^\s]*).*/,"$1"))+" ",1),e.title.length>60?((0,r.openBlock)(),(0,r.createElementBlock)("span",E," …")):(0,r.createCommentVNode)("",!0)]),e.url?((0,r.openBlock)(),(0,r.createElementBlock)("a",{key:2,class:"mt-auto hmc-link",href:e.url},(0,r.toDisplayString)(i.$t("app.read-more")),9,T)):((0,r.openBlock)(),(0,r.createElementBlock)("a",{key:1,class:"mt-auto hmc-link",href:e.route_url},(0,r.toDisplayString)(i.$t("app.read-more")),9,C))])])]})),_:2},1024)})),128))]})),_:1})])):(0,r.createCommentVNode)("",!0)}}};var L=n(379),O=n.n(L),A=n(236),P={insert:"head",singleton:!1};O()(A.Z,P);A.Z.locals;const I=N;var R={key:0,class:"w-full"},F={key:0},M=["href"],B=["src"],j=["href"],V=["src"],D={class:"flex flex-col w-full h-full p-4"},$={key:0,class:"flex flex-wrap gap-2 mt-0 mb-4 -ml-1"},U=["href"],W={key:1,class:"flex mb-1 space-x-1"},H={key:0,class:"text-sm text-gray-500"},z={key:1,class:"text-sm text-gray-500"},G={key:2,class:"flex mb-1 space-x-1"},q={key:0,class:"text-sm text-gray-500"},J={key:1,class:"text-sm text-gray-500"},K={class:"-mb-2"},Y={key:0},Z=["href"],X=["href"];const Q={__name:"EventsCarouselNext",props:{slides:{type:Array,required:!0}},setup:function(e){var t=function(e){return e.filter((function(e){return 1==e.visible}))},n={itemsToShow:1,wrapAround:!1,touchDrag:!0,mouseDrag:!0,itemsToScroll:1,transition:400,snapAlign:"start"},o={768:{itemsToShow:2,itemsToScroll:2,snapAlign:"start"},1024:{itemsToShow:3,itemsToScroll:3,snapAlign:"start"},1280:{itemsToShow:4,itemsToScroll:4,snapAlign:"start"}};return function(i,l){return e.slides.length>0?((0,r.openBlock)(),(0,r.createElementBlock)("div",R,[(0,r.createVNode)((0,r.unref)(a),{snapAlign:"start",settings:n,breakpoints:o},{addons:(0,r.withCtx)((function(e){return[e.slidesCount>1?((0,r.openBlock)(),(0,r.createBlock)((0,r.unref)(u),{key:0})):(0,r.createCommentVNode)("",!0),(0,r.createVNode)((0,r.unref)(p))]})),default:(0,r.withCtx)((function(){return[((0,r.openBlock)(!0),(0,r.createElementBlock)(r.Fragment,null,(0,r.renderList)(e.slides,(function(e){return(0,r.openBlock)(),(0,r.createBlock)((0,r.unref)(f),{key:e},{default:(0,r.withCtx)((function(){return[(0,r.createElementVNode)("div",{class:(0,r.normalizeClass)(["flex flex-col w-full h-full bg-white shadow md:m-3",{"opacity-50":e.in_past}])},[e.image?((0,r.openBlock)(),(0,r.createElementBlock)("div",F,[e.url?((0,r.openBlock)(),(0,r.createElementBlock)("a",{key:1,class:"w-full",href:e.url},[(0,r.createElementVNode)("img",{src:e.image.conversion_urls.md,alt:"",class:"w-full"},null,8,V)],8,j)):((0,r.openBlock)(),(0,r.createElementBlock)("a",{key:0,class:"w-full",href:e.route_url},[(0,r.createElementVNode)("img",{src:e.image.conversion_urls.md,alt:"",class:"w-full"},null,8,B)],8,M))])):(0,r.createCommentVNode)("",!0),(0,r.createElementVNode)("div",D,[t(e.tags).length>0?((0,r.openBlock)(),(0,r.createElementBlock)("div",$,[((0,r.openBlock)(!0),(0,r.createElementBlock)(r.Fragment,null,(0,r.renderList)(t(e.tags),(function(e){return(0,r.openBlock)(),(0,r.createElementBlock)("div",null,[e.visible?((0,r.openBlock)(),(0,r.createElementBlock)("a",{key:0,href:e.route,class:(0,r.normalizeClass)(["inline-flex items-center justify-center px-3 pt-1.5 pb-2 text-sm leading-none rounded-lg bg-opacity-20",e.color?"bg-".concat(e.color," text-").concat(e.color):"bg-blue text-blue"])},(0,r.toDisplayString)(e.title),11,U)):(0,r.createCommentVNode)("",!0)])})),256))])):(0,r.createCommentVNode)("",!0),e.starts_at!=e.ends_at?((0,r.openBlock)(),(0,r.createElementBlock)("div",W,[e.starts_at?((0,r.openBlock)(),(0,r.createElementBlock)("span",H,(0,r.toDisplayString)(e.starts_at),1)):(0,r.createCommentVNode)("",!0),e.ends_at?((0,r.openBlock)(),(0,r.createElementBlock)("span",z," - "+(0,r.toDisplayString)(e.ends_at),1)):(0,r.createCommentVNode)("",!0)])):(0,r.createCommentVNode)("",!0),e.starts_at==e.ends_at?((0,r.openBlock)(),(0,r.createElementBlock)("div",G,[e.starts_at?((0,r.openBlock)(),(0,r.createElementBlock)("span",q,(0,r.toDisplayString)(e.starts_at),1)):(0,r.createCommentVNode)("",!0),e.time?((0,r.openBlock)(),(0,r.createElementBlock)("span",J," | "+(0,r.toDisplayString)(e.time),1)):(0,r.createCommentVNode)("",!0)])):(0,r.createCommentVNode)("",!0),(0,r.createElementVNode)("h3",K,[(0,r.createTextVNode)((0,r.toDisplayString)(e.title.replace(/^(.{60}[^\s]*).*/,"$1"))+" ",1),e.title.length>60?((0,r.openBlock)(),(0,r.createElementBlock)("span",Y," …")):(0,r.createCommentVNode)("",!0)]),e.url?((0,r.openBlock)(),(0,r.createElementBlock)("a",{key:4,class:"mt-auto hmc-link",href:e.url},(0,r.toDisplayString)(i.$t("app.read-more")),9,X)):((0,r.openBlock)(),(0,r.createElementBlock)("a",{key:3,class:"mt-auto hmc-link",href:e.route_url},(0,r.toDisplayString)(i.$t("app.read-more")),9,Z))])],2)]})),_:2},1024)})),128))]})),_:1})])):(0,r.createCommentVNode)("",!0)}}};var ee=n(563),te={insert:"head",singleton:!1};O()(ee.Z,te);ee.Z.locals;const ne=Q;function re(e){return function(e){if(Array.isArray(e))return oe(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return oe(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return oe(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function oe(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0){var r=a(t.dataobjects),o=s(t.dataobjects),i=c(t.dataobjects),l=u(t.dataobjects);e=function(e){for(var t=new Set,n=0;n0&&(e=e.filter((function(e){var t=e.tags.map((function(e){return e.id}));return f.value.every((function(e){return t.includes(e)}))}))),e}))),a=function(e){return e.filter((function(e){var t;return null===(t=e.keywords)||void 0===t?void 0:t.toLowerCase().includes(n.value.toLocaleLowerCase())}))},s=function(e){return e.filter((function(e){var t;return null===(t=e.title)||void 0===t?void 0:t.toLowerCase().includes(n.value.toLocaleLowerCase())}))},c=function(e){return e.filter((function(e){var t;return null===(t=e.text)||void 0===t?void 0:t.toLowerCase().includes(n.value.toLocaleLowerCase())}))},u=function(e){return e.filter((function(e){var t;return null===(t=e.excerpt)||void 0===t?void 0:t.toLowerCase().includes(n.value.toLocaleLowerCase())}))},f=(0,r.ref)([]);return function(t,i){var a;return(0,r.openBlock)(),(0,r.createElementBlock)(r.Fragment,null,[(0,r.createElementVNode)("div",ie,[(0,r.createElementVNode)("div",le,[(0,r.createElementVNode)("div",ae,[((0,r.openBlock)(!0),(0,r.createElementBlock)(r.Fragment,null,(0,r.renderList)(e.filtertags,(function(e){return(0,r.openBlock)(),(0,r.createElementBlock)("div",{onClick:function(t){return n=e.id,void(f.value.includes(n)?f.value.splice(f.value.indexOf(n),1):f.value.push(n));var n},class:(0,r.normalizeClass)(["rounded-md px-3 py-1 cursor-pointer mr-2 transition flex items-center text-sm",[{"bg-blue text-white":f.value.includes(e.id),"bg-gray-200 hover:bg-gray-300 text-gray-500":!f.value.includes(e.id)}]])},[(0,r.createTextVNode)((0,r.toDisplayString)(e.title)+" ",1),f.value.includes(e.id)?((0,r.openBlock)(),(0,r.createElementBlock)("span",ce,[((0,r.openBlock)(),(0,r.createElementBlock)("svg",ue,fe))])):(0,r.createCommentVNode)("",!0)],10,se)})),256))])]),(0,r.createElementVNode)("div",pe,[(0,r.withDirectives)((0,r.createElementVNode)("input",{"onUpdate:modelValue":i[0]||(i[0]=function(e){return n.value=e}),type:"text",placeholder:t.$t("app.search"),class:"w-full px-3 py-3 text-sm bg-white rounded-[10px] outline-none placeholder:text-gray-400 focus:ring focus:ring-blue focus:ring-opacity-30"},null,8,de),[[r.vModelText,n.value]]),he])]),(0,r.createElementVNode)("div",null,(0,r.toDisplayString)(null===(a=o.value)||void 0===a?void 0:a.id),1),((0,r.openBlock)(!0),(0,r.createElementBlock)(r.Fragment,null,(0,r.renderList)((0,r.unref)(l),(function(e){return(0,r.openBlock)(),(0,r.createElementBlock)("div",me,[e.image?((0,r.openBlock)(),(0,r.createElementBlock)("a",{key:0,class:"max-w-full lg:max-w-[200px] mb-auto",href:e.route_url},[(0,r.createElementVNode)("img",{src:e.image.conversion_urls.md,alt:"",class:"w-full"},null,8,ge)],8,ve)):(0,r.createCommentVNode)("",!0),(0,r.createElementVNode)("div",ye,[(0,r.createElementVNode)("div",_e,[(0,r.createElementVNode)("a",{href:e.route_url},(0,r.toDisplayString)(e.title),9,be)]),(0,r.createElementVNode)("div",null,(0,r.toDisplayString)(e.excerpt),1)]),(0,r.createElementVNode)("div",we,[(0,r.createElementVNode)("a",{class:"hmc-link_sm",href:e.route_url},(0,r.toDisplayString)(t.$t("app.detailsLinkText")),9,xe)])])})),256)),0==(0,r.unref)(l).length?((0,r.openBlock)(),(0,r.createElementBlock)("div",ke,[(0,r.createElementVNode)("p",null,(0,r.toDisplayString)(t.$t("app.no-hits")),1)])):(0,r.createCommentVNode)("",!0)],64)}}};function Ee(e,t,...n){if(e in t){let r=t[e];return"function"==typeof r?r(...n):r}let r=new Error(`Tried to handle "${e}" but there is no handler defined. Only defined handlers are: ${Object.keys(t).map((e=>`"${e}"`)).join(", ")}.`);throw Error.captureStackTrace&&Error.captureStackTrace(r,Ee),r}var Ce,Te=((Ce=Te||{})[Ce.None=0]="None",Ce[Ce.RenderStrategy=1]="RenderStrategy",Ce[Ce.Static=2]="Static",Ce),Ne=(e=>(e[e.Unmount=0]="Unmount",e[e.Hidden=1]="Hidden",e))(Ne||{});function Le({visible:e=!0,features:t=0,ourProps:n,theirProps:r,...o}){var i;let l=function(...e){if(0===e.length)return{};if(1===e.length)return e[0];let t={},n={};for(let r of e)for(let e in r)e.startsWith("on")&&"function"==typeof r[e]?(null!=n[e]||(n[e]=[]),n[e].push(r[e])):t[e]=r[e];if(t.disabled||t["aria-disabled"])return Object.assign(t,Object.fromEntries(Object.keys(n).map((e=>[e,void 0]))));for(let e in n)Object.assign(t,{[e](t,...r){let o=n[e];for(let e of o){if(t instanceof Event&&t.defaultPrevented)return;e(t,...r)}}});return t}(r,n),a=Object.assign(o,{props:l});if(e||2&t&&l.static)return Oe(a);if(1&t){return Ee(null==(i=l.unmount)||i?0:1,{0:()=>null,1:()=>Oe({...o,props:{...l,hidden:!0,style:{display:"none"}}})})}return Oe(a)}function Oe({props:e,attrs:t,slots:n,slot:o,name:i}){var l;let{as:a,...s}=Pe(e,["unmount","static"]),c=null==(l=n.default)?void 0:l.call(n,o),u={};if(o){let e=!1,t=[];for(let[n,r]of Object.entries(o))"boolean"==typeof r&&(e=!0),!0===r&&t.push(n);e&&(u["data-headlessui-state"]=t.join(" "))}if("template"===a){if(c=Ae(null!=c?c:[]),Object.keys(s).length>0||Object.keys(t).length>0){let[e,...n]=null!=c?c:[];if(!function(e){return null!=e&&("string"==typeof e.type||"object"==typeof e.type||"function"==typeof e.type)}(e)||n.length>0)throw new Error(['Passing props on "template"!',"",`The current component <${i} /> is rendering a "template".`,"However we need to passthrough the following props:",Object.keys(s).concat(Object.keys(t)).sort(((e,t)=>e.localeCompare(t))).map((e=>` - ${e}`)).join("\n"),"","You can apply a few solutions:",['Add an `as="..."` prop, to ensure that we render an actual element instead of a "template".',"Render a single element as the child so that we can forward the props onto that element."].map((e=>` - ${e}`)).join("\n")].join("\n"));return(0,r.cloneVNode)(e,Object.assign({},s,u))}return Array.isArray(c)&&1===c.length?c[0]:c}return(0,r.h)(a,Object.assign({},s,u),{default:()=>c})}function Ae(e){return e.flatMap((e=>e.type===r.Fragment?Ae(e.children):[e]))}function Pe(e,t=[]){let n=Object.assign({},e);for(let e of t)e in n&&delete n[e];return n}let Ie=0;function Re(){return++Ie}var Fe=(e=>(e.Space=" ",e.Enter="Enter",e.Escape="Escape",e.Backspace="Backspace",e.Delete="Delete",e.ArrowLeft="ArrowLeft",e.ArrowUp="ArrowUp",e.ArrowRight="ArrowRight",e.ArrowDown="ArrowDown",e.Home="Home",e.End="End",e.PageUp="PageUp",e.PageDown="PageDown",e.Tab="Tab",e))(Fe||{});function Me(e){var t;return null==e||null==e.value?null:null!=(t=e.value.$el)?t:e.value}const Be="undefined"==typeof window||"undefined"==typeof document;function je(e){if(Be)return null;if(e instanceof Node)return e.ownerDocument;if(null!=e&&e.hasOwnProperty("value")){let t=Me(e);if(t)return t.ownerDocument}return document}let Ve=["[contentEditable=true]","[tabindex]","a[href]","area[href]","button:not([disabled])","iframe","input:not([disabled])","select:not([disabled])","textarea:not([disabled])"].map((e=>`${e}:not([tabindex='-1'])`)).join(",");var De=(e=>(e[e.First=1]="First",e[e.Previous=2]="Previous",e[e.Next=4]="Next",e[e.Last=8]="Last",e[e.WrapAround=16]="WrapAround",e[e.NoScroll=32]="NoScroll",e))(De||{}),$e=(e=>(e[e.Error=0]="Error",e[e.Overflow=1]="Overflow",e[e.Success=2]="Success",e[e.Underflow=3]="Underflow",e))($e||{}),Ue=(e=>(e[e.Previous=-1]="Previous",e[e.Next=1]="Next",e))(Ue||{});function We(e=document.body){return null==e?[]:Array.from(e.querySelectorAll(Ve))}var He=(e=>(e[e.Strict=0]="Strict",e[e.Loose=1]="Loose",e))(He||{});function ze(e,t=0){var n;return e!==(null==(n=je(e))?void 0:n.body)&&Ee(t,{0:()=>e.matches(Ve),1(){let t=e;for(;null!==t;){if(t.matches(Ve))return!0;t=t.parentElement}return!1}})}let Ge=["textarea","input"].join(",");function qe(e,t,n=!0,r=null){var o;let i=null!=(o=Array.isArray(e)?e.length>0?e[0].ownerDocument:document:null==e?void 0:e.ownerDocument)?o:document,l=Array.isArray(e)?n?function(e,t=(e=>e)){return e.slice().sort(((e,n)=>{let r=t(e),o=t(n);if(null===r||null===o)return 0;let i=r.compareDocumentPosition(o);return i&Node.DOCUMENT_POSITION_FOLLOWING?-1:i&Node.DOCUMENT_POSITION_PRECEDING?1:0}))}(e):e:We(e);r=null!=r?r:i.activeElement;let a,s=(()=>{if(5&t)return 1;if(10&t)return-1;throw new Error("Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last")})(),c=(()=>{if(1&t)return 0;if(2&t)return Math.max(0,l.indexOf(r))-1;if(4&t)return Math.max(0,l.indexOf(r))+1;if(8&t)return l.length-1;throw new Error("Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last")})(),u=32&t?{preventScroll:!0}:{},f=0,p=l.length;do{if(f>=p||f+p<=0)return 0;let e=c+f;if(16&t)e=(e+p)%p;else{if(e<0)return 3;if(e>=p)return 1}a=l[e],null==a||a.focus(u),f+=s}while(a!==i.activeElement);return 6&t&&function(e){var t,n;return null!=(n=null==(t=null==e?void 0:e.matches)?void 0:t.call(e,Ge))&&n}(a)&&a.select(),a.hasAttribute("tabindex")||a.setAttribute("tabindex","0"),2}let Je=Symbol("Context");var Ke=(e=>(e[e.Open=0]="Open",e[e.Closed=1]="Closed",e))(Ke||{});function Ye(){return(0,r.inject)(Je,null)}function Ze(e,t){if(e)return e;let n=null!=t?t:"button";return"string"==typeof n&&"button"===n.toLowerCase()?"button":void 0}function Xe(e,t,n){Be||(0,r.watchEffect)((r=>{document.addEventListener(e,t,n),r((()=>document.removeEventListener(e,t,n)))}))}var Qe=(e=>(e[e.None=1]="None",e[e.Focusable=2]="Focusable",e[e.Hidden=4]="Hidden",e))(Qe||{});let et=(0,r.defineComponent)({name:"Hidden",props:{as:{type:[Object,String],default:"div"},features:{type:Number,default:1}},setup:(e,{slots:t,attrs:n})=>()=>{let{features:r,...o}=e;return Le({ourProps:{"aria-hidden":2==(2&r)||void 0,style:{position:"fixed",top:1,left:1,width:1,height:0,padding:0,margin:-1,overflow:"hidden",clip:"rect(0, 0, 0, 0)",whiteSpace:"nowrap",borderWidth:"0",...4==(4&r)&&2!=(2&r)&&{display:"none"}}},theirProps:o,slot:{},attrs:n,slots:t,name:"Hidden"})}});var tt=(e=>(e[e.Forwards=0]="Forwards",e[e.Backwards=1]="Backwards",e))(tt||{});function nt(){let e=(0,r.ref)(0);return function(e,t,n){Be||(0,r.watchEffect)((r=>{window.addEventListener(e,t,n),r((()=>window.removeEventListener(e,t,n)))}))}("keydown",(t=>{"Tab"===t.key&&(e.value=t.shiftKey?1:0)})),e}var rt=(e=>(e[e.Open=0]="Open",e[e.Closed=1]="Closed",e))(rt||{});let ot=Symbol("PopoverContext");function it(e){let t=(0,r.inject)(ot,null);if(null===t){let t=new Error(`<${e} /> is missing a parent <${ct.name} /> component.`);throw Error.captureStackTrace&&Error.captureStackTrace(t,it),t}return t}let lt=Symbol("PopoverGroupContext");function at(){return(0,r.inject)(lt,null)}let st=Symbol("PopoverPanelContext");let ct=(0,r.defineComponent)({name:"Popover",props:{as:{type:[Object,String],default:"div"}},setup(e,{slots:t,attrs:n,expose:o}){var i;let l=`headlessui-popover-button-${Re()}`,a=`headlessui-popover-panel-${Re()}`,s=(0,r.ref)(null);o({el:s,$el:s});let c=(0,r.ref)(1),u=(0,r.ref)(null),f=(0,r.ref)(null),p=(0,r.ref)(null),d=(0,r.ref)(null),h=(0,r.computed)((()=>je(s))),m=(0,r.computed)((()=>{var e,t;if(!Me(u)||!Me(d))return!1;for(let e of document.querySelectorAll("body > *"))if(Number(null==e?void 0:e.contains(Me(u)))^Number(null==e?void 0:e.contains(Me(d))))return!0;let n=We(),r=n.indexOf(Me(u)),o=(r+n.length-1)%n.length,i=(r+1)%n.length,l=n[o],a=n[i];return!(null!=(e=Me(d))&&e.contains(l)||null!=(t=Me(d))&&t.contains(a))})),v={popoverState:c,buttonId:l,panelId:a,panel:d,button:u,isPortalled:m,beforePanelSentinel:f,afterPanelSentinel:p,togglePopover(){c.value=Ee(c.value,{0:1,1:0})},closePopover(){1!==c.value&&(c.value=1)},close(e){v.closePopover();let t=e?e instanceof HTMLElement?e:e.value instanceof HTMLElement?Me(e):Me(v.button):Me(v.button);null==t||t.focus()}};(0,r.provide)(ot,v),function(e){(0,r.provide)(Je,e)}((0,r.computed)((()=>Ee(c.value,{0:Ke.Open,1:Ke.Closed}))));let g={buttonId:l,panelId:a,close(){v.closePopover()}},y=at(),_=null==y?void 0:y.registerPopover;return(0,r.watchEffect)((()=>null==_?void 0:_(g))),function(e,t,n,o){Be||(0,r.watchEffect)((r=>{(e=null!=e?e:window).addEventListener(t,n,o),r((()=>e.removeEventListener(t,n,o)))}))}(null==(i=h.value)?void 0:i.defaultView,"focus",(e=>{var t,n;0===c.value&&(function(){var e,t,n,r;return null!=(r=null==y?void 0:y.isFocusWithinPopoverGroup())?r:(null==(e=h.value)?void 0:e.activeElement)&&((null==(t=Me(u))?void 0:t.contains(h.value.activeElement))||(null==(n=Me(d))?void 0:n.contains(h.value.activeElement)))}()||!u||!d||null!=(t=Me(v.beforePanelSentinel))&&t.contains(e.target)||null!=(n=Me(v.afterPanelSentinel))&&n.contains(e.target)||v.closePopover())}),!0),function(e,t,n=(0,r.computed)((()=>!0))){function o(r,o){if(!n.value||r.defaultPrevented)return;let i=o(r);if(null===i||!i.getRootNode().contains(i))return;let l=function e(t){return"function"==typeof t?e(t()):Array.isArray(t)||t instanceof Set?t:[t]}(e);for(let e of l){if(null===e)continue;let t=e instanceof HTMLElement?e:Me(e);if(null!=t&&t.contains(i))return}return!ze(i,He.Loose)&&-1!==i.tabIndex&&r.preventDefault(),t(r,i)}let i=(0,r.ref)(null);Xe("mousedown",(e=>{var t,r;n.value&&(i.value=(null==(r=null==(t=e.composedPath)?void 0:t.call(e))?void 0:r[0])||e.target)}),!0),Xe("click",(e=>{!i.value||(o(e,(()=>i.value)),i.value=null)}),!0),Xe("blur",(e=>o(e,(()=>window.document.activeElement instanceof HTMLIFrameElement?window.document.activeElement:null))),!0)}([u,d],((e,t)=>{var n;v.closePopover(),ze(t,He.Loose)||(e.preventDefault(),null==(n=Me(u))||n.focus())}),(0,r.computed)((()=>0===c.value))),()=>{let r={open:0===c.value,close:v.close};return Le({theirProps:e,ourProps:{ref:s},slot:r,slots:t,attrs:n,name:"Popover"})}}}),ut=(0,r.defineComponent)({name:"PopoverButton",props:{as:{type:[Object,String],default:"button"},disabled:{type:[Boolean],default:!1}},inheritAttrs:!1,setup(e,{attrs:t,slots:n,expose:o}){let i=it("PopoverButton"),l=(0,r.computed)((()=>je(i.button)));o({el:i.button,$el:i.button});let a=at(),s=null==a?void 0:a.closeOthers,c=(0,r.inject)(st,null),u=null!==c&&c===i.panelId,f=(0,r.ref)(null),p=`headlessui-focus-sentinel-${Re()}`;u||(0,r.watchEffect)((()=>{i.button.value=f.value}));let d=function(e,t){let n=(0,r.ref)(Ze(e.value.type,e.value.as));return(0,r.onMounted)((()=>{n.value=Ze(e.value.type,e.value.as)})),(0,r.watchEffect)((()=>{var e;n.value||!Me(t)||Me(t)instanceof HTMLButtonElement&&(null==(e=Me(t))||!e.hasAttribute("type"))&&(n.value="button")})),n}((0,r.computed)((()=>({as:e.as,type:t.type}))),f);function h(e){var t,n,r,o,a;if(u){if(1===i.popoverState.value)return;switch(e.key){case Fe.Space:case Fe.Enter:e.preventDefault(),null==(n=(t=e.target).click)||n.call(t),i.closePopover(),null==(r=Me(i.button))||r.focus()}}else switch(e.key){case Fe.Space:case Fe.Enter:e.preventDefault(),e.stopPropagation(),1===i.popoverState.value&&(null==s||s(i.buttonId)),i.togglePopover();break;case Fe.Escape:if(0!==i.popoverState.value)return null==s?void 0:s(i.buttonId);if(!Me(i.button)||(null==(o=l.value)?void 0:o.activeElement)&&(null==(a=Me(i.button))||!a.contains(l.value.activeElement)))return;e.preventDefault(),e.stopPropagation(),i.closePopover()}}function m(e){u||e.key===Fe.Space&&e.preventDefault()}function v(t){var n,r;e.disabled||(u?(i.closePopover(),null==(n=Me(i.button))||n.focus()):(t.preventDefault(),t.stopPropagation(),1===i.popoverState.value&&(null==s||s(i.buttonId)),i.togglePopover(),null==(r=Me(i.button))||r.focus()))}function g(e){e.preventDefault(),e.stopPropagation()}return()=>{let o=0===i.popoverState.value,l={open:o},a=u?{ref:f,type:d.value,onKeydown:h,onClick:v}:{ref:f,id:i.buttonId,type:d.value,"aria-expanded":e.disabled?void 0:0===i.popoverState.value,"aria-controls":Me(i.panel)?i.panelId:void 0,disabled:!!e.disabled||void 0,onKeydown:h,onKeyup:m,onClick:v,onMousedown:g},s=nt();return(0,r.h)(r.Fragment,[Le({ourProps:a,theirProps:{...t,...e},slot:l,attrs:t,slots:n,name:"PopoverButton"}),o&&!u&&i.isPortalled.value&&(0,r.h)(et,{id:p,features:Qe.Focusable,as:"button",type:"button",onFocus:function(){let e=Me(i.panel);e&&Ee(s.value,{[tt.Forwards]:()=>qe(e,De.First),[tt.Backwards]:()=>qe(e,De.Last)})}})])}}}),ft=((0,r.defineComponent)({name:"PopoverOverlay",props:{as:{type:[Object,String],default:"div"},static:{type:Boolean,default:!1},unmount:{type:Boolean,default:!0}},setup(e,{attrs:t,slots:n}){let o=it("PopoverOverlay"),i=`headlessui-popover-overlay-${Re()}`,l=Ye(),a=(0,r.computed)((()=>null!==l?l.value===Ke.Open:0===o.popoverState.value));function s(){o.closePopover()}return()=>{let r={open:0===o.popoverState.value};return Le({ourProps:{id:i,"aria-hidden":!0,onClick:s},theirProps:e,slot:r,attrs:t,slots:n,features:Te.RenderStrategy|Te.Static,visible:a.value,name:"PopoverOverlay"})}}}),(0,r.defineComponent)({name:"PopoverPanel",props:{as:{type:[Object,String],default:"div"},static:{type:Boolean,default:!1},unmount:{type:Boolean,default:!0},focus:{type:Boolean,default:!1}},inheritAttrs:!1,setup(e,{attrs:t,slots:n,expose:o}){let{focus:i}=e,l=it("PopoverPanel"),a=(0,r.computed)((()=>je(l.panel))),s=`headlessui-focus-sentinel-before-${Re()}`,c=`headlessui-focus-sentinel-after-${Re()}`;o({el:l.panel,$el:l.panel}),(0,r.provide)(st,l.panelId),(0,r.watchEffect)((()=>{var e,t;if(!i||0!==l.popoverState.value||!l.panel)return;let n=null==(e=a.value)?void 0:e.activeElement;null!=(t=Me(l.panel))&&t.contains(n)||qe(Me(l.panel),De.First)}));let u=Ye(),f=(0,r.computed)((()=>null!==u?u.value===Ke.Open:0===l.popoverState.value));function p(e){var t,n;if(e.key===Fe.Escape){if(0!==l.popoverState.value||!Me(l.panel)||a.value&&(null==(t=Me(l.panel))||!t.contains(a.value.activeElement)))return;e.preventDefault(),e.stopPropagation(),l.closePopover(),null==(n=Me(l.button))||n.focus()}}function d(e){var t,n,r,o,i;let a=e.relatedTarget;!a||!Me(l.panel)||null!=(t=Me(l.panel))&&t.contains(a)||(l.closePopover(),((null==(r=null==(n=Me(l.beforePanelSentinel))?void 0:n.contains)?void 0:r.call(n,a))||(null==(i=null==(o=Me(l.afterPanelSentinel))?void 0:o.contains)?void 0:i.call(o,a)))&&a.focus({preventScroll:!0}))}let h=nt();function m(){let e=Me(l.panel);e&&Ee(h.value,{[tt.Forwards]:()=>{qe(e,De.Next)},[tt.Backwards]:()=>{var e;null==(e=Me(l.button))||e.focus({preventScroll:!0})}})}function v(){let e=Me(l.panel);e&&Ee(h.value,{[tt.Forwards]:()=>{var e,t;let n=Me(l.button),r=Me(l.panel);if(!n)return;let o=We(),i=o.indexOf(n),a=o.slice(0,i+1),s=[...o.slice(i+1),...a];for(let n of s.slice())if((null==(t=null==(e=null==n?void 0:n.id)?void 0:e.startsWith)?void 0:t.call(e,"headlessui-focus-sentinel-"))||(null==r?void 0:r.contains(n))){let e=s.indexOf(n);-1!==e&&s.splice(e,1)}qe(s,De.First,!1)},[tt.Backwards]:()=>qe(e,De.Previous)})}return()=>{let o={open:0===l.popoverState.value,close:l.close};return Le({ourProps:{ref:l.panel,id:l.panelId,onKeydown:p,onFocusout:i&&0===l.popoverState.value?d:void 0,tabIndex:-1},theirProps:{...t,...Pe(e,["focus"])},attrs:t,slot:o,slots:{...n,default:(...e)=>{var t;return[(0,r.h)(r.Fragment,[f.value&&l.isPortalled.value&&(0,r.h)(et,{id:s,ref:l.beforePanelSentinel,features:Qe.Focusable,as:"button",type:"button",onFocus:m}),null==(t=n.default)?void 0:t.call(n,...e),f.value&&l.isPortalled.value&&(0,r.h)(et,{id:c,ref:l.afterPanelSentinel,features:Qe.Focusable,as:"button",type:"button",onFocus:v})])]}},features:Te.RenderStrategy|Te.Static,visible:f.value,name:"PopoverPanel"})}}}));(0,r.defineComponent)({name:"PopoverGroup",props:{as:{type:[Object,String],default:"div"}},setup(e,{attrs:t,slots:n,expose:o}){let i=(0,r.ref)(null),l=(0,r.ref)([]),a=(0,r.computed)((()=>je(i)));function s(e){let t=l.value.indexOf(e);-1!==t&&l.value.splice(t,1)}return o({el:i,$el:i}),(0,r.provide)(lt,{registerPopover:function(e){return l.value.push(e),()=>{s(e)}},unregisterPopover:s,isFocusWithinPopoverGroup:function(){var e;let t=a.value;if(!t)return!1;let n=t.activeElement;return!(null==(e=Me(i))||!e.contains(n))||l.value.some((e=>{var r,o;return(null==(r=t.getElementById(e.buttonId))?void 0:r.contains(n))||(null==(o=t.getElementById(e.panelId))?void 0:o.contains(n))}))},closeOthers:function(e){for(let t of l.value)t.buttonId!==e&&t.close()}}),()=>Le({ourProps:{ref:i},theirProps:e,slot:{},attrs:t,slots:n,name:"PopoverGroup"})}});var pt={class:"items-center hidden h-full xl:flex"},dt={key:0,class:"relative"},ht=["id"],mt=[(0,r.createElementVNode)("g",{stroke:"none","stroke-width":"1",fill:"none","fill-rule":"evenodd"},[(0,r.createElementVNode)("g",{transform:"translate(-766.000000, -50.000000)",fill:"#005799","fill-rule":"nonzero"},[(0,r.createElementVNode)("polygon",{points:"772 50 772.707107 50.7071068 769.353553 54.0606602 766 50.7071068 766.707107 50 767.544606 50.8375328 769.353553 52.6465534"})])],-1)],vt={key:0,class:"flex flex-col px-5 pb-2 shadow-md"},gt=["href"],yt=["onClick"],_t={class:"!text-blue"},bt=["id"],wt=[(0,r.createElementVNode)("path",{d:"m9 6 6 6-6 6",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round"},null,-1)],xt=["id"],kt=["href"],St=["href"],Et={class:"flex items-center"},Ct={class:"overflow-y-auto h-full"},Tt={class:"p-[50px] grid grid-cols-3 gap-x-[60px] gap-y-[70px]"},Nt={class:""},Lt={class:"flex flex-col w-full"},Ot=["href"],At=["onClick"],Pt={class:"!text-blue"},It=["id"],Rt=[(0,r.createElementVNode)("path",{d:"m9 6 6 6-6 6",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round"},null,-1)],Ft=["id"],Mt=["href"],Bt=(0,r.createElementVNode)("div",{class:"sticky bg-gradient-to-t from-white bottom-0 left-0 w-fill h-32 pointer-events-none mr-12"},null,-1);const jt={__name:"MainNavigation",props:{menu:{type:Array,required:!0}},setup:function(e){var t,n=function(e){clearTimeout(t)},o=function(e){t=setTimeout((function(){i()}),500)},i=function(){document.querySelectorAll(".popover-button-level-1").forEach((function(e){"open"==e.getAttribute("data-headlessui-state")&&e.click()}))};return function(l,a){return(0,r.openBlock)(),(0,r.createElementBlock)("div",pt,[((0,r.openBlock)(!0),(0,r.createElementBlock)(r.Fragment,null,(0,r.renderList)(e.menu,(function(e,l){return(0,r.openBlock)(),(0,r.createBlock)((0,r.unref)(ct),{key:l},{default:(0,r.withCtx)((function(s){var c=s.open;return[JSON.parse(e.children).length>0?((0,r.openBlock)(),(0,r.createElementBlock)("div",dt,[(0,r.createVNode)((0,r.unref)(ut),{as:"div",class:(0,r.normalizeClass)(["popover-button-level-1 px-2 mx-0.5 text-blue hover:text-blue-light min-h-[60px] inline-flex items-center focus:outline-none transition cursor-pointer",{"!text-blue-light":e.is_active}]),onMouseover:a[0]||(a[0]=function(e){return n=e,i(),clearTimeout(t),void("open"!=n.target.getAttribute("data-headlessui-state")&&n.target.click());var n}),onMouseout:a[1]||(a[1]=function(e){t=setTimeout((function(){i()}),500)})},{default:(0,r.withCtx)((function(){return[(0,r.createElementVNode)("div",{id:"main-nav-btn-".concat(l),class:"flex items-center gap-2 uppercase rounded group focus:outline-none pointer-events-none"},[(0,r.createElementVNode)("span",null,(0,r.toDisplayString)(e.title),1),((0,r.openBlock)(),(0,r.createElementBlock)("svg",{width:"7px",height:"4px",viewBox:"0 0 7 4",version:"1.1",xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",class:(0,r.normalizeClass)(["transition duration-200",{"rotate-180":c}])},mt,2))],8,ht)]})),_:2},1032,["class"]),(0,r.createVNode)(r.TransitionGroup,{name:"panels","enter-active-class":"transition duration-300 ease-out","enter-from-class":"opacity-0","enter-to-class":"opacity-100","leave-active-class":"transition duration-150 ease-in","leave-from-class":"opacity-100","leave-to-class":"opacity-0"},{default:(0,r.withCtx)((function(){return[e.mega_menu?(0,r.createCommentVNode)("",!0):(0,r.withDirectives)(((0,r.openBlock)(),(0,r.createBlock)((0,r.unref)(ft),{key:0,static:"",class:"absolute left-1/2 -translate-x-1/2 top-full z-40 w-[258px] hidden overflow-y-auto shadow-xl transform bg-white border-t-4 xl:block border-blue-light pt-2",onMouseover:a[2]||(a[2]=function(e){return n()}),onMouseout:a[3]||(a[3]=function(e){return o()})},{default:(0,r.withCtx)((function(){return[e.mega_menu?(0,r.createCommentVNode)("",!0):((0,r.openBlock)(),(0,r.createElementBlock)("div",vt,[((0,r.openBlock)(!0),(0,r.createElementBlock)(r.Fragment,null,(0,r.renderList)(JSON.parse(e.children),(function(e,t){return(0,r.openBlock)(),(0,r.createElementBlock)("div",{key:t,class:"flex flex-col w-full pb-2 border-b border-gray-200 last:border-white"},[0==JSON.parse(e.children).length?((0,r.openBlock)(),(0,r.createElementBlock)("a",{key:0,class:(0,r.normalizeClass)(["flex w-full pt-3 text-sm text-left text-blue hover:text-blue-light transition",{"!text-blue-light":e.is_active}]),href:e.route},(0,r.toDisplayString)(e.title),11,gt)):(0,r.createCommentVNode)("",!0),JSON.parse(e.children).length>0?((0,r.openBlock)(),(0,r.createElementBlock)("button",{key:1,onClick:function(e){return function(e,t){var n=document.getElementById("sub-level-two-".concat(e,"-").concat(t)),r=document.getElementById("sub-level-two-indicator-".concat(e,"-").concat(t));if(n.classList.contains("hidden"))return n.classList.replace("hidden","flex"),void r.classList.replace("rotate-90","-rotate-90");n.classList.replace("flex","hidden"),r.classList.replace("-rotate-90","rotate-90")}(l,t)},class:(0,r.normalizeClass)(["flex justify-between w-full pt-2 text-sm text-left text-blue hover:text-blue-light transition",{"!text-blue-light":e.is_active}])},[(0,r.createElementVNode)("div",null,(0,r.toDisplayString)(e.title),1),(0,r.createElementVNode)("div",_t,[((0,r.openBlock)(),(0,r.createElementBlock)("svg",{id:"sub-level-two-indicator-".concat(l,"-").concat(t),width:"24",height:"24","stroke-width":"1.5",class:"transition-transform duration-300 origin-center scale-50 rotate-90",fill:"none",xmlns:"http://www.w3.org/2000/svg"},wt,8,bt))])],10,yt)):(0,r.createCommentVNode)("",!0),JSON.parse(e.children).length>0?((0,r.openBlock)(),(0,r.createElementBlock)("div",{key:2,id:"sub-level-two-".concat(l,"-").concat(t),class:"flex-col hidden w-full gap-3 pt-2"},[((0,r.openBlock)(!0),(0,r.createElementBlock)(r.Fragment,null,(0,r.renderList)(JSON.parse(e.children),(function(e,t){return(0,r.openBlock)(),(0,r.createElementBlock)("div",{key:t,class:"flex"},[(0,r.createElementVNode)("a",{class:(0,r.normalizeClass)(["flex pl-3 text-sm text-blue hover:text-blue-light transition",{"!text-blue-light":e.is_active}]),href:e.route},(0,r.toDisplayString)(e.title),11,kt)])})),128))],8,xt)):(0,r.createCommentVNode)("",!0)])})),128))]))]})),_:2},1536)),[[r.vShow,c]])]})),_:2},1024)])):((0,r.openBlock)(),(0,r.createElementBlock)("a",{key:1,href:e.route,class:(0,r.normalizeClass)(["relative min-h-[60px] uppercase px-2 mx-2 text-blue hover:text-blue-light inline-flex items-center font-medium rounded focus:outline-none",{"!text-blue-light":e.is_active}])},[(0,r.createElementVNode)("div",Et,(0,r.toDisplayString)(e.title),1)],10,St)),e.mega_menu?((0,r.openBlock)(),(0,r.createBlock)(r.Teleport,{key:2,to:"#app-header"},[(0,r.createVNode)(r.TransitionGroup,{name:"megapanels","enter-active-class":"transition duration-300 ease-out","enter-from-class":"opacity-0","enter-to-class":"opacity-100","leave-active-class":"transition duration-150 ease-in","leave-from-class":"opacity-100","leave-to-class":"opacity-0"},{default:(0,r.withCtx)((function(){return[(0,r.withDirectives)((0,r.createVNode)((0,r.unref)(ft),{static:"",class:(0,r.normalizeClass)(["absolute right-0 pr-6 pt-6 pb-6 z-40 hidden overflow-x-visible transform bg-white border-t-4 shadow-xl xl:block border-blue-light",{"w-[1000px] mega-height":e.mega_menu,"w-[258px] h-fit":!e.mega_menu}]),onMouseover:a[4]||(a[4]=function(e){return n()}),onMouseout:a[5]||(a[5]=function(e){return o()})},{default:(0,r.withCtx)((function(){return[(0,r.createElementVNode)("div",Ct,[(0,r.createElementVNode)("div",Tt,[((0,r.openBlock)(!0),(0,r.createElementBlock)(r.Fragment,null,(0,r.renderList)(JSON.parse(e.children),(function(e,t){return(0,r.openBlock)(),(0,r.createElementBlock)("div",{key:t},[(0,r.createElementVNode)("div",Nt,[(0,r.createElementVNode)("div",{class:(0,r.normalizeClass)(["text-base flex border-b-4 pb-3.5 text-blue mb-3",{"border-blue":!e.item_color||"blue"==e.item_color,"border-green":"green"==e.item_color,"border-purple":"purple"==e.item_color,"border-red":"red"==e.item_color,"border-orange":"orange"==e.item_color,"border-yellow":"yellow"==e.item_color,"border-turquoise":"turquoise"==e.item_color,"border-darkgreen":"darkgreen"==e.item_color,"border-monochrome":"monochrome"==e.item_color,"border-blueviolet":"blueviolet"==e.item_color,"border-lightblue":"lightblue"==e.item_color,"border-violet":"violet"==e.item_color,"border-gray-400":"gray-400"==e.item_color}])},(0,r.toDisplayString)(e.title),3),(0,r.createElementVNode)("div",Lt,[((0,r.openBlock)(!0),(0,r.createElementBlock)(r.Fragment,null,(0,r.renderList)(JSON.parse(e.children),(function(e,n){return(0,r.openBlock)(),(0,r.createElementBlock)("div",{key:n,class:"pb-2 border-b border-gray-200"},[0==JSON.parse(e.children).length?((0,r.openBlock)(),(0,r.createElementBlock)("a",{key:0,class:(0,r.normalizeClass)(["flex w-full pt-2 text-sm text-left text-blue hover:text-blue-light transition",{"!text-blue-light":e.is_active}]),href:e.route},(0,r.toDisplayString)(e.title),11,Ot)):(0,r.createCommentVNode)("",!0),JSON.parse(e.children).length>0?((0,r.openBlock)(),(0,r.createElementBlock)("button",{key:1,onClick:function(e){return function(e,t){var n=document.getElementById("sub-level-three-".concat(e,"-").concat(t)),r=document.getElementById("sub-level-three-indicator-".concat(e,"-").concat(t));if(n.classList.contains("hidden"))return n.classList.replace("hidden","flex"),void r.classList.replace("rotate-90","-rotate-90");n.classList.replace("flex","hidden"),r.classList.replace("-rotate-90","rotate-90")}(t,n)},class:(0,r.normalizeClass)(["flex justify-between w-full pt-2 text-sm text-left text-blue hover:text-blue-light transition",{"!text-blue-light":e.is_active}])},[(0,r.createElementVNode)("div",null,(0,r.toDisplayString)(e.title),1),(0,r.createElementVNode)("div",Pt,[((0,r.openBlock)(),(0,r.createElementBlock)("svg",{id:"sub-level-three-indicator-".concat(t,"-").concat(n),width:"24",height:"24","stroke-width":"1.5",class:"transition-transform duration-300 origin-center scale-50 rotate-90",fill:"none",xmlns:"http://www.w3.org/2000/svg"},Rt,8,It))])],10,At)):(0,r.createCommentVNode)("",!0),JSON.parse(e.children).length>0?((0,r.openBlock)(),(0,r.createElementBlock)("div",{key:2,id:"sub-level-three-".concat(t,"-").concat(n),class:"flex-col hidden w-full gap-3 pt-2"},[((0,r.openBlock)(!0),(0,r.createElementBlock)(r.Fragment,null,(0,r.renderList)(JSON.parse(e.children),(function(e,t){return(0,r.openBlock)(),(0,r.createElementBlock)("div",{key:t},[(0,r.createElementVNode)("a",{class:(0,r.normalizeClass)(["flex pl-3 text-sm text-blue hover:text-blue-light transition",{"!text-blue-light":e.is_active}]),href:e.route},(0,r.toDisplayString)(e.title),11,Mt)])})),128))],8,Ft)):(0,r.createCommentVNode)("",!0)])})),128))])])])})),128))])]),Bt]})),_:2},1032,["class"]),[[r.vShow,c]])]})),_:2},1024)])):(0,r.createCommentVNode)("",!0)]})),_:2},1024)})),128))])}}};var Vt=n(284),Dt={insert:"head",singleton:!1};O()(Vt.Z,Dt);Vt.Z.locals;const $t=jt,Ut="undefined"!=typeof window;const Wt="function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag,Ht=e=>Wt?Symbol(e):e,zt=e=>JSON.stringify(e).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029").replace(/\u0027/g,"\\u0027"),Gt=e=>"number"==typeof e&&isFinite(e),qt=e=>"[object RegExp]"===cn(e),Jt=e=>un(e)&&0===Object.keys(e).length;function Kt(e,t){"undefined"!=typeof console&&(console.warn("[intlify] "+e),t&&console.warn(t.stack))}const Yt=Object.assign;let Zt;const Xt=()=>Zt||(Zt="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==n.g?n.g:{});function Qt(e){return e.replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}const en=Object.prototype.hasOwnProperty;function tn(e,t){return en.call(e,t)}const nn=Array.isArray,rn=e=>"function"==typeof e,on=e=>"string"==typeof e,ln=e=>"boolean"==typeof e,an=e=>null!==e&&"object"==typeof e,sn=Object.prototype.toString,cn=e=>sn.call(e),un=e=>"[object Object]"===cn(e);const fn=1,pn=2,dn=3,hn=4,mn=5,vn=6,gn=7,yn=8,_n=9,bn=10,wn=11,xn=12,kn=13,Sn=14,En=15;function Cn(e,t,n={}){const{domain:r,messages:o,args:i}=n,l=new SyntaxError(String(e));return l.code=e,t&&(l.location=t),l.domain=r,l}function Tn(e){throw e}function Nn(e,t,n){const r={start:e,end:t};return null!=n&&(r.source=n),r}const Ln=" ",On="\n",An=String.fromCharCode(8232),Pn=String.fromCharCode(8233);function In(e){const t=e;let n=0,r=1,o=1,i=0;const l=e=>"\r"===t[e]&&t[e+1]===On,a=e=>t[e]===Pn,s=e=>t[e]===An,c=e=>l(e)||(e=>t[e]===On)(e)||a(e)||s(e),u=e=>l(e)||a(e)||s(e)?On:t[e];function f(){return i=0,c(n)&&(r++,o=0),l(n)&&n++,n++,o++,t[n]}return{index:()=>n,line:()=>r,column:()=>o,peekOffset:()=>i,charAt:u,currentChar:()=>u(n),currentPeek:()=>u(n+i),next:f,peek:function(){return l(n+i)&&i++,i++,t[n+i]},reset:function(){n=0,r=1,o=1,i=0},resetPeek:function(e=0){i=e},skipToPeek:function(){const e=n+i;for(;e!==n;)f();i=0}}}const Rn=void 0;function Fn(e,t={}){const n=!1!==t.location,r=In(e),o=()=>r.index(),i=()=>{return e=r.line(),t=r.column(),n=r.index(),{line:e,column:t,offset:n};var e,t,n},l=i(),a=o(),s={currentType:14,offset:a,startLoc:l,endLoc:l,lastType:14,lastOffset:a,lastStartLoc:l,lastEndLoc:l,braceNest:0,inLinked:!1,text:""},c=()=>s,{onError:u}=t;function f(e,t,n,...r){const o=c();if(t.column+=n,t.offset+=n,u){const n=Cn(e,Nn(o.startLoc,t),{domain:"tokenizer",args:r});u(n)}}function p(e,t,r){e.endLoc=i(),e.currentType=t;const o={type:t};return n&&(o.loc=Nn(e.startLoc,e.endLoc)),null!=r&&(o.value=r),o}const d=e=>p(e,14);function h(e,t){return e.currentChar()===t?(e.next(),t):(f(fn,i(),0,t),"")}function m(e){let t="";for(;e.currentPeek()===Ln||e.currentPeek()===On;)t+=e.currentPeek(),e.peek();return t}function v(e){const t=m(e);return e.skipToPeek(),t}function g(e){if(e===Rn)return!1;const t=e.charCodeAt(0);return t>=97&&t<=122||t>=65&&t<=90||95===t}function y(e,t){const{currentType:n}=t;if(2!==n)return!1;m(e);const r=function(e){if(e===Rn)return!1;const t=e.charCodeAt(0);return t>=48&&t<=57}("-"===e.currentPeek()?e.peek():e.currentPeek());return e.resetPeek(),r}function _(e){m(e);const t="|"===e.currentPeek();return e.resetPeek(),t}function b(e,t=!0){const n=(t=!1,r="",o=!1)=>{const i=e.currentPeek();return"{"===i?"%"!==r&&t:"@"!==i&&i?"%"===i?(e.peek(),n(t,"%",!0)):"|"===i?!("%"!==r&&!o)||!(r===Ln||r===On):i===Ln?(e.peek(),n(!0,Ln,o)):i!==On||(e.peek(),n(!0,On,o)):"%"===r||t},r=n();return t&&e.resetPeek(),r}function w(e,t){const n=e.currentChar();return n===Rn?Rn:t(n)?(e.next(),n):null}function x(e){return w(e,(e=>{const t=e.charCodeAt(0);return t>=97&&t<=122||t>=65&&t<=90||t>=48&&t<=57||95===t||36===t}))}function k(e){return w(e,(e=>{const t=e.charCodeAt(0);return t>=48&&t<=57}))}function S(e){return w(e,(e=>{const t=e.charCodeAt(0);return t>=48&&t<=57||t>=65&&t<=70||t>=97&&t<=102}))}function E(e){let t="",n="";for(;t=k(e);)n+=t;return n}function C(e){let t="";for(;;){const n=e.currentChar();if("{"===n||"}"===n||"@"===n||"|"===n||!n)break;if("%"===n){if(!b(e))break;t+=n,e.next()}else if(n===Ln||n===On)if(b(e))t+=n,e.next();else{if(_(e))break;t+=n,e.next()}else t+=n,e.next()}return t}function T(e){const t=e.currentChar();switch(t){case"\\":case"'":return e.next(),`\\${t}`;case"u":return N(e,t,4);case"U":return N(e,t,6);default:return f(hn,i(),0,t),""}}function N(e,t,n){h(e,t);let r="";for(let o=0;o=1&&f(_n,i(),0),e.next(),n=p(t,2,"{"),v(e),t.braceNest++,n;case"}":return t.braceNest>0&&2===t.currentType&&f(yn,i(),0),e.next(),n=p(t,3,"}"),t.braceNest--,t.braceNest>0&&v(e),t.inLinked&&0===t.braceNest&&(t.inLinked=!1),n;case"@":return t.braceNest>0&&f(gn,i(),0),n=A(e,t)||d(t),t.braceNest=0,n;default:let r=!0,o=!0,l=!0;if(_(e))return t.braceNest>0&&f(gn,i(),0),n=p(t,1,L(e)),t.braceNest=0,t.inLinked=!1,n;if(t.braceNest>0&&(5===t.currentType||6===t.currentType||7===t.currentType))return f(gn,i(),0),t.braceNest=0,P(e,t);if(r=function(e,t){const{currentType:n}=t;if(2!==n)return!1;m(e);const r=g(e.currentPeek());return e.resetPeek(),r}(e,t))return n=p(t,5,function(e){v(e);let t="",n="";for(;t=x(e);)n+=t;return e.currentChar()===Rn&&f(gn,i(),0),n}(e)),v(e),n;if(o=y(e,t))return n=p(t,6,function(e){v(e);let t="";return"-"===e.currentChar()?(e.next(),t+=`-${E(e)}`):t+=E(e),e.currentChar()===Rn&&f(gn,i(),0),t}(e)),v(e),n;if(l=function(e,t){const{currentType:n}=t;if(2!==n)return!1;m(e);const r="'"===e.currentPeek();return e.resetPeek(),r}(e,t))return n=p(t,7,function(e){v(e),h(e,"'");let t="",n="";const r=e=>"'"!==e&&e!==On;for(;t=w(e,r);)n+="\\"===t?T(e):t;const o=e.currentChar();return o===On||o===Rn?(f(dn,i(),0),o===On&&(e.next(),h(e,"'")),n):(h(e,"'"),n)}(e)),v(e),n;if(!r&&!o&&!l)return n=p(t,13,function(e){v(e);let t="",n="";const r=e=>"{"!==e&&"}"!==e&&e!==Ln&&e!==On;for(;t=w(e,r);)n+=t;return n}(e)),f(pn,i(),0,n.value),v(e),n}return n}function A(e,t){const{currentType:n}=t;let r=null;const o=e.currentChar();switch(8!==n&&9!==n&&12!==n&&10!==n||o!==On&&o!==Ln||f(bn,i(),0),o){case"@":return e.next(),r=p(t,8,"@"),t.inLinked=!0,r;case".":return v(e),e.next(),p(t,9,".");case":":return v(e),e.next(),p(t,10,":");default:return _(e)?(r=p(t,1,L(e)),t.braceNest=0,t.inLinked=!1,r):function(e,t){const{currentType:n}=t;if(8!==n)return!1;m(e);const r="."===e.currentPeek();return e.resetPeek(),r}(e,t)||function(e,t){const{currentType:n}=t;if(8!==n&&12!==n)return!1;m(e);const r=":"===e.currentPeek();return e.resetPeek(),r}(e,t)?(v(e),A(e,t)):function(e,t){const{currentType:n}=t;if(9!==n)return!1;m(e);const r=g(e.currentPeek());return e.resetPeek(),r}(e,t)?(v(e),p(t,12,function(e){let t="",n="";for(;t=x(e);)n+=t;return n}(e))):function(e,t){const{currentType:n}=t;if(10!==n)return!1;const r=()=>{const t=e.currentPeek();return"{"===t?g(e.peek()):!("@"===t||"%"===t||"|"===t||":"===t||"."===t||t===Ln||!t)&&(t===On?(e.peek(),r()):g(t))},o=r();return e.resetPeek(),o}(e,t)?(v(e),"{"===o?O(e,t)||r:p(t,11,function(e){const t=(n=!1,r)=>{const o=e.currentChar();return"{"!==o&&"%"!==o&&"@"!==o&&"|"!==o&&o?o===Ln?r:o===On?(r+=o,e.next(),t(n,r)):(r+=o,e.next(),t(!0,r)):r};return t(!1,"")}(e))):(8===n&&f(bn,i(),0),t.braceNest=0,t.inLinked=!1,P(e,t))}}function P(e,t){let n={type:14};if(t.braceNest>0)return O(e,t)||d(t);if(t.inLinked)return A(e,t)||d(t);switch(e.currentChar()){case"{":return O(e,t)||d(t);case"}":return f(vn,i(),0),e.next(),p(t,3,"}");case"@":return A(e,t)||d(t);default:if(_(e))return n=p(t,1,L(e)),t.braceNest=0,t.inLinked=!1,n;const{isModulo:r,hasSpace:o}=function(e){const t=m(e),n="%"===e.currentPeek()&&"{"===e.peek();return e.resetPeek(),{isModulo:n,hasSpace:t.length>0}}(e);if(r)return o?p(t,0,C(e)):p(t,4,function(e){v(e);const t=e.currentChar();return"%"!==t&&f(fn,i(),0,t),e.next(),"%"}(e));if(b(e))return p(t,0,C(e))}return n}return{nextToken:function(){const{currentType:e,offset:t,startLoc:n,endLoc:l}=s;return s.lastType=e,s.lastOffset=t,s.lastStartLoc=n,s.lastEndLoc=l,s.offset=o(),s.startLoc=i(),r.currentChar()===Rn?p(s,14):P(r,s)},currentOffset:o,currentPosition:i,context:c}}const Mn=/(?:\\\\|\\'|\\u([0-9a-fA-F]{4})|\\U([0-9a-fA-F]{6}))/g;function Bn(e,t,n){switch(e){case"\\\\":return"\\";case"\\'":return"'";default:{const e=parseInt(t||n,16);return e<=55295||e>=57344?String.fromCodePoint(e):"�"}}}function jn(e={}){const t=!1!==e.location,{onError:n}=e;function r(e,t,r,o,...i){const l=e.currentPosition();if(l.offset+=o,l.column+=o,n){const e=Cn(t,Nn(r,l),{domain:"parser",args:i});n(e)}}function o(e,n,r){const o={type:e,start:n,end:n};return t&&(o.loc={start:r,end:r}),o}function i(e,n,r,o){e.end=n,o&&(e.type=o),t&&e.loc&&(e.loc.end=r)}function l(e,t){const n=e.context(),r=o(3,n.offset,n.startLoc);return r.value=t,i(r,e.currentOffset(),e.currentPosition()),r}function a(e,t){const n=e.context(),{lastOffset:r,lastStartLoc:l}=n,a=o(5,r,l);return a.index=parseInt(t,10),e.nextToken(),i(a,e.currentOffset(),e.currentPosition()),a}function s(e,t){const n=e.context(),{lastOffset:r,lastStartLoc:l}=n,a=o(4,r,l);return a.key=t,e.nextToken(),i(a,e.currentOffset(),e.currentPosition()),a}function c(e,t){const n=e.context(),{lastOffset:r,lastStartLoc:l}=n,a=o(9,r,l);return a.value=t.replace(Mn,Bn),e.nextToken(),i(a,e.currentOffset(),e.currentPosition()),a}function u(e){const t=e.context(),n=o(6,t.offset,t.startLoc);let l=e.nextToken();if(9===l.type){const t=function(e){const t=e.nextToken(),n=e.context(),{lastOffset:l,lastStartLoc:a}=n,s=o(8,l,a);return 12!==t.type?(r(e,xn,n.lastStartLoc,0),s.value="",i(s,l,a),{nextConsumeToken:t,node:s}):(null==t.value&&r(e,Sn,n.lastStartLoc,0,Vn(t)),s.value=t.value||"",i(s,e.currentOffset(),e.currentPosition()),{node:s})}(e);n.modifier=t.node,l=t.nextConsumeToken||e.nextToken()}switch(10!==l.type&&r(e,Sn,t.lastStartLoc,0,Vn(l)),l=e.nextToken(),2===l.type&&(l=e.nextToken()),l.type){case 11:null==l.value&&r(e,Sn,t.lastStartLoc,0,Vn(l)),n.key=function(e,t){const n=e.context(),r=o(7,n.offset,n.startLoc);return r.value=t,i(r,e.currentOffset(),e.currentPosition()),r}(e,l.value||"");break;case 5:null==l.value&&r(e,Sn,t.lastStartLoc,0,Vn(l)),n.key=s(e,l.value||"");break;case 6:null==l.value&&r(e,Sn,t.lastStartLoc,0,Vn(l)),n.key=a(e,l.value||"");break;case 7:null==l.value&&r(e,Sn,t.lastStartLoc,0,Vn(l)),n.key=c(e,l.value||"");break;default:r(e,kn,t.lastStartLoc,0);const u=e.context(),f=o(7,u.offset,u.startLoc);return f.value="",i(f,u.offset,u.startLoc),n.key=f,i(n,u.offset,u.startLoc),{nextConsumeToken:l,node:n}}return i(n,e.currentOffset(),e.currentPosition()),{node:n}}function f(e){const t=e.context(),n=o(2,1===t.currentType?e.currentOffset():t.offset,1===t.currentType?t.endLoc:t.startLoc);n.items=[];let f=null;do{const o=f||e.nextToken();switch(f=null,o.type){case 0:null==o.value&&r(e,Sn,t.lastStartLoc,0,Vn(o)),n.items.push(l(e,o.value||""));break;case 6:null==o.value&&r(e,Sn,t.lastStartLoc,0,Vn(o)),n.items.push(a(e,o.value||""));break;case 5:null==o.value&&r(e,Sn,t.lastStartLoc,0,Vn(o)),n.items.push(s(e,o.value||""));break;case 7:null==o.value&&r(e,Sn,t.lastStartLoc,0,Vn(o)),n.items.push(c(e,o.value||""));break;case 8:const i=u(e);n.items.push(i.node),f=i.nextConsumeToken||null}}while(14!==t.currentType&&1!==t.currentType);return i(n,1===t.currentType?t.lastOffset:e.currentOffset(),1===t.currentType?t.lastEndLoc:e.currentPosition()),n}function p(e){const t=e.context(),{offset:n,startLoc:l}=t,a=f(e);return 14===t.currentType?a:function(e,t,n,l){const a=e.context();let s=0===l.items.length;const c=o(1,t,n);c.cases=[],c.cases.push(l);do{const t=f(e);s||(s=0===t.items.length),c.cases.push(t)}while(14!==a.currentType);return s&&r(e,wn,n,0),i(c,e.currentOffset(),e.currentPosition()),c}(e,n,l,a)}return{parse:function(n){const l=Fn(n,Yt({},e)),a=l.context(),s=o(0,a.offset,a.startLoc);return t&&s.loc&&(s.loc.source=n),s.body=p(l),14!==a.currentType&&r(l,Sn,a.lastStartLoc,0,n[a.offset]||""),i(s,l.currentOffset(),l.currentPosition()),s}}}function Vn(e){if(14===e.type)return"EOF";const t=(e.value||"").replace(/\r?\n/gu,"\\n");return t.length>10?t.slice(0,9)+"…":t}function Dn(e,t){for(let n=0;nn,helper:e=>(n.helpers.add(e),e)}}(e);n.helper("normalize"),e.body&&$n(e.body,n);const r=n.context();e.helpers=Array.from(r.helpers)}function Wn(e,t){const{helper:n}=e;switch(t.type){case 0:!function(e,t){t.body?Wn(e,t.body):e.push("null")}(e,t);break;case 1:!function(e,t){const{helper:n,needIndent:r}=e;if(t.cases.length>1){e.push(`${n("plural")}([`),e.indent(r());const o=t.cases.length;for(let n=0;n{const n=on(t.mode)?t.mode:"normal",r=on(t.filename)?t.filename:"message.intl",o=!!t.sourceMap,i=null!=t.breakLineCode?t.breakLineCode:"arrow"===n?";":"\n",l=t.needIndent?t.needIndent:"arrow"!==n,a=e.helpers||[],s=function(e,t){const{sourceMap:n,filename:r,breakLineCode:o,needIndent:i}=t,l={source:e.loc.source,filename:r,code:"",column:1,line:1,offset:0,map:void 0,breakLineCode:o,needIndent:i,indentLevel:0};function a(e,t){l.code+=e}function s(e,t=!0){const n=t?o:"";a(i?n+" ".repeat(e):n)}return{context:()=>l,push:a,indent:function(e=!0){const t=++l.indentLevel;e&&s(t)},deindent:function(e=!0){const t=--l.indentLevel;e&&s(t)},newline:function(){s(l.indentLevel)},helper:e=>`_${e}`,needIndent:()=>l.needIndent}}(e,{mode:n,filename:r,sourceMap:o,breakLineCode:i,needIndent:l});s.push("normal"===n?"function __msg__ (ctx) {":"(ctx) => {"),s.indent(l),a.length>0&&(s.push(`const { ${a.map((e=>`${e}: _${e}`)).join(", ")} } = ctx`),s.newline()),s.push("return "),Wn(s,e),s.deindent(l),s.push("}");const{code:c,map:u}=s.context();return{ast:e,code:c,map:u?u.toJSON():void 0}})(r,n)}const zn="i18n:init",Gn="function:translate",qn=[];qn[0]={w:[0],i:[3,0],"[":[4],o:[7]},qn[1]={w:[1],".":[2],"[":[4],o:[7]},qn[2]={w:[2],i:[3,0],0:[3,0]},qn[3]={i:[3,0],0:[3,0],w:[1,1],".":[2,1],"[":[4,1],o:[7,1]},qn[4]={"'":[5,0],'"':[6,0],"[":[4,2],"]":[1,3],o:8,l:[4,0]},qn[5]={"'":[4,0],o:8,l:[5,0]},qn[6]={'"':[4,0],o:8,l:[6,0]};const Jn=/^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;function Kn(e){if(null==e)return"o";switch(e.charCodeAt(0)){case 91:case 93:case 46:case 34:case 39:return e;case 95:case 36:case 45:return"i";case 9:case 10:case 13:case 160:case 65279:case 8232:case 8233:return"w"}return"i"}function Yn(e){const t=e.trim();return("0"!==e.charAt(0)||!isNaN(parseInt(e)))&&(n=t,Jn.test(n)?function(e){const t=e.charCodeAt(0);return t!==e.charCodeAt(e.length-1)||34!==t&&39!==t?e:e.slice(1,-1)}(t):"*"+t);var n}const Zn=new Map;function Xn(e,t){return an(e)?e[t]:null}const Qn=e=>e,er=e=>"",tr=e=>0===e.length?"":e.join(""),nr=e=>null==e?"":nn(e)||un(e)&&e.toString===sn?JSON.stringify(e,null,2):String(e);function rr(e,t){return e=Math.abs(e),2===t?e?e>1?1:0:1:e?Math.min(e,2):0}function or(e={}){const t=e.locale,n=function(e){const t=Gt(e.pluralIndex)?e.pluralIndex:-1;return e.named&&(Gt(e.named.count)||Gt(e.named.n))?Gt(e.named.count)?e.named.count:Gt(e.named.n)?e.named.n:t:t}(e),r=an(e.pluralRules)&&on(t)&&rn(e.pluralRules[t])?e.pluralRules[t]:rr,o=an(e.pluralRules)&&on(t)&&rn(e.pluralRules[t])?rr:void 0,i=e.list||[],l=e.named||{};Gt(e.pluralIndex)&&function(e,t){t.count||(t.count=e),t.n||(t.n=e)}(n,l);function a(t){const n=rn(e.messages)?e.messages(t):!!an(e.messages)&&e.messages[t];return n||(e.parent?e.parent.message(t):er)}const s=un(e.processor)&&rn(e.processor.normalize)?e.processor.normalize:tr,c=un(e.processor)&&rn(e.processor.interpolate)?e.processor.interpolate:nr,u={list:e=>i[e],named:e=>l[e],plural:e=>e[r(n,e.length,o)],linked:(t,...n)=>{const[r,o]=n;let i="text",l="";1===n.length?an(r)?(l=r.modifier||l,i=r.type||i):on(r)&&(l=r||l):2===n.length&&(on(r)&&(l=r||l),on(o)&&(i=o||i));let s=a(t)(u);return"vnode"===i&&nn(s)&&l&&(s=s[0]),l?(c=l,e.modifiers?e.modifiers[c]:Qn)(s,i):s;var c},message:a,type:un(e.processor)&&on(e.processor.type)?e.processor.type:"text",interpolate:c,normalize:s};return u}let ir=null;const lr=ar(Gn);function ar(e){return t=>ir&&ir.emit(e,t)}const sr=7;function cr(e,t,n){return[...new Set([n,...nn(t)?t:an(t)?Object.keys(t):on(t)?[t]:[n]])]}function ur(e,t,n){const r=on(n)?n:hr,o=e;o.__localeChainCache||(o.__localeChainCache=new Map);let i=o.__localeChainCache.get(r);if(!i){i=[];let e=[n];for(;nn(e);)e=fr(i,e,t);const l=nn(t)||!un(t)?t:t.default?t.default:null;e=on(l)?[l]:l,nn(e)&&fr(i,e,!1),o.__localeChainCache.set(r,i)}return i}function fr(e,t,n){let r=!0;for(let o=0;o`${e.charAt(0).toLocaleUpperCase()}${e.substr(1)}`;let vr,gr,yr;let _r=null;const br=e=>{_r=e};let wr=null;const xr=e=>{wr=e};let kr=0;function Sr(e={}){const t=on(e.version)?e.version:"9.2.2",n=on(e.locale)?e.locale:hr,r=nn(e.fallbackLocale)||un(e.fallbackLocale)||on(e.fallbackLocale)||!1===e.fallbackLocale?e.fallbackLocale:n,o=un(e.messages)?e.messages:{[n]:{}},i=un(e.datetimeFormats)?e.datetimeFormats:{[n]:{}},l=un(e.numberFormats)?e.numberFormats:{[n]:{}},a=Yt({},e.modifiers||{},{upper:(e,t)=>"text"===t&&on(e)?e.toUpperCase():"vnode"===t&&an(e)&&"__v_isVNode"in e?e.children.toUpperCase():e,lower:(e,t)=>"text"===t&&on(e)?e.toLowerCase():"vnode"===t&&an(e)&&"__v_isVNode"in e?e.children.toLowerCase():e,capitalize:(e,t)=>"text"===t&&on(e)?mr(e):"vnode"===t&&an(e)&&"__v_isVNode"in e?mr(e.children):e}),s=e.pluralRules||{},c=rn(e.missing)?e.missing:null,u=!ln(e.missingWarn)&&!qt(e.missingWarn)||e.missingWarn,f=!ln(e.fallbackWarn)&&!qt(e.fallbackWarn)||e.fallbackWarn,p=!!e.fallbackFormat,d=!!e.unresolving,h=rn(e.postTranslation)?e.postTranslation:null,m=un(e.processor)?e.processor:null,v=!ln(e.warnHtmlMessage)||e.warnHtmlMessage,g=!!e.escapeParameter,y=rn(e.messageCompiler)?e.messageCompiler:vr,_=rn(e.messageResolver)?e.messageResolver:gr||Xn,b=rn(e.localeFallbacker)?e.localeFallbacker:yr||cr,w=an(e.fallbackContext)?e.fallbackContext:void 0,x=rn(e.onWarn)?e.onWarn:Kt,k=e,S=an(k.__datetimeFormatters)?k.__datetimeFormatters:new Map,E=an(k.__numberFormatters)?k.__numberFormatters:new Map,C=an(k.__meta)?k.__meta:{};kr++;const T={version:t,cid:kr,locale:n,fallbackLocale:r,messages:o,modifiers:a,pluralRules:s,missing:c,missingWarn:u,fallbackWarn:f,fallbackFormat:p,unresolving:d,postTranslation:h,processor:m,warnHtmlMessage:v,escapeParameter:g,messageCompiler:y,messageResolver:_,localeFallbacker:b,fallbackContext:w,onWarn:x,__meta:C};return T.datetimeFormats=i,T.numberFormats=l,T.__datetimeFormatters=S,T.__numberFormatters=E,__INTLIFY_PROD_DEVTOOLS__&&function(e,t,n){ir&&ir.emit(zn,{timestamp:Date.now(),i18n:e,version:t,meta:n})}(T,t,C),T}function Er(e,t,n,r,o){const{missing:i,onWarn:l}=e;if(null!==i){const r=i(e,n,t,o);return on(r)?r:t}return t}function Cr(e,t,n){e.__localeChainCache=new Map,e.localeFallbacker(e,n,t)}const Tr=e=>e;let Nr=Object.create(null);let Lr=En;const Or=()=>++Lr,Ar={INVALID_ARGUMENT:Lr,INVALID_DATE_ARGUMENT:Or(),INVALID_ISO_DATE_ARGUMENT:Or(),__EXTEND_POINT__:Or()};function Pr(e){return Cn(e,null,void 0)}const Ir=()=>"",Rr=e=>rn(e);function Fr(e,...t){const{fallbackFormat:n,postTranslation:r,unresolving:o,messageCompiler:i,fallbackLocale:l,messages:a}=e,[s,c]=jr(...t),u=ln(c.missingWarn)?c.missingWarn:e.missingWarn,f=ln(c.fallbackWarn)?c.fallbackWarn:e.fallbackWarn,p=ln(c.escapeParameter)?c.escapeParameter:e.escapeParameter,d=!!c.resolvedMessage,h=on(c.default)||ln(c.default)?ln(c.default)?i?s:()=>s:c.default:n?i?s:()=>s:"",m=n||""!==h,v=on(c.locale)?c.locale:e.locale;p&&function(e){nn(e.list)?e.list=e.list.map((e=>on(e)?Qt(e):e)):an(e.named)&&Object.keys(e.named).forEach((t=>{on(e.named[t])&&(e.named[t]=Qt(e.named[t]))}))}(c);let[g,y,_]=d?[s,v,a[v]||{}]:Mr(e,s,v,l,f,u),b=g,w=s;if(d||on(b)||Rr(b)||m&&(b=h,w=b),!(d||(on(b)||Rr(b))&&on(y)))return o?-1:s;let x=!1;const k=Rr(b)?b:Br(e,s,y,b,w,(()=>{x=!0}));if(x)return b;const S=function(e,t,n,r){const{modifiers:o,pluralRules:i,messageResolver:l,fallbackLocale:a,fallbackWarn:s,missingWarn:c,fallbackContext:u}=e,f=r=>{let o=l(n,r);if(null==o&&u){const[,,e]=Mr(u,r,t,a,s,c);o=l(e,r)}if(on(o)){let n=!1;const i=Br(e,r,t,o,r,(()=>{n=!0}));return n?Ir:i}return Rr(o)?o:Ir},p={locale:t,modifiers:o,pluralRules:i,messages:f};e.processor&&(p.processor=e.processor);r.list&&(p.list=r.list);r.named&&(p.named=r.named);Gt(r.plural)&&(p.pluralIndex=r.plural);return p}(e,y,_,c),E=function(e,t,n){0;0;return t(n)}(0,k,or(S)),C=r?r(E,s):E;if(__INTLIFY_PROD_DEVTOOLS__){const t={timestamp:Date.now(),key:on(s)?s:Rr(b)?b.key:"",locale:y||(Rr(b)?b.locale:""),format:on(b)?b:Rr(b)?b.source:"",message:C};t.meta=Yt({},e.__meta,_r||{}),lr(t)}return C}function Mr(e,t,n,r,o,i){const{messages:l,onWarn:a,messageResolver:s,localeFallbacker:c}=e,u=c(e,r,n);let f,p={},d=null,h=n,m=null;for(let n=0;nr;return e.locale=n,e.key=t,e}const s=l(r,function(e,t,n,r,o,i){return{warnHtmlMessage:o,onError:e=>{throw i&&i(e),e},onCacheKey:e=>((e,t,n)=>zt({l:e,k:t,s:n}))(t,n,e)}}(0,n,o,0,a,i));return s.locale=n,s.key=t,s.source=r,s}function jr(...e){const[t,n,r]=e,o={};if(!on(t)&&!Gt(t)&&!Rr(t))throw Pr(Ar.INVALID_ARGUMENT);const i=Gt(t)?String(t):(Rr(t),t);return Gt(n)?o.plural=n:on(n)?o.default=n:un(n)&&!Jt(n)?o.named=n:nn(n)&&(o.list=n),Gt(r)?o.plural=r:on(r)?o.default=r:un(r)&&Yt(o,r),[i,o]}const Vr="undefined"!=typeof Intl;Vr&&Intl.DateTimeFormat,Vr&&Intl.NumberFormat;function Dr(e,...t){const{datetimeFormats:n,unresolving:r,fallbackLocale:o,onWarn:i,localeFallbacker:l}=e,{__datetimeFormatters:a}=e;const[s,c,u,f]=Ur(...t),p=(ln(u.missingWarn)?u.missingWarn:e.missingWarn,ln(u.fallbackWarn)?u.fallbackWarn:e.fallbackWarn,!!u.part),d=on(u.locale)?u.locale:e.locale,h=l(e,o,d);if(!on(s)||""===s)return new Intl.DateTimeFormat(d,f).format(c);let m,v={},g=null,y=d,_=null;for(let t=0;t{$r.includes(e)?a[e]=n[e]:i[e]=n[e]})),on(r)?i.locale=r:un(r)&&(a=r),un(o)&&(a=o),[i.key||"",l,i,a]}function Wr(e,t,n){const r=e;for(const e in n){const n=`${t}__${e}`;r.__datetimeFormatters.has(n)&&r.__datetimeFormatters.delete(n)}}function Hr(e,...t){const{numberFormats:n,unresolving:r,fallbackLocale:o,onWarn:i,localeFallbacker:l}=e,{__numberFormatters:a}=e;const[s,c,u,f]=Gr(...t),p=(ln(u.missingWarn)?u.missingWarn:e.missingWarn,ln(u.fallbackWarn)?u.fallbackWarn:e.fallbackWarn,!!u.part),d=on(u.locale)?u.locale:e.locale,h=l(e,o,d);if(!on(s)||""===s)return new Intl.NumberFormat(d,f).format(c);let m,v={},g=null,y=d,_=null;for(let t=0;t{zr.includes(e)?l[e]=n[e]:i[e]=n[e]})),on(r)?i.locale=r:un(r)&&(l=r),un(o)&&(l=o),[i.key||"",a,i,l]}function qr(e,t,n){const r=e;for(const e in n){const n=`${t}__${e}`;r.__numberFormatters.has(n)&&r.__numberFormatters.delete(n)}}"boolean"!=typeof __INTLIFY_PROD_DEVTOOLS__&&(Xt().__INTLIFY_PROD_DEVTOOLS__=!1);let Jr=sr;const Kr=()=>++Jr;Kr(),Kr(),Kr(),Kr(),Kr(),Kr();let Yr=En;const Zr=()=>++Yr,Xr={UNEXPECTED_RETURN_TYPE:Yr,INVALID_ARGUMENT:Zr(),MUST_BE_CALL_SETUP_TOP:Zr(),NOT_INSLALLED:Zr(),NOT_AVAILABLE_IN_LEGACY_MODE:Zr(),REQUIRED_VALUE:Zr(),INVALID_VALUE:Zr(),CANNOT_SETUP_VUE_DEVTOOLS_PLUGIN:Zr(),NOT_INSLALLED_WITH_PROVIDE:Zr(),UNEXPECTED_ERROR:Zr(),NOT_COMPATIBLE_LEGACY_VUE_I18N:Zr(),BRIDGE_SUPPORT_VUE_2_ONLY:Zr(),MUST_DEFINE_I18N_OPTION_IN_ALLOW_COMPOSITION:Zr(),NOT_AVAILABLE_COMPOSITION_IN_LEGACY:Zr(),__EXTEND_POINT__:Zr()};function Qr(e,...t){return Cn(e,null,void 0)}const eo=Ht("__transrateVNode"),to=Ht("__datetimeParts"),no=Ht("__numberParts"),ro=Ht("__setPluralRules");Ht("__intlifyMeta");const oo=Ht("__injectWithOption");function io(e){if(!an(e))return e;for(const t in e)if(tn(e,t))if(t.includes(".")){const n=t.split("."),r=n.length-1;let o=e;for(let e=0;e{if("locale"in e&&"resource"in e){const{locale:t,resource:n}=e;t?(l[t]=l[t]||{},so(n,l[t])):so(n,l)}else on(e)&&so(JSON.parse(e),l)})),null==o&&i)for(const e in l)tn(l,e)&&io(l[e]);return l}const ao=e=>!an(e)||nn(e);function so(e,t){if(ao(e)||ao(t))throw Qr(Xr.INVALID_VALUE);for(const n in e)tn(e,n)&&(ao(e[n])||ao(t[n])?t[n]=e[n]:so(e[n],t[n]))}function co(e){return e.type}function uo(e,t,n){let r=an(t.messages)?t.messages:{};"__i18nGlobal"in n&&(r=lo(e.locale.value,{messages:r,__i18n:n.__i18nGlobal}));const o=Object.keys(r);if(o.length&&o.forEach((t=>{e.mergeLocaleMessage(t,r[t])})),an(t.datetimeFormats)){const n=Object.keys(t.datetimeFormats);n.length&&n.forEach((n=>{e.mergeDateTimeFormat(n,t.datetimeFormats[n])}))}if(an(t.numberFormats)){const n=Object.keys(t.numberFormats);n.length&&n.forEach((n=>{e.mergeNumberFormat(n,t.numberFormats[n])}))}}function fo(e){return(0,r.createVNode)(r.Text,null,e,0)}const po="__INTLIFY_META__";let ho=0;function mo(e){return(t,n,o,i)=>e(n,o,(0,r.getCurrentInstance)()||void 0,i)}function vo(e={},t){const{__root:n}=e,o=void 0===n;let i=!ln(e.inheritLocale)||e.inheritLocale;const l=(0,r.ref)(n&&i?n.locale.value:on(e.locale)?e.locale:hr),a=(0,r.ref)(n&&i?n.fallbackLocale.value:on(e.fallbackLocale)||nn(e.fallbackLocale)||un(e.fallbackLocale)||!1===e.fallbackLocale?e.fallbackLocale:l.value),s=(0,r.ref)(lo(l.value,e)),c=(0,r.ref)(un(e.datetimeFormats)?e.datetimeFormats:{[l.value]:{}}),u=(0,r.ref)(un(e.numberFormats)?e.numberFormats:{[l.value]:{}});let f=n?n.missingWarn:!ln(e.missingWarn)&&!qt(e.missingWarn)||e.missingWarn,p=n?n.fallbackWarn:!ln(e.fallbackWarn)&&!qt(e.fallbackWarn)||e.fallbackWarn,d=n?n.fallbackRoot:!ln(e.fallbackRoot)||e.fallbackRoot,h=!!e.fallbackFormat,m=rn(e.missing)?e.missing:null,v=rn(e.missing)?mo(e.missing):null,g=rn(e.postTranslation)?e.postTranslation:null,y=n?n.warnHtmlMessage:!ln(e.warnHtmlMessage)||e.warnHtmlMessage,_=!!e.escapeParameter;const b=n?n.modifiers:un(e.modifiers)?e.modifiers:{};let w,x=e.pluralRules||n&&n.pluralRules;w=(()=>{o&&xr(null);const t={version:"9.2.2",locale:l.value,fallbackLocale:a.value,messages:s.value,modifiers:b,pluralRules:x,missing:null===v?void 0:v,missingWarn:f,fallbackWarn:p,fallbackFormat:h,unresolving:!0,postTranslation:null===g?void 0:g,warnHtmlMessage:y,escapeParameter:_,messageResolver:e.messageResolver,__meta:{framework:"vue"}};t.datetimeFormats=c.value,t.numberFormats=u.value,t.__datetimeFormatters=un(w)?w.__datetimeFormatters:void 0,t.__numberFormatters=un(w)?w.__numberFormatters:void 0;const n=Sr(t);return o&&xr(n),n})(),Cr(w,l.value,a.value);const k=(0,r.computed)({get:()=>l.value,set:e=>{l.value=e,w.locale=l.value}}),S=(0,r.computed)({get:()=>a.value,set:e=>{a.value=e,w.fallbackLocale=a.value,Cr(w,l.value,e)}}),E=(0,r.computed)((()=>s.value)),C=(0,r.computed)((()=>c.value)),T=(0,r.computed)((()=>u.value));const N=(e,t,i,f,p,h)=>{let m;if(l.value,a.value,s.value,c.value,u.value,__INTLIFY_PROD_DEVTOOLS__)try{br((()=>{const e=(0,r.getCurrentInstance)();let t=null;return e&&(t=co(e)[po])?{[po]:t}:null})()),o||(w.fallbackContext=n?wr:void 0),m=e(w)}finally{br(null),o||(w.fallbackContext=void 0)}else m=e(w);if(Gt(m)&&-1===m){const[e,r]=t();return n&&d?f(n):p(e)}if(h(m))return m;throw Qr(Xr.UNEXPECTED_RETURN_TYPE)};function L(...e){return N((t=>Reflect.apply(Fr,null,[t,...e])),(()=>jr(...e)),0,(t=>Reflect.apply(t.t,t,[...e])),(e=>e),(e=>on(e)))}const O={normalize:function(e){return e.map((e=>on(e)||Gt(e)||ln(e)?fo(String(e)):e))},interpolate:e=>e,type:"vnode"};function A(e){return s.value[e]||{}}ho++,n&&Ut&&((0,r.watch)(n.locale,(e=>{i&&(l.value=e,w.locale=e,Cr(w,l.value,a.value))})),(0,r.watch)(n.fallbackLocale,(e=>{i&&(a.value=e,w.fallbackLocale=e,Cr(w,l.value,a.value))})));const P={id:ho,locale:k,fallbackLocale:S,get inheritLocale(){return i},set inheritLocale(e){i=e,e&&n&&(l.value=n.locale.value,a.value=n.fallbackLocale.value,Cr(w,l.value,a.value))},get availableLocales(){return Object.keys(s.value).sort()},messages:E,get modifiers(){return b},get pluralRules(){return x||{}},get isGlobal(){return o},get missingWarn(){return f},set missingWarn(e){f=e,w.missingWarn=f},get fallbackWarn(){return p},set fallbackWarn(e){p=e,w.fallbackWarn=p},get fallbackRoot(){return d},set fallbackRoot(e){d=e},get fallbackFormat(){return h},set fallbackFormat(e){h=e,w.fallbackFormat=h},get warnHtmlMessage(){return y},set warnHtmlMessage(e){y=e,w.warnHtmlMessage=e},get escapeParameter(){return _},set escapeParameter(e){_=e,w.escapeParameter=e},t:L,getLocaleMessage:A,setLocaleMessage:function(e,t){s.value[e]=t,w.messages=s.value},mergeLocaleMessage:function(e,t){s.value[e]=s.value[e]||{},so(t,s.value[e]),w.messages=s.value},getPostTranslationHandler:function(){return rn(g)?g:null},setPostTranslationHandler:function(e){g=e,w.postTranslation=e},getMissingHandler:function(){return m},setMissingHandler:function(e){null!==e&&(v=mo(e)),m=e,w.missing=v},[ro]:function(e){x=e,w.pluralRules=x}};return P.datetimeFormats=C,P.numberFormats=T,P.rt=function(...e){const[t,n,r]=e;if(r&&!an(r))throw Qr(Xr.INVALID_ARGUMENT);return L(t,n,Yt({resolvedMessage:!0},r||{}))},P.te=function(e,t){const n=A(on(t)?t:l.value);return null!==w.messageResolver(n,e)},P.tm=function(e){const t=function(e){let t=null;const n=ur(w,a.value,l.value);for(let r=0;rReflect.apply(Dr,null,[t,...e])),(()=>Ur(...e)),0,(t=>Reflect.apply(t.d,t,[...e])),(()=>""),(e=>on(e)))},P.n=function(...e){return N((t=>Reflect.apply(Hr,null,[t,...e])),(()=>Gr(...e)),0,(t=>Reflect.apply(t.n,t,[...e])),(()=>""),(e=>on(e)))},P.getDateTimeFormat=function(e){return c.value[e]||{}},P.setDateTimeFormat=function(e,t){c.value[e]=t,w.datetimeFormats=c.value,Wr(w,e,t)},P.mergeDateTimeFormat=function(e,t){c.value[e]=Yt(c.value[e]||{},t),w.datetimeFormats=c.value,Wr(w,e,t)},P.getNumberFormat=function(e){return u.value[e]||{}},P.setNumberFormat=function(e,t){u.value[e]=t,w.numberFormats=u.value,qr(w,e,t)},P.mergeNumberFormat=function(e,t){u.value[e]=Yt(u.value[e]||{},t),w.numberFormats=u.value,qr(w,e,t)},P[oo]=e.__injectWithOption,P[eo]=function(...e){return N((t=>{let n;const r=t;try{r.processor=O,n=Reflect.apply(Fr,null,[r,...e])}finally{r.processor=null}return n}),(()=>jr(...e)),0,(t=>t[eo](...e)),(e=>[fo(e)]),(e=>nn(e)))},P[to]=function(...e){return N((t=>Reflect.apply(Dr,null,[t,...e])),(()=>Ur(...e)),0,(t=>t[to](...e)),(()=>[]),(e=>on(e)||nn(e)))},P[no]=function(...e){return N((t=>Reflect.apply(Hr,null,[t,...e])),(()=>Gr(...e)),0,(t=>t[no](...e)),(()=>[]),(e=>on(e)||nn(e)))},P}function go(e={},t){{const t=vo(function(e){const t=on(e.locale)?e.locale:hr,n=on(e.fallbackLocale)||nn(e.fallbackLocale)||un(e.fallbackLocale)||!1===e.fallbackLocale?e.fallbackLocale:t,r=rn(e.missing)?e.missing:void 0,o=!ln(e.silentTranslationWarn)&&!qt(e.silentTranslationWarn)||!e.silentTranslationWarn,i=!ln(e.silentFallbackWarn)&&!qt(e.silentFallbackWarn)||!e.silentFallbackWarn,l=!ln(e.fallbackRoot)||e.fallbackRoot,a=!!e.formatFallbackMessages,s=un(e.modifiers)?e.modifiers:{},c=e.pluralizationRules,u=rn(e.postTranslation)?e.postTranslation:void 0,f=!on(e.warnHtmlInMessage)||"off"!==e.warnHtmlInMessage,p=!!e.escapeParameterHtml,d=!ln(e.sync)||e.sync;let h=e.messages;if(un(e.sharedMessages)){const t=e.sharedMessages;h=Object.keys(t).reduce(((e,n)=>{const r=e[n]||(e[n]={});return Yt(r,t[n]),e}),h||{})}const{__i18n:m,__root:v,__injectWithOption:g}=e,y=e.datetimeFormats,_=e.numberFormats;return{locale:t,fallbackLocale:n,messages:h,flatJson:e.flatJson,datetimeFormats:y,numberFormats:_,missing:r,missingWarn:o,fallbackWarn:i,fallbackRoot:l,fallbackFormat:a,modifiers:s,pluralRules:c,postTranslation:u,warnHtmlMessage:f,escapeParameter:p,messageResolver:e.messageResolver,inheritLocale:d,__i18n:m,__root:v,__injectWithOption:g}}(e)),n={id:t.id,get locale(){return t.locale.value},set locale(e){t.locale.value=e},get fallbackLocale(){return t.fallbackLocale.value},set fallbackLocale(e){t.fallbackLocale.value=e},get messages(){return t.messages.value},get datetimeFormats(){return t.datetimeFormats.value},get numberFormats(){return t.numberFormats.value},get availableLocales(){return t.availableLocales},get formatter(){return{interpolate:()=>[]}},set formatter(e){},get missing(){return t.getMissingHandler()},set missing(e){t.setMissingHandler(e)},get silentTranslationWarn(){return ln(t.missingWarn)?!t.missingWarn:t.missingWarn},set silentTranslationWarn(e){t.missingWarn=ln(e)?!e:e},get silentFallbackWarn(){return ln(t.fallbackWarn)?!t.fallbackWarn:t.fallbackWarn},set silentFallbackWarn(e){t.fallbackWarn=ln(e)?!e:e},get modifiers(){return t.modifiers},get formatFallbackMessages(){return t.fallbackFormat},set formatFallbackMessages(e){t.fallbackFormat=e},get postTranslation(){return t.getPostTranslationHandler()},set postTranslation(e){t.setPostTranslationHandler(e)},get sync(){return t.inheritLocale},set sync(e){t.inheritLocale=e},get warnHtmlInMessage(){return t.warnHtmlMessage?"warn":"off"},set warnHtmlInMessage(e){t.warnHtmlMessage="off"!==e},get escapeParameterHtml(){return t.escapeParameter},set escapeParameterHtml(e){t.escapeParameter=e},get preserveDirectiveContent(){return!0},set preserveDirectiveContent(e){},get pluralizationRules(){return t.pluralRules||{}},__composer:t,t(...e){const[n,r,o]=e,i={};let l=null,a=null;if(!on(n))throw Qr(Xr.INVALID_ARGUMENT);const s=n;return on(r)?i.locale=r:nn(r)?l=r:un(r)&&(a=r),nn(o)?l=o:un(o)&&(a=o),Reflect.apply(t.t,t,[s,l||a||{},i])},rt:(...e)=>Reflect.apply(t.rt,t,[...e]),tc(...e){const[n,r,o]=e,i={plural:1};let l=null,a=null;if(!on(n))throw Qr(Xr.INVALID_ARGUMENT);const s=n;return on(r)?i.locale=r:Gt(r)?i.plural=r:nn(r)?l=r:un(r)&&(a=r),on(o)?i.locale=o:nn(o)?l=o:un(o)&&(a=o),Reflect.apply(t.t,t,[s,l||a||{},i])},te:(e,n)=>t.te(e,n),tm:e=>t.tm(e),getLocaleMessage:e=>t.getLocaleMessage(e),setLocaleMessage(e,n){t.setLocaleMessage(e,n)},mergeLocaleMessage(e,n){t.mergeLocaleMessage(e,n)},d:(...e)=>Reflect.apply(t.d,t,[...e]),getDateTimeFormat:e=>t.getDateTimeFormat(e),setDateTimeFormat(e,n){t.setDateTimeFormat(e,n)},mergeDateTimeFormat(e,n){t.mergeDateTimeFormat(e,n)},n:(...e)=>Reflect.apply(t.n,t,[...e]),getNumberFormat:e=>t.getNumberFormat(e),setNumberFormat(e,n){t.setNumberFormat(e,n)},mergeNumberFormat(e,n){t.mergeNumberFormat(e,n)},getChoiceIndex:(e,t)=>-1,__onComponentInstanceCreated(t){const{componentInstanceCreatedListener:r}=e;r&&r(t,n)}};return n}}const yo={tag:{type:[String,Object]},locale:{type:String},scope:{type:String,validator:e=>"parent"===e||"global"===e,default:"parent"},i18n:{type:Object}};function _o(e){return r.Fragment}const bo={name:"i18n-t",props:Yt({keypath:{type:String,required:!0},plural:{type:[Number,String],validator:e=>Gt(e)||!isNaN(e)}},yo),setup(e,t){const{slots:n,attrs:o}=t,i=e.i18n||Lo({useScope:e.scope,__useComponent:!0});return()=>{const l=Object.keys(n).filter((e=>"_"!==e)),a={};e.locale&&(a.locale=e.locale),void 0!==e.plural&&(a.plural=on(e.plural)?+e.plural:e.plural);const s=function({slots:e},t){if(1===t.length&&"default"===t[0])return(e.default?e.default():[]).reduce(((e,t)=>[...e,...nn(t.children)?t.children:[t]]),[]);return t.reduce(((t,n)=>{const r=e[n];return r&&(t[n]=r()),t}),{})}(t,l),c=i[eo](e.keypath,s,a),u=Yt({},o),f=on(e.tag)||an(e.tag)?e.tag:_o();return(0,r.h)(f,u,c)}}};function wo(e,t,n,o){const{slots:i,attrs:l}=t;return()=>{const t={part:!0};let a={};e.locale&&(t.locale=e.locale),on(e.format)?t.key=e.format:an(e.format)&&(on(e.format.key)&&(t.key=e.format.key),a=Object.keys(e.format).reduce(((t,r)=>n.includes(r)?Yt({},t,{[r]:e.format[r]}):t),{}));const s=o(e.value,t,a);let c=[t.key];nn(s)?c=s.map(((e,t)=>{const n=i[e.type],r=n?n({[e.type]:e.value,index:t,parts:s}):[e.value];var o;return nn(o=r)&&!on(o[0])&&(r[0].key=`${e.type}-${t}`),r})):on(s)&&(c=[s]);const u=Yt({},l),f=on(e.tag)||an(e.tag)?e.tag:_o();return(0,r.h)(f,u,c)}}const xo={name:"i18n-n",props:Yt({value:{type:Number,required:!0},format:{type:[String,Object]}},yo),setup(e,t){const n=e.i18n||Lo({useScope:"parent",__useComponent:!0});return wo(e,t,zr,((...e)=>n[no](...e)))}},ko={name:"i18n-d",props:Yt({value:{type:[Number,Date],required:!0},format:{type:[String,Object]}},yo),setup(e,t){const n=e.i18n||Lo({useScope:"parent",__useComponent:!0});return wo(e,t,$r,((...e)=>n[to](...e)))}};function So(e){if(on(e))return{path:e};if(un(e)){if(!("path"in e))throw Qr(Xr.REQUIRED_VALUE);return e}throw Qr(Xr.INVALID_VALUE)}function Eo(e){const{path:t,locale:n,args:r,choice:o,plural:i}=e,l={},a=r||{};return on(n)&&(l.locale=n),Gt(o)&&(l.plural=o),Gt(i)&&(l.plural=i),[t,a,l]}function Co(e,t,...n){const o=un(n[0])?n[0]:{},i=!!o.useI18nComponentName;(!ln(o.globalInstall)||o.globalInstall)&&(e.component(i?"i18n":bo.name,bo),e.component(xo.name,xo),e.component(ko.name,ko)),e.directive("t",function(e){const t=t=>{const{instance:n,modifiers:r,value:o}=t;if(!n||!n.$)throw Qr(Xr.UNEXPECTED_ERROR);const i=function(e,t){const n=e;if("composition"===e.mode)return n.__getInstance(t)||e.global;{const r=n.__getInstance(t);return null!=r?r.__composer:e.global.__composer}}(e,n.$),l=So(o);return[Reflect.apply(i.t,i,[...Eo(l)]),i]};return{created:(n,o)=>{const[i,l]=t(o);Ut&&e.global===l&&(n.__i18nWatcher=(0,r.watch)(l.locale,(()=>{o.instance&&o.instance.$forceUpdate()}))),n.__composer=l,n.textContent=i},unmounted:e=>{Ut&&e.__i18nWatcher&&(e.__i18nWatcher(),e.__i18nWatcher=void 0,delete e.__i18nWatcher),e.__composer&&(e.__composer=void 0,delete e.__composer)},beforeUpdate:(e,{value:t})=>{if(e.__composer){const n=e.__composer,r=So(t);e.textContent=Reflect.apply(n.t,n,[...Eo(r)])}},getSSRProps:e=>{const[n]=t(e);return{textContent:n}}}}(t))}function To(e,t){e.locale=t.locale||e.locale,e.fallbackLocale=t.fallbackLocale||e.fallbackLocale,e.missing=t.missing||e.missing,e.silentTranslationWarn=t.silentTranslationWarn||e.silentFallbackWarn,e.silentFallbackWarn=t.silentFallbackWarn||e.silentFallbackWarn,e.formatFallbackMessages=t.formatFallbackMessages||e.formatFallbackMessages,e.postTranslation=t.postTranslation||e.postTranslation,e.warnHtmlInMessage=t.warnHtmlInMessage||e.warnHtmlInMessage,e.escapeParameterHtml=t.escapeParameterHtml||e.escapeParameterHtml,e.sync=t.sync||e.sync,e.__composer[ro](t.pluralizationRules||e.pluralizationRules);const n=lo(e.locale,{messages:t.messages,__i18n:t.__i18n});return Object.keys(n).forEach((t=>e.mergeLocaleMessage(t,n[t]))),t.datetimeFormats&&Object.keys(t.datetimeFormats).forEach((n=>e.mergeDateTimeFormat(n,t.datetimeFormats[n]))),t.numberFormats&&Object.keys(t.numberFormats).forEach((n=>e.mergeNumberFormat(n,t.numberFormats[n]))),e}const No=Ht("global-vue-i18n");function Lo(e={}){const t=(0,r.getCurrentInstance)();if(null==t)throw Qr(Xr.MUST_BE_CALL_SETUP_TOP);if(!t.isCE&&null!=t.appContext.app&&!t.appContext.app.__VUE_I18N_SYMBOL__)throw Qr(Xr.NOT_INSLALLED);const n=function(e){{const t=(0,r.inject)(e.isCE?No:e.appContext.app.__VUE_I18N_SYMBOL__);if(!t)throw Qr(e.isCE?Xr.NOT_INSLALLED_WITH_PROVIDE:Xr.UNEXPECTED_ERROR);return t}}(t),o=function(e){return"composition"===e.mode?e.global:e.global.__composer}(n),i=co(t),l=function(e,t){return Jt(e)?"__i18n"in t?"local":"global":e.useScope?e.useScope:"local"}(e,i);if(__VUE_I18N_LEGACY_API__&&"legacy"===n.mode&&!e.__useComponent){if(!n.allowComposition)throw Qr(Xr.NOT_AVAILABLE_IN_LEGACY_MODE);return function(e,t,n,o={}){const i="local"===t,l=(0,r.shallowRef)(null);if(i&&e.proxy&&!e.proxy.$options.i18n&&!e.proxy.$options.__i18n)throw Qr(Xr.MUST_DEFINE_I18N_OPTION_IN_ALLOW_COMPOSITION);const a=!ln(o.inheritLocale)||o.inheritLocale,s=(0,r.ref)(i&&a?n.locale.value:on(o.locale)?o.locale:hr),c=(0,r.ref)(i&&a?n.fallbackLocale.value:on(o.fallbackLocale)||nn(o.fallbackLocale)||un(o.fallbackLocale)||!1===o.fallbackLocale?o.fallbackLocale:s.value),u=(0,r.ref)(lo(s.value,o)),f=(0,r.ref)(un(o.datetimeFormats)?o.datetimeFormats:{[s.value]:{}}),p=(0,r.ref)(un(o.numberFormats)?o.numberFormats:{[s.value]:{}}),d=i?n.missingWarn:!ln(o.missingWarn)&&!qt(o.missingWarn)||o.missingWarn,h=i?n.fallbackWarn:!ln(o.fallbackWarn)&&!qt(o.fallbackWarn)||o.fallbackWarn,m=i?n.fallbackRoot:!ln(o.fallbackRoot)||o.fallbackRoot,v=!!o.fallbackFormat,g=rn(o.missing)?o.missing:null,y=rn(o.postTranslation)?o.postTranslation:null,_=i?n.warnHtmlMessage:!ln(o.warnHtmlMessage)||o.warnHtmlMessage,b=!!o.escapeParameter,w=i?n.modifiers:un(o.modifiers)?o.modifiers:{},x=o.pluralRules||i&&n.pluralRules;function k(){return[s.value,c.value,u.value,f.value,p.value]}const S=(0,r.computed)({get:()=>l.value?l.value.locale.value:s.value,set:e=>{l.value&&(l.value.locale.value=e),s.value=e}}),E=(0,r.computed)({get:()=>l.value?l.value.fallbackLocale.value:c.value,set:e=>{l.value&&(l.value.fallbackLocale.value=e),c.value=e}}),C=(0,r.computed)((()=>l.value?l.value.messages.value:u.value)),T=(0,r.computed)((()=>f.value)),N=(0,r.computed)((()=>p.value));function L(){return l.value?l.value.getPostTranslationHandler():y}function O(e){l.value&&l.value.setPostTranslationHandler(e)}function A(){return l.value?l.value.getMissingHandler():g}function P(e){l.value&&l.value.setMissingHandler(e)}function I(e){return k(),e()}function R(...e){return l.value?I((()=>Reflect.apply(l.value.t,null,[...e]))):I((()=>""))}function F(...e){return l.value?Reflect.apply(l.value.rt,null,[...e]):""}function M(...e){return l.value?I((()=>Reflect.apply(l.value.d,null,[...e]))):I((()=>""))}function B(...e){return l.value?I((()=>Reflect.apply(l.value.n,null,[...e]))):I((()=>""))}function j(e){return l.value?l.value.tm(e):{}}function V(e,t){return!!l.value&&l.value.te(e,t)}function D(e){return l.value?l.value.getLocaleMessage(e):{}}function $(e,t){l.value&&(l.value.setLocaleMessage(e,t),u.value[e]=t)}function U(e,t){l.value&&l.value.mergeLocaleMessage(e,t)}function W(e){return l.value?l.value.getDateTimeFormat(e):{}}function H(e,t){l.value&&(l.value.setDateTimeFormat(e,t),f.value[e]=t)}function z(e,t){l.value&&l.value.mergeDateTimeFormat(e,t)}function G(e){return l.value?l.value.getNumberFormat(e):{}}function q(e,t){l.value&&(l.value.setNumberFormat(e,t),p.value[e]=t)}function J(e,t){l.value&&l.value.mergeNumberFormat(e,t)}const K={get id(){return l.value?l.value.id:-1},locale:S,fallbackLocale:E,messages:C,datetimeFormats:T,numberFormats:N,get inheritLocale(){return l.value?l.value.inheritLocale:a},set inheritLocale(e){l.value&&(l.value.inheritLocale=e)},get availableLocales(){return l.value?l.value.availableLocales:Object.keys(u.value)},get modifiers(){return l.value?l.value.modifiers:w},get pluralRules(){return l.value?l.value.pluralRules:x},get isGlobal(){return!!l.value&&l.value.isGlobal},get missingWarn(){return l.value?l.value.missingWarn:d},set missingWarn(e){l.value&&(l.value.missingWarn=e)},get fallbackWarn(){return l.value?l.value.fallbackWarn:h},set fallbackWarn(e){l.value&&(l.value.missingWarn=e)},get fallbackRoot(){return l.value?l.value.fallbackRoot:m},set fallbackRoot(e){l.value&&(l.value.fallbackRoot=e)},get fallbackFormat(){return l.value?l.value.fallbackFormat:v},set fallbackFormat(e){l.value&&(l.value.fallbackFormat=e)},get warnHtmlMessage(){return l.value?l.value.warnHtmlMessage:_},set warnHtmlMessage(e){l.value&&(l.value.warnHtmlMessage=e)},get escapeParameter(){return l.value?l.value.escapeParameter:b},set escapeParameter(e){l.value&&(l.value.escapeParameter=e)},t:R,getPostTranslationHandler:L,setPostTranslationHandler:O,getMissingHandler:A,setMissingHandler:P,rt:F,d:M,n:B,tm:j,te:V,getLocaleMessage:D,setLocaleMessage:$,mergeLocaleMessage:U,getDateTimeFormat:W,setDateTimeFormat:H,mergeDateTimeFormat:z,getNumberFormat:G,setNumberFormat:q,mergeNumberFormat:J};function Y(e){e.locale.value=s.value,e.fallbackLocale.value=c.value,Object.keys(u.value).forEach((t=>{e.mergeLocaleMessage(t,u.value[t])})),Object.keys(f.value).forEach((t=>{e.mergeDateTimeFormat(t,f.value[t])})),Object.keys(p.value).forEach((t=>{e.mergeNumberFormat(t,p.value[t])})),e.escapeParameter=b,e.fallbackFormat=v,e.fallbackRoot=m,e.fallbackWarn=h,e.missingWarn=d,e.warnHtmlMessage=_}return(0,r.onBeforeMount)((()=>{if(null==e.proxy||null==e.proxy.$i18n)throw Qr(Xr.NOT_AVAILABLE_COMPOSITION_IN_LEGACY);const n=l.value=e.proxy.$i18n.__composer;"global"===t?(s.value=n.locale.value,c.value=n.fallbackLocale.value,u.value=n.messages.value,f.value=n.datetimeFormats.value,p.value=n.numberFormats.value):i&&Y(n)})),K}(t,l,o,e)}if("global"===l)return uo(o,e,i),o;if("parent"===l){let r=function(e,t,n=!1){let r=null;const o=t.root;let i=t.parent;for(;null!=i;){const t=e;if("composition"===e.mode)r=t.__getInstance(i);else if(__VUE_I18N_LEGACY_API__){const e=t.__getInstance(i);null!=e&&(r=e.__composer,n&&r&&!r[oo]&&(r=null))}if(null!=r)break;if(o===i)break;i=i.parent}return r}(n,t,e.__useComponent);return null==r&&(r=o),r}const a=n;let s=a.__getInstance(t);if(null==s){const n=Yt({},e);"__i18n"in i&&(n.__i18n=i.__i18n),o&&(n.__root=o),s=vo(n),function(e,t,n){(0,r.onMounted)((()=>{0}),t),(0,r.onUnmounted)((()=>{e.__deleteInstance(t)}),t)}(a,t),a.__setInstance(t,s)}return s}const Oo=["locale","fallbackLocale","availableLocales"],Ao=["t","rt","d","n","tm"];var Po,Io,Ro;if(Po=function(e,t={}){{const n=(t.onCacheKey||Tr)(e),r=Nr[n];if(r)return r;let o=!1;const i=t.onError||Tn;t.onError=e=>{o=!0,i(e)};const{code:l}=Hn(e,t),a=new Function(`return ${l}`)();return o?a:Nr[n]=a}},vr=Po,gr=function(e,t){if(!an(e))return null;let n=Zn.get(t);if(n||(n=function(e){const t=[];let n,r,o,i,l,a,s,c=-1,u=0,f=0;const p=[];function d(){const t=e[c+1];if(5===u&&"'"===t||6===u&&'"'===t)return c++,o="\\"+t,p[0](),!0}for(p[0]=()=>{void 0===r?r=o:r+=o},p[1]=()=>{void 0!==r&&(t.push(r),r=void 0)},p[2]=()=>{p[0](),f++},p[3]=()=>{if(f>0)f--,u=4,p[0]();else{if(f=0,void 0===r)return!1;if(r=Yn(r),!1===r)return!1;p[1]()}};null!==u;)if(c++,n=e[c],"\\"!==n||!d()){if(i=Kn(n),s=qn[u],l=s[i]||s.l||8,8===l)return;if(u=l[0],void 0!==l[1]&&(a=p[l[1]],a&&(o=n,!1===a())))return;if(7===u)return t}}(t),n&&Zn.set(t,n)),!n)return null;const r=n.length;let o=e,i=0;for(;igo(e))):o.run((()=>vo(e)));if(null==n)throw Qr(Xr.UNEXPECTED_ERROR);return[o,n]}}(e,n),c=Ht("");{const e={get mode(){return __VUE_I18N_LEGACY_API__&&n?"legacy":"composition"},get allowComposition(){return i},async install(t,...i){t.__VUE_I18N_SYMBOL__=c,t.provide(t.__VUE_I18N_SYMBOL__,e),!n&&o&&function(e,t){const n=Object.create(null);Oo.forEach((e=>{const o=Object.getOwnPropertyDescriptor(t,e);if(!o)throw Qr(Xr.UNEXPECTED_ERROR);const i=(0,r.isRef)(o.value)?{get:()=>o.value.value,set(e){o.value.value=e}}:{get:()=>o.get&&o.get()};Object.defineProperty(n,e,i)})),e.config.globalProperties.$i18n=n,Ao.forEach((n=>{const r=Object.getOwnPropertyDescriptor(t,n);if(!r||!r.value)throw Qr(Xr.UNEXPECTED_ERROR);Object.defineProperty(e.config.globalProperties,`$${n}`,r)}))}(t,e.global),__VUE_I18N_FULL_INSTALL__&&Co(t,e,...i),__VUE_I18N_LEGACY_API__&&n&&t.mixin(function(e,t,n){return{beforeCreate(){const o=(0,r.getCurrentInstance)();if(!o)throw Qr(Xr.UNEXPECTED_ERROR);const i=this.$options;if(i.i18n){const n=i.i18n;i.__i18n&&(n.__i18n=i.__i18n),n.__root=t,this===this.$root?this.$i18n=To(e,n):(n.__injectWithOption=!0,this.$i18n=go(n))}else i.__i18n?this===this.$root?this.$i18n=To(e,i):this.$i18n=go({__i18n:i.__i18n,__injectWithOption:!0,__root:t}):this.$i18n=e;i.__i18nGlobal&&uo(t,i,i),e.__onComponentInstanceCreated(this.$i18n),n.__setInstance(o,this.$i18n),this.$t=(...e)=>this.$i18n.t(...e),this.$rt=(...e)=>this.$i18n.rt(...e),this.$tc=(...e)=>this.$i18n.tc(...e),this.$te=(e,t)=>this.$i18n.te(e,t),this.$d=(...e)=>this.$i18n.d(...e),this.$n=(...e)=>this.$i18n.n(...e),this.$tm=e=>this.$i18n.tm(e)},mounted(){},unmounted(){const e=(0,r.getCurrentInstance)();if(!e)throw Qr(Xr.UNEXPECTED_ERROR);delete this.$t,delete this.$rt,delete this.$tc,delete this.$te,delete this.$d,delete this.$n,delete this.$tm,n.__deleteInstance(e),delete this.$i18n}}}(s,s.__composer,e));const l=t.unmount;t.unmount=()=>{e.dispose(),l()}},get global(){return s},dispose(){a.stop()},__instances:l,__getInstance:function(e){return l.get(e)||null},__setInstance:function(e,t){l.set(e,t)},__deleteInstance:function(e){l.delete(e)}};return e}}({locale:null!==(Ro=window.location.href.split("/")[3])&&void 0!==Ro?Ro:"en",fallbackLocale:"en",messages:Fo});const Bo=Mo;n(333),n(85);var jo=(0,r.createApp)({});jo.component("news-carousel-next",I),jo.component("events-carousel-next",ne),jo.use(Bo),jo.mount("#slider");var Vo=(0,r.createApp)({});Vo.component("list-overview",Se),Vo.use(Bo),Vo.mount("#list-overview-search");var Do=(0,r.createApp)({});Do.component("main-navigation",$t),Do.use(Bo),Do.mount("#main-navigation")},333:(e,t,n)=>{window._=n(486),window.Vue=n(821),window.axios=n(669),window.axios.defaults.headers.common["X-Requested-With"]="XMLHttpRequest"},85:(e,t,n)=>{"use strict";function r(e,t){var n={start:function(){return 0},center:function(e){return r(e)/2},end:r};function r(e){return t-e}return{measure:function(r){return"number"==typeof e?t*Number(e):n[e](r)}}}function o(e){return Math.abs(e)}function i(e){return e?e/o(e):0}function l(e,t){return o(e-t)}function a(e,t){for(var n=[],r=0;rt}function l(e){return r(e)||i(e)}return{length:n,max:t,min:e,constrain:function(n){return l(n)?r(n)?e:t:n},reachedAny:l,reachedMax:i,reachedMin:r,removeOffset:function(e){return n?e-n*Math.ceil((e-t)/n):e}}}function p(e,t,n){var r=f(0,e),i=r.min,l=r.constrain,a=e+1,s=c(t);function c(e){return n?o((a+e)%a):l(e)}function u(){return s}function d(e){return s=c(e),h}var h={add:function(e){return d(u()+e)},clone:function(){return p(e,u(),n)},get:u,set:d,min:i,max:e};return h}function d(){var e=[];var t={add:function(n,r,o,i){return void 0===i&&(i=!1),n.addEventListener(r,o,i),e.push((function(){return n.removeEventListener(r,o,i)})),t},removeAll:function(){return e=e.filter((function(e){return e()})),t}};return t}function h(e){var t=e;function n(e){return t/=e,o}function r(e){return"number"==typeof e?e:e.get()}var o={add:function(e){return t+=r(e),o},divide:n,get:function(){return t},multiply:function(e){return t*=e,o},normalize:function(){return 0!==t&&n(t),o},set:function(e){return t=r(e),o},subtract:function(e){return t-=r(e),o}};return o}function m(e,t,n,r,a,s,c,u,f,p,m,v,g,y,_){var b=e.cross,w=["INPUT","SELECT","TEXTAREA"],x=h(0),k=d(),S=d(),E={mouse:300,touch:400},C={mouse:500,touch:600},T=a?5:16,N=0,L=0,O=!1,A=!1,P=!1,I=!1;function R(e){if(!(I="mousedown"===e.type)||0===e.button){var t,o,i=l(r.get(),c.get())>=2,a=I||!i,u=(t=e.target,o=t.nodeName||"",!(w.indexOf(o)>-1)),f=i||I&&u;O=!0,s.pointerDown(e),x.set(r),r.set(c),p.useBaseMass().useSpeed(80),function(){var e=I?document:n;S.add(e,"touchmove",F).add(e,"touchend",M).add(e,"mousemove",F).add(e,"mouseup",M)}(),N=s.readPoint(e),L=s.readPoint(e,b),g.emit("pointerDown"),a&&(P=!1),f&&e.preventDefault()}}function F(e){if(!A&&!I){if(!e.cancelable)return M(e);var n=s.readPoint(e),o=s.readPoint(e,b),i=l(n,N),a=l(o,L);if(!(A=i>a)&&!P)return M(e)}var c=s.pointerMove(e);!P&&c&&(P=!0),u.start(),r.add(t.apply(c)),e.preventDefault()}function M(e){var n=m.byDistance(0,!1).index!==v.get(),c=s.pointerUp(e)*(a?C:E)[I?"mouse":"touch"],u=function(e,t){var n=v.clone().add(-1*i(e)),r=n.get()===v.min||n.get()===v.max,l=m.byDistance(e,!a).distance;return a||o(e)<20?l:!y&&r?.4*l:_&&t?.5*l:m.byIndex(n.get(),0).distance}(t.apply(c),n),d=function(e,t){if(0===e||0===t)return 0;if(o(e)<=o(t))return 0;var n=l(o(e),o(t));return o(n/e)}(c,u),h=l(r.get(),x.get())>=.5,b=n&&d>.75,w=o(c)<20,k=b?10:T,N=b?1+2.5*d:1;h&&!I&&(P=!0),A=!1,O=!1,S.removeAll(),p.useSpeed(w?9:k).useMass(N),f.distance(u,!a),I=!1,g.emit("pointerUp")}function B(e){P&&e.preventDefault()}return{addActivationEvents:function(){var e=n;k.add(e,"touchmove",(function(){})).add(e,"touchend",(function(){})).add(e,"touchstart",R).add(e,"mousedown",R).add(e,"touchcancel",M).add(e,"contextmenu",M).add(e,"click",B)},clickAllowed:function(){return!P},pointerDown:function(){return O},removeAllEvents:function(){k.removeAll(),S.removeAll()}}}function v(e,t,n){var r,o,l=(r=2,o=Math.pow(10,r),function(e){return Math.round(e*o)/o}),a=h(0),s=h(0),c=h(0),u=0,f=t,p=n;function d(e){return f=e,v}function m(e){return p=e,v}var v={direction:function(){return u},seek:function(t){c.set(t).subtract(e);var n,r,o,l,d=(n=c.get(),(o=0)+(n-(r=0))/(100-r)*(f-o));return u=i(c.get()),c.normalize().multiply(d).subtract(a),(l=c).divide(p),s.add(l),v},settle:function(t){var n=t.get()-e.get(),r=!l(n);return r&&e.set(t),r},update:function(){a.add(s),e.add(a),s.multiply(0)},useBaseMass:function(){return m(n)},useBaseSpeed:function(){return d(t)},useMass:m,useSpeed:d};return v}function g(e,t,n,r){var i=!1;return{constrain:function(l){if(!i&&e.reachedAny(n.get())&&e.reachedAny(t.get())){var a=e.reachedMin(t.get())?"min":"max",s=o(e[a]-t.get()),c=n.get()-t.get(),u=Math.min(s/50,.85);n.subtract(c*u),!l&&o(c)<10&&(n.set(e.constrain(n.get())),r.useSpeed(10).useMass(3))}},toggleActive:function(e){i=!e}}}function y(e,t,n,r,o){var i=f(-t+e,n[0]),l=r.map(i.constrain);return{snapsContained:function(){if(t<=e)return[i.max];if("keepSnaps"===o)return l;var n=function(){var e=l[0],t=c(l),n=l.lastIndexOf(e),r=l.indexOf(t)+1;return f(n,r)}(),r=n.min,a=n.max;return l.slice(r,a)}()}}function _(e,t,n,r,o){var i=f(n.min+t.measure(.1),n.max+t.measure(.1)),l=i.reachedMin,a=i.reachedMax;return{loop:function(t){if(function(e){return 1===e?a(r.get()):-1===e&&l(r.get())}(t)){var n=e*(-1*t);o.forEach((function(e){return e.add(n)}))}}}}function b(e){var t=e.max,n=e.length;return{get:function(e){return(e-t)/-n}}}function w(e,t,n,r,i,l){var s,u,f=e.startEdge,p=e.endEdge,d=i.map((function(e){return r[f]-e[f]})).map(n.measure).map((function(e){return-o(e)})),h=(s=a(d,l).map((function(e){return e[0]})),u=a(i,l).map((function(e){return c(e)[p]-e[0][f]})).map(n.measure).map(o).map(t.measure),s.map((function(e,t){return e+u[t]})));return{snaps:d,snapsAligned:h}}function x(e,t,n,r,i){var l=r.reachedAny,a=r.removeOffset,s=r.constrain;function c(e,t){return o(e)0?e.concat([n]):e}),[])}function m(e,t){var r="start"===t,o=r?-n:n,a=i.findSlideBounds([o]);return e.map((function(e){var t=r?0:-n,o=r?n:0,i=a.filter((function(t){return t.index===e}))[0][r?"end":"start"];return{point:i,getTarget:function(){return l.get()>i?t:o},index:e,location:-1}}))}return{canLoop:function(){return p.every((function(e){var n=e.index;return d(u.filter((function(e){return e!==n})),t)<=0}))},clear:function(){p.forEach((function(t){var n=t.index;a[n].style[e.startEdge]=""}))},loop:function(){p.forEach((function(t){var n=t.getTarget,r=t.location,o=t.index,i=n();i!==r&&(a[o].style[e.startEdge]=i+"%",t.location=i)}))},loopPoints:p}}function S(e,t,n){var r="x"===e.scroll?function(e){return"translate3d("+e+"%,0px,0px)"}:function(e){return"translate3d(0px,"+e+"%,0px)"},o=n.style,i=!1;return{clear:function(){o.transform=""},to:function(e){i||(o.transform=r(t.apply(e.get())))},toggleActive:function(e){i=!e}}}function E(e,t,n,i,l){var a,E=i.align,C=i.axis,T=i.direction,N=i.startIndex,L=i.inViewThreshold,O=i.loop,A=i.speed,P=i.dragFree,I=i.slidesToScroll,R=i.skipSnaps,F=i.containScroll,M=t.getBoundingClientRect(),B=n.map((function(e){return e.getBoundingClientRect()})),j=function(e){var t="rtl"===e?-1:1;return{apply:function(e){return e*t}}}(T),V=function(e,t){var n="y"===e?"y":"x";return{scroll:n,cross:"y"===e?"x":"y",startEdge:"y"===n?"top":"rtl"===t?"right":"left",endEdge:"y"===n?"bottom":"rtl"===t?"left":"right",measureSize:function(e){var t=e.width,r=e.height;return"x"===n?t:r}}}(C,T),D=(a=V.measureSize(M),{measure:function(e){return 0===a?0:e/a*100},totalPercent:100}),$=D.totalPercent,U=r(E,$),W=function(e,t,n,r,i){var l=e.measureSize,a=e.startEdge,s=e.endEdge,f=r.map(l);return{slideSizes:f.map(t.measure),slideSizesWithGaps:r.map((function(e,t,r){var o=t===u(r),l=window.getComputedStyle(c(n)),p=parseFloat(l.getPropertyValue("margin-"+s));return o?f[t]+(i?p:0):r[t+1][a]-e[a]})).map(t.measure).map(o)}}(V,D,n,B,O),H=W.slideSizes,z=W.slideSizesWithGaps,G=w(V,U,D,M,B,I),q=G.snaps,J=G.snapsAligned,K=-c(q)+c(z),Y=y($,K,q,J,F).snapsContained,Z=!O&&""!==F?Y:J,X=function(e,t,n){var r,o;return{limit:(r=t[0],o=c(t),f(n?r-e:o,r))}}(K,Z,O).limit,Q=p(u(Z),N,O),ee=Q.clone(),te=s(n),ne=function(e){var t=0;function n(e,n){return function(){e===!!t&&n()}}function r(){t=window.requestAnimationFrame(e)}return{proceed:n(!0,r),start:n(!1,r),stop:n(!0,(function(){window.cancelAnimationFrame(t),t=0}))}}((function(){O||fe.scrollBounds.constrain(fe.dragHandler.pointerDown()),fe.scrollBody.seek(ie).update();var e=fe.scrollBody.settle(ie);e&&!fe.dragHandler.pointerDown()&&(fe.animation.stop(),l.emit("settle")),e||l.emit("scroll"),O&&(fe.scrollLooper.loop(fe.scrollBody.direction()),fe.slideLooper.loop()),fe.translate.to(oe),fe.animation.proceed()})),re=Z[Q.get()],oe=h(re),ie=h(re),le=v(oe,A,1),ae=x(O,Z,K,X,ie),se=function(e,t,n,r,o,i){function l(r){var l=r.distance,a=r.index!==t.get();l&&(e.start(),o.add(l)),a&&(n.set(t.get()),t.set(r.index),i.emit("select"))}return{distance:function(e,t){l(r.byDistance(e,t))},index:function(e,n){var o=t.clone().set(e);l(r.byIndex(o.get(),n))}}}(ne,Q,ee,ae,ie,l),ce=function(e,t,n,r,o,i,l){var a=o.removeOffset,s=o.constrain,c=Math.min(Math.max(l,.01),.99),u=i?[0,t,-t]:[0],f=p(u,c);function p(t,o){var i=t||u,l=o||0,a=n.map((function(e){return e*l}));return i.reduce((function(t,o){var i=r.map((function(t,r){return{start:t-n[r]+a[r]+o,end:t+e-a[r]+o,index:r}}));return t.concat(i)}),[])}return{check:function(e,t){var n=i?a(e):s(e);return(t||f).reduce((function(e,t){var r=t.index,o=t.start,i=t.end;return-1===e.indexOf(r)&&on?e.concat([r]):e}),[])},findSlideBounds:p}}($,K,H,q,X,O,L),ue=m(V,j,e,ie,P,function(e,t){var n,r;function i(e){return"undefined"!=typeof TouchEvent&&e instanceof TouchEvent}function l(e){return e.timeStamp}function a(t,n){var r="client"+("x"===(n||e.scroll)?"X":"Y");return(i(t)?t.touches[0]:t)[r]}return{isTouchEvent:i,pointerDown:function(e){return n=e,r=e,t.measure(a(e))},pointerMove:function(e){var o=a(e)-a(r),i=l(e)-l(n)>170;return r=e,i&&(n=e),t.measure(o)},pointerUp:function(e){if(!n||!r)return 0;var i=a(r)-a(n),s=l(e)-l(n),c=l(e)-l(r)>170,u=i/s;return s&&!c&&o(u)>.1?t.measure(u):0},readPoint:a}}(V,D),oe,ne,se,le,ae,Q,l,O,R),fe={containerRect:M,slideRects:B,animation:ne,axis:V,direction:j,dragHandler:ue,eventStore:d(),pxToPercent:D,index:Q,indexPrevious:ee,limit:X,location:oe,options:i,scrollBody:le,scrollBounds:g(X,oe,ie,le),scrollLooper:_(K,D,X,oe,[oe,ie]),scrollProgress:b(X),scrollSnaps:Z,scrollTarget:ae,scrollTo:se,slideLooper:k(V,$,K,z,Z,ce,oe,n),slidesInView:ce,slideIndexes:te,target:ie,translate:S(V,j,t)};return fe}n.r(t);var C={align:"center",axis:"x",containScroll:"",direction:"ltr",dragFree:!1,draggable:!0,inViewThreshold:0,loop:!1,skipSnaps:!1,slidesToScroll:1,speed:10,startIndex:0};function T(e,t,n){var r,o,i,l,a,s,c,u,f,p=function(){var e={};function t(t){return e[t]||[]}var n={emit:function(e){return t(e).forEach((function(t){return t(e)})),n},off:function(r,o){return e[r]=t(r).filter((function(e){return e!==o})),n},on:function(r,o){return e[r]=t(r).concat([o]),n}};return n}(),d=(r=function(){if(g){var e=l.axis.measureSize(c.getBoundingClientRect());b!==e&&k(),p.emit("resize")}},o=500,i=0,function(){window.clearTimeout(i),i=window.setTimeout(r,o)||0}),h=k,m=p.on,v=p.off,g=!1,y=Object.assign({},C,T.globalOptions),_=Object.assign({},y),b=0;function w(){var t,n="container"in e&&e.container,r="slides"in e&&e.slides;c="root"in e?e.root:e,u=n||c.children[0],f=r||[].slice.call(u.children),t=getComputedStyle(c,":before").content,a={get:function(){try{return JSON.parse(t.slice(1,-1).replace(/\\/g,""))}catch(e){}return{}}}}function x(e,t){if(w(),y=Object.assign({},y,e),_=Object.assign({},y,a.get()),s=Object.assign([],t),(l=E(c,u,f,_,p)).eventStore.add(window,"resize",d),l.translate.to(l.location),b=l.axis.measureSize(c.getBoundingClientRect()),s.forEach((function(e){return e.init(A)})),_.loop){if(!l.slideLooper.canLoop())return S(),x({loop:!1},t);l.slideLooper.loop()}_.draggable&&u.offsetParent&&f.length&&l.dragHandler.addActivationEvents(),g||(setTimeout((function(){return p.emit("init")}),0),g=!0)}function k(e,t){if(g){var n=O(),r=Object.assign({startIndex:n},e);S(),x(r,t||s),p.emit("reInit")}}function S(){l.dragHandler.removeAllEvents(),l.animation.stop(),l.eventStore.removeAll(),l.translate.clear(),l.slideLooper.clear(),s.forEach((function(e){return e.destroy()}))}function N(e){var t=l[e?"target":"location"].get(),n=_.loop?"removeOffset":"constrain";return l.slidesInView.check(l.limit[n](t))}function L(e,t,n){l.scrollBody.useBaseMass().useSpeed(t?100:_.speed),g&&l.scrollTo.index(e,n||0)}function O(){return l.index.get()}var A={canScrollNext:function(){return l.index.clone().add(1).get()!==O()},canScrollPrev:function(){return l.index.clone().add(-1).get()!==O()},clickAllowed:function(){return l.dragHandler.clickAllowed()},containerNode:function(){return u},internalEngine:function(){return l},destroy:function(){g&&(S(),g=!1,p.emit("destroy"))},off:v,on:m,previousScrollSnap:function(){return l.indexPrevious.get()},reInit:h,rootNode:function(){return c},scrollNext:function(e){L(l.index.clone().add(1).get(),!0===e,-1)},scrollPrev:function(e){L(l.index.clone().add(-1).get(),!0===e,1)},scrollProgress:function(){return l.scrollProgress.get(l.location.get())},scrollSnapList:function(){return l.scrollSnaps.map(l.scrollProgress.get)},scrollTo:L,selectedScrollSnap:O,slideNodes:function(){return f},slidesInView:N,slidesNotInView:function(e){var t=N(e);return l.slideIndexes.filter((function(e){return-1===t.indexOf(e)}))}};return x(t,n),A}T.globalOptions=void 0;const N=T;var L={delay:4e3,playOnInit:!0,stopOnInteraction:!0,stopOnMouseEnter:!1,stopOnLastSnap:!1};function O(e,t){var n,r=Object.assign({},L,O.globalOptions,e),o=r.playOnInit,i=r.stopOnInteraction,l=r.stopOnMouseEnter,a=r.stopOnLastSnap,s=r.delay,c=i?f:d,u=0;function f(){n.off("pointerDown",c),i||n.off("pointerUp",h),d(),u=0}function p(){d(),u=window.setTimeout(m,s)}function d(){u&&window.clearTimeout(u)}function h(){u&&(d(),p())}function m(){var e=n.internalEngine().index;if(a&&e.get()===e.max)return f();n.canScrollNext()?n.scrollNext():n.scrollTo(0),p()}var v={name:"Autoplay",options:r,init:function(e){var r=(n=e).internalEngine().eventStore,a=n.rootNode(),s=t&&t(a)||a;n.on("pointerDown",c),i||n.on("pointerUp",h),l&&(r.add(s,"mouseenter",c),i||r.add(s,"mouseleave",h)),r.add(document,"visibilitychange",(function(){if("hidden"===document.visibilityState)return d();h()})),r.add(window,"pagehide",(function(e){e.persisted&&d()})),o&&p()},destroy:f,play:p,stop:d,reset:h};return v}O.globalOptions=void 0;const A=O;var P=document.querySelector(".embla");if(P){var I=null==P?void 0:P.querySelector(".embla__viewport"),R=null==P?void 0:P.querySelector(".embla__button--prev"),F=null==P?void 0:P.querySelector(".embla__button--next"),M=document.querySelector(".embla__dots"),B=A({delay:1e4,stopOnInteraction:!1},(function(e){return e.parentElement})),j=N(I,{loop:!1,skipSnaps:!1,speed:2},[B]),V=function(e,t){var n=t.scrollSnapList(),r=document.createDocumentFragment(),o=n.map((function(){return document.createElement("button")}));return o.forEach((function(e){return r.appendChild(e)})),null==e||e.appendChild(r),o}(M,j),D=function(e,t){return function(){var n=t.previousScrollSnap(),r=t.selectedScrollSnap();t.slideNodes()[n].classList.remove("is-selected"),t.slideNodes()[r].classList.add("is-selected"),e[n].classList.remove("is-selected"),e[r].classList.add("is-selected")}}(V,j),$=function(e,t,n){return function(){n.canScrollPrev()?null==e||e.removeAttribute("disabled"):null==e||e.setAttribute("disabled","disabled"),n.canScrollNext()?null==t||t.removeAttribute("disabled"):null==t||t.setAttribute("disabled","disabled")}}(R,F,j);!function(e,t,n){null==e||e.addEventListener("click",(function(){n.reset(),t.scrollPrev(),t.slideNodes()[t.previousScrollSnap()].classList.remove("is-selected"),t.slideNodes()[t.selectedScrollSnap()].classList.add("is-selected")}),!1)}(R,j,B),function(e,t,n){null==e||e.addEventListener("click",(function(){n.reset(),t.scrollNext(),t.slideNodes()[t.previousScrollSnap()].classList.remove("is-selected"),t.slideNodes()[t.selectedScrollSnap()].classList.add("is-selected")}),!1)}(F,j,B),function(e,t){e.forEach((function(e,n){e.classList.add("embla__dot"),e.addEventListener("click",(function(){return t.scrollTo(n)}),!1)}))}(V,j);var U=function(e){var t="resize"===e,n=t?"remove":"add";I.classList[n]("embla--is-ready"),t&&j.reInit()};j.on("select",D),j.on("select",$),j.on("init",D),j.on("init",$),j.on("init",U),j.on("resize",U),j.on("reInit",U),j.internalEngine().translate.toggleActive(!1),j.internalEngine().translate.clear()}},563:(e,t,n)=>{"use strict";n.d(t,{Z:()=>i});var r=n(645),o=n.n(r)()((function(e){return e[1]}));o.push([e.id,".carousel__slide{align-items:center;display:flex;flex-shrink:0;justify-content:center;margin:0;position:relative;scroll-snap-stop:auto}.carousel{margin-left:-.75rem;margin-right:-.75rem;position:relative}.carousel,.carousel *{box-sizing:border-box}.carousel__track{display:flex;margin:0;padding:0;position:relative}.carousel__viewport{overflow:hidden}:root{--vc-clr-primary:#57666a;--vc-clr-secondary:#bfc3c5;--vc-clr-white:#fff;--vc-icn-width:1em;--vc-nav-width:40px;--vc-nav-color:#fff;--vc-nav-background-color:var(--vc-clr-primary);--vc-pgn-width:8px;--vc-pgn-height:8px;--vc-pgn-margin:7px;--vc-pgn-border-radius:0;--vc-pgn-background-color:var(--vc-clr-secondary);--vc-pgn-active-color:var(--vc-clr-primary)}.carousel__next,.carousel__prev{align-items:center;background-color:#fff;border:0;border-radius:100%;color:#005a9a;cursor:pointer;display:none;font-size:calc(var(--vc-nav-width)*2/3);height:var(--vc-nav-width);justify-content:center;padding:0;position:absolute;text-align:center;width:var(--vc-nav-width)}.carousel__prev{right:54px;top:calc(100% - 35px)}.carousel__next{right:0;top:calc(100% - 35px)}.carousel__icon{fill:currentColor;height:var(--vc-icn-width);width:var(--vc-icn-width)}.carousel__pagination{display:flex;flex-wrap:wrap;justify-content:center;list-style:none;margin-left:0;margin-top:30px}@media (min-width:768px){.carousel__pagination{display:flex;justify-content:flex-start;list-style:none;margin-left:8px;margin-top:30px;max-width:300px}.carousel__next,.carousel__prev{display:flex}.carousel__prev{right:66px;top:calc(100% - 35px)}.carousel__next{right:12px;top:calc(100% - 35px)}}.carousel__pagination-button{background-color:var(--vc-pgn-background-color);border:0;border-radius:var(--vc-pgn-height);cursor:pointer;height:var(--vc-pgn-height);margin:var(--vc-pgn-margin);width:var(--vc-pgn-width)}.carousel__pagination-button--active{background-color:var(--vc-pgn-active-color)}",""]);const i=o},284:(e,t,n)=>{"use strict";n.d(t,{Z:()=>i});var r=n(645),o=n.n(r)()((function(e){return e[1]}));o.push([e.id,".mega-height{height:calc(100vh - 93px)}.scrolled .mega-height{height:calc(100vh - 62px)}",""]);const i=o},236:(e,t,n)=>{"use strict";n.d(t,{Z:()=>i});var r=n(645),o=n.n(r)()((function(e){return e[1]}));o.push([e.id,".carousel__slide{align-items:center;display:flex;flex-shrink:0;justify-content:center;margin:0;position:relative;scroll-snap-stop:auto}.carousel{position:relative}.carousel,.carousel *{box-sizing:border-box}.carousel__track{display:flex;margin:0;padding:0;position:relative}.carousel__viewport{overflow:hidden}:root{--vc-clr-primary:#57666a;--vc-clr-secondary:#bfc3c5;--vc-clr-white:#fff;--vc-icn-width:1em;--vc-nav-width:40px;--vc-nav-color:#fff;--vc-nav-background-color:var(--vc-clr-primary);--vc-pgn-width:8px;--vc-pgn-height:8px;--vc-pgn-margin:7px;--vc-pgn-border-radius:0;--vc-pgn-background-color:var(--vc-clr-secondary);--vc-pgn-active-color:var(--vc-clr-primary)}.carousel__next,.carousel__prev{align-items:center;background-color:#fff;border:0;border-radius:9px;color:#005a9a;cursor:pointer;display:none;font-size:calc(var(--vc-nav-width)*2/3);height:var(--vc-nav-width);justify-content:center;padding:0;position:absolute;text-align:center;width:var(--vc-nav-width)}.carousel__prev{right:54px;top:calc(100% - 35px)}.carousel__next{right:0;top:calc(100% - 35px)}.carousel__icon{fill:currentColor;height:var(--vc-icn-width);width:var(--vc-icn-width)}.carousel__pagination{display:flex;flex-wrap:wrap;justify-content:center;list-style:none;margin-left:0;margin-top:30px}@media (min-width:768px){.carousel__pagination{display:flex;justify-content:flex-start;list-style:none;margin-left:8px;margin-top:30px;max-width:300px}.carousel__next,.carousel__prev{display:flex}.carousel__prev{right:66px;top:calc(100% - 35px)}.carousel__next{right:12px;top:calc(100% - 35px)}}.carousel__pagination-button{background-color:var(--vc-pgn-background-color);border:0;border-radius:var(--vc-pgn-height);cursor:pointer;height:var(--vc-pgn-height);margin:var(--vc-pgn-margin);width:var(--vc-pgn-width)}.carousel__pagination-button--active{background-color:var(--vc-pgn-active-color)}",""]);const i=o},645:e=>{"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=e(t);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n})).join("")},t.i=function(e,n,r){"string"==typeof e&&(e=[[null,e,""]]);var o={};if(r)for(var i=0;i"']/g,Y=RegExp(J.source),Z=RegExp(K.source),X=/<%-([\s\S]+?)%>/g,Q=/<%([\s\S]+?)%>/g,ee=/<%=([\s\S]+?)%>/g,te=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,ne=/^\w*$/,re=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,oe=/[\\^$.*+?()[\]{}|]/g,ie=RegExp(oe.source),le=/^\s+/,ae=/\s/,se=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,ce=/\{\n\/\* \[wrapped with (.+)\] \*/,ue=/,? & /,fe=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,pe=/[()=,{}\[\]\/\s]/,de=/\\(\\)?/g,he=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,me=/\w*$/,ve=/^[-+]0x[0-9a-f]+$/i,ge=/^0b[01]+$/i,ye=/^\[object .+?Constructor\]$/,_e=/^0o[0-7]+$/i,be=/^(?:0|[1-9]\d*)$/,we=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,xe=/($^)/,ke=/['\n\r\u2028\u2029\\]/g,Se="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",Ee="\\u2700-\\u27bf",Ce="a-z\\xdf-\\xf6\\xf8-\\xff",Te="A-Z\\xc0-\\xd6\\xd8-\\xde",Ne="\\ufe0e\\ufe0f",Le="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",Oe="['’]",Ae="[\\ud800-\\udfff]",Pe="["+Le+"]",Ie="["+Se+"]",Re="\\d+",Fe="[\\u2700-\\u27bf]",Me="["+Ce+"]",Be="[^\\ud800-\\udfff"+Le+Re+Ee+Ce+Te+"]",je="\\ud83c[\\udffb-\\udfff]",Ve="[^\\ud800-\\udfff]",De="(?:\\ud83c[\\udde6-\\uddff]){2}",$e="[\\ud800-\\udbff][\\udc00-\\udfff]",Ue="["+Te+"]",We="(?:"+Me+"|"+Be+")",He="(?:"+Ue+"|"+Be+")",ze="(?:['’](?:d|ll|m|re|s|t|ve))?",Ge="(?:['’](?:D|LL|M|RE|S|T|VE))?",qe="(?:"+Ie+"|"+je+")"+"?",Je="[\\ufe0e\\ufe0f]?",Ke=Je+qe+("(?:\\u200d(?:"+[Ve,De,$e].join("|")+")"+Je+qe+")*"),Ye="(?:"+[Fe,De,$e].join("|")+")"+Ke,Ze="(?:"+[Ve+Ie+"?",Ie,De,$e,Ae].join("|")+")",Xe=RegExp(Oe,"g"),Qe=RegExp(Ie,"g"),et=RegExp(je+"(?="+je+")|"+Ze+Ke,"g"),tt=RegExp([Ue+"?"+Me+"+"+ze+"(?="+[Pe,Ue,"$"].join("|")+")",He+"+"+Ge+"(?="+[Pe,Ue+We,"$"].join("|")+")",Ue+"?"+We+"+"+ze,Ue+"+"+Ge,"\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",Re,Ye].join("|"),"g"),nt=RegExp("[\\u200d\\ud800-\\udfff"+Se+Ne+"]"),rt=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,ot=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],it=-1,lt={};lt[M]=lt[B]=lt[j]=lt[V]=lt[D]=lt[$]=lt[U]=lt[W]=lt[H]=!0,lt[y]=lt[_]=lt[R]=lt[b]=lt[F]=lt[w]=lt[x]=lt[k]=lt[E]=lt[C]=lt[T]=lt[L]=lt[O]=lt[A]=lt[I]=!1;var at={};at[y]=at[_]=at[R]=at[F]=at[b]=at[w]=at[M]=at[B]=at[j]=at[V]=at[D]=at[E]=at[C]=at[T]=at[L]=at[O]=at[A]=at[P]=at[$]=at[U]=at[W]=at[H]=!0,at[x]=at[k]=at[I]=!1;var st={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},ct=parseFloat,ut=parseInt,ft="object"==typeof n.g&&n.g&&n.g.Object===Object&&n.g,pt="object"==typeof self&&self&&self.Object===Object&&self,dt=ft||pt||Function("return this")(),ht=t&&!t.nodeType&&t,mt=ht&&e&&!e.nodeType&&e,vt=mt&&mt.exports===ht,gt=vt&&ft.process,yt=function(){try{var e=mt&&mt.require&&mt.require("util").types;return e||gt&>.binding&>.binding("util")}catch(e){}}(),_t=yt&&yt.isArrayBuffer,bt=yt&&yt.isDate,wt=yt&&yt.isMap,xt=yt&&yt.isRegExp,kt=yt&&yt.isSet,St=yt&&yt.isTypedArray;function Et(e,t,n){switch(n.length){case 0:return e.call(t);case 1:return e.call(t,n[0]);case 2:return e.call(t,n[0],n[1]);case 3:return e.call(t,n[0],n[1],n[2])}return e.apply(t,n)}function Ct(e,t,n,r){for(var o=-1,i=null==e?0:e.length;++o-1}function Pt(e,t,n){for(var r=-1,o=null==e?0:e.length;++r-1;);return n}function tn(e,t){for(var n=e.length;n--&&$t(t,e[n],0)>-1;);return n}function nn(e,t){for(var n=e.length,r=0;n--;)e[n]===t&&++r;return r}var rn=Gt({À:"A",Á:"A",Â:"A",Ã:"A",Ä:"A",Å:"A",à:"a",á:"a",â:"a",ã:"a",ä:"a",å:"a",Ç:"C",ç:"c",Ð:"D",ð:"d",È:"E",É:"E",Ê:"E",Ë:"E",è:"e",é:"e",ê:"e",ë:"e",Ì:"I",Í:"I",Î:"I",Ï:"I",ì:"i",í:"i",î:"i",ï:"i",Ñ:"N",ñ:"n",Ò:"O",Ó:"O",Ô:"O",Õ:"O",Ö:"O",Ø:"O",ò:"o",ó:"o",ô:"o",õ:"o",ö:"o",ø:"o",Ù:"U",Ú:"U",Û:"U",Ü:"U",ù:"u",ú:"u",û:"u",ü:"u",Ý:"Y",ý:"y",ÿ:"y",Æ:"Ae",æ:"ae",Þ:"Th",þ:"th",ß:"ss",Ā:"A",Ă:"A",Ą:"A",ā:"a",ă:"a",ą:"a",Ć:"C",Ĉ:"C",Ċ:"C",Č:"C",ć:"c",ĉ:"c",ċ:"c",č:"c",Ď:"D",Đ:"D",ď:"d",đ:"d",Ē:"E",Ĕ:"E",Ė:"E",Ę:"E",Ě:"E",ē:"e",ĕ:"e",ė:"e",ę:"e",ě:"e",Ĝ:"G",Ğ:"G",Ġ:"G",Ģ:"G",ĝ:"g",ğ:"g",ġ:"g",ģ:"g",Ĥ:"H",Ħ:"H",ĥ:"h",ħ:"h",Ĩ:"I",Ī:"I",Ĭ:"I",Į:"I",İ:"I",ĩ:"i",ī:"i",ĭ:"i",į:"i",ı:"i",Ĵ:"J",ĵ:"j",Ķ:"K",ķ:"k",ĸ:"k",Ĺ:"L",Ļ:"L",Ľ:"L",Ŀ:"L",Ł:"L",ĺ:"l",ļ:"l",ľ:"l",ŀ:"l",ł:"l",Ń:"N",Ņ:"N",Ň:"N",Ŋ:"N",ń:"n",ņ:"n",ň:"n",ŋ:"n",Ō:"O",Ŏ:"O",Ő:"O",ō:"o",ŏ:"o",ő:"o",Ŕ:"R",Ŗ:"R",Ř:"R",ŕ:"r",ŗ:"r",ř:"r",Ś:"S",Ŝ:"S",Ş:"S",Š:"S",ś:"s",ŝ:"s",ş:"s",š:"s",Ţ:"T",Ť:"T",Ŧ:"T",ţ:"t",ť:"t",ŧ:"t",Ũ:"U",Ū:"U",Ŭ:"U",Ů:"U",Ű:"U",Ų:"U",ũ:"u",ū:"u",ŭ:"u",ů:"u",ű:"u",ų:"u",Ŵ:"W",ŵ:"w",Ŷ:"Y",ŷ:"y",Ÿ:"Y",Ź:"Z",Ż:"Z",Ž:"Z",ź:"z",ż:"z",ž:"z",IJ:"IJ",ij:"ij",Œ:"Oe",œ:"oe",ʼn:"'n",ſ:"s"}),on=Gt({"&":"&","<":"<",">":">",'"':""","'":"'"});function ln(e){return"\\"+st[e]}function an(e){return nt.test(e)}function sn(e){var t=-1,n=Array(e.size);return e.forEach((function(e,r){n[++t]=[r,e]})),n}function cn(e,t){return function(n){return e(t(n))}}function un(e,t){for(var n=-1,r=e.length,o=0,i=[];++n",""":'"',"'":"'"});var gn=function e(t){var n,r=(t=null==t?dt:gn.defaults(dt.Object(),t,gn.pick(dt,ot))).Array,ae=t.Date,Se=t.Error,Ee=t.Function,Ce=t.Math,Te=t.Object,Ne=t.RegExp,Le=t.String,Oe=t.TypeError,Ae=r.prototype,Pe=Ee.prototype,Ie=Te.prototype,Re=t["__core-js_shared__"],Fe=Pe.toString,Me=Ie.hasOwnProperty,Be=0,je=(n=/[^.]+$/.exec(Re&&Re.keys&&Re.keys.IE_PROTO||""))?"Symbol(src)_1."+n:"",Ve=Ie.toString,De=Fe.call(Te),$e=dt._,Ue=Ne("^"+Fe.call(Me).replace(oe,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),We=vt?t.Buffer:o,He=t.Symbol,ze=t.Uint8Array,Ge=We?We.allocUnsafe:o,qe=cn(Te.getPrototypeOf,Te),Je=Te.create,Ke=Ie.propertyIsEnumerable,Ye=Ae.splice,Ze=He?He.isConcatSpreadable:o,et=He?He.iterator:o,nt=He?He.toStringTag:o,st=function(){try{var e=hi(Te,"defineProperty");return e({},"",{}),e}catch(e){}}(),ft=t.clearTimeout!==dt.clearTimeout&&t.clearTimeout,pt=ae&&ae.now!==dt.Date.now&&ae.now,ht=t.setTimeout!==dt.setTimeout&&t.setTimeout,mt=Ce.ceil,gt=Ce.floor,yt=Te.getOwnPropertySymbols,jt=We?We.isBuffer:o,Gt=t.isFinite,yn=Ae.join,_n=cn(Te.keys,Te),bn=Ce.max,wn=Ce.min,xn=ae.now,kn=t.parseInt,Sn=Ce.random,En=Ae.reverse,Cn=hi(t,"DataView"),Tn=hi(t,"Map"),Nn=hi(t,"Promise"),Ln=hi(t,"Set"),On=hi(t,"WeakMap"),An=hi(Te,"create"),Pn=On&&new On,In={},Rn=$i(Cn),Fn=$i(Tn),Mn=$i(Nn),Bn=$i(Ln),jn=$i(On),Vn=He?He.prototype:o,Dn=Vn?Vn.valueOf:o,$n=Vn?Vn.toString:o;function Un(e){if(oa(e)&&!ql(e)&&!(e instanceof Gn)){if(e instanceof zn)return e;if(Me.call(e,"__wrapped__"))return Ui(e)}return new zn(e)}var Wn=function(){function e(){}return function(t){if(!ra(t))return{};if(Je)return Je(t);e.prototype=t;var n=new e;return e.prototype=o,n}}();function Hn(){}function zn(e,t){this.__wrapped__=e,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=o}function Gn(e){this.__wrapped__=e,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=v,this.__views__=[]}function qn(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t=t?e:t)),e}function ur(e,t,n,r,i,l){var a,s=1&t,c=2&t,u=4&t;if(n&&(a=i?n(e,r,i,l):n(e)),a!==o)return a;if(!ra(e))return e;var f=ql(e);if(f){if(a=function(e){var t=e.length,n=new e.constructor(t);t&&"string"==typeof e[0]&&Me.call(e,"index")&&(n.index=e.index,n.input=e.input);return n}(e),!s)return Po(e,a)}else{var p=gi(e),d=p==k||p==S;if(Zl(e))return Co(e,s);if(p==T||p==y||d&&!i){if(a=c||d?{}:_i(e),!s)return c?function(e,t){return Io(e,vi(e),t)}(e,function(e,t){return e&&Io(t,Fa(t),e)}(a,e)):function(e,t){return Io(e,mi(e),t)}(e,lr(a,e))}else{if(!at[p])return i?e:{};a=function(e,t,n){var r=e.constructor;switch(t){case R:return To(e);case b:case w:return new r(+e);case F:return function(e,t){var n=t?To(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.byteLength)}(e,n);case M:case B:case j:case V:case D:case $:case U:case W:case H:return No(e,n);case E:return new r;case C:case A:return new r(e);case L:return function(e){var t=new e.constructor(e.source,me.exec(e));return t.lastIndex=e.lastIndex,t}(e);case O:return new r;case P:return o=e,Dn?Te(Dn.call(o)):{}}var o}(e,p,s)}}l||(l=new Zn);var h=l.get(e);if(h)return h;l.set(e,a),ca(e)?e.forEach((function(r){a.add(ur(r,t,n,r,e,l))})):ia(e)&&e.forEach((function(r,o){a.set(o,ur(r,t,n,o,e,l))}));var m=f?o:(u?c?ai:li:c?Fa:Ra)(e);return Tt(m||e,(function(r,o){m&&(r=e[o=r]),rr(a,o,ur(r,t,n,o,e,l))})),a}function fr(e,t,n){var r=n.length;if(null==e)return!r;for(e=Te(e);r--;){var i=n[r],l=t[i],a=e[i];if(a===o&&!(i in e)||!l(a))return!1}return!0}function pr(e,t,n){if("function"!=typeof e)throw new Oe(i);return Ri((function(){e.apply(o,n)}),t)}function dr(e,t,n,r){var o=-1,i=At,l=!0,a=e.length,s=[],c=t.length;if(!a)return s;n&&(t=It(t,Zt(n))),r?(i=Pt,l=!1):t.length>=200&&(i=Qt,l=!1,t=new Yn(t));e:for(;++o-1},Jn.prototype.set=function(e,t){var n=this.__data__,r=or(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this},Kn.prototype.clear=function(){this.size=0,this.__data__={hash:new qn,map:new(Tn||Jn),string:new qn}},Kn.prototype.delete=function(e){var t=pi(this,e).delete(e);return this.size-=t?1:0,t},Kn.prototype.get=function(e){return pi(this,e).get(e)},Kn.prototype.has=function(e){return pi(this,e).has(e)},Kn.prototype.set=function(e,t){var n=pi(this,e),r=n.size;return n.set(e,t),this.size+=n.size==r?0:1,this},Yn.prototype.add=Yn.prototype.push=function(e){return this.__data__.set(e,l),this},Yn.prototype.has=function(e){return this.__data__.has(e)},Zn.prototype.clear=function(){this.__data__=new Jn,this.size=0},Zn.prototype.delete=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n},Zn.prototype.get=function(e){return this.__data__.get(e)},Zn.prototype.has=function(e){return this.__data__.has(e)},Zn.prototype.set=function(e,t){var n=this.__data__;if(n instanceof Jn){var r=n.__data__;if(!Tn||r.length<199)return r.push([e,t]),this.size=++n.size,this;n=this.__data__=new Kn(r)}return n.set(e,t),this.size=n.size,this};var hr=Mo(xr),mr=Mo(kr,!0);function vr(e,t){var n=!0;return hr(e,(function(e,r,o){return n=!!t(e,r,o)})),n}function gr(e,t,n){for(var r=-1,i=e.length;++r0&&n(a)?t>1?_r(a,t-1,n,r,o):Rt(o,a):r||(o[o.length]=a)}return o}var br=Bo(),wr=Bo(!0);function xr(e,t){return e&&br(e,t,Ra)}function kr(e,t){return e&&wr(e,t,Ra)}function Sr(e,t){return Ot(t,(function(t){return ea(e[t])}))}function Er(e,t){for(var n=0,r=(t=xo(t,e)).length;null!=e&&nt}function Lr(e,t){return null!=e&&Me.call(e,t)}function Or(e,t){return null!=e&&t in Te(e)}function Ar(e,t,n){for(var i=n?Pt:At,l=e[0].length,a=e.length,s=a,c=r(a),u=1/0,f=[];s--;){var p=e[s];s&&t&&(p=It(p,Zt(t))),u=wn(p.length,u),c[s]=!n&&(t||l>=120&&p.length>=120)?new Yn(s&&p):o}p=e[0];var d=-1,h=c[0];e:for(;++d=a?s:s*("desc"==n[r]?-1:1)}return e.index-t.index}(e,t,n)}))}function qr(e,t,n){for(var r=-1,o=t.length,i={};++r-1;)a!==e&&Ye.call(a,s,1),Ye.call(e,s,1);return e}function Kr(e,t){for(var n=e?t.length:0,r=n-1;n--;){var o=t[n];if(n==r||o!==i){var i=o;wi(o)?Ye.call(e,o,1):ho(e,o)}}return e}function Yr(e,t){return e+gt(Sn()*(t-e+1))}function Zr(e,t){var n="";if(!e||t<1||t>h)return n;do{t%2&&(n+=e),(t=gt(t/2))&&(e+=e)}while(t);return n}function Xr(e,t){return Fi(Li(e,t,ls),e+"")}function Qr(e){return Qn(Wa(e))}function eo(e,t){var n=Wa(e);return ji(n,cr(t,0,n.length))}function to(e,t,n,r){if(!ra(e))return e;for(var i=-1,l=(t=xo(t,e)).length,a=l-1,s=e;null!=s&&++ii?0:i+t),(n=n>i?i:n)<0&&(n+=i),i=t>n?0:n-t>>>0,t>>>=0;for(var l=r(i);++o>>1,l=e[i];null!==l&&!fa(l)&&(n?l<=t:l=200){var c=t?null:Xo(e);if(c)return fn(c);l=!1,o=Qt,s=new Yn}else s=t?[]:a;e:for(;++r=r?e:io(e,t,n)}var Eo=ft||function(e){return dt.clearTimeout(e)};function Co(e,t){if(t)return e.slice();var n=e.length,r=Ge?Ge(n):new e.constructor(n);return e.copy(r),r}function To(e){var t=new e.constructor(e.byteLength);return new ze(t).set(new ze(e)),t}function No(e,t){var n=t?To(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.length)}function Lo(e,t){if(e!==t){var n=e!==o,r=null===e,i=e==e,l=fa(e),a=t!==o,s=null===t,c=t==t,u=fa(t);if(!s&&!u&&!l&&e>t||l&&a&&c&&!s&&!u||r&&a&&c||!n&&c||!i)return 1;if(!r&&!l&&!u&&e1?n[i-1]:o,a=i>2?n[2]:o;for(l=e.length>3&&"function"==typeof l?(i--,l):o,a&&xi(n[0],n[1],a)&&(l=i<3?o:l,i=1),t=Te(t);++r-1?i[l?t[a]:a]:o}}function Uo(e){return ii((function(t){var n=t.length,r=n,l=zn.prototype.thru;for(e&&t.reverse();r--;){var a=t[r];if("function"!=typeof a)throw new Oe(i);if(l&&!s&&"wrapper"==ci(a))var s=new zn([],!0)}for(r=s?r:n;++r1&&_.reverse(),d&&us))return!1;var u=l.get(e),f=l.get(t);if(u&&f)return u==t&&f==e;var p=-1,d=!0,h=2&n?new Yn:o;for(l.set(e,t),l.set(t,e);++p-1&&e%1==0&&e1?"& ":"")+t[r],t=t.join(n>2?", ":" "),e.replace(se,"{\n/* [wrapped with "+t+"] */\n")}(r,function(e,t){return Tt(g,(function(n){var r="_."+n[0];t&n[1]&&!At(e,r)&&e.push(r)})),e.sort()}(function(e){var t=e.match(ce);return t?t[1].split(ue):[]}(r),n)))}function Bi(e){var t=0,n=0;return function(){var r=xn(),i=16-(r-n);if(n=r,i>0){if(++t>=800)return arguments[0]}else t=0;return e.apply(o,arguments)}}function ji(e,t){var n=-1,r=e.length,i=r-1;for(t=t===o?r:t;++n1?e[t-1]:o;return n="function"==typeof n?(e.pop(),n):o,sl(e,n)}));function ml(e){var t=Un(e);return t.__chain__=!0,t}function vl(e,t){return t(e)}var gl=ii((function(e){var t=e.length,n=t?e[0]:0,r=this.__wrapped__,i=function(t){return sr(t,e)};return!(t>1||this.__actions__.length)&&r instanceof Gn&&wi(n)?((r=r.slice(n,+n+(t?1:0))).__actions__.push({func:vl,args:[i],thisArg:o}),new zn(r,this.__chain__).thru((function(e){return t&&!e.length&&e.push(o),e}))):this.thru(i)}));var yl=Ro((function(e,t,n){Me.call(e,n)?++e[n]:ar(e,n,1)}));var _l=$o(Gi),bl=$o(qi);function wl(e,t){return(ql(e)?Tt:hr)(e,fi(t,3))}function xl(e,t){return(ql(e)?Nt:mr)(e,fi(t,3))}var kl=Ro((function(e,t,n){Me.call(e,n)?e[n].push(t):ar(e,n,[t])}));var Sl=Xr((function(e,t,n){var o=-1,i="function"==typeof t,l=Kl(e)?r(e.length):[];return hr(e,(function(e){l[++o]=i?Et(t,e,n):Pr(e,t,n)})),l})),El=Ro((function(e,t,n){ar(e,n,t)}));function Cl(e,t){return(ql(e)?It:$r)(e,fi(t,3))}var Tl=Ro((function(e,t,n){e[n?0:1].push(t)}),(function(){return[[],[]]}));var Nl=Xr((function(e,t){if(null==e)return[];var n=t.length;return n>1&&xi(e,t[0],t[1])?t=[]:n>2&&xi(t[0],t[1],t[2])&&(t=[t[0]]),Gr(e,_r(t,1),[])})),Ll=pt||function(){return dt.Date.now()};function Ol(e,t,n){return t=n?o:t,t=e&&null==t?e.length:t,ei(e,f,o,o,o,o,t)}function Al(e,t){var n;if("function"!=typeof t)throw new Oe(i);return e=ga(e),function(){return--e>0&&(n=t.apply(this,arguments)),e<=1&&(t=o),n}}var Pl=Xr((function(e,t,n){var r=1;if(n.length){var o=un(n,ui(Pl));r|=c}return ei(e,r,t,n,o)})),Il=Xr((function(e,t,n){var r=3;if(n.length){var o=un(n,ui(Il));r|=c}return ei(t,r,e,n,o)}));function Rl(e,t,n){var r,l,a,s,c,u,f=0,p=!1,d=!1,h=!0;if("function"!=typeof e)throw new Oe(i);function m(t){var n=r,i=l;return r=l=o,f=t,s=e.apply(i,n)}function v(e){return f=e,c=Ri(y,t),p?m(e):s}function g(e){var n=e-u;return u===o||n>=t||n<0||d&&e-f>=a}function y(){var e=Ll();if(g(e))return _(e);c=Ri(y,function(e){var n=t-(e-u);return d?wn(n,a-(e-f)):n}(e))}function _(e){return c=o,h&&r?m(e):(r=l=o,s)}function b(){var e=Ll(),n=g(e);if(r=arguments,l=this,u=e,n){if(c===o)return v(u);if(d)return Eo(c),c=Ri(y,t),m(u)}return c===o&&(c=Ri(y,t)),s}return t=_a(t)||0,ra(n)&&(p=!!n.leading,a=(d="maxWait"in n)?bn(_a(n.maxWait)||0,t):a,h="trailing"in n?!!n.trailing:h),b.cancel=function(){c!==o&&Eo(c),f=0,r=u=l=c=o},b.flush=function(){return c===o?s:_(Ll())},b}var Fl=Xr((function(e,t){return pr(e,1,t)})),Ml=Xr((function(e,t,n){return pr(e,_a(t)||0,n)}));function Bl(e,t){if("function"!=typeof e||null!=t&&"function"!=typeof t)throw new Oe(i);var n=function(){var r=arguments,o=t?t.apply(this,r):r[0],i=n.cache;if(i.has(o))return i.get(o);var l=e.apply(this,r);return n.cache=i.set(o,l)||i,l};return n.cache=new(Bl.Cache||Kn),n}function jl(e){if("function"!=typeof e)throw new Oe(i);return function(){var t=arguments;switch(t.length){case 0:return!e.call(this);case 1:return!e.call(this,t[0]);case 2:return!e.call(this,t[0],t[1]);case 3:return!e.call(this,t[0],t[1],t[2])}return!e.apply(this,t)}}Bl.Cache=Kn;var Vl=ko((function(e,t){var n=(t=1==t.length&&ql(t[0])?It(t[0],Zt(fi())):It(_r(t,1),Zt(fi()))).length;return Xr((function(r){for(var o=-1,i=wn(r.length,n);++o=t})),Gl=Ir(function(){return arguments}())?Ir:function(e){return oa(e)&&Me.call(e,"callee")&&!Ke.call(e,"callee")},ql=r.isArray,Jl=_t?Zt(_t):function(e){return oa(e)&&Tr(e)==R};function Kl(e){return null!=e&&na(e.length)&&!ea(e)}function Yl(e){return oa(e)&&Kl(e)}var Zl=jt||_s,Xl=bt?Zt(bt):function(e){return oa(e)&&Tr(e)==w};function Ql(e){if(!oa(e))return!1;var t=Tr(e);return t==x||"[object DOMException]"==t||"string"==typeof e.message&&"string"==typeof e.name&&!aa(e)}function ea(e){if(!ra(e))return!1;var t=Tr(e);return t==k||t==S||"[object AsyncFunction]"==t||"[object Proxy]"==t}function ta(e){return"number"==typeof e&&e==ga(e)}function na(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=h}function ra(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}function oa(e){return null!=e&&"object"==typeof e}var ia=wt?Zt(wt):function(e){return oa(e)&&gi(e)==E};function la(e){return"number"==typeof e||oa(e)&&Tr(e)==C}function aa(e){if(!oa(e)||Tr(e)!=T)return!1;var t=qe(e);if(null===t)return!0;var n=Me.call(t,"constructor")&&t.constructor;return"function"==typeof n&&n instanceof n&&Fe.call(n)==De}var sa=xt?Zt(xt):function(e){return oa(e)&&Tr(e)==L};var ca=kt?Zt(kt):function(e){return oa(e)&&gi(e)==O};function ua(e){return"string"==typeof e||!ql(e)&&oa(e)&&Tr(e)==A}function fa(e){return"symbol"==typeof e||oa(e)&&Tr(e)==P}var pa=St?Zt(St):function(e){return oa(e)&&na(e.length)&&!!lt[Tr(e)]};var da=Ko(Dr),ha=Ko((function(e,t){return e<=t}));function ma(e){if(!e)return[];if(Kl(e))return ua(e)?hn(e):Po(e);if(et&&e[et])return function(e){for(var t,n=[];!(t=e.next()).done;)n.push(t.value);return n}(e[et]());var t=gi(e);return(t==E?sn:t==O?fn:Wa)(e)}function va(e){return e?(e=_a(e))===d||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}function ga(e){var t=va(e),n=t%1;return t==t?n?t-n:t:0}function ya(e){return e?cr(ga(e),0,v):0}function _a(e){if("number"==typeof e)return e;if(fa(e))return m;if(ra(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=ra(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=Yt(e);var n=ge.test(e);return n||_e.test(e)?ut(e.slice(2),n?2:8):ve.test(e)?m:+e}function ba(e){return Io(e,Fa(e))}function wa(e){return null==e?"":fo(e)}var xa=Fo((function(e,t){if(Ci(t)||Kl(t))Io(t,Ra(t),e);else for(var n in t)Me.call(t,n)&&rr(e,n,t[n])})),ka=Fo((function(e,t){Io(t,Fa(t),e)})),Sa=Fo((function(e,t,n,r){Io(t,Fa(t),e,r)})),Ea=Fo((function(e,t,n,r){Io(t,Ra(t),e,r)})),Ca=ii(sr);var Ta=Xr((function(e,t){e=Te(e);var n=-1,r=t.length,i=r>2?t[2]:o;for(i&&xi(t[0],t[1],i)&&(r=1);++n1),t})),Io(e,ai(e),n),r&&(n=ur(n,7,ri));for(var o=t.length;o--;)ho(n,t[o]);return n}));var Va=ii((function(e,t){return null==e?{}:function(e,t){return qr(e,t,(function(t,n){return Oa(e,n)}))}(e,t)}));function Da(e,t){if(null==e)return{};var n=It(ai(e),(function(e){return[e]}));return t=fi(t),qr(e,n,(function(e,n){return t(e,n[0])}))}var $a=Qo(Ra),Ua=Qo(Fa);function Wa(e){return null==e?[]:Xt(e,Ra(e))}var Ha=Vo((function(e,t,n){return t=t.toLowerCase(),e+(n?za(t):t)}));function za(e){return Qa(wa(e).toLowerCase())}function Ga(e){return(e=wa(e))&&e.replace(we,rn).replace(Qe,"")}var qa=Vo((function(e,t,n){return e+(n?"-":"")+t.toLowerCase()})),Ja=Vo((function(e,t,n){return e+(n?" ":"")+t.toLowerCase()})),Ka=jo("toLowerCase");var Ya=Vo((function(e,t,n){return e+(n?"_":"")+t.toLowerCase()}));var Za=Vo((function(e,t,n){return e+(n?" ":"")+Qa(t)}));var Xa=Vo((function(e,t,n){return e+(n?" ":"")+t.toUpperCase()})),Qa=jo("toUpperCase");function es(e,t,n){return e=wa(e),(t=n?o:t)===o?function(e){return rt.test(e)}(e)?function(e){return e.match(tt)||[]}(e):function(e){return e.match(fe)||[]}(e):e.match(t)||[]}var ts=Xr((function(e,t){try{return Et(e,o,t)}catch(e){return Ql(e)?e:new Se(e)}})),ns=ii((function(e,t){return Tt(t,(function(t){t=Di(t),ar(e,t,Pl(e[t],e))})),e}));function rs(e){return function(){return e}}var os=Uo(),is=Uo(!0);function ls(e){return e}function as(e){return Br("function"==typeof e?e:ur(e,1))}var ss=Xr((function(e,t){return function(n){return Pr(n,e,t)}})),cs=Xr((function(e,t){return function(n){return Pr(e,n,t)}}));function us(e,t,n){var r=Ra(t),o=Sr(t,r);null!=n||ra(t)&&(o.length||!r.length)||(n=t,t=e,e=this,o=Sr(t,Ra(t)));var i=!(ra(n)&&"chain"in n&&!n.chain),l=ea(e);return Tt(o,(function(n){var r=t[n];e[n]=r,l&&(e.prototype[n]=function(){var t=this.__chain__;if(i||t){var n=e(this.__wrapped__),o=n.__actions__=Po(this.__actions__);return o.push({func:r,args:arguments,thisArg:e}),n.__chain__=t,n}return r.apply(e,Rt([this.value()],arguments))})})),e}function fs(){}var ps=Go(It),ds=Go(Lt),hs=Go(Bt);function ms(e){return ki(e)?zt(Di(e)):function(e){return function(t){return Er(t,e)}}(e)}var vs=Jo(),gs=Jo(!0);function ys(){return[]}function _s(){return!1}var bs=zo((function(e,t){return e+t}),0),ws=Zo("ceil"),xs=zo((function(e,t){return e/t}),1),ks=Zo("floor");var Ss,Es=zo((function(e,t){return e*t}),1),Cs=Zo("round"),Ts=zo((function(e,t){return e-t}),0);return Un.after=function(e,t){if("function"!=typeof t)throw new Oe(i);return e=ga(e),function(){if(--e<1)return t.apply(this,arguments)}},Un.ary=Ol,Un.assign=xa,Un.assignIn=ka,Un.assignInWith=Sa,Un.assignWith=Ea,Un.at=Ca,Un.before=Al,Un.bind=Pl,Un.bindAll=ns,Un.bindKey=Il,Un.castArray=function(){if(!arguments.length)return[];var e=arguments[0];return ql(e)?e:[e]},Un.chain=ml,Un.chunk=function(e,t,n){t=(n?xi(e,t,n):t===o)?1:bn(ga(t),0);var i=null==e?0:e.length;if(!i||t<1)return[];for(var l=0,a=0,s=r(mt(i/t));li?0:i+n),(r=r===o||r>i?i:ga(r))<0&&(r+=i),r=n>r?0:ya(r);n>>0)?(e=wa(e))&&("string"==typeof t||null!=t&&!sa(t))&&!(t=fo(t))&&an(e)?So(hn(e),0,n):e.split(t,n):[]},Un.spread=function(e,t){if("function"!=typeof e)throw new Oe(i);return t=null==t?0:bn(ga(t),0),Xr((function(n){var r=n[t],o=So(n,0,t);return r&&Rt(o,r),Et(e,this,o)}))},Un.tail=function(e){var t=null==e?0:e.length;return t?io(e,1,t):[]},Un.take=function(e,t,n){return e&&e.length?io(e,0,(t=n||t===o?1:ga(t))<0?0:t):[]},Un.takeRight=function(e,t,n){var r=null==e?0:e.length;return r?io(e,(t=r-(t=n||t===o?1:ga(t)))<0?0:t,r):[]},Un.takeRightWhile=function(e,t){return e&&e.length?vo(e,fi(t,3),!1,!0):[]},Un.takeWhile=function(e,t){return e&&e.length?vo(e,fi(t,3)):[]},Un.tap=function(e,t){return t(e),e},Un.throttle=function(e,t,n){var r=!0,o=!0;if("function"!=typeof e)throw new Oe(i);return ra(n)&&(r="leading"in n?!!n.leading:r,o="trailing"in n?!!n.trailing:o),Rl(e,t,{leading:r,maxWait:t,trailing:o})},Un.thru=vl,Un.toArray=ma,Un.toPairs=$a,Un.toPairsIn=Ua,Un.toPath=function(e){return ql(e)?It(e,Di):fa(e)?[e]:Po(Vi(wa(e)))},Un.toPlainObject=ba,Un.transform=function(e,t,n){var r=ql(e),o=r||Zl(e)||pa(e);if(t=fi(t,4),null==n){var i=e&&e.constructor;n=o?r?new i:[]:ra(e)&&ea(i)?Wn(qe(e)):{}}return(o?Tt:xr)(e,(function(e,r,o){return t(n,e,r,o)})),n},Un.unary=function(e){return Ol(e,1)},Un.union=ol,Un.unionBy=il,Un.unionWith=ll,Un.uniq=function(e){return e&&e.length?po(e):[]},Un.uniqBy=function(e,t){return e&&e.length?po(e,fi(t,2)):[]},Un.uniqWith=function(e,t){return t="function"==typeof t?t:o,e&&e.length?po(e,o,t):[]},Un.unset=function(e,t){return null==e||ho(e,t)},Un.unzip=al,Un.unzipWith=sl,Un.update=function(e,t,n){return null==e?e:mo(e,t,wo(n))},Un.updateWith=function(e,t,n,r){return r="function"==typeof r?r:o,null==e?e:mo(e,t,wo(n),r)},Un.values=Wa,Un.valuesIn=function(e){return null==e?[]:Xt(e,Fa(e))},Un.without=cl,Un.words=es,Un.wrap=function(e,t){return Dl(wo(t),e)},Un.xor=ul,Un.xorBy=fl,Un.xorWith=pl,Un.zip=dl,Un.zipObject=function(e,t){return _o(e||[],t||[],rr)},Un.zipObjectDeep=function(e,t){return _o(e||[],t||[],to)},Un.zipWith=hl,Un.entries=$a,Un.entriesIn=Ua,Un.extend=ka,Un.extendWith=Sa,us(Un,Un),Un.add=bs,Un.attempt=ts,Un.camelCase=Ha,Un.capitalize=za,Un.ceil=ws,Un.clamp=function(e,t,n){return n===o&&(n=t,t=o),n!==o&&(n=(n=_a(n))==n?n:0),t!==o&&(t=(t=_a(t))==t?t:0),cr(_a(e),t,n)},Un.clone=function(e){return ur(e,4)},Un.cloneDeep=function(e){return ur(e,5)},Un.cloneDeepWith=function(e,t){return ur(e,5,t="function"==typeof t?t:o)},Un.cloneWith=function(e,t){return ur(e,4,t="function"==typeof t?t:o)},Un.conformsTo=function(e,t){return null==t||fr(e,t,Ra(t))},Un.deburr=Ga,Un.defaultTo=function(e,t){return null==e||e!=e?t:e},Un.divide=xs,Un.endsWith=function(e,t,n){e=wa(e),t=fo(t);var r=e.length,i=n=n===o?r:cr(ga(n),0,r);return(n-=t.length)>=0&&e.slice(n,i)==t},Un.eq=Wl,Un.escape=function(e){return(e=wa(e))&&Z.test(e)?e.replace(K,on):e},Un.escapeRegExp=function(e){return(e=wa(e))&&ie.test(e)?e.replace(oe,"\\$&"):e},Un.every=function(e,t,n){var r=ql(e)?Lt:vr;return n&&xi(e,t,n)&&(t=o),r(e,fi(t,3))},Un.find=_l,Un.findIndex=Gi,Un.findKey=function(e,t){return Vt(e,fi(t,3),xr)},Un.findLast=bl,Un.findLastIndex=qi,Un.findLastKey=function(e,t){return Vt(e,fi(t,3),kr)},Un.floor=ks,Un.forEach=wl,Un.forEachRight=xl,Un.forIn=function(e,t){return null==e?e:br(e,fi(t,3),Fa)},Un.forInRight=function(e,t){return null==e?e:wr(e,fi(t,3),Fa)},Un.forOwn=function(e,t){return e&&xr(e,fi(t,3))},Un.forOwnRight=function(e,t){return e&&kr(e,fi(t,3))},Un.get=La,Un.gt=Hl,Un.gte=zl,Un.has=function(e,t){return null!=e&&yi(e,t,Lr)},Un.hasIn=Oa,Un.head=Ki,Un.identity=ls,Un.includes=function(e,t,n,r){e=Kl(e)?e:Wa(e),n=n&&!r?ga(n):0;var o=e.length;return n<0&&(n=bn(o+n,0)),ua(e)?n<=o&&e.indexOf(t,n)>-1:!!o&&$t(e,t,n)>-1},Un.indexOf=function(e,t,n){var r=null==e?0:e.length;if(!r)return-1;var o=null==n?0:ga(n);return o<0&&(o=bn(r+o,0)),$t(e,t,o)},Un.inRange=function(e,t,n){return t=va(t),n===o?(n=t,t=0):n=va(n),function(e,t,n){return e>=wn(t,n)&&e=-9007199254740991&&e<=h},Un.isSet=ca,Un.isString=ua,Un.isSymbol=fa,Un.isTypedArray=pa,Un.isUndefined=function(e){return e===o},Un.isWeakMap=function(e){return oa(e)&&gi(e)==I},Un.isWeakSet=function(e){return oa(e)&&"[object WeakSet]"==Tr(e)},Un.join=function(e,t){return null==e?"":yn.call(e,t)},Un.kebabCase=qa,Un.last=Qi,Un.lastIndexOf=function(e,t,n){var r=null==e?0:e.length;if(!r)return-1;var i=r;return n!==o&&(i=(i=ga(n))<0?bn(r+i,0):wn(i,r-1)),t==t?function(e,t,n){for(var r=n+1;r--;)if(e[r]===t)return r;return r}(e,t,i):Dt(e,Wt,i,!0)},Un.lowerCase=Ja,Un.lowerFirst=Ka,Un.lt=da,Un.lte=ha,Un.max=function(e){return e&&e.length?gr(e,ls,Nr):o},Un.maxBy=function(e,t){return e&&e.length?gr(e,fi(t,2),Nr):o},Un.mean=function(e){return Ht(e,ls)},Un.meanBy=function(e,t){return Ht(e,fi(t,2))},Un.min=function(e){return e&&e.length?gr(e,ls,Dr):o},Un.minBy=function(e,t){return e&&e.length?gr(e,fi(t,2),Dr):o},Un.stubArray=ys,Un.stubFalse=_s,Un.stubObject=function(){return{}},Un.stubString=function(){return""},Un.stubTrue=function(){return!0},Un.multiply=Es,Un.nth=function(e,t){return e&&e.length?zr(e,ga(t)):o},Un.noConflict=function(){return dt._===this&&(dt._=$e),this},Un.noop=fs,Un.now=Ll,Un.pad=function(e,t,n){e=wa(e);var r=(t=ga(t))?dn(e):0;if(!t||r>=t)return e;var o=(t-r)/2;return qo(gt(o),n)+e+qo(mt(o),n)},Un.padEnd=function(e,t,n){e=wa(e);var r=(t=ga(t))?dn(e):0;return t&&rt){var r=e;e=t,t=r}if(n||e%1||t%1){var i=Sn();return wn(e+i*(t-e+ct("1e-"+((i+"").length-1))),t)}return Yr(e,t)},Un.reduce=function(e,t,n){var r=ql(e)?Ft:qt,o=arguments.length<3;return r(e,fi(t,4),n,o,hr)},Un.reduceRight=function(e,t,n){var r=ql(e)?Mt:qt,o=arguments.length<3;return r(e,fi(t,4),n,o,mr)},Un.repeat=function(e,t,n){return t=(n?xi(e,t,n):t===o)?1:ga(t),Zr(wa(e),t)},Un.replace=function(){var e=arguments,t=wa(e[0]);return e.length<3?t:t.replace(e[1],e[2])},Un.result=function(e,t,n){var r=-1,i=(t=xo(t,e)).length;for(i||(i=1,e=o);++rh)return[];var n=v,r=wn(e,v);t=fi(t),e-=v;for(var o=Kt(r,t);++n=l)return e;var s=n-dn(r);if(s<1)return r;var c=a?So(a,0,s).join(""):e.slice(0,s);if(i===o)return c+r;if(a&&(s+=c.length-s),sa(i)){if(e.slice(s).search(i)){var u,f=c;for(i.global||(i=Ne(i.source,wa(me.exec(i))+"g")),i.lastIndex=0;u=i.exec(f);)var p=u.index;c=c.slice(0,p===o?s:p)}}else if(e.indexOf(fo(i),s)!=s){var d=c.lastIndexOf(i);d>-1&&(c=c.slice(0,d))}return c+r},Un.unescape=function(e){return(e=wa(e))&&Y.test(e)?e.replace(J,vn):e},Un.uniqueId=function(e){var t=++Be;return wa(e)+t},Un.upperCase=Xa,Un.upperFirst=Qa,Un.each=wl,Un.eachRight=xl,Un.first=Ki,us(Un,(Ss={},xr(Un,(function(e,t){Me.call(Un.prototype,t)||(Ss[t]=e)})),Ss),{chain:!1}),Un.VERSION="4.17.21",Tt(["bind","bindKey","curry","curryRight","partial","partialRight"],(function(e){Un[e].placeholder=Un})),Tt(["drop","take"],(function(e,t){Gn.prototype[e]=function(n){n=n===o?1:bn(ga(n),0);var r=this.__filtered__&&!t?new Gn(this):this.clone();return r.__filtered__?r.__takeCount__=wn(n,r.__takeCount__):r.__views__.push({size:wn(n,v),type:e+(r.__dir__<0?"Right":"")}),r},Gn.prototype[e+"Right"]=function(t){return this.reverse()[e](t).reverse()}})),Tt(["filter","map","takeWhile"],(function(e,t){var n=t+1,r=1==n||3==n;Gn.prototype[e]=function(e){var t=this.clone();return t.__iteratees__.push({iteratee:fi(e,3),type:n}),t.__filtered__=t.__filtered__||r,t}})),Tt(["head","last"],(function(e,t){var n="take"+(t?"Right":"");Gn.prototype[e]=function(){return this[n](1).value()[0]}})),Tt(["initial","tail"],(function(e,t){var n="drop"+(t?"":"Right");Gn.prototype[e]=function(){return this.__filtered__?new Gn(this):this[n](1)}})),Gn.prototype.compact=function(){return this.filter(ls)},Gn.prototype.find=function(e){return this.filter(e).head()},Gn.prototype.findLast=function(e){return this.reverse().find(e)},Gn.prototype.invokeMap=Xr((function(e,t){return"function"==typeof e?new Gn(this):this.map((function(n){return Pr(n,e,t)}))})),Gn.prototype.reject=function(e){return this.filter(jl(fi(e)))},Gn.prototype.slice=function(e,t){e=ga(e);var n=this;return n.__filtered__&&(e>0||t<0)?new Gn(n):(e<0?n=n.takeRight(-e):e&&(n=n.drop(e)),t!==o&&(n=(t=ga(t))<0?n.dropRight(-t):n.take(t-e)),n)},Gn.prototype.takeRightWhile=function(e){return this.reverse().takeWhile(e).reverse()},Gn.prototype.toArray=function(){return this.take(v)},xr(Gn.prototype,(function(e,t){var n=/^(?:filter|find|map|reject)|While$/.test(t),r=/^(?:head|last)$/.test(t),i=Un[r?"take"+("last"==t?"Right":""):t],l=r||/^find/.test(t);i&&(Un.prototype[t]=function(){var t=this.__wrapped__,a=r?[1]:arguments,s=t instanceof Gn,c=a[0],u=s||ql(t),f=function(e){var t=i.apply(Un,Rt([e],a));return r&&p?t[0]:t};u&&n&&"function"==typeof c&&1!=c.length&&(s=u=!1);var p=this.__chain__,d=!!this.__actions__.length,h=l&&!p,m=s&&!d;if(!l&&u){t=m?t:new Gn(this);var v=e.apply(t,a);return v.__actions__.push({func:vl,args:[f],thisArg:o}),new zn(v,p)}return h&&m?e.apply(this,a):(v=this.thru(f),h?r?v.value()[0]:v.value():v)})})),Tt(["pop","push","shift","sort","splice","unshift"],(function(e){var t=Ae[e],n=/^(?:push|sort|unshift)$/.test(e)?"tap":"thru",r=/^(?:pop|shift)$/.test(e);Un.prototype[e]=function(){var e=arguments;if(r&&!this.__chain__){var o=this.value();return t.apply(ql(o)?o:[],e)}return this[n]((function(n){return t.apply(ql(n)?n:[],e)}))}})),xr(Gn.prototype,(function(e,t){var n=Un[t];if(n){var r=n.name+"";Me.call(In,r)||(In[r]=[]),In[r].push({name:t,func:n})}})),In[Wo(o,2).name]=[{name:"wrapper",func:o}],Gn.prototype.clone=function(){var e=new Gn(this.__wrapped__);return e.__actions__=Po(this.__actions__),e.__dir__=this.__dir__,e.__filtered__=this.__filtered__,e.__iteratees__=Po(this.__iteratees__),e.__takeCount__=this.__takeCount__,e.__views__=Po(this.__views__),e},Gn.prototype.reverse=function(){if(this.__filtered__){var e=new Gn(this);e.__dir__=-1,e.__filtered__=!0}else(e=this.clone()).__dir__*=-1;return e},Gn.prototype.value=function(){var e=this.__wrapped__.value(),t=this.__dir__,n=ql(e),r=t<0,o=n?e.length:0,i=function(e,t,n){var r=-1,o=n.length;for(;++r=this.__values__.length;return{done:e,value:e?o:this.__values__[this.__index__++]}},Un.prototype.plant=function(e){for(var t,n=this;n instanceof Hn;){var r=Ui(n);r.__index__=0,r.__values__=o,t?i.__wrapped__=r:t=r;var i=r;n=n.__wrapped__}return i.__wrapped__=e,t},Un.prototype.reverse=function(){var e=this.__wrapped__;if(e instanceof Gn){var t=e;return this.__actions__.length&&(t=new Gn(this)),(t=t.reverse()).__actions__.push({func:vl,args:[rl],thisArg:o}),new zn(t,this.__chain__)}return this.thru(rl)},Un.prototype.toJSON=Un.prototype.valueOf=Un.prototype.value=function(){return go(this.__wrapped__,this.__actions__)},Un.prototype.first=Un.prototype.head,et&&(Un.prototype[et]=function(){return this}),Un}();dt._=gn,(r=function(){return gn}.call(t,n,t,e))===o||(e.exports=r)}.call(this)},423:()=>{},155:e=>{var t,n,r=e.exports={};function o(){throw new Error("setTimeout has not been defined")}function i(){throw new Error("clearTimeout has not been defined")}function l(e){if(t===setTimeout)return setTimeout(e,0);if((t===o||!t)&&setTimeout)return t=setTimeout,setTimeout(e,0);try{return t(e,0)}catch(n){try{return t.call(null,e,0)}catch(n){return t.call(this,e,0)}}}!function(){try{t="function"==typeof setTimeout?setTimeout:o}catch(e){t=o}try{n="function"==typeof clearTimeout?clearTimeout:i}catch(e){n=i}}();var a,s=[],c=!1,u=-1;function f(){c&&a&&(c=!1,a.length?s=a.concat(s):u=-1,s.length&&p())}function p(){if(!c){var e=l(f);c=!0;for(var t=s.length;t;){for(a=s,s=[];++u1)for(var n=1;n{"use strict";var r,o=function(){return void 0===r&&(r=Boolean(window&&document&&document.all&&!window.atob)),r},i=function(){var e={};return function(t){if(void 0===e[t]){var n=document.querySelector(t);if(window.HTMLIFrameElement&&n instanceof window.HTMLIFrameElement)try{n=n.contentDocument.head}catch(e){n=null}e[t]=n}return e[t]}}(),l=[];function a(e){for(var t=-1,n=0;n{"use strict";n.r(t),n.d(t,{BaseTransition:()=>sr,Comment:()=>Zo,EffectScope:()=>se,Fragment:()=>Ko,KeepAlive:()=>br,ReactiveEffect:()=>xe,Static:()=>Xo,Suspense:()=>Wn,Teleport:()=>qo,Text:()=>Yo,Transition:()=>Vl,TransitionGroup:()=>ra,VueElement:()=>Pl,callWithAsyncErrorHandling:()=>tn,callWithErrorHandling:()=>en,camelize:()=>Z,capitalize:()=>ee,cloneVNode:()=>_i,compatUtils:()=>hl,compile:()=>Tf,computed:()=>Ji,createApp:()=>Fa,createBlock:()=>si,createCommentVNode:()=>xi,createElementBlock:()=>ai,createElementVNode:()=>mi,createHydrationRenderer:()=>Vo,createPropsRestProxy:()=>rl,createRenderer:()=>jo,createSSRApp:()=>Ma,createSlots:()=>Yr,createStaticVNode:()=>wi,createTextVNode:()=>bi,createVNode:()=>vi,customRef:()=>qt,defineAsyncComponent:()=>gr,defineComponent:()=>mr,defineCustomElement:()=>Ll,defineEmits:()=>Yi,defineExpose:()=>Zi,defineProps:()=>Ki,defineSSRCustomElement:()=>Ol,devtools:()=>xn,effect:()=>Se,effectScope:()=>ce,getCurrentInstance:()=>Pi,getCurrentScope:()=>fe,getTransitionRawChildren:()=>hr,guardReactiveProps:()=>yi,h:()=>il,handleError:()=>nn,hydrate:()=>Ra,initCustomFormatter:()=>sl,initDirectivesForSSR:()=>Va,inject:()=>Yn,isMemoSame:()=>ul,isProxy:()=>Ot,isReactive:()=>Tt,isReadonly:()=>Nt,isRef:()=>Bt,isRuntimeOnly:()=>Ui,isShallow:()=>Lt,isVNode:()=>ci,markRaw:()=>Pt,mergeDefaults:()=>nl,mergeProps:()=>Ci,nextTick:()=>dn,normalizeClass:()=>f,normalizeProps:()=>p,normalizeStyle:()=>l,onActivated:()=>xr,onBeforeMount:()=>Or,onBeforeUnmount:()=>Rr,onBeforeUpdate:()=>Pr,onDeactivated:()=>kr,onErrorCaptured:()=>Vr,onMounted:()=>Ar,onRenderTracked:()=>jr,onRenderTriggered:()=>Br,onScopeDispose:()=>pe,onServerPrefetch:()=>Mr,onUnmounted:()=>Fr,onUpdated:()=>Ir,openBlock:()=>ti,popScopeId:()=>In,provide:()=>Kn,proxyRefs:()=>zt,pushScopeId:()=>Pn,queuePostFlushCb:()=>vn,reactive:()=>xt,readonly:()=>St,ref:()=>jt,registerRuntimeCompiler:()=>$i,render:()=>Ia,renderList:()=>Kr,renderSlot:()=>Zr,resolveComponent:()=>Wr,resolveDirective:()=>Gr,resolveDynamicComponent:()=>zr,resolveFilter:()=>dl,resolveTransitionHooks:()=>ur,setBlockTracking:()=>ii,setDevtoolsHook:()=>En,setTransitionHooks:()=>dr,shallowReactive:()=>kt,shallowReadonly:()=>Et,shallowRef:()=>Vt,ssrContextKey:()=>ll,ssrUtils:()=>pl,stop:()=>Ee,toDisplayString:()=>w,toHandlerKey:()=>te,toHandlers:()=>Qr,toRaw:()=>At,toRef:()=>Yt,toRefs:()=>Jt,transformVNodeArgs:()=>fi,triggerRef:()=>Ut,unref:()=>Wt,useAttrs:()=>el,useCssModule:()=>Il,useCssVars:()=>Rl,useSSRContext:()=>al,useSlots:()=>Qi,useTransitionState:()=>lr,vModelCheckbox:()=>fa,vModelDynamic:()=>ya,vModelRadio:()=>da,vModelSelect:()=>ha,vModelText:()=>ua,vShow:()=>Ca,version:()=>fl,warn:()=>Qt,watch:()=>tr,watchEffect:()=>Zn,watchPostEffect:()=>Xn,watchSyncEffect:()=>Qn,withAsyncContext:()=>ol,withCtx:()=>Fn,withDefaults:()=>Xi,withDirectives:()=>Dr,withKeys:()=>Ea,withMemo:()=>cl,withModifiers:()=>ka,withScopeId:()=>Rn});var r={};function o(e,t){const n=Object.create(null),r=e.split(",");for(let e=0;e!!n[e.toLowerCase()]:e=>!!n[e]}n.r(r),n.d(r,{BaseTransition:()=>sr,Comment:()=>Zo,EffectScope:()=>se,Fragment:()=>Ko,KeepAlive:()=>br,ReactiveEffect:()=>xe,Static:()=>Xo,Suspense:()=>Wn,Teleport:()=>qo,Text:()=>Yo,Transition:()=>Vl,TransitionGroup:()=>ra,VueElement:()=>Pl,callWithAsyncErrorHandling:()=>tn,callWithErrorHandling:()=>en,camelize:()=>Z,capitalize:()=>ee,cloneVNode:()=>_i,compatUtils:()=>hl,computed:()=>Ji,createApp:()=>Fa,createBlock:()=>si,createCommentVNode:()=>xi,createElementBlock:()=>ai,createElementVNode:()=>mi,createHydrationRenderer:()=>Vo,createPropsRestProxy:()=>rl,createRenderer:()=>jo,createSSRApp:()=>Ma,createSlots:()=>Yr,createStaticVNode:()=>wi,createTextVNode:()=>bi,createVNode:()=>vi,customRef:()=>qt,defineAsyncComponent:()=>gr,defineComponent:()=>mr,defineCustomElement:()=>Ll,defineEmits:()=>Yi,defineExpose:()=>Zi,defineProps:()=>Ki,defineSSRCustomElement:()=>Ol,devtools:()=>xn,effect:()=>Se,effectScope:()=>ce,getCurrentInstance:()=>Pi,getCurrentScope:()=>fe,getTransitionRawChildren:()=>hr,guardReactiveProps:()=>yi,h:()=>il,handleError:()=>nn,hydrate:()=>Ra,initCustomFormatter:()=>sl,initDirectivesForSSR:()=>Va,inject:()=>Yn,isMemoSame:()=>ul,isProxy:()=>Ot,isReactive:()=>Tt,isReadonly:()=>Nt,isRef:()=>Bt,isRuntimeOnly:()=>Ui,isShallow:()=>Lt,isVNode:()=>ci,markRaw:()=>Pt,mergeDefaults:()=>nl,mergeProps:()=>Ci,nextTick:()=>dn,normalizeClass:()=>f,normalizeProps:()=>p,normalizeStyle:()=>l,onActivated:()=>xr,onBeforeMount:()=>Or,onBeforeUnmount:()=>Rr,onBeforeUpdate:()=>Pr,onDeactivated:()=>kr,onErrorCaptured:()=>Vr,onMounted:()=>Ar,onRenderTracked:()=>jr,onRenderTriggered:()=>Br,onScopeDispose:()=>pe,onServerPrefetch:()=>Mr,onUnmounted:()=>Fr,onUpdated:()=>Ir,openBlock:()=>ti,popScopeId:()=>In,provide:()=>Kn,proxyRefs:()=>zt,pushScopeId:()=>Pn,queuePostFlushCb:()=>vn,reactive:()=>xt,readonly:()=>St,ref:()=>jt,registerRuntimeCompiler:()=>$i,render:()=>Ia,renderList:()=>Kr,renderSlot:()=>Zr,resolveComponent:()=>Wr,resolveDirective:()=>Gr,resolveDynamicComponent:()=>zr,resolveFilter:()=>dl,resolveTransitionHooks:()=>ur,setBlockTracking:()=>ii,setDevtoolsHook:()=>En,setTransitionHooks:()=>dr,shallowReactive:()=>kt,shallowReadonly:()=>Et,shallowRef:()=>Vt,ssrContextKey:()=>ll,ssrUtils:()=>pl,stop:()=>Ee,toDisplayString:()=>w,toHandlerKey:()=>te,toHandlers:()=>Qr,toRaw:()=>At,toRef:()=>Yt,toRefs:()=>Jt,transformVNodeArgs:()=>fi,triggerRef:()=>Ut,unref:()=>Wt,useAttrs:()=>el,useCssModule:()=>Il,useCssVars:()=>Rl,useSSRContext:()=>al,useSlots:()=>Qi,useTransitionState:()=>lr,vModelCheckbox:()=>fa,vModelDynamic:()=>ya,vModelRadio:()=>da,vModelSelect:()=>ha,vModelText:()=>ua,vShow:()=>Ca,version:()=>fl,warn:()=>Qt,watch:()=>tr,watchEffect:()=>Zn,watchPostEffect:()=>Xn,watchSyncEffect:()=>Qn,withAsyncContext:()=>ol,withCtx:()=>Fn,withDefaults:()=>Xi,withDirectives:()=>Dr,withKeys:()=>Ea,withMemo:()=>cl,withModifiers:()=>ka,withScopeId:()=>Rn});const i=o("Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt");function l(e){if(R(e)){const t={};for(let n=0;n{if(e){const n=e.split(s);n.length>1&&(t[n[0].trim()]=n[1].trim())}})),t}function f(e){let t="";if(V(e))t=e;else if(R(e))for(let n=0;n_(e,t)))}const w=e=>V(e)?e:null==e?"":R(e)||$(e)&&(e.toString===W||!j(e.toString))?JSON.stringify(e,x,2):String(e),x=(e,t)=>t&&t.__v_isRef?x(e,t.value):F(t)?{[`Map(${t.size})`]:[...t.entries()].reduce(((e,[t,n])=>(e[`${t} =>`]=n,e)),{})}:M(t)?{[`Set(${t.size})`]:[...t.values()]}:!$(t)||R(t)||z(t)?t:String(t),k={},S=[],E=()=>{},C=()=>!1,T=/^on[^a-z]/,N=e=>T.test(e),L=e=>e.startsWith("onUpdate:"),O=Object.assign,A=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},P=Object.prototype.hasOwnProperty,I=(e,t)=>P.call(e,t),R=Array.isArray,F=e=>"[object Map]"===H(e),M=e=>"[object Set]"===H(e),B=e=>"[object Date]"===H(e),j=e=>"function"==typeof e,V=e=>"string"==typeof e,D=e=>"symbol"==typeof e,$=e=>null!==e&&"object"==typeof e,U=e=>$(e)&&j(e.then)&&j(e.catch),W=Object.prototype.toString,H=e=>W.call(e),z=e=>"[object Object]"===H(e),G=e=>V(e)&&"NaN"!==e&&"-"!==e[0]&&""+parseInt(e,10)===e,q=o(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),J=o("bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo"),K=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},Y=/-(\w)/g,Z=K((e=>e.replace(Y,((e,t)=>t?t.toUpperCase():"")))),X=/\B([A-Z])/g,Q=K((e=>e.replace(X,"-$1").toLowerCase())),ee=K((e=>e.charAt(0).toUpperCase()+e.slice(1))),te=K((e=>e?`on${ee(e)}`:"")),ne=(e,t)=>!Object.is(e,t),re=(e,t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:n})},ie=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let le;let ae;class se{constructor(e=!1){this.detached=e,this.active=!0,this.effects=[],this.cleanups=[],this.parent=ae,!e&&ae&&(this.index=(ae.scopes||(ae.scopes=[])).push(this)-1)}run(e){if(this.active){const t=ae;try{return ae=this,e()}finally{ae=t}}else 0}on(){ae=this}off(){ae=this.parent}stop(e){if(this.active){let t,n;for(t=0,n=this.effects.length;t{const t=new Set(e);return t.w=0,t.n=0,t},he=e=>(e.w&ye)>0,me=e=>(e.n&ye)>0,ve=new WeakMap;let ge=0,ye=1;let _e;const be=Symbol(""),we=Symbol("");class xe{constructor(e,t=null,n){this.fn=e,this.scheduler=t,this.active=!0,this.deps=[],this.parent=void 0,ue(this,n)}run(){if(!this.active)return this.fn();let e=_e,t=Ce;for(;e;){if(e===this)return;e=e.parent}try{return this.parent=_e,_e=this,Ce=!0,ye=1<<++ge,ge<=30?(({deps:e})=>{if(e.length)for(let t=0;t{const{deps:t}=e;if(t.length){let n=0;for(let r=0;r{("length"===n||n>=e)&&a.push(t)}))}else switch(void 0!==n&&a.push(l.get(n)),t){case"add":R(e)?G(n)&&a.push(l.get("length")):(a.push(l.get(be)),F(e)&&a.push(l.get(we)));break;case"delete":R(e)||(a.push(l.get(be)),F(e)&&a.push(l.get(we)));break;case"set":F(e)&&a.push(l.get(be))}if(1===a.length)a[0]&&Ie(a[0]);else{const e=[];for(const t of a)t&&e.push(...t);Ie(de(e))}}function Ie(e,t){const n=R(e)?e:[...e];for(const e of n)e.computed&&Re(e,t);for(const e of n)e.computed||Re(e,t)}function Re(e,t){(e!==_e||e.allowRecurse)&&(e.scheduler?e.scheduler():e.run())}const Fe=o("__proto__,__v_isRef,__isVue"),Me=new Set(Object.getOwnPropertyNames(Symbol).filter((e=>"arguments"!==e&&"caller"!==e)).map((e=>Symbol[e])).filter(D)),Be=We(),je=We(!1,!0),Ve=We(!0),De=We(!0,!0),$e=Ue();function Ue(){const e={};return["includes","indexOf","lastIndexOf"].forEach((t=>{e[t]=function(...e){const n=At(this);for(let e=0,t=this.length;e{e[t]=function(...e){Ne();const n=At(this)[t].apply(this,e);return Le(),n}})),e}function We(e=!1,t=!1){return function(n,r,o){if("__v_isReactive"===r)return!e;if("__v_isReadonly"===r)return e;if("__v_isShallow"===r)return t;if("__v_raw"===r&&o===(e?t?bt:_t:t?yt:gt).get(n))return n;const i=R(n);if(!e&&i&&I($e,r))return Reflect.get($e,r,o);const l=Reflect.get(n,r,o);return(D(r)?Me.has(r):Fe(r))?l:(e||Oe(n,0,r),t?l:Bt(l)?i&&G(r)?l:l.value:$(l)?e?St(l):xt(l):l)}}function He(e=!1){return function(t,n,r,o){let i=t[n];if(Nt(i)&&Bt(i)&&!Bt(r))return!1;if(!e&&(Lt(r)||Nt(r)||(i=At(i),r=At(r)),!R(t)&&Bt(i)&&!Bt(r)))return i.value=r,!0;const l=R(t)&&G(n)?Number(n)!0,deleteProperty:(e,t)=>!0},qe=O({},ze,{get:je,set:He(!0)}),Je=O({},Ge,{get:De}),Ke=e=>e,Ye=e=>Reflect.getPrototypeOf(e);function Ze(e,t,n=!1,r=!1){const o=At(e=e.__v_raw),i=At(t);n||(t!==i&&Oe(o,0,t),Oe(o,0,i));const{has:l}=Ye(o),a=r?Ke:n?Rt:It;return l.call(o,t)?a(e.get(t)):l.call(o,i)?a(e.get(i)):void(e!==o&&e.get(t))}function Xe(e,t=!1){const n=this.__v_raw,r=At(n),o=At(e);return t||(e!==o&&Oe(r,0,e),Oe(r,0,o)),e===o?n.has(e):n.has(e)||n.has(o)}function Qe(e,t=!1){return e=e.__v_raw,!t&&Oe(At(e),0,be),Reflect.get(e,"size",e)}function et(e){e=At(e);const t=At(this);return Ye(t).has.call(t,e)||(t.add(e),Pe(t,"add",e,e)),this}function tt(e,t){t=At(t);const n=At(this),{has:r,get:o}=Ye(n);let i=r.call(n,e);i||(e=At(e),i=r.call(n,e));const l=o.call(n,e);return n.set(e,t),i?ne(t,l)&&Pe(n,"set",e,t):Pe(n,"add",e,t),this}function nt(e){const t=At(this),{has:n,get:r}=Ye(t);let o=n.call(t,e);o||(e=At(e),o=n.call(t,e));r&&r.call(t,e);const i=t.delete(e);return o&&Pe(t,"delete",e,void 0),i}function rt(){const e=At(this),t=0!==e.size,n=e.clear();return t&&Pe(e,"clear",void 0,void 0),n}function ot(e,t){return function(n,r){const o=this,i=o.__v_raw,l=At(i),a=t?Ke:e?Rt:It;return!e&&Oe(l,0,be),i.forEach(((e,t)=>n.call(r,a(e),a(t),o)))}}function it(e,t,n){return function(...r){const o=this.__v_raw,i=At(o),l=F(i),a="entries"===e||e===Symbol.iterator&&l,s="keys"===e&&l,c=o[e](...r),u=n?Ke:t?Rt:It;return!t&&Oe(i,0,s?we:be),{next(){const{value:e,done:t}=c.next();return t?{value:e,done:t}:{value:a?[u(e[0]),u(e[1])]:u(e),done:t}},[Symbol.iterator](){return this}}}}function lt(e){return function(...t){return"delete"!==e&&this}}function at(){const e={get(e){return Ze(this,e)},get size(){return Qe(this)},has:Xe,add:et,set:tt,delete:nt,clear:rt,forEach:ot(!1,!1)},t={get(e){return Ze(this,e,!1,!0)},get size(){return Qe(this)},has:Xe,add:et,set:tt,delete:nt,clear:rt,forEach:ot(!1,!0)},n={get(e){return Ze(this,e,!0)},get size(){return Qe(this,!0)},has(e){return Xe.call(this,e,!0)},add:lt("add"),set:lt("set"),delete:lt("delete"),clear:lt("clear"),forEach:ot(!0,!1)},r={get(e){return Ze(this,e,!0,!0)},get size(){return Qe(this,!0)},has(e){return Xe.call(this,e,!0)},add:lt("add"),set:lt("set"),delete:lt("delete"),clear:lt("clear"),forEach:ot(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach((o=>{e[o]=it(o,!1,!1),n[o]=it(o,!0,!1),t[o]=it(o,!1,!0),r[o]=it(o,!0,!0)})),[e,n,t,r]}const[st,ct,ut,ft]=at();function pt(e,t){const n=t?e?ft:ut:e?ct:st;return(t,r,o)=>"__v_isReactive"===r?!e:"__v_isReadonly"===r?e:"__v_raw"===r?t:Reflect.get(I(n,r)&&r in t?n:t,r,o)}const dt={get:pt(!1,!1)},ht={get:pt(!1,!0)},mt={get:pt(!0,!1)},vt={get:pt(!0,!0)};const gt=new WeakMap,yt=new WeakMap,_t=new WeakMap,bt=new WeakMap;function wt(e){return e.__v_skip||!Object.isExtensible(e)?0:function(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}((e=>H(e).slice(8,-1))(e))}function xt(e){return Nt(e)?e:Ct(e,!1,ze,dt,gt)}function kt(e){return Ct(e,!1,qe,ht,yt)}function St(e){return Ct(e,!0,Ge,mt,_t)}function Et(e){return Ct(e,!0,Je,vt,bt)}function Ct(e,t,n,r,o){if(!$(e))return e;if(e.__v_raw&&(!t||!e.__v_isReactive))return e;const i=o.get(e);if(i)return i;const l=wt(e);if(0===l)return e;const a=new Proxy(e,2===l?r:n);return o.set(e,a),a}function Tt(e){return Nt(e)?Tt(e.__v_raw):!(!e||!e.__v_isReactive)}function Nt(e){return!(!e||!e.__v_isReadonly)}function Lt(e){return!(!e||!e.__v_isShallow)}function Ot(e){return Tt(e)||Nt(e)}function At(e){const t=e&&e.__v_raw;return t?At(t):e}function Pt(e){return oe(e,"__v_skip",!0),e}const It=e=>$(e)?xt(e):e,Rt=e=>$(e)?St(e):e;function Ft(e){Ce&&_e&&Ae((e=At(e)).dep||(e.dep=de()))}function Mt(e,t){(e=At(e)).dep&&Ie(e.dep)}function Bt(e){return!(!e||!0!==e.__v_isRef)}function jt(e){return Dt(e,!1)}function Vt(e){return Dt(e,!0)}function Dt(e,t){return Bt(e)?e:new $t(e,t)}class $t{constructor(e,t){this.__v_isShallow=t,this.dep=void 0,this.__v_isRef=!0,this._rawValue=t?e:At(e),this._value=t?e:It(e)}get value(){return Ft(this),this._value}set value(e){const t=this.__v_isShallow||Lt(e)||Nt(e);e=t?e:At(e),ne(e,this._rawValue)&&(this._rawValue=e,this._value=t?e:It(e),Mt(this))}}function Ut(e){Mt(e)}function Wt(e){return Bt(e)?e.value:e}const Ht={get:(e,t,n)=>Wt(Reflect.get(e,t,n)),set:(e,t,n,r)=>{const o=e[t];return Bt(o)&&!Bt(n)?(o.value=n,!0):Reflect.set(e,t,n,r)}};function zt(e){return Tt(e)?e:new Proxy(e,Ht)}class Gt{constructor(e){this.dep=void 0,this.__v_isRef=!0;const{get:t,set:n}=e((()=>Ft(this)),(()=>Mt(this)));this._get=t,this._set=n}get value(){return this._get()}set value(e){this._set(e)}}function qt(e){return new Gt(e)}function Jt(e){const t=R(e)?new Array(e.length):{};for(const n in e)t[n]=Yt(e,n);return t}class Kt{constructor(e,t,n){this._object=e,this._key=t,this._defaultValue=n,this.__v_isRef=!0}get value(){const e=this._object[this._key];return void 0===e?this._defaultValue:e}set value(e){this._object[this._key]=e}}function Yt(e,t,n){const r=e[t];return Bt(r)?r:new Kt(e,t,n)}var Zt;class Xt{constructor(e,t,n,r){this._setter=t,this.dep=void 0,this.__v_isRef=!0,this[Zt]=!1,this._dirty=!0,this.effect=new xe(e,(()=>{this._dirty||(this._dirty=!0,Mt(this))})),this.effect.computed=this,this.effect.active=this._cacheable=!r,this.__v_isReadonly=n}get value(){const e=At(this);return Ft(e),!e._dirty&&e._cacheable||(e._dirty=!1,e._value=e.effect.run()),e._value}set value(e){this._setter(e)}}Zt="__v_isReadonly";function Qt(e,...t){}function en(e,t,n,r){let o;try{o=r?e(...r):e()}catch(e){nn(e,t,n)}return o}function tn(e,t,n,r){if(j(e)){const o=en(e,t,n,r);return o&&U(o)&&o.catch((e=>{nn(e,t,n)})),o}const o=[];for(let i=0;i>>1;_n(ln[r])_n(e)-_n(t))),un=0;unnull==e.id?1/0:e.id,bn=(e,t)=>{const n=_n(e)-_n(t);if(0===n){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return n};function wn(e){on=!1,rn=!0,ln.sort(bn);try{for(an=0;anxn.emit(e,...t))),kn=[];else if("undefined"!=typeof window&&window.HTMLElement&&!(null===(r=null===(n=window.navigator)||void 0===n?void 0:n.userAgent)||void 0===r?void 0:r.includes("jsdom"))){(t.__VUE_DEVTOOLS_HOOK_REPLAY__=t.__VUE_DEVTOOLS_HOOK_REPLAY__||[]).push((e=>{En(e,t)})),setTimeout((()=>{xn||(t.__VUE_DEVTOOLS_HOOK_REPLAY__=null,Sn=!0,kn=[])}),3e3)}else Sn=!0,kn=[]}function Cn(e,t,...n){if(e.isUnmounted)return;const r=e.vnode.props||k;let o=n;const i=t.startsWith("update:"),l=i&&t.slice(7);if(l&&l in r){const e=`${"modelValue"===l?"model":l}Modifiers`,{number:t,trim:i}=r[e]||k;i&&(o=n.map((e=>V(e)?e.trim():e))),t&&(o=n.map(ie))}let a;let s=r[a=te(t)]||r[a=te(Z(t))];!s&&i&&(s=r[a=te(Q(t))]),s&&tn(s,e,6,o);const c=r[a+"Once"];if(c){if(e.emitted){if(e.emitted[a])return}else e.emitted={};e.emitted[a]=!0,tn(c,e,6,o)}}function Tn(e,t,n=!1){const r=t.emitsCache,o=r.get(e);if(void 0!==o)return o;const i=e.emits;let l={},a=!1;if(!j(e)){const r=e=>{const n=Tn(e,t,!0);n&&(a=!0,O(l,n))};!n&&t.mixins.length&&t.mixins.forEach(r),e.extends&&r(e.extends),e.mixins&&e.mixins.forEach(r)}return i||a?(R(i)?i.forEach((e=>l[e]=null)):O(l,i),$(e)&&r.set(e,l),l):($(e)&&r.set(e,null),null)}function Nn(e,t){return!(!e||!N(t))&&(t=t.slice(2).replace(/Once$/,""),I(e,t[0].toLowerCase()+t.slice(1))||I(e,Q(t))||I(e,t))}let Ln=null,On=null;function An(e){const t=Ln;return Ln=e,On=e&&e.type.__scopeId||null,t}function Pn(e){On=e}function In(){On=null}const Rn=e=>Fn;function Fn(e,t=Ln,n){if(!t)return e;if(e._n)return e;const r=(...n)=>{r._d&&ii(-1);const o=An(t);let i;try{i=e(...n)}finally{An(o),r._d&&ii(1)}return i};return r._n=!0,r._c=!0,r._d=!0,r}function Mn(e){const{type:t,vnode:n,proxy:r,withProxy:o,props:i,propsOptions:[l],slots:a,attrs:s,emit:c,render:u,renderCache:f,data:p,setupState:d,ctx:h,inheritAttrs:m}=e;let v,g;const y=An(e);try{if(4&n.shapeFlag){const e=o||r;v=ki(u.call(e,e,f,i,d,p,h)),g=s}else{const e=t;0,v=ki(e.length>1?e(i,{attrs:s,slots:a,emit:c}):e(i,null)),g=t.props?s:jn(s)}}catch(t){Qo.length=0,nn(t,e,1),v=vi(Zo)}let _=v;if(g&&!1!==m){const e=Object.keys(g),{shapeFlag:t}=_;e.length&&7&t&&(l&&e.some(L)&&(g=Vn(g,l)),_=_i(_,g))}return n.dirs&&(_=_i(_),_.dirs=_.dirs?_.dirs.concat(n.dirs):n.dirs),n.transition&&(_.transition=n.transition),v=_,An(y),v}function Bn(e){let t;for(let n=0;n{let t;for(const n in e)("class"===n||"style"===n||N(n))&&((t||(t={}))[n]=e[n]);return t},Vn=(e,t)=>{const n={};for(const r in e)L(r)&&r.slice(9)in t||(n[r]=e[r]);return n};function Dn(e,t,n){const r=Object.keys(t);if(r.length!==Object.keys(e).length)return!0;for(let o=0;oe.__isSuspense,Wn={name:"Suspense",__isSuspense:!0,process(e,t,n,r,o,i,l,a,s,c){null==e?function(e,t,n,r,o,i,l,a,s){const{p:c,o:{createElement:u}}=s,f=u("div"),p=e.suspense=zn(e,o,r,t,f,n,i,l,a,s);c(null,p.pendingBranch=e.ssContent,f,null,r,p,i,l),p.deps>0?(Hn(e,"onPending"),Hn(e,"onFallback"),c(null,e.ssFallback,t,n,r,null,i,l),Jn(p,e.ssFallback)):p.resolve()}(t,n,r,o,i,l,a,s,c):function(e,t,n,r,o,i,l,a,{p:s,um:c,o:{createElement:u}}){const f=t.suspense=e.suspense;f.vnode=t,t.el=e.el;const p=t.ssContent,d=t.ssFallback,{activeBranch:h,pendingBranch:m,isInFallback:v,isHydrating:g}=f;if(m)f.pendingBranch=p,ui(p,m)?(s(m,p,f.hiddenContainer,null,o,f,i,l,a),f.deps<=0?f.resolve():v&&(s(h,d,n,r,o,null,i,l,a),Jn(f,d))):(f.pendingId++,g?(f.isHydrating=!1,f.activeBranch=m):c(m,o,f),f.deps=0,f.effects.length=0,f.hiddenContainer=u("div"),v?(s(null,p,f.hiddenContainer,null,o,f,i,l,a),f.deps<=0?f.resolve():(s(h,d,n,r,o,null,i,l,a),Jn(f,d))):h&&ui(p,h)?(s(h,p,n,r,o,f,i,l,a),f.resolve(!0)):(s(null,p,f.hiddenContainer,null,o,f,i,l,a),f.deps<=0&&f.resolve()));else if(h&&ui(p,h))s(h,p,n,r,o,f,i,l,a),Jn(f,p);else if(Hn(t,"onPending"),f.pendingBranch=p,f.pendingId++,s(null,p,f.hiddenContainer,null,o,f,i,l,a),f.deps<=0)f.resolve();else{const{timeout:e,pendingId:t}=f;e>0?setTimeout((()=>{f.pendingId===t&&f.fallback(d)}),e):0===e&&f.fallback(d)}}(e,t,n,r,o,l,a,s,c)},hydrate:function(e,t,n,r,o,i,l,a,s){const c=t.suspense=zn(t,r,n,e.parentNode,document.createElement("div"),null,o,i,l,a,!0),u=s(e,c.pendingBranch=t.ssContent,n,c,i,l);0===c.deps&&c.resolve();return u},create:zn,normalize:function(e){const{shapeFlag:t,children:n}=e,r=32&t;e.ssContent=Gn(r?n.default:n),e.ssFallback=r?Gn(n.fallback):vi(Zo)}};function Hn(e,t){const n=e.props&&e.props[t];j(n)&&n()}function zn(e,t,n,r,o,i,l,a,s,c,u=!1){const{p:f,m:p,um:d,n:h,o:{parentNode:m,remove:v}}=c,g=ie(e.props&&e.props.timeout),y={vnode:e,parent:t,parentComponent:n,isSVG:l,container:r,hiddenContainer:o,anchor:i,deps:0,pendingId:0,timeout:"number"==typeof g?g:-1,activeBranch:null,pendingBranch:null,isInFallback:!0,isHydrating:u,isUnmounted:!1,effects:[],resolve(e=!1){const{vnode:t,activeBranch:n,pendingBranch:r,pendingId:o,effects:i,parentComponent:l,container:a}=y;if(y.isHydrating)y.isHydrating=!1;else if(!e){const e=n&&r.transition&&"out-in"===r.transition.mode;e&&(n.transition.afterLeave=()=>{o===y.pendingId&&p(r,a,t,0)});let{anchor:t}=y;n&&(t=h(n),d(n,l,y,!0)),e||p(r,a,t,0)}Jn(y,r),y.pendingBranch=null,y.isInFallback=!1;let s=y.parent,c=!1;for(;s;){if(s.pendingBranch){s.effects.push(...i),c=!0;break}s=s.parent}c||vn(i),y.effects=[],Hn(t,"onResolve")},fallback(e){if(!y.pendingBranch)return;const{vnode:t,activeBranch:n,parentComponent:r,container:o,isSVG:i}=y;Hn(t,"onFallback");const l=h(n),c=()=>{y.isInFallback&&(f(null,e,o,l,r,null,i,a,s),Jn(y,e))},u=e.transition&&"out-in"===e.transition.mode;u&&(n.transition.afterLeave=c),y.isInFallback=!0,d(n,r,null,!0),u||c()},move(e,t,n){y.activeBranch&&p(y.activeBranch,e,t,n),y.container=e},next:()=>y.activeBranch&&h(y.activeBranch),registerDep(e,t){const n=!!y.pendingBranch;n&&y.deps++;const r=e.vnode.el;e.asyncDep.catch((t=>{nn(t,e,0)})).then((o=>{if(e.isUnmounted||y.isUnmounted||y.pendingId!==e.suspenseId)return;e.asyncResolved=!0;const{vnode:i}=e;Di(e,o,!1),r&&(i.el=r);const a=!r&&e.subTree.el;t(e,i,m(r||e.subTree.el),r?null:h(e.subTree),y,l,s),a&&v(a),$n(e,i.el),n&&0==--y.deps&&y.resolve()}))},unmount(e,t){y.isUnmounted=!0,y.activeBranch&&d(y.activeBranch,n,e,t),y.pendingBranch&&d(y.pendingBranch,n,e,t)}};return y}function Gn(e){let t;if(j(e)){const n=oi&&e._c;n&&(e._d=!1,ti()),e=e(),n&&(e._d=!0,t=ei,ni())}if(R(e)){const t=Bn(e);0,e=t}return e=ki(e),t&&!e.dynamicChildren&&(e.dynamicChildren=t.filter((t=>t!==e))),e}function qn(e,t){t&&t.pendingBranch?R(e)?t.effects.push(...e):t.effects.push(e):vn(e)}function Jn(e,t){e.activeBranch=t;const{vnode:n,parentComponent:r}=e,o=n.el=t.el;r&&r.subTree===n&&(r.vnode.el=o,$n(r,o))}function Kn(e,t){if(Ai){let n=Ai.provides;const r=Ai.parent&&Ai.parent.provides;r===n&&(n=Ai.provides=Object.create(r)),n[e]=t}else 0}function Yn(e,t,n=!1){const r=Ai||Ln;if(r){const o=null==r.parent?r.vnode.appContext&&r.vnode.appContext.provides:r.parent.provides;if(o&&e in o)return o[e];if(arguments.length>1)return n&&j(t)?t.call(r.proxy):t}else 0}function Zn(e,t){return nr(e,null,t)}function Xn(e,t){return nr(e,null,{flush:"post"})}function Qn(e,t){return nr(e,null,{flush:"sync"})}const er={};function tr(e,t,n){return nr(e,t,n)}function nr(e,t,{immediate:n,deep:r,flush:o,onTrack:i,onTrigger:l}=k){const a=Ai;let s,c,u=!1,f=!1;if(Bt(e)?(s=()=>e.value,u=Lt(e)):Tt(e)?(s=()=>e,r=!0):R(e)?(f=!0,u=e.some((e=>Tt(e)||Lt(e))),s=()=>e.map((e=>Bt(e)?e.value:Tt(e)?ir(e):j(e)?en(e,a,2):void 0))):s=j(e)?t?()=>en(e,a,2):()=>{if(!a||!a.isUnmounted)return c&&c(),tn(e,a,3,[d])}:E,t&&r){const e=s;s=()=>ir(e())}let p,d=e=>{c=g.onStop=()=>{en(e,a,4)}};if(ji){if(d=E,t?n&&tn(t,a,3,[s(),f?[]:void 0,d]):s(),"sync"!==o)return E;{const e=al();p=e.__watcherHandles||(e.__watcherHandles=[])}}let h=f?new Array(e.length).fill(er):er;const m=()=>{if(g.active)if(t){const e=g.run();(r||u||(f?e.some(((e,t)=>ne(e,h[t]))):ne(e,h)))&&(c&&c(),tn(t,a,3,[e,h===er?void 0:f&&h[0]===er?[]:h,d]),h=e)}else g.run()};let v;m.allowRecurse=!!t,"sync"===o?v=m:"post"===o?v=()=>Bo(m,a&&a.suspense):(m.pre=!0,a&&(m.id=a.uid),v=()=>hn(m));const g=new xe(s,v);t?n?m():h=g.run():"post"===o?Bo(g.run.bind(g),a&&a.suspense):g.run();const y=()=>{g.stop(),a&&a.scope&&A(a.scope.effects,g)};return p&&p.push(y),y}function rr(e,t,n){const r=this.proxy,o=V(e)?e.includes(".")?or(r,e):()=>r[e]:e.bind(r,r);let i;j(t)?i=t:(i=t.handler,n=t);const l=Ai;Ii(this);const a=nr(o,i.bind(r),n);return l?Ii(l):Ri(),a}function or(e,t){const n=t.split(".");return()=>{let t=e;for(let e=0;e{ir(e,t)}));else if(z(e))for(const n in e)ir(e[n],t);return e}function lr(){const e={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return Ar((()=>{e.isMounted=!0})),Rr((()=>{e.isUnmounting=!0})),e}const ar=[Function,Array],sr={name:"BaseTransition",props:{mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:ar,onEnter:ar,onAfterEnter:ar,onEnterCancelled:ar,onBeforeLeave:ar,onLeave:ar,onAfterLeave:ar,onLeaveCancelled:ar,onBeforeAppear:ar,onAppear:ar,onAfterAppear:ar,onAppearCancelled:ar},setup(e,{slots:t}){const n=Pi(),r=lr();let o;return()=>{const i=t.default&&hr(t.default(),!0);if(!i||!i.length)return;let l=i[0];if(i.length>1){let e=!1;for(const t of i)if(t.type!==Zo){0,l=t,e=!0;break}}const a=At(e),{mode:s}=a;if(r.isLeaving)return fr(l);const c=pr(l);if(!c)return fr(l);const u=ur(c,a,r,n);dr(c,u);const f=n.subTree,p=f&&pr(f);let d=!1;const{getTransitionKey:h}=c.type;if(h){const e=h();void 0===o?o=e:e!==o&&(o=e,d=!0)}if(p&&p.type!==Zo&&(!ui(c,p)||d)){const e=ur(p,a,r,n);if(dr(p,e),"out-in"===s)return r.isLeaving=!0,e.afterLeave=()=>{r.isLeaving=!1,!1!==n.update.active&&n.update()},fr(l);"in-out"===s&&c.type!==Zo&&(e.delayLeave=(e,t,n)=>{cr(r,p)[String(p.key)]=p,e._leaveCb=()=>{t(),e._leaveCb=void 0,delete u.delayedLeave},u.delayedLeave=n})}return l}}};function cr(e,t){const{leavingVNodes:n}=e;let r=n.get(t.type);return r||(r=Object.create(null),n.set(t.type,r)),r}function ur(e,t,n,r){const{appear:o,mode:i,persisted:l=!1,onBeforeEnter:a,onEnter:s,onAfterEnter:c,onEnterCancelled:u,onBeforeLeave:f,onLeave:p,onAfterLeave:d,onLeaveCancelled:h,onBeforeAppear:m,onAppear:v,onAfterAppear:g,onAppearCancelled:y}=t,_=String(e.key),b=cr(n,e),w=(e,t)=>{e&&tn(e,r,9,t)},x=(e,t)=>{const n=t[1];w(e,t),R(e)?e.every((e=>e.length<=1))&&n():e.length<=1&&n()},k={mode:i,persisted:l,beforeEnter(t){let r=a;if(!n.isMounted){if(!o)return;r=m||a}t._leaveCb&&t._leaveCb(!0);const i=b[_];i&&ui(e,i)&&i.el._leaveCb&&i.el._leaveCb(),w(r,[t])},enter(e){let t=s,r=c,i=u;if(!n.isMounted){if(!o)return;t=v||s,r=g||c,i=y||u}let l=!1;const a=e._enterCb=t=>{l||(l=!0,w(t?i:r,[e]),k.delayedLeave&&k.delayedLeave(),e._enterCb=void 0)};t?x(t,[e,a]):a()},leave(t,r){const o=String(e.key);if(t._enterCb&&t._enterCb(!0),n.isUnmounting)return r();w(f,[t]);let i=!1;const l=t._leaveCb=n=>{i||(i=!0,r(),w(n?h:d,[t]),t._leaveCb=void 0,b[o]===e&&delete b[o])};b[o]=e,p?x(p,[t,l]):l()},clone:e=>ur(e,t,n,r)};return k}function fr(e){if(_r(e))return(e=_i(e)).children=null,e}function pr(e){return _r(e)?e.children?e.children[0]:void 0:e}function dr(e,t){6&e.shapeFlag&&e.component?dr(e.component.subTree,t):128&e.shapeFlag?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function hr(e,t=!1,n){let r=[],o=0;for(let i=0;i1)for(let e=0;e!!e.type.__asyncLoader;function gr(e){j(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:r,delay:o=200,timeout:i,suspensible:l=!0,onError:a}=e;let s,c=null,u=0;const f=()=>{let e;return c||(e=c=t().catch((e=>{if(e=e instanceof Error?e:new Error(String(e)),a)return new Promise(((t,n)=>{a(e,(()=>t((u++,c=null,f()))),(()=>n(e)),u+1)}));throw e})).then((t=>e!==c&&c?c:(t&&(t.__esModule||"Module"===t[Symbol.toStringTag])&&(t=t.default),s=t,t))))};return mr({name:"AsyncComponentWrapper",__asyncLoader:f,get __asyncResolved(){return s},setup(){const e=Ai;if(s)return()=>yr(s,e);const t=t=>{c=null,nn(t,e,13,!r)};if(l&&e.suspense||ji)return f().then((t=>()=>yr(t,e))).catch((e=>(t(e),()=>r?vi(r,{error:e}):null)));const a=jt(!1),u=jt(),p=jt(!!o);return o&&setTimeout((()=>{p.value=!1}),o),null!=i&&setTimeout((()=>{if(!a.value&&!u.value){const e=new Error(`Async component timed out after ${i}ms.`);t(e),u.value=e}}),i),f().then((()=>{a.value=!0,e.parent&&_r(e.parent.vnode)&&hn(e.parent.update)})).catch((e=>{t(e),u.value=e})),()=>a.value&&s?yr(s,e):u.value&&r?vi(r,{error:u.value}):n&&!p.value?vi(n):void 0}})}function yr(e,t){const{ref:n,props:r,children:o,ce:i}=t.vnode,l=vi(e,r,o);return l.ref=n,l.ce=i,delete t.vnode.ce,l}const _r=e=>e.type.__isKeepAlive,br={name:"KeepAlive",__isKeepAlive:!0,props:{include:[String,RegExp,Array],exclude:[String,RegExp,Array],max:[String,Number]},setup(e,{slots:t}){const n=Pi(),r=n.ctx;if(!r.renderer)return()=>{const e=t.default&&t.default();return e&&1===e.length?e[0]:e};const o=new Map,i=new Set;let l=null;const a=n.suspense,{renderer:{p:s,m:c,um:u,o:{createElement:f}}}=r,p=f("div");function d(e){Cr(e),u(e,n,a,!0)}function h(e){o.forEach(((t,n)=>{const r=Gi(t.type);!r||e&&e(r)||m(n)}))}function m(e){const t=o.get(e);l&&t.type===l.type?l&&Cr(l):d(t),o.delete(e),i.delete(e)}r.activate=(e,t,n,r,o)=>{const i=e.component;c(e,t,n,0,a),s(i.vnode,e,t,n,i,a,r,e.slotScopeIds,o),Bo((()=>{i.isDeactivated=!1,i.a&&re(i.a);const t=e.props&&e.props.onVnodeMounted;t&&Ti(t,i.parent,e)}),a)},r.deactivate=e=>{const t=e.component;c(e,p,null,1,a),Bo((()=>{t.da&&re(t.da);const n=e.props&&e.props.onVnodeUnmounted;n&&Ti(n,t.parent,e),t.isDeactivated=!0}),a)},tr((()=>[e.include,e.exclude]),(([e,t])=>{e&&h((t=>wr(e,t))),t&&h((e=>!wr(t,e)))}),{flush:"post",deep:!0});let v=null;const g=()=>{null!=v&&o.set(v,Tr(n.subTree))};return Ar(g),Ir(g),Rr((()=>{o.forEach((e=>{const{subTree:t,suspense:r}=n,o=Tr(t);if(e.type!==o.type)d(e);else{Cr(o);const e=o.component.da;e&&Bo(e,r)}}))})),()=>{if(v=null,!t.default)return null;const n=t.default(),r=n[0];if(n.length>1)return l=null,n;if(!(ci(r)&&(4&r.shapeFlag||128&r.shapeFlag)))return l=null,r;let a=Tr(r);const s=a.type,c=Gi(vr(a)?a.type.__asyncResolved||{}:s),{include:u,exclude:f,max:p}=e;if(u&&(!c||!wr(u,c))||f&&c&&wr(f,c))return l=a,r;const d=null==a.key?s:a.key,h=o.get(d);return a.el&&(a=_i(a),128&r.shapeFlag&&(r.ssContent=a)),v=d,h?(a.el=h.el,a.component=h.component,a.transition&&dr(a,a.transition),a.shapeFlag|=512,i.delete(d),i.add(d)):(i.add(d),p&&i.size>parseInt(p,10)&&m(i.values().next().value)),a.shapeFlag|=256,l=a,Un(r.type)?r:a}}};function wr(e,t){return R(e)?e.some((e=>wr(e,t))):V(e)?e.split(",").includes(t):!!e.test&&e.test(t)}function xr(e,t){Sr(e,"a",t)}function kr(e,t){Sr(e,"da",t)}function Sr(e,t,n=Ai){const r=e.__wdc||(e.__wdc=()=>{let t=n;for(;t;){if(t.isDeactivated)return;t=t.parent}return e()});if(Nr(t,r,n),n){let e=n.parent;for(;e&&e.parent;)_r(e.parent.vnode)&&Er(r,t,n,e),e=e.parent}}function Er(e,t,n,r){const o=Nr(t,e,r,!0);Fr((()=>{A(r[t],o)}),n)}function Cr(e){e.shapeFlag&=-257,e.shapeFlag&=-513}function Tr(e){return 128&e.shapeFlag?e.ssContent:e}function Nr(e,t,n=Ai,r=!1){if(n){const o=n[e]||(n[e]=[]),i=t.__weh||(t.__weh=(...r)=>{if(n.isUnmounted)return;Ne(),Ii(n);const o=tn(t,n,e,r);return Ri(),Le(),o});return r?o.unshift(i):o.push(i),i}}const Lr=e=>(t,n=Ai)=>(!ji||"sp"===e)&&Nr(e,((...e)=>t(...e)),n),Or=Lr("bm"),Ar=Lr("m"),Pr=Lr("bu"),Ir=Lr("u"),Rr=Lr("bum"),Fr=Lr("um"),Mr=Lr("sp"),Br=Lr("rtg"),jr=Lr("rtc");function Vr(e,t=Ai){Nr("ec",e,t)}function Dr(e,t){const n=Ln;if(null===n)return e;const r=zi(n)||n.proxy,o=e.dirs||(e.dirs=[]);for(let e=0;et(e,n,void 0,i&&i[n])));else{const n=Object.keys(e);o=new Array(n.length);for(let r=0,l=n.length;r{const t=r.fn(...e);return t&&(t.key=r.key),t}:r.fn)}return e}function Zr(e,t,n={},r,o){if(Ln.isCE||Ln.parent&&vr(Ln.parent)&&Ln.parent.isCE)return"default"!==t&&(n.name=t),vi("slot",n,r&&r());let i=e[t];i&&i._c&&(i._d=!1),ti();const l=i&&Xr(i(n)),a=si(Ko,{key:n.key||l&&l.key||`_${t}`},l||(r?r():[]),l&&1===e._?64:-2);return!o&&a.scopeId&&(a.slotScopeIds=[a.scopeId+"-s"]),i&&i._c&&(i._d=!0),a}function Xr(e){return e.some((e=>!ci(e)||e.type!==Zo&&!(e.type===Ko&&!Xr(e.children))))?e:null}function Qr(e,t){const n={};for(const r in e)n[t&&/[A-Z]/.test(r)?`on:${r}`:te(r)]=e[r];return n}const eo=e=>e?Fi(e)?zi(e)||e.proxy:eo(e.parent):null,to=O(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>eo(e.parent),$root:e=>eo(e.root),$emit:e=>e.emit,$options:e=>co(e),$forceUpdate:e=>e.f||(e.f=()=>hn(e.update)),$nextTick:e=>e.n||(e.n=dn.bind(e.proxy)),$watch:e=>rr.bind(e)}),no=(e,t)=>e!==k&&!e.__isScriptSetup&&I(e,t),ro={get({_:e},t){const{ctx:n,setupState:r,data:o,props:i,accessCache:l,type:a,appContext:s}=e;let c;if("$"!==t[0]){const a=l[t];if(void 0!==a)switch(a){case 1:return r[t];case 2:return o[t];case 4:return n[t];case 3:return i[t]}else{if(no(r,t))return l[t]=1,r[t];if(o!==k&&I(o,t))return l[t]=2,o[t];if((c=e.propsOptions[0])&&I(c,t))return l[t]=3,i[t];if(n!==k&&I(n,t))return l[t]=4,n[t];io&&(l[t]=0)}}const u=to[t];let f,p;return u?("$attrs"===t&&Oe(e,0,t),u(e)):(f=a.__cssModules)&&(f=f[t])?f:n!==k&&I(n,t)?(l[t]=4,n[t]):(p=s.config.globalProperties,I(p,t)?p[t]:void 0)},set({_:e},t,n){const{data:r,setupState:o,ctx:i}=e;return no(o,t)?(o[t]=n,!0):r!==k&&I(r,t)?(r[t]=n,!0):!I(e.props,t)&&(("$"!==t[0]||!(t.slice(1)in e))&&(i[t]=n,!0))},has({_:{data:e,setupState:t,accessCache:n,ctx:r,appContext:o,propsOptions:i}},l){let a;return!!n[l]||e!==k&&I(e,l)||no(t,l)||(a=i[0])&&I(a,l)||I(r,l)||I(to,l)||I(o.config.globalProperties,l)},defineProperty(e,t,n){return null!=n.get?e._.accessCache[t]=0:I(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};const oo=O({},ro,{get(e,t){if(t!==Symbol.unscopables)return ro.get(e,t,e)},has:(e,t)=>"_"!==t[0]&&!i(t)});let io=!0;function lo(e){const t=co(e),n=e.proxy,r=e.ctx;io=!1,t.beforeCreate&&ao(t.beforeCreate,e,"bc");const{data:o,computed:i,methods:l,watch:a,provide:s,inject:c,created:u,beforeMount:f,mounted:p,beforeUpdate:d,updated:h,activated:m,deactivated:v,beforeDestroy:g,beforeUnmount:y,destroyed:_,unmounted:b,render:w,renderTracked:x,renderTriggered:k,errorCaptured:S,serverPrefetch:C,expose:T,inheritAttrs:N,components:L,directives:O,filters:A}=t;if(c&&function(e,t,n=E,r=!1){R(e)&&(e=ho(e));for(const n in e){const o=e[n];let i;i=$(o)?"default"in o?Yn(o.from||n,o.default,!0):Yn(o.from||n):Yn(o),Bt(i)&&r?Object.defineProperty(t,n,{enumerable:!0,configurable:!0,get:()=>i.value,set:e=>i.value=e}):t[n]=i}}(c,r,null,e.appContext.config.unwrapInjectedRef),l)for(const e in l){const t=l[e];j(t)&&(r[e]=t.bind(n))}if(o){0;const t=o.call(n,n);0,$(t)&&(e.data=xt(t))}if(io=!0,i)for(const e in i){const t=i[e],o=j(t)?t.bind(n,n):j(t.get)?t.get.bind(n,n):E;0;const l=!j(t)&&j(t.set)?t.set.bind(n):E,a=Ji({get:o,set:l});Object.defineProperty(r,e,{enumerable:!0,configurable:!0,get:()=>a.value,set:e=>a.value=e})}if(a)for(const e in a)so(a[e],r,n,e);if(s){const e=j(s)?s.call(n):s;Reflect.ownKeys(e).forEach((t=>{Kn(t,e[t])}))}function P(e,t){R(t)?t.forEach((t=>e(t.bind(n)))):t&&e(t.bind(n))}if(u&&ao(u,e,"c"),P(Or,f),P(Ar,p),P(Pr,d),P(Ir,h),P(xr,m),P(kr,v),P(Vr,S),P(jr,x),P(Br,k),P(Rr,y),P(Fr,b),P(Mr,C),R(T))if(T.length){const t=e.exposed||(e.exposed={});T.forEach((e=>{Object.defineProperty(t,e,{get:()=>n[e],set:t=>n[e]=t})}))}else e.exposed||(e.exposed={});w&&e.render===E&&(e.render=w),null!=N&&(e.inheritAttrs=N),L&&(e.components=L),O&&(e.directives=O)}function ao(e,t,n){tn(R(e)?e.map((e=>e.bind(t.proxy))):e.bind(t.proxy),t,n)}function so(e,t,n,r){const o=r.includes(".")?or(n,r):()=>n[r];if(V(e)){const n=t[e];j(n)&&tr(o,n)}else if(j(e))tr(o,e.bind(n));else if($(e))if(R(e))e.forEach((e=>so(e,t,n,r)));else{const r=j(e.handler)?e.handler.bind(n):t[e.handler];j(r)&&tr(o,r,e)}else 0}function co(e){const t=e.type,{mixins:n,extends:r}=t,{mixins:o,optionsCache:i,config:{optionMergeStrategies:l}}=e.appContext,a=i.get(t);let s;return a?s=a:o.length||n||r?(s={},o.length&&o.forEach((e=>uo(s,e,l,!0))),uo(s,t,l)):s=t,$(t)&&i.set(t,s),s}function uo(e,t,n,r=!1){const{mixins:o,extends:i}=t;i&&uo(e,i,n,!0),o&&o.forEach((t=>uo(e,t,n,!0)));for(const o in t)if(r&&"expose"===o);else{const r=fo[o]||n&&n[o];e[o]=r?r(e[o],t[o]):t[o]}return e}const fo={data:po,props:vo,emits:vo,methods:vo,computed:vo,beforeCreate:mo,created:mo,beforeMount:mo,mounted:mo,beforeUpdate:mo,updated:mo,beforeDestroy:mo,beforeUnmount:mo,destroyed:mo,unmounted:mo,activated:mo,deactivated:mo,errorCaptured:mo,serverPrefetch:mo,components:vo,directives:vo,watch:function(e,t){if(!e)return t;if(!t)return e;const n=O(Object.create(null),e);for(const r in t)n[r]=mo(e[r],t[r]);return n},provide:po,inject:function(e,t){return vo(ho(e),ho(t))}};function po(e,t){return t?e?function(){return O(j(e)?e.call(this,this):e,j(t)?t.call(this,this):t)}:t:e}function ho(e){if(R(e)){const t={};for(let n=0;n{s=!0;const[n,r]=_o(e,t,!0);O(l,n),r&&a.push(...r)};!n&&t.mixins.length&&t.mixins.forEach(r),e.extends&&r(e.extends),e.mixins&&e.mixins.forEach(r)}if(!i&&!s)return $(e)&&r.set(e,S),S;if(R(i))for(let e=0;e-1,r[1]=n<0||e-1||I(r,"default"))&&a.push(t)}}}}const c=[l,a];return $(e)&&r.set(e,c),c}function bo(e){return"$"!==e[0]}function wo(e){const t=e&&e.toString().match(/^\s*function (\w+)/);return t?t[1]:null===e?"null":""}function xo(e,t){return wo(e)===wo(t)}function ko(e,t){return R(t)?t.findIndex((t=>xo(t,e))):j(t)&&xo(t,e)?0:-1}const So=e=>"_"===e[0]||"$stable"===e,Eo=e=>R(e)?e.map(ki):[ki(e)],Co=(e,t,n)=>{if(t._n)return t;const r=Fn(((...e)=>Eo(t(...e))),n);return r._c=!1,r},To=(e,t,n)=>{const r=e._ctx;for(const n in e){if(So(n))continue;const o=e[n];if(j(o))t[n]=Co(0,o,r);else if(null!=o){0;const e=Eo(o);t[n]=()=>e}}},No=(e,t)=>{const n=Eo(t);e.slots.default=()=>n};function Lo(){return{app:null,config:{isNativeTag:C,performance:!1,globalProperties:{},optionMergeStrategies:{},errorHandler:void 0,warnHandler:void 0,compilerOptions:{}},mixins:[],components:{},directives:{},provides:Object.create(null),optionsCache:new WeakMap,propsCache:new WeakMap,emitsCache:new WeakMap}}let Oo=0;function Ao(e,t){return function(n,r=null){j(n)||(n=Object.assign({},n)),null==r||$(r)||(r=null);const o=Lo(),i=new Set;let l=!1;const a=o.app={_uid:Oo++,_component:n,_props:r,_container:null,_context:o,_instance:null,version:fl,get config(){return o.config},set config(e){0},use:(e,...t)=>(i.has(e)||(e&&j(e.install)?(i.add(e),e.install(a,...t)):j(e)&&(i.add(e),e(a,...t))),a),mixin:e=>(o.mixins.includes(e)||o.mixins.push(e),a),component:(e,t)=>t?(o.components[e]=t,a):o.components[e],directive:(e,t)=>t?(o.directives[e]=t,a):o.directives[e],mount(i,s,c){if(!l){0;const u=vi(n,r);return u.appContext=o,s&&t?t(u,i):e(u,i,c),l=!0,a._container=i,i.__vue_app__=a,zi(u.component)||u.component.proxy}},unmount(){l&&(e(null,a._container),delete a._container.__vue_app__)},provide:(e,t)=>(o.provides[e]=t,a)};return a}}function Po(e,t,n,r,o=!1){if(R(e))return void e.forEach(((e,i)=>Po(e,t&&(R(t)?t[i]:t),n,r,o)));if(vr(r)&&!o)return;const i=4&r.shapeFlag?zi(r.component)||r.component.proxy:r.el,l=o?null:i,{i:a,r:s}=e;const c=t&&t.r,u=a.refs===k?a.refs={}:a.refs,f=a.setupState;if(null!=c&&c!==s&&(V(c)?(u[c]=null,I(f,c)&&(f[c]=null)):Bt(c)&&(c.value=null)),j(s))en(s,a,12,[l,u]);else{const t=V(s),r=Bt(s);if(t||r){const a=()=>{if(e.f){const n=t?I(f,s)?f[s]:u[s]:s.value;o?R(n)&&A(n,i):R(n)?n.includes(i)||n.push(i):t?(u[s]=[i],I(f,s)&&(f[s]=u[s])):(s.value=[i],e.k&&(u[e.k]=s.value))}else t?(u[s]=l,I(f,s)&&(f[s]=l)):r&&(s.value=l,e.k&&(u[e.k]=l))};l?(a.id=-1,Bo(a,n)):a()}else 0}}let Io=!1;const Ro=e=>/svg/.test(e.namespaceURI)&&"foreignObject"!==e.tagName,Fo=e=>8===e.nodeType;function Mo(e){const{mt:t,p:n,o:{patchProp:r,createText:o,nextSibling:i,parentNode:l,remove:a,insert:s,createComment:c}}=e,u=(n,r,a,c,v,g=!1)=>{const y=Fo(n)&&"["===n.data,_=()=>h(n,r,a,c,v,y),{type:b,ref:w,shapeFlag:x,patchFlag:k}=r;let S=n.nodeType;r.el=n,-2===k&&(g=!1,r.dynamicChildren=null);let E=null;switch(b){case Yo:3!==S?""===r.children?(s(r.el=o(""),l(n),n),E=n):E=_():(n.data!==r.children&&(Io=!0,n.data=r.children),E=i(n));break;case Zo:E=8!==S||y?_():i(n);break;case Xo:if(y&&(S=(n=i(n)).nodeType),1===S||3===S){E=n;const e=!r.children.length;for(let t=0;t{l=l||!!t.dynamicChildren;const{type:s,props:c,patchFlag:u,shapeFlag:f,dirs:d}=t,h="input"===s&&d||"option"===s;if(h||-1!==u){if(d&&$r(t,null,n,"created"),c)if(h||!l||48&u)for(const t in c)(h&&t.endsWith("value")||N(t)&&!q(t))&&r(e,t,null,c[t],!1,void 0,n);else c.onClick&&r(e,"onClick",null,c.onClick,!1,void 0,n);let s;if((s=c&&c.onVnodeBeforeMount)&&Ti(s,n,t),d&&$r(t,null,n,"beforeMount"),((s=c&&c.onVnodeMounted)||d)&&qn((()=>{s&&Ti(s,n,t),d&&$r(t,null,n,"mounted")}),o),16&f&&(!c||!c.innerHTML&&!c.textContent)){let r=p(e.firstChild,t,e,n,o,i,l);for(;r;){Io=!0;const e=r;r=r.nextSibling,a(e)}}else 8&f&&e.textContent!==t.children&&(Io=!0,e.textContent=t.children)}return e.nextSibling},p=(e,t,r,o,i,l,a)=>{a=a||!!t.dynamicChildren;const s=t.children,c=s.length;for(let t=0;t{const{slotScopeIds:u}=t;u&&(o=o?o.concat(u):u);const f=l(e),d=p(i(e),t,f,n,r,o,a);return d&&Fo(d)&&"]"===d.data?i(t.anchor=d):(Io=!0,s(t.anchor=c("]"),f,d),d)},h=(e,t,r,o,s,c)=>{if(Io=!0,t.el=null,c){const t=m(e);for(;;){const n=i(e);if(!n||n===t)break;a(n)}}const u=i(e),f=l(e);return a(e),n(null,t,f,u,r,o,Ro(f),s),u},m=e=>{let t=0;for(;e;)if((e=i(e))&&Fo(e)&&("["===e.data&&t++,"]"===e.data)){if(0===t)return i(e);t--}return e};return[(e,t)=>{if(!t.hasChildNodes())return n(null,e,t),yn(),void(t._vnode=e);Io=!1,u(t.firstChild,e,null,null,null),yn(),t._vnode=e,Io&&console.error("Hydration completed but contains mismatches.")},u]}const Bo=qn;function jo(e){return Do(e)}function Vo(e){return Do(e,Mo)}function Do(e,t){(le||(le="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==n.g?n.g:{})).__VUE__=!0;const{insert:r,remove:o,patchProp:i,createElement:l,createText:a,createComment:s,setText:c,setElementText:u,parentNode:f,nextSibling:p,setScopeId:d=E,insertStaticContent:h}=e,m=(e,t,n,r=null,o=null,i=null,l=!1,a=null,s=!!t.dynamicChildren)=>{if(e===t)return;e&&!ui(e,t)&&(r=J(e),U(e,o,i,!0),e=null),-2===t.patchFlag&&(s=!1,t.dynamicChildren=null);const{type:c,ref:u,shapeFlag:f}=t;switch(c){case Yo:v(e,t,n,r);break;case Zo:g(e,t,n,r);break;case Xo:null==e&&y(t,n,r,l);break;case Ko:A(e,t,n,r,o,i,l,a,s);break;default:1&f?b(e,t,n,r,o,i,l,a,s):6&f?P(e,t,n,r,o,i,l,a,s):(64&f||128&f)&&c.process(e,t,n,r,o,i,l,a,s,Y)}null!=u&&o&&Po(u,e&&e.ref,i,t||e,!t)},v=(e,t,n,o)=>{if(null==e)r(t.el=a(t.children),n,o);else{const n=t.el=e.el;t.children!==e.children&&c(n,t.children)}},g=(e,t,n,o)=>{null==e?r(t.el=s(t.children||""),n,o):t.el=e.el},y=(e,t,n,r)=>{[e.el,e.anchor]=h(e.children,t,n,r,e.el,e.anchor)},_=({el:e,anchor:t})=>{let n;for(;e&&e!==t;)n=p(e),o(e),e=n;o(t)},b=(e,t,n,r,o,i,l,a,s)=>{l=l||"svg"===t.type,null==e?w(t,n,r,o,i,l,a,s):T(e,t,o,i,l,a,s)},w=(e,t,n,o,a,s,c,f)=>{let p,d;const{type:h,props:m,shapeFlag:v,transition:g,dirs:y}=e;if(p=e.el=l(e.type,s,m&&m.is,m),8&v?u(p,e.children):16&v&&C(e.children,p,null,o,a,s&&"foreignObject"!==h,c,f),y&&$r(e,null,o,"created"),m){for(const t in m)"value"===t||q(t)||i(p,t,null,m[t],s,e.children,o,a,G);"value"in m&&i(p,"value",null,m.value),(d=m.onVnodeBeforeMount)&&Ti(d,o,e)}x(p,e,e.scopeId,c,o),y&&$r(e,null,o,"beforeMount");const _=(!a||a&&!a.pendingBranch)&&g&&!g.persisted;_&&g.beforeEnter(p),r(p,t,n),((d=m&&m.onVnodeMounted)||_||y)&&Bo((()=>{d&&Ti(d,o,e),_&&g.enter(p),y&&$r(e,null,o,"mounted")}),a)},x=(e,t,n,r,o)=>{if(n&&d(e,n),r)for(let t=0;t{for(let c=s;c{const s=t.el=e.el;let{patchFlag:c,dynamicChildren:f,dirs:p}=t;c|=16&e.patchFlag;const d=e.props||k,h=t.props||k;let m;n&&$o(n,!1),(m=h.onVnodeBeforeUpdate)&&Ti(m,n,t,e),p&&$r(t,e,n,"beforeUpdate"),n&&$o(n,!0);const v=o&&"foreignObject"!==t.type;if(f?N(e.dynamicChildren,f,s,n,r,v,l):a||j(e,t,s,null,n,r,v,l,!1),c>0){if(16&c)L(s,t,d,h,n,r,o);else if(2&c&&d.class!==h.class&&i(s,"class",null,h.class,o),4&c&&i(s,"style",d.style,h.style,o),8&c){const l=t.dynamicProps;for(let t=0;t{m&&Ti(m,n,t,e),p&&$r(t,e,n,"updated")}),r)},N=(e,t,n,r,o,i,l)=>{for(let a=0;a{if(n!==r){if(n!==k)for(const s in n)q(s)||s in r||i(e,s,n[s],null,a,t.children,o,l,G);for(const s in r){if(q(s))continue;const c=r[s],u=n[s];c!==u&&"value"!==s&&i(e,s,u,c,a,t.children,o,l,G)}"value"in r&&i(e,"value",n.value,r.value)}},A=(e,t,n,o,i,l,s,c,u)=>{const f=t.el=e?e.el:a(""),p=t.anchor=e?e.anchor:a("");let{patchFlag:d,dynamicChildren:h,slotScopeIds:m}=t;m&&(c=c?c.concat(m):m),null==e?(r(f,n,o),r(p,n,o),C(t.children,n,p,i,l,s,c,u)):d>0&&64&d&&h&&e.dynamicChildren?(N(e.dynamicChildren,h,n,i,l,s,c),(null!=t.key||i&&t===i.subTree)&&Uo(e,t,!0)):j(e,t,n,p,i,l,s,c,u)},P=(e,t,n,r,o,i,l,a,s)=>{t.slotScopeIds=a,null==e?512&t.shapeFlag?o.ctx.activate(t,n,r,l,s):R(t,n,r,o,i,l,s):F(e,t,s)},R=(e,t,n,r,o,i,l)=>{const a=e.component=Oi(e,r,o);if(_r(e)&&(a.ctx.renderer=Y),Vi(a),a.asyncDep){if(o&&o.registerDep(a,M),!e.el){const e=a.subTree=vi(Zo);g(null,e,t,n)}}else M(a,e,t,n,o,i,l)},F=(e,t,n)=>{const r=t.component=e.component;if(function(e,t,n){const{props:r,children:o,component:i}=e,{props:l,children:a,patchFlag:s}=t,c=i.emitsOptions;if(t.dirs||t.transition)return!0;if(!(n&&s>=0))return!(!o&&!a||a&&a.$stable)||r!==l&&(r?!l||Dn(r,l,c):!!l);if(1024&s)return!0;if(16&s)return r?Dn(r,l,c):!!l;if(8&s){const e=t.dynamicProps;for(let t=0;tan&&ln.splice(t,1)}(r.update),r.update()}else t.el=e.el,r.vnode=t},M=(e,t,n,r,o,i,l)=>{const a=e.effect=new xe((()=>{if(e.isMounted){let t,{next:n,bu:r,u:a,parent:s,vnode:c}=e,u=n;0,$o(e,!1),n?(n.el=c.el,B(e,n,l)):n=c,r&&re(r),(t=n.props&&n.props.onVnodeBeforeUpdate)&&Ti(t,s,n,c),$o(e,!0);const p=Mn(e);0;const d=e.subTree;e.subTree=p,m(d,p,f(d.el),J(d),e,o,i),n.el=p.el,null===u&&$n(e,p.el),a&&Bo(a,o),(t=n.props&&n.props.onVnodeUpdated)&&Bo((()=>Ti(t,s,n,c)),o)}else{let l;const{el:a,props:s}=t,{bm:c,m:u,parent:f}=e,p=vr(t);if($o(e,!1),c&&re(c),!p&&(l=s&&s.onVnodeBeforeMount)&&Ti(l,f,t),$o(e,!0),a&&ee){const n=()=>{e.subTree=Mn(e),ee(a,e.subTree,e,o,null)};p?t.type.__asyncLoader().then((()=>!e.isUnmounted&&n())):n()}else{0;const l=e.subTree=Mn(e);0,m(null,l,n,r,e,o,i),t.el=l.el}if(u&&Bo(u,o),!p&&(l=s&&s.onVnodeMounted)){const e=t;Bo((()=>Ti(l,f,e)),o)}(256&t.shapeFlag||f&&vr(f.vnode)&&256&f.vnode.shapeFlag)&&e.a&&Bo(e.a,o),e.isMounted=!0,t=n=r=null}}),(()=>hn(s)),e.scope),s=e.update=()=>a.run();s.id=e.uid,$o(e,!0),s()},B=(e,t,n)=>{t.component=e;const r=e.vnode.props;e.vnode=t,e.next=null,function(e,t,n,r){const{props:o,attrs:i,vnode:{patchFlag:l}}=e,a=At(o),[s]=e.propsOptions;let c=!1;if(!(r||l>0)||16&l){let r;go(e,t,o,i)&&(c=!0);for(const i in a)t&&(I(t,i)||(r=Q(i))!==i&&I(t,r))||(s?!n||void 0===n[i]&&void 0===n[r]||(o[i]=yo(s,a,i,void 0,e,!0)):delete o[i]);if(i!==a)for(const e in i)t&&I(t,e)||(delete i[e],c=!0)}else if(8&l){const n=e.vnode.dynamicProps;for(let r=0;r{const{vnode:r,slots:o}=e;let i=!0,l=k;if(32&r.shapeFlag){const e=t._;e?n&&1===e?i=!1:(O(o,t),n||1!==e||delete o._):(i=!t.$stable,To(t,o)),l=t}else t&&(No(e,t),l={default:1});if(i)for(const e in o)So(e)||e in l||delete o[e]})(e,t.children,n),Ne(),gn(),Le()},j=(e,t,n,r,o,i,l,a,s=!1)=>{const c=e&&e.children,f=e?e.shapeFlag:0,p=t.children,{patchFlag:d,shapeFlag:h}=t;if(d>0){if(128&d)return void D(c,p,n,r,o,i,l,a,s);if(256&d)return void V(c,p,n,r,o,i,l,a,s)}8&h?(16&f&&G(c,o,i),p!==c&&u(n,p)):16&f?16&h?D(c,p,n,r,o,i,l,a,s):G(c,o,i,!0):(8&f&&u(n,""),16&h&&C(p,n,r,o,i,l,a,s))},V=(e,t,n,r,o,i,l,a,s)=>{t=t||S;const c=(e=e||S).length,u=t.length,f=Math.min(c,u);let p;for(p=0;pu?G(e,o,i,!0,!1,f):C(t,n,r,o,i,l,a,s,f)},D=(e,t,n,r,o,i,l,a,s)=>{let c=0;const u=t.length;let f=e.length-1,p=u-1;for(;c<=f&&c<=p;){const r=e[c],u=t[c]=s?Si(t[c]):ki(t[c]);if(!ui(r,u))break;m(r,u,n,null,o,i,l,a,s),c++}for(;c<=f&&c<=p;){const r=e[f],c=t[p]=s?Si(t[p]):ki(t[p]);if(!ui(r,c))break;m(r,c,n,null,o,i,l,a,s),f--,p--}if(c>f){if(c<=p){const e=p+1,f=ep)for(;c<=f;)U(e[c],o,i,!0),c++;else{const d=c,h=c,v=new Map;for(c=h;c<=p;c++){const e=t[c]=s?Si(t[c]):ki(t[c]);null!=e.key&&v.set(e.key,c)}let g,y=0;const _=p-h+1;let b=!1,w=0;const x=new Array(_);for(c=0;c<_;c++)x[c]=0;for(c=d;c<=f;c++){const r=e[c];if(y>=_){U(r,o,i,!0);continue}let u;if(null!=r.key)u=v.get(r.key);else for(g=h;g<=p;g++)if(0===x[g-h]&&ui(r,t[g])){u=g;break}void 0===u?U(r,o,i,!0):(x[u-h]=c+1,u>=w?w=u:b=!0,m(r,t[u],n,null,o,i,l,a,s),y++)}const k=b?function(e){const t=e.slice(),n=[0];let r,o,i,l,a;const s=e.length;for(r=0;r>1,e[n[a]]0&&(t[r]=n[i-1]),n[i]=r)}}i=n.length,l=n[i-1];for(;i-- >0;)n[i]=l,l=t[l];return n}(x):S;for(g=k.length-1,c=_-1;c>=0;c--){const e=h+c,f=t[e],p=e+1{const{el:l,type:a,transition:s,children:c,shapeFlag:u}=e;if(6&u)return void $(e.component.subTree,t,n,o);if(128&u)return void e.suspense.move(t,n,o);if(64&u)return void a.move(e,t,n,Y);if(a===Ko){r(l,t,n);for(let e=0;e{let i;for(;e&&e!==t;)i=p(e),r(e,n,o),e=i;r(t,n,o)})(e,t,n);if(2!==o&&1&u&&s)if(0===o)s.beforeEnter(l),r(l,t,n),Bo((()=>s.enter(l)),i);else{const{leave:e,delayLeave:o,afterLeave:i}=s,a=()=>r(l,t,n),c=()=>{e(l,(()=>{a(),i&&i()}))};o?o(l,a,c):c()}else r(l,t,n)},U=(e,t,n,r=!1,o=!1)=>{const{type:i,props:l,ref:a,children:s,dynamicChildren:c,shapeFlag:u,patchFlag:f,dirs:p}=e;if(null!=a&&Po(a,null,n,e,!0),256&u)return void t.ctx.deactivate(e);const d=1&u&&p,h=!vr(e);let m;if(h&&(m=l&&l.onVnodeBeforeUnmount)&&Ti(m,t,e),6&u)z(e.component,n,r);else{if(128&u)return void e.suspense.unmount(n,r);d&&$r(e,null,t,"beforeUnmount"),64&u?e.type.remove(e,t,n,o,Y,r):c&&(i!==Ko||f>0&&64&f)?G(c,t,n,!1,!0):(i===Ko&&384&f||!o&&16&u)&&G(s,t,n),r&&W(e)}(h&&(m=l&&l.onVnodeUnmounted)||d)&&Bo((()=>{m&&Ti(m,t,e),d&&$r(e,null,t,"unmounted")}),n)},W=e=>{const{type:t,el:n,anchor:r,transition:i}=e;if(t===Ko)return void H(n,r);if(t===Xo)return void _(e);const l=()=>{o(n),i&&!i.persisted&&i.afterLeave&&i.afterLeave()};if(1&e.shapeFlag&&i&&!i.persisted){const{leave:t,delayLeave:r}=i,o=()=>t(n,l);r?r(e.el,l,o):o()}else l()},H=(e,t)=>{let n;for(;e!==t;)n=p(e),o(e),e=n;o(t)},z=(e,t,n)=>{const{bum:r,scope:o,update:i,subTree:l,um:a}=e;r&&re(r),o.stop(),i&&(i.active=!1,U(l,e,t,n)),a&&Bo(a,t),Bo((()=>{e.isUnmounted=!0}),t),t&&t.pendingBranch&&!t.isUnmounted&&e.asyncDep&&!e.asyncResolved&&e.suspenseId===t.pendingId&&(t.deps--,0===t.deps&&t.resolve())},G=(e,t,n,r=!1,o=!1,i=0)=>{for(let l=i;l6&e.shapeFlag?J(e.component.subTree):128&e.shapeFlag?e.suspense.next():p(e.anchor||e.el),K=(e,t,n)=>{null==e?t._vnode&&U(t._vnode,null,null,!0):m(t._vnode||null,e,t,null,null,null,n),gn(),yn(),t._vnode=e},Y={p:m,um:U,m:$,r:W,mt:R,mc:C,pc:j,pbc:N,n:J,o:e};let X,ee;return t&&([X,ee]=t(Y)),{render:K,hydrate:X,createApp:Ao(K,X)}}function $o({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function Uo(e,t,n=!1){const r=e.children,o=t.children;if(R(r)&&R(o))for(let e=0;ee&&(e.disabled||""===e.disabled),Ho=e=>"undefined"!=typeof SVGElement&&e instanceof SVGElement,zo=(e,t)=>{const n=e&&e.to;if(V(n)){if(t){const e=t(n);return e}return null}return n};function Go(e,t,n,{o:{insert:r},m:o},i=2){0===i&&r(e.targetAnchor,t,n);const{el:l,anchor:a,shapeFlag:s,children:c,props:u}=e,f=2===i;if(f&&r(l,t,n),(!f||Wo(u))&&16&s)for(let e=0;e{16&y&&u(_,e,t,o,i,l,a,s)};g?v(n,c):f&&v(f,p)}else{t.el=e.el;const r=t.anchor=e.anchor,u=t.target=e.target,d=t.targetAnchor=e.targetAnchor,m=Wo(e.props),v=m?n:u,y=m?r:d;if(l=l||Ho(u),b?(p(e.dynamicChildren,b,v,o,i,l,a),Uo(e,t,!0)):s||f(e,t,v,y,o,i,l,a,!1),g)m||Go(t,n,r,c,1);else if((t.props&&t.props.to)!==(e.props&&e.props.to)){const e=t.target=zo(t.props,h);e&&Go(t,e,null,c,0)}else m&&Go(t,u,d,c,1)}Jo(t)},remove(e,t,n,r,{um:o,o:{remove:i}},l){const{shapeFlag:a,children:s,anchor:c,targetAnchor:u,target:f,props:p}=e;if(f&&i(u),(l||!Wo(p))&&(i(c),16&a))for(let e=0;e0?ei||S:null,ni(),oi>0&&ei&&ei.push(e),e}function ai(e,t,n,r,o,i){return li(mi(e,t,n,r,o,i,!0))}function si(e,t,n,r,o){return li(vi(e,t,n,r,o,!0))}function ci(e){return!!e&&!0===e.__v_isVNode}function ui(e,t){return e.type===t.type&&e.key===t.key}function fi(e){ri=e}const pi="__vInternal",di=({key:e})=>null!=e?e:null,hi=({ref:e,ref_key:t,ref_for:n})=>null!=e?V(e)||Bt(e)||j(e)?{i:Ln,r:e,k:t,f:!!n}:e:null;function mi(e,t=null,n=null,r=0,o=null,i=(e===Ko?0:1),l=!1,a=!1){const s={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&di(t),ref:t&&hi(t),scopeId:On,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:i,patchFlag:r,dynamicProps:o,dynamicChildren:null,appContext:null,ctx:Ln};return a?(Ei(s,n),128&i&&e.normalize(s)):n&&(s.shapeFlag|=V(n)?8:16),oi>0&&!l&&ei&&(s.patchFlag>0||6&i)&&32!==s.patchFlag&&ei.push(s),s}const vi=gi;function gi(e,t=null,n=null,r=0,o=null,i=!1){if(e&&e!==Hr||(e=Zo),ci(e)){const r=_i(e,t,!0);return n&&Ei(r,n),oi>0&&!i&&ei&&(6&r.shapeFlag?ei[ei.indexOf(e)]=r:ei.push(r)),r.patchFlag|=-2,r}if(qi(e)&&(e=e.__vccOpts),t){t=yi(t);let{class:e,style:n}=t;e&&!V(e)&&(t.class=f(e)),$(n)&&(Ot(n)&&!R(n)&&(n=O({},n)),t.style=l(n))}return mi(e,t,n,r,o,V(e)?1:Un(e)?128:(e=>e.__isTeleport)(e)?64:$(e)?4:j(e)?2:0,i,!0)}function yi(e){return e?Ot(e)||pi in e?O({},e):e:null}function _i(e,t,n=!1){const{props:r,ref:o,patchFlag:i,children:l}=e,a=t?Ci(r||{},t):r;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:a,key:a&&di(a),ref:t&&t.ref?n&&o?R(o)?o.concat(hi(t)):[o,hi(t)]:hi(t):o,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:l,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==Ko?-1===i?16:16|i:i,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&_i(e.ssContent),ssFallback:e.ssFallback&&_i(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx}}function bi(e=" ",t=0){return vi(Yo,null,e,t)}function wi(e,t){const n=vi(Xo,null,e);return n.staticCount=t,n}function xi(e="",t=!1){return t?(ti(),si(Zo,null,e)):vi(Zo,null,e)}function ki(e){return null==e||"boolean"==typeof e?vi(Zo):R(e)?vi(Ko,null,e.slice()):"object"==typeof e?Si(e):vi(Yo,null,String(e))}function Si(e){return null===e.el&&-1!==e.patchFlag||e.memo?e:_i(e)}function Ei(e,t){let n=0;const{shapeFlag:r}=e;if(null==t)t=null;else if(R(t))n=16;else if("object"==typeof t){if(65&r){const n=t.default;return void(n&&(n._c&&(n._d=!1),Ei(e,n()),n._c&&(n._d=!0)))}{n=32;const r=t._;r||pi in t?3===r&&Ln&&(1===Ln.slots._?t._=1:(t._=2,e.patchFlag|=1024)):t._ctx=Ln}}else j(t)?(t={default:t,_ctx:Ln},n=32):(t=String(t),64&r?(n=16,t=[bi(t)]):n=8);e.children=t,e.shapeFlag|=n}function Ci(...e){const t={};for(let n=0;nAi||Ln,Ii=e=>{Ai=e,e.scope.on()},Ri=()=>{Ai&&Ai.scope.off(),Ai=null};function Fi(e){return 4&e.vnode.shapeFlag}let Mi,Bi,ji=!1;function Vi(e,t=!1){ji=t;const{props:n,children:r}=e.vnode,o=Fi(e);!function(e,t,n,r=!1){const o={},i={};oe(i,pi,1),e.propsDefaults=Object.create(null),go(e,t,o,i);for(const t in e.propsOptions[0])t in o||(o[t]=void 0);n?e.props=r?o:kt(o):e.type.props?e.props=o:e.props=i,e.attrs=i}(e,n,o,t),((e,t)=>{if(32&e.vnode.shapeFlag){const n=t._;n?(e.slots=At(t),oe(t,"_",n)):To(t,e.slots={})}else e.slots={},t&&No(e,t);oe(e.slots,pi,1)})(e,r);const i=o?function(e,t){const n=e.type;0;e.accessCache=Object.create(null),e.proxy=Pt(new Proxy(e.ctx,ro)),!1;const{setup:r}=n;if(r){const n=e.setupContext=r.length>1?Hi(e):null;Ii(e),Ne();const o=en(r,e,0,[e.props,n]);if(Le(),Ri(),U(o)){if(o.then(Ri,Ri),t)return o.then((n=>{Di(e,n,t)})).catch((t=>{nn(t,e,0)}));e.asyncDep=o}else Di(e,o,t)}else Wi(e,t)}(e,t):void 0;return ji=!1,i}function Di(e,t,n){j(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:$(t)&&(e.setupState=zt(t)),Wi(e,n)}function $i(e){Mi=e,Bi=e=>{e.render._rc&&(e.withProxy=new Proxy(e.ctx,oo))}}const Ui=()=>!Mi;function Wi(e,t,n){const r=e.type;if(!e.render){if(!t&&Mi&&!r.render){const t=r.template||co(e).template;if(t){0;const{isCustomElement:n,compilerOptions:o}=e.appContext.config,{delimiters:i,compilerOptions:l}=r,a=O(O({isCustomElement:n,delimiters:i},o),l);r.render=Mi(t,a)}}e.render=r.render||E,Bi&&Bi(e)}Ii(e),Ne(),lo(e),Le(),Ri()}function Hi(e){const t=t=>{e.exposed=t||{}};let n;return{get attrs(){return n||(n=function(e){return new Proxy(e.attrs,{get:(t,n)=>(Oe(e,0,"$attrs"),t[n])})}(e))},slots:e.slots,emit:e.emit,expose:t}}function zi(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(zt(Pt(e.exposed)),{get:(t,n)=>n in t?t[n]:n in to?to[n](e):void 0,has:(e,t)=>t in e||t in to}))}function Gi(e,t=!0){return j(e)?e.displayName||e.name:e.name||t&&e.__name}function qi(e){return j(e)&&"__vccOpts"in e}const Ji=(e,t)=>function(e,t,n=!1){let r,o;const i=j(e);return i?(r=e,o=E):(r=e.get,o=e.set),new Xt(r,o,i||!o,n)}(e,0,ji);function Ki(){return null}function Yi(){return null}function Zi(e){0}function Xi(e,t){return null}function Qi(){return tl().slots}function el(){return tl().attrs}function tl(){const e=Pi();return e.setupContext||(e.setupContext=Hi(e))}function nl(e,t){const n=R(e)?e.reduce(((e,t)=>(e[t]={},e)),{}):e;for(const e in t){const r=n[e];r?R(r)||j(r)?n[e]={type:r,default:t[e]}:r.default=t[e]:null===r&&(n[e]={default:t[e]})}return n}function rl(e,t){const n={};for(const r in e)t.includes(r)||Object.defineProperty(n,r,{enumerable:!0,get:()=>e[r]});return n}function ol(e){const t=Pi();let n=e();return Ri(),U(n)&&(n=n.catch((e=>{throw Ii(t),e}))),[n,()=>Ii(t)]}function il(e,t,n){const r=arguments.length;return 2===r?$(t)&&!R(t)?ci(t)?vi(e,null,[t]):vi(e,t):vi(e,null,t):(r>3?n=Array.prototype.slice.call(arguments,2):3===r&&ci(n)&&(n=[n]),vi(e,t,n))}const ll=Symbol(""),al=()=>{{const e=Yn(ll);return e}};function sl(){return void 0}function cl(e,t,n,r){const o=n[r];if(o&&ul(o,e))return o;const i=t();return i.memo=e.slice(),n[r]=i}function ul(e,t){const n=e.memo;if(n.length!=t.length)return!1;for(let e=0;e0&&ei&&ei.push(e),!0}const fl="3.2.45",pl={createComponentInstance:Oi,setupComponent:Vi,renderComponentRoot:Mn,setCurrentRenderingInstance:An,isVNode:ci,normalizeVNode:ki},dl=null,hl=null,ml="undefined"!=typeof document?document:null,vl=ml&&ml.createElement("template"),gl={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const o=t?ml.createElementNS("http://www.w3.org/2000/svg",e):ml.createElement(e,n?{is:n}:void 0);return"select"===e&&r&&null!=r.multiple&&o.setAttribute("multiple",r.multiple),o},createText:e=>ml.createTextNode(e),createComment:e=>ml.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>ml.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,o,i){const l=n?n.previousSibling:t.lastChild;if(o&&(o===i||o.nextSibling))for(;t.insertBefore(o.cloneNode(!0),n),o!==i&&(o=o.nextSibling););else{vl.innerHTML=r?`${e}`:e;const o=vl.content;if(r){const e=o.firstChild;for(;e.firstChild;)o.appendChild(e.firstChild);o.removeChild(e)}t.insertBefore(o,n)}return[l?l.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}};const yl=/\s*!important$/;function _l(e,t,n){if(R(n))n.forEach((n=>_l(e,t,n)));else if(null==n&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const r=function(e,t){const n=wl[t];if(n)return n;let r=Z(t);if("filter"!==r&&r in e)return wl[t]=r;r=ee(r);for(let n=0;n{if(e._vts){if(e._vts<=n.attached)return}else e._vts=Date.now();tn(function(e,t){if(R(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map((e=>t=>!t._stopped&&e&&e(t)))}return t}(e,n.value),t,5,[e])};return n.value=e,n.attached=(()=>Cl||(Tl.then((()=>Cl=0)),Cl=Date.now()))(),n}(r,o);kl(e,n,l,a)}else l&&(!function(e,t,n,r){e.removeEventListener(t,n,r)}(e,n,l,a),i[t]=void 0)}}const El=/(?:Once|Passive|Capture)$/;let Cl=0;const Tl=Promise.resolve();const Nl=/^on[a-z]/;function Ll(e,t){const n=mr(e);class r extends Pl{constructor(e){super(n,e,t)}}return r.def=n,r}const Ol=e=>Ll(e,Ra),Al="undefined"!=typeof HTMLElement?HTMLElement:class{};class Pl extends Al{constructor(e,t={},n){super(),this._def=e,this._props=t,this._instance=null,this._connected=!1,this._resolved=!1,this._numberProps=null,this.shadowRoot&&n?n(this._createVNode(),this.shadowRoot):(this.attachShadow({mode:"open"}),this._def.__asyncLoader||this._resolveProps(this._def))}connectedCallback(){this._connected=!0,this._instance||(this._resolved?this._update():this._resolveDef())}disconnectedCallback(){this._connected=!1,dn((()=>{this._connected||(Ia(null,this.shadowRoot),this._instance=null)}))}_resolveDef(){this._resolved=!0;for(let e=0;e{for(const t of e)this._setAttr(t.attributeName)})).observe(this,{attributes:!0});const e=(e,t=!1)=>{const{props:n,styles:r}=e;let o;if(n&&!R(n))for(const e in n){const t=n[e];(t===Number||t&&t.type===Number)&&(e in this._props&&(this._props[e]=ie(this._props[e])),(o||(o=Object.create(null)))[Z(e)]=!0)}this._numberProps=o,t&&this._resolveProps(e),this._applyStyles(r),this._update()},t=this._def.__asyncLoader;t?t().then((t=>e(t,!0))):e(this._def)}_resolveProps(e){const{props:t}=e,n=R(t)?t:Object.keys(t||{});for(const e of Object.keys(this))"_"!==e[0]&&n.includes(e)&&this._setProp(e,this[e],!0,!1);for(const e of n.map(Z))Object.defineProperty(this,e,{get(){return this._getProp(e)},set(t){this._setProp(e,t)}})}_setAttr(e){let t=this.getAttribute(e);const n=Z(e);this._numberProps&&this._numberProps[n]&&(t=ie(t)),this._setProp(n,t,!1)}_getProp(e){return this._props[e]}_setProp(e,t,n=!0,r=!0){t!==this._props[e]&&(this._props[e]=t,r&&this._instance&&this._update(),n&&(!0===t?this.setAttribute(Q(e),""):"string"==typeof t||"number"==typeof t?this.setAttribute(Q(e),t+""):t||this.removeAttribute(Q(e))))}_update(){Ia(this._createVNode(),this.shadowRoot)}_createVNode(){const e=vi(this._def,O({},this._props));return this._instance||(e.ce=e=>{this._instance=e,e.isCE=!0;const t=(e,t)=>{this.dispatchEvent(new CustomEvent(e,{detail:t}))};e.emit=(e,...n)=>{t(e,n),Q(e)!==e&&t(Q(e),n)};let n=this;for(;n=n&&(n.parentNode||n.host);)if(n instanceof Pl){e.parent=n._instance,e.provides=n._instance.provides;break}}),e}_applyStyles(e){e&&e.forEach((e=>{const t=document.createElement("style");t.textContent=e,this.shadowRoot.appendChild(t)}))}}function Il(e="$style"){{const t=Pi();if(!t)return k;const n=t.type.__cssModules;if(!n)return k;const r=n[e];return r||k}}function Rl(e){const t=Pi();if(!t)return;const n=t.ut=(n=e(t.proxy))=>{Array.from(document.querySelectorAll(`[data-v-owner="${t.uid}"]`)).forEach((e=>Ml(e,n)))},r=()=>{const r=e(t.proxy);Fl(t.subTree,r),n(r)};Xn(r),Ar((()=>{const e=new MutationObserver(r);e.observe(t.subTree.el.parentNode,{childList:!0}),Fr((()=>e.disconnect()))}))}function Fl(e,t){if(128&e.shapeFlag){const n=e.suspense;e=n.activeBranch,n.pendingBranch&&!n.isHydrating&&n.effects.push((()=>{Fl(n.activeBranch,t)}))}for(;e.component;)e=e.component.subTree;if(1&e.shapeFlag&&e.el)Ml(e.el,t);else if(e.type===Ko)e.children.forEach((e=>Fl(e,t)));else if(e.type===Xo){let{el:n,anchor:r}=e;for(;n&&(Ml(n,t),n!==r);)n=n.nextSibling}}function Ml(e,t){if(1===e.nodeType){const n=e.style;for(const e in t)n.setProperty(`--${e}`,t[e])}}const Bl="transition",jl="animation",Vl=(e,{slots:t})=>il(sr,Hl(e),t);Vl.displayName="Transition";const Dl={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},$l=Vl.props=O({},sr.props,Dl),Ul=(e,t=[])=>{R(e)?e.forEach((e=>e(...t))):e&&e(...t)},Wl=e=>!!e&&(R(e)?e.some((e=>e.length>1)):e.length>1);function Hl(e){const t={};for(const n in e)n in Dl||(t[n]=e[n]);if(!1===e.css)return t;const{name:n="v",type:r,duration:o,enterFromClass:i=`${n}-enter-from`,enterActiveClass:l=`${n}-enter-active`,enterToClass:a=`${n}-enter-to`,appearFromClass:s=i,appearActiveClass:c=l,appearToClass:u=a,leaveFromClass:f=`${n}-leave-from`,leaveActiveClass:p=`${n}-leave-active`,leaveToClass:d=`${n}-leave-to`}=e,h=function(e){if(null==e)return null;if($(e))return[zl(e.enter),zl(e.leave)];{const t=zl(e);return[t,t]}}(o),m=h&&h[0],v=h&&h[1],{onBeforeEnter:g,onEnter:y,onEnterCancelled:_,onLeave:b,onLeaveCancelled:w,onBeforeAppear:x=g,onAppear:k=y,onAppearCancelled:S=_}=t,E=(e,t,n)=>{ql(e,t?u:a),ql(e,t?c:l),n&&n()},C=(e,t)=>{e._isLeaving=!1,ql(e,f),ql(e,d),ql(e,p),t&&t()},T=e=>(t,n)=>{const o=e?k:y,l=()=>E(t,e,n);Ul(o,[t,l]),Jl((()=>{ql(t,e?s:i),Gl(t,e?u:a),Wl(o)||Yl(t,r,m,l)}))};return O(t,{onBeforeEnter(e){Ul(g,[e]),Gl(e,i),Gl(e,l)},onBeforeAppear(e){Ul(x,[e]),Gl(e,s),Gl(e,c)},onEnter:T(!1),onAppear:T(!0),onLeave(e,t){e._isLeaving=!0;const n=()=>C(e,t);Gl(e,f),ea(),Gl(e,p),Jl((()=>{e._isLeaving&&(ql(e,f),Gl(e,d),Wl(b)||Yl(e,r,v,n))})),Ul(b,[e,n])},onEnterCancelled(e){E(e,!1),Ul(_,[e])},onAppearCancelled(e){E(e,!0),Ul(S,[e])},onLeaveCancelled(e){C(e),Ul(w,[e])}})}function zl(e){return ie(e)}function Gl(e,t){t.split(/\s+/).forEach((t=>t&&e.classList.add(t))),(e._vtc||(e._vtc=new Set)).add(t)}function ql(e,t){t.split(/\s+/).forEach((t=>t&&e.classList.remove(t)));const{_vtc:n}=e;n&&(n.delete(t),n.size||(e._vtc=void 0))}function Jl(e){requestAnimationFrame((()=>{requestAnimationFrame(e)}))}let Kl=0;function Yl(e,t,n,r){const o=e._endId=++Kl,i=()=>{o===e._endId&&r()};if(n)return setTimeout(i,n);const{type:l,timeout:a,propCount:s}=Zl(e,t);if(!l)return r();const c=l+"end";let u=0;const f=()=>{e.removeEventListener(c,p),i()},p=t=>{t.target===e&&++u>=s&&f()};setTimeout((()=>{u(n[e]||"").split(", "),o=r("transitionDelay"),i=r("transitionDuration"),l=Xl(o,i),a=r("animationDelay"),s=r("animationDuration"),c=Xl(a,s);let u=null,f=0,p=0;t===Bl?l>0&&(u=Bl,f=l,p=i.length):t===jl?c>0&&(u=jl,f=c,p=s.length):(f=Math.max(l,c),u=f>0?l>c?Bl:jl:null,p=u?u===Bl?i.length:s.length:0);return{type:u,timeout:f,propCount:p,hasTransform:u===Bl&&/\b(transform|all)(,|$)/.test(r("transitionProperty").toString())}}function Xl(e,t){for(;e.lengthQl(t)+Ql(e[n]))))}function Ql(e){return 1e3*Number(e.slice(0,-1).replace(",","."))}function ea(){return document.body.offsetHeight}const ta=new WeakMap,na=new WeakMap,ra={name:"TransitionGroup",props:O({},$l,{tag:String,moveClass:String}),setup(e,{slots:t}){const n=Pi(),r=lr();let o,i;return Ir((()=>{if(!o.length)return;const t=e.moveClass||`${e.name||"v"}-move`;if(!function(e,t,n){const r=e.cloneNode();e._vtc&&e._vtc.forEach((e=>{e.split(/\s+/).forEach((e=>e&&r.classList.remove(e)))}));n.split(/\s+/).forEach((e=>e&&r.classList.add(e))),r.style.display="none";const o=1===t.nodeType?t:t.parentNode;o.appendChild(r);const{hasTransform:i}=Zl(r);return o.removeChild(r),i}(o[0].el,n.vnode.el,t))return;o.forEach(oa),o.forEach(ia);const r=o.filter(la);ea(),r.forEach((e=>{const n=e.el,r=n.style;Gl(n,t),r.transform=r.webkitTransform=r.transitionDuration="";const o=n._moveCb=e=>{e&&e.target!==n||e&&!/transform$/.test(e.propertyName)||(n.removeEventListener("transitionend",o),n._moveCb=null,ql(n,t))};n.addEventListener("transitionend",o)}))})),()=>{const l=At(e),a=Hl(l);let s=l.tag||Ko;o=i,i=t.default?hr(t.default()):[];for(let e=0;e{const t=e.props["onUpdate:modelValue"]||!1;return R(t)?e=>re(t,e):t};function sa(e){e.target.composing=!0}function ca(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const ua={created(e,{modifiers:{lazy:t,trim:n,number:r}},o){e._assign=aa(o);const i=r||o.props&&"number"===o.props.type;kl(e,t?"change":"input",(t=>{if(t.target.composing)return;let r=e.value;n&&(r=r.trim()),i&&(r=ie(r)),e._assign(r)})),n&&kl(e,"change",(()=>{e.value=e.value.trim()})),t||(kl(e,"compositionstart",sa),kl(e,"compositionend",ca),kl(e,"change",ca))},mounted(e,{value:t}){e.value=null==t?"":t},beforeUpdate(e,{value:t,modifiers:{lazy:n,trim:r,number:o}},i){if(e._assign=aa(i),e.composing)return;if(document.activeElement===e&&"range"!==e.type){if(n)return;if(r&&e.value.trim()===t)return;if((o||"number"===e.type)&&ie(e.value)===t)return}const l=null==t?"":t;e.value!==l&&(e.value=l)}},fa={deep:!0,created(e,t,n){e._assign=aa(n),kl(e,"change",(()=>{const t=e._modelValue,n=va(e),r=e.checked,o=e._assign;if(R(t)){const e=b(t,n),i=-1!==e;if(r&&!i)o(t.concat(n));else if(!r&&i){const n=[...t];n.splice(e,1),o(n)}}else if(M(t)){const e=new Set(t);r?e.add(n):e.delete(n),o(e)}else o(ga(e,r))}))},mounted:pa,beforeUpdate(e,t,n){e._assign=aa(n),pa(e,t,n)}};function pa(e,{value:t,oldValue:n},r){e._modelValue=t,R(t)?e.checked=b(t,r.props.value)>-1:M(t)?e.checked=t.has(r.props.value):t!==n&&(e.checked=_(t,ga(e,!0)))}const da={created(e,{value:t},n){e.checked=_(t,n.props.value),e._assign=aa(n),kl(e,"change",(()=>{e._assign(va(e))}))},beforeUpdate(e,{value:t,oldValue:n},r){e._assign=aa(r),t!==n&&(e.checked=_(t,r.props.value))}},ha={deep:!0,created(e,{value:t,modifiers:{number:n}},r){const o=M(t);kl(e,"change",(()=>{const t=Array.prototype.filter.call(e.options,(e=>e.selected)).map((e=>n?ie(va(e)):va(e)));e._assign(e.multiple?o?new Set(t):t:t[0])})),e._assign=aa(r)},mounted(e,{value:t}){ma(e,t)},beforeUpdate(e,t,n){e._assign=aa(n)},updated(e,{value:t}){ma(e,t)}};function ma(e,t){const n=e.multiple;if(!n||R(t)||M(t)){for(let r=0,o=e.options.length;r-1:o.selected=t.has(i);else if(_(va(o),t))return void(e.selectedIndex!==r&&(e.selectedIndex=r))}n||-1===e.selectedIndex||(e.selectedIndex=-1)}}function va(e){return"_value"in e?e._value:e.value}function ga(e,t){const n=t?"_trueValue":"_falseValue";return n in e?e[n]:t}const ya={created(e,t,n){ba(e,t,n,null,"created")},mounted(e,t,n){ba(e,t,n,null,"mounted")},beforeUpdate(e,t,n,r){ba(e,t,n,r,"beforeUpdate")},updated(e,t,n,r){ba(e,t,n,r,"updated")}};function _a(e,t){switch(e){case"SELECT":return ha;case"TEXTAREA":return ua;default:switch(t){case"checkbox":return fa;case"radio":return da;default:return ua}}}function ba(e,t,n,r,o){const i=_a(e.tagName,n.props&&n.props.type)[o];i&&i(e,t,n,r)}const wa=["ctrl","shift","alt","meta"],xa={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&0!==e.button,middle:e=>"button"in e&&1!==e.button,right:e=>"button"in e&&2!==e.button,exact:(e,t)=>wa.some((n=>e[`${n}Key`]&&!t.includes(n)))},ka=(e,t)=>(n,...r)=>{for(let e=0;en=>{if(!("key"in n))return;const r=Q(n.key);return t.some((e=>e===r||Sa[e]===r))?e(n):void 0},Ca={beforeMount(e,{value:t},{transition:n}){e._vod="none"===e.style.display?"":e.style.display,n&&t?n.beforeEnter(e):Ta(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:r}){!t!=!n&&(r?t?(r.beforeEnter(e),Ta(e,!0),r.enter(e)):r.leave(e,(()=>{Ta(e,!1)})):Ta(e,t))},beforeUnmount(e,{value:t}){Ta(e,t)}};function Ta(e,t){e.style.display=t?e._vod:"none"}const Na=O({patchProp:(e,t,n,r,o=!1,i,l,a,s)=>{"class"===t?function(e,t,n){const r=e._vtc;r&&(t=(t?[t,...r]:[...r]).join(" ")),null==t?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}(e,r,o):"style"===t?function(e,t,n){const r=e.style,o=V(n);if(n&&!o){for(const e in n)_l(r,e,n[e]);if(t&&!V(t))for(const e in t)null==n[e]&&_l(r,e,"")}else{const i=r.display;o?t!==n&&(r.cssText=n):t&&e.removeAttribute("style"),"_vod"in e&&(r.display=i)}}(e,n,r):N(t)?L(t)||Sl(e,t,0,r,l):("."===t[0]?(t=t.slice(1),1):"^"===t[0]?(t=t.slice(1),0):function(e,t,n,r){if(r)return"innerHTML"===t||"textContent"===t||!!(t in e&&Nl.test(t)&&j(n));if("spellcheck"===t||"draggable"===t||"translate"===t)return!1;if("form"===t)return!1;if("list"===t&&"INPUT"===e.tagName)return!1;if("type"===t&&"TEXTAREA"===e.tagName)return!1;if(Nl.test(t)&&V(n))return!1;return t in e}(e,t,r,o))?function(e,t,n,r,o,i,l){if("innerHTML"===t||"textContent"===t)return r&&l(r,o,i),void(e[t]=null==n?"":n);if("value"===t&&"PROGRESS"!==e.tagName&&!e.tagName.includes("-")){e._value=n;const r=null==n?"":n;return e.value===r&&"OPTION"!==e.tagName||(e.value=r),void(null==n&&e.removeAttribute(t))}let a=!1;if(""===n||null==n){const r=typeof e[t];"boolean"===r?n=y(n):null==n&&"string"===r?(n="",a=!0):"number"===r&&(n=0,a=!0)}try{e[t]=n}catch(e){}a&&e.removeAttribute(t)}(e,t,r,i,l,a,s):("true-value"===t?e._trueValue=r:"false-value"===t&&(e._falseValue=r),function(e,t,n,r,o){if(r&&t.startsWith("xlink:"))null==n?e.removeAttributeNS(xl,t.slice(6,t.length)):e.setAttributeNS(xl,t,n);else{const r=g(t);null==n||r&&!y(n)?e.removeAttribute(t):e.setAttribute(t,r?"":n)}}(e,t,r,o))}},gl);let La,Oa=!1;function Aa(){return La||(La=jo(Na))}function Pa(){return La=Oa?La:Vo(Na),Oa=!0,La}const Ia=(...e)=>{Aa().render(...e)},Ra=(...e)=>{Pa().hydrate(...e)},Fa=(...e)=>{const t=Aa().createApp(...e);const{mount:n}=t;return t.mount=e=>{const r=Ba(e);if(!r)return;const o=t._component;j(o)||o.render||o.template||(o.template=r.innerHTML),r.innerHTML="";const i=n(r,!1,r instanceof SVGElement);return r instanceof Element&&(r.removeAttribute("v-cloak"),r.setAttribute("data-v-app","")),i},t},Ma=(...e)=>{const t=Pa().createApp(...e);const{mount:n}=t;return t.mount=e=>{const t=Ba(e);if(t)return n(t,!0,t instanceof SVGElement)},t};function Ba(e){if(V(e)){return document.querySelector(e)}return e}let ja=!1;const Va=()=>{ja||(ja=!0,ua.getSSRProps=({value:e})=>({value:e}),da.getSSRProps=({value:e},t)=>{if(t.props&&_(t.props.value,e))return{checked:!0}},fa.getSSRProps=({value:e},t)=>{if(R(e)){if(t.props&&b(e,t.props.value)>-1)return{checked:!0}}else if(M(e)){if(t.props&&e.has(t.props.value))return{checked:!0}}else if(e)return{checked:!0}},ya.getSSRProps=(e,t)=>{if("string"!=typeof t.type)return;const n=_a(t.type.toUpperCase(),t.props&&t.props.type);return n.getSSRProps?n.getSSRProps(e,t):void 0},Ca.getSSRProps=({value:e})=>{if(!e)return{style:{display:"none"}}})};function Da(e){throw e}function $a(e){}function Ua(e,t,n,r){const o=new SyntaxError(String(e));return o.code=e,o.loc=t,o}const Wa=Symbol(""),Ha=Symbol(""),za=Symbol(""),Ga=Symbol(""),qa=Symbol(""),Ja=Symbol(""),Ka=Symbol(""),Ya=Symbol(""),Za=Symbol(""),Xa=Symbol(""),Qa=Symbol(""),es=Symbol(""),ts=Symbol(""),ns=Symbol(""),rs=Symbol(""),os=Symbol(""),is=Symbol(""),ls=Symbol(""),as=Symbol(""),ss=Symbol(""),cs=Symbol(""),us=Symbol(""),fs=Symbol(""),ps=Symbol(""),ds=Symbol(""),hs=Symbol(""),ms=Symbol(""),vs=Symbol(""),gs=Symbol(""),ys=Symbol(""),_s=Symbol(""),bs=Symbol(""),ws=Symbol(""),xs=Symbol(""),ks=Symbol(""),Ss=Symbol(""),Es=Symbol(""),Cs=Symbol(""),Ts=Symbol(""),Ns={[Wa]:"Fragment",[Ha]:"Teleport",[za]:"Suspense",[Ga]:"KeepAlive",[qa]:"BaseTransition",[Ja]:"openBlock",[Ka]:"createBlock",[Ya]:"createElementBlock",[Za]:"createVNode",[Xa]:"createElementVNode",[Qa]:"createCommentVNode",[es]:"createTextVNode",[ts]:"createStaticVNode",[ns]:"resolveComponent",[rs]:"resolveDynamicComponent",[os]:"resolveDirective",[is]:"resolveFilter",[ls]:"withDirectives",[as]:"renderList",[ss]:"renderSlot",[cs]:"createSlots",[us]:"toDisplayString",[fs]:"mergeProps",[ps]:"normalizeClass",[ds]:"normalizeStyle",[hs]:"normalizeProps",[ms]:"guardReactiveProps",[vs]:"toHandlers",[gs]:"camelize",[ys]:"capitalize",[_s]:"toHandlerKey",[bs]:"setBlockTracking",[ws]:"pushScopeId",[xs]:"popScopeId",[ks]:"withCtx",[Ss]:"unref",[Es]:"isRef",[Cs]:"withMemo",[Ts]:"isMemoSame"};const Ls={source:"",start:{line:1,column:1,offset:0},end:{line:1,column:1,offset:0}};function Os(e,t,n,r,o,i,l,a=!1,s=!1,c=!1,u=Ls){return e&&(a?(e.helper(Ja),e.helper(ic(e.inSSR,c))):e.helper(oc(e.inSSR,c)),l&&e.helper(ls)),{type:13,tag:t,props:n,children:r,patchFlag:o,dynamicProps:i,directives:l,isBlock:a,disableTracking:s,isComponent:c,loc:u}}function As(e,t=Ls){return{type:17,loc:t,elements:e}}function Ps(e,t=Ls){return{type:15,loc:t,properties:e}}function Is(e,t){return{type:16,loc:Ls,key:V(e)?Rs(e,!0):e,value:t}}function Rs(e,t=!1,n=Ls,r=0){return{type:4,loc:n,content:e,isStatic:t,constType:t?3:r}}function Fs(e,t=Ls){return{type:8,loc:t,children:e}}function Ms(e,t=[],n=Ls){return{type:14,loc:n,callee:e,arguments:t}}function Bs(e,t,n=!1,r=!1,o=Ls){return{type:18,params:e,returns:t,newline:n,isSlot:r,loc:o}}function js(e,t,n,r=!0){return{type:19,test:e,consequent:t,alternate:n,newline:r,loc:Ls}}const Vs=e=>4===e.type&&e.isStatic,Ds=(e,t)=>e===t||e===Q(t);function $s(e){return Ds(e,"Teleport")?Ha:Ds(e,"Suspense")?za:Ds(e,"KeepAlive")?Ga:Ds(e,"BaseTransition")?qa:void 0}const Us=/^\d|[^\$\w]/,Ws=e=>!Us.test(e),Hs=/[A-Za-z_$\xA0-\uFFFF]/,zs=/[\.\?\w$\xA0-\uFFFF]/,Gs=/\s+[.[]\s*|\s*[.[]\s+/g,qs=e=>{e=e.trim().replace(Gs,(e=>e.trim()));let t=0,n=[],r=0,o=0,i=null;for(let l=0;l4===e.key.type&&e.key.content===r))}return n}function uc(e,t){return`_${t}_${e.replace(/[^\w]/g,((t,n)=>"-"===t?"_":e.charCodeAt(n).toString()))}`}function fc(e,{helper:t,removeHelper:n,inSSR:r}){e.isBlock||(e.isBlock=!0,n(oc(r,e.isComponent)),t(Ja),t(ic(r,e.isComponent)))}function pc(e,t){const n=t.options?t.options.compatConfig:t.compatConfig,r=n&&n[e];return"MODE"===e?r||3:r}function dc(e,t){const n=pc("MODE",t),r=pc(e,t);return 3===n?!0===r:!1!==r}function hc(e,t,n,...r){return dc(e,t)}const mc=/&(gt|lt|amp|apos|quot);/g,vc={gt:">",lt:"<",amp:"&",apos:"'",quot:'"'},gc={delimiters:["{{","}}"],getNamespace:()=>0,getTextMode:()=>0,isVoidTag:C,isPreTag:C,isCustomElement:C,decodeEntities:e=>e.replace(mc,((e,t)=>vc[t])),onError:Da,onWarn:$a,comments:!1};function yc(e,t={}){const n=function(e,t){const n=O({},gc);let r;for(r in t)n[r]=void 0===t[r]?gc[r]:t[r];return{options:n,column:1,line:1,offset:0,originalSource:e,source:e,inPre:!1,inVPre:!1,onWarn:n.onWarn}}(e,t),r=Pc(n);return function(e,t=Ls){return{type:0,children:e,helpers:[],components:[],directives:[],hoists:[],imports:[],cached:0,temps:0,codegenNode:void 0,loc:t}}(_c(n,0,[]),Ic(n,r))}function _c(e,t,n){const r=Rc(n),o=r?r.ns:0,i=[];for(;!Dc(e,t,n);){const l=e.source;let a;if(0===t||1===t)if(!e.inVPre&&Fc(l,e.options.delimiters[0]))a=Lc(e,t);else if(0===t&&"<"===l[0])if(1===l.length)Vc(e,5,1);else if("!"===l[1])Fc(l,"\x3c!--")?a=xc(e):Fc(l,""===l[2]){Vc(e,14,2),Mc(e,3);continue}if(/[a-z]/i.test(l[2])){Vc(e,23),Cc(e,1,r);continue}Vc(e,12,2),a=kc(e)}else/[a-z]/i.test(l[1])?(a=Sc(e,n),dc("COMPILER_NATIVE_TEMPLATE",e)&&a&&"template"===a.tag&&!a.props.some((e=>7===e.type&&Ec(e.name)))&&(a=a.children)):"?"===l[1]?(Vc(e,21,1),a=kc(e)):Vc(e,12,1);if(a||(a=Oc(e,t)),R(a))for(let e=0;e/.exec(e.source);if(r){r.index<=3&&Vc(e,0),r[1]&&Vc(e,10),n=e.source.slice(4,r.index);const t=e.source.slice(0,r.index);let o=1,i=0;for(;-1!==(i=t.indexOf("\x3c!--",o));)Mc(e,i-o+1),i+4");return-1===o?(r=e.source.slice(n),Mc(e,e.source.length)):(r=e.source.slice(n,o),Mc(e,o+1)),{type:3,content:r,loc:Ic(e,t)}}function Sc(e,t){const n=e.inPre,r=e.inVPre,o=Rc(t),i=Cc(e,0,o),l=e.inPre&&!n,a=e.inVPre&&!r;if(i.isSelfClosing||e.options.isVoidTag(i.tag))return l&&(e.inPre=!1),a&&(e.inVPre=!1),i;t.push(i);const s=e.options.getTextMode(i,o),c=_c(e,s,t);t.pop();{const t=i.props.find((e=>6===e.type&&"inline-template"===e.name));if(t&&hc("COMPILER_INLINE_TEMPLATE",e,t.loc)){const n=Ic(e,i.loc.end);t.value={type:2,content:n.source,loc:n}}}if(i.children=c,$c(e.source,i.tag))Cc(e,1,o);else if(Vc(e,24,0,i.loc.start),0===e.source.length&&"script"===i.tag.toLowerCase()){const t=c[0];t&&Fc(t.loc.source,"\x3c!--")&&Vc(e,8)}return i.loc=Ic(e,i.loc.start),l&&(e.inPre=!1),a&&(e.inVPre=!1),i}const Ec=o("if,else,else-if,for,slot");function Cc(e,t,n){const r=Pc(e),o=/^<\/?([a-z][^\t\r\n\f />]*)/i.exec(e.source),i=o[1],l=e.options.getNamespace(i,n);Mc(e,o[0].length),Bc(e);const a=Pc(e),s=e.source;e.options.isPreTag(i)&&(e.inPre=!0);let c=Tc(e,t);0===t&&!e.inVPre&&c.some((e=>7===e.type&&"pre"===e.name))&&(e.inVPre=!0,O(e,a),e.source=s,c=Tc(e,t).filter((e=>"v-pre"!==e.name)));let u=!1;if(0===e.source.length?Vc(e,9):(u=Fc(e.source,"/>"),1===t&&u&&Vc(e,4),Mc(e,u?2:1)),1===t)return;let f=0;return e.inVPre||("slot"===i?f=2:"template"===i?c.some((e=>7===e.type&&Ec(e.name)))&&(f=3):function(e,t,n){const r=n.options;if(r.isCustomElement(e))return!1;if("component"===e||/^[A-Z]/.test(e)||$s(e)||r.isBuiltInComponent&&r.isBuiltInComponent(e)||r.isNativeTag&&!r.isNativeTag(e))return!0;for(let e=0;e0&&!Fc(e.source,">")&&!Fc(e.source,"/>");){if(Fc(e.source,"/")){Vc(e,22),Mc(e,1),Bc(e);continue}1===t&&Vc(e,3);const o=Nc(e,r);6===o.type&&o.value&&"class"===o.name&&(o.value.content=o.value.content.replace(/\s+/g," ").trim()),0===t&&n.push(o),/^[^\t\r\n\f />]/.test(e.source)&&Vc(e,15),Bc(e)}return n}function Nc(e,t){const n=Pc(e),r=/^[^\t\r\n\f />][^\t\r\n\f />=]*/.exec(e.source)[0];t.has(r)&&Vc(e,2),t.add(r),"="===r[0]&&Vc(e,19);{const t=/["'<]/g;let n;for(;n=t.exec(r);)Vc(e,17,n.index)}let o;Mc(e,r.length),/^[\t\r\n\f ]*=/.test(e.source)&&(Bc(e),Mc(e,1),Bc(e),o=function(e){const t=Pc(e);let n;const r=e.source[0],o='"'===r||"'"===r;if(o){Mc(e,1);const t=e.source.indexOf(r);-1===t?n=Ac(e,e.source.length,4):(n=Ac(e,t,4),Mc(e,1))}else{const t=/^[^\t\r\n\f >]+/.exec(e.source);if(!t)return;const r=/["'<=`]/g;let o;for(;o=r.exec(t[0]);)Vc(e,18,o.index);n=Ac(e,t[0].length,4)}return{content:n,isQuoted:o,loc:Ic(e,t)}}(e),o||Vc(e,13));const i=Ic(e,n);if(!e.inVPre&&/^(v-[A-Za-z0-9-]|:|\.|@|#)/.test(r)){const t=/(?:^v-([a-z0-9-]+))?(?:(?::|^\.|^@|^#)(\[[^\]]+\]|[^\.]+))?(.+)?$/i.exec(r);let l,a=Fc(r,"."),s=t[1]||(a||Fc(r,":")?"bind":Fc(r,"@")?"on":"slot");if(t[2]){const o="slot"===s,i=r.lastIndexOf(t[2]),a=Ic(e,jc(e,n,i),jc(e,n,i+t[2].length+(o&&t[3]||"").length));let c=t[2],u=!0;c.startsWith("[")?(u=!1,c.endsWith("]")?c=c.slice(1,c.length-1):(Vc(e,27),c=c.slice(1))):o&&(c+=t[3]||""),l={type:4,content:c,isStatic:u,constType:u?3:0,loc:a}}if(o&&o.isQuoted){const e=o.loc;e.start.offset++,e.start.column++,e.end=Ks(e.start,o.content),e.source=e.source.slice(1,-1)}const c=t[3]?t[3].slice(1).split("."):[];return a&&c.push("prop"),"bind"===s&&l&&c.includes("sync")&&hc("COMPILER_V_BIND_SYNC",e,0,l.loc.source)&&(s="model",c.splice(c.indexOf("sync"),1)),{type:7,name:s,exp:o&&{type:4,content:o.content,isStatic:!1,constType:0,loc:o.loc},arg:l,modifiers:c,loc:i}}return!e.inVPre&&Fc(r,"v-")&&Vc(e,26),{type:6,name:r,value:o&&{type:2,content:o.content,loc:o.loc},loc:i}}function Lc(e,t){const[n,r]=e.options.delimiters,o=e.source.indexOf(r,n.length);if(-1===o)return void Vc(e,25);const i=Pc(e);Mc(e,n.length);const l=Pc(e),a=Pc(e),s=o-n.length,c=e.source.slice(0,s),u=Ac(e,s,t),f=u.trim(),p=u.indexOf(f);p>0&&Ys(l,c,p);return Ys(a,c,s-(u.length-f.length-p)),Mc(e,r.length),{type:5,content:{type:4,isStatic:!1,constType:0,content:f,loc:Ic(e,l,a)},loc:Ic(e,i)}}function Oc(e,t){const n=3===t?["]]>"]:["<",e.options.delimiters[0]];let r=e.source.length;for(let t=0;to&&(r=o)}const o=Pc(e);return{type:2,content:Ac(e,r,t),loc:Ic(e,o)}}function Ac(e,t,n){const r=e.source.slice(0,t);return Mc(e,t),2!==n&&3!==n&&r.includes("&")?e.options.decodeEntities(r,4===n):r}function Pc(e){const{column:t,line:n,offset:r}=e;return{column:t,line:n,offset:r}}function Ic(e,t,n){return{start:t,end:n=n||Pc(e),source:e.originalSource.slice(t.offset,n.offset)}}function Rc(e){return e[e.length-1]}function Fc(e,t){return e.startsWith(t)}function Mc(e,t){const{source:n}=e;Ys(e,n,t),e.source=n.slice(t)}function Bc(e){const t=/^[\t\r\n\f ]+/.exec(e.source);t&&Mc(e,t[0].length)}function jc(e,t,n){return Ks(t,e.originalSource.slice(t.offset,n),n)}function Vc(e,t,n,r=Pc(e)){n&&(r.offset+=n,r.column+=n),e.options.onError(Ua(t,{start:r,end:r,source:""}))}function Dc(e,t,n){const r=e.source;switch(t){case 0:if(Fc(r,"=0;--e)if($c(r,n[e].tag))return!0;break;case 1:case 2:{const e=Rc(n);if(e&&$c(r,e.tag))return!0;break}case 3:if(Fc(r,"]]>"))return!0}return!r}function $c(e,t){return Fc(e,"]/.test(e[2+t.length]||">")}function Uc(e,t){Hc(e,t,Wc(e,e.children[0]))}function Wc(e,t){const{children:n}=e;return 1===n.length&&1===t.type&&!rc(t)}function Hc(e,t,n=!1){const{children:r}=e,o=r.length;let i=0;for(let e=0;e0){if(e>=2){o.codegenNode.patchFlag="-1",o.codegenNode=t.hoist(o.codegenNode),i++;continue}}else{const e=o.codegenNode;if(13===e.type){const n=Yc(e);if((!n||512===n||1===n)&&Jc(o,t)>=2){const n=Kc(o);n&&(e.props=t.hoist(n))}e.dynamicProps&&(e.dynamicProps=t.hoist(e.dynamicProps))}}}if(1===o.type){const e=1===o.tagType;e&&t.scopes.vSlot++,Hc(o,t),e&&t.scopes.vSlot--}else if(11===o.type)Hc(o,t,1===o.children.length);else if(9===o.type)for(let e=0;e1)for(let o=0;o`_${Ns[S.helper(e)]}`,replaceNode(e){S.parent.children[S.childIndex]=S.currentNode=e},removeNode(e){const t=S.parent.children,n=e?t.indexOf(e):S.currentNode?S.childIndex:-1;e&&e!==S.currentNode?S.childIndex>n&&(S.childIndex--,S.onNodeRemoved()):(S.currentNode=null,S.onNodeRemoved()),S.parent.children.splice(n,1)},onNodeRemoved:()=>{},addIdentifiers(e){},removeIdentifiers(e){},hoist(e){V(e)&&(e=Rs(e)),S.hoists.push(e);const t=Rs(`_hoisted_${S.hoists.length}`,!1,e.loc,2);return t.hoisted=e,t},cache:(e,t=!1)=>function(e,t,n=!1){return{type:20,index:e,value:t,isVNode:n,loc:Ls}}(S.cached++,e,t)};return S.filters=new Set,S}function Xc(e,t){const n=Zc(e,t);Qc(e,n),t.hoistStatic&&Uc(e,n),t.ssr||function(e,t){const{helper:n}=t,{children:r}=e;if(1===r.length){const n=r[0];if(Wc(e,n)&&n.codegenNode){const r=n.codegenNode;13===r.type&&fc(r,t),e.codegenNode=r}else e.codegenNode=n}else if(r.length>1){let r=64;0,e.codegenNode=Os(t,n(Wa),void 0,e.children,r+"",void 0,void 0,!0,void 0,!1)}}(e,n),e.helpers=[...n.helpers.keys()],e.components=[...n.components],e.directives=[...n.directives],e.imports=n.imports,e.hoists=n.hoists,e.temps=n.temps,e.cached=n.cached,e.filters=[...n.filters]}function Qc(e,t){t.currentNode=e;const{nodeTransforms:n}=t,r=[];for(let o=0;o{n--};for(;nt===e:t=>e.test(t);return(e,r)=>{if(1===e.type){const{props:o}=e;if(3===e.tagType&&o.some(tc))return;const i=[];for(let l=0;l`${Ns[e]}: _${Ns[e]}`;function ru(e,t={}){const n=function(e,{mode:t="function",prefixIdentifiers:n="module"===t,sourceMap:r=!1,filename:o="template.vue.html",scopeId:i=null,optimizeImports:l=!1,runtimeGlobalName:a="Vue",runtimeModuleName:s="vue",ssrRuntimeModuleName:c="vue/server-renderer",ssr:u=!1,isTS:f=!1,inSSR:p=!1}){const d={mode:t,prefixIdentifiers:n,sourceMap:r,filename:o,scopeId:i,optimizeImports:l,runtimeGlobalName:a,runtimeModuleName:s,ssrRuntimeModuleName:c,ssr:u,isTS:f,inSSR:p,source:e.loc.source,code:"",column:1,line:1,offset:0,indentLevel:0,pure:!1,map:void 0,helper:e=>`_${Ns[e]}`,push(e,t){d.code+=e},indent(){h(++d.indentLevel)},deindent(e=!1){e?--d.indentLevel:h(--d.indentLevel)},newline(){h(d.indentLevel)}};function h(e){d.push("\n"+" ".repeat(e))}return d}(e,t);t.onContextCreated&&t.onContextCreated(n);const{mode:r,push:o,prefixIdentifiers:i,indent:l,deindent:a,newline:s,scopeId:c,ssr:u}=n,f=e.helpers.length>0,p=!i&&"module"!==r;!function(e,t){const{ssr:n,prefixIdentifiers:r,push:o,newline:i,runtimeModuleName:l,runtimeGlobalName:a,ssrRuntimeModuleName:s}=t,c=a;if(e.helpers.length>0&&(o(`const _Vue = ${c}\n`),e.hoists.length)){o(`const { ${[Za,Xa,Qa,es,ts].filter((t=>e.helpers.includes(t))).map(nu).join(", ")} } = _Vue\n`)}(function(e,t){if(!e.length)return;t.pure=!0;const{push:n,newline:r,helper:o,scopeId:i,mode:l}=t;r();for(let o=0;o0)&&s()),e.directives.length&&(ou(e.directives,"directive",n),e.temps>0&&s()),e.filters&&e.filters.length&&(s(),ou(e.filters,"filter",n),s()),e.temps>0){o("let ");for(let t=0;t0?", ":""}_temp${t}`)}return(e.components.length||e.directives.length||e.temps)&&(o("\n"),s()),u||o("return "),e.codegenNode?au(e.codegenNode,n):o("null"),p&&(a(),o("}")),a(),o("}"),{ast:e,code:n.code,preamble:"",map:n.map?n.map.toJSON():void 0}}function ou(e,t,{helper:n,push:r,newline:o,isTS:i}){const l=n("filter"===t?is:"component"===t?ns:os);for(let n=0;n3||!1;t.push("["),n&&t.indent(),lu(e,t,n),n&&t.deindent(),t.push("]")}function lu(e,t,n=!1,r=!0){const{push:o,newline:i}=t;for(let l=0;le||"null"))}([i,l,a,s,c]),t),n(")"),f&&n(")");u&&(n(", "),au(u,t),n(")"))}(e,t);break;case 14:!function(e,t){const{push:n,helper:r,pure:o}=t,i=V(e.callee)?e.callee:r(e.callee);o&&n(tu);n(i+"(",e),lu(e.arguments,t),n(")")}(e,t);break;case 15:!function(e,t){const{push:n,indent:r,deindent:o,newline:i}=t,{properties:l}=e;if(!l.length)return void n("{}",e);const a=l.length>1||!1;n(a?"{":"{ "),a&&r();for(let e=0;e "),(s||a)&&(n("{"),r());l?(s&&n("return "),R(l)?iu(l,t):au(l,t)):a&&au(a,t);(s||a)&&(o(),n("}"));c&&(e.isNonScopedSlot&&n(", undefined, true"),n(")"))}(e,t);break;case 19:!function(e,t){const{test:n,consequent:r,alternate:o,newline:i}=e,{push:l,indent:a,deindent:s,newline:c}=t;if(4===n.type){const e=!Ws(n.content);e&&l("("),su(n,t),e&&l(")")}else l("("),au(n,t),l(")");i&&a(),t.indentLevel++,i||l(" "),l("? "),au(r,t),t.indentLevel--,i&&c(),i||l(" "),l(": ");const u=19===o.type;u||t.indentLevel++;au(o,t),u||t.indentLevel--;i&&s(!0)}(e,t);break;case 20:!function(e,t){const{push:n,helper:r,indent:o,deindent:i,newline:l}=t;n(`_cache[${e.index}] || (`),e.isVNode&&(o(),n(`${r(bs)}(-1),`),l());n(`_cache[${e.index}] = `),au(e.value,t),e.isVNode&&(n(","),l(),n(`${r(bs)}(1),`),l(),n(`_cache[${e.index}]`),i());n(")")}(e,t);break;case 21:lu(e.body,t,!0,!1)}}function su(e,t){const{content:n,isStatic:r}=e;t.push(r?JSON.stringify(n):n,e)}function cu(e,t){for(let n=0;nfunction(e,t,n,r){if(!("else"===t.name||t.exp&&t.exp.content.trim())){const r=t.exp?t.exp.loc:e.loc;n.onError(Ua(28,t.loc)),t.exp=Rs("true",!1,r)}0;if("if"===t.name){const o=pu(e,t),i={type:9,loc:e.loc,branches:[o]};if(n.replaceNode(i),r)return r(i,o,!0)}else{const o=n.parent.children;let i=o.indexOf(e);for(;i-- >=-1;){const l=o[i];if(l&&3===l.type)n.removeNode(l);else{if(!l||2!==l.type||l.content.trim().length){if(l&&9===l.type){"else-if"===t.name&&void 0===l.branches[l.branches.length-1].condition&&n.onError(Ua(30,e.loc)),n.removeNode();const o=pu(e,t);0,l.branches.push(o);const i=r&&r(l,o,!1);Qc(o,n),i&&i(),n.currentNode=null}else n.onError(Ua(30,e.loc));break}n.removeNode(l)}}}}(e,t,n,((e,t,r)=>{const o=n.parent.children;let i=o.indexOf(e),l=0;for(;i-- >=0;){const e=o[i];e&&9===e.type&&(l+=e.branches.length)}return()=>{if(r)e.codegenNode=du(t,l,n);else{const r=function(e){for(;;)if(19===e.type){if(19!==e.alternate.type)return e;e=e.alternate}else 20===e.type&&(e=e.value)}(e.codegenNode);r.alternate=du(t,l+e.branches.length-1,n)}}}))));function pu(e,t){const n=3===e.tagType;return{type:10,loc:e.loc,condition:"else"===t.name?void 0:t.exp,children:n&&!Zs(e,"for")?e.children:[e],userKey:Xs(e,"key"),isTemplateIf:n}}function du(e,t,n){return e.condition?js(e.condition,hu(e,t,n),Ms(n.helper(Qa),['""',"true"])):hu(e,t,n)}function hu(e,t,n){const{helper:r}=n,o=Is("key",Rs(`${t}`,!1,Ls,2)),{children:i}=e,l=i[0];if(1!==i.length||1!==l.type){if(1===i.length&&11===l.type){const e=l.codegenNode;return sc(e,o,n),e}{let t=64;return Os(n,r(Wa),Ps([o]),i,t+"",void 0,void 0,!0,!1,!1,e.loc)}}{const e=l.codegenNode,t=14===(a=e).type&&a.callee===Cs?a.arguments[1].returns:a;return 13===t.type&&fc(t,n),sc(t,o,n),e}var a}const mu=eu("for",((e,t,n)=>{const{helper:r,removeHelper:o}=n;return function(e,t,n,r){if(!t.exp)return void n.onError(Ua(31,t.loc));const o=_u(t.exp,n);if(!o)return void n.onError(Ua(32,t.loc));const{addIdentifiers:i,removeIdentifiers:l,scopes:a}=n,{source:s,value:c,key:u,index:f}=o,p={type:11,loc:t.loc,source:s,valueAlias:c,keyAlias:u,objectIndexAlias:f,parseResult:o,children:nc(e)?e.children:[e]};n.replaceNode(p),a.vFor++;const d=r&&r(p);return()=>{a.vFor--,d&&d()}}(e,t,n,(t=>{const i=Ms(r(as),[t.source]),l=nc(e),a=Zs(e,"memo"),s=Xs(e,"key"),c=s&&(6===s.type?Rs(s.value.content,!0):s.exp),u=s?Is("key",c):null,f=4===t.source.type&&t.source.constType>0,p=f?64:s?128:256;return t.codegenNode=Os(n,r(Wa),void 0,i,p+"",void 0,void 0,!0,!f,!1,e.loc),()=>{let s;const{children:p}=t;const d=1!==p.length||1!==p[0].type,h=rc(e)?e:l&&1===e.children.length&&rc(e.children[0])?e.children[0]:null;if(h?(s=h.codegenNode,l&&u&&sc(s,u,n)):d?s=Os(n,r(Wa),u?Ps([u]):void 0,e.children,"64",void 0,void 0,!0,void 0,!1):(s=p[0].codegenNode,l&&u&&sc(s,u,n),s.isBlock!==!f&&(s.isBlock?(o(Ja),o(ic(n.inSSR,s.isComponent))):o(oc(n.inSSR,s.isComponent))),s.isBlock=!f,s.isBlock?(r(Ja),r(ic(n.inSSR,s.isComponent))):r(oc(n.inSSR,s.isComponent))),a){const e=Bs(wu(t.parseResult,[Rs("_cached")]));e.body={type:21,body:[Fs(["const _memo = (",a.exp,")"]),Fs(["if (_cached",...c?[" && _cached.key === ",c]:[],` && ${n.helperString(Ts)}(_cached, _memo)) return _cached`]),Fs(["const _item = ",s]),Rs("_item.memo = _memo"),Rs("return _item")],loc:Ls},i.arguments.push(e,Rs("_cache"),Rs(String(n.cached++)))}else i.arguments.push(Bs(wu(t.parseResult),s,!0))}}))}));const vu=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,gu=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,yu=/^\(|\)$/g;function _u(e,t){const n=e.loc,r=e.content,o=r.match(vu);if(!o)return;const[,i,l]=o,a={source:bu(n,l.trim(),r.indexOf(l,i.length)),value:void 0,key:void 0,index:void 0};let s=i.trim().replace(yu,"").trim();const c=i.indexOf(s),u=s.match(gu);if(u){s=s.replace(gu,"").trim();const e=u[1].trim();let t;if(e&&(t=r.indexOf(e,c+s.length),a.key=bu(n,e,t)),u[2]){const o=u[2].trim();o&&(a.index=bu(n,o,r.indexOf(o,a.key?t+e.length:c+s.length)))}}return s&&(a.value=bu(n,s,c)),a}function bu(e,t,n){return Rs(t,!1,Js(e,n,t.length))}function wu({value:e,key:t,index:n},r=[]){return function(e){let t=e.length;for(;t--&&!e[t];);return e.slice(0,t+1).map(((e,t)=>e||Rs("_".repeat(t+1),!1)))}([e,t,n,...r])}const xu=Rs("undefined",!1),ku=(e,t)=>{if(1===e.type&&(1===e.tagType||3===e.tagType)){const n=Zs(e,"slot");if(n)return n.exp,t.scopes.vSlot++,()=>{t.scopes.vSlot--}}},Su=(e,t,n)=>Bs(e,t,!1,!0,t.length?t[0].loc:n);function Eu(e,t,n=Su){t.helper(ks);const{children:r,loc:o}=e,i=[],l=[];let a=t.scopes.vSlot>0||t.scopes.vFor>0;const s=Zs(e,"slot",!0);if(s){const{arg:e,exp:t}=s;e&&!Vs(e)&&(a=!0),i.push(Is(e||Rs("default",!0),n(t,r,o)))}let c=!1,u=!1;const f=[],p=new Set;let d=0;for(let e=0;e{const i=n(e,r,o);return t.compatConfig&&(i.isNonScopedSlot=!0),Is("default",i)};c?f.length&&f.some((e=>Nu(e)))&&(u?t.onError(Ua(39,f[0].loc)):i.push(e(void 0,f))):i.push(e(void 0,r))}const h=a?2:Tu(e.children)?3:1;let m=Ps(i.concat(Is("_",Rs(h+"",!1))),o);return l.length&&(m=Ms(t.helper(cs),[m,As(l)])),{slots:m,hasDynamicSlots:a}}function Cu(e,t,n){const r=[Is("name",e),Is("fn",t)];return null!=n&&r.push(Is("key",Rs(String(n),!0))),Ps(r)}function Tu(e){for(let t=0;tfunction(){if(1!==(e=t.currentNode).type||0!==e.tagType&&1!==e.tagType)return;const{tag:n,props:r}=e,o=1===e.tagType;let i=o?function(e,t,n=!1){let{tag:r}=e;const o=Ru(r),i=Xs(e,"is");if(i)if(o||dc("COMPILER_IS_ON_ELEMENT",t)){const e=6===i.type?i.value&&Rs(i.value.content,!0):i.exp;if(e)return Ms(t.helper(rs),[e])}else 6===i.type&&i.value.content.startsWith("vue:")&&(r=i.value.content.slice(4));const l=!o&&Zs(e,"is");if(l&&l.exp)return Ms(t.helper(rs),[l.exp]);const a=$s(r)||t.isBuiltInComponent(r);if(a)return n||t.helper(a),a;return t.helper(ns),t.components.add(r),uc(r,"component")}(e,t):`"${n}"`;const l=$(i)&&i.callee===rs;let a,s,c,u,f,p,d=0,h=l||i===Ha||i===za||!o&&("svg"===n||"foreignObject"===n);if(r.length>0){const n=Au(e,t,void 0,o,l);a=n.props,d=n.patchFlag,f=n.dynamicPropNames;const r=n.directives;p=r&&r.length?As(r.map((e=>function(e,t){const n=[],r=Lu.get(e);r?n.push(t.helperString(r)):(t.helper(os),t.directives.add(e.name),n.push(uc(e.name,"directive")));const{loc:o}=e;e.exp&&n.push(e.exp);e.arg&&(e.exp||n.push("void 0"),n.push(e.arg));if(Object.keys(e.modifiers).length){e.arg||(e.exp||n.push("void 0"),n.push("void 0"));const t=Rs("true",!1,o);n.push(Ps(e.modifiers.map((e=>Is(e,t))),o))}return As(n,e.loc)}(e,t)))):void 0,n.shouldUseBlock&&(h=!0)}if(e.children.length>0){i===Ga&&(h=!0,d|=1024);if(o&&i!==Ha&&i!==Ga){const{slots:n,hasDynamicSlots:r}=Eu(e,t);s=n,r&&(d|=1024)}else if(1===e.children.length&&i!==Ha){const n=e.children[0],r=n.type,o=5===r||8===r;o&&0===zc(n,t)&&(d|=1),s=o||2===r?n:e.children}else s=e.children}0!==d&&(c=String(d),f&&f.length&&(u=function(e){let t="[";for(let n=0,r=e.length;n0;let d=!1,h=0,m=!1,v=!1,g=!1,y=!1,_=!1,b=!1;const w=[],x=e=>{c.length&&(u.push(Ps(Pu(c),a)),c=[]),e&&u.push(e)},k=({key:e,value:n})=>{if(Vs(e)){const i=e.content,l=N(i);if(!l||r&&!o||"onclick"===i.toLowerCase()||"onUpdate:modelValue"===i||q(i)||(y=!0),l&&q(i)&&(b=!0),20===n.type||(4===n.type||8===n.type)&&zc(n,t)>0)return;"ref"===i?m=!0:"class"===i?v=!0:"style"===i?g=!0:"key"===i||w.includes(i)||w.push(i),!r||"class"!==i&&"style"!==i||w.includes(i)||w.push(i)}else _=!0};for(let o=0;o0&&c.push(Is(Rs("ref_for",!0),Rs("true")))),"is"===n&&(Ru(l)||r&&r.content.startsWith("vue:")||dc("COMPILER_IS_ON_ELEMENT",t)))continue;c.push(Is(Rs(n,!0,Js(e,0,n.length)),Rs(r?r.content:"",o,r?r.loc:e)))}else{const{name:n,arg:o,exp:h,loc:m}=s,v="bind"===n,g="on"===n;if("slot"===n){r||t.onError(Ua(40,m));continue}if("once"===n||"memo"===n)continue;if("is"===n||v&&Qs(o,"is")&&(Ru(l)||dc("COMPILER_IS_ON_ELEMENT",t)))continue;if(g&&i)continue;if((v&&Qs(o,"key")||g&&p&&Qs(o,"vue:before-update"))&&(d=!0),v&&Qs(o,"ref")&&t.scopes.vFor>0&&c.push(Is(Rs("ref_for",!0),Rs("true"))),!o&&(v||g)){if(_=!0,h)if(v){if(x(),dc("COMPILER_V_BIND_OBJECT_ORDER",t)){u.unshift(h);continue}u.push(h)}else x({type:14,loc:m,callee:t.helper(vs),arguments:r?[h]:[h,"true"]});else t.onError(Ua(v?34:35,m));continue}const y=t.directiveTransforms[n];if(y){const{props:n,needRuntime:r}=y(s,e,t);!i&&n.forEach(k),g&&o&&!Vs(o)?x(Ps(n,a)):c.push(...n),r&&(f.push(s),D(r)&&Lu.set(s,r))}else J(n)||(f.push(s),p&&(d=!0))}}let S;if(u.length?(x(),S=u.length>1?Ms(t.helper(fs),u,a):u[0]):c.length&&(S=Ps(Pu(c),a)),_?h|=16:(v&&!r&&(h|=2),g&&!r&&(h|=4),w.length&&(h|=8),y&&(h|=32)),d||0!==h&&32!==h||!(m||b||f.length>0)||(h|=512),!t.inSSR&&S)switch(S.type){case 15:let e=-1,n=-1,r=!1;for(let t=0;t{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))})((e=>e.replace(Fu,((e,t)=>t?t.toUpperCase():"")))),Bu=(e,t)=>{if(rc(e)){const{children:n,loc:r}=e,{slotName:o,slotProps:i}=function(e,t){let n,r='"default"';const o=[];for(let t=0;t0){const{props:r,directives:i}=Au(e,t,o,!1,!1);n=r,i.length&&t.onError(Ua(36,i[0].loc))}return{slotName:r,slotProps:n}}(e,t),l=[t.prefixIdentifiers?"_ctx.$slots":"$slots",o,"{}","undefined","true"];let a=2;i&&(l[2]=i,a=3),n.length&&(l[3]=Bs([],n,!1,!1,r),a=4),t.scopeId&&!t.slotted&&(a=5),l.splice(a),e.codegenNode=Ms(t.helper(ss),l,r)}};const ju=/^\s*([\w$_]+|(async\s*)?\([^)]*?\))\s*(:[^=]+)?=>|^\s*(async\s+)?function(?:\s+[\w$]+)?\s*\(/,Vu=(e,t,n,r)=>{const{loc:o,modifiers:i,arg:l}=e;let a;if(e.exp||i.length||n.onError(Ua(35,o)),4===l.type)if(l.isStatic){let e=l.content;e.startsWith("vue:")&&(e=`vnode-${e.slice(4)}`);a=Rs(0!==t.tagType||e.startsWith("vnode")||!/[A-Z]/.test(e)?te(Z(e)):`on:${e}`,!0,l.loc)}else a=Fs([`${n.helperString(_s)}(`,l,")"]);else a=l,a.children.unshift(`${n.helperString(_s)}(`),a.children.push(")");let s=e.exp;s&&!s.content.trim()&&(s=void 0);let c=n.cacheHandlers&&!s&&!n.inVOnce;if(s){const e=qs(s.content),t=!(e||ju.test(s.content)),n=s.content.includes(";");0,(t||c&&e)&&(s=Fs([`${t?"$event":"(...args)"} => ${n?"{":"("}`,s,n?"}":")"]))}let u={props:[Is(a,s||Rs("() => {}",!1,o))]};return r&&(u=r(u)),c&&(u.props[0].value=n.cache(u.props[0].value)),u.props.forEach((e=>e.key.isHandlerKey=!0)),u},Du=(e,t,n)=>{const{exp:r,modifiers:o,loc:i}=e,l=e.arg;return 4!==l.type?(l.children.unshift("("),l.children.push(') || ""')):l.isStatic||(l.content=`${l.content} || ""`),o.includes("camel")&&(4===l.type?l.isStatic?l.content=Z(l.content):l.content=`${n.helperString(gs)}(${l.content})`:(l.children.unshift(`${n.helperString(gs)}(`),l.children.push(")"))),n.inSSR||(o.includes("prop")&&$u(l,"."),o.includes("attr")&&$u(l,"^")),!r||4===r.type&&!r.content.trim()?(n.onError(Ua(34,i)),{props:[Is(l,Rs("",!0,i))]}):{props:[Is(l,r)]}},$u=(e,t)=>{4===e.type?e.isStatic?e.content=t+e.content:e.content=`\`${t}\${${e.content}}\``:(e.children.unshift(`'${t}' + (`),e.children.push(")"))},Uu=(e,t)=>{if(0===e.type||1===e.type||11===e.type||10===e.type)return()=>{const n=e.children;let r,o=!1;for(let e=0;e7===e.type&&!t.directiveTransforms[e.name]))||"template"===e.tag)))for(let e=0;e{if(1===e.type&&Zs(e,"once",!0)){if(Wu.has(e)||t.inVOnce)return;return Wu.add(e),t.inVOnce=!0,t.helper(bs),()=>{t.inVOnce=!1;const e=t.currentNode;e.codegenNode&&(e.codegenNode=t.cache(e.codegenNode,!0))}}},zu=(e,t,n)=>{const{exp:r,arg:o}=e;if(!r)return n.onError(Ua(41,e.loc)),Gu();const i=r.loc.source,l=4===r.type?r.content:i,a=n.bindingMetadata[i];if("props"===a||"props-aliased"===a)return n.onError(Ua(44,r.loc)),Gu();if(!l.trim()||!qs(l))return n.onError(Ua(42,r.loc)),Gu();const s=o||Rs("modelValue",!0),c=o?Vs(o)?`onUpdate:${o.content}`:Fs(['"onUpdate:" + ',o]):"onUpdate:modelValue";let u;u=Fs([`${n.isTS?"($event: any)":"$event"} => ((`,r,") = $event)"]);const f=[Is(s,e.exp),Is(c,u)];if(e.modifiers.length&&1===t.tagType){const t=e.modifiers.map((e=>(Ws(e)?e:JSON.stringify(e))+": true")).join(", "),n=o?Vs(o)?`${o.content}Modifiers`:Fs([o,' + "Modifiers"']):"modelModifiers";f.push(Is(n,Rs(`{ ${t} }`,!1,e.loc,2)))}return Gu(f)};function Gu(e=[]){return{props:e}}const qu=/[\w).+\-_$\]]/,Ju=(e,t)=>{dc("COMPILER_FILTER",t)&&(5===e.type&&Ku(e.content,t),1===e.type&&e.props.forEach((e=>{7===e.type&&"for"!==e.name&&e.exp&&Ku(e.exp,t)})))};function Ku(e,t){if(4===e.type)Yu(e,t);else for(let n=0;n=0&&(e=n.charAt(t)," "===e);t--);e&&qu.test(e)||(u=!0)}}else void 0===l?(h=i+1,l=n.slice(0,i).trim()):v();function v(){m.push(n.slice(h,i).trim()),h=i+1}if(void 0===l?l=n.slice(0,i).trim():0!==h&&v(),m.length){for(i=0;i{if(1===e.type){const n=Zs(e,"memo");if(!n||Xu.has(e))return;return Xu.add(e),()=>{const r=e.codegenNode||t.currentNode.codegenNode;r&&13===r.type&&(1!==e.tagType&&fc(r,t),e.codegenNode=Ms(t.helper(Cs),[n.exp,Bs(void 0,r),"_cache",String(t.cached++)]))}}};function ef(e,t={}){const n=t.onError||Da,r="module"===t.mode;!0===t.prefixIdentifiers?n(Ua(47)):r&&n(Ua(48));t.cacheHandlers&&n(Ua(49)),t.scopeId&&!r&&n(Ua(50));const o=V(e)?yc(e,t):e,[i,l]=[[Hu,fu,Qu,mu,Ju,Bu,Ou,ku,Uu],{on:Vu,bind:Du,model:zu}];return Xc(o,O({},t,{prefixIdentifiers:false,nodeTransforms:[...i,...t.nodeTransforms||[]],directiveTransforms:O({},l,t.directiveTransforms||{})})),ru(o,O({},t,{prefixIdentifiers:false}))}const tf=Symbol(""),nf=Symbol(""),rf=Symbol(""),of=Symbol(""),lf=Symbol(""),af=Symbol(""),sf=Symbol(""),cf=Symbol(""),uf=Symbol(""),ff=Symbol("");var pf;let df;pf={[tf]:"vModelRadio",[nf]:"vModelCheckbox",[rf]:"vModelText",[of]:"vModelSelect",[lf]:"vModelDynamic",[af]:"withModifiers",[sf]:"withKeys",[cf]:"vShow",[uf]:"Transition",[ff]:"TransitionGroup"},Object.getOwnPropertySymbols(pf).forEach((e=>{Ns[e]=pf[e]}));const hf=o("style,iframe,script,noscript",!0),mf={isVoidTag:m,isNativeTag:e=>d(e)||h(e),isPreTag:e=>"pre"===e,decodeEntities:function(e,t=!1){return df||(df=document.createElement("div")),t?(df.innerHTML=`
`,df.children[0].getAttribute("foo")):(df.innerHTML=e,df.textContent)},isBuiltInComponent:e=>Ds(e,"Transition")?uf:Ds(e,"TransitionGroup")?ff:void 0,getNamespace(e,t){let n=t?t.ns:0;if(t&&2===n)if("annotation-xml"===t.tag){if("svg"===e)return 1;t.props.some((e=>6===e.type&&"encoding"===e.name&&null!=e.value&&("text/html"===e.value.content||"application/xhtml+xml"===e.value.content)))&&(n=0)}else/^m(?:[ions]|text)$/.test(t.tag)&&"mglyph"!==e&&"malignmark"!==e&&(n=0);else t&&1===n&&("foreignObject"!==t.tag&&"desc"!==t.tag&&"title"!==t.tag||(n=0));if(0===n){if("svg"===e)return 1;if("math"===e)return 2}return n},getTextMode({tag:e,ns:t}){if(0===t){if("textarea"===e||"title"===e)return 1;if(hf(e))return 2}return 0}},vf=(e,t)=>{const n=u(e);return Rs(JSON.stringify(n),!1,t,3)};function gf(e,t){return Ua(e,t)}const yf=o("passive,once,capture"),_f=o("stop,prevent,self,ctrl,shift,alt,meta,exact,middle"),bf=o("left,right"),wf=o("onkeyup,onkeydown,onkeypress",!0),xf=(e,t)=>Vs(e)&&"onclick"===e.content.toLowerCase()?Rs(t,!0):4!==e.type?Fs(["(",e,`) === "onClick" ? "${t}" : (`,e,")"]):e;const kf=(e,t)=>{1!==e.type||0!==e.tagType||"script"!==e.tag&&"style"!==e.tag||(t.onError(gf(61,e.loc)),t.removeNode())},Sf=[e=>{1===e.type&&e.props.forEach(((t,n)=>{6===t.type&&"style"===t.name&&t.value&&(e.props[n]={type:7,name:"bind",arg:Rs("style",!0,t.loc),exp:vf(t.value.content,t.loc),modifiers:[],loc:t.loc})}))}],Ef={cloak:()=>({props:[]}),html:(e,t,n)=>{const{exp:r,loc:o}=e;return r||n.onError(gf(51,o)),t.children.length&&(n.onError(gf(52,o)),t.children.length=0),{props:[Is(Rs("innerHTML",!0,o),r||Rs("",!0))]}},text:(e,t,n)=>{const{exp:r,loc:o}=e;return r||n.onError(gf(53,o)),t.children.length&&(n.onError(gf(54,o)),t.children.length=0),{props:[Is(Rs("textContent",!0),r?zc(r,n)>0?r:Ms(n.helperString(us),[r],o):Rs("",!0))]}},model:(e,t,n)=>{const r=zu(e,t,n);if(!r.props.length||1===t.tagType)return r;e.arg&&n.onError(gf(56,e.arg.loc));const{tag:o}=t,i=n.isCustomElement(o);if("input"===o||"textarea"===o||"select"===o||i){let l=rf,a=!1;if("input"===o||i){const r=Xs(t,"type");if(r){if(7===r.type)l=lf;else if(r.value)switch(r.value.content){case"radio":l=tf;break;case"checkbox":l=nf;break;case"file":a=!0,n.onError(gf(57,e.loc))}}else(function(e){return e.props.some((e=>!(7!==e.type||"bind"!==e.name||e.arg&&4===e.arg.type&&e.arg.isStatic)))})(t)&&(l=lf)}else"select"===o&&(l=of);a||(r.needRuntime=n.helper(l))}else n.onError(gf(55,e.loc));return r.props=r.props.filter((e=>!(4===e.key.type&&"modelValue"===e.key.content))),r},on:(e,t,n)=>Vu(e,t,n,(t=>{const{modifiers:r}=e;if(!r.length)return t;let{key:o,value:i}=t.props[0];const{keyModifiers:l,nonKeyModifiers:a,eventOptionModifiers:s}=((e,t,n,r)=>{const o=[],i=[],l=[];for(let r=0;r{const{exp:r,loc:o}=e;return r||n.onError(gf(59,o)),{props:[],needRuntime:n.helper(cf)}}};const Cf=Object.create(null);function Tf(e,t){if(!V(e)){if(!e.nodeType)return E;e=e.innerHTML}const n=e,o=Cf[n];if(o)return o;if("#"===e[0]){const t=document.querySelector(e);0,e=t?t.innerHTML:""}const i=O({hoistStatic:!0,onError:void 0,onWarn:E},t);i.isCustomElement||"undefined"==typeof customElements||(i.isCustomElement=e=>!!customElements.get(e));const{code:l}=function(e,t={}){return ef(e,O({},mf,t,{nodeTransforms:[kf,...Sf,...t.nodeTransforms||[]],directiveTransforms:O({},Ef,t.directiveTransforms||{}),transformHoist:null}))}(e,i);const a=new Function("Vue",l)(r);return a._rc=!0,Cf[n]=a}$i(Tf)}},n={};function r(e){var o=n[e];if(void 0!==o)return o.exports;var i=n[e]={id:e,loaded:!1,exports:{}};return t[e].call(i.exports,i,i.exports,r),i.loaded=!0,i.exports}r.m=t,e=[],r.O=(t,n,o,i)=>{if(!n){var l=1/0;for(u=0;u=i)&&Object.keys(r.O).every((e=>r.O[e](n[s])))?n.splice(s--,1):(a=!1,i0&&e[u-1][2]>i;u--)e[u]=e[u-1];e[u]=[n,o,i]},r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e={773:0,170:0};r.O.j=t=>0===e[t];var t=(t,n)=>{var o,i,[l,a,s]=n,c=0;if(l.some((t=>0!==e[t]))){for(o in a)r.o(a,o)&&(r.m[o]=a[o]);if(s)var u=s(r)}for(t&&t(n);cr(435)));var o=r.O(void 0,[170],(()=>r(423)));o=r.O(o)})(); \ No newline at end of file diff --git a/survey_dashboard/hmc_layout/static/en_files/cables-logo.svg b/survey_dashboard/hmc_layout/static/en_files/cables-logo.svg new file mode 100644 index 0000000..7fbeca9 --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/cables-logo.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/survey_dashboard/hmc_layout/static/en_files/cables.min(1).js b/survey_dashboard/hmc_layout/static/en_files/cables.min(1).js new file mode 100644 index 0000000..093c973 --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/cables.min(1).js @@ -0,0 +1,4 @@ +var CABLES=function(t){var e={};function i(s){if(e[s])return e[s].exports;var r=e[s]={i:s,l:!1,exports:{}};return t[s].call(r.exports,r,r.exports,i),r.l=!0,r.exports}return i.m=t,i.c=e,i.d=function(t,e,s){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:s})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var s=Object.create(null);if(i.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)i.d(s,r,function(e){return t[e]}.bind(null,r));return s},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=0)}([function(t,e,i){t.exports=i(2)},function(module,__webpack_exports__,__webpack_require__){"use strict";let GLOB_EXP=/(?:^|[^\\])\*/,NOT_LINE_ENDING=/[^\r\n]/g;const Preprocessor=function(t,e,i){this.source=""+t,this.baseDir="string"==typeof e?e:".",this.includes="object"==typeof e?e:{},this.preserveLineNumbers="boolean"==typeof i&&i,this.isNode=!("undefined"!=typeof window&&window.window),this.errorSourceAhead=50,this.defines=[]};Preprocessor.EXPR=/([ ]*)\/\/[ ]+#(include_once|include|ifn?def|if|endif|else|elif|put|define)/g,Preprocessor.ALL=/([^\r\n]*)\r?(?:\n|$)/,Preprocessor.INCLUDE=/(include_once|include)[ ]+"([^"\\]*(\\.[^"\\]*)*)"[ ]*\r?(?:\n|$)/g,Preprocessor.IF=/(ifdef|ifndef|if)[ ]*([^\r\n]+)\r?\n/g,Preprocessor.ENDIF=/(endif|else|elif)([ ]+[^\r\n]+)?\r?(?:\n|$)/g,Preprocessor.PUT=/put[ ]+([^\n]+)[ ]*/g,Preprocessor.DEFINE=/define[ ]+([^\n\r]+)\r?(?:\n|$)/g,Preprocessor.VAR=/define[ ]+var[ ]+([a-zA-Z_][a-zA-Z0-9_]*)[ ]*=[ ]*(.+)/g,Preprocessor.BOOLVAR=/define[ ]+([a-zA-Z_][a-zA-Z0-9_]*)[ ]*/g,Preprocessor.FUNCTION=/define[ ]+function[ ]+([a-zA-Z_][a-zA-Z0-9_]*)[ ]*(.+)/g,Preprocessor.stripSlashes=function(t){return(t+"").replace(/\\(.?)/g,(function(t,e){switch(e){case"\\":return"\\";case"0":return"\0";case"":return"";default:return e}}))},Preprocessor.addSlashes=function(t){return(t+"").replace(/([\\"'])/g,"\\$1").replace(/\0/g,"\\0")},Preprocessor.indent=function(t,e){let i=t.split("\n");for(let t=0;t0&&"endif"!==i[2]&&"else"!==i[2]&&"elif"!==i[2]){if(a=h.pop(),e(" pop ("+h.length+"): "+JSON.stringify(a)),Preprocessor.ALL.lastIndex=i.index,null===(s=Preprocessor.ALL.exec(this.source)))throw new Error("Illegal #"+i[2]+": "+this.source.substring(i.index,i.index+this.errorSourceAhead)+"...");h.push(o={include:a.include,index:a.index,lastIndex:Preprocessor.ALL.lastIndex}),e(" push ("+h.length+"): "+JSON.stringify(o))}else switch(i[2]){case"ifdef":case"ifndef":case"if":if(Preprocessor.IF.lastIndex=i.index,null===(s=Preprocessor.IF.exec(this.source)))throw new Error("Illegal #"+i[2]+": "+this.source.substring(i.index,i.index+this.errorSourceAhead)+"...");e(" test: "+s[2]),e(" defines "+JSON.stringify(t)),n="ifdef"===s[1]?void 0!==t[s[2]]:"ifndef"===s[1]?void 0===t[s[2]]:Preprocessor.evaluate(t,s[2]),l=!n,e(" value: "+n+", isSkip: "+l),h.push(o={include:n,index:i.index,lastIndex:Preprocessor.IF.lastIndex}),e(" push ("+h.length+"): "+JSON.stringify(o));break;case"endif":case"else":case"elif":if(Preprocessor.ENDIF.lastIndex=i.index,null===(s=Preprocessor.ENDIF.exec(this.source)))throw new Error("Illegal #"+i[2]+': "'+this.source.substring(i.index,i.index+this.errorSourceAhead)+"...");if(0===h.length)throw new Error("Unexpected #"+s[1]+': "'+this.source.substring(i.index,i.index+this.errorSourceAhead)+"...");a=h.pop(),e(" pop ("+h.length+"): "+JSON.stringify(a)),n=this.preserveLineNumbers?this.source.substring(a.index,a.lastIndex).replace(NOT_LINE_ENDING,"")+this.source.substring(a.lastIndex,i.index)+this.source.substring(i.index,Preprocessor.ENDIF.lastIndex).replace(NOT_LINE_ENDING,""):this.source.substring(a.lastIndex,i.index),a.include?(e(" incl: "+Preprocessor.nlToStr(n)+", 0-"+a.index+" + "+n.length+" bytes + "+Preprocessor.ENDIF.lastIndex+"-"+this.source.length),this.source=this.source.substring(0,a.index)+n+this.source.substring(Preprocessor.ENDIF.lastIndex)):this.preserveLineNumbers?(e(" excl(\\n): "+Preprocessor.nlToStr(n)+", 0-"+a.index+" + "+Preprocessor.ENDIF.lastIndex+"-"+this.source.length),n=n.replace(NOT_LINE_ENDING,""),this.source=this.source.substring(0,a.index)+n+this.source.substring(Preprocessor.ENDIF.lastIndex)):(e(" excl: "+Preprocessor.nlToStr(n)+", 0-"+a.index+" + "+Preprocessor.ENDIF.lastIndex+"-"+this.source.length),n="",this.source=this.source.substring(0,a.index)+this.source.substring(Preprocessor.ENDIF.lastIndex)),""===this.source&&e(" result empty"),l=!1,Preprocessor.EXPR.lastIndex=a.index+n.length,e(" continue at "+Preprocessor.EXPR.lastIndex),"else"!==s[1]&&"elif"!==s[1]||(n="else"===s[1]?!a.include:Preprocessor.evaluate(t,s[2]),l=!n,e(" isSkip: "+l),h.push(o={include:n,index:Preprocessor.EXPR.lastIndex,lastIndex:Preprocessor.EXPR.lastIndex}),e(" push ("+h.length+"): "+JSON.stringify(o)));break;case"define":if(Preprocessor.DEFINE.lastIndex=i.index,Preprocessor.VAR.lastIndex=i.index,Preprocessor.FUNCTION.lastIndex=i.index,Preprocessor.BOOLVAR.lastIndex=i.index,null===(s=Preprocessor.DEFINE.exec(this.source)))throw new Error("Illegal #"+i[2]+": "+this.source.substring(i.index,i.index+this.errorSourceAhead)+"...");var c,u,g;if(e(' def: "'+s[1]+'"'),null!==(r=Preprocessor.VAR.exec(this.source)))g="var",c=r[1],u=r[2],e(" match3(var): "+JSON.stringify(r));else if(null!==(r=Preprocessor.FUNCTION.exec(this.source)))g="function",c=r[1],u=r[2],e(" match3(function): "+JSON.stringify(r));else{if(null===(r=Preprocessor.BOOLVAR.exec(this.source)))throw new Error("Illegal #"+i[2]+": "+this.source.substring(i.index,i.index+this.errorSourceAhead)+"...");g="var",c=r[1],u=!0,e(" match3(boolvar): "+JSON.stringify(r))}e(" type: "+g),e(" identifier: "+c),e(" value: "+u),t[c]={type:g,value:u},e(" defines "+JSON.stringify(t));var p="";this.preserveLineNumbers&&(p=this.source.substring(i.index,Preprocessor.DEFINE.lastIndex).replace(NOT_LINE_ENDING,"")),this.source=this.source.substring(0,i.index)+_+p+this.source.substring(Preprocessor.DEFINE.lastIndex),Preprocessor.EXPR.lastIndex=i.index,e(" continue at "+Preprocessor.EXPR.lastIndex)}}return h.length>0&&e("Still on stack ("+h.length+"): "+JSON.stringify(h.pop())),this.source};var _unused_webpack_default_export=Preprocessor},function(t,e,i){"use strict";i.r(e);var s={};i.r(s),i.d(s,"getShortOpName",(function(){return p})),i.d(s,"shuffleArray",(function(){return _})),i.d(s,"shortId",(function(){return m})),i.d(s,"uuid",(function(){return T})),i.d(s,"generateUUID",(function(){return A})),i.d(s,"simpleId",(function(){return x})),i.d(s,"smoothStep",(function(){return v})),i.d(s,"smootherStep",(function(){return y})),i.d(s,"clamp",(function(){return I})),i.d(s,"map",(function(){return S})),i.d(s,"cacheBust",(function(){return R})),i.d(s,"copyArray",(function(){return P})),i.d(s,"basename",(function(){return O})),i.d(s,"jsonp",(function(){return F})),i.d(s,"ajaxSync",(function(){return C})),i.d(s,"ajax",(function(){return w})),i.d(s,"request",(function(){return M})),i.d(s,"keyCodeToName",(function(){return U})),i.d(s,"UTILS",(function(){return g}));var r={};i.r(r),i.d(r,"base64Chars",(function(){return k})),i.d(r,"base64lookup",(function(){return D})),i.d(r,"b64encTypesArray",(function(){return G})),i.d(r,"b64decTypedArray",(function(){return H}));var n={};i.r(n),i.d(n,"easeExpoIn",(function(){return j})),i.d(n,"easeExpoOut",(function(){return K})),i.d(n,"easeExpoInOut",(function(){return Q})),i.d(n,"easeCubicIn",(function(){return q})),i.d(n,"easeCubicOut",(function(){return J})),i.d(n,"easeCubicInOut",(function(){return Z})),i.d(n,"ANIM",(function(){return X})),i.d(n,"Anim",(function(){return $})),i.d(n,"TL",(function(){return tt}));var o={};i.r(o),i.d(o,"PatchConnectionReceiver",(function(){return Kt})),i.d(o,"PatchConnectionSender",(function(){return Qt})),i.d(o,"PatchConnectorBroadcastChannel",(function(){return qt}));class a{constructor(t){this._logs=[],this.initiator=t}stack(t){console.error("["+this.initiator+"] ",t),console.log((new Error).stack),window.gui&&window.gui.emitEvent("coreLogEvent",this.initiator,"error",t)}groupCollapsed(t){console.groupCollapsed("["+this.initiator+"] "+t)}table(t){console.table(t)}groupEnd(){console.groupEnd()}error(t){console.error("["+this.initiator+"]",...arguments),window.gui&&window.gui.emitEvent("coreLogEvent",this.initiator,"error",arguments)}info(t){console.error("["+this.initiator+"]",...arguments),window.gui&&window.gui.emitEvent("coreLogEvent",this.initiator,"info",arguments)}warn(t){console.warn("["+this.initiator+"]",...arguments),window.gui&&window.gui.emitEvent("coreLogEvent",this.initiator,"warn",arguments)}verbose(){(CABLES.UI&&CABLES.UI.logFilter.shouldPrint(this.initiator,...arguments)||!CABLES.logSilent)&&console.log("["+this.initiator+"]",...arguments),window.gui&&window.gui.emitEvent("coreLogEvent",this.initiator,"verbose",arguments)}log(t){(CABLES.UI&&CABLES.UI.logFilter.shouldPrint(this.initiator,...arguments)||!CABLES.logSilent)&&console.log("["+this.initiator+"]",...arguments),window.gui&&window.gui.emitEvent("coreLogEvent",this.initiator,"log",arguments)}userInteraction(t){}}const h={EASINGS:["linear","absolute","smoothstep","smootherstep","Cubic In","Cubic Out","Cubic In Out","Expo In","Expo Out","Expo In Out","Sin In","Sin Out","Sin In Out","Quart In","Quart Out","Quart In Out","Quint In","Quint Out","Quint In Out","Back In","Back Out","Back In Out","Elastic In","Elastic Out","Bounce In","Bounce Out"],EASING_LINEAR:0,EASING_ABSOLUTE:1,EASING_SMOOTHSTEP:2,EASING_SMOOTHERSTEP:3,EASING_CUBICSPLINE:4,EASING_CUBIC_IN:5,EASING_CUBIC_OUT:6,EASING_CUBIC_INOUT:7,EASING_EXPO_IN:8,EASING_EXPO_OUT:9,EASING_EXPO_INOUT:10,EASING_SIN_IN:11,EASING_SIN_OUT:12,EASING_SIN_INOUT:13,EASING_BACK_IN:14,EASING_BACK_OUT:15,EASING_BACK_INOUT:16,EASING_ELASTIC_IN:17,EASING_ELASTIC_OUT:18,EASING_BOUNCE_IN:19,EASING_BOUNCE_OUT:21,EASING_QUART_IN:22,EASING_QUART_OUT:23,EASING_QUART_INOUT:24,EASING_QUINT_IN:25,EASING_QUINT_OUT:26,EASING_QUINT_INOUT:27},l={OP_PORT_TYPE_VALUE:0,OP_PORT_TYPE_FUNCTION:1,OP_PORT_TYPE_OBJECT:2,OP_PORT_TYPE_TEXTURE:2,OP_PORT_TYPE_ARRAY:3,OP_PORT_TYPE_DYNAMIC:4,OP_PORT_TYPE_STRING:5,OP_VERSION_PREFIX:"_v"},c={PORT_DIR_IN:0,PORT_DIR_OUT:1},u={PACO_CLEAR:0,PACO_VALUECHANGE:1,PACO_OP_DELETE:2,PACO_UNLINK:3,PACO_LINK:4,PACO_LOAD:5,PACO_OP_CREATE:6,PACO_OP_ENABLE:7,PACO_OP_DISABLE:8,PACO_UIATTRIBS:9,PACO_VARIABLES:10,PACO_TRIGGERS:11,PACO_PORT_SETVARIABLE:12,PACO_PORT_SETANIMATED:13,PACO_PORT_ANIM_UPDATED:14,PACO_DESERIALIZE:15},g={float32Concat:function(t,e){t instanceof Float32Array||(t=new Float32Array(t)),e instanceof Float32Array||(e=new Float32Array(e));const i=new Float32Array(t.length+e.length);return i.set(t),i.set(e,t.length),i}},p=function(t){let e=t.split(".")[t.split(".").length-1];if(e.indexOf(l.OP_VERSION_PREFIX)>0){const t=e.split(l.OP_VERSION_PREFIX)[1];e=e.substring(0,e.length-(l.OP_VERSION_PREFIX+t).length)}return e},_=function(t){for(let e=t.length-1;e>0;e--){const i=Math.floor(Math.seededRandom()*(e+1)),s=t[e];t[e]=t[i],t[i]=s}return t},d={},f=function(){let t=Math.random().toString(36).substr(2,9);return d.hasOwnProperty(t)&&(t=f()),d[t]=!0,t},m=f,E=function(){let t=(new Date).getTime();return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const i=(t+16*Math.random())%16|0;return t=Math.floor(t/16),("x"==e?i:3&i|8).toString(16)})},T=E,A=E;let b=0;const x=function(){return b++,b},v=function(t){const e=Math.max(0,Math.min(1,(t-0)/1));return t=e*e*(3-2*e)},y=function(t){const e=Math.max(0,Math.min(1,(t-0)/1));return t=e*e*e*(e*(6*e-15)+10)},I=function(t,e,i){return Math.min(Math.max(t,e),i)},S=function(t,e,i,s,r,n){if(t>=i)return r;if(t<=e)return s;let o=!1;const a=Math.min(e,i),h=Math.max(e,i);a!=e&&(o=!0);let l=!1;const c=Math.min(s,r),u=Math.max(s,r);c!=s&&(l=!0);let g=0,p=0;return g=o?(h-t)*(u-c)/(h-a):(t-a)*(u-c)/(h-a),p=l?u-g:g+c,n?1==n?s+(t=Math.max(0,Math.min(1,(p-s)/(r-s))))*t*(3-2*t)*(r-s):2==n?s+(t=Math.max(0,Math.min(1,(p-s)/(r-s))))*t*t*(t*(6*t-15)+10)*(r-s):p:p};Math.randomSeed=1,Math.seededRandom=function(t,e){0===Math.randomSeed&&(Math.randomSeed=999*Math.random()),t=t||1,e=e||0,Math.randomSeed=(9301*Math.randomSeed+49297)%233280;return e+Math.randomSeed/233280*(t-e)},g.arrayWriteToEnd=function(t,e){for(let e=1;e-1?t+="&":t+="?",t+"cb="+CABLES.uuid()},P=function(t,e){if(!t)return null;(e=e||[]).length=t.length;for(let i=0;i0){let t=i[i.length-1].split("?");e=t[0],t=e.split("."),e=t[0]}return e};let N=null;const F=function(t,e){N=N||0,N++;const i=N;CABLES["jsonpFunc"+i]=function(t){e(!1,t)};let s="?";t.indexOf(s)>-1&&(s="&");const r=document.createElement("script");r.setAttribute("src",t+s+"callback=CABLES.jsonpFunc"+i),document.body.appendChild(r)},C=function(t,e,i,s,r){M({url:t,cb:e,method:i,data:s,contenttype:r,sync:!0})},w=function(t,e,i,s,r,n,o={}){M({url:t,cb:e,method:i,data:s,contenttype:r,sync:!1,jsonP:n,headers:o})},M=function(t){let e;t.hasOwnProperty("asynch")||(t.asynch=!0);try{e=new XMLHttpRequest}catch(t){}if(e.onreadystatechange=function(){4==e.readyState&&t.cb&&(200==e.status||0==e.status?t.cb(!1,e.responseText,e):t.cb(!0,e.responseText,e))},e.addEventListener("progress",t=>{}),e.open(t.method?t.method.toUpperCase():"GET",t.url,!t.sync),"object"==typeof t.headers){const i=Object.keys(t.headers);for(let s=0;sthis._cgl.maxTexSize||e>this._cgl.maxTexSize)&&this._log.error("texture size too big! "+t+"x"+e+" / max: "+this._cgl.maxTexSize),t=Math.min(t,this._cgl.maxTexSize),e=Math.min(e,this._cgl.maxTexSize),t=Math.floor(t),e=Math.floor(e),this.width==t&&this.height==e)return;this.width=t,this.height=e,this.deleted=!1,this.shortInfoString=this.getInfoOneLine(),this._cgl.gl.bindTexture(this.texTarget,this.tex),this._cgl.profileData.profileTextureResize++;if(this._cgl.patch.config.canvas.forceTextureNearest&&(this.filter=B.FILTER_NEAREST),1!=this._cgl.glVersion||this.textureType!=B.TYPE_FLOAT||this.filter!=B.FILTER_LINEAR||this._cgl.gl.getExtension("OES_texture_float_linear")||(console.warn("this graphics card does not support floating point texture linear interpolation! using NEAREST"),this.filter=B.FILTER_NEAREST),this.textureType==B.TYPE_FLOAT)if(1==this._cgl.glVersion)if(this._cgl.glUseHalfFloatTex){const i=this._cgl.gl.getExtension("OES_texture_half_float");this._cgl.gl.getExtension("EXT_color_buffer_half_float");if(!i)throw new Error("no half float texture extension");this._cgl.gl.texImage2D(this.texTarget,0,this._cgl.gl.RGBA,t,e,0,this._cgl.gl.RGBA,i.HALF_FLOAT_OES,null)}else this._cgl.gl.getExtension("OES_texture_float"),this._cgl.gl.texImage2D(this.texTarget,0,this._cgl.gl.RGBA,t,e,0,this._cgl.gl.RGBA,this._cgl.gl.FLOAT,null);else if(this._cgl.glUseHalfFloatTex){if(!this._cgl.gl.getExtension("EXT_color_buffer_half_float"))throw new Error("no half float texture extension");console.log("half float",this._cgl.gl.RGBA16F,this._cgl.gl.HALF_FLOAT),console.log("half float",this._cgl.gl.HALF_FLOAT),console.log("half float",this._cgl.gl.RGBA16F),this._cgl.gl.texImage2D(this.texTarget,0,this._cgl.gl.RGBA,t,e,0,this._cgl.gl.RGBA,this._cgl.gl.HALF_FLOAT,null)}else this._cgl.gl.getExtension("EXT_color_buffer_float"),this._cgl.gl.getExtension("EXT_color_buffer_float_linear"),this._cgl.gl.getExtension("OES_texture_float_linear"),this._cgl.gl.texImage2D(this.texTarget,0,this._cgl.gl.RGBA32F,t,e,0,this._cgl.gl.RGBA,this._cgl.gl.FLOAT,null);else if(this.textureType==B.TYPE_DEPTH)if(1==this._cgl.glVersion){const i=this._cgl.gl.DEPTH_COMPONENT;this._cgl.gl.texImage2D(this.texTarget,0,i,t,e,0,this._cgl.gl.DEPTH_COMPONENT,this._cgl.gl.UNSIGNED_SHORT,null)}else{const i=this._cgl.gl.DEPTH_COMPONENT32F;this._cgl.gl.texImage2D(this.texTarget,0,i,t,e,0,this._cgl.gl.DEPTH_COMPONENT,this._cgl.gl.FLOAT,null)}else this._cgl.gl.texImage2D(this.texTarget,0,this._cgl.gl.RGBA,t,e,0,this._cgl.gl.RGBA,this._cgl.gl.UNSIGNED_BYTE,null);this._setFilter(),this.updateMipMap(),this._cgl.gl.bindTexture(this.texTarget,null)},B.prototype.initFromData=function(t,e,i,s,r){if(this.filter=s,this.wrap=r,null==s&&(this.filter=B.FILTER_LINEAR),null==r&&(this.wrap=B.WRAP_CLAMP_TO_EDGE),this.width=e,this.height=i,this._fromData=!0,this.deleted=!1,this.height>this._cgl.maxTexSize||this.width>this._cgl.maxTexSize){const t=CGL.Texture.getTempTexture(this._cgl);return this.width=t.width,this.height=t.height,this.tex=t.tex,void this._log.error("[cgl_texture] texture size to big!!!",this.width,this.height,this._cgl.maxTexSize)}this.flip&&this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_FLIP_Y_WEBGL,this.flip),this._cgl.gl.bindTexture(this.texTarget,this.tex),this.textureType==B.TYPE_FLOAT?this._cgl.gl.texImage2D(this.texTarget,0,this._cgl.gl.RGBA32F,e,i,0,this._cgl.gl.RGBA,this._cgl.gl.FLOAT,t):this._cgl.gl.texImage2D(this.texTarget,0,this._cgl.gl.RGBA,e,i,0,this._cgl.gl.RGBA,this._cgl.gl.UNSIGNED_BYTE,t),this._setFilter(),this.updateMipMap(),this.flip&&this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_FLIP_Y_WEBGL,!1),this._cgl.gl.bindTexture(this.texTarget,null)},B.prototype.updateMipMap=function(){2!=this._cgl.glVersion&&!this.isPowerOfTwo()||this.filter!=B.FILTER_MIPMAP||(this._cgl.gl.generateMipmap(this.texTarget),this._cgl.profileData.profileGenMipMap++)},B.prototype.initTexture=function(t,e){if(this._cgl.printError("before initTexture"),this._cgl.checkFrameStarted("texture inittexture"),this._fromData=!1,this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL,this.unpackAlpha),t.width&&(this.width=t.width),t.height&&(this.height=t.height),e&&(this.filter=e),t.height>this._cgl.maxTexSize||t.width>this._cgl.maxTexSize){const e=CGL.Texture.getTempTexture(this._cgl);return this.width=e.width,this.height=e.height,this.tex=e.tex,void this._log.error("[cgl_texture] texture size to big!!!",t.width,t.height,this._cgl.maxTexSize)}this._cgl.gl.bindTexture(this.texTarget,this.tex),this.deleted=!1,this.flipped=!this.flip,this.flipped&&this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_FLIP_Y_WEBGL,this.flipped),this._cgl.gl.texImage2D(this.texTarget,0,this._cgl.gl.RGBA,this._cgl.gl.RGBA,this._cgl.gl.UNSIGNED_BYTE,t),this._setFilter(),this.updateMipMap(),this._cgl.gl.bindTexture(this.texTarget,null),this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),this.flipped&&this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_FLIP_Y_WEBGL,!1),this.getInfoOneLine(),this._cgl.printError("initTexture")},B.prototype.delete=function(){this.loading||(this.deleted=!0,this.width=0,this.height=0,this._cgl.profileData.profileTextureDelete++,this._cgl.gl.deleteTexture(this.tex),this.image=null,this.tex=null)},B.prototype.isPowerOfTwo=function(){return B.isPowerOfTwo(this.width)&&B.isPowerOfTwo(this.height)},B.prototype.printInfo=function(){console.log(this.getInfo())},B.prototype.getInfoReadable=function(){const t=this.getInfo();let e="";t.name=t.name.substr(0,t.name.indexOf("?rnd="));for(const i in t)e+="* "+i+": **"+t[i]+"**\n";return e},B.prototype.getInfoOneLine=function(){let t=this.width+"x"+this.height;return this.textureType===CGL.Texture.TYPE_FLOAT?t+=" 32bit":t+=" 8bit",this.filter===CGL.Texture.FILTER_NEAREST&&(t+=" nearest"),this.filter===CGL.Texture.FILTER_LINEAR&&(t+=" linear"),this.filter===CGL.Texture.FILTER_MIPMAP&&(t+=" mipmap"),this.wrap===CGL.Texture.WRAP_CLAMP_TO_EDGE&&(t+=" clamp"),this.wrap===CGL.Texture.WRAP_REPEAT&&(t+=" repeat"),this.wrap===CGL.Texture.WRAP_MIRRORED_REPEAT&&(t+=" repeatmir"),this.shortInfoString=t,t},B.prototype.getInfo=function(){return B.getTexInfo(this)},B.prototype._setFilter=function(){if(this._cgl.printError("before _setFilter"),this._fromData||this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL,this.unpackAlpha),this.shadowMap&&(this._cgl.gl.texParameteri(this._cgl.gl.TEXTURE_2D,this._cgl.gl.TEXTURE_COMPARE_MODE,this._cgl.gl.COMPARE_REF_TO_TEXTURE),this._cgl.gl.texParameteri(this._cgl.gl.TEXTURE_2D,this._cgl.gl.TEXTURE_COMPARE_FUNC,this._cgl.gl.LEQUAL)),this.textureType==B.TYPE_FLOAT&&this.filter==B.FILTER_MIPMAP&&(this.filter=B.FILTER_LINEAR,this._log.stack("texture: HDR and mipmap filtering at the same time is not possible")),1!=this._cgl.glVersion||this.isPowerOfTwo()){if(this.wrap==B.WRAP_CLAMP_TO_EDGE?(this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_WRAP_S,this._cgl.gl.CLAMP_TO_EDGE),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_WRAP_T,this._cgl.gl.CLAMP_TO_EDGE)):this.wrap==B.WRAP_REPEAT?(this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_WRAP_S,this._cgl.gl.REPEAT),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_WRAP_T,this._cgl.gl.REPEAT)):this.wrap==B.WRAP_MIRRORED_REPEAT&&(this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_WRAP_S,this._cgl.gl.MIRRORED_REPEAT),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_WRAP_T,this._cgl.gl.MIRRORED_REPEAT)),this.filter==B.FILTER_NEAREST)this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_MAG_FILTER,this._cgl.gl.NEAREST),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_MIN_FILTER,this._cgl.gl.NEAREST);else if(this.filter==B.FILTER_LINEAR)this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_MIN_FILTER,this._cgl.gl.LINEAR),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_MAG_FILTER,this._cgl.gl.LINEAR);else{if(this.filter!=B.FILTER_MIPMAP)throw this._log.log("unknown texture filter!",this.filter),new Error("unknown texture filter!"+this.filter);this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_MAG_FILTER,this._cgl.gl.LINEAR),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_MIN_FILTER,this._cgl.gl.LINEAR_MIPMAP_LINEAR)}if(this.anisotropic){const t=this._cgl.gl.getExtension("EXT_texture_filter_anisotropic");if(t){const e=this._cgl.gl.getParameter(t.MAX_TEXTURE_MAX_ANISOTROPY_EXT);this._cgl.gl.texParameterf(this._cgl.gl.TEXTURE_2D,t.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(e,this.anisotropic))}}}else this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_MAG_FILTER,this._cgl.gl.NEAREST),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_MIN_FILTER,this._cgl.gl.NEAREST),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_WRAP_S,this._cgl.gl.CLAMP_TO_EDGE),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_WRAP_T,this._cgl.gl.CLAMP_TO_EDGE),this.filter=B.FILTER_NEAREST,this.wrap=B.WRAP_CLAMP_TO_EDGE;this.getInfoOneLine(),this._cgl.printError("_setFilter")},B.load=function(t,e,i,s){if(!e)return i({error:!0});let r=null;t.patch.loading.existByName(e)||(r=t.patch.loading.start("texture",e));const n=new B(t);return n.name=e,t.patch.isEditorMode()&&gui.jobs().start({id:"loadtexture"+r,title:"loading texture "+CABLES.basename(e)}),n.image=new Image,n.image.crossOrigin="anonymous",n.loading=!0,s&&s.hasOwnProperty("filter")&&(n.filter=s.filter),s&&s.hasOwnProperty("flip")&&(n.flip=s.flip),s&&s.hasOwnProperty("wrap")&&(n.wrap=s.wrap),s&&s.hasOwnProperty("anisotropic")&&(n.anisotropic=s.anisotropic),s&&s.hasOwnProperty("unpackAlpha")&&(n.unpackAlpha=s.unpackAlpha),n.image.onabort=n.image.onerror=s=>{console.warn("[cgl.texture.load] error loading texture",e,s),n.loading=!1,r&&t.patch.loading.finished(r);i&&i({error:!0},n),t.patch.isEditorMode()&&gui.jobs().finish("loadtexture"+r)},n.image.onload=function(e){t.addNextFrameOnceCallback(()=>{n.initTexture(n.image),r&&t.patch.loading.finished(r),n.loading=!1,t.patch.isEditorMode()&&gui.jobs().finish("loadtexture"+r),i&&i(null,n)})},n.image.src=e,n},B.getTempTexture=function(t){return t||console.error("[getTempTexture] no cgl!"),t.tempTexture||(t.tempTexture=B.getTemporaryTexture(t,256,B.FILTER_LINEAR,B.REPEAT)),t.tempTexture},B.getEmptyTexture=function(t,e){if(e)return B.getEmptyTextureFloat(t);if(t||console.error("[getEmptyTexture] no cgl!"),t.tempTextureEmpty)return t.tempTextureEmpty;t.tempTextureEmpty=new B(t,{name:"emptyTexture"});const i=new Uint8Array(256).fill(0);for(let t=0;t<256;t+=4)i[t+3]=0;return t.tempTextureEmpty.initFromData(i,8,8,B.FILTER_NEAREST,B.WRAP_REPEAT),t.tempTextureEmpty},B.getEmptyTextureFloat=function(t){if(t||console.error("[getEmptyTextureFloat] no cgl!"),t.tempTextureEmptyFloat)return t.tempTextureEmptyFloat;t.tempTextureEmptyFloat=new B(t,{name:"emptyTexture",isFloatingPointTexture:!0});const e=new Float32Array(256).fill(1);for(let t=0;t<256;t+=4)e[t+3]=0;return t.tempTextureEmptyFloat.initFromData(e,8,8,B.FILTER_NEAREST,B.WRAP_REPEAT),t.tempTextureEmptyFloat},B.getRandomTexture=function(t){if(t||console.error("[getRandomTexture] no cgl!"),t.randomTexture)return t.randomTexture;const e=new Uint8Array(262144);for(let t=0;t<65536;t++)e[4*t+0]=255*Math.random(),e[4*t+1]=255*Math.random(),e[4*t+2]=255*Math.random(),e[4*t+3]=255;return t.randomTexture=new B(t),t.randomTexture.initFromData(e,256,256,B.FILTER_NEAREST,B.WRAP_REPEAT),t.randomTexture},B.getBlackTexture=function(t){if(t||this._log.error("[getBlackTexture] no cgl!"),t.blackTexture)return t.blackTexture;const e=new Uint8Array(256);for(let t=0;t<64;t++)e[4*t+0]=e[4*t+1]=e[4*t+2]=0,e[4*t+3]=255;return t.blackTexture=new B(t),t.blackTexture.initFromData(e,8,8,B.FILTER_NEAREST,B.WRAP_REPEAT),t.blackTexture},B.getEmptyCubemapTexture=function(t){const e=[t.gl.TEXTURE_CUBE_MAP_POSITIVE_X,t.gl.TEXTURE_CUBE_MAP_NEGATIVE_X,t.gl.TEXTURE_CUBE_MAP_POSITIVE_Y,t.gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,t.gl.TEXTURE_CUBE_MAP_POSITIVE_Z,t.gl.TEXTURE_CUBE_MAP_NEGATIVE_Z],i=t.gl.createTexture(),s=t.gl.TEXTURE_CUBE_MAP,r=B.FILTER_NEAREST,n=B.WRAP_CLAMP_TO_EDGE;t.profileData.profileTextureNew++,t.gl.bindTexture(s,i),t.profileData.profileTextureResize++;for(let i=0;i<6;i+=1){const r=new Uint8Array(256);t.gl.texImage2D(e[i],0,t.gl.RGBA,8,8,0,t.gl.RGBA,t.gl.UNSIGNED_BYTE,r),t.gl.texParameteri(s,t.gl.TEXTURE_MAG_FILTER,t.gl.NEAREST),t.gl.texParameteri(s,t.gl.TEXTURE_MIN_FILTER,t.gl.NEAREST),t.gl.texParameteri(s,t.gl.TEXTURE_WRAP_S,t.gl.CLAMP_TO_EDGE),t.gl.texParameteri(s,t.gl.TEXTURE_WRAP_T,t.gl.CLAMP_TO_EDGE)}return t.gl.bindTexture(s,null),{id:CABLES.uuid(),tex:i,cubemap:i,width:8,height:8,filter:r,wrap:n,unpackAlpha:!0,flip:!0,_fromData:!0,name:"emptyCubemapTexture",anisotropic:0}},B.getTempGradientTexture=function(t){if(t||console.error("[getTempGradientTexture] no cgl!"),t.tempTextureGradient)return t.tempTextureGradient;const e=new B(t),i=new Uint8Array(262144);for(let t=0;t<256;t++)for(let e=0;e<256;e++)i[4*(e+256*t)+0]=i[4*(e+256*t)+1]=i[4*(e+256*t)+2]=255-t,i[4*(e+256*t)+3]=255;return e.initFromData(i,256,256,B.FILTER_NEAREST,B.WRAP_REPEAT),t.tempTextureGradient=e,e},B.getTemporaryTexture=function(t,e,i,s){const r=new B(t),n=[];for(let t=0;t>2],r+=k[(3&i[e])<<4|i[e+1]>>4],r+=k[(15&i[e+1])<<2|i[e+2]>>6],r+=k[63&i[e+2]];return s%3==2?r=r.substring(0,r.length-1)+"=":s%3==1&&(r=r.substring(0,r.length-2)+"=="),r},H=function(t){let e,i,s,r,n,o=.75*t.length,a=t.length,h=0;"="===t[t.length-1]&&(o--,"="===t[t.length-2]&&o--);let l=new ArrayBuffer(o),c=new Uint8Array(l);for(e=0;e>4,c[h++]=(15&s)<<4|r>>2,c[h++]=(3&r)<<6|63&n;return l};class z{constructor(t){this._init(),this._first=!0,this._wireMesh=null,t&&this.apply(t)}_init(){this._max=[-Number.MAX_VALUE,-Number.MAX_VALUE,-Number.MAX_VALUE],this._min=[Number.MAX_VALUE,Number.MAX_VALUE,Number.MAX_VALUE],this._center=[0,0,0],this._size=[0,0,0],this._maxAxis=0,this._first=!0}get maxAxis(){return this._maxAxis||1}get size(){return this._size}get center(){return this._center}get x(){return this._center[0]}get y(){return this._center[1]}get z(){return this._center[2]}get minX(){return this._min[0]}get minY(){return this._min[1]}get minZ(){return this._min[2]}get maxX(){return this._max[0]}get maxY(){return this._max[1]}get maxZ(){return this._max[2]}apply(t,e){if(t){if(t instanceof z){const e=t;this.applyPos(e.maxX,e.maxY,e.maxZ),this.applyPos(e.minX,e.minY,e.minZ)}else for(let e=0;e4)&&(console.log("itemsize wrong?",i,t),this._log.stack("itemsize"),i=3),1==i?s="float":2==i?s="vec2":3==i?s="vec3":4==i&&(s="vec4");const r={name:t,data:e,itemSize:i,type:s};this._attributes[t]=r},W.prototype.copyAttribute=function(t,e){const i=this.getAttribute(t);e.setAttribute(t,new Float32Array(i.data),i.itemSize)},W.prototype.setVertices=function(t){t instanceof Float32Array?this._vertices=t:this._vertices=new Float32Array(t)},W.prototype.setTexCoords=function(t){t instanceof Float32Array?this.texCoords=t:this.texCoords=new Float32Array(t)},W.prototype.calcNormals=function(t){t||this.unIndex(),this.calculateNormals({})},W.prototype.flipNormals=function(t,e,i){let s=vec3.create();null==t&&(t=1),null==e&&(e=1),null==i&&(i=1);for(let r=0;r0&&o.push(this.tangents[3*this.verticesIndices[l+0]+0],this.tangents[3*this.verticesIndices[l+0]+1],this.tangents[3*this.verticesIndices[l+0]+2]),this.biTangents.length>0&&a.push(this.biTangents[3*this.verticesIndices[l+0]+0],this.biTangents[3*this.verticesIndices[l+0]+1],this.biTangents[3*this.verticesIndices[l+0]+2]),this.texCoords?r.push(this.texCoords[2*this.verticesIndices[l+0]+0],this.texCoords[2*this.verticesIndices[l+0]+1]):r.push(0,0),s.push(h),h++,i.push(this.vertices[3*this.verticesIndices[l+1]+0],this.vertices[3*this.verticesIndices[l+1]+1],this.vertices[3*this.verticesIndices[l+1]+2]),n.push(this.vertexNormals[3*this.verticesIndices[l+1]+0],this.vertexNormals[3*this.verticesIndices[l+1]+1],this.vertexNormals[3*this.verticesIndices[l+1]+2]),this.tangents.length>0&&o.push(this.tangents[3*this.verticesIndices[l+1]+0],this.tangents[3*this.verticesIndices[l+1]+1],this.tangents[3*this.verticesIndices[l+1]+2]),this.biTangents.length>0&&a.push(this.biTangents[3*this.verticesIndices[l+1]+0],this.biTangents[3*this.verticesIndices[l+1]+1],this.biTangents[3*this.verticesIndices[l+1]+2]),this.texCoords?r.push(this.texCoords[2*this.verticesIndices[l+1]+0],this.texCoords[2*this.verticesIndices[l+1]+1]):r.push(0,0),s.push(h),h++,i.push(this.vertices[3*this.verticesIndices[l+2]+0],this.vertices[3*this.verticesIndices[l+2]+1],this.vertices[3*this.verticesIndices[l+2]+2]),n.push(this.vertexNormals[3*this.verticesIndices[l+2]+0],this.vertexNormals[3*this.verticesIndices[l+2]+1],this.vertexNormals[3*this.verticesIndices[l+2]+2]),this.tangents.length>0&&o.push(this.tangents[3*this.verticesIndices[l+2]+0],this.tangents[3*this.verticesIndices[l+2]+1],this.tangents[3*this.verticesIndices[l+2]+2]),this.biTangents.length>0&&a.push(this.biTangents[3*this.verticesIndices[l+2]+0],this.biTangents[3*this.verticesIndices[l+2]+1],this.biTangents[3*this.verticesIndices[l+2]+2]),this.texCoords?r.push(this.texCoords[2*this.verticesIndices[l+2]+0],this.texCoords[2*this.verticesIndices[l+2]+1]):r.push(0,0),s.push(h),h++;this.vertices=i,this.texCoords=r,this.vertexNormals=n,o.length>0&&(this.tangents=o),a.length>0&&(this.biTangents=a),this.verticesIndices.length=0,t&&(this.verticesIndices=s),e||this.calculateNormals()},W.prototype.calcBarycentric=function(){let t=[];t.length=this.vertices.length;for(let e=0;e1&&this.keys.splice(0,i)},$.prototype.clear=function(t){let e=0;t&&(e=this.getValue(t)),this.keys.length=0,t&&this.setValue(t,e),null!==this.onChange&&this.onChange(),this.emitEvent("onChange",this)},$.prototype.sortKeys=function(){this.keys.sort((t,e)=>parseFloat(t.time)-parseFloat(e.time)),this._needsSort=!1},$.prototype.getLength=function(){return 0===this.keys.length?0:this.keys[this.keys.length-1].time},$.prototype.getKeyIndex=function(t){let e=0;for(let i=0;i=this.keys[i].time&&(e=i),this.keys[i].time>t)return e;return e},$.prototype.setValue=function(t,e,i){let s=null;for(const r in this.keys)if(this.keys[r].time==t){s=this.keys[r],this.keys[r].setValue(e),this.keys[r].cb=i;break}return s||(s=new X.Key({time:t,value:e,e:this.defaultEasing,cb:i}),this.keys.push(s)),this.onChange&&this.onChange(),this.emitEvent("onChange",this),this._needsSort=!0,s},$.prototype.setKeyEasing=function(t,e){this.keys[t]&&(this.keys[t].setEasing(e),this.emitEvent("onChange",this))},$.prototype.getSerialized=function(){const t={keys:[]};t.loop=this.loop;for(const e in this.keys)t.keys.push(this.keys[e].getSerialized());return t},$.prototype.getKey=function(t){const e=this.getKeyIndex(t);return this.keys[e]},$.prototype.getNextKey=function(t){let e=this.getKeyIndex(t)+1;return e>=this.keys.length&&(e=this.keys.length-1),this.keys[e]},$.prototype.isFinished=function(t){return this.keys.length<=0||t>this.keys[this.keys.length-1].time},$.prototype.isStarted=function(t){return!(this.keys.length<=0)&&t>=this.keys[0].time},$.prototype.getValue=function(t){if(0===this.keys.length)return 0;if(this._needsSort&&this.sortKeys(),tthis.keys[e].time){t/this.keys[e].time>this._timesLooped&&(this._timesLooped++,this.onLooped&&this.onLooped()),t=(t-this.keys[0].time)%(this.keys[e].time-this.keys[0].time),t+=this.keys[0].time}const i=this.getKeyIndex(t);if(i>=e)return this.keys[e].cb&&!this.keys[e].cbTriggered&&this.keys[e].trigger(),this.keys[e].value;const s=parseInt(i,10)+1,r=this.keys[i],n=this.keys[s];if(r.cb&&!r.cbTriggered&&r.trigger(),!n)return-1;const o=(t-r.time)/(n.time-r.time);return r.ease||this.log._warn("has no ease",r,n),r.ease(o,n)},$.prototype.addKey=function(t){void 0===t.time?this.log.warn("key time undefined, ignoring!"):(this.keys.push(t),null!==this.onChange&&this.onChange(),this.emitEvent("onChange",this))},$.prototype.easingFromString=function(t){return"linear"==t?h.EASING_LINEAR:"absolute"==t?h.EASING_ABSOLUTE:"smoothstep"==t?h.EASING_SMOOTHSTEP:"smootherstep"==t?h.EASING_SMOOTHERSTEP:"Cubic In"==t?h.EASING_CUBIC_IN:"Cubic Out"==t?h.EASING_CUBIC_OUT:"Cubic In Out"==t?h.EASING_CUBIC_INOUT:"Expo In"==t?h.EASING_EXPO_IN:"Expo Out"==t?h.EASING_EXPO_OUT:"Expo In Out"==t?h.EASING_EXPO_INOUT:"Sin In"==t?h.EASING_SIN_IN:"Sin Out"==t?h.EASING_SIN_OUT:"Sin In Out"==t?h.EASING_SIN_INOUT:"Back In"==t?h.EASING_BACK_IN:"Back Out"==t?h.EASING_BACK_OUT:"Back In Out"==t?h.EASING_BACK_INOUT:"Elastic In"==t?h.EASING_ELASTIC_IN:"Elastic Out"==t?h.EASING_ELASTIC_OUT:"Bounce In"==t?h.EASING_BOUNCE_IN:"Bounce Out"==t?h.EASING_BOUNCE_OUT:"Quart Out"==t?h.EASING_QUART_OUT:"Quart In"==t?h.EASING_QUART_IN:"Quart In Out"==t?h.EASING_QUART_INOUT:"Quint Out"==t?h.EASING_QUINT_OUT:"Quint In"==t?h.EASING_QUINT_IN:"Quint In Out"==t?h.EASING_QUINT_INOUT:void 0},$.prototype.createPort=function(t,e,i){const s=t.inDropDown(e,h.EASINGS);return s.set("linear"),s.defaultValue="linear",s.onChange=function(){this.defaultEasing=this.easingFromString(s.get()),i&&i()}.bind(this),s},$.slerpQuaternion=function(t,e,i,s,r,n){$.slerpQuaternion.q1||($.slerpQuaternion.q1=quat.create(),$.slerpQuaternion.q2=quat.create());const o=i.getKeyIndex(t);let a=o+1;if(a>=i.keys.length&&(a=i.keys.length-1),o==a)quat.set(e,i.keys[o].value,s.keys[o].value,r.keys[o].value,n.keys[o].value);else{const h=i.keys[o].time,l=(t-h)/(i.keys[a].time-h);quat.set($.slerpQuaternion.q1,i.keys[o].value,s.keys[o].value,r.keys[o].value,n.keys[o].value),quat.set($.slerpQuaternion.q2,i.keys[a].value,s.keys[a].value,r.keys[a].value,n.keys[a].value),quat.slerp(e,$.slerpQuaternion.q1,$.slerpQuaternion.q2,l)}return e};const tt=X;tt.Anim=$;const et=function(t,e,i,s){Y.apply(this),this.data={},this._log=new a("core_port"),this.direction=c.PORT_DIR_IN,this.id=CABLES.simpleId(),this.parent=t,this.links=[],this.value=0,this.name=e,this.type=i||l.OP_PORT_TYPE_VALUE,this.uiAttribs=s||{},this.anim=null,this._oldAnimVal=-5711,this.defaultValue=null,this._uiActiveState=!0,this.ignoreValueSerialize=!1,this.onLinkChanged=null,this.crashed=!1,this._valueBeforeLink=null,this._lastAnimFrame=-1,this._animated=!1,this.onValueChanged=null,this.onTriggered=null,this.onUiActiveStateChange=null,this.changeAlways=!1,this._warnedDeprecated=!1,this._useVariableName=null,this.activityCounter=0,this._tempLastUiValue=null,Object.defineProperty(this,"title",{get(){return this.uiAttribs.title||this.name}}),Object.defineProperty(this,"val",{get(){return this._log.warn("val getter deprecated!",this),this._log.stack("val getter deprecated"),this._warnedDeprecated=!0,this.get()},set(t){this._log.warn("val setter deprecated!",this),this._log.stack("val setter deprecated"),this.setValue(t),this._warnedDeprecated=!0}})};et.prototype.copyLinkedUiAttrib=function(t,e){if(!CABLES.UI)return;if(!this.isLinked())return;const i={};i[t]=this.links[0].getOtherPort(this).getUiAttrib(t),e.setUiAttribs(i)},et.prototype.getValueForDisplay=function(){let t=String(this.value);return this.uiAttribs&&"boolnum"==this.uiAttribs.display&&(t+=" - ",this.value?t+="true":t+="false"),t=t.replace(/(<([^>]+)>)/gi,""),t.length>100&&(t=t.substring(0,100)),t},et.prototype.onAnimToggle=function(){},et.prototype._onAnimToggle=function(){this.onAnimToggle()},et.prototype.remove=function(){this.removeLinks(),this.parent.removePort(this)},et.prototype.setUiAttribs=function(t){let e=!1;this.uiAttribs||(this.uiAttribs={});for(const i in t)this.uiAttribs[i]!=t[i]&&(e=!0),this.uiAttribs[i]=t[i],"group"==i&&this.indexPort&&this.indexPort.setUiAttribs({group:t[i]});e&&this.emitEvent("onUiAttrChange",t,this)},et.prototype.getUiAttribs=function(){return this.uiAttribs},et.prototype.getUiAttrib=function(t){return this.uiAttribs&&this.uiAttribs.hasOwnProperty(t)?this.uiAttribs[t]:null},et.prototype.get=function(){return this._animated&&this._lastAnimFrame!=this.parent.patch.getFrameNum()&&(this._lastAnimFrame=this.parent.patch.getFrameNum(),this.value=this.anim.getValue(this.parent.patch.timer.getTime()),this._oldAnimVal=this.value,this.forceChange()),this.value},et.prototype.set=et.prototype.setValue=function(t){if(void 0!==t&&this.parent.enabled&&!this.crashed&&(t!==this.value||this.changeAlways||this.type==l.OP_PORT_TYPE_TEXTURE||this.type==l.OP_PORT_TYPE_ARRAY)){if(this._animated)this.anim.setValue(this.parent.patch.timer.getTime(),t);else{try{this.value=t,this.forceChange()}catch(t){this.crashed=!0,this.setValue=function(t){},this.onTriggered=function(){},this._log.error("onvaluechanged exception cought",t),this._log.error(t.stack),this._log.warn("exception in: "+this.parent.name),this.parent.patch.isEditorMode()&&gui.showOpCrash(this.parent),this.parent.patch.emitEvent("exception",t,this.parent),this.parent.onError&&this.parent.onError(t)}this.parent&&this.parent.patch&&this.parent.patch.isEditorMode()&&this.type==l.OP_PORT_TYPE_TEXTURE&&gui.texturePreview().updateTexturePort(this)}if(this.direction==c.PORT_DIR_OUT)for(let t=0;t{this.parent.patch.emitEvent("portAnimUpdated",this.parent,this,this.anim)}),t.anim.loop&&(this.anim.loop=t.anim.loop);for(const e in t.anim.keys)this.anim.keys.push(new X.Key(t.anim.keys[e]))}},et.prototype.getSerialized=function(){const t={};if(t.name=this.getName(),this.ignoreValueSerialize||0!==this.links.length||this.type==l.OP_PORT_TYPE_OBJECT&&this.value&&this.value.tex||(t.value=this.value),this._useVariableName&&(t.useVariable=this._useVariableName),this._animated&&(t.animated=!0),this.anim&&(t.anim=this.anim.getSerialized()),"file"==this.uiAttribs.display&&(t.display=this.uiAttribs.display),this.direction==c.PORT_DIR_OUT&&this.links.length>0){t.links=[];for(const e in this.links)!this.links[e].ignoreInSerialize&&this.links[e].portIn&&this.links[e].portOut&&t.links.push(this.links[e].getSerialized())}return t},et.prototype.shouldLink=function(){return!0},et.prototype.removeLinks=function(){let t=0;for(;this.links.length>0;){if(t++,t>5e3){this._log.warn("could not delete links... / infinite loop"),this.links.length=0;break}this.links[0].remove()}},et.prototype.removeLink=function(t){for(const e in this.links)this.links[e]==t&&this.links.splice(e,1);this.direction==c.PORT_DIR_IN&&(this.type==l.OP_PORT_TYPE_VALUE?this.setValue(this._valueBeforeLink||0):this.setValue(this._valueBeforeLink||null)),CABLES.UI&&this.parent.checkLinkTimeWarnings&&this.parent.checkLinkTimeWarnings(),this.onLinkChanged&&this.onLinkChanged(),this.emitEvent("onLinkChanged"),this.parent.emitEvent("onLinkChanged")},et.prototype.getName=function(){return this.name},et.prototype.addLink=function(t){this._valueBeforeLink=this.value,this.links.push(t),CABLES.UI&&this.parent.checkLinkTimeWarnings&&this.parent.checkLinkTimeWarnings(),this.onLinkChanged&&this.onLinkChanged(),this.emitEvent("onLinkChanged"),this.parent.emitEvent("onLinkChanged")},et.prototype.getLinkTo=function(t){for(const e in this.links)if(this.links[e].portIn==t||this.links[e].portOut==t)return this.links[e]},et.prototype.removeLinkTo=function(t){for(const e in this.links)if(this.links[e].portIn==t||this.links[e].portOut==t)return this.links[e].remove(),CABLES.UI&&this.parent.checkLinkTimeWarnings&&this.parent.checkLinkTimeWarnings(),this.onLinkChanged&&this.onLinkChanged(),void this.emitEvent("onLinkChanged")},et.prototype.isLinkedTo=function(t){for(const e in this.links)if(this.links[e].portIn==t||this.links[e].portOut==t)return!0;return!1},et.prototype._activity=function(){this.activityCounter++},et.prototype.trigger=function(){if(this._activity(),0===this.links.length)return;if(!this.parent.enabled)return;let t=null;try{for(let e=0;e{this.set(null),this.set(this._variableIn.getValue())}):this._varChangeListenerId=this._variableIn.on("change",this.set.bind(this)),this.set(this._variableIn.getValue())):this._log.warn("PORT VAR NOT FOUND!!!",t),this._useVariableName=t,e.useVariable=!0,e.variableName=this._useVariableName):(e.variableName=this._useVariableName=null,e.useVariable=!1),this.setUiAttribs(e),this.parent.patch.emitEvent("portSetVariable",this.parent,this,t)},et.prototype._handleNoTriggerOpAnimUpdates=function(t){let e=!1;for(let t=0;t{this.updateAnim()}):this.parent.patch.removeEventListener(this._notriggerAnimUpdate))},et.prototype.setAnimated=function(t){this._animated!=t&&(this._animated=t,this._animated&&!this.anim&&(this.anim=new $,this.anim.addEventListener("onChange",()=>{this.parent.patch.emitEvent("portAnimUpdated",this.parent,this,this.anim)})),this._onAnimToggle()),this._handleNoTriggerOpAnimUpdates(t),this.setUiAttribs({isAnimated:this._animated})},et.prototype.toggleAnim=function(){this._animated=!this._animated,this._animated&&!this.anim&&(this.anim=new $,this.anim.addEventListener("onChange",()=>{this.parent.patch.emitEvent("portAnimUpdated",this.parent,this,this.anim)})),this.setAnimated(this._animated),this._onAnimToggle(),this.setUiAttribs({isAnimated:this._animated})},et.prototype.getType=function(){return this.type},et.prototype.isLinked=function(){return this.links.length>0||this._animated||null!=this._useVariableName},et.prototype.isBoundToVar=function(){return null!=this._useVariableName},et.prototype.isAnimated=function(){return this._animated},et.prototype.isHidden=function(){return this.uiAttribs.hidePort},et.prototype._onTriggered=function(t){this._activity(),this.parent.updateAnims(),this.parent.enabled&&this.onTriggered&&this.onTriggered(t)},et.prototype._onSetProfiling=function(t){this.parent.patch.profiler.add("port",this),this.setValue(t),this.parent.patch.profiler.add("port",null)},et.prototype._onTriggeredProfiling=function(){this.parent.enabled&&this.onTriggered&&(this.parent.patch.profiler.add("port",this),this.onTriggered(),this.parent.patch.profiler.add("port",null))},et.prototype.onValueChange=function(t){this.onChange=t},et.prototype.getUiActiveState=function(){return this._uiActiveState},et.prototype.setUiActiveState=function(t){this._uiActiveState=t,this.onUiActiveStateChange&&this.onUiActiveStateChange()},et.prototype.hidePort=function(){this._log.warn("op.hideport() is deprecated, do not use it!")},et.portTypeNumberToString=function(t){return t==l.OP_PORT_TYPE_VALUE?"value":t==l.OP_PORT_TYPE_FUNCTION?"function":t==l.OP_PORT_TYPE_OBJECT?"object":t==l.OP_PORT_TYPE_ARRAY?"array":t==l.OP_PORT_TYPE_STRING?"string":t==l.OP_PORT_TYPE_DYNAMIC?"dynamic":"unknown"};class it extends et{constructor(t,e,i,s,r){super(t,e,i,s),this.indexPort=r,this.indexPort.set=t=>{const e=s.values;if(!e)return;let i=Math.floor(t);i=Math.min(i,e.length-1),i=Math.max(i,0),this.indexPort.setValue(i),this.set(e[i]),this.parent.patch.isEditorMode()&&window.gui&&gui.patchView.isCurrentOp(this.parent)&&gui.opParams.show(this.parent)}}setUiAttribs(t){const e=t.hidePort;t.hidePort=!0,super.setUiAttribs(t),void 0!==e&&this.indexPort.setUiAttribs({hidePort:e})}}class st extends it{setUiAttribs(t){if(this.indexPort.isLinked())for(const e in t)"greyout"!=e||t[e]||(t[e]="true");super.setUiAttribs(t)}}var rt=class{constructor(t,e,i,s,r,n,o,h,l,c){if(this._log=new a("cg_uniform"),this._type=e,this._name=i,this._shader=t,this._value=1e-5,this._oldValue=null,this._port=null,this._structName=l,this._structUniformName=h,this._propertyName=c,this._shader._addUniform(this),this.needsUpdate=!0,this.shaderType=null,this.comment=null,"f"==e)this.set=this.setValue=this.setValueF.bind(this),this.updateValue=this.updateValueF.bind(this);else if("f[]"==e)this.set=this.setValue=this.setValueArrayF.bind(this),this.updateValue=this.updateValueArrayF.bind(this);else if("2f[]"==e)this.set=this.setValue=this.setValueArray2F.bind(this),this.updateValue=this.updateValueArray2F.bind(this);else if("3f[]"==e)this.set=this.setValue=this.setValueArray3F.bind(this),this.updateValue=this.updateValueArray3F.bind(this);else if("4f[]"==e)this.set=this.setValue=this.setValueArray4F.bind(this),this.updateValue=this.updateValueArray4F.bind(this);else if("i"==e)this.set=this.setValue=this.setValueI.bind(this),this.updateValue=this.updateValueI.bind(this);else if("2i"==e)this.set=this.setValue=this.setValue2I.bind(this),this.updateValue=this.updateValue2I.bind(this);else if("3i"==e)this.set=this.setValue=this.setValue3I.bind(this),this.updateValue=this.updateValue3I.bind(this);else if("4i"==e)this.set=this.setValue=this.setValue4I.bind(this),this.updateValue=this.updateValue4I.bind(this);else if("b"==e)this.set=this.setValue=this.setValueBool.bind(this),this.updateValue=this.updateValueBool.bind(this);else if("4f"==e)this.set=this.setValue=this.setValue4F.bind(this),this.updateValue=this.updateValue4F.bind(this);else if("3f"==e)this.set=this.setValue=this.setValue3F.bind(this),this.updateValue=this.updateValue3F.bind(this);else if("2f"==e)this.set=this.setValue=this.setValue2F.bind(this),this.updateValue=this.updateValue2F.bind(this);else if("t"==e)this.set=this.setValue=this.setValueT.bind(this),this.updateValue=this.updateValueT.bind(this);else if("tc"==e)this.set=this.setValue=this.setValueT.bind(this),this.updateValue=this.updateValueT.bind(this);else if("t[]"==e)this.set=this.setValue=this.setValueArrayT.bind(this),this.updateValue=this.updateValueArrayT.bind(this);else{if("m4"!=e&&"m4[]"!=e)throw new Error("Unknown uniform type");this.set=this.setValue=this.setValueM4.bind(this),this.updateValue=this.updateValueM4.bind(this)}"object"==typeof s&&s instanceof et?(this._port=s,this._value=this._port.get(),r&&n&&o?(r instanceof et&&n instanceof et&&o instanceof et||this._log.error("[cgl_uniform] mixed port/value parameter for vec4 ",this._name),this._value=[0,0,0,0],this._port2=r,this._port3=n,this._port4=o,this._port.on("change",this.updateFromPort4f.bind(this)),this._port2.on("change",this.updateFromPort4f.bind(this)),this._port3.on("change",this.updateFromPort4f.bind(this)),this._port4.on("change",this.updateFromPort4f.bind(this)),this.updateFromPort4f()):r&&n?(r instanceof et&&n instanceof et||this._log.error("[cgl_uniform] mixed port/value parameter for vec4 ",this._name),this._value=[0,0,0],this._port2=r,this._port3=n,this._port.on("change",this.updateFromPort3f.bind(this)),this._port2.on("change",this.updateFromPort3f.bind(this)),this._port3.on("change",this.updateFromPort3f.bind(this)),this.updateFromPort3f()):r?(r instanceof et||this._log.error("[cgl_uniform] mixed port/value parameter for vec4 ",this._name),this._value=[0,0],this._port2=r,this._port.on("change",this.updateFromPort2f.bind(this)),this._port2.on("change",this.updateFromPort2f.bind(this)),this.updateFromPort2f()):this._port.on("change",this.updateFromPort.bind(this))):this._value=s,this.setValue(this._value),this.needsUpdate=!0}getType(){return this._type}getName(){return this._name}getValue(){return this._value}getShaderType(){return this.shaderType}isStructMember(){return!!this._structName}updateFromPort4f(){this._value[0]=this._port.get(),this._value[1]=this._port2.get(),this._value[2]=this._port3.get(),this._value[3]=this._port4.get(),this.setValue(this._value)}updateFromPort3f(){this._value[0]=this._port.get(),this._value[1]=this._port2.get(),this._value[2]=this._port3.get(),this.setValue(this._value)}updateFromPort2f(){this._value[0]=this._port.get(),this._value[1]=this._port2.get(),this.setValue(this._value)}updateFromPort(){this.setValue(this._port.get())}};class nt extends rt{constructor(t,e,i,s,r,n,o,a,h,l){super(t,e,i,s,r,n,o,a,h,l),this._loc=-1,this._cgl=t._cgl}copy(t){const e=new nt(t,this._type,this._name,this._value,this._port2,this._port3,this._port4,this._structUniformName,this._structName,this._propertyName);return e.shaderType=this.shaderType,e}getGlslTypeString(){return nt.glslTypeString(this._type)}_isValidLoc(){return-1!=this._loc}resetLoc(){this._loc=-1,this.needsUpdate=!0}bindTextures(){}getLoc(){return this._loc}updateFromPort4f(){this._value[0]=this._port.get(),this._value[1]=this._port2.get(),this._value[2]=this._port3.get(),this._value[3]=this._port4.get(),this.setValue(this._value)}updateFromPort3f(){this._value[0]=this._port.get(),this._value[1]=this._port2.get(),this._value[2]=this._port3.get(),this.setValue(this._value)}updateFromPort2f(){this._value[0]=this._port.get(),this._value[1]=this._port2.get(),this.setValue(this._value)}updateFromPort(){this.setValue(this._port.get())}updateValueF(){this._isValidLoc()?this.needsUpdate=!1:this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._shader.getCgl().gl.uniform1f(this._loc,this._value),this._cgl.profileData.profileUniformCount++}setValueF(t){t!=this._value&&(this.needsUpdate=!0,this._value=t)}updateValueI(){this._isValidLoc()?this.needsUpdate=!1:this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._shader.getCgl().gl.uniform1i(this._loc,this._value),this._cgl.profileData.profileUniformCount++}updateValue2I(){this._value&&(this._isValidLoc()||(this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._cgl.profileData.profileShaderGetUniform++,this._cgl.profileData.profileShaderGetUniformName=this._name),this._shader.getCgl().gl.uniform2i(this._loc,this._value[0],this._value[1]),this.needsUpdate=!1,this._cgl.profileData.profileUniformCount++)}updateValue3I(){this._value&&(this._isValidLoc()||(this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._cgl.profileData.profileShaderGetUniform++,this._cgl.profileData.profileShaderGetUniformName=this._name),this._shader.getCgl().gl.uniform3i(this._loc,this._value[0],this._value[1],this._value[2]),this.needsUpdate=!1,this._cgl.profileData.profileUniformCount++)}updateValue4I(){this._isValidLoc()||(this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._cgl.profileData.profileShaderGetUniform++,this._cgl.profileData.profileShaderGetUniformName=this._name),this._shader.getCgl().gl.uniform4i(this._loc,this._value[0],this._value[1],this._value[2],this._value[3]),this._cgl.profileData.profileUniformCount++}setValueI(t){t!=this._value&&(this.needsUpdate=!0,this._value=t)}setValue2I(t){t&&(this._oldValue?t[0]==this._oldValue[0]&&t[1]==this._oldValue[1]||(this._oldValue[0]=t[0],this._oldValue[1]=t[1],this.needsUpdate=!0):(this._oldValue=[t[0]-1,1],this.needsUpdate=!0),this._value=t)}setValue3I(t){t&&(this._oldValue?t[0]==this._oldValue[0]&&t[1]==this._oldValue[1]&&t[2]==this._oldValue[2]||(this._oldValue[0]=t[0],this._oldValue[1]=t[1],this._oldValue[2]=t[2],this.needsUpdate=!0):(this._oldValue=[t[0]-1,1,2],this.needsUpdate=!0),this._value=t)}setValue4I(t){this.needsUpdate=!0,this._value=t||vec4.create()}updateValueBool(){this._isValidLoc()?this.needsUpdate=!1:this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._shader.getCgl().gl.uniform1i(this._loc,this._value?1:0),this._cgl.profileData.profileUniformCount++}setValueBool(t){t!=this._value&&(this.needsUpdate=!0,this._value=t)}setValueArray4F(t){this.needsUpdate=!0,this._value=t}updateValueArray4F(){this._isValidLoc()?this.needsUpdate=!1:this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._value&&(this._shader.getCgl().gl.uniform4fv(this._loc,this._value),this._cgl.profileData.profileUniformCount++)}setValueArray3F(t){this.needsUpdate=!0,this._value=t}updateValueArray3F(){this._isValidLoc()?this.needsUpdate=!1:this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._value&&(this._shader.getCgl().gl.uniform3fv(this._loc,this._value),this._cgl.profileData.profileUniformCount++)}setValueArray2F(t){this.needsUpdate=!0,this._value=t}updateValueArray2F(){this._isValidLoc()?this.needsUpdate=!1:this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._value&&(this._shader.getCgl().gl.uniform2fv(this._loc,this._value),this._cgl.profileData.profileUniformCount++)}setValueArrayF(t){this.needsUpdate=!0,this._value=t}updateValueArrayF(){this._isValidLoc()?this.needsUpdate=!1:this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._value&&(this._shader.getCgl().gl.uniform1fv(this._loc,this._value),this._cgl.profileData.profileUniformCount++)}setValueArrayT(t){this.needsUpdate=!0,this._value=t}updateValue3F(){this._value&&(this._isValidLoc()||(this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._cgl.profileData.profileShaderGetUniform++,this._cgl.profileData.profileShaderGetUniformName=this._name),this._shader.getCgl().gl.uniform3f(this._loc,this._value[0],this._value[1],this._value[2]),this.needsUpdate=!1,this._cgl.profileData.profileUniformCount++)}setValue3F(t){t&&(this._oldValue?t[0]==this._oldValue[0]&&t[1]==this._oldValue[1]&&t[2]==this._oldValue[2]||(this._oldValue[0]=t[0],this._oldValue[1]=t[1],this._oldValue[2]=t[2],this.needsUpdate=!0):(this._oldValue=[t[0]-1,1,2],this.needsUpdate=!0),this._value=t)}updateValue2F(){this._value&&(this._isValidLoc()||(this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._cgl.profileData.profileShaderGetUniform++,this._cgl.profileData.profileShaderGetUniformName=this._name),this._shader.getCgl().gl.uniform2f(this._loc,this._value[0],this._value[1]),this.needsUpdate=!1,this._cgl.profileData.profileUniformCount++)}setValue2F(t){t&&(this._oldValue?t[0]==this._oldValue[0]&&t[1]==this._oldValue[1]||(this._oldValue[0]=t[0],this._oldValue[1]=t[1],this.needsUpdate=!0):(this._oldValue=[t[0]-1,1],this.needsUpdate=!0),this._value=t)}updateValue4F(){this._isValidLoc()||(this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._cgl.profileData.profileShaderGetUniform++,this._cgl.profileData.profileShaderGetUniformName=this._name),this._value||(this._log.warn("no value for uniform",this._name,this),this._value=[0,0,0,0]),this.needsUpdate=!1,this._shader.getCgl().gl.uniform4f(this._loc,this._value[0],this._value[1],this._value[2],this._value[3]),this._cgl.profileData.profileUniformCount++}setValue4F(t){"number"==typeof this.value&&(this.value=vec4.create()),t&&(this._oldValue?t[0]==this._oldValue[0]&&t[1]==this._oldValue[1]&&t[2]==this._oldValue[2]&&t[3]==this._oldValue[3]||(this._oldValue[0]=t[0],this._oldValue[1]=t[1],this._oldValue[2]=t[2],this.needsUpdate=!0):(this._oldValue=[t[0]-1,1,2,3],this.needsUpdate=!0),this._value=t)}updateValueM4(){if(this._isValidLoc()||(this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._cgl.profileData.profileShaderGetUniform++,this._cgl.profileData.profileShaderGetUniformName=this._name),!this._value||this._value.length%16!=0)return console.log("this.name",this._name,this._value);this._shader.getCgl().gl.uniformMatrix4fv(this._loc,!1,this._value),this._cgl.profileData.profileUniformCount++}setValueM4(t){this.needsUpdate=!0,this._value=t||mat4.create()}updateValueArrayT(){this._isValidLoc()?this.needsUpdate=!1:this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._value&&(this._shader.getCgl().gl.uniform1iv(this._loc,this._value),this._cgl.profileData.profileUniformCount++)}updateValueT(){this._isValidLoc()||(this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._cgl.profileData.profileShaderGetUniform++,this._cgl.profileData.profileShaderGetUniformName=this._name),this._cgl.profileData.profileUniformCount++,this._shader.getCgl().gl.uniform1i(this._loc,this._value),this.needsUpdate=!1}setValueT(t){this.needsUpdate=!0,this._value=t}}nt.glslTypeString=t=>"f"==t?"float":"b"==t?"bool":"i"==t?"int":"2i"==t?"ivec2":"2f"==t?"vec2":"3f"==t?"vec3":"4f"==t?"vec4":"m4"==t?"mat4":"t"==t?"sampler2D":"tc"==t?"samplerCube":"3f[]"==t||"m4[]"==t||"f[]"==t?null:void(void 0)._log.warn("[CGL UNIFORM] unknown glsl type string ",t);const ot=180/Math.PI,at={MATH:{DEG2RAD:Math.PI/180,RAD2DEG:ot},SHADER:{SHADERVAR_VERTEX_POSITION:"vPosition",SHADERVAR_VERTEX_NUMBER:"attrVertIndex",SHADERVAR_VERTEX_NORMAL:"attrVertNormal",SHADERVAR_VERTEX_TEXCOORD:"attrTexCoord",SHADERVAR_INSTANCE_MMATRIX:"instMat",SHADERVAR_VERTEX_COLOR:"attrVertColor",SHADERVAR_UNI_PROJMAT:"projMatrix",SHADERVAR_UNI_VIEWMAT:"viewMatrix",SHADERVAR_UNI_MODELMAT:"modelMatrix",SHADERVAR_UNI_NORMALMAT:"normalMatrix",SHADERVAR_UNI_INVVIEWMAT:"inverseViewMatrix",SHADERVAR_UNI_INVPROJMAT:"invProjMatrix",SHADERVAR_UNI_VIEWPOS:"camPos"},BLEND_MODES:{BLEND_NONE:0,BLEND_NORMAL:1,BLEND_ADD:2,BLEND_SUB:3,BLEND_MUL:4}};const ht={lastMesh:null},lt=function(t,e,i){this._cgl=t,this._log=new a("cgl_mesh"),this._bufVertexAttrib=null,this._bufVerticesIndizes=this._cgl.gl.createBuffer(),this._indexType=this._cgl.gl.UNSIGNED_SHORT,this._attributes=[],this._attribLocs={},this._geom=null,this._lastShader=null,this._numInstances=0,this._glPrimitive=i,this._preWireframeGeom=null,this.addVertexNumbers=!1,this.feedBackAttributes=[],this.setGeom(e),this._feedBacks=[],this._feedBacksChanged=!1,this._transformFeedBackLoc=-1,this._lastAttrUpdate=0,this._name="unknown",this._cgl.profileData.addHeavyEvent("mesh constructed",this._name),this._queryExt=null,Object.defineProperty(this,"numInstances",{get(){return this._numInstances},set(t){this.setNumInstances(t)}})};var ct;lt.prototype.updateVertices=function(t){this.setAttribute(at.SHADER.SHADERVAR_VERTEX_POSITION,t.vertices,3),this._numVerts=t.vertices.length/3},lt.prototype.setAttributePointer=function(t,e,i,s){for(let r=0;r=e.length-1&&this._log.log(this._cgl.canvas.id+" "+t.name+" buffersubdata out of bounds ?",e.length,s,i,t),1==this._cgl.glVersion?this._cgl.gl.bufferSubData(this._cgl.gl.ARRAY_BUFFER,0,e):this._cgl.gl.bufferSubData(this._cgl.gl.ARRAY_BUFFER,4*i,e,i,s-i))},lt.prototype._resizeAttr=function(t,e){e.buffer&&this._cgl.gl.deleteBuffer(e.buffer),e.buffer=this._cgl.gl.createBuffer(),this._cgl.gl.bindBuffer(this._cgl.gl.ARRAY_BUFFER,e.buffer),this._bufferArray(t,e),e.numItems=t.length/e.itemSize},lt.prototype._bufferArray=function(t,e){let i=null;t&&(this._cgl.debugOneFrame&&console.log("_bufferArray",t.length,e.name),t instanceof Float32Array?i=t:e&&i&&i.length==t.length?i.set(t):(i=new Float32Array(t),this._cgl.debugOneFrame&&console.log("_bufferArray create new float32array",t.length,e.name),this._cgl.profileData.profileNonTypedAttrib++,this._cgl.profileData.profileNonTypedAttribNames="("+this._name+":"+e.name+")"),e.arrayLength=i.length,this._cgl.gl.bufferData(this._cgl.gl.ARRAY_BUFFER,i,this._cgl.gl.DYNAMIC_DRAW))},lt.prototype.addAttribute=lt.prototype.updateAttribute=lt.prototype.setAttribute=function(t,e,i,s){if(!e)throw this._log.error("mesh addAttribute - no array given! "+t),new Error;let r=null,n=!1,o=0;const a=e.length/i;for(this._cgl.profileData.profileMeshAttributes+=a||0,"function"==typeof s&&(r=s),"object"==typeof s&&(s.cb&&(r=s.cb),s.instanced&&(n=s.instanced)),t==at.SHADER.SHADERVAR_INSTANCE_MMATRIX&&(n=!0),o=0;o0)this.setAttribute(at.SHADER.SHADERVAR_VERTEX_TEXCOORD,t.texCoords,2);else{const e=new Float32Array(Math.round(t.vertices.length/3*2));this.setAttribute(at.SHADER.SHADERVAR_VERTEX_TEXCOORD,e,2)}},lt.prototype.updateNormals=function(t){if(t.vertexNormals&&t.vertexNormals.length>0)this.setAttribute(at.SHADER.SHADERVAR_VERTEX_NORMAL,t.vertexNormals,3);else{const e=new Float32Array(Math.round(t.vertices.length));this.setAttribute(at.SHADER.SHADERVAR_VERTEX_NORMAL,e,3)}},lt.prototype._setVertexNumbers=function(t){if(!this._verticesNumbers||this._verticesNumbers.length!=this._numVerts||t){if(t)this._verticesNumbers=t;else{this._verticesNumbers=new Float32Array(this._numVerts);for(let t=0;t{i.uniformNumVertices||(i.uniformNumVertices=new nt(i,"f","numVertices",this._numVerts)),i.uniformNumVertices.setValue(this._numVerts)})}},lt.prototype.setVertexIndices=function(t){if(this._bufVerticesIndizes)if(t.length>0){for(let e=0;e=this._numVerts)return void this._log.warn("invalid index in "+this._name);this._cgl.gl.bindBuffer(this._cgl.gl.ELEMENT_ARRAY_BUFFER,this._bufVerticesIndizes),t instanceof Float32Array&&this._log.warn("vertIndices float32Array: "+this._name),t instanceof Uint32Array?(this.vertIndicesTyped=t,this._indexType=this._cgl.gl.UNSIGNED_INT):t instanceof Uint16Array?this.vertIndicesTyped=t:this.vertIndicesTyped=new Uint16Array(t),this._cgl.gl.bufferData(this._cgl.gl.ELEMENT_ARRAY_BUFFER,this.vertIndicesTyped,this._cgl.gl.DYNAMIC_DRAW),this._bufVerticesIndizes.itemSize=1,this._bufVerticesIndizes.numItems=t.length}else this._bufVerticesIndizes.numItems=0;else this._log.warn("no bufVerticesIndizes: "+this._name)},lt.prototype.setGeom=function(t,e){this._geom=t,null!=t.glPrimitive&&(this._glPrimitive=t.glPrimitive),this._geom&&this._geom.name&&(this._name="mesh "+this._geom.name),ht.lastMesh=null,this._cgl.profileData.profileMeshSetGeom++,this._disposeAttributes(),this.updateVertices(this._geom),this.setVertexIndices(this._geom.verticesIndices),this.addVertexNumbers&&this._setVertexNumbers();const i=this._geom.getAttributes(),s={texCoords:at.SHADER.SHADERVAR_VERTEX_TEXCOORD,vertexNormals:at.SHADER.SHADERVAR_VERTEX_NORMAL,vertexColors:at.SHADER.SHADERVAR_VERTEX_COLOR,tangents:"attrTangent",biTangents:"attrBiTangent"};for(const t in i)i[t].data&&i[t].data.length&&this.setAttribute(s[t]||t,i[t].data,i[t].itemSize);e&&(this._geom=null)},lt.prototype._preBind=function(t){for(let e=0;ethis._lastAttrUpdate||e.length!=this._attributes.length){this._lastAttrUpdate=t.lastCompile;for(let t=0;t=0&&this._cgl.gl.disableVertexAttribArray(e[t])):(this._cgl.gl.vertexAttribDivisor(e[t],0),this._cgl.gl.vertexAttribDivisor(e[t]+1,0),this._cgl.gl.vertexAttribDivisor(e[t]+2,0),this._cgl.gl.vertexAttribDivisor(e[t]+3,0),this._cgl.gl.disableVertexAttribArray(e[t]+1),this._cgl.gl.disableVertexAttribArray(e[t]+2),this._cgl.gl.disableVertexAttribArray(e[t]+3))),-1!=e[t]&&this._cgl.gl.disableVertexAttribArray(e[t])},lt.prototype.meshChanged=function(){return this._cgl.lastMesh&&this._cgl.lastMesh!=this},lt.prototype.printDebug=function(t){console.log("--attributes");for(let t=0;t0},ct.prototype.removeFeedbacks=function(t){this._feedbacks&&(this._feedbacks.length=0,this._feedBacksChanged=!0)},ct.prototype.setAttributeFeedback=function(){},ct.prototype.setFeedback=function(t,e,i){let s={nameOut:e},r=!1;this.unBindFeedbacks();for(let t=0;t=e)return t.setUiError("texeffect",null),!0;e&&t.patch.cgl.currentTextureEffect.imgCompVer="+e+' Downgrade to previous version",1)}return!!t.patch.cgl.currentTextureEffect||(t.patch.cgl.currentTextureEffect||t.uiAttribs.uierrors&&0!=t.uiAttribs.uierrors.length?!!t.patch.cgl.currentTextureEffect:(t.setUiError("texeffect",'This op must be a child of an ImageCompose op! More infos here. ',1),!1))},gt.getBlendCode=function(t){let e="".endl()+"vec3 _blend(vec3 base,vec3 blend)".endl()+"{".endl()+" vec3 colNew=blend;".endl()+" #ifdef BM_MULTIPLY".endl()+" colNew=base*blend;".endl()+" #endif".endl()+" #ifdef BM_MULTIPLY_INV".endl()+" colNew=base* vec3(1.0)-blend;".endl()+" #endif".endl()+" #ifdef BM_AVERAGE".endl()+" colNew=((base + blend) / 2.0);".endl()+" #endif".endl()+" #ifdef BM_ADD".endl()+" colNew=min(base + blend, vec3(1.0));".endl()+" #endif".endl()+" #ifdef BM_SUBTRACT_ONE".endl()+" colNew=max(base + blend - vec3(1.0), vec3(0.0));".endl()+" #endif".endl()+" #ifdef BM_SUBTRACT".endl()+" colNew=base - blend;".endl()+" #endif".endl()+" #ifdef BM_DIFFERENCE".endl()+" colNew=abs(base - blend);".endl()+" #endif".endl()+" #ifdef BM_NEGATION".endl()+" colNew=(vec3(1.0) - abs(vec3(1.0) - base - blend));".endl()+" #endif".endl()+" #ifdef BM_EXCLUSION".endl()+" colNew=(base + blend - 2.0 * base * blend);".endl()+" #endif".endl()+" #ifdef BM_LIGHTEN".endl()+" colNew=max(blend, base);".endl()+" #endif".endl()+" #ifdef BM_DARKEN".endl()+" colNew=min(blend, base);".endl()+" #endif".endl()+" #ifdef BM_OVERLAY".endl()+" #define BlendOverlayf(base, blend) (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))".endl()+" colNew=vec3(BlendOverlayf(base.r, blend.r),BlendOverlayf(base.g, blend.g),BlendOverlayf(base.b, blend.b));".endl()+" #endif".endl()+" #ifdef BM_SCREEN".endl()+" #define BlendScreenf(base, blend) (1.0 - ((1.0 - base) * (1.0 - blend)))".endl()+" colNew=vec3(BlendScreenf(base.r, blend.r),BlendScreenf(base.g, blend.g),BlendScreenf(base.b, blend.b));".endl()+" #endif".endl()+" #ifdef BM_SOFTLIGHT".endl()+" #define BlendSoftLightf(base, blend) ((blend < 0.5) ? (2.0 * base * blend + base * base * (1.0 - 2.0 * blend)) : (sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend)))".endl()+" colNew=vec3(BlendSoftLightf(base.r, blend.r),BlendSoftLightf(base.g, blend.g),BlendSoftLightf(base.b, blend.b));".endl()+" #endif".endl()+" #ifdef BM_HARDLIGHT".endl()+" #define BlendOverlayf(base, blend) (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))".endl()+" colNew=vec3(BlendOverlayf(base.r, blend.r),BlendOverlayf(base.g, blend.g),BlendOverlayf(base.b, blend.b));".endl()+" #endif".endl()+" #ifdef BM_COLORDODGE".endl()+" #define BlendColorDodgef(base, blend) ((blend == 1.0) ? blend : min(base / (1.0 - blend), 1.0))".endl()+" colNew=vec3(BlendColorDodgef(base.r, blend.r),BlendColorDodgef(base.g, blend.g),BlendColorDodgef(base.b, blend.b));".endl()+" #endif".endl()+" #ifdef BM_COLORBURN".endl()+" #define BlendColorBurnf(base, blend) ((blend == 0.0) ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0))".endl()+" colNew=vec3(BlendColorBurnf(base.r, blend.r),BlendColorBurnf(base.g, blend.g),BlendColorBurnf(base.b, blend.b));".endl()+" #endif".endl()+" return colNew;".endl()+"}".endl();return t||(e+="vec4 cgl_blend(vec4 oldColor,vec4 newColor,float amount)".endl()+"{".endl()+"vec4 col=vec4( _blend(oldColor.rgb,newColor.rgb) ,1.0);".endl()+"col=vec4( mix( col.rgb, oldColor.rgb ,1.0-oldColor.a*amount),1.0);".endl()+"return col;".endl()+"}".endl()),t>=3&&(e+="vec4 cgl_blendPixel(vec4 base,vec4 col,float amount)".endl()+"{".endl()+"vec3 colNew=_blend(base.rgb,col.rgb);".endl()+"float newA=clamp(base.a+(col.a*amount),0.,1.);".endl()+"#ifdef BM_ALPHAMASKED".endl()+"newA=base.a;".endl()+"#endif".endl()+"return vec4(".endl()+"mix(colNew,base.rgb,1.0-(amount*col.a)),".endl()+"newA);".endl()+"}".endl()),e},gt.onChangeBlendSelect=function(t,e,i){t.toggleDefine("BM_NORMAL","normal"==e),t.toggleDefine("BM_MULTIPLY","multiply"==e),t.toggleDefine("BM_MULTIPLY_INV","multiply invert"==e),t.toggleDefine("BM_AVERAGE","average"==e),t.toggleDefine("BM_ADD","add"==e),t.toggleDefine("BM_SUBTRACT_ONE","subtract one"==e),t.toggleDefine("BM_SUBTRACT","subtract"==e),t.toggleDefine("BM_DIFFERENCE","difference"==e),t.toggleDefine("BM_NEGATION","negation"==e),t.toggleDefine("BM_EXCLUSION","exclusion"==e),t.toggleDefine("BM_LIGHTEN","lighten"==e),t.toggleDefine("BM_DARKEN","darken"==e),t.toggleDefine("BM_OVERLAY","overlay"==e),t.toggleDefine("BM_SCREEN","screen"==e),t.toggleDefine("BM_SOFTLIGHT","softlight"==e),t.toggleDefine("BM_HARDLIGHT","hardlight"==e),t.toggleDefine("BM_COLORDODGE","color dodge"==e),t.toggleDefine("BM_COLORBURN","color burn"==e),t.toggleDefine("BM_ALPHAMASKED",i)},gt.AddBlendSelect=function(t,e,i){return t.inValueSelect(e||"Blend Mode",["normal","lighten","darken","multiply","multiply invert","average","add","subtract","difference","negation","exclusion","overlay","screen","color dodge","color burn","softlight","hardlight","subtract one"],i||"normal")},gt.AddBlendAlphaMask=function(t,e,i){return t.inSwitch(e||"Alpha Mask",["Off","On"],i||"Off")},gt.setupBlending=function(t,e,i,s,r){const n=()=>{let s=!1;r&&(s="On"==r.get()),gt.onChangeBlendSelect(e,i.get(),s);let n=i.get();"normal"==n?n=null:"multiply"==n?n="mul":"multiply invert"==n?n="mulinv":"lighten"==n?n="light":"darken"==n?n="darken":"average"==n?n="avg":"subtract one"==n?n="sub one":"subtract"==n?n="sub":"difference"==n?n="diff":"negation"==n||"negation"==n||"negation"==n?n="neg":"exclusion"==n?n="exc":"overlay"==n?n="ovl":"color dodge"==n?n="dodge":"color burn"==n?n="burn":"softlight"==n?n="soft":"hardlight"==n&&(n="hard"),t.setUiAttrib({extendTitle:n})};t.setPortGroup("Blending",[i,s,r]);let o=!1;i.onChange=n,r&&(r.onChange=n,o="On"==r.get()),gt.onChangeBlendSelect(e,i.get(),o)};const pt={"CGL.BLENDMODES":function(){this.name="blendmodes",this.srcHeadFrag=gt.getBlendCode()},"CGL.BLENDMODES3":function(){this.name="blendmodes3",this.srcHeadFrag=gt.getBlendCode(3)},"CGL.LUMINANCE":function(){this.name="luminance",this.srcHeadFrag="".endl()+"float cgl_luminance(vec3 c)".endl()+"{".endl()+" return dot(vec3(0.2126,0.7152,0.0722),c);".endl()+"}".endl()},"CGL.RANDOM_OLD":function(){this.name="randomNumber",this.srcHeadFrag="".endl()+"float cgl_random(vec2 co)".endl()+"{".endl()+" return fract(sin(dot(co.xy ,vec2(12.9898,4.1414))) * 432758.5453);".endl()+"}".endl()+"vec3 cgl_random3(vec2 co)".endl()+"{".endl()+" return vec3( cgl_random(co),cgl_random(co+0.5711),cgl_random(co+1.5711));".endl()+"}"},"CGL.RANDOM_LOW":function(){this.name="randomNumber",this.srcHeadFrag="".endl()+"float cgl_random(vec2 co)".endl()+"{".endl()+" return fract(sin(dot(co.xy ,vec2(12.9898,4.1414))) * 358.5453);".endl()+"}".endl()+"vec3 cgl_random3(vec2 co)".endl()+"{".endl()+" return vec3( cgl_random(co),cgl_random(co+0.5711),cgl_random(co+1.5711));".endl()+"}"},"CGL.RANDOM_TEX":function(){this.name="randomNumbertex",this.srcHeadFrag="".endl()+"UNI sampler2D CGLRNDTEX;".endl()+"float cgl_random(vec2 co)".endl()+"{".endl()+" return texture(CGLRNDTEX,co*5711.0).r;".endl()+"}".endl()+"vec3 cgl_random3(vec2 co)".endl()+"{".endl()+" return texture(CGLRNDTEX,co*5711.0).rgb;".endl()+"}",this.initUniforms=function(t){return[new nt(t,"t","CGLRNDTEX",7)]},this.onBind=function(t,e){B.getRandomTexture(t),t.setTexture(7,B.getRandomTexture(t).tex)}}},_t=function(){return window.performance.now()},dt=function(){return _t()},ft=function(){CABLES.EventTarget.apply(this),this._timeStart=_t(),this._timeOffset=0,this._currentTime=0,this._lastTime=0,this._paused=!0,this._delay=0,this.overwriteTime=-1};ft.prototype._getTime=function(){return this._lastTime=(_t()-this._timeStart)/1e3,this._lastTime+this._timeOffset},ft.prototype.setDelay=function(t){this._delay=t,this.emitEvent("timeChange")},ft.prototype.isPlaying=function(){return!this._paused},ft.prototype.update=function(){if(!this._paused)return this._currentTime=this._getTime(),this._currentTime},ft.prototype.getMillis=function(){return 1e3*this.get()},ft.prototype.get=ft.prototype.getTime=function(){return this.overwriteTime>=0?this.overwriteTime-this._delay:this._currentTime-this._delay},ft.prototype.togglePlay=function(){this._paused?this.play():this.pause()},ft.prototype.setTime=function(t){(isNaN(t)||t<0)&&(t=0),this._timeStart=_t(),this._timeOffset=t,this._currentTime=t,this.emitEvent("timeChange")},ft.prototype.setOffset=function(t){this._currentTime+t<0?(this._timeStart=_t(),this._timeOffset=0,this._currentTime=0):(this._timeOffset+=t,this._currentTime=this._lastTime+this._timeOffset),this.emitEvent("timeChange")},ft.prototype.play=function(){this._timeStart=_t(),this._paused=!1,this.emitEvent("playPause")},ft.prototype.pause=function(){this._timeOffset=this._currentTime,this._paused=!0,this.emitEvent("playPause")};const mt=Math.PI/180,Et=(Math.PI,-1!=window.navigator.userAgent.indexOf("Windows")),Tt=function(t){let e;if(t.wheelDelta)e=t.wheelDelta%120-0==-0?t.wheelDelta/120:t.wheelDelta/30,e*=-1.5,Et&&(e*=2);else{let i=t.deltaY;t.shiftKey&&(i=t.deltaX);const s=i||t.detail;e=-(s%3?10*s:s/3),e*=-3}return e>20&&(e=20),e<-20&&(e=-20),e},At=Tt,bt=Tt,xt={"&":"&","<":"<",">":">",'"':""","'":"'"},vt=/[&<>"']/g,yt=RegExp(vt.source);const It=function(t,e){if(!t)throw new Error("shader constructed without cgl "+e);this._log=new a("cgl_shader"),this._cgl=t,e||this._log.stack("no shader name given"),this._name=e||"unknown",this.glslVersion=0,t.glVersion>1&&(this.glslVersion=300),this.id=x(),this._isValid=!0,this._program=null,this._uniforms=[],this._drawBuffers=[!0],this._defines=[],this._needsRecompile=!0,this._compileReason="initial",this._projMatrixUniform=null,this._mvMatrixUniform=null,this._mMatrixUniform=null,this._vMatrixUniform=null,this._camPosUniform=null,this._normalMatrixUniform=null,this._inverseViewMatrixUniform=null,this._attrVertexPos=-1,this.precision=t.patch.config.glslPrecision||"highp",this._pMatrixState=-1,this._vMatrixState=-1,this._modGroupCount=0,this._feedBackNames=[],this._attributes=[],this.glPrimitive=null,this.offScreenPass=!1,this._extensions=[],this.srcVert=this.getDefaultVertexShader(),this.srcFrag=this.getDefaultFragmentShader(),this.lastCompile=0,this._moduleNames=[],this._modules=[],this._moduleNumId=0,this._libs=[],this._structNames=[],this._structUniformNames=[],this._textureStackUni=[],this._textureStackTex=[],this._textureStackType=[],this._textureStackTexCgl=[],this._tempNormalMatrix=mat4.create(),this._tempCamPosMatrix=mat4.create(),this._tempInverseViewMatrix=mat4.create(),this._tempInverseProjMatrix=mat4.create(),this.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG"])};It.prototype.isValid=function(){return this._isValid},It.prototype.getCgl=function(){return this._cgl},It.prototype.getName=function(){return this._name},It.prototype.enableExtension=function(t){this.setWhyCompile("enable extension "+t),this._needsRecompile=!0,this._extensions.push(t)},It.prototype.getAttrVertexPos=function(){return this._attrVertexPos},It.prototype.hasTextureUniforms=function(){for(let t=0;t-1){const i=new pt[e];t=t.replace("{{"+e+"}}",i.srcHeadFrag),this._libs.push(i),i.initUniforms&&i.initUniforms(this)}return t},It.prototype.createStructUniforms=function(){let t="",e="";this._structNames=[],this._injectedStringsFrag={},this._injectedStringsVert={},this._structUniformNamesIndicesFrag=[],this._structUniformNamesIndicesVert=[];for(let i=0;it._name),e=[];for(let i=0;i-1&&e.push(i)}for(let t=this._uniforms.length-1;t>=0;t-=1)e.indexOf(t)>-1?this._uniforms.splice(t,1):this._uniforms[t].resetLoc()}this._cgl.printError("uniform resets"),this.hasTextureUniforms()&&(i+="#define HAS_TEXTURES".endl());let r="",n="";this.srcFrag||(this._log.error("[cgl shader] has no fragment source!",this),this.srcVert=this.getDefaultVertexShader(),this.srcFrag=this.getDefaultFragmentShader()),300==this.glslVersion?(r="#version 300 es".endl()+"// ".endl()+"// vertex shader "+this._name.endl()+"// ".endl()+"precision "+this.precision+" float;".endl()+"precision "+this.precision+" sampler2D;".endl()+"".endl()+"#define WEBGL2".endl()+"#define texture2D texture".endl()+"#define UNI uniform".endl()+"#define IN in".endl()+"#define OUT out".endl(),n="#version 300 es".endl()+"// ".endl()+"// fragment shader "+this._name.endl()+"// ".endl()+"precision "+this.precision+" float;".endl()+"precision "+this.precision+" sampler2D;".endl()+"".endl()+"#define WEBGL2".endl()+"#define texture2D texture".endl()+"#define IN in".endl()+"#define UNI uniform".endl()+"{{DRAWBUFFER}}".endl()):(n="".endl()+"// ".endl()+"// fragment shader "+this._name.endl()+"// ".endl()+"#define WEBGL1".endl()+"#define texture texture2D".endl()+"#define outColor gl_FragColor".endl()+"#define IN varying".endl()+"#define UNI uniform".endl(),r="".endl()+"// ".endl()+"// vertex shader "+this._name.endl()+"// ".endl()+"#define WEBGL1".endl()+"#define texture texture2D".endl()+"#define OUT varying".endl()+"#define IN attribute".endl()+"#define UNI uniform".endl());let o="\n// cgl generated".endl(),a="\n// cgl generated".endl();n+="\n// active mods: --------------- ",r+="\n// active mods: --------------- ";let h=!1,l=!1;for(let t=0;t=this._cgl.maxUniformsFrag&&this._log.warn("[cgl_shader] num uniforms frag: "+c+" / "+this._cgl.maxUniformsFrag),u>=this._cgl.maxUniformsVert&&this._log.warn("[cgl_shader] num uniforms vert: "+u+" / "+this._cgl.maxUniformsVert),-1==n.indexOf("precision")&&(n="precision "+this.precision+" float;".endl()+n),-1==r.indexOf("precision")&&(r="precision "+this.precision+" float;".endl()+r),/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)&&(n+="#define MOBILE".endl(),r+="#define MOBILE".endl()),r=e+r+i+s[0]+o+"\n// -- \n"+this.srcVert,n=e+n+i+s[1]+a+"\n// -- \n"+this.srcFrag;let g="",p="";this._modules.sort((function(t,e){return t.group-e.group})),this._modules.sort((function(t,e){return t.priority||0-e.priority||0}));let _=!1;for(let t=0;t-1&&(this._drawBuffers[0]=!0),n.indexOf("outColor1")>-1&&(this._drawBuffers[1]=!0),n.indexOf("outColor2")>-1&&(this._drawBuffers[2]=!0),n.indexOf("outColor3")>-1&&(this._drawBuffers[3]=!0),1==this._drawBuffers.length)d="out vec4 outColor;".endl(),d+="#define gl_FragColor outColor".endl();else{d+="#define MULTI_COLORTARGETS".endl(),d+="vec4 outColor;".endl();let t=0;for(let e=0;e{this.toggleDefine(t,e)},e.changeListener=e.on("change",e.onToggleDefine),e=e.get()),e?this.define(t):this.removeDefine(t)},It.prototype.define=function(t,e){null==e&&(e=""),"object"==typeof e&&(e.removeEventListener("change",e.onDefineChange),e.onDefineChange=e=>{this.define(t,e)},e.on("change",e.onDefineChange),e=e.get());for(let i=0;i0&&this._cgl.gl.transformFeedbackVaryings(t,this._feedBackNames,this._cgl.gl.SEPARATE_ATTRIBS),this._cgl.gl.linkProgram(t),this._cgl.printError("gl.linkprogram"),this._isValid=!0,this._hasErrors=!1,!1!==this._cgl.patch.config.glValidateShader&&(this._cgl.gl.validateProgram(t),this._cgl.gl.getProgramParameter(t,this._cgl.gl.VALIDATE_STATUS)||(console.log("shaderprogram validation failed..."),console.log(this._name+" programinfo: ",this._cgl.gl.getProgramInfoLog(t))),this._cgl.gl.getProgramParameter(t,this._cgl.gl.LINK_STATUS)||(this._hasErrors=!0,this._log.warn(this._cgl.gl.getShaderInfoLog(this.fshader)||"empty shader infolog"),this._log.warn(this._cgl.gl.getShaderInfoLog(this.vshader)||"empty shader infolog"),this._log.error(this._name+" shader linking fail..."),console.log(this._name+" programinfo: ",this._cgl.gl.getProgramInfoLog(t)),console.log("--------------------------------------"),console.log(this),console.log("--------------------------------------"),this._isValid=!1,this._name="errorshader",this.setSource(It.getDefaultVertexShader(),It.getErrorFragmentShader()),this._cgl.printError("shader link err")))},It.prototype.getProgram=function(){return this._program},It.prototype.setFeedbackNames=function(t){this.setWhyCompile("setFeedbackNames"),this._needsRecompile=!0,this._feedBackNames=t},It.prototype.getDefaultVertexShader=It.getDefaultVertexShader=function(){return"{{MODULES_HEAD}}\nIN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\nIN vec3 attrTangent,attrBiTangent;\n\nIN float attrVertIndex;\n\nOUT vec2 texCoord;\nOUT vec3 norm;\nUNI mat4 projMatrix;\nUNI mat4 viewMatrix;\nUNI mat4 modelMatrix;\n\nvoid main()\n{\n texCoord=attrTexCoord;\n norm=attrVertNormal;\n vec4 pos=vec4(vPosition, 1.0);\n vec3 tangent=attrTangent;\n vec3 bitangent=attrBiTangent;\n mat4 mMatrix=modelMatrix;\n {{MODULE_VERTEX_POSITION}}\n gl_Position = projMatrix * (viewMatrix*mMatrix) * pos;\n}\n"},It.prototype.getDefaultFragmentShader=It.getDefaultFragmentShader=function(t,e,i){return null==t&&(t=.5,e=.5,i=.5),"".endl()+"IN vec2 texCoord;".endl()+"{{MODULES_HEAD}}".endl()+"void main()".endl()+"{".endl()+" vec4 col=vec4("+t+","+e+","+i+",1.0);".endl()+" {{MODULE_COLOR}}".endl()+" outColor = col;".endl()+"}"},It.prototype.addAttribute=function(t){for(let e=0;ethis._cgl.maxTextureUnits&&this._log.warn("[shader._bindTextures] too many textures bound",this._textureStackTex.length+"/"+this._cgl.maxTextureUnits);for(let t=0;t",h+='
'),h+=(n=i)&&yt.test(n)?n.replace(vt,(function(t){return xt[t]})):n||"",s&&(h+="
",h+='
')}console.warn(o),o=o.replace(/\n/g,"
"),h=o+"
"+h+"

",h+="
",t.patch.emitEvent("criticalError",{title:"Shader error "+this._name,text:h}),t.patch.isEditorMode()&&console.log("Shader error "+this._name,h),this._name="errorshader",s.setSource(It.getDefaultVertexShader(),It.getErrorFragmentShader())}var n;return r};class St{constructor(t){this._cgl=t,this._lastTime=0,this.pause=!1,this.profileUniformCount=0,this.profileShaderBinds=0,this.profileUniformCount=0,this.profileShaderCompiles=0,this.profileVideosPlaying=0,this.profileMVPMatrixCount=0,this.profileEffectBuffercreate=0,this.profileShaderGetUniform=0,this.profileFrameBuffercreate=0,this.profileMeshSetGeom=0,this.profileTextureNew=0,this.profileGenMipMap=0,this.profileOnAnimFrameOps=0,this.profileMainloopMs=0,this.profileMeshDraw=0,this.profileTextureEffect=0,this.profileTexPreviews=0,this.shaderCompileTime=0,this.profileMeshNumElements=0,this.profileMeshAttributes=0,this.profileSingleMeshAttribute=[],this.heavyEvents=[],this.doProfileGlQuery=!1,this.glQueryData={}}clear(){this.profileSingleMeshAttribute={},this.profileMeshAttributes=0,this.profileUniformCount=0,this.profileShaderGetUniform=0,this.profileShaderCompiles=0,this.profileShaderBinds=0,this.profileTextureResize=0,this.profileFrameBuffercreate=0,this.profileEffectBuffercreate=0,this.profileTextureDelete=0,this.profileMeshSetGeom=0,this.profileVideosPlaying=0,this.profileMVPMatrixCount=0,this.profileNonTypedAttrib=0,this.profileNonTypedAttribNames="",this.profileTextureNew=0,this.profileGenMipMap=0,this.profileFramebuffer=0,this.profileMeshDraw=0,this.profileTextureEffect=0,this.profileTexPreviews=0,this.profileMeshNumElements=0}clearGlQuery(){for(let t in this.glQueryData)(!this.glQueryData[t].lastClear||performance.now()-this.glQueryData[t].lastClear>1e3)&&(this.glQueryData[t].time=this.glQueryData[t]._times/this.glQueryData[t]._numcount,this.glQueryData[t].num=this.glQueryData[t]._numcount,this.glQueryData[t]._times=0,this.glQueryData[t]._numcount=0,this.glQueryData[t].lastClear=performance.now())}addHeavyEvent(t,e,i){const s={event:t,name:e,info:i,date:performance.now()};this.heavyEvents.push(s),this._cgl.emitEvent("heavyEvent",s)}}const Rt={GAPI_WEBGL:0,GAPI_WEBGPU:1,Geometry:W,BoundingBox:z,FpsCounter:class extends Y{constructor(){super(),this._timeStartFrame=0,this._timeStartSecond=0,this._fpsCounter=0,this._msCounter=0,this.stats={ms:0,fps:0}}startFrame(){this._timeStartFrame=CABLES.now()}endFrame(){this._fpsCounter++;const t=CABLES.now()-this._timeStartFrame;this._msCounter+=t,CABLES.now()-this._timeStartSecond>1e3&&this.endSecond()}endSecond(){this.stats.fps=this._fpsCounter,this.stats.ms=Math.round(this._msCounter/this._fpsCounter*100)/100,this.emitEvent("performance",this.stats),this._fpsCounter=0,this._msCounter=0,this._timeStartSecond=CABLES.now()}}},Pt=function(t){Ut.apply(this),this.patch=t,this.gApi=Rt.GAPI_WEBGPU,this._viewport=[0,0,256,256],this._shaderStack=[],this.getViewPort=function(){return[0,0,this.canvasWidth,this.canvasHeight]},this.renderStart=function(t,e,i){this.fpsCounter.startFrame(),this._startMatrixStacks(e,i),this.setViewPort(0,0,this.canvasWidth,this.canvasHeight),this.emitEvent("beginFrame")},this.renderEnd=function(t){this._endMatrixStacks(),this.emitEvent("endFrame"),this.fpsCounter.endFrame()}};Pt.prototype.setViewPort=function(t,e,i,s){this._viewport=[t,e,i,s]},Pt.prototype.getViewPort=function(){return this._viewPort},Pt.prototype.createMesh=function(t,e){return new CGP.Mesh(this,t,e)},Pt.prototype.getShader=function(){return{}},Pt.prototype.pushShader=function(t){this._shaderStack.push(t)},Pt.prototype.popShader=function(){if(0===this._shaderStack.length)throw new Error("Invalid shader stack pop!");this._shaderStack.pop()},Pt.prototype.getShader=function(){return this._shaderStack[this._shaderStack.length-1]},Pt.prototype.pushErrorScope=function(){this.device.pushErrorScope("validation")},Pt.prototype.popErrorScope=function(t,e){this.device.popErrorScope().then(i=>{i&&(this.patch.emitEvent("criticalError",{title:'WebGPU error "'+t+'"',codeText:i.message}),console.warn("[cgp]",t,i.message,i,e),e&&e(i))})};class Ot extends rt{constructor(t,e,i,s,r,n,o,a,h,l){super(t,e,i,s,r,n,o,a,h,l),this._loc=-1,this._cgl=t._cgl}updateValueF(){}setValueF(t){this.needsUpdate=!0,this._value=t}updateValue2F(){}setValue2F(t){this.needsUpdate=!0,this._value=t}updateValue3F(){}setValue3F(t){this.needsUpdate=!0,this._value=t}updateValue4F(){}setValue4F(t){this.needsUpdate=!0,this._value=t}getSizeBytes(){return"f"==this._type||"i"==this._type?4:"2i"==this._type||"2f"==this._type?8:"3f"==this._type?12:"4f"==this._type?16:"m4"==this._type?64:void this._log.warn("unknown type getSizeBytes")}}class Nt{constructor(t,e){this._shaderType=e,this._shader=t,this._cgp=t._cgp,this._gpuBuffer=null,this._values=null,this._sizeBytes=0,this.update()}update(){this._sizeBytes=0;for(let t=0;t1)for(let e=0;e{this._isValid=!1})}}class Ct{constructor(t,e){if(!t)throw new Error("no cgp");this._log=new a("cgp_texture"),this._cgp=t,this.id=CABLES.uuid(),e=e||{},this.name=e.name||"unknown"}initTexture(t,e){this.width=t.width,this.height=t.height,this.textureType="rgba8unorm";const i={size:{width:t.width,height:t.height},format:this.textureType,usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST},s=this._cgp.device.createTexture(i);return this._cgp.device.queue.copyExternalImageToTexture({source:t},{texture:s},i.size),s}getInfo(){const t={};return t.name=this.name,t.size=this.width+" x "+this.height,t.textureType=this.textureType,t}}Ct.load=function(t,e,i,s){fetch(e).then(s=>{s.blob().then(s=>{createImageBitmap(s).then(s=>{const r=new Ct(t,{name:e});r.initTexture(s),i?i(r):console.log("Texture.load no onFinished callback")})})})};const wt=Object.assign({Context:Pt,Shader:class{constructor(t,e){if(!t)throw new Error("shader constructed without cgp "+e);this._log=new a("cgp_shader"),this._cgp=t,this._name=e,this._uniforms=[],e||this._log.stack("no shader name given"),this._name=e||"unknown",this.id=x(),this._isValid=!0,this._compileReason="",this.shaderModule=null,this._needsRecompile=!0,this._src=""}get isValid(){return this._isValid}get uniforms(){return this._uniforms}getName(){return this._name}setWhyCompile(t){this._compileReason=t}setSource(t){this._src=t,this.setWhyCompile("Source changed"),this._needsRecompile=!0}compile(){this._isValid=!0,console.log("compiling shader...",this._compileReason),this._cgp.pushErrorScope(),this.shaderModule=this._cgp.device.createShaderModule({code:this._src}),this._cgp.popErrorScope("cgp_shader "+this._name,this.error.bind(this)),this._needsRecompile=!1}error(t){this._isValid=!1}bind(){for(let t=0;t["WebGL","WebGPU"][this.gApi],this.setCanvas=function(t){this.canvas="string"==typeof t?document.getElementById(t):t,this._setCanvas&&this._setCanvas(t),this.updateSize()},this.updateSize=function(){this.canvas.width=this.canvasWidth=this.canvas.clientWidth*this.pixelDensity,this.canvas.height=this.canvasHeight=this.canvas.clientHeight*this.pixelDensity},this.setSize=function(t,e,i){i||(this.canvas.style.width=t+"px",this.canvas.style.height=e+"px"),this.canvas.width=t*this.pixelDensity,this.canvas.height=e*this.pixelDensity,this.updateSize()},this._resizeToWindowSize=function(){this.setSize(window.innerWidth,window.innerHeight),this.updateSize()},this._resizeToParentSize=function(){const t=this.canvas.parentElement;t?(this.setSize(t.clientWidth,t.clientHeight),this.updateSize()):this._log.error("cables: can not resize to container element")},this.setAutoResize=function(t){window.removeEventListener("resize",this._resizeToWindowSize.bind(this)),window.removeEventListener("resize",this._resizeToParentSize.bind(this)),"window"==t&&(window.addEventListener("resize",this._resizeToWindowSize.bind(this)),window.addEventListener("orientationchange",this._resizeToWindowSize.bind(this)),this._resizeToWindowSize()),"parent"==t&&(window.addEventListener("resize",this._resizeToParentSize.bind(this)),this._resizeToParentSize())},this.pushPMatrix=function(){this.pMatrix=this._pMatrixStack.push(this.pMatrix)},this.popPMatrix=function(){return this.pMatrix=this._pMatrixStack.pop(),this.pMatrix},this.getProjectionMatrixStateCount=function(){return this._pMatrixStack.stateCounter},this.pushModelMatrix=function(){this.mMatrix=this._mMatrixStack.push(this.mMatrix)},this.popModelMatrix=function(){return this.mMatrix=this._mMatrixStack.pop(),this.mMatrix},this.modelMatrix=function(){return this.mMatrix},this.pushViewMatrix=function(){this.vMatrix=this._vMatrixStack.push(this.vMatrix)},this.popViewMatrix=function(){this.vMatrix=this._vMatrixStack.pop()},this.getViewMatrixStateCount=function(){return this._vMatrixStack.stateCounter},this._startMatrixStacks=(t,e)=>{t=t||this._ident,e=e||this._identView,mat4.perspective(this.pMatrix,45,this.canvasWidth/this.canvasHeight,.1,1e3),mat4.identity(this.mMatrix),mat4.identity(this.vMatrix),mat4.translate(this.mMatrix,this.mMatrix,t),mat4.translate(this.vMatrix,this.vMatrix,e),this.pushPMatrix(),this.pushModelMatrix(),this.pushViewMatrix()},this._endMatrixStacks=()=>{this.popViewMatrix(),this.popModelMatrix(),this.popPMatrix()}},Bt=function(t){Ut.apply(this),this.gApi=Rt.GAPI_WEBGL,this.pushMvMatrix=this.pushModelMatrix,this.popMvMatrix=this.popmMatrix=this.popModelMatrix,this.profileData=new St(this),this._log=new a("cgl_context");const e=[0,0,0,0];this.glVersion=0,this.glUseHalfFloatTex=!1,this.clearCanvasTransparent=!0,this.clearCanvasDepth=!0,this.patch=t,this.debugOneFrame=!1,this.checkGlErrors=!0,this.maxTextureUnits=0,this.maxVaryingVectors=0,this.currentProgram=null,this._hadStackError=!1,this.glSlowRenderer=!1,this._isSafariCrap=!1,this.temporaryTexture=null,this.frameStore={},this._onetimeCallbacks=[],this.gl=null,this._cursor="auto",this._currentCursor="",this._glFrameBufferStack=[],this._frameBufferStack=[],this._shaderStack=[],this._stackDepthTest=[],Object.defineProperty(this,"mvMatrix",{get(){return this.mMatrix},set(t){this.mMatrix=t}});const i=new It(this,"simpleshader");i.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG"]),i.setSource(It.getDefaultVertexShader(),It.getDefaultFragmentShader());let s=i;this.aborted=!1;const r=[];this.exitError=function(t,e){this.patch.exitError(t,e),this.aborted=!0},this._setCanvas=function(t){if(this.patch.config.canvas||(this.patch.config.canvas={}),this.patch.config.canvas.hasOwnProperty("preserveDrawingBuffer")||(this.patch.config.canvas.preserveDrawingBuffer=!1),this.patch.config.canvas.hasOwnProperty("premultipliedAlpha")||(this.patch.config.canvas.premultipliedAlpha=!1),this.patch.config.canvas.hasOwnProperty("alpha")||(this.patch.config.canvas.alpha=!1),this.patch.config.canvas.stencil=!0,this.patch.config.hasOwnProperty("clearCanvasColor")&&(this.clearCanvasTransparent=this.patch.config.clearCanvasColor),this.patch.config.hasOwnProperty("clearCanvasDepth")&&(this.clearCanvasDepth=this.patch.config.clearCanvasDepth),/^((?!chrome|android).)*safari/i.test(navigator.userAgent)&&(this._isSafariCrap=!0),this.patch.config.canvas.forceWebGl1||(this.gl=this.canvas.getContext("webgl2",this.patch.config.canvas)),this.gl&&"WebGL 1.0"!=this.gl.getParameter(this.gl.VERSION)?this.glVersion=2:(this.gl=this.canvas.getContext("webgl",this.patch.config.canvas)||this.canvas.getContext("experimental-webgl",this.patch.config.canvas),this.glVersion=1,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)&&navigator.userAgent.match(/iPhone/i)&&(this.glUseHalfFloatTex=!0),/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream&&(this.patch.config.canvas.hasOwnProperty("powerPreference")||(this.patch.config.canvas.powerPreference="high-performance"))),!this.gl)return void this.exitError("NO_WEBGL","sorry, could not initialize WebGL. Please check if your Browser supports WebGL or try to restart your browser.");const e=this.gl.getExtension("WEBGL_debug_renderer_info");e&&(this.glRenderer=this.gl.getParameter(e.UNMASKED_RENDERER_WEBGL),"Google SwiftShader"===this.glRenderer&&(this.glSlowRenderer=!0)),this.gl.getExtension("OES_standard_derivatives");const i=this.gl.getExtension("ANGLE_instanced_arrays")||this.gl;this.canvas.addEventListener("webglcontextlost",t=>{this._log.error("canvas lost...",t),this.emitEvent("webglcontextlost"),this.aborted=!0}),this.maxVaryingVectors=this.gl.getParameter(this.gl.MAX_VARYING_VECTORS),this.maxTextureUnits=this.gl.getParameter(this.gl.MAX_TEXTURE_IMAGE_UNITS),this.maxTexSize=this.gl.getParameter(this.gl.MAX_TEXTURE_SIZE),this.maxUniformsFrag=this.gl.getParameter(this.gl.MAX_FRAGMENT_UNIFORM_VECTORS),this.maxUniformsVert=this.gl.getParameter(this.gl.MAX_VERTEX_UNIFORM_VECTORS),this.maxSamples=0,this.gl.MAX_SAMPLES&&(this.maxSamples=this.gl.getParameter(this.gl.MAX_SAMPLES)),i.vertexAttribDivisorANGLE&&(this.gl.vertexAttribDivisor=i.vertexAttribDivisorANGLE.bind(i),this.gl.drawElementsInstanced=i.drawElementsInstancedANGLE.bind(i))},this.getInfo=function(){return{glVersion:this.glVersion,glRenderer:this.glRenderer,glUseHalfFloatTex:this.glUseHalfFloatTex,maxVaryingVectors:this.maxVaryingVectors,maxTextureUnits:this.maxTextureUnits,maxTexSize:this.maxTexSize,maxUniformsFrag:this.maxUniformsFrag,maxUniformsVert:this.maxUniformsVert,maxSamples:this.maxSamples}};let n=-1,o=-1;this.getViewPort=function(){return e},this.resetViewPort=function(){this.gl.viewport(e[0],e[1],e[2],e[3])},this.setViewPort=function(t,i,s,r){e[0]=Math.round(t),e[1]=Math.round(i),e[2]=Math.round(s),e[3]=Math.round(r),this.gl.viewport(e[0],e[1],e[2],e[3])},this.screenShot=function(t,e,i,s){e&&(this.gl.clearColor(1,1,1,1),this.gl.colorMask(!1,!1,!1,!0),this.gl.clear(this.gl.COLOR_BUFFER_BIT),this.gl.colorMask(!0,!0,!0,!0)),this.canvas&&this.canvas.toBlob&&this.canvas.toBlob(e=>{t?t(e):this._log.log("no screenshot callback...")},i,s)},this.endFrame=function(){if(this.patch.isEditorMode()&&CABLES.GL_MARKER.drawMarkerLayer(this),this.setPreviousShader(),this._vMatrixStack.length()>0&&this.logStackError("view matrix stack length !=0 at end of rendering..."),this._mMatrixStack.length()>0&&this.logStackError("mvmatrix stack length !=0 at end of rendering..."),this._pMatrixStack.length()>0&&this.logStackError("pmatrix stack length !=0 at end of rendering..."),this._glFrameBufferStack.length>0&&this.logStackError("glFrameBuffer stack length !=0 at end of rendering..."),this._stackDepthTest.length>0&&this.logStackError("depthtest stack length !=0 at end of rendering..."),this._stackDepthWrite.length>0&&this.logStackError("depthwrite stack length !=0 at end of rendering..."),this._stackDepthFunc.length>0&&this.logStackError("depthfunc stack length !=0 at end of rendering..."),this._stackBlend.length>0&&this.logStackError("blend stack length !=0 at end of rendering..."),this._stackBlendMode.length>0&&this.logStackError("blendMode stack length !=0 at end of rendering..."),this._shaderStack.length>0&&this.logStackError("this._shaderStack length !=0 at end of rendering..."),this._stackCullFace.length>0&&this.logStackError("this._stackCullFace length !=0 at end of rendering..."),this._stackCullFaceFacing.length>0&&this.logStackError("this._stackCullFaceFacing length !=0 at end of rendering..."),this._frameStarted=!1,n!=this.canvasWidth||o!=this.canvasHeight){n=this.canvasWidth,o=this.canvasHeight,this.setSize(this.canvasWidth/this.pixelDensity,this.canvasHeight/this.pixelDensity),this.updateSize();for(let t=0;t=0;t--)if(this._shaderStack[t]&&this.frameStore.renderOffscreen==this._shaderStack[t].offScreenPass)return this._shaderStack[t]},this.getDefaultShader=function(){return i},this.pushShader=this.setShader=function(t){this._shaderStack.push(t),s=t},this.popShader=this.setPreviousShader=function(){if(0===this._shaderStack.length)throw new Error("Invalid shader stack pop!");this._shaderStack.pop(),s=this._shaderStack[this._shaderStack.length-1]},this.pushGlFrameBuffer=function(t){this._glFrameBufferStack.push(t)},this.popGlFrameBuffer=function(){return 0==this._glFrameBufferStack.length?null:(this._glFrameBufferStack.pop(),this._glFrameBufferStack[this._glFrameBufferStack.length-1])},this.getCurrentGlFrameBuffer=function(){return 0===this._glFrameBufferStack.length?null:this._glFrameBufferStack[this._glFrameBufferStack.length-1]},this.pushFrameBuffer=function(t){this._frameBufferStack.push(t)},this.popFrameBuffer=function(){return 0==this._frameBufferStack.length?null:(this._frameBufferStack.pop(),this._frameBufferStack[this._frameBufferStack.length-1])},this.getCurrentFrameBuffer=function(){return 0===this._frameBufferStack.length?null:this._frameBufferStack[this._frameBufferStack.length-1]},this.renderStart=function(t,e,s){this.fpsCounter.startFrame(),this.pushDepthTest(!0),this.pushDepthWrite(!0),this.pushDepthFunc(t.gl.LEQUAL),this.pushCullFaceFacing(t.gl.BACK),this.pushCullFace(!1),this.clearCanvasTransparent&&(t.gl.clearColor(0,0,0,0),t.gl.clear(t.gl.COLOR_BUFFER_BIT)),this.clearCanvasDepth&&t.gl.clear(t.gl.DEPTH_BUFFER_BIT),t.setViewPort(0,0,t.canvasWidth,t.canvasHeight),this._startMatrixStacks(e,s),t.pushBlendMode(at.BLEND_MODES.BLEND_NORMAL,!1);for(let t=0;t0){for(let t=0;t0&&this.gl.cullFace(this._stackCullFaceFacing[this._stackCullFaceFacing.length-1])},Bt.prototype._stackDepthFunc=[],Bt.prototype.pushDepthFunc=function(t){this._stackDepthFunc.push(t),this.gl.depthFunc(t)},Bt.prototype.stateDepthFunc=function(){return this._stackDepthFunc.length>0&&this._stackDepthFunc[this._stackDepthFunc.length-1]},Bt.prototype.popDepthFunc=function(){this._stackDepthFunc.pop(),this._stackDepthFunc.length>0&&this.gl.depthFunc(this._stackDepthFunc[this._stackDepthFunc.length-1])},Bt.prototype._stackBlend=[],Bt.prototype.pushBlend=function(t){this._stackBlend.push(t),t?this.gl.enable(this.gl.BLEND):this.gl.disable(this.gl.BLEND)},Bt.prototype.popBlend=function(){this._stackBlend.pop(),this._stackBlend[this._stackBlend.length-1]?this.gl.enable(this.gl.BLEND):this.gl.disable(this.gl.BLEND)},Bt.prototype.stateBlend=function(){return this._stackBlend[this._stackBlend.length-1]};Bt.prototype._stackBlendMode=[],Bt.prototype._stackBlendModePremul=[],Bt.prototype.pushBlendMode=function(t,e){this._stackBlendMode.push(t),this._stackBlendModePremul.push(e);const i=this._stackBlendMode.length-1;this.pushBlend(this._stackBlendMode[i]!==at.BLEND_MODES.BLEND_NONE),this._setBlendMode(this._stackBlendMode[i],this._stackBlendModePremul[i])},Bt.prototype.popBlendMode=function(){this._stackBlendMode.pop(),this._stackBlendModePremul.pop();const t=this._stackBlendMode.length-1;this.popBlend(this._stackBlendMode[t]!==at.BLEND_MODES.BLEND_NONE),t>=0&&this._setBlendMode(this._stackBlendMode[t],this._stackBlendModePremul[t])},Bt.prototype._stackStencil=[],Bt.prototype.pushStencil=function(t){this._stackStencil.push(t),t?this.gl.enable(this.gl.STENCIL_TEST):this.gl.disable(this.gl.STENCIL_TEST)},Bt.prototype.popStencil=function(){this._stackStencil.pop(),this._stackStencil[this._stackStencil.length-1]?this.gl.enable(this.gl.STENCIL_TEST):this.gl.disable(this.gl.STENCIL_TEST)},Bt.prototype.glGetAttribLocation=function(t,e){return this.gl.getAttribLocation(t,e)},Bt.prototype.shouldDrawHelpers=function(t){if(this.frameStore.shadowPass)return!1;if(!t.patch.isEditorMode())return!1;const e=this.getCurrentFrameBuffer();if(e&&e.getWidth){if(!(this.canvasWidth/this.canvasHeight==e.getWidth()/e.getHeight()))return!1}return CABLES.UI.renderHelper||CABLES.UI.renderHelperCurrent&&t.isCurrentUiOp()},Bt.prototype._setBlendMode=function(t,e){const i=this.gl;t==at.BLEND_MODES.BLEND_NONE||(t==at.BLEND_MODES.BLEND_ADD?e?(i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD),i.blendFuncSeparate(i.ONE,i.ONE,i.ONE,i.ONE)):(i.blendEquation(i.FUNC_ADD),i.blendFunc(i.SRC_ALPHA,i.ONE)):t==at.BLEND_MODES.BLEND_SUB?e?(i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD),i.blendFuncSeparate(i.ZERO,i.ZERO,i.ONE_MINUS_SRC_COLOR,i.ONE_MINUS_SRC_ALPHA)):(i.blendEquation(i.FUNC_ADD),i.blendFunc(i.ZERO,i.ONE_MINUS_SRC_COLOR)):t==at.BLEND_MODES.BLEND_MUL?e?(i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD),i.blendFuncSeparate(i.ZERO,i.SRC_COLOR,i.ZERO,i.SRC_ALPHA)):(i.blendEquation(i.FUNC_ADD),i.blendFunc(i.ZERO,i.SRC_COLOR)):t==at.BLEND_MODES.BLEND_NORMAL?e?(i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD),i.blendFuncSeparate(i.ONE,i.ONE_MINUS_SRC_ALPHA,i.ONE,i.ONE_MINUS_SRC_ALPHA)):(i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD),i.blendFuncSeparate(i.SRC_ALPHA,i.ONE_MINUS_SRC_ALPHA,i.ONE,i.ONE_MINUS_SRC_ALPHA)):this._log.log("setblendmode: unknown blendmode"))},Bt.prototype.createMesh=function(t,e){return new CGL.Mesh(this,t,e)},Bt.prototype.setCursor=function(t){this._cursor=t};const Lt=Object.assign({Framebuffer:function(t,e,i,s){const r=t;this._log=new a("Framebuffer");const n=r.gl.getExtension("WEBGL_depth_texture")||r.gl.getExtension("WEBKIT_WEBGL_depth_texture")||r.gl.getExtension("MOZ_WEBGL_depth_texture")||r.gl.DEPTH_TEXTURE;n||r.exitError("NO_DEPTH_TEXTURE","no depth texture support");let o=e||512,h=i||512;(s=s||{isFloatingPointTexture:!1}).hasOwnProperty("clear")||(s.clear=!0),s.hasOwnProperty("filter")||(s.filter=B.FILTER_LINEAR);const l=new B(r,{isFloatingPointTexture:s.isFloatingPointTexture,filter:s.filter,wrap:s.wrap||B.CLAMP_TO_EDGE});let c=null;n&&(c=new B(r,{isDepthTexture:!0})),this._options=s;const u=r.gl.createFramebuffer(),g=r.gl.createRenderbuffer();this.getWidth=function(){return o},this.getHeight=function(){return h},this.getGlFrameBuffer=function(){return u},this.getDepthRenderBuffer=function(){return g},this.getTextureColor=function(){return l},this.getTextureDepth=function(){return c},this.setFilter=function(t){l.filter=t,l.setSize(o,h)},this.setSize=function(t,e){if(t<2&&(t=2),e<2&&(e=2),o=Math.ceil(t),h=Math.ceil(e),r.profileData.profileFrameBuffercreate++,r.gl.bindFramebuffer(r.gl.FRAMEBUFFER,u),r.gl.bindRenderbuffer(r.gl.RENDERBUFFER,g),l.setSize(o,h),c&&c.setSize(o,h),n&&r.gl.renderbufferStorage(r.gl.RENDERBUFFER,r.gl.DEPTH_COMPONENT16,o,h),r.gl.framebufferTexture2D(r.gl.FRAMEBUFFER,r.gl.COLOR_ATTACHMENT0,r.gl.TEXTURE_2D,l.tex,0),n&&(r.gl.framebufferRenderbuffer(r.gl.FRAMEBUFFER,r.gl.DEPTH_ATTACHMENT,r.gl.RENDERBUFFER,g),r.gl.framebufferTexture2D(r.gl.FRAMEBUFFER,r.gl.DEPTH_ATTACHMENT,r.gl.TEXTURE_2D,c.tex,0)),!r.gl.isFramebuffer(u))throw new Error("Invalid framebuffer");const i=r.gl.checkFramebufferStatus(r.gl.FRAMEBUFFER);switch(i){case r.gl.FRAMEBUFFER_COMPLETE:break;case r.gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:throw this._log.warn("FRAMEBUFFER_INCOMPLETE_ATTACHMENT...",o,h,l.tex,g),new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_ATTACHMENT");case r.gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:throw this._log.warn("FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"),new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");case r.gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:throw this._log.warn("FRAMEBUFFER_INCOMPLETE_DIMENSIONS"),new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_DIMENSIONS");case r.gl.FRAMEBUFFER_UNSUPPORTED:throw this._log.warn("FRAMEBUFFER_UNSUPPORTED"),new Error("Incomplete framebuffer: FRAMEBUFFER_UNSUPPORTED");case 36059:this._log.warn("Incomplete: FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER from ext. Or Safari/iOS undefined behaviour.");break;default:throw this._log.warn("incomplete framebuffer",i),new Error("Incomplete framebuffer: "+i)}r.gl.bindTexture(r.gl.TEXTURE_2D,null),r.gl.bindRenderbuffer(r.gl.RENDERBUFFER,null),r.gl.bindFramebuffer(r.gl.FRAMEBUFFER,null)},this.renderStart=function(){r.pushModelMatrix(),r.gl.bindFramebuffer(r.gl.FRAMEBUFFER,u),r.pushGlFrameBuffer(u),r.pushFrameBuffer(this),r.pushPMatrix(),r.gl.viewport(0,0,o,h),this._options.clear&&(r.gl.clearColor(0,0,0,0),r.gl.clear(r.gl.COLOR_BUFFER_BIT|r.gl.DEPTH_BUFFER_BIT))},this.renderEnd=function(){r.popPMatrix(),r.gl.bindFramebuffer(r.gl.FRAMEBUFFER,r.popGlFrameBuffer()),r.popFrameBuffer(),r.popModelMatrix(),r.resetViewPort()},this.delete=function(){l.delete(),c&&c.delete(),r.gl.deleteRenderbuffer(g),r.gl.deleteFramebuffer(u)},this.setSize(o,h)},Framebuffer2:L,Geometry:W,BoundingBox:z,Marker:function(t){const e=new W("marker");e.setPointVertices([1e-5,0,0,1,0,0,0,1e-5,0,0,1,0,0,0,1e-5,0,0,1]);const i=new lt(t,e,t.gl.LINES);i.setGeom(e);const s=new It(t,"markermaterial"),r="".endl()+"precision highp float;".endl()+"IN vec3 axisColor;".endl()+"void main()".endl()+"{".endl()+" vec4 col=vec4(axisColor,1.0);".endl()+" outColor = col;".endl()+"}",n="".endl()+"IN vec3 vPosition;".endl()+"UNI mat4 projMatrix;".endl()+"UNI mat4 mvMatrix;".endl()+"OUT vec3 axisColor;".endl()+"void main()".endl()+"{".endl()+" vec4 pos=vec4(vPosition, 1.0);".endl()+" if(pos.x!=0.0)axisColor=vec3(1.0,0.3,0.0);".endl()+" if(pos.y!=0.0)axisColor=vec3(0.0,1.0,0.2);".endl()+" if(pos.z!=0.0)axisColor=vec3(0.0,0.5,1.0);".endl()+" gl_Position = projMatrix * mvMatrix * pos;".endl()+"}";s.setSource(n,r),this._vScale=vec3.create(),this.draw=function(t,e,r){const n=e||2;t.pushModelMatrix(),t.pushShader(s),vec3.set(this._vScale,n,n,n),mat4.scale(t.mvMatrix,t.mvMatrix,this._vScale),t.pushDepthTest(1==r),i.render(t.getShader()),t.popDepthTest(),t.popShader(),t.popModelMatrix()}},WirePoint:function(t){const e=t.gl.createBuffer(),i=vec3.create();this.render=function(t,s){t.pushModelMatrix(),vec3.set(i,s,s,s),mat4.scale(t.mvMatrix,t.mvMatrix,i);const r=t.getShader();r&&(r.bind(),t.gl.bindBuffer(t.gl.ARRAY_BUFFER,e),t.gl.vertexAttribPointer(r.getAttrVertexPos(),e.itemSize,t.gl.FLOAT,!1,0,0),t.gl.enableVertexAttribArray(r.getAttrVertexPos()),t.gl.bindBuffer(t.gl.ARRAY_BUFFER,e),t.gl.drawArrays(t.gl.LINE_STRIP,0,e.numItems)),t.popModelMatrix()},function(){const i=[];let s=0,r=0;for(s=0;s<=Math.round(24);s++)r=360/Math.round(24)*s*mt,i.push(.5*Math.cos(r)),i.push(0),i.push(.5*Math.sin(r));for(s=0;s<=Math.round(24);s++)r=360/Math.round(24)*s*mt,i.push(.5*Math.cos(r)),i.push(.5*Math.sin(r)),i.push(0);for(s=0;s<=Math.round(24);s++)r=360/Math.round(24)*s*mt,i.push(0),i.push(.5*Math.cos(r)),i.push(.5*Math.sin(r));t.gl.bindBuffer(t.gl.ARRAY_BUFFER,e),t.gl.bufferData(t.gl.ARRAY_BUFFER,new Float32Array(i),t.gl.STATIC_DRAW),e.itemSize=3,e.numItems=i.length/e.itemSize}()},WireCube:function(t){const e=t.gl.createBuffer(),i=vec3.create();this.render=function(t,s,r,n){t.pushModelMatrix(),vec3.set(i,s||1,r||1,n||1),mat4.scale(t.mvMatrix,t.mvMatrix,i);const o=t.getShader();o&&(o.bind(),t.gl.bindBuffer(t.gl.ARRAY_BUFFER,e),t.gl.vertexAttribPointer(o.getAttrVertexPos(),e.itemSize,t.gl.FLOAT,!1,0,0),t.gl.enableVertexAttribArray(o.getAttrVertexPos()),t.gl.bindBuffer(t.gl.ARRAY_BUFFER,e),t.gl.drawArrays(t.gl.LINE_STRIP,0,e.numItems)),t.popModelMatrix()},function(){const i=[];i.push(-1,-1,1),i.push(1,-1,1),i.push(1,1,1),i.push(-1,1,1),i.push(-1,-1,1),i.push(-1,-1,-1),i.push(1,-1,-1),i.push(1,1,-1),i.push(-1,1,-1),i.push(-1,-1,-1),i.push(-1,-1,-1),i.push(-1,1,-1),i.push(-1,1,1),i.push(-1,-1,1),i.push(-1,-1,-1),i.push(1,-1,-1),i.push(1,1,-1),i.push(1,1,1),i.push(1,-1,1),i.push(1,-1,-1),t.gl.bindBuffer(t.gl.ARRAY_BUFFER,e),t.gl.bufferData(t.gl.ARRAY_BUFFER,new Float32Array(i),t.gl.STATIC_DRAW),e.itemSize=3,e.numItems=i.length/e.itemSize}()},MatrixStack:Mt,Mesh:lt,MESH:ht,ShaderLibMods:pt,Shader:It,Uniform:nt,MESHES:ut,Context:Bt,Texture:B,TextureEffect:gt,isWindows:Et,getWheelSpeed:At,getWheelDelta:bt,onLoadingAssetsFinished:null,ProfileData:St,UniColorShader:class{constructor(t){this.shader=new CGL.Shader(t,"markermaterial");const e="".endl()+"void main()".endl()+"{".endl()+" outColor = vec4(color.rgb,1.0);".endl()+"}",i="".endl()+"IN vec3 vPosition;".endl()+"UNI mat4 projMatrix;".endl()+"UNI mat4 mvMatrix;".endl()+"void main()".endl()+"{".endl()+" gl_Position = projMatrix * mvMatrix * vec4(vPosition,1.0);".endl()+"}";this.shader.setSource(i,e),this.coloruni=this.shader.addUniformFrag("4f","color",[1,.777,1,1])}setColor(t,e,i,s){this.coloruni.set(t,e,i,s)}}},at.BLEND_MODES,at.SHADER,at.MATH,at.BLEND_MODES);window.CGL=Lt;const kt=function(t){Y.apply(this),this.id=CABLES.uuid(),this.portIn=null,this.portOut=null,this.scene=t,this.activityCounter=0,this.ignoreInSerialize=!1};kt.prototype.setValue=function(t){void 0===t?this._setValue():this.portIn.set(t)},kt.prototype.activity=function(){this.activityCounter++},kt.prototype._setValue=function(){if(!this.portOut)return void this.remove();const t=this.portOut.get();t==t&&(this.portIn.type!=l.OP_PORT_TYPE_FUNCTION&&this.activity(),(this.portIn.get()!==t||this.portIn.changeAlways)&&this.portIn.set(t))},kt.prototype.getOtherPort=function(t){return t==this.portIn?this.portOut:this.portIn},kt.prototype.remove=function(){this.portIn&&this.portIn.removeLink(this),this.portOut&&this.portOut.removeLink(this),this.scene&&this.scene.emitEvent("onUnLink",this.portIn,this.portOut,this),!this.portIn||this.portIn.type!=l.OP_PORT_TYPE_OBJECT&&this.portIn.type!=l.OP_PORT_TYPE_ARRAY||(this.portIn.set(null),this.portIn.links.length>0&&this.portIn.set(this.portIn.links[0].getOtherPort(this.portIn).get())),this.portIn&&this.portIn.parent._checkLinksNeededToWork(),this.portOut&&this.portOut.parent._checkLinksNeededToWork(),this.portIn=null,this.portOut=null,this.scene=null},kt.prototype.link=function(t,e){if(!kt.canLink(t,e))return console.warn("[core_link] cannot link ports!",t,e),!1;t.direction==c.PORT_DIR_IN?(this.portIn=t,this.portOut=e):(this.portIn=e,this.portOut=t),t.addLink(this),e.addLink(this),this.setValue(),t.onLink&&t.onLink(this),e.onLink&&e.onLink(this),t.parent._checkLinksNeededToWork(),e.parent._checkLinksNeededToWork()},kt.prototype.getSerialized=function(){const t={};return t.portIn=this.portIn.getName(),t.portOut=this.portOut.getName(),t.objIn=this.portIn.parent.id,t.objOut=this.portOut.parent.id,t},kt.canLinkText=function(t,e){if(t.direction==e.direction){let t="(out)";return e.direction==c.PORT_DIR_IN&&(t="(in)"),"can not link: same direction "+t}return t.parent==e.parent?"can not link: same op":t.type!=l.OP_PORT_TYPE_DYNAMIC&&e.type!=l.OP_PORT_TYPE_DYNAMIC&&t.type!=e.type?"can not link: different type":t?e?t.direction==c.PORT_DIR_IN&&t.isAnimated()||e.direction==c.PORT_DIR_IN&&e.isAnimated()?"can not link: is animated":t.isLinkedTo(e)?"ports already linked":t.canLink&&!t.canLink(e)||e.canLink&&!e.canLink(t)?"Incompatible":"can link":"can not link: port 2 invalid":"can not link: port 1 invalid"},kt.canLink=function(t,e){return!!t&&(!!e&&((t.direction!=c.PORT_DIR_IN||!t.isAnimated())&&((e.direction!=c.PORT_DIR_IN||!e.isAnimated())&&(!t.isHidden()&&!e.isHidden()&&(!t.isLinkedTo(e)&&(t.direction!=e.direction&&((t.type==e.type||t.type==l.OP_PORT_TYPE_DYNAMIC||e.type==l.OP_PORT_TYPE_DYNAMIC)&&(t.type==l.OP_PORT_TYPE_DYNAMIC||e.type==l.OP_PORT_TYPE_DYNAMIC||t.parent!=e.parent&&(!(t.canLink&&!t.canLink(e))&&!(e.canLink&&!e.canLink(t)))))))))))};const Vt=function(){Y.apply(this),this._log=new a("core_op"),this.data={},this.storage={},this.objName="",this.portsOut=[],this.portsIn=[],this.portsInData=[],this.opId="",this.uiAttribs={},this.enabled=!0,this.patch=arguments[0],this.name=arguments[1],this._needsLinkedToWork=[],this._needsParentOp=null,this._shortOpName="",this.hasUiErrors=!1,this._uiErrors={},arguments[1]&&(this._shortOpName=CABLES.getShortOpName(arguments[1]),this.getTitle()),this.id=arguments[2]||T(),this.onAddPort=null,this.onCreate=null,this.onResize=null,this.onLoaded=null,this.onDelete=null,this.onUiAttrChange=null,this.onError=null,this._instances=null,this.preRender=null,this.init=null};{Vt.prototype.clearUiAttrib=function(t){const e={name:null};this.uiAttrib(e)},Vt.prototype.getTitle=function(){return this.uiAttribs?(void 0!==this.uiAttribs.title&&""!==this.uiAttribs.title||-1!=this.objName.indexOf("Ops.Ui.")||(this.uiAttribs.title=this._shortOpName),void 0===this.uiAttribs.title&&(this.uiAttribs.title=this._shortOpName),this.uiAttribs.title):"nouiattribs"+this.name},Vt.prototype.setTitle=function(t){const e=this.name!=t;this.name=t,this.uiAttr({title:t}),e&&this.emitEvent("onTitleChange",t)};const t=function(t){if(!t)return;(t.error||t.warning||t.hint)&&this._log.warn("old ui error/warning attribute in "+this.name+", use op.setUiError !",t),"object"!=typeof t&&this._log.error("op.uiAttrib attribs are not of type object"),this.uiAttribs||(this.uiAttribs={});let e=!1;for(const i in t)this.uiAttribs[i]!=t[i]&&(e=!0),this.uiAttribs[i]=t[i];this.uiAttribs.hasOwnProperty("selected")&&0==this.uiAttribs.selected&&delete this.uiAttribs.selected,t.title&&t.title!=this.name&&this.setTitle(t.title),e&&(this.emitEvent("onUiAttribsChange",t),this.patch.emitEvent("onUiAttribsChange",this,t))};Vt.prototype.setUiAttribs=Vt.prototype.setUiAttrib=Vt.prototype.uiAttr=t,Vt.prototype.getName=function(){return this.uiAttribs.name?this.uiAttribs.name:this.objName.split(".")},Vt.prototype.addOutPort=function(t){return t.direction=c.PORT_DIR_OUT,t.parent=this,this.portsOut.push(t),this.emitEvent("onPortAdd",t),t},Vt.prototype.hasDynamicPort=function(){let t=0;for(t=0;tt==i);n.setValue(t),r.defaultValue=i,n.defaultValue=t}}return r},Vt.prototype.inSwitch=function(t,e,i,s){let r=null;if(s){const i=new et(this,t,l.OP_PORT_TYPE_STRING,{display:"switch",hidePort:!0,type:"string",values:e});r=this.addInPort(i)}else{const s=new et(this,t+" index",l.OP_PORT_TYPE_VALUE,{increment:"integer",hideParam:!0}),n=this.addInPort(s),o=new it(this,t,l.OP_PORT_TYPE_STRING,{display:"switch",hidePort:!0,type:"string",values:e},n);if(s.onLinkChanged=function(){o.setUiAttribs({greyout:s.isLinked()})},r=this.addInPort(o),void 0!==i){r.set(i);const t=e.findIndex(t=>t==i);n.setValue(t),r.defaultValue=i,n.defaultValue=t}}return r},Vt.prototype.inValueInt=Vt.prototype.inInt=function(t,e){const i=this.addInPort(new et(this,t,l.OP_PORT_TYPE_VALUE,{increment:"integer"}));return void 0!==e&&(i.set(e),i.defaultValue=e),i},Vt.prototype.inFile=function(t,e,i){const s=this.addInPort(new et(this,t,l.OP_PORT_TYPE_VALUE,{display:"file",type:"string",filter:e}));return void 0!==i&&(s.set(i),s.defaultValue=i),s},Vt.prototype.inUrl=function(t,e,i){const s=this.addInPort(new et(this,t,l.OP_PORT_TYPE_STRING,{display:"file",type:"string",filter:e}));return void 0!==i&&(s.set(i),s.defaultValue=i),s},Vt.prototype.inTexture=function(t,e){const i=this.addInPort(new et(this,t,l.OP_PORT_TYPE_OBJECT,{display:"texture",objType:"texture",preview:!0}));return void 0!==e&&i.set(e),i},Vt.prototype.inObject=function(t,e,i){const s=this.addInPort(new et(this,t,l.OP_PORT_TYPE_OBJECT,{objType:i}));return void 0!==e&&s.set(e),s},Vt.prototype.inGradient=function(t,e){const i=this.addInPort(new et(this,t,l.OP_PORT_TYPE_VALUE,{display:"gradient",hidePort:!0}));return void 0!==e&&i.set(e),i},Vt.prototype.inArray=function(t,e,i){!i&&CABLES.UTILS.isNumeric(e)&&(i=e);const s=this.addInPort(new et(this,t,l.OP_PORT_TYPE_ARRAY,{stride:i}));return void 0===e||!Array.isArray(e)&&null!=e||s.set(e),s},Vt.prototype.inValueSlider=Vt.prototype.inFloatSlider=function(t,e,i,s){const r={display:"range"};null!=i&&null!=s&&(r.min=i,r.max=s);const n=this.addInPort(new et(this,t,l.OP_PORT_TYPE_VALUE,r));return void 0!==e&&(n.set(e),n.defaultValue=e),n},Vt.prototype.outFunction=Vt.prototype.outTrigger=function(t,e){const i=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_FUNCTION));return void 0!==e&&i.set(e),i},Vt.prototype.outValue=Vt.prototype.outNumber=function(t,e){const i=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_VALUE));return void 0!==e&&i.set(e),i},Vt.prototype.outValueBool=Vt.prototype.outBool=function(t,e){const i=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_VALUE,{display:"bool"}));return void 0!==e?i.set(e):i.set(0),i},Vt.prototype.outBoolNum=function(t,e){const i=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_VALUE,{display:"boolnum"}));return i.set=function(t){this.setValue(t?1:0)}.bind(i),void 0!==e?i.set(e):i.set(0),i},Vt.prototype.outValueString=function(t,e){const i=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_VALUE,{type:"string"}));return void 0!==e&&i.set(e),i},Vt.prototype.outString=function(t,e){const i=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_STRING,{type:"string"}));return void 0!==e?i.set(e):i.set(""),i},Vt.prototype.outObject=function(t,e,i){const s=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_OBJECT,{objType:i||null}));return s.set(e||null),s.ignoreValueSerialize=!0,s},Vt.prototype.outArray=function(t,e,i){!i&&CABLES.UTILS.isNumeric(e)&&(i=e);const s=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_ARRAY,{stride:i}));return void 0===e||!Array.isArray(e)&&null!=e||s.set(e),s.ignoreValueSerialize=!0,s},Vt.prototype.outTexture=function(t,e){const i=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_OBJECT,{preview:!0,objType:"texture"}));return void 0!==e&&i.set(e),i.ignoreValueSerialize=!0,i},Vt.prototype.inDynamic=function(t,e,i,s){const r=new et(this,t,l.OP_PORT_TYPE_DYNAMIC,i);return r.shouldLink=function(t,i){if(e&&g.isArray(e)){for(let s=0;s0&&(t.storage=this.storage),this.uiAttribs.hasOwnProperty("working")&&1==this.uiAttribs.working&&delete this.uiAttribs.working,t.portsIn=[],t.portsOut=[];for(let e=0;e-1&&this._log.warn("setuierror id cant have spaces! ",t),!e&&this._uiErrors.hasOwnProperty(t)?delete this._uiErrors[t]:!e||this._uiErrors.hasOwnProperty(t)&&this._uiErrors[t].txt==e||(null==i&&(i=2),this._uiErrors[t]={txt:e,level:i,id:t});const s=[];for(const t in this._uiErrors)s.push(this._uiErrors[t]);this.uiAttr({uierrors:s}),this.hasUiErrors=Object.keys(this._uiErrors).length,this.emitEvent("uiErrorChange")},Vt.prototype.setError=function(t,e){this._log.warn("old error message op.error() - use op.setUiError()")},Vt.prototype.setEnabled=function(t){this.enabled=t,this.emitEvent("onEnabledChange",t)},Vt.prototype.setPortGroup=function(t,e){for(let i=0;i{e(this._patch),this.emitEvent("finishedAll")},100)}this._wasFinishedPrinted||(this._wasFinishedPrinted=!0,this.print()),this.emitEvent("finishedAll")}},Dt.prototype.getList=function(){let t=[];for(const e in this._loadingAssets)t.push(this._loadingAssets[e]);return t},Dt.prototype.getListJobs=function(){let t=[];for(const e in this._loadingAssets)this._loadingAssets[e].finished||t.push(this._loadingAssets[e].name);return t},Dt.prototype.print=function(){if(this._patch.config.silent)return;const t=[];for(const e in this._loadingAssets)t.push([this._loadingAssets[e].order,this._loadingAssets[e].type,this._loadingAssets[e].name,(this._loadingAssets[e].timeEnd-this._loadingAssets[e].timeStart)/1e3+"s"]);this._log.groupCollapsed("finished loading "+this._order+" assets in "+(Date.now()-this._startTime)/1e3+"s"),this._log.table(t),this._log.groupEnd()},Dt.prototype.finished=function(t){this._loadingAssets[t]&&(this._loadingAssets[t].finished=!0,this._loadingAssets[t].timeEnd=Date.now()),this.checkStatus(),this.emitEvent("finishedTask")},Dt.prototype._startAssetTasks=function(){for(let t=0;t0},Gt.prototype.increment=function(){this._index++},Gt.prototype.index=function(){return this._index};const Ht=function(t){this.startFrame=t.getFrameNum();let e={},i=null,s=0;this.getItems=function(){return e},this.clear=function(){e={}},this.add=function(r,n){null!==i&&(n&&n.id==i||e[i]&&(e[i].timeUsed+=performance.now()-s,(!e[i].peakTime||dt()-e[i].peakTime>5e3)&&(e[i].peak=0,e[i].peakTime=dt()),e[i].peak=Math.max(e[i].peak,performance.now()-s))),null!==n?(e[n.id]||(e[n.id]={numTriggers:0,timeUsed:0}),e[n.id].lastFrame!=t.getFrameNum()&&(e[n.id].numTriggers=0),e[n.id].lastFrame=t.getFrameNum(),e[n.id].numTriggers++,e[n.id].opid=n.parent.id,e[n.id].title=n.parent.name+"."+n.name,e[n.id].subPatch=n.parent.uiAttribs.subPatch,i=n.id,s=performance.now()):i=null},this.print=function(){console.log("--------");for(const t in e)console.log(e[t].title+": "+e[t].numTriggers+" / "+e[t].timeUsed)}};var zt=class extends Y{constructor(t,e,i){super(),this._name=t,this.type=i,this.setValue(e)}addListener(t){this.on("change",t,"var")}getValue(){return this._v}getName(){return this._name}setValue(t){this._v=t,this.emitEvent("change",t,this)}};const Wt=function(t){Y.apply(this),this._log=new a("core_patch"),this.ops=[],this.settings={},this.config=t||{glCanvasResizeToWindow:!1,prefixAssetPath:"",prefixJsPath:"",silent:!0,onError:null,onFinishedLoading:null,onFirstFrameRendered:null,onPatchLoaded:null,fpsLimit:0},this.timer=new ft,this.freeTimer=new ft,this.animFrameOps=[],this.animFrameCallbacks=[],this.gui=!1,CABLES.logSilent=this.silent=!0,this.profiler=null,this.aborted=!1,this._crashedOps=[],this._renderOneFrame=!1,this._animReq=null,this._opIdCache={},this._triggerStack=[],this.loading=new Dt(this),this._volumeListeners=[],this._paused=!1,this._frameNum=0,this.instancing=new Gt,this.onOneFrameRendered=null,this.namedTriggers={},this._origData=null,this._frameNext=0,this._frameInterval=0,this._lastFrameTime=0,this._frameWasdelayed=!0,function(){return!this}()||this._log.warn("not in strict mode: core patch"),this._isLocal=0===document.location.href.indexOf("file:"),this.config.hasOwnProperty("silent")&&(this.silent=CABLES.logSilent=this.config.silent),this.config.hasOwnProperty("doRequestAnimation")||(this.config.doRequestAnimation=!0),this.config.prefixAssetPath||(this.config.prefixAssetPath=""),this.config.prefixJsPath||(this.config.prefixJsPath=""),this.config.masterVolume||(this.config.masterVolume=1),this._variables={},this._variableListeners=[],this.vars={},t&&t.vars&&(this.vars=t.vars),this.cgl=new Bt(this),this.cgp=null,this.cgl.setCanvas(this.config.glCanvasId||this.config.glCanvas||"glcanvas"),!0===this.config.glCanvasResizeToWindow&&this.cgl.setAutoResize("window"),!0===this.config.glCanvasResizeToParent&&this.cgl.setAutoResize("parent"),this.loading.setOnFinishedLoading(this.config.onFinishedLoading),this.cgl.aborted&&(this.aborted=!0),this.cgl.silent&&(this.silent=!0),this.freeTimer.play(),this.exec(),this.aborted||(this.config.patch?this.deSerialize(this.config.patch):this.config.patchFile&&w(this.config.patchFile,(t,e)=>{const i=JSON.parse(e);if(t){return this._log.error("err",t),this._log.error("data",i),void this._log.error("data",i.msg)}this.deSerialize(i)}),this.timer.play()),console.log("made with https://cables.gl")};Wt.prototype.isPlaying=function(){return!this._paused},Wt.prototype.isRenderingOneFrame=function(){return this._renderOneFrame},Wt.prototype.renderOneFrame=function(){this._paused=!0,this._renderOneFrame=!0,this.exec(),this._renderOneFrame=!1},Wt.prototype.getFPS=function(){return console.log("deprecated getfps"),0},Wt.prototype.isEditorMode=function(){return!0===this.config.editorMode},Wt.prototype.pause=function(){cancelAnimationFrame(this._animReq),this.emitEvent("pause"),this._animReq=null,this._paused=!0,this.freeTimer.pause()},Wt.prototype.resume=function(){this._paused&&(cancelAnimationFrame(this._animReq),this._paused=!1,this.freeTimer.play(),this.emitEvent("resume"),this.exec())},Wt.prototype.setVolume=function(t){this.config.masterVolume=t;for(let e=0;e0||document.location.href.indexOf("cables.local")>0){const e=document.location.pathname.split("/");return"/assets/"+(t||e[e.length-1])+"/"}return this.config.hasOwnProperty("assetPath")?this.config.assetPath:"assets/"},Wt.prototype.getJsPath=function(){return this.config.hasOwnProperty("jsPath")?this.config.jsPath:"js/"},Wt.prototype.getFilePath=function(t){return this._isLocal&&!this.config.allowLocalFileAccess&&this.exitError("localAccess","Browser security forbids loading files directly without a webserver. Upload files to a server to work. use allowLocalFileAccess:true to ignore this."),t?0===(t=String(t)).indexOf("https:")||0===t.indexOf("http:")||0===t.indexOf("data:")?t:(t=t.replace("//","/"),this.config.prefixAssetPath+t+(this.config.suffixAssetPath||"")):t},Wt.prototype.clear=function(){for(this.emitEvent("patchClearStart"),this.cgl.TextureEffectMesh=null,this.animFrameOps.length=0,this.timer=new ft;this.ops.length>0;)this.deleteOp(this.ops[0].id);this.emitEvent("patchClearEnd")},Wt.getOpClass=function(t){const e=t.split(".");let i=null;try{return 2==e.length?i=window[e[0]][e[1]]:3==e.length?i=window[e[0]][e[1]][e[2]]:4==e.length?i=window[e[0]][e[1]][e[2]][e[3]]:5==e.length?i=window[e[0]][e[1]][e[2]][e[3]][e[4]]:6==e.length?i=window[e[0]][e[1]][e[2]][e[3]][e[4]][e[5]]:7==e.length?i=window[e[0]][e[1]][e[2]][e[3]][e[4]][e[5]][e[6]]:8==e.length?i=window[e[0]][e[1]][e[2]][e[3]][e[4]][e[5]][e[6]][e[7]]:9==e.length?i=window[e[0]][e[1]][e[2]][e[3]][e[4]][e[5]][e[6]][e[7]][e[8]]:10==e.length&&(i=window[e[0]][e[1]][e[2]][e[3]][e[4]][e[5]][e[6]][e[7]][e[8]][e[9]]),i}catch(t){return null}},Wt.prototype.createOp=function(t,e,i=null){let s=null,r="";try{if(-1===t.indexOf("Ops.")){const n=t;if(CABLES.OPS[n])r=CABLES.OPS[n].objName,s=new CABLES.OPS[n].f(this,r,e,n),s.opId=n;else{if(!i)throw new Error("could not find op by id: "+n);t=i,this._log.warn("could not find op by id: "+n)}}if(!s){r=t;const i=t.split(".");if(!Wt.getOpClass(r))throw this.emitEvent("criticalError",{title:"unknown op",text:"unknown op: "+r}),this._log.error("unknown op: "+r),new Error("unknown op: "+r);if(2==i.length?s=new window[i[0]][i[1]](this,r,e):3==i.length?s=new window[i[0]][i[1]][i[2]](this,r,e):4==i.length?s=new window[i[0]][i[1]][i[2]][i[3]](this,r,e):5==i.length?s=new window[i[0]][i[1]][i[2]][i[3]][i[4]](this,r,e):6==i.length?s=new window[i[0]][i[1]][i[2]][i[3]][i[4]][i[5]](this,r,e):7==i.length?s=new window[i[0]][i[1]][i[2]][i[3]][i[4]][i[5]][i[6]](this,r,e):8==i.length?s=new window[i[0]][i[1]][i[2]][i[3]][i[4]][i[5]][i[6]][i[7]](this,r,e):9==i.length?s=new window[i[0]][i[1]][i[2]][i[3]][i[4]][i[5]][i[6]][i[7]][i[8]](this,r,e):10==i.length?s=new window[i[0]][i[1]][i[2]][i[3]][i[4]][i[5]][i[6]][i[7]][i[8]][i[9]](this,r,e):this._log.warn("parts.length",i.length),s){s.opId=null;for(const t in CABLES.OPS)CABLES.OPS[t].objName==r&&(s.opId=t)}}}catch(t){if(this._crashedOps.push(r),this.emitEvent("exceptionOp",t,r,s),!this.isEditorMode())throw this._log.error(t),this._log.error("[instancing error] "+r,t),CABLES.api&&CABLES.api.sendErrorReport(t),this.exitError("INSTANCE_ERR","Instancing Error "+r,t),new Error("instancing error "+r)}return s?(s.objName=r,s.patch=this):this._log.log("no op was created!?",t,e),s},Wt.prototype.addOp=function(t,e,i,s,r){const n=this.createOp(t,i,r);if(n){if((e=e||{}).hasOwnProperty("errors")&&delete e.errors,e.hasOwnProperty("error")&&delete e.error,e.subPatch=e.subPatch||0,n.uiAttr(e),n.onCreate&&n.onCreate(),n.hasOwnProperty("onAnimFrame")&&this.addOnAnimFrame(n),n.hasOwnProperty("onMasterVolumeChanged")&&this._volumeListeners.push(n),this._opIdCache[n.id])return void this._log.warn("opid with id "+n.id+" already exists in patch!");this.ops.push(n),this._opIdCache[n.id]=n,this.emitEvent("onOpAdd",n,s),n.init&&n.init()}else this._log.error("addop: no op.....");return n},Wt.prototype.addOnAnimFrame=function(t){for(let e=0;e0&&n.portsIn[0].isLinked()&&n.portsOut.length>0&&n.portsOut[0].isLinked()&&n.portsIn[0].getType()==n.portsOut[0].getType()&&n.portsIn[0].links[0]&&(o=n.portsIn[0].links[0].getOtherPort(n.portsIn[0]),a=n.portsOut[0].links[0].getOtherPort(n.portsOut[0]));const h=this.ops[r];h.removeLinks(),h.emitEvent("onDelete",this.ops[r]),this.onDelete&&(this._log.warn("deprecated this.onDelete",this.onDelete),this.onDelete(h)),this.ops.splice(r,1),this.emitEvent("onOpDelete",h,i),h.onDelete&&h.onDelete(i),h.cleanUp(),null!==o&&null!==a&&this.link(o.parent,o.getName(),a.parent,a.getName()),delete this._opIdCache[t];break}}s||this._log.warn("core patch deleteop: not found...")},Wt.prototype.getFrameNum=function(){return this._frameNum},Wt.prototype.emitOnAnimFrameEvent=function(t){t=t||this.timer.getTime();for(let e=0;e=500&&0!==this._lastFrameTime&&!this._frameWasdelayed)return this._lastFrameTime=0,setTimeout(this.exec.bind(this),500),this.emitEvent("renderDelayStart"),void(this._frameWasdelayed=!0);if(this._renderOneFrame||0===this.config.fpsLimit||i>this._frameInterval||this._frameWasdelayed){CABLES.now();this.renderFrame(),this._frameInterval&&(this._frameNext=e-i%this._frameInterval)}this._frameWasdelayed&&(this.emitEvent("renderDelayEnd"),this._frameWasdelayed=!1),this._renderOneFrame&&(this.onOneFrameRendered&&this.onOneFrameRendered(),this.emitEvent("renderedOneFrame"),this._renderOneFrame=!1),this.config.doRequestAnimation&&(this._animReq=requestAnimationFrame(this.exec.bind(this)))},Wt.prototype.link=function(t,e,i,s,r,n){if(!t)return void this._log.warn("link: op1 is null ");if(!i)return void this._log.warn("link: op2 is null");const o=t.getPort(e,r),a=i.getPort(s,r);if(o)if(a){if(!o.shouldLink(o,a)||!a.shouldLink(o,a))return!1;if(kt.canLink(o,a)){const t=new kt(this);return t.link(o,a),this.emitEvent("onLink",o,a,t,n),t}}else this._log.warn("port not found! "+s+" of "+i.name+"("+i.objName+")");else this._log.warn("port not found! "+e+"("+t.objName+")")},Wt.prototype.serialize=function(t){const e={};t=t||{},e.ops=[],e.settings=this.settings;for(const t in this.ops){const i=this.ops[t];e.ops.push(i.getSerialized())}return t.asObject?e:JSON.stringify(e)},Wt.prototype.getOpById=function(t){return this._opIdCache[t]},Wt.prototype.getOpsByName=function(t){const e=[];for(const i in this.ops)this.ops[i].name==t&&e.push(this.ops[i]);return e},Wt.prototype.getOpsByObjName=function(t){const e=[];for(const i in this.ops)this.ops[i].objName==t&&e.push(this.ops[i]);return e},Wt.prototype.loadLib=function(t){C("/ui/libs/"+t+".js",(t,e)=>{const i=document.createElement("script");i.type="text/javascript",i.text=e,document.getElementsByTagName("head")[0].appendChild(i)},"GET")},Wt.prototype.reloadOp=function(t,e){let i=0;const s=[],r=[];for(const e in this.ops)this.ops[e].objName==t&&r.push(this.ops[e]);for(let e=0;e200&&this._log.warn("long op init ",t.ops[s].objName,a)}for(const t in this.ops)this.ops[t].onLoadedValueSet&&(this.ops[t].onLoadedValueSet(this.ops[t]._origData),this.ops[t].onLoadedValueSet=null,this.ops[t]._origData=null),this.ops[t].emitEvent("loadedValueSet");if(t.ops)for(let e=0;e{this.loading.finished(s)},100),this.config.onPatchLoaded&&this.config.onPatchLoaded(this),this.emitEvent("patchLoadEnd",i,t,e)},Wt.prototype.profile=function(t){this.profiler=new Ht(this);for(const e in this.ops)this.ops[e].profile(t)},Wt.prototype.setVariable=function(t,e){void 0!==this._variables[t]?this._variables[t].setValue(e):this._log.warn("variable "+t+" not found!")},Wt.prototype._sortVars=function(){if(!this.isEditorMode())return;const t={};Object.keys(this._variables).sort((t,e)=>t.localeCompare(e,"en",{sensitivity:"base"})).forEach(e=>{t[e]=this._variables[e]}),this._variables=t},Wt.prototype.hasVar=function(t){return void 0!==this._variables[t]},Wt.prototype.setVarValue=function(t,e,i){return this.hasVar(t)?this._variables[t].setValue(e):(this._variables[t]=new zt(t,e,i),this._sortVars(),this.emitEvent("variablesChanged")),this._variables[t]},Wt.prototype.getVarValue=function(t,e){if(this._variables.hasOwnProperty(t))return this._variables[t].getValue()},Wt.prototype.getVar=function(t){if(this._variables.hasOwnProperty(t))return this._variables[t]},Wt.prototype.deleteVar=function(t){for(let e=0;e=i._param.minValue&&e<=i._param.maxValue)try{i.setValueAtTime?i.setValueAtTime(e,s.currentTime):i.value=e}catch(e){throw t.log("Possible AudioParam problem with tone.js op: ",e),e.printStackTrace&&e.printStackTrace(),e}else t.log("Warning: The value for an audio parameter is out of range!");else if(i.minValue&&i.maxValue)if(e>=i.minValue&&e<=i.maxValue)try{i.setValueAtTime?i.setValueAtTime(e,s.currentTime):i.value=e}catch(e){throw t.log("AudioParam has minValue / maxValue defined, and value is in range, but setting the value failed! ",e),e.printStackTrace&&e.printStackTrace(),e}else t.log("Warning: The value for an audio parameter is out of range!");else try{i.setValueAtTime?i.setValueAtTime(e,s.currentTime):i.value=e}catch(e){throw t.log("Possible AudioParam problem (without minValue / maxValue): ",e),e.printStackTrace&&e.printStackTrace(),e}if(n.webAudio.previousAudioInNode&&n.webAudio.previousAudioInNode.disconnect){try{n.webAudio.previousAudioInNode.disconnect(i)}catch(e){throw t.log("Could not disconnect previous audio node: ",e),e}n.webAudio.previousAudioInNode=void 0}}else n.webAudio.previousAudioInNode},n},loadAudioFile:function(t,e,i,s,r){const n=jt.createAudioContext();let o=null;(r||void 0===r)&&(o=t.loading.start("audio",e),t.isEditorMode()&&gui.jobs().start({id:"loadaudio"+o,title:" loading audio ("+e+")"}));const a=new XMLHttpRequest;e&&(a.open("GET",e,!0),a.responseType="arraybuffer",a.onload=function(){t.loading.finished(o),t.isEditorMode()&&gui.jobs().finish("loadaudio"+o),n.decodeAudioData(a.response,i,s)},a.send())},isValidToneTime:function(t){try{new Tone.Time(t)}catch(t){return!1}return!0},isValidToneNote:function(t){try{Tone.Frequency(t)}catch(t){return!1}return!0}},Kt=function(t,e,i){this._patch=t,this.connector=i,this._log=new a("PatchConnectionReceiver")};Kt.prototype._addOp=function(t){let e=null;t.vars.uiAttribs&&(e=t.vars.uiAttribs);const i=this._patch.addOp(t.vars.objName,e,t.vars.opId,!0);i&&(i.id=t.vars.opId,t.vars.portsIn&&t.vars.portsIn.forEach(t=>{const e=i.getPortByName(t.name);e&&e.set(t.value)}))},Kt.prototype._receive=function(t){let e={};if(e=t.hasOwnProperty("event")?t:JSON.parse(t.data),e.event==u.PACO_OP_CREATE){if(this._patch.getOpById(e.vars.opId))return;this._log.verbose("op create:",e.vars.objName),window.gui?gui.serverOps.loadOpLibs(e.vars.objName,()=>{this._addOp(e)}):this._addOp(e)}else if(e.event==u.PACO_DESERIALIZE)e.vars.json&&(window.gui?gui.serverOps.loadProjectDependencies(e.vars.json,()=>{this._patch.deSerialize(e.vars.json,e.vars.genIds)}):this._patch.deSerialize(e.vars.json,e.vars.genIds));else if(e.event==u.PACO_LOAD)this._log.verbose("PACO load patch....."),this._patch.clear(),window.gui?gui.serverOps.loadProjectDependencies(JSON.parse(e.vars.patch),()=>{this._patch.deSerialize(e.vars.patch)}):this._patch.deSerialize(e.vars.patch);else if(e.event==u.PACO_CLEAR)this._patch.clear(),this._log.log("clear");else if(e.event==u.PACO_OP_DELETE){this._log.verbose("op delete",e.vars.objName);this._patch.getOpById(e.vars.op);this._patch.deleteOp(e.vars.op,!0)}else if(e.event==u.PACO_OP_ENABLE){const t=this._patch.getOpById(e.vars.op);t&&(t.enabled=!0)}else if(e.event==u.PACO_OP_DISABLE){const t=this._patch.getOpById(e.vars.op);t&&(t.enabled=!1)}else if(e.event==u.PACO_UIATTRIBS){const t=this._patch.getOpById(e.vars.op);t&&t.setUiAttrib(e.vars.uiAttribs)}else if(e.event==u.PACO_UNLINK){const t=this._patch.getOpById(e.vars.op1),i=this._patch.getOpById(e.vars.op2);if(!t||!i)return;const s=t.getPort(e.vars.port1),r=i.getPort(e.vars.port2);s&&r?s.removeLinkTo(r):this._log.warn("paco unlink could not find port...")}else if(e.event==u.PACO_LINK){const t=this._patch.getOpById(e.vars.op1),i=this._patch.getOpById(e.vars.op2);t&&i&&this._patch.link(t,e.vars.port1,i,e.vars.port2)}else if(e.event==u.PACO_VALUECHANGE){if("+ create new one"===e.vars.v)return;const t=this._patch.getOpById(e.vars.op);if(t){const i=t.getPort(e.vars.port);i&&i.set(e.vars.v)}}else if(e.event==u.PACO_VARIABLES){const t=this._patch.getOpById(e.vars.opId);t&&t.varName&&t.varName.set(e.vars.varName)}else if(e.event==u.PACO_TRIGGERS){const t=this._patch.getOpById(e.vars.opId);t&&t.varName&&t.varName.set(e.vars.varName)}else if(e.event==u.PACO_PORT_SETVARIABLE){const t=this._patch.getOpById(e.vars.opId);if(t){const i=t.getPortByName(e.vars.portName);i&&i.setVariable(e.vars.variableName)}}else if(e.event==u.PACO_PORT_SETANIMATED){const t=this._patch.getOpById(e.vars.opId);if(t){t.portsIn[e.vars.portIndex]&&e.vars.hasOwnProperty("targetState")&&this._patch.emitEvent("pacoPortValueSetAnimated",t,e.vars.portIndex,e.vars.targetState,e.vars.defaultValue)}}else if(e.event==u.PACO_PORT_ANIM_UPDATED){const t=this._patch.getOpById(e.vars.opId);if(t){const i=t.getPortByName(e.vars.portName);if(i){const t=i.getSerialized();t.anim=e.vars.anim,i.anim=null,i.deSerializeSettings(t),this._patch.emitEvent("pacoPortAnimUpdated",i)}}}else this._log.warn("unknown patchConnectionEvent!",t)};const Qt=function(t){this.connectors=[],this.paused=!1,t.addEventListener("onOpDelete",t=>{this.send(CABLES.PACO_OP_DELETE,{op:t.id,objName:t.objName})}),t.addEventListener("patchClearStart",()=>{this.paused=!0}),t.addEventListener("patchClearEnd",()=>{this.paused=!1}),t.addEventListener("patchLoadStart",()=>{this.paused=!0}),t.addEventListener("patchLoadEnd",(t,e,i)=>{this.paused=!1,this.send(CABLES.PACO_DESERIALIZE,{json:e,genIds:i})}),t.addEventListener("onOpAdd",t=>{const e=[];t.portsIn.forEach(t=>{const i={id:t.id,name:t.name,value:t.get()};e.push(i)});let i={};t.uiAttribs&&(i={...t.uiAttribs}),this.send(CABLES.PACO_OP_CREATE,{opId:t.id,objName:t.objName,uiAttribs:i,portsIn:e})}),t.addEventListener("onUnLink",(t,e)=>{this.send(CABLES.PACO_UNLINK,{op1:t.parent.id,op2:e.parent.id,port1:t.getName(),port2:e.getName()})}),t.addEventListener("onUiAttribsChange",(t,e)=>{e&&(delete e.extendTitle,delete e.history,delete e.translate,Object.keys(e).length>0&&this.send(CABLES.PACO_UIATTRIBS,{op:t.id,uiAttribs:e}))}),t.addEventListener("opVariableNameChanged",(t,e)=>{const i={opId:t.id,varName:e};this.send(CABLES.PACO_VARIABLES,i)}),t.addEventListener("opTriggerNameChanged",(t,e)=>{const i={opId:t.id,varName:e};this.send(CABLES.PACO_TRIGGERS,i)}),t.addEventListener("onLink",(t,e)=>{this.send(CABLES.PACO_LINK,{op1:t.parent.id,op2:e.parent.id,port1:t.name,port2:e.name})}),t.addEventListener("portSetVariable",(t,e,i)=>{const s={opId:t.id,portName:e.name,variableName:i};this.send(CABLES.PACO_PORT_SETVARIABLE,s)}),t.addEventListener("portAnimUpdated",(t,e,i)=>{if(t&&e){const s={opId:t.id,portName:e.name,anim:i.getSerialized()};this.send(CABLES.PACO_PORT_ANIM_UPDATED,s)}})};Qt.prototype.send=function(t,e){if(!this.paused&&(t!==CABLES.PACO_VALUECHANGE||"+ create new one"!==e.v))for(let i=0;i0&&"endif"!==i[2]&&"else"!==i[2]&&"elif"!==i[2]){if(a=h.pop(),e(" pop ("+h.length+"): "+JSON.stringify(a)),Preprocessor.ALL.lastIndex=i.index,null===(s=Preprocessor.ALL.exec(this.source)))throw new Error("Illegal #"+i[2]+": "+this.source.substring(i.index,i.index+this.errorSourceAhead)+"...");h.push(o={include:a.include,index:a.index,lastIndex:Preprocessor.ALL.lastIndex}),e(" push ("+h.length+"): "+JSON.stringify(o))}else switch(i[2]){case"ifdef":case"ifndef":case"if":if(Preprocessor.IF.lastIndex=i.index,null===(s=Preprocessor.IF.exec(this.source)))throw new Error("Illegal #"+i[2]+": "+this.source.substring(i.index,i.index+this.errorSourceAhead)+"...");e(" test: "+s[2]),e(" defines "+JSON.stringify(t)),n="ifdef"===s[1]?void 0!==t[s[2]]:"ifndef"===s[1]?void 0===t[s[2]]:Preprocessor.evaluate(t,s[2]),l=!n,e(" value: "+n+", isSkip: "+l),h.push(o={include:n,index:i.index,lastIndex:Preprocessor.IF.lastIndex}),e(" push ("+h.length+"): "+JSON.stringify(o));break;case"endif":case"else":case"elif":if(Preprocessor.ENDIF.lastIndex=i.index,null===(s=Preprocessor.ENDIF.exec(this.source)))throw new Error("Illegal #"+i[2]+': "'+this.source.substring(i.index,i.index+this.errorSourceAhead)+"...");if(0===h.length)throw new Error("Unexpected #"+s[1]+': "'+this.source.substring(i.index,i.index+this.errorSourceAhead)+"...");a=h.pop(),e(" pop ("+h.length+"): "+JSON.stringify(a)),n=this.preserveLineNumbers?this.source.substring(a.index,a.lastIndex).replace(NOT_LINE_ENDING,"")+this.source.substring(a.lastIndex,i.index)+this.source.substring(i.index,Preprocessor.ENDIF.lastIndex).replace(NOT_LINE_ENDING,""):this.source.substring(a.lastIndex,i.index),a.include?(e(" incl: "+Preprocessor.nlToStr(n)+", 0-"+a.index+" + "+n.length+" bytes + "+Preprocessor.ENDIF.lastIndex+"-"+this.source.length),this.source=this.source.substring(0,a.index)+n+this.source.substring(Preprocessor.ENDIF.lastIndex)):this.preserveLineNumbers?(e(" excl(\\n): "+Preprocessor.nlToStr(n)+", 0-"+a.index+" + "+Preprocessor.ENDIF.lastIndex+"-"+this.source.length),n=n.replace(NOT_LINE_ENDING,""),this.source=this.source.substring(0,a.index)+n+this.source.substring(Preprocessor.ENDIF.lastIndex)):(e(" excl: "+Preprocessor.nlToStr(n)+", 0-"+a.index+" + "+Preprocessor.ENDIF.lastIndex+"-"+this.source.length),n="",this.source=this.source.substring(0,a.index)+this.source.substring(Preprocessor.ENDIF.lastIndex)),""===this.source&&e(" result empty"),l=!1,Preprocessor.EXPR.lastIndex=a.index+n.length,e(" continue at "+Preprocessor.EXPR.lastIndex),"else"!==s[1]&&"elif"!==s[1]||(n="else"===s[1]?!a.include:Preprocessor.evaluate(t,s[2]),l=!n,e(" isSkip: "+l),h.push(o={include:n,index:Preprocessor.EXPR.lastIndex,lastIndex:Preprocessor.EXPR.lastIndex}),e(" push ("+h.length+"): "+JSON.stringify(o)));break;case"define":if(Preprocessor.DEFINE.lastIndex=i.index,Preprocessor.VAR.lastIndex=i.index,Preprocessor.FUNCTION.lastIndex=i.index,Preprocessor.BOOLVAR.lastIndex=i.index,null===(s=Preprocessor.DEFINE.exec(this.source)))throw new Error("Illegal #"+i[2]+": "+this.source.substring(i.index,i.index+this.errorSourceAhead)+"...");var c,u,g;if(e(' def: "'+s[1]+'"'),null!==(r=Preprocessor.VAR.exec(this.source)))g="var",c=r[1],u=r[2],e(" match3(var): "+JSON.stringify(r));else if(null!==(r=Preprocessor.FUNCTION.exec(this.source)))g="function",c=r[1],u=r[2],e(" match3(function): "+JSON.stringify(r));else{if(null===(r=Preprocessor.BOOLVAR.exec(this.source)))throw new Error("Illegal #"+i[2]+": "+this.source.substring(i.index,i.index+this.errorSourceAhead)+"...");g="var",c=r[1],u=!0,e(" match3(boolvar): "+JSON.stringify(r))}e(" type: "+g),e(" identifier: "+c),e(" value: "+u),t[c]={type:g,value:u},e(" defines "+JSON.stringify(t));var p="";this.preserveLineNumbers&&(p=this.source.substring(i.index,Preprocessor.DEFINE.lastIndex).replace(NOT_LINE_ENDING,"")),this.source=this.source.substring(0,i.index)+_+p+this.source.substring(Preprocessor.DEFINE.lastIndex),Preprocessor.EXPR.lastIndex=i.index,e(" continue at "+Preprocessor.EXPR.lastIndex)}}return h.length>0&&e("Still on stack ("+h.length+"): "+JSON.stringify(h.pop())),this.source};var _unused_webpack_default_export=Preprocessor},function(t,e,i){"use strict";i.r(e);var s={};i.r(s),i.d(s,"getShortOpName",(function(){return p})),i.d(s,"shuffleArray",(function(){return _})),i.d(s,"shortId",(function(){return m})),i.d(s,"uuid",(function(){return T})),i.d(s,"generateUUID",(function(){return A})),i.d(s,"simpleId",(function(){return x})),i.d(s,"smoothStep",(function(){return v})),i.d(s,"smootherStep",(function(){return y})),i.d(s,"clamp",(function(){return I})),i.d(s,"map",(function(){return S})),i.d(s,"cacheBust",(function(){return R})),i.d(s,"copyArray",(function(){return P})),i.d(s,"basename",(function(){return O})),i.d(s,"jsonp",(function(){return F})),i.d(s,"ajaxSync",(function(){return C})),i.d(s,"ajax",(function(){return w})),i.d(s,"request",(function(){return M})),i.d(s,"keyCodeToName",(function(){return U})),i.d(s,"UTILS",(function(){return g}));var r={};i.r(r),i.d(r,"base64Chars",(function(){return k})),i.d(r,"base64lookup",(function(){return D})),i.d(r,"b64encTypesArray",(function(){return G})),i.d(r,"b64decTypedArray",(function(){return H}));var n={};i.r(n),i.d(n,"easeExpoIn",(function(){return j})),i.d(n,"easeExpoOut",(function(){return K})),i.d(n,"easeExpoInOut",(function(){return Q})),i.d(n,"easeCubicIn",(function(){return q})),i.d(n,"easeCubicOut",(function(){return J})),i.d(n,"easeCubicInOut",(function(){return Z})),i.d(n,"ANIM",(function(){return X})),i.d(n,"Anim",(function(){return $})),i.d(n,"TL",(function(){return tt}));var o={};i.r(o),i.d(o,"PatchConnectionReceiver",(function(){return Kt})),i.d(o,"PatchConnectionSender",(function(){return Qt})),i.d(o,"PatchConnectorBroadcastChannel",(function(){return qt}));class a{constructor(t){this._logs=[],this.initiator=t}stack(t){console.error("["+this.initiator+"] ",t),console.log((new Error).stack),window.gui&&window.gui.emitEvent("coreLogEvent",this.initiator,"error",t)}groupCollapsed(t){console.groupCollapsed("["+this.initiator+"] "+t)}table(t){console.table(t)}groupEnd(){console.groupEnd()}error(t){console.error("["+this.initiator+"]",...arguments),window.gui&&window.gui.emitEvent("coreLogEvent",this.initiator,"error",arguments)}info(t){console.error("["+this.initiator+"]",...arguments),window.gui&&window.gui.emitEvent("coreLogEvent",this.initiator,"info",arguments)}warn(t){console.warn("["+this.initiator+"]",...arguments),window.gui&&window.gui.emitEvent("coreLogEvent",this.initiator,"warn",arguments)}verbose(){(CABLES.UI&&CABLES.UI.logFilter.shouldPrint(this.initiator,...arguments)||!CABLES.logSilent)&&console.log("["+this.initiator+"]",...arguments),window.gui&&window.gui.emitEvent("coreLogEvent",this.initiator,"verbose",arguments)}log(t){(CABLES.UI&&CABLES.UI.logFilter.shouldPrint(this.initiator,...arguments)||!CABLES.logSilent)&&console.log("["+this.initiator+"]",...arguments),window.gui&&window.gui.emitEvent("coreLogEvent",this.initiator,"log",arguments)}userInteraction(t){}}const h={EASINGS:["linear","absolute","smoothstep","smootherstep","Cubic In","Cubic Out","Cubic In Out","Expo In","Expo Out","Expo In Out","Sin In","Sin Out","Sin In Out","Quart In","Quart Out","Quart In Out","Quint In","Quint Out","Quint In Out","Back In","Back Out","Back In Out","Elastic In","Elastic Out","Bounce In","Bounce Out"],EASING_LINEAR:0,EASING_ABSOLUTE:1,EASING_SMOOTHSTEP:2,EASING_SMOOTHERSTEP:3,EASING_CUBICSPLINE:4,EASING_CUBIC_IN:5,EASING_CUBIC_OUT:6,EASING_CUBIC_INOUT:7,EASING_EXPO_IN:8,EASING_EXPO_OUT:9,EASING_EXPO_INOUT:10,EASING_SIN_IN:11,EASING_SIN_OUT:12,EASING_SIN_INOUT:13,EASING_BACK_IN:14,EASING_BACK_OUT:15,EASING_BACK_INOUT:16,EASING_ELASTIC_IN:17,EASING_ELASTIC_OUT:18,EASING_BOUNCE_IN:19,EASING_BOUNCE_OUT:21,EASING_QUART_IN:22,EASING_QUART_OUT:23,EASING_QUART_INOUT:24,EASING_QUINT_IN:25,EASING_QUINT_OUT:26,EASING_QUINT_INOUT:27},l={OP_PORT_TYPE_VALUE:0,OP_PORT_TYPE_FUNCTION:1,OP_PORT_TYPE_OBJECT:2,OP_PORT_TYPE_TEXTURE:2,OP_PORT_TYPE_ARRAY:3,OP_PORT_TYPE_DYNAMIC:4,OP_PORT_TYPE_STRING:5,OP_VERSION_PREFIX:"_v"},c={PORT_DIR_IN:0,PORT_DIR_OUT:1},u={PACO_CLEAR:0,PACO_VALUECHANGE:1,PACO_OP_DELETE:2,PACO_UNLINK:3,PACO_LINK:4,PACO_LOAD:5,PACO_OP_CREATE:6,PACO_OP_ENABLE:7,PACO_OP_DISABLE:8,PACO_UIATTRIBS:9,PACO_VARIABLES:10,PACO_TRIGGERS:11,PACO_PORT_SETVARIABLE:12,PACO_PORT_SETANIMATED:13,PACO_PORT_ANIM_UPDATED:14,PACO_DESERIALIZE:15},g={float32Concat:function(t,e){t instanceof Float32Array||(t=new Float32Array(t)),e instanceof Float32Array||(e=new Float32Array(e));const i=new Float32Array(t.length+e.length);return i.set(t),i.set(e,t.length),i}},p=function(t){let e=t.split(".")[t.split(".").length-1];if(e.indexOf(l.OP_VERSION_PREFIX)>0){const t=e.split(l.OP_VERSION_PREFIX)[1];e=e.substring(0,e.length-(l.OP_VERSION_PREFIX+t).length)}return e},_=function(t){for(let e=t.length-1;e>0;e--){const i=Math.floor(Math.seededRandom()*(e+1)),s=t[e];t[e]=t[i],t[i]=s}return t},d={},f=function(){let t=Math.random().toString(36).substr(2,9);return d.hasOwnProperty(t)&&(t=f()),d[t]=!0,t},m=f,E=function(){let t=(new Date).getTime();return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const i=(t+16*Math.random())%16|0;return t=Math.floor(t/16),("x"==e?i:3&i|8).toString(16)})},T=E,A=E;let b=0;const x=function(){return b++,b},v=function(t){const e=Math.max(0,Math.min(1,(t-0)/1));return t=e*e*(3-2*e)},y=function(t){const e=Math.max(0,Math.min(1,(t-0)/1));return t=e*e*e*(e*(6*e-15)+10)},I=function(t,e,i){return Math.min(Math.max(t,e),i)},S=function(t,e,i,s,r,n){if(t>=i)return r;if(t<=e)return s;let o=!1;const a=Math.min(e,i),h=Math.max(e,i);a!=e&&(o=!0);let l=!1;const c=Math.min(s,r),u=Math.max(s,r);c!=s&&(l=!0);let g=0,p=0;return g=o?(h-t)*(u-c)/(h-a):(t-a)*(u-c)/(h-a),p=l?u-g:g+c,n?1==n?s+(t=Math.max(0,Math.min(1,(p-s)/(r-s))))*t*(3-2*t)*(r-s):2==n?s+(t=Math.max(0,Math.min(1,(p-s)/(r-s))))*t*t*(t*(6*t-15)+10)*(r-s):p:p};Math.randomSeed=1,Math.seededRandom=function(t,e){0===Math.randomSeed&&(Math.randomSeed=999*Math.random()),t=t||1,e=e||0,Math.randomSeed=(9301*Math.randomSeed+49297)%233280;return e+Math.randomSeed/233280*(t-e)},g.arrayWriteToEnd=function(t,e){for(let e=1;e-1?t+="&":t+="?",t+"cb="+CABLES.uuid()},P=function(t,e){if(!t)return null;(e=e||[]).length=t.length;for(let i=0;i0){let t=i[i.length-1].split("?");e=t[0],t=e.split("."),e=t[0]}return e};let N=null;const F=function(t,e){N=N||0,N++;const i=N;CABLES["jsonpFunc"+i]=function(t){e(!1,t)};let s="?";t.indexOf(s)>-1&&(s="&");const r=document.createElement("script");r.setAttribute("src",t+s+"callback=CABLES.jsonpFunc"+i),document.body.appendChild(r)},C=function(t,e,i,s,r){M({url:t,cb:e,method:i,data:s,contenttype:r,sync:!0})},w=function(t,e,i,s,r,n,o={}){M({url:t,cb:e,method:i,data:s,contenttype:r,sync:!1,jsonP:n,headers:o})},M=function(t){let e;t.hasOwnProperty("asynch")||(t.asynch=!0);try{e=new XMLHttpRequest}catch(t){}if(e.onreadystatechange=function(){4==e.readyState&&t.cb&&(200==e.status||0==e.status?t.cb(!1,e.responseText,e):t.cb(!0,e.responseText,e))},e.addEventListener("progress",t=>{}),e.open(t.method?t.method.toUpperCase():"GET",t.url,!t.sync),"object"==typeof t.headers){const i=Object.keys(t.headers);for(let s=0;sthis._cgl.maxTexSize||e>this._cgl.maxTexSize)&&this._log.error("texture size too big! "+t+"x"+e+" / max: "+this._cgl.maxTexSize),t=Math.min(t,this._cgl.maxTexSize),e=Math.min(e,this._cgl.maxTexSize),t=Math.floor(t),e=Math.floor(e),this.width==t&&this.height==e)return;this.width=t,this.height=e,this.deleted=!1,this.shortInfoString=this.getInfoOneLine(),this._cgl.gl.bindTexture(this.texTarget,this.tex),this._cgl.profileData.profileTextureResize++;if(this._cgl.patch.config.canvas.forceTextureNearest&&(this.filter=B.FILTER_NEAREST),1!=this._cgl.glVersion||this.textureType!=B.TYPE_FLOAT||this.filter!=B.FILTER_LINEAR||this._cgl.gl.getExtension("OES_texture_float_linear")||(console.warn("this graphics card does not support floating point texture linear interpolation! using NEAREST"),this.filter=B.FILTER_NEAREST),this.textureType==B.TYPE_FLOAT)if(1==this._cgl.glVersion)if(this._cgl.glUseHalfFloatTex){const i=this._cgl.gl.getExtension("OES_texture_half_float");this._cgl.gl.getExtension("EXT_color_buffer_half_float");if(!i)throw new Error("no half float texture extension");this._cgl.gl.texImage2D(this.texTarget,0,this._cgl.gl.RGBA,t,e,0,this._cgl.gl.RGBA,i.HALF_FLOAT_OES,null)}else this._cgl.gl.getExtension("OES_texture_float"),this._cgl.gl.texImage2D(this.texTarget,0,this._cgl.gl.RGBA,t,e,0,this._cgl.gl.RGBA,this._cgl.gl.FLOAT,null);else if(this._cgl.glUseHalfFloatTex){if(!this._cgl.gl.getExtension("EXT_color_buffer_half_float"))throw new Error("no half float texture extension");console.log("half float",this._cgl.gl.RGBA16F,this._cgl.gl.HALF_FLOAT),console.log("half float",this._cgl.gl.HALF_FLOAT),console.log("half float",this._cgl.gl.RGBA16F),this._cgl.gl.texImage2D(this.texTarget,0,this._cgl.gl.RGBA,t,e,0,this._cgl.gl.RGBA,this._cgl.gl.HALF_FLOAT,null)}else this._cgl.gl.getExtension("EXT_color_buffer_float"),this._cgl.gl.getExtension("EXT_color_buffer_float_linear"),this._cgl.gl.getExtension("OES_texture_float_linear"),this._cgl.gl.texImage2D(this.texTarget,0,this._cgl.gl.RGBA32F,t,e,0,this._cgl.gl.RGBA,this._cgl.gl.FLOAT,null);else if(this.textureType==B.TYPE_DEPTH)if(1==this._cgl.glVersion){const i=this._cgl.gl.DEPTH_COMPONENT;this._cgl.gl.texImage2D(this.texTarget,0,i,t,e,0,this._cgl.gl.DEPTH_COMPONENT,this._cgl.gl.UNSIGNED_SHORT,null)}else{const i=this._cgl.gl.DEPTH_COMPONENT32F;this._cgl.gl.texImage2D(this.texTarget,0,i,t,e,0,this._cgl.gl.DEPTH_COMPONENT,this._cgl.gl.FLOAT,null)}else this._cgl.gl.texImage2D(this.texTarget,0,this._cgl.gl.RGBA,t,e,0,this._cgl.gl.RGBA,this._cgl.gl.UNSIGNED_BYTE,null);this._setFilter(),this.updateMipMap(),this._cgl.gl.bindTexture(this.texTarget,null)},B.prototype.initFromData=function(t,e,i,s,r){if(this.filter=s,this.wrap=r,null==s&&(this.filter=B.FILTER_LINEAR),null==r&&(this.wrap=B.WRAP_CLAMP_TO_EDGE),this.width=e,this.height=i,this._fromData=!0,this.deleted=!1,this.height>this._cgl.maxTexSize||this.width>this._cgl.maxTexSize){const t=CGL.Texture.getTempTexture(this._cgl);return this.width=t.width,this.height=t.height,this.tex=t.tex,void this._log.error("[cgl_texture] texture size to big!!!",this.width,this.height,this._cgl.maxTexSize)}this.flip&&this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_FLIP_Y_WEBGL,this.flip),this._cgl.gl.bindTexture(this.texTarget,this.tex),this.textureType==B.TYPE_FLOAT?this._cgl.gl.texImage2D(this.texTarget,0,this._cgl.gl.RGBA32F,e,i,0,this._cgl.gl.RGBA,this._cgl.gl.FLOAT,t):this._cgl.gl.texImage2D(this.texTarget,0,this._cgl.gl.RGBA,e,i,0,this._cgl.gl.RGBA,this._cgl.gl.UNSIGNED_BYTE,t),this._setFilter(),this.updateMipMap(),this.flip&&this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_FLIP_Y_WEBGL,!1),this._cgl.gl.bindTexture(this.texTarget,null)},B.prototype.updateMipMap=function(){2!=this._cgl.glVersion&&!this.isPowerOfTwo()||this.filter!=B.FILTER_MIPMAP||(this._cgl.gl.generateMipmap(this.texTarget),this._cgl.profileData.profileGenMipMap++)},B.prototype.initTexture=function(t,e){if(this._cgl.printError("before initTexture"),this._cgl.checkFrameStarted("texture inittexture"),this._fromData=!1,this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL,this.unpackAlpha),t.width&&(this.width=t.width),t.height&&(this.height=t.height),e&&(this.filter=e),t.height>this._cgl.maxTexSize||t.width>this._cgl.maxTexSize){const e=CGL.Texture.getTempTexture(this._cgl);return this.width=e.width,this.height=e.height,this.tex=e.tex,void this._log.error("[cgl_texture] texture size to big!!!",t.width,t.height,this._cgl.maxTexSize)}this._cgl.gl.bindTexture(this.texTarget,this.tex),this.deleted=!1,this.flipped=!this.flip,this.flipped&&this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_FLIP_Y_WEBGL,this.flipped),this._cgl.gl.texImage2D(this.texTarget,0,this._cgl.gl.RGBA,this._cgl.gl.RGBA,this._cgl.gl.UNSIGNED_BYTE,t),this._setFilter(),this.updateMipMap(),this._cgl.gl.bindTexture(this.texTarget,null),this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),this.flipped&&this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_FLIP_Y_WEBGL,!1),this.getInfoOneLine(),this._cgl.printError("initTexture")},B.prototype.delete=function(){this.loading||(this.deleted=!0,this.width=0,this.height=0,this._cgl.profileData.profileTextureDelete++,this._cgl.gl.deleteTexture(this.tex),this.image=null,this.tex=null)},B.prototype.isPowerOfTwo=function(){return B.isPowerOfTwo(this.width)&&B.isPowerOfTwo(this.height)},B.prototype.printInfo=function(){console.log(this.getInfo())},B.prototype.getInfoReadable=function(){const t=this.getInfo();let e="";t.name=t.name.substr(0,t.name.indexOf("?rnd="));for(const i in t)e+="* "+i+": **"+t[i]+"**\n";return e},B.prototype.getInfoOneLine=function(){let t=this.width+"x"+this.height;return this.textureType===CGL.Texture.TYPE_FLOAT?t+=" 32bit":t+=" 8bit",this.filter===CGL.Texture.FILTER_NEAREST&&(t+=" nearest"),this.filter===CGL.Texture.FILTER_LINEAR&&(t+=" linear"),this.filter===CGL.Texture.FILTER_MIPMAP&&(t+=" mipmap"),this.wrap===CGL.Texture.WRAP_CLAMP_TO_EDGE&&(t+=" clamp"),this.wrap===CGL.Texture.WRAP_REPEAT&&(t+=" repeat"),this.wrap===CGL.Texture.WRAP_MIRRORED_REPEAT&&(t+=" repeatmir"),this.shortInfoString=t,t},B.prototype.getInfo=function(){return B.getTexInfo(this)},B.prototype._setFilter=function(){if(this._cgl.printError("before _setFilter"),this._fromData||this._cgl.gl.pixelStorei(this._cgl.gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL,this.unpackAlpha),this.shadowMap&&(this._cgl.gl.texParameteri(this._cgl.gl.TEXTURE_2D,this._cgl.gl.TEXTURE_COMPARE_MODE,this._cgl.gl.COMPARE_REF_TO_TEXTURE),this._cgl.gl.texParameteri(this._cgl.gl.TEXTURE_2D,this._cgl.gl.TEXTURE_COMPARE_FUNC,this._cgl.gl.LEQUAL)),this.textureType==B.TYPE_FLOAT&&this.filter==B.FILTER_MIPMAP&&(this.filter=B.FILTER_LINEAR,this._log.stack("texture: HDR and mipmap filtering at the same time is not possible")),1!=this._cgl.glVersion||this.isPowerOfTwo()){if(this.wrap==B.WRAP_CLAMP_TO_EDGE?(this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_WRAP_S,this._cgl.gl.CLAMP_TO_EDGE),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_WRAP_T,this._cgl.gl.CLAMP_TO_EDGE)):this.wrap==B.WRAP_REPEAT?(this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_WRAP_S,this._cgl.gl.REPEAT),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_WRAP_T,this._cgl.gl.REPEAT)):this.wrap==B.WRAP_MIRRORED_REPEAT&&(this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_WRAP_S,this._cgl.gl.MIRRORED_REPEAT),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_WRAP_T,this._cgl.gl.MIRRORED_REPEAT)),this.filter==B.FILTER_NEAREST)this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_MAG_FILTER,this._cgl.gl.NEAREST),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_MIN_FILTER,this._cgl.gl.NEAREST);else if(this.filter==B.FILTER_LINEAR)this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_MIN_FILTER,this._cgl.gl.LINEAR),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_MAG_FILTER,this._cgl.gl.LINEAR);else{if(this.filter!=B.FILTER_MIPMAP)throw this._log.log("unknown texture filter!",this.filter),new Error("unknown texture filter!"+this.filter);this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_MAG_FILTER,this._cgl.gl.LINEAR),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_MIN_FILTER,this._cgl.gl.LINEAR_MIPMAP_LINEAR)}if(this.anisotropic){const t=this._cgl.gl.getExtension("EXT_texture_filter_anisotropic");if(t){const e=this._cgl.gl.getParameter(t.MAX_TEXTURE_MAX_ANISOTROPY_EXT);this._cgl.gl.texParameterf(this._cgl.gl.TEXTURE_2D,t.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(e,this.anisotropic))}}}else this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_MAG_FILTER,this._cgl.gl.NEAREST),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_MIN_FILTER,this._cgl.gl.NEAREST),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_WRAP_S,this._cgl.gl.CLAMP_TO_EDGE),this._cgl.gl.texParameteri(this.texTarget,this._cgl.gl.TEXTURE_WRAP_T,this._cgl.gl.CLAMP_TO_EDGE),this.filter=B.FILTER_NEAREST,this.wrap=B.WRAP_CLAMP_TO_EDGE;this.getInfoOneLine(),this._cgl.printError("_setFilter")},B.load=function(t,e,i,s){if(!e)return i({error:!0});let r=null;t.patch.loading.existByName(e)||(r=t.patch.loading.start("texture",e));const n=new B(t);return n.name=e,t.patch.isEditorMode()&&gui.jobs().start({id:"loadtexture"+r,title:"loading texture "+CABLES.basename(e)}),n.image=new Image,n.image.crossOrigin="anonymous",n.loading=!0,s&&s.hasOwnProperty("filter")&&(n.filter=s.filter),s&&s.hasOwnProperty("flip")&&(n.flip=s.flip),s&&s.hasOwnProperty("wrap")&&(n.wrap=s.wrap),s&&s.hasOwnProperty("anisotropic")&&(n.anisotropic=s.anisotropic),s&&s.hasOwnProperty("unpackAlpha")&&(n.unpackAlpha=s.unpackAlpha),n.image.onabort=n.image.onerror=s=>{console.warn("[cgl.texture.load] error loading texture",e,s),n.loading=!1,r&&t.patch.loading.finished(r);i&&i({error:!0},n),t.patch.isEditorMode()&&gui.jobs().finish("loadtexture"+r)},n.image.onload=function(e){t.addNextFrameOnceCallback(()=>{n.initTexture(n.image),r&&t.patch.loading.finished(r),n.loading=!1,t.patch.isEditorMode()&&gui.jobs().finish("loadtexture"+r),i&&i(null,n)})},n.image.src=e,n},B.getTempTexture=function(t){return t||console.error("[getTempTexture] no cgl!"),t.tempTexture||(t.tempTexture=B.getTemporaryTexture(t,256,B.FILTER_LINEAR,B.REPEAT)),t.tempTexture},B.getEmptyTexture=function(t,e){if(e)return B.getEmptyTextureFloat(t);if(t||console.error("[getEmptyTexture] no cgl!"),t.tempTextureEmpty)return t.tempTextureEmpty;t.tempTextureEmpty=new B(t,{name:"emptyTexture"});const i=new Uint8Array(256).fill(0);for(let t=0;t<256;t+=4)i[t+3]=0;return t.tempTextureEmpty.initFromData(i,8,8,B.FILTER_NEAREST,B.WRAP_REPEAT),t.tempTextureEmpty},B.getEmptyTextureFloat=function(t){if(t||console.error("[getEmptyTextureFloat] no cgl!"),t.tempTextureEmptyFloat)return t.tempTextureEmptyFloat;t.tempTextureEmptyFloat=new B(t,{name:"emptyTexture",isFloatingPointTexture:!0});const e=new Float32Array(256).fill(1);for(let t=0;t<256;t+=4)e[t+3]=0;return t.tempTextureEmptyFloat.initFromData(e,8,8,B.FILTER_NEAREST,B.WRAP_REPEAT),t.tempTextureEmptyFloat},B.getRandomTexture=function(t){if(t||console.error("[getRandomTexture] no cgl!"),t.randomTexture)return t.randomTexture;const e=new Uint8Array(262144);for(let t=0;t<65536;t++)e[4*t+0]=255*Math.random(),e[4*t+1]=255*Math.random(),e[4*t+2]=255*Math.random(),e[4*t+3]=255;return t.randomTexture=new B(t),t.randomTexture.initFromData(e,256,256,B.FILTER_NEAREST,B.WRAP_REPEAT),t.randomTexture},B.getBlackTexture=function(t){if(t||this._log.error("[getBlackTexture] no cgl!"),t.blackTexture)return t.blackTexture;const e=new Uint8Array(256);for(let t=0;t<64;t++)e[4*t+0]=e[4*t+1]=e[4*t+2]=0,e[4*t+3]=255;return t.blackTexture=new B(t),t.blackTexture.initFromData(e,8,8,B.FILTER_NEAREST,B.WRAP_REPEAT),t.blackTexture},B.getEmptyCubemapTexture=function(t){const e=[t.gl.TEXTURE_CUBE_MAP_POSITIVE_X,t.gl.TEXTURE_CUBE_MAP_NEGATIVE_X,t.gl.TEXTURE_CUBE_MAP_POSITIVE_Y,t.gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,t.gl.TEXTURE_CUBE_MAP_POSITIVE_Z,t.gl.TEXTURE_CUBE_MAP_NEGATIVE_Z],i=t.gl.createTexture(),s=t.gl.TEXTURE_CUBE_MAP,r=B.FILTER_NEAREST,n=B.WRAP_CLAMP_TO_EDGE;t.profileData.profileTextureNew++,t.gl.bindTexture(s,i),t.profileData.profileTextureResize++;for(let i=0;i<6;i+=1){const r=new Uint8Array(256);t.gl.texImage2D(e[i],0,t.gl.RGBA,8,8,0,t.gl.RGBA,t.gl.UNSIGNED_BYTE,r),t.gl.texParameteri(s,t.gl.TEXTURE_MAG_FILTER,t.gl.NEAREST),t.gl.texParameteri(s,t.gl.TEXTURE_MIN_FILTER,t.gl.NEAREST),t.gl.texParameteri(s,t.gl.TEXTURE_WRAP_S,t.gl.CLAMP_TO_EDGE),t.gl.texParameteri(s,t.gl.TEXTURE_WRAP_T,t.gl.CLAMP_TO_EDGE)}return t.gl.bindTexture(s,null),{id:CABLES.uuid(),tex:i,cubemap:i,width:8,height:8,filter:r,wrap:n,unpackAlpha:!0,flip:!0,_fromData:!0,name:"emptyCubemapTexture",anisotropic:0}},B.getTempGradientTexture=function(t){if(t||console.error("[getTempGradientTexture] no cgl!"),t.tempTextureGradient)return t.tempTextureGradient;const e=new B(t),i=new Uint8Array(262144);for(let t=0;t<256;t++)for(let e=0;e<256;e++)i[4*(e+256*t)+0]=i[4*(e+256*t)+1]=i[4*(e+256*t)+2]=255-t,i[4*(e+256*t)+3]=255;return e.initFromData(i,256,256,B.FILTER_NEAREST,B.WRAP_REPEAT),t.tempTextureGradient=e,e},B.getTemporaryTexture=function(t,e,i,s){const r=new B(t),n=[];for(let t=0;t>2],r+=k[(3&i[e])<<4|i[e+1]>>4],r+=k[(15&i[e+1])<<2|i[e+2]>>6],r+=k[63&i[e+2]];return s%3==2?r=r.substring(0,r.length-1)+"=":s%3==1&&(r=r.substring(0,r.length-2)+"=="),r},H=function(t){let e,i,s,r,n,o=.75*t.length,a=t.length,h=0;"="===t[t.length-1]&&(o--,"="===t[t.length-2]&&o--);let l=new ArrayBuffer(o),c=new Uint8Array(l);for(e=0;e>4,c[h++]=(15&s)<<4|r>>2,c[h++]=(3&r)<<6|63&n;return l};class z{constructor(t){this._init(),this._first=!0,this._wireMesh=null,t&&this.apply(t)}_init(){this._max=[-Number.MAX_VALUE,-Number.MAX_VALUE,-Number.MAX_VALUE],this._min=[Number.MAX_VALUE,Number.MAX_VALUE,Number.MAX_VALUE],this._center=[0,0,0],this._size=[0,0,0],this._maxAxis=0,this._first=!0}get maxAxis(){return this._maxAxis||1}get size(){return this._size}get center(){return this._center}get x(){return this._center[0]}get y(){return this._center[1]}get z(){return this._center[2]}get minX(){return this._min[0]}get minY(){return this._min[1]}get minZ(){return this._min[2]}get maxX(){return this._max[0]}get maxY(){return this._max[1]}get maxZ(){return this._max[2]}apply(t,e){if(t){if(t instanceof z){const e=t;this.applyPos(e.maxX,e.maxY,e.maxZ),this.applyPos(e.minX,e.minY,e.minZ)}else for(let e=0;e4)&&(console.log("itemsize wrong?",i,t),this._log.stack("itemsize"),i=3),1==i?s="float":2==i?s="vec2":3==i?s="vec3":4==i&&(s="vec4");const r={name:t,data:e,itemSize:i,type:s};this._attributes[t]=r},W.prototype.copyAttribute=function(t,e){const i=this.getAttribute(t);e.setAttribute(t,new Float32Array(i.data),i.itemSize)},W.prototype.setVertices=function(t){t instanceof Float32Array?this._vertices=t:this._vertices=new Float32Array(t)},W.prototype.setTexCoords=function(t){t instanceof Float32Array?this.texCoords=t:this.texCoords=new Float32Array(t)},W.prototype.calcNormals=function(t){t||this.unIndex(),this.calculateNormals({})},W.prototype.flipNormals=function(t,e,i){let s=vec3.create();null==t&&(t=1),null==e&&(e=1),null==i&&(i=1);for(let r=0;r0&&o.push(this.tangents[3*this.verticesIndices[l+0]+0],this.tangents[3*this.verticesIndices[l+0]+1],this.tangents[3*this.verticesIndices[l+0]+2]),this.biTangents.length>0&&a.push(this.biTangents[3*this.verticesIndices[l+0]+0],this.biTangents[3*this.verticesIndices[l+0]+1],this.biTangents[3*this.verticesIndices[l+0]+2]),this.texCoords?r.push(this.texCoords[2*this.verticesIndices[l+0]+0],this.texCoords[2*this.verticesIndices[l+0]+1]):r.push(0,0),s.push(h),h++,i.push(this.vertices[3*this.verticesIndices[l+1]+0],this.vertices[3*this.verticesIndices[l+1]+1],this.vertices[3*this.verticesIndices[l+1]+2]),n.push(this.vertexNormals[3*this.verticesIndices[l+1]+0],this.vertexNormals[3*this.verticesIndices[l+1]+1],this.vertexNormals[3*this.verticesIndices[l+1]+2]),this.tangents.length>0&&o.push(this.tangents[3*this.verticesIndices[l+1]+0],this.tangents[3*this.verticesIndices[l+1]+1],this.tangents[3*this.verticesIndices[l+1]+2]),this.biTangents.length>0&&a.push(this.biTangents[3*this.verticesIndices[l+1]+0],this.biTangents[3*this.verticesIndices[l+1]+1],this.biTangents[3*this.verticesIndices[l+1]+2]),this.texCoords?r.push(this.texCoords[2*this.verticesIndices[l+1]+0],this.texCoords[2*this.verticesIndices[l+1]+1]):r.push(0,0),s.push(h),h++,i.push(this.vertices[3*this.verticesIndices[l+2]+0],this.vertices[3*this.verticesIndices[l+2]+1],this.vertices[3*this.verticesIndices[l+2]+2]),n.push(this.vertexNormals[3*this.verticesIndices[l+2]+0],this.vertexNormals[3*this.verticesIndices[l+2]+1],this.vertexNormals[3*this.verticesIndices[l+2]+2]),this.tangents.length>0&&o.push(this.tangents[3*this.verticesIndices[l+2]+0],this.tangents[3*this.verticesIndices[l+2]+1],this.tangents[3*this.verticesIndices[l+2]+2]),this.biTangents.length>0&&a.push(this.biTangents[3*this.verticesIndices[l+2]+0],this.biTangents[3*this.verticesIndices[l+2]+1],this.biTangents[3*this.verticesIndices[l+2]+2]),this.texCoords?r.push(this.texCoords[2*this.verticesIndices[l+2]+0],this.texCoords[2*this.verticesIndices[l+2]+1]):r.push(0,0),s.push(h),h++;this.vertices=i,this.texCoords=r,this.vertexNormals=n,o.length>0&&(this.tangents=o),a.length>0&&(this.biTangents=a),this.verticesIndices.length=0,t&&(this.verticesIndices=s),e||this.calculateNormals()},W.prototype.calcBarycentric=function(){let t=[];t.length=this.vertices.length;for(let e=0;e1&&this.keys.splice(0,i)},$.prototype.clear=function(t){let e=0;t&&(e=this.getValue(t)),this.keys.length=0,t&&this.setValue(t,e),null!==this.onChange&&this.onChange(),this.emitEvent("onChange",this)},$.prototype.sortKeys=function(){this.keys.sort((t,e)=>parseFloat(t.time)-parseFloat(e.time)),this._needsSort=!1},$.prototype.getLength=function(){return 0===this.keys.length?0:this.keys[this.keys.length-1].time},$.prototype.getKeyIndex=function(t){let e=0;for(let i=0;i=this.keys[i].time&&(e=i),this.keys[i].time>t)return e;return e},$.prototype.setValue=function(t,e,i){let s=null;for(const r in this.keys)if(this.keys[r].time==t){s=this.keys[r],this.keys[r].setValue(e),this.keys[r].cb=i;break}return s||(s=new X.Key({time:t,value:e,e:this.defaultEasing,cb:i}),this.keys.push(s)),this.onChange&&this.onChange(),this.emitEvent("onChange",this),this._needsSort=!0,s},$.prototype.setKeyEasing=function(t,e){this.keys[t]&&(this.keys[t].setEasing(e),this.emitEvent("onChange",this))},$.prototype.getSerialized=function(){const t={keys:[]};t.loop=this.loop;for(const e in this.keys)t.keys.push(this.keys[e].getSerialized());return t},$.prototype.getKey=function(t){const e=this.getKeyIndex(t);return this.keys[e]},$.prototype.getNextKey=function(t){let e=this.getKeyIndex(t)+1;return e>=this.keys.length&&(e=this.keys.length-1),this.keys[e]},$.prototype.isFinished=function(t){return this.keys.length<=0||t>this.keys[this.keys.length-1].time},$.prototype.isStarted=function(t){return!(this.keys.length<=0)&&t>=this.keys[0].time},$.prototype.getValue=function(t){if(0===this.keys.length)return 0;if(this._needsSort&&this.sortKeys(),tthis.keys[e].time){t/this.keys[e].time>this._timesLooped&&(this._timesLooped++,this.onLooped&&this.onLooped()),t=(t-this.keys[0].time)%(this.keys[e].time-this.keys[0].time),t+=this.keys[0].time}const i=this.getKeyIndex(t);if(i>=e)return this.keys[e].cb&&!this.keys[e].cbTriggered&&this.keys[e].trigger(),this.keys[e].value;const s=parseInt(i,10)+1,r=this.keys[i],n=this.keys[s];if(r.cb&&!r.cbTriggered&&r.trigger(),!n)return-1;const o=(t-r.time)/(n.time-r.time);return r.ease||this.log._warn("has no ease",r,n),r.ease(o,n)},$.prototype.addKey=function(t){void 0===t.time?this.log.warn("key time undefined, ignoring!"):(this.keys.push(t),null!==this.onChange&&this.onChange(),this.emitEvent("onChange",this))},$.prototype.easingFromString=function(t){return"linear"==t?h.EASING_LINEAR:"absolute"==t?h.EASING_ABSOLUTE:"smoothstep"==t?h.EASING_SMOOTHSTEP:"smootherstep"==t?h.EASING_SMOOTHERSTEP:"Cubic In"==t?h.EASING_CUBIC_IN:"Cubic Out"==t?h.EASING_CUBIC_OUT:"Cubic In Out"==t?h.EASING_CUBIC_INOUT:"Expo In"==t?h.EASING_EXPO_IN:"Expo Out"==t?h.EASING_EXPO_OUT:"Expo In Out"==t?h.EASING_EXPO_INOUT:"Sin In"==t?h.EASING_SIN_IN:"Sin Out"==t?h.EASING_SIN_OUT:"Sin In Out"==t?h.EASING_SIN_INOUT:"Back In"==t?h.EASING_BACK_IN:"Back Out"==t?h.EASING_BACK_OUT:"Back In Out"==t?h.EASING_BACK_INOUT:"Elastic In"==t?h.EASING_ELASTIC_IN:"Elastic Out"==t?h.EASING_ELASTIC_OUT:"Bounce In"==t?h.EASING_BOUNCE_IN:"Bounce Out"==t?h.EASING_BOUNCE_OUT:"Quart Out"==t?h.EASING_QUART_OUT:"Quart In"==t?h.EASING_QUART_IN:"Quart In Out"==t?h.EASING_QUART_INOUT:"Quint Out"==t?h.EASING_QUINT_OUT:"Quint In"==t?h.EASING_QUINT_IN:"Quint In Out"==t?h.EASING_QUINT_INOUT:void 0},$.prototype.createPort=function(t,e,i){const s=t.inDropDown(e,h.EASINGS);return s.set("linear"),s.defaultValue="linear",s.onChange=function(){this.defaultEasing=this.easingFromString(s.get()),i&&i()}.bind(this),s},$.slerpQuaternion=function(t,e,i,s,r,n){$.slerpQuaternion.q1||($.slerpQuaternion.q1=quat.create(),$.slerpQuaternion.q2=quat.create());const o=i.getKeyIndex(t);let a=o+1;if(a>=i.keys.length&&(a=i.keys.length-1),o==a)quat.set(e,i.keys[o].value,s.keys[o].value,r.keys[o].value,n.keys[o].value);else{const h=i.keys[o].time,l=(t-h)/(i.keys[a].time-h);quat.set($.slerpQuaternion.q1,i.keys[o].value,s.keys[o].value,r.keys[o].value,n.keys[o].value),quat.set($.slerpQuaternion.q2,i.keys[a].value,s.keys[a].value,r.keys[a].value,n.keys[a].value),quat.slerp(e,$.slerpQuaternion.q1,$.slerpQuaternion.q2,l)}return e};const tt=X;tt.Anim=$;const et=function(t,e,i,s){Y.apply(this),this.data={},this._log=new a("core_port"),this.direction=c.PORT_DIR_IN,this.id=CABLES.simpleId(),this.parent=t,this.links=[],this.value=0,this.name=e,this.type=i||l.OP_PORT_TYPE_VALUE,this.uiAttribs=s||{},this.anim=null,this._oldAnimVal=-5711,this.defaultValue=null,this._uiActiveState=!0,this.ignoreValueSerialize=!1,this.onLinkChanged=null,this.crashed=!1,this._valueBeforeLink=null,this._lastAnimFrame=-1,this._animated=!1,this.onValueChanged=null,this.onTriggered=null,this.onUiActiveStateChange=null,this.changeAlways=!1,this._warnedDeprecated=!1,this._useVariableName=null,this.activityCounter=0,this._tempLastUiValue=null,Object.defineProperty(this,"title",{get(){return this.uiAttribs.title||this.name}}),Object.defineProperty(this,"val",{get(){return this._log.warn("val getter deprecated!",this),this._log.stack("val getter deprecated"),this._warnedDeprecated=!0,this.get()},set(t){this._log.warn("val setter deprecated!",this),this._log.stack("val setter deprecated"),this.setValue(t),this._warnedDeprecated=!0}})};et.prototype.copyLinkedUiAttrib=function(t,e){if(!CABLES.UI)return;if(!this.isLinked())return;const i={};i[t]=this.links[0].getOtherPort(this).getUiAttrib(t),e.setUiAttribs(i)},et.prototype.getValueForDisplay=function(){let t=String(this.value);return this.uiAttribs&&"boolnum"==this.uiAttribs.display&&(t+=" - ",this.value?t+="true":t+="false"),t=t.replace(/(<([^>]+)>)/gi,""),t.length>100&&(t=t.substring(0,100)),t},et.prototype.onAnimToggle=function(){},et.prototype._onAnimToggle=function(){this.onAnimToggle()},et.prototype.remove=function(){this.removeLinks(),this.parent.removePort(this)},et.prototype.setUiAttribs=function(t){let e=!1;this.uiAttribs||(this.uiAttribs={});for(const i in t)this.uiAttribs[i]!=t[i]&&(e=!0),this.uiAttribs[i]=t[i],"group"==i&&this.indexPort&&this.indexPort.setUiAttribs({group:t[i]});e&&this.emitEvent("onUiAttrChange",t,this)},et.prototype.getUiAttribs=function(){return this.uiAttribs},et.prototype.getUiAttrib=function(t){return this.uiAttribs&&this.uiAttribs.hasOwnProperty(t)?this.uiAttribs[t]:null},et.prototype.get=function(){return this._animated&&this._lastAnimFrame!=this.parent.patch.getFrameNum()&&(this._lastAnimFrame=this.parent.patch.getFrameNum(),this.value=this.anim.getValue(this.parent.patch.timer.getTime()),this._oldAnimVal=this.value,this.forceChange()),this.value},et.prototype.set=et.prototype.setValue=function(t){if(void 0!==t&&this.parent.enabled&&!this.crashed&&(t!==this.value||this.changeAlways||this.type==l.OP_PORT_TYPE_TEXTURE||this.type==l.OP_PORT_TYPE_ARRAY)){if(this._animated)this.anim.setValue(this.parent.patch.timer.getTime(),t);else{try{this.value=t,this.forceChange()}catch(t){this.crashed=!0,this.setValue=function(t){},this.onTriggered=function(){},this._log.error("onvaluechanged exception cought",t),this._log.error(t.stack),this._log.warn("exception in: "+this.parent.name),this.parent.patch.isEditorMode()&&gui.showOpCrash(this.parent),this.parent.patch.emitEvent("exception",t,this.parent),this.parent.onError&&this.parent.onError(t)}this.parent&&this.parent.patch&&this.parent.patch.isEditorMode()&&this.type==l.OP_PORT_TYPE_TEXTURE&&gui.texturePreview().updateTexturePort(this)}if(this.direction==c.PORT_DIR_OUT)for(let t=0;t{this.parent.patch.emitEvent("portAnimUpdated",this.parent,this,this.anim)}),t.anim.loop&&(this.anim.loop=t.anim.loop);for(const e in t.anim.keys)this.anim.keys.push(new X.Key(t.anim.keys[e]))}},et.prototype.getSerialized=function(){const t={};if(t.name=this.getName(),this.ignoreValueSerialize||0!==this.links.length||this.type==l.OP_PORT_TYPE_OBJECT&&this.value&&this.value.tex||(t.value=this.value),this._useVariableName&&(t.useVariable=this._useVariableName),this._animated&&(t.animated=!0),this.anim&&(t.anim=this.anim.getSerialized()),"file"==this.uiAttribs.display&&(t.display=this.uiAttribs.display),this.direction==c.PORT_DIR_OUT&&this.links.length>0){t.links=[];for(const e in this.links)!this.links[e].ignoreInSerialize&&this.links[e].portIn&&this.links[e].portOut&&t.links.push(this.links[e].getSerialized())}return t},et.prototype.shouldLink=function(){return!0},et.prototype.removeLinks=function(){let t=0;for(;this.links.length>0;){if(t++,t>5e3){this._log.warn("could not delete links... / infinite loop"),this.links.length=0;break}this.links[0].remove()}},et.prototype.removeLink=function(t){for(const e in this.links)this.links[e]==t&&this.links.splice(e,1);this.direction==c.PORT_DIR_IN&&(this.type==l.OP_PORT_TYPE_VALUE?this.setValue(this._valueBeforeLink||0):this.setValue(this._valueBeforeLink||null)),CABLES.UI&&this.parent.checkLinkTimeWarnings&&this.parent.checkLinkTimeWarnings(),this.onLinkChanged&&this.onLinkChanged(),this.emitEvent("onLinkChanged"),this.parent.emitEvent("onLinkChanged")},et.prototype.getName=function(){return this.name},et.prototype.addLink=function(t){this._valueBeforeLink=this.value,this.links.push(t),CABLES.UI&&this.parent.checkLinkTimeWarnings&&this.parent.checkLinkTimeWarnings(),this.onLinkChanged&&this.onLinkChanged(),this.emitEvent("onLinkChanged"),this.parent.emitEvent("onLinkChanged")},et.prototype.getLinkTo=function(t){for(const e in this.links)if(this.links[e].portIn==t||this.links[e].portOut==t)return this.links[e]},et.prototype.removeLinkTo=function(t){for(const e in this.links)if(this.links[e].portIn==t||this.links[e].portOut==t)return this.links[e].remove(),CABLES.UI&&this.parent.checkLinkTimeWarnings&&this.parent.checkLinkTimeWarnings(),this.onLinkChanged&&this.onLinkChanged(),void this.emitEvent("onLinkChanged")},et.prototype.isLinkedTo=function(t){for(const e in this.links)if(this.links[e].portIn==t||this.links[e].portOut==t)return!0;return!1},et.prototype._activity=function(){this.activityCounter++},et.prototype.trigger=function(){if(this._activity(),0===this.links.length)return;if(!this.parent.enabled)return;let t=null;try{for(let e=0;e{this.set(null),this.set(this._variableIn.getValue())}):this._varChangeListenerId=this._variableIn.on("change",this.set.bind(this)),this.set(this._variableIn.getValue())):this._log.warn("PORT VAR NOT FOUND!!!",t),this._useVariableName=t,e.useVariable=!0,e.variableName=this._useVariableName):(e.variableName=this._useVariableName=null,e.useVariable=!1),this.setUiAttribs(e),this.parent.patch.emitEvent("portSetVariable",this.parent,this,t)},et.prototype._handleNoTriggerOpAnimUpdates=function(t){let e=!1;for(let t=0;t{this.updateAnim()}):this.parent.patch.removeEventListener(this._notriggerAnimUpdate))},et.prototype.setAnimated=function(t){this._animated!=t&&(this._animated=t,this._animated&&!this.anim&&(this.anim=new $,this.anim.addEventListener("onChange",()=>{this.parent.patch.emitEvent("portAnimUpdated",this.parent,this,this.anim)})),this._onAnimToggle()),this._handleNoTriggerOpAnimUpdates(t),this.setUiAttribs({isAnimated:this._animated})},et.prototype.toggleAnim=function(){this._animated=!this._animated,this._animated&&!this.anim&&(this.anim=new $,this.anim.addEventListener("onChange",()=>{this.parent.patch.emitEvent("portAnimUpdated",this.parent,this,this.anim)})),this.setAnimated(this._animated),this._onAnimToggle(),this.setUiAttribs({isAnimated:this._animated})},et.prototype.getType=function(){return this.type},et.prototype.isLinked=function(){return this.links.length>0||this._animated||null!=this._useVariableName},et.prototype.isBoundToVar=function(){return null!=this._useVariableName},et.prototype.isAnimated=function(){return this._animated},et.prototype.isHidden=function(){return this.uiAttribs.hidePort},et.prototype._onTriggered=function(t){this._activity(),this.parent.updateAnims(),this.parent.enabled&&this.onTriggered&&this.onTriggered(t)},et.prototype._onSetProfiling=function(t){this.parent.patch.profiler.add("port",this),this.setValue(t),this.parent.patch.profiler.add("port",null)},et.prototype._onTriggeredProfiling=function(){this.parent.enabled&&this.onTriggered&&(this.parent.patch.profiler.add("port",this),this.onTriggered(),this.parent.patch.profiler.add("port",null))},et.prototype.onValueChange=function(t){this.onChange=t},et.prototype.getUiActiveState=function(){return this._uiActiveState},et.prototype.setUiActiveState=function(t){this._uiActiveState=t,this.onUiActiveStateChange&&this.onUiActiveStateChange()},et.prototype.hidePort=function(){this._log.warn("op.hideport() is deprecated, do not use it!")},et.portTypeNumberToString=function(t){return t==l.OP_PORT_TYPE_VALUE?"value":t==l.OP_PORT_TYPE_FUNCTION?"function":t==l.OP_PORT_TYPE_OBJECT?"object":t==l.OP_PORT_TYPE_ARRAY?"array":t==l.OP_PORT_TYPE_STRING?"string":t==l.OP_PORT_TYPE_DYNAMIC?"dynamic":"unknown"};class it extends et{constructor(t,e,i,s,r){super(t,e,i,s),this.indexPort=r,this.indexPort.set=t=>{const e=s.values;if(!e)return;let i=Math.floor(t);i=Math.min(i,e.length-1),i=Math.max(i,0),this.indexPort.setValue(i),this.set(e[i]),this.parent.patch.isEditorMode()&&window.gui&&gui.patchView.isCurrentOp(this.parent)&&gui.opParams.show(this.parent)}}setUiAttribs(t){const e=t.hidePort;t.hidePort=!0,super.setUiAttribs(t),void 0!==e&&this.indexPort.setUiAttribs({hidePort:e})}}class st extends it{setUiAttribs(t){if(this.indexPort.isLinked())for(const e in t)"greyout"!=e||t[e]||(t[e]="true");super.setUiAttribs(t)}}var rt=class{constructor(t,e,i,s,r,n,o,h,l,c){if(this._log=new a("cg_uniform"),this._type=e,this._name=i,this._shader=t,this._value=1e-5,this._oldValue=null,this._port=null,this._structName=l,this._structUniformName=h,this._propertyName=c,this._shader._addUniform(this),this.needsUpdate=!0,this.shaderType=null,this.comment=null,"f"==e)this.set=this.setValue=this.setValueF.bind(this),this.updateValue=this.updateValueF.bind(this);else if("f[]"==e)this.set=this.setValue=this.setValueArrayF.bind(this),this.updateValue=this.updateValueArrayF.bind(this);else if("2f[]"==e)this.set=this.setValue=this.setValueArray2F.bind(this),this.updateValue=this.updateValueArray2F.bind(this);else if("3f[]"==e)this.set=this.setValue=this.setValueArray3F.bind(this),this.updateValue=this.updateValueArray3F.bind(this);else if("4f[]"==e)this.set=this.setValue=this.setValueArray4F.bind(this),this.updateValue=this.updateValueArray4F.bind(this);else if("i"==e)this.set=this.setValue=this.setValueI.bind(this),this.updateValue=this.updateValueI.bind(this);else if("2i"==e)this.set=this.setValue=this.setValue2I.bind(this),this.updateValue=this.updateValue2I.bind(this);else if("3i"==e)this.set=this.setValue=this.setValue3I.bind(this),this.updateValue=this.updateValue3I.bind(this);else if("4i"==e)this.set=this.setValue=this.setValue4I.bind(this),this.updateValue=this.updateValue4I.bind(this);else if("b"==e)this.set=this.setValue=this.setValueBool.bind(this),this.updateValue=this.updateValueBool.bind(this);else if("4f"==e)this.set=this.setValue=this.setValue4F.bind(this),this.updateValue=this.updateValue4F.bind(this);else if("3f"==e)this.set=this.setValue=this.setValue3F.bind(this),this.updateValue=this.updateValue3F.bind(this);else if("2f"==e)this.set=this.setValue=this.setValue2F.bind(this),this.updateValue=this.updateValue2F.bind(this);else if("t"==e)this.set=this.setValue=this.setValueT.bind(this),this.updateValue=this.updateValueT.bind(this);else if("tc"==e)this.set=this.setValue=this.setValueT.bind(this),this.updateValue=this.updateValueT.bind(this);else if("t[]"==e)this.set=this.setValue=this.setValueArrayT.bind(this),this.updateValue=this.updateValueArrayT.bind(this);else{if("m4"!=e&&"m4[]"!=e)throw new Error("Unknown uniform type");this.set=this.setValue=this.setValueM4.bind(this),this.updateValue=this.updateValueM4.bind(this)}"object"==typeof s&&s instanceof et?(this._port=s,this._value=this._port.get(),r&&n&&o?(r instanceof et&&n instanceof et&&o instanceof et||this._log.error("[cgl_uniform] mixed port/value parameter for vec4 ",this._name),this._value=[0,0,0,0],this._port2=r,this._port3=n,this._port4=o,this._port.on("change",this.updateFromPort4f.bind(this)),this._port2.on("change",this.updateFromPort4f.bind(this)),this._port3.on("change",this.updateFromPort4f.bind(this)),this._port4.on("change",this.updateFromPort4f.bind(this)),this.updateFromPort4f()):r&&n?(r instanceof et&&n instanceof et||this._log.error("[cgl_uniform] mixed port/value parameter for vec4 ",this._name),this._value=[0,0,0],this._port2=r,this._port3=n,this._port.on("change",this.updateFromPort3f.bind(this)),this._port2.on("change",this.updateFromPort3f.bind(this)),this._port3.on("change",this.updateFromPort3f.bind(this)),this.updateFromPort3f()):r?(r instanceof et||this._log.error("[cgl_uniform] mixed port/value parameter for vec4 ",this._name),this._value=[0,0],this._port2=r,this._port.on("change",this.updateFromPort2f.bind(this)),this._port2.on("change",this.updateFromPort2f.bind(this)),this.updateFromPort2f()):this._port.on("change",this.updateFromPort.bind(this))):this._value=s,this.setValue(this._value),this.needsUpdate=!0}getType(){return this._type}getName(){return this._name}getValue(){return this._value}getShaderType(){return this.shaderType}isStructMember(){return!!this._structName}updateFromPort4f(){this._value[0]=this._port.get(),this._value[1]=this._port2.get(),this._value[2]=this._port3.get(),this._value[3]=this._port4.get(),this.setValue(this._value)}updateFromPort3f(){this._value[0]=this._port.get(),this._value[1]=this._port2.get(),this._value[2]=this._port3.get(),this.setValue(this._value)}updateFromPort2f(){this._value[0]=this._port.get(),this._value[1]=this._port2.get(),this.setValue(this._value)}updateFromPort(){this.setValue(this._port.get())}};class nt extends rt{constructor(t,e,i,s,r,n,o,a,h,l){super(t,e,i,s,r,n,o,a,h,l),this._loc=-1,this._cgl=t._cgl}copy(t){const e=new nt(t,this._type,this._name,this._value,this._port2,this._port3,this._port4,this._structUniformName,this._structName,this._propertyName);return e.shaderType=this.shaderType,e}getGlslTypeString(){return nt.glslTypeString(this._type)}_isValidLoc(){return-1!=this._loc}resetLoc(){this._loc=-1,this.needsUpdate=!0}bindTextures(){}getLoc(){return this._loc}updateFromPort4f(){this._value[0]=this._port.get(),this._value[1]=this._port2.get(),this._value[2]=this._port3.get(),this._value[3]=this._port4.get(),this.setValue(this._value)}updateFromPort3f(){this._value[0]=this._port.get(),this._value[1]=this._port2.get(),this._value[2]=this._port3.get(),this.setValue(this._value)}updateFromPort2f(){this._value[0]=this._port.get(),this._value[1]=this._port2.get(),this.setValue(this._value)}updateFromPort(){this.setValue(this._port.get())}updateValueF(){this._isValidLoc()?this.needsUpdate=!1:this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._shader.getCgl().gl.uniform1f(this._loc,this._value),this._cgl.profileData.profileUniformCount++}setValueF(t){t!=this._value&&(this.needsUpdate=!0,this._value=t)}updateValueI(){this._isValidLoc()?this.needsUpdate=!1:this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._shader.getCgl().gl.uniform1i(this._loc,this._value),this._cgl.profileData.profileUniformCount++}updateValue2I(){this._value&&(this._isValidLoc()||(this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._cgl.profileData.profileShaderGetUniform++,this._cgl.profileData.profileShaderGetUniformName=this._name),this._shader.getCgl().gl.uniform2i(this._loc,this._value[0],this._value[1]),this.needsUpdate=!1,this._cgl.profileData.profileUniformCount++)}updateValue3I(){this._value&&(this._isValidLoc()||(this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._cgl.profileData.profileShaderGetUniform++,this._cgl.profileData.profileShaderGetUniformName=this._name),this._shader.getCgl().gl.uniform3i(this._loc,this._value[0],this._value[1],this._value[2]),this.needsUpdate=!1,this._cgl.profileData.profileUniformCount++)}updateValue4I(){this._isValidLoc()||(this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._cgl.profileData.profileShaderGetUniform++,this._cgl.profileData.profileShaderGetUniformName=this._name),this._shader.getCgl().gl.uniform4i(this._loc,this._value[0],this._value[1],this._value[2],this._value[3]),this._cgl.profileData.profileUniformCount++}setValueI(t){t!=this._value&&(this.needsUpdate=!0,this._value=t)}setValue2I(t){t&&(this._oldValue?t[0]==this._oldValue[0]&&t[1]==this._oldValue[1]||(this._oldValue[0]=t[0],this._oldValue[1]=t[1],this.needsUpdate=!0):(this._oldValue=[t[0]-1,1],this.needsUpdate=!0),this._value=t)}setValue3I(t){t&&(this._oldValue?t[0]==this._oldValue[0]&&t[1]==this._oldValue[1]&&t[2]==this._oldValue[2]||(this._oldValue[0]=t[0],this._oldValue[1]=t[1],this._oldValue[2]=t[2],this.needsUpdate=!0):(this._oldValue=[t[0]-1,1,2],this.needsUpdate=!0),this._value=t)}setValue4I(t){this.needsUpdate=!0,this._value=t||vec4.create()}updateValueBool(){this._isValidLoc()?this.needsUpdate=!1:this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._shader.getCgl().gl.uniform1i(this._loc,this._value?1:0),this._cgl.profileData.profileUniformCount++}setValueBool(t){t!=this._value&&(this.needsUpdate=!0,this._value=t)}setValueArray4F(t){this.needsUpdate=!0,this._value=t}updateValueArray4F(){this._isValidLoc()?this.needsUpdate=!1:this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._value&&(this._shader.getCgl().gl.uniform4fv(this._loc,this._value),this._cgl.profileData.profileUniformCount++)}setValueArray3F(t){this.needsUpdate=!0,this._value=t}updateValueArray3F(){this._isValidLoc()?this.needsUpdate=!1:this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._value&&(this._shader.getCgl().gl.uniform3fv(this._loc,this._value),this._cgl.profileData.profileUniformCount++)}setValueArray2F(t){this.needsUpdate=!0,this._value=t}updateValueArray2F(){this._isValidLoc()?this.needsUpdate=!1:this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._value&&(this._shader.getCgl().gl.uniform2fv(this._loc,this._value),this._cgl.profileData.profileUniformCount++)}setValueArrayF(t){this.needsUpdate=!0,this._value=t}updateValueArrayF(){this._isValidLoc()?this.needsUpdate=!1:this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._value&&(this._shader.getCgl().gl.uniform1fv(this._loc,this._value),this._cgl.profileData.profileUniformCount++)}setValueArrayT(t){this.needsUpdate=!0,this._value=t}updateValue3F(){this._value&&(this._isValidLoc()||(this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._cgl.profileData.profileShaderGetUniform++,this._cgl.profileData.profileShaderGetUniformName=this._name),this._shader.getCgl().gl.uniform3f(this._loc,this._value[0],this._value[1],this._value[2]),this.needsUpdate=!1,this._cgl.profileData.profileUniformCount++)}setValue3F(t){t&&(this._oldValue?t[0]==this._oldValue[0]&&t[1]==this._oldValue[1]&&t[2]==this._oldValue[2]||(this._oldValue[0]=t[0],this._oldValue[1]=t[1],this._oldValue[2]=t[2],this.needsUpdate=!0):(this._oldValue=[t[0]-1,1,2],this.needsUpdate=!0),this._value=t)}updateValue2F(){this._value&&(this._isValidLoc()||(this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._cgl.profileData.profileShaderGetUniform++,this._cgl.profileData.profileShaderGetUniformName=this._name),this._shader.getCgl().gl.uniform2f(this._loc,this._value[0],this._value[1]),this.needsUpdate=!1,this._cgl.profileData.profileUniformCount++)}setValue2F(t){t&&(this._oldValue?t[0]==this._oldValue[0]&&t[1]==this._oldValue[1]||(this._oldValue[0]=t[0],this._oldValue[1]=t[1],this.needsUpdate=!0):(this._oldValue=[t[0]-1,1],this.needsUpdate=!0),this._value=t)}updateValue4F(){this._isValidLoc()||(this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._cgl.profileData.profileShaderGetUniform++,this._cgl.profileData.profileShaderGetUniformName=this._name),this._value||(this._log.warn("no value for uniform",this._name,this),this._value=[0,0,0,0]),this.needsUpdate=!1,this._shader.getCgl().gl.uniform4f(this._loc,this._value[0],this._value[1],this._value[2],this._value[3]),this._cgl.profileData.profileUniformCount++}setValue4F(t){"number"==typeof this.value&&(this.value=vec4.create()),t&&(this._oldValue?t[0]==this._oldValue[0]&&t[1]==this._oldValue[1]&&t[2]==this._oldValue[2]&&t[3]==this._oldValue[3]||(this._oldValue[0]=t[0],this._oldValue[1]=t[1],this._oldValue[2]=t[2],this.needsUpdate=!0):(this._oldValue=[t[0]-1,1,2,3],this.needsUpdate=!0),this._value=t)}updateValueM4(){if(this._isValidLoc()||(this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._cgl.profileData.profileShaderGetUniform++,this._cgl.profileData.profileShaderGetUniformName=this._name),!this._value||this._value.length%16!=0)return console.log("this.name",this._name,this._value);this._shader.getCgl().gl.uniformMatrix4fv(this._loc,!1,this._value),this._cgl.profileData.profileUniformCount++}setValueM4(t){this.needsUpdate=!0,this._value=t||mat4.create()}updateValueArrayT(){this._isValidLoc()?this.needsUpdate=!1:this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._value&&(this._shader.getCgl().gl.uniform1iv(this._loc,this._value),this._cgl.profileData.profileUniformCount++)}updateValueT(){this._isValidLoc()||(this._loc=this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(),this._name),this._cgl.profileData.profileShaderGetUniform++,this._cgl.profileData.profileShaderGetUniformName=this._name),this._cgl.profileData.profileUniformCount++,this._shader.getCgl().gl.uniform1i(this._loc,this._value),this.needsUpdate=!1}setValueT(t){this.needsUpdate=!0,this._value=t}}nt.glslTypeString=t=>"f"==t?"float":"b"==t?"bool":"i"==t?"int":"2i"==t?"ivec2":"2f"==t?"vec2":"3f"==t?"vec3":"4f"==t?"vec4":"m4"==t?"mat4":"t"==t?"sampler2D":"tc"==t?"samplerCube":"3f[]"==t||"m4[]"==t||"f[]"==t?null:void(void 0)._log.warn("[CGL UNIFORM] unknown glsl type string ",t);const ot=180/Math.PI,at={MATH:{DEG2RAD:Math.PI/180,RAD2DEG:ot},SHADER:{SHADERVAR_VERTEX_POSITION:"vPosition",SHADERVAR_VERTEX_NUMBER:"attrVertIndex",SHADERVAR_VERTEX_NORMAL:"attrVertNormal",SHADERVAR_VERTEX_TEXCOORD:"attrTexCoord",SHADERVAR_INSTANCE_MMATRIX:"instMat",SHADERVAR_VERTEX_COLOR:"attrVertColor",SHADERVAR_UNI_PROJMAT:"projMatrix",SHADERVAR_UNI_VIEWMAT:"viewMatrix",SHADERVAR_UNI_MODELMAT:"modelMatrix",SHADERVAR_UNI_NORMALMAT:"normalMatrix",SHADERVAR_UNI_INVVIEWMAT:"inverseViewMatrix",SHADERVAR_UNI_INVPROJMAT:"invProjMatrix",SHADERVAR_UNI_VIEWPOS:"camPos"},BLEND_MODES:{BLEND_NONE:0,BLEND_NORMAL:1,BLEND_ADD:2,BLEND_SUB:3,BLEND_MUL:4}};const ht={lastMesh:null},lt=function(t,e,i){this._cgl=t,this._log=new a("cgl_mesh"),this._bufVertexAttrib=null,this._bufVerticesIndizes=this._cgl.gl.createBuffer(),this._indexType=this._cgl.gl.UNSIGNED_SHORT,this._attributes=[],this._attribLocs={},this._geom=null,this._lastShader=null,this._numInstances=0,this._glPrimitive=i,this._preWireframeGeom=null,this.addVertexNumbers=!1,this.feedBackAttributes=[],this.setGeom(e),this._feedBacks=[],this._feedBacksChanged=!1,this._transformFeedBackLoc=-1,this._lastAttrUpdate=0,this._name="unknown",this._cgl.profileData.addHeavyEvent("mesh constructed",this._name),this._queryExt=null,Object.defineProperty(this,"numInstances",{get(){return this._numInstances},set(t){this.setNumInstances(t)}})};var ct;lt.prototype.updateVertices=function(t){this.setAttribute(at.SHADER.SHADERVAR_VERTEX_POSITION,t.vertices,3),this._numVerts=t.vertices.length/3},lt.prototype.setAttributePointer=function(t,e,i,s){for(let r=0;r=e.length-1&&this._log.log(this._cgl.canvas.id+" "+t.name+" buffersubdata out of bounds ?",e.length,s,i,t),1==this._cgl.glVersion?this._cgl.gl.bufferSubData(this._cgl.gl.ARRAY_BUFFER,0,e):this._cgl.gl.bufferSubData(this._cgl.gl.ARRAY_BUFFER,4*i,e,i,s-i))},lt.prototype._resizeAttr=function(t,e){e.buffer&&this._cgl.gl.deleteBuffer(e.buffer),e.buffer=this._cgl.gl.createBuffer(),this._cgl.gl.bindBuffer(this._cgl.gl.ARRAY_BUFFER,e.buffer),this._bufferArray(t,e),e.numItems=t.length/e.itemSize},lt.prototype._bufferArray=function(t,e){let i=null;t&&(this._cgl.debugOneFrame&&console.log("_bufferArray",t.length,e.name),t instanceof Float32Array?i=t:e&&i&&i.length==t.length?i.set(t):(i=new Float32Array(t),this._cgl.debugOneFrame&&console.log("_bufferArray create new float32array",t.length,e.name),this._cgl.profileData.profileNonTypedAttrib++,this._cgl.profileData.profileNonTypedAttribNames="("+this._name+":"+e.name+")"),e.arrayLength=i.length,this._cgl.gl.bufferData(this._cgl.gl.ARRAY_BUFFER,i,this._cgl.gl.DYNAMIC_DRAW))},lt.prototype.addAttribute=lt.prototype.updateAttribute=lt.prototype.setAttribute=function(t,e,i,s){if(!e)throw this._log.error("mesh addAttribute - no array given! "+t),new Error;let r=null,n=!1,o=0;const a=e.length/i;for(this._cgl.profileData.profileMeshAttributes+=a||0,"function"==typeof s&&(r=s),"object"==typeof s&&(s.cb&&(r=s.cb),s.instanced&&(n=s.instanced)),t==at.SHADER.SHADERVAR_INSTANCE_MMATRIX&&(n=!0),o=0;o0)this.setAttribute(at.SHADER.SHADERVAR_VERTEX_TEXCOORD,t.texCoords,2);else{const e=new Float32Array(Math.round(t.vertices.length/3*2));this.setAttribute(at.SHADER.SHADERVAR_VERTEX_TEXCOORD,e,2)}},lt.prototype.updateNormals=function(t){if(t.vertexNormals&&t.vertexNormals.length>0)this.setAttribute(at.SHADER.SHADERVAR_VERTEX_NORMAL,t.vertexNormals,3);else{const e=new Float32Array(Math.round(t.vertices.length));this.setAttribute(at.SHADER.SHADERVAR_VERTEX_NORMAL,e,3)}},lt.prototype._setVertexNumbers=function(t){if(!this._verticesNumbers||this._verticesNumbers.length!=this._numVerts||t){if(t)this._verticesNumbers=t;else{this._verticesNumbers=new Float32Array(this._numVerts);for(let t=0;t{i.uniformNumVertices||(i.uniformNumVertices=new nt(i,"f","numVertices",this._numVerts)),i.uniformNumVertices.setValue(this._numVerts)})}},lt.prototype.setVertexIndices=function(t){if(this._bufVerticesIndizes)if(t.length>0){for(let e=0;e=this._numVerts)return void this._log.warn("invalid index in "+this._name);this._cgl.gl.bindBuffer(this._cgl.gl.ELEMENT_ARRAY_BUFFER,this._bufVerticesIndizes),t instanceof Float32Array&&this._log.warn("vertIndices float32Array: "+this._name),t instanceof Uint32Array?(this.vertIndicesTyped=t,this._indexType=this._cgl.gl.UNSIGNED_INT):t instanceof Uint16Array?this.vertIndicesTyped=t:this.vertIndicesTyped=new Uint16Array(t),this._cgl.gl.bufferData(this._cgl.gl.ELEMENT_ARRAY_BUFFER,this.vertIndicesTyped,this._cgl.gl.DYNAMIC_DRAW),this._bufVerticesIndizes.itemSize=1,this._bufVerticesIndizes.numItems=t.length}else this._bufVerticesIndizes.numItems=0;else this._log.warn("no bufVerticesIndizes: "+this._name)},lt.prototype.setGeom=function(t,e){this._geom=t,null!=t.glPrimitive&&(this._glPrimitive=t.glPrimitive),this._geom&&this._geom.name&&(this._name="mesh "+this._geom.name),ht.lastMesh=null,this._cgl.profileData.profileMeshSetGeom++,this._disposeAttributes(),this.updateVertices(this._geom),this.setVertexIndices(this._geom.verticesIndices),this.addVertexNumbers&&this._setVertexNumbers();const i=this._geom.getAttributes(),s={texCoords:at.SHADER.SHADERVAR_VERTEX_TEXCOORD,vertexNormals:at.SHADER.SHADERVAR_VERTEX_NORMAL,vertexColors:at.SHADER.SHADERVAR_VERTEX_COLOR,tangents:"attrTangent",biTangents:"attrBiTangent"};for(const t in i)i[t].data&&i[t].data.length&&this.setAttribute(s[t]||t,i[t].data,i[t].itemSize);e&&(this._geom=null)},lt.prototype._preBind=function(t){for(let e=0;ethis._lastAttrUpdate||e.length!=this._attributes.length){this._lastAttrUpdate=t.lastCompile;for(let t=0;t=0&&this._cgl.gl.disableVertexAttribArray(e[t])):(this._cgl.gl.vertexAttribDivisor(e[t],0),this._cgl.gl.vertexAttribDivisor(e[t]+1,0),this._cgl.gl.vertexAttribDivisor(e[t]+2,0),this._cgl.gl.vertexAttribDivisor(e[t]+3,0),this._cgl.gl.disableVertexAttribArray(e[t]+1),this._cgl.gl.disableVertexAttribArray(e[t]+2),this._cgl.gl.disableVertexAttribArray(e[t]+3))),-1!=e[t]&&this._cgl.gl.disableVertexAttribArray(e[t])},lt.prototype.meshChanged=function(){return this._cgl.lastMesh&&this._cgl.lastMesh!=this},lt.prototype.printDebug=function(t){console.log("--attributes");for(let t=0;t0},ct.prototype.removeFeedbacks=function(t){this._feedbacks&&(this._feedbacks.length=0,this._feedBacksChanged=!0)},ct.prototype.setAttributeFeedback=function(){},ct.prototype.setFeedback=function(t,e,i){let s={nameOut:e},r=!1;this.unBindFeedbacks();for(let t=0;t=e)return t.setUiError("texeffect",null),!0;e&&t.patch.cgl.currentTextureEffect.imgCompVer="+e+' Downgrade to previous version",1)}return!!t.patch.cgl.currentTextureEffect||(t.patch.cgl.currentTextureEffect||t.uiAttribs.uierrors&&0!=t.uiAttribs.uierrors.length?!!t.patch.cgl.currentTextureEffect:(t.setUiError("texeffect",'This op must be a child of an ImageCompose op! More infos here. ',1),!1))},gt.getBlendCode=function(t){let e="".endl()+"vec3 _blend(vec3 base,vec3 blend)".endl()+"{".endl()+" vec3 colNew=blend;".endl()+" #ifdef BM_MULTIPLY".endl()+" colNew=base*blend;".endl()+" #endif".endl()+" #ifdef BM_MULTIPLY_INV".endl()+" colNew=base* vec3(1.0)-blend;".endl()+" #endif".endl()+" #ifdef BM_AVERAGE".endl()+" colNew=((base + blend) / 2.0);".endl()+" #endif".endl()+" #ifdef BM_ADD".endl()+" colNew=min(base + blend, vec3(1.0));".endl()+" #endif".endl()+" #ifdef BM_SUBTRACT_ONE".endl()+" colNew=max(base + blend - vec3(1.0), vec3(0.0));".endl()+" #endif".endl()+" #ifdef BM_SUBTRACT".endl()+" colNew=base - blend;".endl()+" #endif".endl()+" #ifdef BM_DIFFERENCE".endl()+" colNew=abs(base - blend);".endl()+" #endif".endl()+" #ifdef BM_NEGATION".endl()+" colNew=(vec3(1.0) - abs(vec3(1.0) - base - blend));".endl()+" #endif".endl()+" #ifdef BM_EXCLUSION".endl()+" colNew=(base + blend - 2.0 * base * blend);".endl()+" #endif".endl()+" #ifdef BM_LIGHTEN".endl()+" colNew=max(blend, base);".endl()+" #endif".endl()+" #ifdef BM_DARKEN".endl()+" colNew=min(blend, base);".endl()+" #endif".endl()+" #ifdef BM_OVERLAY".endl()+" #define BlendOverlayf(base, blend) (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))".endl()+" colNew=vec3(BlendOverlayf(base.r, blend.r),BlendOverlayf(base.g, blend.g),BlendOverlayf(base.b, blend.b));".endl()+" #endif".endl()+" #ifdef BM_SCREEN".endl()+" #define BlendScreenf(base, blend) (1.0 - ((1.0 - base) * (1.0 - blend)))".endl()+" colNew=vec3(BlendScreenf(base.r, blend.r),BlendScreenf(base.g, blend.g),BlendScreenf(base.b, blend.b));".endl()+" #endif".endl()+" #ifdef BM_SOFTLIGHT".endl()+" #define BlendSoftLightf(base, blend) ((blend < 0.5) ? (2.0 * base * blend + base * base * (1.0 - 2.0 * blend)) : (sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend)))".endl()+" colNew=vec3(BlendSoftLightf(base.r, blend.r),BlendSoftLightf(base.g, blend.g),BlendSoftLightf(base.b, blend.b));".endl()+" #endif".endl()+" #ifdef BM_HARDLIGHT".endl()+" #define BlendOverlayf(base, blend) (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))".endl()+" colNew=vec3(BlendOverlayf(base.r, blend.r),BlendOverlayf(base.g, blend.g),BlendOverlayf(base.b, blend.b));".endl()+" #endif".endl()+" #ifdef BM_COLORDODGE".endl()+" #define BlendColorDodgef(base, blend) ((blend == 1.0) ? blend : min(base / (1.0 - blend), 1.0))".endl()+" colNew=vec3(BlendColorDodgef(base.r, blend.r),BlendColorDodgef(base.g, blend.g),BlendColorDodgef(base.b, blend.b));".endl()+" #endif".endl()+" #ifdef BM_COLORBURN".endl()+" #define BlendColorBurnf(base, blend) ((blend == 0.0) ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0))".endl()+" colNew=vec3(BlendColorBurnf(base.r, blend.r),BlendColorBurnf(base.g, blend.g),BlendColorBurnf(base.b, blend.b));".endl()+" #endif".endl()+" return colNew;".endl()+"}".endl();return t||(e+="vec4 cgl_blend(vec4 oldColor,vec4 newColor,float amount)".endl()+"{".endl()+"vec4 col=vec4( _blend(oldColor.rgb,newColor.rgb) ,1.0);".endl()+"col=vec4( mix( col.rgb, oldColor.rgb ,1.0-oldColor.a*amount),1.0);".endl()+"return col;".endl()+"}".endl()),t>=3&&(e+="vec4 cgl_blendPixel(vec4 base,vec4 col,float amount)".endl()+"{".endl()+"vec3 colNew=_blend(base.rgb,col.rgb);".endl()+"float newA=clamp(base.a+(col.a*amount),0.,1.);".endl()+"#ifdef BM_ALPHAMASKED".endl()+"newA=base.a;".endl()+"#endif".endl()+"return vec4(".endl()+"mix(colNew,base.rgb,1.0-(amount*col.a)),".endl()+"newA);".endl()+"}".endl()),e},gt.onChangeBlendSelect=function(t,e,i){t.toggleDefine("BM_NORMAL","normal"==e),t.toggleDefine("BM_MULTIPLY","multiply"==e),t.toggleDefine("BM_MULTIPLY_INV","multiply invert"==e),t.toggleDefine("BM_AVERAGE","average"==e),t.toggleDefine("BM_ADD","add"==e),t.toggleDefine("BM_SUBTRACT_ONE","subtract one"==e),t.toggleDefine("BM_SUBTRACT","subtract"==e),t.toggleDefine("BM_DIFFERENCE","difference"==e),t.toggleDefine("BM_NEGATION","negation"==e),t.toggleDefine("BM_EXCLUSION","exclusion"==e),t.toggleDefine("BM_LIGHTEN","lighten"==e),t.toggleDefine("BM_DARKEN","darken"==e),t.toggleDefine("BM_OVERLAY","overlay"==e),t.toggleDefine("BM_SCREEN","screen"==e),t.toggleDefine("BM_SOFTLIGHT","softlight"==e),t.toggleDefine("BM_HARDLIGHT","hardlight"==e),t.toggleDefine("BM_COLORDODGE","color dodge"==e),t.toggleDefine("BM_COLORBURN","color burn"==e),t.toggleDefine("BM_ALPHAMASKED",i)},gt.AddBlendSelect=function(t,e,i){return t.inValueSelect(e||"Blend Mode",["normal","lighten","darken","multiply","multiply invert","average","add","subtract","difference","negation","exclusion","overlay","screen","color dodge","color burn","softlight","hardlight","subtract one"],i||"normal")},gt.AddBlendAlphaMask=function(t,e,i){return t.inSwitch(e||"Alpha Mask",["Off","On"],i||"Off")},gt.setupBlending=function(t,e,i,s,r){const n=()=>{let s=!1;r&&(s="On"==r.get()),gt.onChangeBlendSelect(e,i.get(),s);let n=i.get();"normal"==n?n=null:"multiply"==n?n="mul":"multiply invert"==n?n="mulinv":"lighten"==n?n="light":"darken"==n?n="darken":"average"==n?n="avg":"subtract one"==n?n="sub one":"subtract"==n?n="sub":"difference"==n?n="diff":"negation"==n||"negation"==n||"negation"==n?n="neg":"exclusion"==n?n="exc":"overlay"==n?n="ovl":"color dodge"==n?n="dodge":"color burn"==n?n="burn":"softlight"==n?n="soft":"hardlight"==n&&(n="hard"),t.setUiAttrib({extendTitle:n})};t.setPortGroup("Blending",[i,s,r]);let o=!1;i.onChange=n,r&&(r.onChange=n,o="On"==r.get()),gt.onChangeBlendSelect(e,i.get(),o)};const pt={"CGL.BLENDMODES":function(){this.name="blendmodes",this.srcHeadFrag=gt.getBlendCode()},"CGL.BLENDMODES3":function(){this.name="blendmodes3",this.srcHeadFrag=gt.getBlendCode(3)},"CGL.LUMINANCE":function(){this.name="luminance",this.srcHeadFrag="".endl()+"float cgl_luminance(vec3 c)".endl()+"{".endl()+" return dot(vec3(0.2126,0.7152,0.0722),c);".endl()+"}".endl()},"CGL.RANDOM_OLD":function(){this.name="randomNumber",this.srcHeadFrag="".endl()+"float cgl_random(vec2 co)".endl()+"{".endl()+" return fract(sin(dot(co.xy ,vec2(12.9898,4.1414))) * 432758.5453);".endl()+"}".endl()+"vec3 cgl_random3(vec2 co)".endl()+"{".endl()+" return vec3( cgl_random(co),cgl_random(co+0.5711),cgl_random(co+1.5711));".endl()+"}"},"CGL.RANDOM_LOW":function(){this.name="randomNumber",this.srcHeadFrag="".endl()+"float cgl_random(vec2 co)".endl()+"{".endl()+" return fract(sin(dot(co.xy ,vec2(12.9898,4.1414))) * 358.5453);".endl()+"}".endl()+"vec3 cgl_random3(vec2 co)".endl()+"{".endl()+" return vec3( cgl_random(co),cgl_random(co+0.5711),cgl_random(co+1.5711));".endl()+"}"},"CGL.RANDOM_TEX":function(){this.name="randomNumbertex",this.srcHeadFrag="".endl()+"UNI sampler2D CGLRNDTEX;".endl()+"float cgl_random(vec2 co)".endl()+"{".endl()+" return texture(CGLRNDTEX,co*5711.0).r;".endl()+"}".endl()+"vec3 cgl_random3(vec2 co)".endl()+"{".endl()+" return texture(CGLRNDTEX,co*5711.0).rgb;".endl()+"}",this.initUniforms=function(t){return[new nt(t,"t","CGLRNDTEX",7)]},this.onBind=function(t,e){B.getRandomTexture(t),t.setTexture(7,B.getRandomTexture(t).tex)}}},_t=function(){return window.performance.now()},dt=function(){return _t()},ft=function(){CABLES.EventTarget.apply(this),this._timeStart=_t(),this._timeOffset=0,this._currentTime=0,this._lastTime=0,this._paused=!0,this._delay=0,this.overwriteTime=-1};ft.prototype._getTime=function(){return this._lastTime=(_t()-this._timeStart)/1e3,this._lastTime+this._timeOffset},ft.prototype.setDelay=function(t){this._delay=t,this.emitEvent("timeChange")},ft.prototype.isPlaying=function(){return!this._paused},ft.prototype.update=function(){if(!this._paused)return this._currentTime=this._getTime(),this._currentTime},ft.prototype.getMillis=function(){return 1e3*this.get()},ft.prototype.get=ft.prototype.getTime=function(){return this.overwriteTime>=0?this.overwriteTime-this._delay:this._currentTime-this._delay},ft.prototype.togglePlay=function(){this._paused?this.play():this.pause()},ft.prototype.setTime=function(t){(isNaN(t)||t<0)&&(t=0),this._timeStart=_t(),this._timeOffset=t,this._currentTime=t,this.emitEvent("timeChange")},ft.prototype.setOffset=function(t){this._currentTime+t<0?(this._timeStart=_t(),this._timeOffset=0,this._currentTime=0):(this._timeOffset+=t,this._currentTime=this._lastTime+this._timeOffset),this.emitEvent("timeChange")},ft.prototype.play=function(){this._timeStart=_t(),this._paused=!1,this.emitEvent("playPause")},ft.prototype.pause=function(){this._timeOffset=this._currentTime,this._paused=!0,this.emitEvent("playPause")};const mt=Math.PI/180,Et=(Math.PI,-1!=window.navigator.userAgent.indexOf("Windows")),Tt=function(t){let e;if(t.wheelDelta)e=t.wheelDelta%120-0==-0?t.wheelDelta/120:t.wheelDelta/30,e*=-1.5,Et&&(e*=2);else{let i=t.deltaY;t.shiftKey&&(i=t.deltaX);const s=i||t.detail;e=-(s%3?10*s:s/3),e*=-3}return e>20&&(e=20),e<-20&&(e=-20),e},At=Tt,bt=Tt,xt={"&":"&","<":"<",">":">",'"':""","'":"'"},vt=/[&<>"']/g,yt=RegExp(vt.source);const It=function(t,e){if(!t)throw new Error("shader constructed without cgl "+e);this._log=new a("cgl_shader"),this._cgl=t,e||this._log.stack("no shader name given"),this._name=e||"unknown",this.glslVersion=0,t.glVersion>1&&(this.glslVersion=300),this.id=x(),this._isValid=!0,this._program=null,this._uniforms=[],this._drawBuffers=[!0],this._defines=[],this._needsRecompile=!0,this._compileReason="initial",this._projMatrixUniform=null,this._mvMatrixUniform=null,this._mMatrixUniform=null,this._vMatrixUniform=null,this._camPosUniform=null,this._normalMatrixUniform=null,this._inverseViewMatrixUniform=null,this._attrVertexPos=-1,this.precision=t.patch.config.glslPrecision||"highp",this._pMatrixState=-1,this._vMatrixState=-1,this._modGroupCount=0,this._feedBackNames=[],this._attributes=[],this.glPrimitive=null,this.offScreenPass=!1,this._extensions=[],this.srcVert=this.getDefaultVertexShader(),this.srcFrag=this.getDefaultFragmentShader(),this.lastCompile=0,this._moduleNames=[],this._modules=[],this._moduleNumId=0,this._libs=[],this._structNames=[],this._structUniformNames=[],this._textureStackUni=[],this._textureStackTex=[],this._textureStackType=[],this._textureStackTexCgl=[],this._tempNormalMatrix=mat4.create(),this._tempCamPosMatrix=mat4.create(),this._tempInverseViewMatrix=mat4.create(),this._tempInverseProjMatrix=mat4.create(),this.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG"])};It.prototype.isValid=function(){return this._isValid},It.prototype.getCgl=function(){return this._cgl},It.prototype.getName=function(){return this._name},It.prototype.enableExtension=function(t){this.setWhyCompile("enable extension "+t),this._needsRecompile=!0,this._extensions.push(t)},It.prototype.getAttrVertexPos=function(){return this._attrVertexPos},It.prototype.hasTextureUniforms=function(){for(let t=0;t-1){const i=new pt[e];t=t.replace("{{"+e+"}}",i.srcHeadFrag),this._libs.push(i),i.initUniforms&&i.initUniforms(this)}return t},It.prototype.createStructUniforms=function(){let t="",e="";this._structNames=[],this._injectedStringsFrag={},this._injectedStringsVert={},this._structUniformNamesIndicesFrag=[],this._structUniformNamesIndicesVert=[];for(let i=0;it._name),e=[];for(let i=0;i-1&&e.push(i)}for(let t=this._uniforms.length-1;t>=0;t-=1)e.indexOf(t)>-1?this._uniforms.splice(t,1):this._uniforms[t].resetLoc()}this._cgl.printError("uniform resets"),this.hasTextureUniforms()&&(i+="#define HAS_TEXTURES".endl());let r="",n="";this.srcFrag||(this._log.error("[cgl shader] has no fragment source!",this),this.srcVert=this.getDefaultVertexShader(),this.srcFrag=this.getDefaultFragmentShader()),300==this.glslVersion?(r="#version 300 es".endl()+"// ".endl()+"// vertex shader "+this._name.endl()+"// ".endl()+"precision "+this.precision+" float;".endl()+"precision "+this.precision+" sampler2D;".endl()+"".endl()+"#define WEBGL2".endl()+"#define texture2D texture".endl()+"#define UNI uniform".endl()+"#define IN in".endl()+"#define OUT out".endl(),n="#version 300 es".endl()+"// ".endl()+"// fragment shader "+this._name.endl()+"// ".endl()+"precision "+this.precision+" float;".endl()+"precision "+this.precision+" sampler2D;".endl()+"".endl()+"#define WEBGL2".endl()+"#define texture2D texture".endl()+"#define IN in".endl()+"#define UNI uniform".endl()+"{{DRAWBUFFER}}".endl()):(n="".endl()+"// ".endl()+"// fragment shader "+this._name.endl()+"// ".endl()+"#define WEBGL1".endl()+"#define texture texture2D".endl()+"#define outColor gl_FragColor".endl()+"#define IN varying".endl()+"#define UNI uniform".endl(),r="".endl()+"// ".endl()+"// vertex shader "+this._name.endl()+"// ".endl()+"#define WEBGL1".endl()+"#define texture texture2D".endl()+"#define OUT varying".endl()+"#define IN attribute".endl()+"#define UNI uniform".endl());let o="\n// cgl generated".endl(),a="\n// cgl generated".endl();n+="\n// active mods: --------------- ",r+="\n// active mods: --------------- ";let h=!1,l=!1;for(let t=0;t=this._cgl.maxUniformsFrag&&this._log.warn("[cgl_shader] num uniforms frag: "+c+" / "+this._cgl.maxUniformsFrag),u>=this._cgl.maxUniformsVert&&this._log.warn("[cgl_shader] num uniforms vert: "+u+" / "+this._cgl.maxUniformsVert),-1==n.indexOf("precision")&&(n="precision "+this.precision+" float;".endl()+n),-1==r.indexOf("precision")&&(r="precision "+this.precision+" float;".endl()+r),/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)&&(n+="#define MOBILE".endl(),r+="#define MOBILE".endl()),r=e+r+i+s[0]+o+"\n// -- \n"+this.srcVert,n=e+n+i+s[1]+a+"\n// -- \n"+this.srcFrag;let g="",p="";this._modules.sort((function(t,e){return t.group-e.group})),this._modules.sort((function(t,e){return t.priority||0-e.priority||0}));let _=!1;for(let t=0;t-1&&(this._drawBuffers[0]=!0),n.indexOf("outColor1")>-1&&(this._drawBuffers[1]=!0),n.indexOf("outColor2")>-1&&(this._drawBuffers[2]=!0),n.indexOf("outColor3")>-1&&(this._drawBuffers[3]=!0),1==this._drawBuffers.length)d="out vec4 outColor;".endl(),d+="#define gl_FragColor outColor".endl();else{d+="#define MULTI_COLORTARGETS".endl(),d+="vec4 outColor;".endl();let t=0;for(let e=0;e{this.toggleDefine(t,e)},e.changeListener=e.on("change",e.onToggleDefine),e=e.get()),e?this.define(t):this.removeDefine(t)},It.prototype.define=function(t,e){null==e&&(e=""),"object"==typeof e&&(e.removeEventListener("change",e.onDefineChange),e.onDefineChange=e=>{this.define(t,e)},e.on("change",e.onDefineChange),e=e.get());for(let i=0;i0&&this._cgl.gl.transformFeedbackVaryings(t,this._feedBackNames,this._cgl.gl.SEPARATE_ATTRIBS),this._cgl.gl.linkProgram(t),this._cgl.printError("gl.linkprogram"),this._isValid=!0,this._hasErrors=!1,!1!==this._cgl.patch.config.glValidateShader&&(this._cgl.gl.validateProgram(t),this._cgl.gl.getProgramParameter(t,this._cgl.gl.VALIDATE_STATUS)||(console.log("shaderprogram validation failed..."),console.log(this._name+" programinfo: ",this._cgl.gl.getProgramInfoLog(t))),this._cgl.gl.getProgramParameter(t,this._cgl.gl.LINK_STATUS)||(this._hasErrors=!0,this._log.warn(this._cgl.gl.getShaderInfoLog(this.fshader)||"empty shader infolog"),this._log.warn(this._cgl.gl.getShaderInfoLog(this.vshader)||"empty shader infolog"),this._log.error(this._name+" shader linking fail..."),console.log(this._name+" programinfo: ",this._cgl.gl.getProgramInfoLog(t)),console.log("--------------------------------------"),console.log(this),console.log("--------------------------------------"),this._isValid=!1,this._name="errorshader",this.setSource(It.getDefaultVertexShader(),It.getErrorFragmentShader()),this._cgl.printError("shader link err")))},It.prototype.getProgram=function(){return this._program},It.prototype.setFeedbackNames=function(t){this.setWhyCompile("setFeedbackNames"),this._needsRecompile=!0,this._feedBackNames=t},It.prototype.getDefaultVertexShader=It.getDefaultVertexShader=function(){return"{{MODULES_HEAD}}\nIN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\nIN vec3 attrTangent,attrBiTangent;\n\nIN float attrVertIndex;\n\nOUT vec2 texCoord;\nOUT vec3 norm;\nUNI mat4 projMatrix;\nUNI mat4 viewMatrix;\nUNI mat4 modelMatrix;\n\nvoid main()\n{\n texCoord=attrTexCoord;\n norm=attrVertNormal;\n vec4 pos=vec4(vPosition, 1.0);\n vec3 tangent=attrTangent;\n vec3 bitangent=attrBiTangent;\n mat4 mMatrix=modelMatrix;\n {{MODULE_VERTEX_POSITION}}\n gl_Position = projMatrix * (viewMatrix*mMatrix) * pos;\n}\n"},It.prototype.getDefaultFragmentShader=It.getDefaultFragmentShader=function(t,e,i){return null==t&&(t=.5,e=.5,i=.5),"".endl()+"IN vec2 texCoord;".endl()+"{{MODULES_HEAD}}".endl()+"void main()".endl()+"{".endl()+" vec4 col=vec4("+t+","+e+","+i+",1.0);".endl()+" {{MODULE_COLOR}}".endl()+" outColor = col;".endl()+"}"},It.prototype.addAttribute=function(t){for(let e=0;ethis._cgl.maxTextureUnits&&this._log.warn("[shader._bindTextures] too many textures bound",this._textureStackTex.length+"/"+this._cgl.maxTextureUnits);for(let t=0;t",h+='
'),h+=(n=i)&&yt.test(n)?n.replace(vt,(function(t){return xt[t]})):n||"",s&&(h+="
",h+='
')}console.warn(o),o=o.replace(/\n/g,"
"),h=o+"
"+h+"

",h+="
",t.patch.emitEvent("criticalError",{title:"Shader error "+this._name,text:h}),t.patch.isEditorMode()&&console.log("Shader error "+this._name,h),this._name="errorshader",s.setSource(It.getDefaultVertexShader(),It.getErrorFragmentShader())}var n;return r};class St{constructor(t){this._cgl=t,this._lastTime=0,this.pause=!1,this.profileUniformCount=0,this.profileShaderBinds=0,this.profileUniformCount=0,this.profileShaderCompiles=0,this.profileVideosPlaying=0,this.profileMVPMatrixCount=0,this.profileEffectBuffercreate=0,this.profileShaderGetUniform=0,this.profileFrameBuffercreate=0,this.profileMeshSetGeom=0,this.profileTextureNew=0,this.profileGenMipMap=0,this.profileOnAnimFrameOps=0,this.profileMainloopMs=0,this.profileMeshDraw=0,this.profileTextureEffect=0,this.profileTexPreviews=0,this.shaderCompileTime=0,this.profileMeshNumElements=0,this.profileMeshAttributes=0,this.profileSingleMeshAttribute=[],this.heavyEvents=[],this.doProfileGlQuery=!1,this.glQueryData={}}clear(){this.profileSingleMeshAttribute={},this.profileMeshAttributes=0,this.profileUniformCount=0,this.profileShaderGetUniform=0,this.profileShaderCompiles=0,this.profileShaderBinds=0,this.profileTextureResize=0,this.profileFrameBuffercreate=0,this.profileEffectBuffercreate=0,this.profileTextureDelete=0,this.profileMeshSetGeom=0,this.profileVideosPlaying=0,this.profileMVPMatrixCount=0,this.profileNonTypedAttrib=0,this.profileNonTypedAttribNames="",this.profileTextureNew=0,this.profileGenMipMap=0,this.profileFramebuffer=0,this.profileMeshDraw=0,this.profileTextureEffect=0,this.profileTexPreviews=0,this.profileMeshNumElements=0}clearGlQuery(){for(let t in this.glQueryData)(!this.glQueryData[t].lastClear||performance.now()-this.glQueryData[t].lastClear>1e3)&&(this.glQueryData[t].time=this.glQueryData[t]._times/this.glQueryData[t]._numcount,this.glQueryData[t].num=this.glQueryData[t]._numcount,this.glQueryData[t]._times=0,this.glQueryData[t]._numcount=0,this.glQueryData[t].lastClear=performance.now())}addHeavyEvent(t,e,i){const s={event:t,name:e,info:i,date:performance.now()};this.heavyEvents.push(s),this._cgl.emitEvent("heavyEvent",s)}}const Rt={GAPI_WEBGL:0,GAPI_WEBGPU:1,Geometry:W,BoundingBox:z,FpsCounter:class extends Y{constructor(){super(),this._timeStartFrame=0,this._timeStartSecond=0,this._fpsCounter=0,this._msCounter=0,this.stats={ms:0,fps:0}}startFrame(){this._timeStartFrame=CABLES.now()}endFrame(){this._fpsCounter++;const t=CABLES.now()-this._timeStartFrame;this._msCounter+=t,CABLES.now()-this._timeStartSecond>1e3&&this.endSecond()}endSecond(){this.stats.fps=this._fpsCounter,this.stats.ms=Math.round(this._msCounter/this._fpsCounter*100)/100,this.emitEvent("performance",this.stats),this._fpsCounter=0,this._msCounter=0,this._timeStartSecond=CABLES.now()}}},Pt=function(t){Ut.apply(this),this.patch=t,this.gApi=Rt.GAPI_WEBGPU,this._viewport=[0,0,256,256],this._shaderStack=[],this.getViewPort=function(){return[0,0,this.canvasWidth,this.canvasHeight]},this.renderStart=function(t,e,i){this.fpsCounter.startFrame(),this._startMatrixStacks(e,i),this.setViewPort(0,0,this.canvasWidth,this.canvasHeight),this.emitEvent("beginFrame")},this.renderEnd=function(t){this._endMatrixStacks(),this.emitEvent("endFrame"),this.fpsCounter.endFrame()}};Pt.prototype.setViewPort=function(t,e,i,s){this._viewport=[t,e,i,s]},Pt.prototype.getViewPort=function(){return this._viewPort},Pt.prototype.createMesh=function(t,e){return new CGP.Mesh(this,t,e)},Pt.prototype.getShader=function(){return{}},Pt.prototype.pushShader=function(t){this._shaderStack.push(t)},Pt.prototype.popShader=function(){if(0===this._shaderStack.length)throw new Error("Invalid shader stack pop!");this._shaderStack.pop()},Pt.prototype.getShader=function(){return this._shaderStack[this._shaderStack.length-1]},Pt.prototype.pushErrorScope=function(){this.device.pushErrorScope("validation")},Pt.prototype.popErrorScope=function(t,e){this.device.popErrorScope().then(i=>{i&&(this.patch.emitEvent("criticalError",{title:'WebGPU error "'+t+'"',codeText:i.message}),console.warn("[cgp]",t,i.message,i,e),e&&e(i))})};class Ot extends rt{constructor(t,e,i,s,r,n,o,a,h,l){super(t,e,i,s,r,n,o,a,h,l),this._loc=-1,this._cgl=t._cgl}updateValueF(){}setValueF(t){this.needsUpdate=!0,this._value=t}updateValue2F(){}setValue2F(t){this.needsUpdate=!0,this._value=t}updateValue3F(){}setValue3F(t){this.needsUpdate=!0,this._value=t}updateValue4F(){}setValue4F(t){this.needsUpdate=!0,this._value=t}getSizeBytes(){return"f"==this._type||"i"==this._type?4:"2i"==this._type||"2f"==this._type?8:"3f"==this._type?12:"4f"==this._type?16:"m4"==this._type?64:void this._log.warn("unknown type getSizeBytes")}}class Nt{constructor(t,e){this._shaderType=e,this._shader=t,this._cgp=t._cgp,this._gpuBuffer=null,this._values=null,this._sizeBytes=0,this.update()}update(){this._sizeBytes=0;for(let t=0;t1)for(let e=0;e{this._isValid=!1})}}class Ct{constructor(t,e){if(!t)throw new Error("no cgp");this._log=new a("cgp_texture"),this._cgp=t,this.id=CABLES.uuid(),e=e||{},this.name=e.name||"unknown"}initTexture(t,e){this.width=t.width,this.height=t.height,this.textureType="rgba8unorm";const i={size:{width:t.width,height:t.height},format:this.textureType,usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST},s=this._cgp.device.createTexture(i);return this._cgp.device.queue.copyExternalImageToTexture({source:t},{texture:s},i.size),s}getInfo(){const t={};return t.name=this.name,t.size=this.width+" x "+this.height,t.textureType=this.textureType,t}}Ct.load=function(t,e,i,s){fetch(e).then(s=>{s.blob().then(s=>{createImageBitmap(s).then(s=>{const r=new Ct(t,{name:e});r.initTexture(s),i?i(r):console.log("Texture.load no onFinished callback")})})})};const wt=Object.assign({Context:Pt,Shader:class{constructor(t,e){if(!t)throw new Error("shader constructed without cgp "+e);this._log=new a("cgp_shader"),this._cgp=t,this._name=e,this._uniforms=[],e||this._log.stack("no shader name given"),this._name=e||"unknown",this.id=x(),this._isValid=!0,this._compileReason="",this.shaderModule=null,this._needsRecompile=!0,this._src=""}get isValid(){return this._isValid}get uniforms(){return this._uniforms}getName(){return this._name}setWhyCompile(t){this._compileReason=t}setSource(t){this._src=t,this.setWhyCompile("Source changed"),this._needsRecompile=!0}compile(){this._isValid=!0,console.log("compiling shader...",this._compileReason),this._cgp.pushErrorScope(),this.shaderModule=this._cgp.device.createShaderModule({code:this._src}),this._cgp.popErrorScope("cgp_shader "+this._name,this.error.bind(this)),this._needsRecompile=!1}error(t){this._isValid=!1}bind(){for(let t=0;t["WebGL","WebGPU"][this.gApi],this.setCanvas=function(t){this.canvas="string"==typeof t?document.getElementById(t):t,this._setCanvas&&this._setCanvas(t),this.updateSize()},this.updateSize=function(){this.canvas.width=this.canvasWidth=this.canvas.clientWidth*this.pixelDensity,this.canvas.height=this.canvasHeight=this.canvas.clientHeight*this.pixelDensity},this.setSize=function(t,e,i){i||(this.canvas.style.width=t+"px",this.canvas.style.height=e+"px"),this.canvas.width=t*this.pixelDensity,this.canvas.height=e*this.pixelDensity,this.updateSize()},this._resizeToWindowSize=function(){this.setSize(window.innerWidth,window.innerHeight),this.updateSize()},this._resizeToParentSize=function(){const t=this.canvas.parentElement;t?(this.setSize(t.clientWidth,t.clientHeight),this.updateSize()):this._log.error("cables: can not resize to container element")},this.setAutoResize=function(t){window.removeEventListener("resize",this._resizeToWindowSize.bind(this)),window.removeEventListener("resize",this._resizeToParentSize.bind(this)),"window"==t&&(window.addEventListener("resize",this._resizeToWindowSize.bind(this)),window.addEventListener("orientationchange",this._resizeToWindowSize.bind(this)),this._resizeToWindowSize()),"parent"==t&&(window.addEventListener("resize",this._resizeToParentSize.bind(this)),this._resizeToParentSize())},this.pushPMatrix=function(){this.pMatrix=this._pMatrixStack.push(this.pMatrix)},this.popPMatrix=function(){return this.pMatrix=this._pMatrixStack.pop(),this.pMatrix},this.getProjectionMatrixStateCount=function(){return this._pMatrixStack.stateCounter},this.pushModelMatrix=function(){this.mMatrix=this._mMatrixStack.push(this.mMatrix)},this.popModelMatrix=function(){return this.mMatrix=this._mMatrixStack.pop(),this.mMatrix},this.modelMatrix=function(){return this.mMatrix},this.pushViewMatrix=function(){this.vMatrix=this._vMatrixStack.push(this.vMatrix)},this.popViewMatrix=function(){this.vMatrix=this._vMatrixStack.pop()},this.getViewMatrixStateCount=function(){return this._vMatrixStack.stateCounter},this._startMatrixStacks=(t,e)=>{t=t||this._ident,e=e||this._identView,mat4.perspective(this.pMatrix,45,this.canvasWidth/this.canvasHeight,.1,1e3),mat4.identity(this.mMatrix),mat4.identity(this.vMatrix),mat4.translate(this.mMatrix,this.mMatrix,t),mat4.translate(this.vMatrix,this.vMatrix,e),this.pushPMatrix(),this.pushModelMatrix(),this.pushViewMatrix()},this._endMatrixStacks=()=>{this.popViewMatrix(),this.popModelMatrix(),this.popPMatrix()}},Bt=function(t){Ut.apply(this),this.gApi=Rt.GAPI_WEBGL,this.pushMvMatrix=this.pushModelMatrix,this.popMvMatrix=this.popmMatrix=this.popModelMatrix,this.profileData=new St(this),this._log=new a("cgl_context");const e=[0,0,0,0];this.glVersion=0,this.glUseHalfFloatTex=!1,this.clearCanvasTransparent=!0,this.clearCanvasDepth=!0,this.patch=t,this.debugOneFrame=!1,this.checkGlErrors=!0,this.maxTextureUnits=0,this.maxVaryingVectors=0,this.currentProgram=null,this._hadStackError=!1,this.glSlowRenderer=!1,this._isSafariCrap=!1,this.temporaryTexture=null,this.frameStore={},this._onetimeCallbacks=[],this.gl=null,this._cursor="auto",this._currentCursor="",this._glFrameBufferStack=[],this._frameBufferStack=[],this._shaderStack=[],this._stackDepthTest=[],Object.defineProperty(this,"mvMatrix",{get(){return this.mMatrix},set(t){this.mMatrix=t}});const i=new It(this,"simpleshader");i.setModules(["MODULE_VERTEX_POSITION","MODULE_COLOR","MODULE_BEGIN_FRAG"]),i.setSource(It.getDefaultVertexShader(),It.getDefaultFragmentShader());let s=i;this.aborted=!1;const r=[];this.exitError=function(t,e){this.patch.exitError(t,e),this.aborted=!0},this._setCanvas=function(t){if(this.patch.config.canvas||(this.patch.config.canvas={}),this.patch.config.canvas.hasOwnProperty("preserveDrawingBuffer")||(this.patch.config.canvas.preserveDrawingBuffer=!1),this.patch.config.canvas.hasOwnProperty("premultipliedAlpha")||(this.patch.config.canvas.premultipliedAlpha=!1),this.patch.config.canvas.hasOwnProperty("alpha")||(this.patch.config.canvas.alpha=!1),this.patch.config.canvas.stencil=!0,this.patch.config.hasOwnProperty("clearCanvasColor")&&(this.clearCanvasTransparent=this.patch.config.clearCanvasColor),this.patch.config.hasOwnProperty("clearCanvasDepth")&&(this.clearCanvasDepth=this.patch.config.clearCanvasDepth),/^((?!chrome|android).)*safari/i.test(navigator.userAgent)&&(this._isSafariCrap=!0),this.patch.config.canvas.forceWebGl1||(this.gl=this.canvas.getContext("webgl2",this.patch.config.canvas)),this.gl&&"WebGL 1.0"!=this.gl.getParameter(this.gl.VERSION)?this.glVersion=2:(this.gl=this.canvas.getContext("webgl",this.patch.config.canvas)||this.canvas.getContext("experimental-webgl",this.patch.config.canvas),this.glVersion=1,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)&&navigator.userAgent.match(/iPhone/i)&&(this.glUseHalfFloatTex=!0),/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream&&(this.patch.config.canvas.hasOwnProperty("powerPreference")||(this.patch.config.canvas.powerPreference="high-performance"))),!this.gl)return void this.exitError("NO_WEBGL","sorry, could not initialize WebGL. Please check if your Browser supports WebGL or try to restart your browser.");const e=this.gl.getExtension("WEBGL_debug_renderer_info");e&&(this.glRenderer=this.gl.getParameter(e.UNMASKED_RENDERER_WEBGL),"Google SwiftShader"===this.glRenderer&&(this.glSlowRenderer=!0)),this.gl.getExtension("OES_standard_derivatives");const i=this.gl.getExtension("ANGLE_instanced_arrays")||this.gl;this.canvas.addEventListener("webglcontextlost",t=>{this._log.error("canvas lost...",t),this.emitEvent("webglcontextlost"),this.aborted=!0}),this.maxVaryingVectors=this.gl.getParameter(this.gl.MAX_VARYING_VECTORS),this.maxTextureUnits=this.gl.getParameter(this.gl.MAX_TEXTURE_IMAGE_UNITS),this.maxTexSize=this.gl.getParameter(this.gl.MAX_TEXTURE_SIZE),this.maxUniformsFrag=this.gl.getParameter(this.gl.MAX_FRAGMENT_UNIFORM_VECTORS),this.maxUniformsVert=this.gl.getParameter(this.gl.MAX_VERTEX_UNIFORM_VECTORS),this.maxSamples=0,this.gl.MAX_SAMPLES&&(this.maxSamples=this.gl.getParameter(this.gl.MAX_SAMPLES)),i.vertexAttribDivisorANGLE&&(this.gl.vertexAttribDivisor=i.vertexAttribDivisorANGLE.bind(i),this.gl.drawElementsInstanced=i.drawElementsInstancedANGLE.bind(i))},this.getInfo=function(){return{glVersion:this.glVersion,glRenderer:this.glRenderer,glUseHalfFloatTex:this.glUseHalfFloatTex,maxVaryingVectors:this.maxVaryingVectors,maxTextureUnits:this.maxTextureUnits,maxTexSize:this.maxTexSize,maxUniformsFrag:this.maxUniformsFrag,maxUniformsVert:this.maxUniformsVert,maxSamples:this.maxSamples}};let n=-1,o=-1;this.getViewPort=function(){return e},this.resetViewPort=function(){this.gl.viewport(e[0],e[1],e[2],e[3])},this.setViewPort=function(t,i,s,r){e[0]=Math.round(t),e[1]=Math.round(i),e[2]=Math.round(s),e[3]=Math.round(r),this.gl.viewport(e[0],e[1],e[2],e[3])},this.screenShot=function(t,e,i,s){e&&(this.gl.clearColor(1,1,1,1),this.gl.colorMask(!1,!1,!1,!0),this.gl.clear(this.gl.COLOR_BUFFER_BIT),this.gl.colorMask(!0,!0,!0,!0)),this.canvas&&this.canvas.toBlob&&this.canvas.toBlob(e=>{t?t(e):this._log.log("no screenshot callback...")},i,s)},this.endFrame=function(){if(this.patch.isEditorMode()&&CABLES.GL_MARKER.drawMarkerLayer(this),this.setPreviousShader(),this._vMatrixStack.length()>0&&this.logStackError("view matrix stack length !=0 at end of rendering..."),this._mMatrixStack.length()>0&&this.logStackError("mvmatrix stack length !=0 at end of rendering..."),this._pMatrixStack.length()>0&&this.logStackError("pmatrix stack length !=0 at end of rendering..."),this._glFrameBufferStack.length>0&&this.logStackError("glFrameBuffer stack length !=0 at end of rendering..."),this._stackDepthTest.length>0&&this.logStackError("depthtest stack length !=0 at end of rendering..."),this._stackDepthWrite.length>0&&this.logStackError("depthwrite stack length !=0 at end of rendering..."),this._stackDepthFunc.length>0&&this.logStackError("depthfunc stack length !=0 at end of rendering..."),this._stackBlend.length>0&&this.logStackError("blend stack length !=0 at end of rendering..."),this._stackBlendMode.length>0&&this.logStackError("blendMode stack length !=0 at end of rendering..."),this._shaderStack.length>0&&this.logStackError("this._shaderStack length !=0 at end of rendering..."),this._stackCullFace.length>0&&this.logStackError("this._stackCullFace length !=0 at end of rendering..."),this._stackCullFaceFacing.length>0&&this.logStackError("this._stackCullFaceFacing length !=0 at end of rendering..."),this._frameStarted=!1,n!=this.canvasWidth||o!=this.canvasHeight){n=this.canvasWidth,o=this.canvasHeight,this.setSize(this.canvasWidth/this.pixelDensity,this.canvasHeight/this.pixelDensity),this.updateSize();for(let t=0;t=0;t--)if(this._shaderStack[t]&&this.frameStore.renderOffscreen==this._shaderStack[t].offScreenPass)return this._shaderStack[t]},this.getDefaultShader=function(){return i},this.pushShader=this.setShader=function(t){this._shaderStack.push(t),s=t},this.popShader=this.setPreviousShader=function(){if(0===this._shaderStack.length)throw new Error("Invalid shader stack pop!");this._shaderStack.pop(),s=this._shaderStack[this._shaderStack.length-1]},this.pushGlFrameBuffer=function(t){this._glFrameBufferStack.push(t)},this.popGlFrameBuffer=function(){return 0==this._glFrameBufferStack.length?null:(this._glFrameBufferStack.pop(),this._glFrameBufferStack[this._glFrameBufferStack.length-1])},this.getCurrentGlFrameBuffer=function(){return 0===this._glFrameBufferStack.length?null:this._glFrameBufferStack[this._glFrameBufferStack.length-1]},this.pushFrameBuffer=function(t){this._frameBufferStack.push(t)},this.popFrameBuffer=function(){return 0==this._frameBufferStack.length?null:(this._frameBufferStack.pop(),this._frameBufferStack[this._frameBufferStack.length-1])},this.getCurrentFrameBuffer=function(){return 0===this._frameBufferStack.length?null:this._frameBufferStack[this._frameBufferStack.length-1]},this.renderStart=function(t,e,s){this.fpsCounter.startFrame(),this.pushDepthTest(!0),this.pushDepthWrite(!0),this.pushDepthFunc(t.gl.LEQUAL),this.pushCullFaceFacing(t.gl.BACK),this.pushCullFace(!1),this.clearCanvasTransparent&&(t.gl.clearColor(0,0,0,0),t.gl.clear(t.gl.COLOR_BUFFER_BIT)),this.clearCanvasDepth&&t.gl.clear(t.gl.DEPTH_BUFFER_BIT),t.setViewPort(0,0,t.canvasWidth,t.canvasHeight),this._startMatrixStacks(e,s),t.pushBlendMode(at.BLEND_MODES.BLEND_NORMAL,!1);for(let t=0;t0){for(let t=0;t0&&this.gl.cullFace(this._stackCullFaceFacing[this._stackCullFaceFacing.length-1])},Bt.prototype._stackDepthFunc=[],Bt.prototype.pushDepthFunc=function(t){this._stackDepthFunc.push(t),this.gl.depthFunc(t)},Bt.prototype.stateDepthFunc=function(){return this._stackDepthFunc.length>0&&this._stackDepthFunc[this._stackDepthFunc.length-1]},Bt.prototype.popDepthFunc=function(){this._stackDepthFunc.pop(),this._stackDepthFunc.length>0&&this.gl.depthFunc(this._stackDepthFunc[this._stackDepthFunc.length-1])},Bt.prototype._stackBlend=[],Bt.prototype.pushBlend=function(t){this._stackBlend.push(t),t?this.gl.enable(this.gl.BLEND):this.gl.disable(this.gl.BLEND)},Bt.prototype.popBlend=function(){this._stackBlend.pop(),this._stackBlend[this._stackBlend.length-1]?this.gl.enable(this.gl.BLEND):this.gl.disable(this.gl.BLEND)},Bt.prototype.stateBlend=function(){return this._stackBlend[this._stackBlend.length-1]};Bt.prototype._stackBlendMode=[],Bt.prototype._stackBlendModePremul=[],Bt.prototype.pushBlendMode=function(t,e){this._stackBlendMode.push(t),this._stackBlendModePremul.push(e);const i=this._stackBlendMode.length-1;this.pushBlend(this._stackBlendMode[i]!==at.BLEND_MODES.BLEND_NONE),this._setBlendMode(this._stackBlendMode[i],this._stackBlendModePremul[i])},Bt.prototype.popBlendMode=function(){this._stackBlendMode.pop(),this._stackBlendModePremul.pop();const t=this._stackBlendMode.length-1;this.popBlend(this._stackBlendMode[t]!==at.BLEND_MODES.BLEND_NONE),t>=0&&this._setBlendMode(this._stackBlendMode[t],this._stackBlendModePremul[t])},Bt.prototype._stackStencil=[],Bt.prototype.pushStencil=function(t){this._stackStencil.push(t),t?this.gl.enable(this.gl.STENCIL_TEST):this.gl.disable(this.gl.STENCIL_TEST)},Bt.prototype.popStencil=function(){this._stackStencil.pop(),this._stackStencil[this._stackStencil.length-1]?this.gl.enable(this.gl.STENCIL_TEST):this.gl.disable(this.gl.STENCIL_TEST)},Bt.prototype.glGetAttribLocation=function(t,e){return this.gl.getAttribLocation(t,e)},Bt.prototype.shouldDrawHelpers=function(t){if(this.frameStore.shadowPass)return!1;if(!t.patch.isEditorMode())return!1;const e=this.getCurrentFrameBuffer();if(e&&e.getWidth){if(!(this.canvasWidth/this.canvasHeight==e.getWidth()/e.getHeight()))return!1}return CABLES.UI.renderHelper||CABLES.UI.renderHelperCurrent&&t.isCurrentUiOp()},Bt.prototype._setBlendMode=function(t,e){const i=this.gl;t==at.BLEND_MODES.BLEND_NONE||(t==at.BLEND_MODES.BLEND_ADD?e?(i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD),i.blendFuncSeparate(i.ONE,i.ONE,i.ONE,i.ONE)):(i.blendEquation(i.FUNC_ADD),i.blendFunc(i.SRC_ALPHA,i.ONE)):t==at.BLEND_MODES.BLEND_SUB?e?(i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD),i.blendFuncSeparate(i.ZERO,i.ZERO,i.ONE_MINUS_SRC_COLOR,i.ONE_MINUS_SRC_ALPHA)):(i.blendEquation(i.FUNC_ADD),i.blendFunc(i.ZERO,i.ONE_MINUS_SRC_COLOR)):t==at.BLEND_MODES.BLEND_MUL?e?(i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD),i.blendFuncSeparate(i.ZERO,i.SRC_COLOR,i.ZERO,i.SRC_ALPHA)):(i.blendEquation(i.FUNC_ADD),i.blendFunc(i.ZERO,i.SRC_COLOR)):t==at.BLEND_MODES.BLEND_NORMAL?e?(i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD),i.blendFuncSeparate(i.ONE,i.ONE_MINUS_SRC_ALPHA,i.ONE,i.ONE_MINUS_SRC_ALPHA)):(i.blendEquationSeparate(i.FUNC_ADD,i.FUNC_ADD),i.blendFuncSeparate(i.SRC_ALPHA,i.ONE_MINUS_SRC_ALPHA,i.ONE,i.ONE_MINUS_SRC_ALPHA)):this._log.log("setblendmode: unknown blendmode"))},Bt.prototype.createMesh=function(t,e){return new CGL.Mesh(this,t,e)},Bt.prototype.setCursor=function(t){this._cursor=t};const Lt=Object.assign({Framebuffer:function(t,e,i,s){const r=t;this._log=new a("Framebuffer");const n=r.gl.getExtension("WEBGL_depth_texture")||r.gl.getExtension("WEBKIT_WEBGL_depth_texture")||r.gl.getExtension("MOZ_WEBGL_depth_texture")||r.gl.DEPTH_TEXTURE;n||r.exitError("NO_DEPTH_TEXTURE","no depth texture support");let o=e||512,h=i||512;(s=s||{isFloatingPointTexture:!1}).hasOwnProperty("clear")||(s.clear=!0),s.hasOwnProperty("filter")||(s.filter=B.FILTER_LINEAR);const l=new B(r,{isFloatingPointTexture:s.isFloatingPointTexture,filter:s.filter,wrap:s.wrap||B.CLAMP_TO_EDGE});let c=null;n&&(c=new B(r,{isDepthTexture:!0})),this._options=s;const u=r.gl.createFramebuffer(),g=r.gl.createRenderbuffer();this.getWidth=function(){return o},this.getHeight=function(){return h},this.getGlFrameBuffer=function(){return u},this.getDepthRenderBuffer=function(){return g},this.getTextureColor=function(){return l},this.getTextureDepth=function(){return c},this.setFilter=function(t){l.filter=t,l.setSize(o,h)},this.setSize=function(t,e){if(t<2&&(t=2),e<2&&(e=2),o=Math.ceil(t),h=Math.ceil(e),r.profileData.profileFrameBuffercreate++,r.gl.bindFramebuffer(r.gl.FRAMEBUFFER,u),r.gl.bindRenderbuffer(r.gl.RENDERBUFFER,g),l.setSize(o,h),c&&c.setSize(o,h),n&&r.gl.renderbufferStorage(r.gl.RENDERBUFFER,r.gl.DEPTH_COMPONENT16,o,h),r.gl.framebufferTexture2D(r.gl.FRAMEBUFFER,r.gl.COLOR_ATTACHMENT0,r.gl.TEXTURE_2D,l.tex,0),n&&(r.gl.framebufferRenderbuffer(r.gl.FRAMEBUFFER,r.gl.DEPTH_ATTACHMENT,r.gl.RENDERBUFFER,g),r.gl.framebufferTexture2D(r.gl.FRAMEBUFFER,r.gl.DEPTH_ATTACHMENT,r.gl.TEXTURE_2D,c.tex,0)),!r.gl.isFramebuffer(u))throw new Error("Invalid framebuffer");const i=r.gl.checkFramebufferStatus(r.gl.FRAMEBUFFER);switch(i){case r.gl.FRAMEBUFFER_COMPLETE:break;case r.gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:throw this._log.warn("FRAMEBUFFER_INCOMPLETE_ATTACHMENT...",o,h,l.tex,g),new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_ATTACHMENT");case r.gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:throw this._log.warn("FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"),new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");case r.gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:throw this._log.warn("FRAMEBUFFER_INCOMPLETE_DIMENSIONS"),new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_DIMENSIONS");case r.gl.FRAMEBUFFER_UNSUPPORTED:throw this._log.warn("FRAMEBUFFER_UNSUPPORTED"),new Error("Incomplete framebuffer: FRAMEBUFFER_UNSUPPORTED");case 36059:this._log.warn("Incomplete: FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER from ext. Or Safari/iOS undefined behaviour.");break;default:throw this._log.warn("incomplete framebuffer",i),new Error("Incomplete framebuffer: "+i)}r.gl.bindTexture(r.gl.TEXTURE_2D,null),r.gl.bindRenderbuffer(r.gl.RENDERBUFFER,null),r.gl.bindFramebuffer(r.gl.FRAMEBUFFER,null)},this.renderStart=function(){r.pushModelMatrix(),r.gl.bindFramebuffer(r.gl.FRAMEBUFFER,u),r.pushGlFrameBuffer(u),r.pushFrameBuffer(this),r.pushPMatrix(),r.gl.viewport(0,0,o,h),this._options.clear&&(r.gl.clearColor(0,0,0,0),r.gl.clear(r.gl.COLOR_BUFFER_BIT|r.gl.DEPTH_BUFFER_BIT))},this.renderEnd=function(){r.popPMatrix(),r.gl.bindFramebuffer(r.gl.FRAMEBUFFER,r.popGlFrameBuffer()),r.popFrameBuffer(),r.popModelMatrix(),r.resetViewPort()},this.delete=function(){l.delete(),c&&c.delete(),r.gl.deleteRenderbuffer(g),r.gl.deleteFramebuffer(u)},this.setSize(o,h)},Framebuffer2:L,Geometry:W,BoundingBox:z,Marker:function(t){const e=new W("marker");e.setPointVertices([1e-5,0,0,1,0,0,0,1e-5,0,0,1,0,0,0,1e-5,0,0,1]);const i=new lt(t,e,t.gl.LINES);i.setGeom(e);const s=new It(t,"markermaterial"),r="".endl()+"precision highp float;".endl()+"IN vec3 axisColor;".endl()+"void main()".endl()+"{".endl()+" vec4 col=vec4(axisColor,1.0);".endl()+" outColor = col;".endl()+"}",n="".endl()+"IN vec3 vPosition;".endl()+"UNI mat4 projMatrix;".endl()+"UNI mat4 mvMatrix;".endl()+"OUT vec3 axisColor;".endl()+"void main()".endl()+"{".endl()+" vec4 pos=vec4(vPosition, 1.0);".endl()+" if(pos.x!=0.0)axisColor=vec3(1.0,0.3,0.0);".endl()+" if(pos.y!=0.0)axisColor=vec3(0.0,1.0,0.2);".endl()+" if(pos.z!=0.0)axisColor=vec3(0.0,0.5,1.0);".endl()+" gl_Position = projMatrix * mvMatrix * pos;".endl()+"}";s.setSource(n,r),this._vScale=vec3.create(),this.draw=function(t,e,r){const n=e||2;t.pushModelMatrix(),t.pushShader(s),vec3.set(this._vScale,n,n,n),mat4.scale(t.mvMatrix,t.mvMatrix,this._vScale),t.pushDepthTest(1==r),i.render(t.getShader()),t.popDepthTest(),t.popShader(),t.popModelMatrix()}},WirePoint:function(t){const e=t.gl.createBuffer(),i=vec3.create();this.render=function(t,s){t.pushModelMatrix(),vec3.set(i,s,s,s),mat4.scale(t.mvMatrix,t.mvMatrix,i);const r=t.getShader();r&&(r.bind(),t.gl.bindBuffer(t.gl.ARRAY_BUFFER,e),t.gl.vertexAttribPointer(r.getAttrVertexPos(),e.itemSize,t.gl.FLOAT,!1,0,0),t.gl.enableVertexAttribArray(r.getAttrVertexPos()),t.gl.bindBuffer(t.gl.ARRAY_BUFFER,e),t.gl.drawArrays(t.gl.LINE_STRIP,0,e.numItems)),t.popModelMatrix()},function(){const i=[];let s=0,r=0;for(s=0;s<=Math.round(24);s++)r=360/Math.round(24)*s*mt,i.push(.5*Math.cos(r)),i.push(0),i.push(.5*Math.sin(r));for(s=0;s<=Math.round(24);s++)r=360/Math.round(24)*s*mt,i.push(.5*Math.cos(r)),i.push(.5*Math.sin(r)),i.push(0);for(s=0;s<=Math.round(24);s++)r=360/Math.round(24)*s*mt,i.push(0),i.push(.5*Math.cos(r)),i.push(.5*Math.sin(r));t.gl.bindBuffer(t.gl.ARRAY_BUFFER,e),t.gl.bufferData(t.gl.ARRAY_BUFFER,new Float32Array(i),t.gl.STATIC_DRAW),e.itemSize=3,e.numItems=i.length/e.itemSize}()},WireCube:function(t){const e=t.gl.createBuffer(),i=vec3.create();this.render=function(t,s,r,n){t.pushModelMatrix(),vec3.set(i,s||1,r||1,n||1),mat4.scale(t.mvMatrix,t.mvMatrix,i);const o=t.getShader();o&&(o.bind(),t.gl.bindBuffer(t.gl.ARRAY_BUFFER,e),t.gl.vertexAttribPointer(o.getAttrVertexPos(),e.itemSize,t.gl.FLOAT,!1,0,0),t.gl.enableVertexAttribArray(o.getAttrVertexPos()),t.gl.bindBuffer(t.gl.ARRAY_BUFFER,e),t.gl.drawArrays(t.gl.LINE_STRIP,0,e.numItems)),t.popModelMatrix()},function(){const i=[];i.push(-1,-1,1),i.push(1,-1,1),i.push(1,1,1),i.push(-1,1,1),i.push(-1,-1,1),i.push(-1,-1,-1),i.push(1,-1,-1),i.push(1,1,-1),i.push(-1,1,-1),i.push(-1,-1,-1),i.push(-1,-1,-1),i.push(-1,1,-1),i.push(-1,1,1),i.push(-1,-1,1),i.push(-1,-1,-1),i.push(1,-1,-1),i.push(1,1,-1),i.push(1,1,1),i.push(1,-1,1),i.push(1,-1,-1),t.gl.bindBuffer(t.gl.ARRAY_BUFFER,e),t.gl.bufferData(t.gl.ARRAY_BUFFER,new Float32Array(i),t.gl.STATIC_DRAW),e.itemSize=3,e.numItems=i.length/e.itemSize}()},MatrixStack:Mt,Mesh:lt,MESH:ht,ShaderLibMods:pt,Shader:It,Uniform:nt,MESHES:ut,Context:Bt,Texture:B,TextureEffect:gt,isWindows:Et,getWheelSpeed:At,getWheelDelta:bt,onLoadingAssetsFinished:null,ProfileData:St,UniColorShader:class{constructor(t){this.shader=new CGL.Shader(t,"markermaterial");const e="".endl()+"void main()".endl()+"{".endl()+" outColor = vec4(color.rgb,1.0);".endl()+"}",i="".endl()+"IN vec3 vPosition;".endl()+"UNI mat4 projMatrix;".endl()+"UNI mat4 mvMatrix;".endl()+"void main()".endl()+"{".endl()+" gl_Position = projMatrix * mvMatrix * vec4(vPosition,1.0);".endl()+"}";this.shader.setSource(i,e),this.coloruni=this.shader.addUniformFrag("4f","color",[1,.777,1,1])}setColor(t,e,i,s){this.coloruni.set(t,e,i,s)}}},at.BLEND_MODES,at.SHADER,at.MATH,at.BLEND_MODES);window.CGL=Lt;const kt=function(t){Y.apply(this),this.id=CABLES.uuid(),this.portIn=null,this.portOut=null,this.scene=t,this.activityCounter=0,this.ignoreInSerialize=!1};kt.prototype.setValue=function(t){void 0===t?this._setValue():this.portIn.set(t)},kt.prototype.activity=function(){this.activityCounter++},kt.prototype._setValue=function(){if(!this.portOut)return void this.remove();const t=this.portOut.get();t==t&&(this.portIn.type!=l.OP_PORT_TYPE_FUNCTION&&this.activity(),(this.portIn.get()!==t||this.portIn.changeAlways)&&this.portIn.set(t))},kt.prototype.getOtherPort=function(t){return t==this.portIn?this.portOut:this.portIn},kt.prototype.remove=function(){this.portIn&&this.portIn.removeLink(this),this.portOut&&this.portOut.removeLink(this),this.scene&&this.scene.emitEvent("onUnLink",this.portIn,this.portOut,this),!this.portIn||this.portIn.type!=l.OP_PORT_TYPE_OBJECT&&this.portIn.type!=l.OP_PORT_TYPE_ARRAY||(this.portIn.set(null),this.portIn.links.length>0&&this.portIn.set(this.portIn.links[0].getOtherPort(this.portIn).get())),this.portIn&&this.portIn.parent._checkLinksNeededToWork(),this.portOut&&this.portOut.parent._checkLinksNeededToWork(),this.portIn=null,this.portOut=null,this.scene=null},kt.prototype.link=function(t,e){if(!kt.canLink(t,e))return console.warn("[core_link] cannot link ports!",t,e),!1;t.direction==c.PORT_DIR_IN?(this.portIn=t,this.portOut=e):(this.portIn=e,this.portOut=t),t.addLink(this),e.addLink(this),this.setValue(),t.onLink&&t.onLink(this),e.onLink&&e.onLink(this),t.parent._checkLinksNeededToWork(),e.parent._checkLinksNeededToWork()},kt.prototype.getSerialized=function(){const t={};return t.portIn=this.portIn.getName(),t.portOut=this.portOut.getName(),t.objIn=this.portIn.parent.id,t.objOut=this.portOut.parent.id,t},kt.canLinkText=function(t,e){if(t.direction==e.direction){let t="(out)";return e.direction==c.PORT_DIR_IN&&(t="(in)"),"can not link: same direction "+t}return t.parent==e.parent?"can not link: same op":t.type!=l.OP_PORT_TYPE_DYNAMIC&&e.type!=l.OP_PORT_TYPE_DYNAMIC&&t.type!=e.type?"can not link: different type":t?e?t.direction==c.PORT_DIR_IN&&t.isAnimated()||e.direction==c.PORT_DIR_IN&&e.isAnimated()?"can not link: is animated":t.isLinkedTo(e)?"ports already linked":t.canLink&&!t.canLink(e)||e.canLink&&!e.canLink(t)?"Incompatible":"can link":"can not link: port 2 invalid":"can not link: port 1 invalid"},kt.canLink=function(t,e){return!!t&&(!!e&&((t.direction!=c.PORT_DIR_IN||!t.isAnimated())&&((e.direction!=c.PORT_DIR_IN||!e.isAnimated())&&(!t.isHidden()&&!e.isHidden()&&(!t.isLinkedTo(e)&&(t.direction!=e.direction&&((t.type==e.type||t.type==l.OP_PORT_TYPE_DYNAMIC||e.type==l.OP_PORT_TYPE_DYNAMIC)&&(t.type==l.OP_PORT_TYPE_DYNAMIC||e.type==l.OP_PORT_TYPE_DYNAMIC||t.parent!=e.parent&&(!(t.canLink&&!t.canLink(e))&&!(e.canLink&&!e.canLink(t)))))))))))};const Vt=function(){Y.apply(this),this._log=new a("core_op"),this.data={},this.storage={},this.objName="",this.portsOut=[],this.portsIn=[],this.portsInData=[],this.opId="",this.uiAttribs={},this.enabled=!0,this.patch=arguments[0],this.name=arguments[1],this._needsLinkedToWork=[],this._needsParentOp=null,this._shortOpName="",this.hasUiErrors=!1,this._uiErrors={},arguments[1]&&(this._shortOpName=CABLES.getShortOpName(arguments[1]),this.getTitle()),this.id=arguments[2]||T(),this.onAddPort=null,this.onCreate=null,this.onResize=null,this.onLoaded=null,this.onDelete=null,this.onUiAttrChange=null,this.onError=null,this._instances=null,this.preRender=null,this.init=null};{Vt.prototype.clearUiAttrib=function(t){const e={name:null};this.uiAttrib(e)},Vt.prototype.getTitle=function(){return this.uiAttribs?(void 0!==this.uiAttribs.title&&""!==this.uiAttribs.title||-1!=this.objName.indexOf("Ops.Ui.")||(this.uiAttribs.title=this._shortOpName),void 0===this.uiAttribs.title&&(this.uiAttribs.title=this._shortOpName),this.uiAttribs.title):"nouiattribs"+this.name},Vt.prototype.setTitle=function(t){const e=this.name!=t;this.name=t,this.uiAttr({title:t}),e&&this.emitEvent("onTitleChange",t)};const t=function(t){if(!t)return;(t.error||t.warning||t.hint)&&this._log.warn("old ui error/warning attribute in "+this.name+", use op.setUiError !",t),"object"!=typeof t&&this._log.error("op.uiAttrib attribs are not of type object"),this.uiAttribs||(this.uiAttribs={});let e=!1;for(const i in t)this.uiAttribs[i]!=t[i]&&(e=!0),this.uiAttribs[i]=t[i];this.uiAttribs.hasOwnProperty("selected")&&0==this.uiAttribs.selected&&delete this.uiAttribs.selected,t.title&&t.title!=this.name&&this.setTitle(t.title),e&&(this.emitEvent("onUiAttribsChange",t),this.patch.emitEvent("onUiAttribsChange",this,t))};Vt.prototype.setUiAttribs=Vt.prototype.setUiAttrib=Vt.prototype.uiAttr=t,Vt.prototype.getName=function(){return this.uiAttribs.name?this.uiAttribs.name:this.objName.split(".")},Vt.prototype.addOutPort=function(t){return t.direction=c.PORT_DIR_OUT,t.parent=this,this.portsOut.push(t),this.emitEvent("onPortAdd",t),t},Vt.prototype.hasDynamicPort=function(){let t=0;for(t=0;tt==i);n.setValue(t),r.defaultValue=i,n.defaultValue=t}}return r},Vt.prototype.inSwitch=function(t,e,i,s){let r=null;if(s){const i=new et(this,t,l.OP_PORT_TYPE_STRING,{display:"switch",hidePort:!0,type:"string",values:e});r=this.addInPort(i)}else{const s=new et(this,t+" index",l.OP_PORT_TYPE_VALUE,{increment:"integer",hideParam:!0}),n=this.addInPort(s),o=new it(this,t,l.OP_PORT_TYPE_STRING,{display:"switch",hidePort:!0,type:"string",values:e},n);if(s.onLinkChanged=function(){o.setUiAttribs({greyout:s.isLinked()})},r=this.addInPort(o),void 0!==i){r.set(i);const t=e.findIndex(t=>t==i);n.setValue(t),r.defaultValue=i,n.defaultValue=t}}return r},Vt.prototype.inValueInt=Vt.prototype.inInt=function(t,e){const i=this.addInPort(new et(this,t,l.OP_PORT_TYPE_VALUE,{increment:"integer"}));return void 0!==e&&(i.set(e),i.defaultValue=e),i},Vt.prototype.inFile=function(t,e,i){const s=this.addInPort(new et(this,t,l.OP_PORT_TYPE_VALUE,{display:"file",type:"string",filter:e}));return void 0!==i&&(s.set(i),s.defaultValue=i),s},Vt.prototype.inUrl=function(t,e,i){const s=this.addInPort(new et(this,t,l.OP_PORT_TYPE_STRING,{display:"file",type:"string",filter:e}));return void 0!==i&&(s.set(i),s.defaultValue=i),s},Vt.prototype.inTexture=function(t,e){const i=this.addInPort(new et(this,t,l.OP_PORT_TYPE_OBJECT,{display:"texture",objType:"texture",preview:!0}));return void 0!==e&&i.set(e),i},Vt.prototype.inObject=function(t,e,i){const s=this.addInPort(new et(this,t,l.OP_PORT_TYPE_OBJECT,{objType:i}));return void 0!==e&&s.set(e),s},Vt.prototype.inGradient=function(t,e){const i=this.addInPort(new et(this,t,l.OP_PORT_TYPE_VALUE,{display:"gradient",hidePort:!0}));return void 0!==e&&i.set(e),i},Vt.prototype.inArray=function(t,e,i){!i&&CABLES.UTILS.isNumeric(e)&&(i=e);const s=this.addInPort(new et(this,t,l.OP_PORT_TYPE_ARRAY,{stride:i}));return void 0===e||!Array.isArray(e)&&null!=e||s.set(e),s},Vt.prototype.inValueSlider=Vt.prototype.inFloatSlider=function(t,e,i,s){const r={display:"range"};null!=i&&null!=s&&(r.min=i,r.max=s);const n=this.addInPort(new et(this,t,l.OP_PORT_TYPE_VALUE,r));return void 0!==e&&(n.set(e),n.defaultValue=e),n},Vt.prototype.outFunction=Vt.prototype.outTrigger=function(t,e){const i=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_FUNCTION));return void 0!==e&&i.set(e),i},Vt.prototype.outValue=Vt.prototype.outNumber=function(t,e){const i=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_VALUE));return void 0!==e&&i.set(e),i},Vt.prototype.outValueBool=Vt.prototype.outBool=function(t,e){const i=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_VALUE,{display:"bool"}));return void 0!==e?i.set(e):i.set(0),i},Vt.prototype.outBoolNum=function(t,e){const i=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_VALUE,{display:"boolnum"}));return i.set=function(t){this.setValue(t?1:0)}.bind(i),void 0!==e?i.set(e):i.set(0),i},Vt.prototype.outValueString=function(t,e){const i=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_VALUE,{type:"string"}));return void 0!==e&&i.set(e),i},Vt.prototype.outString=function(t,e){const i=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_STRING,{type:"string"}));return void 0!==e?i.set(e):i.set(""),i},Vt.prototype.outObject=function(t,e,i){const s=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_OBJECT,{objType:i||null}));return s.set(e||null),s.ignoreValueSerialize=!0,s},Vt.prototype.outArray=function(t,e,i){!i&&CABLES.UTILS.isNumeric(e)&&(i=e);const s=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_ARRAY,{stride:i}));return void 0===e||!Array.isArray(e)&&null!=e||s.set(e),s.ignoreValueSerialize=!0,s},Vt.prototype.outTexture=function(t,e){const i=this.addOutPort(new et(this,t,l.OP_PORT_TYPE_OBJECT,{preview:!0,objType:"texture"}));return void 0!==e&&i.set(e),i.ignoreValueSerialize=!0,i},Vt.prototype.inDynamic=function(t,e,i,s){const r=new et(this,t,l.OP_PORT_TYPE_DYNAMIC,i);return r.shouldLink=function(t,i){if(e&&g.isArray(e)){for(let s=0;s0&&(t.storage=this.storage),this.uiAttribs.hasOwnProperty("working")&&1==this.uiAttribs.working&&delete this.uiAttribs.working,t.portsIn=[],t.portsOut=[];for(let e=0;e-1&&this._log.warn("setuierror id cant have spaces! ",t),!e&&this._uiErrors.hasOwnProperty(t)?delete this._uiErrors[t]:!e||this._uiErrors.hasOwnProperty(t)&&this._uiErrors[t].txt==e||(null==i&&(i=2),this._uiErrors[t]={txt:e,level:i,id:t});const s=[];for(const t in this._uiErrors)s.push(this._uiErrors[t]);this.uiAttr({uierrors:s}),this.hasUiErrors=Object.keys(this._uiErrors).length,this.emitEvent("uiErrorChange")},Vt.prototype.setError=function(t,e){this._log.warn("old error message op.error() - use op.setUiError()")},Vt.prototype.setEnabled=function(t){this.enabled=t,this.emitEvent("onEnabledChange",t)},Vt.prototype.setPortGroup=function(t,e){for(let i=0;i{e(this._patch),this.emitEvent("finishedAll")},100)}this._wasFinishedPrinted||(this._wasFinishedPrinted=!0,this.print()),this.emitEvent("finishedAll")}},Dt.prototype.getList=function(){let t=[];for(const e in this._loadingAssets)t.push(this._loadingAssets[e]);return t},Dt.prototype.getListJobs=function(){let t=[];for(const e in this._loadingAssets)this._loadingAssets[e].finished||t.push(this._loadingAssets[e].name);return t},Dt.prototype.print=function(){if(this._patch.config.silent)return;const t=[];for(const e in this._loadingAssets)t.push([this._loadingAssets[e].order,this._loadingAssets[e].type,this._loadingAssets[e].name,(this._loadingAssets[e].timeEnd-this._loadingAssets[e].timeStart)/1e3+"s"]);this._log.groupCollapsed("finished loading "+this._order+" assets in "+(Date.now()-this._startTime)/1e3+"s"),this._log.table(t),this._log.groupEnd()},Dt.prototype.finished=function(t){this._loadingAssets[t]&&(this._loadingAssets[t].finished=!0,this._loadingAssets[t].timeEnd=Date.now()),this.checkStatus(),this.emitEvent("finishedTask")},Dt.prototype._startAssetTasks=function(){for(let t=0;t0},Gt.prototype.increment=function(){this._index++},Gt.prototype.index=function(){return this._index};const Ht=function(t){this.startFrame=t.getFrameNum();let e={},i=null,s=0;this.getItems=function(){return e},this.clear=function(){e={}},this.add=function(r,n){null!==i&&(n&&n.id==i||e[i]&&(e[i].timeUsed+=performance.now()-s,(!e[i].peakTime||dt()-e[i].peakTime>5e3)&&(e[i].peak=0,e[i].peakTime=dt()),e[i].peak=Math.max(e[i].peak,performance.now()-s))),null!==n?(e[n.id]||(e[n.id]={numTriggers:0,timeUsed:0}),e[n.id].lastFrame!=t.getFrameNum()&&(e[n.id].numTriggers=0),e[n.id].lastFrame=t.getFrameNum(),e[n.id].numTriggers++,e[n.id].opid=n.parent.id,e[n.id].title=n.parent.name+"."+n.name,e[n.id].subPatch=n.parent.uiAttribs.subPatch,i=n.id,s=performance.now()):i=null},this.print=function(){console.log("--------");for(const t in e)console.log(e[t].title+": "+e[t].numTriggers+" / "+e[t].timeUsed)}};var zt=class extends Y{constructor(t,e,i){super(),this._name=t,this.type=i,this.setValue(e)}addListener(t){this.on("change",t,"var")}getValue(){return this._v}getName(){return this._name}setValue(t){this._v=t,this.emitEvent("change",t,this)}};const Wt=function(t){Y.apply(this),this._log=new a("core_patch"),this.ops=[],this.settings={},this.config=t||{glCanvasResizeToWindow:!1,prefixAssetPath:"",prefixJsPath:"",silent:!0,onError:null,onFinishedLoading:null,onFirstFrameRendered:null,onPatchLoaded:null,fpsLimit:0},this.timer=new ft,this.freeTimer=new ft,this.animFrameOps=[],this.animFrameCallbacks=[],this.gui=!1,CABLES.logSilent=this.silent=!0,this.profiler=null,this.aborted=!1,this._crashedOps=[],this._renderOneFrame=!1,this._animReq=null,this._opIdCache={},this._triggerStack=[],this.loading=new Dt(this),this._volumeListeners=[],this._paused=!1,this._frameNum=0,this.instancing=new Gt,this.onOneFrameRendered=null,this.namedTriggers={},this._origData=null,this._frameNext=0,this._frameInterval=0,this._lastFrameTime=0,this._frameWasdelayed=!0,function(){return!this}()||this._log.warn("not in strict mode: core patch"),this._isLocal=0===document.location.href.indexOf("file:"),this.config.hasOwnProperty("silent")&&(this.silent=CABLES.logSilent=this.config.silent),this.config.hasOwnProperty("doRequestAnimation")||(this.config.doRequestAnimation=!0),this.config.prefixAssetPath||(this.config.prefixAssetPath=""),this.config.prefixJsPath||(this.config.prefixJsPath=""),this.config.masterVolume||(this.config.masterVolume=1),this._variables={},this._variableListeners=[],this.vars={},t&&t.vars&&(this.vars=t.vars),this.cgl=new Bt(this),this.cgp=null,this.cgl.setCanvas(this.config.glCanvasId||this.config.glCanvas||"glcanvas"),!0===this.config.glCanvasResizeToWindow&&this.cgl.setAutoResize("window"),!0===this.config.glCanvasResizeToParent&&this.cgl.setAutoResize("parent"),this.loading.setOnFinishedLoading(this.config.onFinishedLoading),this.cgl.aborted&&(this.aborted=!0),this.cgl.silent&&(this.silent=!0),this.freeTimer.play(),this.exec(),this.aborted||(this.config.patch?this.deSerialize(this.config.patch):this.config.patchFile&&w(this.config.patchFile,(t,e)=>{const i=JSON.parse(e);if(t){return this._log.error("err",t),this._log.error("data",i),void this._log.error("data",i.msg)}this.deSerialize(i)}),this.timer.play()),console.log("made with https://cables.gl")};Wt.prototype.isPlaying=function(){return!this._paused},Wt.prototype.isRenderingOneFrame=function(){return this._renderOneFrame},Wt.prototype.renderOneFrame=function(){this._paused=!0,this._renderOneFrame=!0,this.exec(),this._renderOneFrame=!1},Wt.prototype.getFPS=function(){return console.log("deprecated getfps"),0},Wt.prototype.isEditorMode=function(){return!0===this.config.editorMode},Wt.prototype.pause=function(){cancelAnimationFrame(this._animReq),this.emitEvent("pause"),this._animReq=null,this._paused=!0,this.freeTimer.pause()},Wt.prototype.resume=function(){this._paused&&(cancelAnimationFrame(this._animReq),this._paused=!1,this.freeTimer.play(),this.emitEvent("resume"),this.exec())},Wt.prototype.setVolume=function(t){this.config.masterVolume=t;for(let e=0;e0||document.location.href.indexOf("cables.local")>0){const e=document.location.pathname.split("/");return"/assets/"+(t||e[e.length-1])+"/"}return this.config.hasOwnProperty("assetPath")?this.config.assetPath:"assets/"},Wt.prototype.getJsPath=function(){return this.config.hasOwnProperty("jsPath")?this.config.jsPath:"js/"},Wt.prototype.getFilePath=function(t){return this._isLocal&&!this.config.allowLocalFileAccess&&this.exitError("localAccess","Browser security forbids loading files directly without a webserver. Upload files to a server to work. use allowLocalFileAccess:true to ignore this."),t?0===(t=String(t)).indexOf("https:")||0===t.indexOf("http:")||0===t.indexOf("data:")?t:(t=t.replace("//","/"),this.config.prefixAssetPath+t+(this.config.suffixAssetPath||"")):t},Wt.prototype.clear=function(){for(this.emitEvent("patchClearStart"),this.cgl.TextureEffectMesh=null,this.animFrameOps.length=0,this.timer=new ft;this.ops.length>0;)this.deleteOp(this.ops[0].id);this.emitEvent("patchClearEnd")},Wt.getOpClass=function(t){const e=t.split(".");let i=null;try{return 2==e.length?i=window[e[0]][e[1]]:3==e.length?i=window[e[0]][e[1]][e[2]]:4==e.length?i=window[e[0]][e[1]][e[2]][e[3]]:5==e.length?i=window[e[0]][e[1]][e[2]][e[3]][e[4]]:6==e.length?i=window[e[0]][e[1]][e[2]][e[3]][e[4]][e[5]]:7==e.length?i=window[e[0]][e[1]][e[2]][e[3]][e[4]][e[5]][e[6]]:8==e.length?i=window[e[0]][e[1]][e[2]][e[3]][e[4]][e[5]][e[6]][e[7]]:9==e.length?i=window[e[0]][e[1]][e[2]][e[3]][e[4]][e[5]][e[6]][e[7]][e[8]]:10==e.length&&(i=window[e[0]][e[1]][e[2]][e[3]][e[4]][e[5]][e[6]][e[7]][e[8]][e[9]]),i}catch(t){return null}},Wt.prototype.createOp=function(t,e,i=null){let s=null,r="";try{if(-1===t.indexOf("Ops.")){const n=t;if(CABLES.OPS[n])r=CABLES.OPS[n].objName,s=new CABLES.OPS[n].f(this,r,e,n),s.opId=n;else{if(!i)throw new Error("could not find op by id: "+n);t=i,this._log.warn("could not find op by id: "+n)}}if(!s){r=t;const i=t.split(".");if(!Wt.getOpClass(r))throw this.emitEvent("criticalError",{title:"unknown op",text:"unknown op: "+r}),this._log.error("unknown op: "+r),new Error("unknown op: "+r);if(2==i.length?s=new window[i[0]][i[1]](this,r,e):3==i.length?s=new window[i[0]][i[1]][i[2]](this,r,e):4==i.length?s=new window[i[0]][i[1]][i[2]][i[3]](this,r,e):5==i.length?s=new window[i[0]][i[1]][i[2]][i[3]][i[4]](this,r,e):6==i.length?s=new window[i[0]][i[1]][i[2]][i[3]][i[4]][i[5]](this,r,e):7==i.length?s=new window[i[0]][i[1]][i[2]][i[3]][i[4]][i[5]][i[6]](this,r,e):8==i.length?s=new window[i[0]][i[1]][i[2]][i[3]][i[4]][i[5]][i[6]][i[7]](this,r,e):9==i.length?s=new window[i[0]][i[1]][i[2]][i[3]][i[4]][i[5]][i[6]][i[7]][i[8]](this,r,e):10==i.length?s=new window[i[0]][i[1]][i[2]][i[3]][i[4]][i[5]][i[6]][i[7]][i[8]][i[9]](this,r,e):this._log.warn("parts.length",i.length),s){s.opId=null;for(const t in CABLES.OPS)CABLES.OPS[t].objName==r&&(s.opId=t)}}}catch(t){if(this._crashedOps.push(r),this.emitEvent("exceptionOp",t,r,s),!this.isEditorMode())throw this._log.error(t),this._log.error("[instancing error] "+r,t),CABLES.api&&CABLES.api.sendErrorReport(t),this.exitError("INSTANCE_ERR","Instancing Error "+r,t),new Error("instancing error "+r)}return s?(s.objName=r,s.patch=this):this._log.log("no op was created!?",t,e),s},Wt.prototype.addOp=function(t,e,i,s,r){const n=this.createOp(t,i,r);if(n){if((e=e||{}).hasOwnProperty("errors")&&delete e.errors,e.hasOwnProperty("error")&&delete e.error,e.subPatch=e.subPatch||0,n.uiAttr(e),n.onCreate&&n.onCreate(),n.hasOwnProperty("onAnimFrame")&&this.addOnAnimFrame(n),n.hasOwnProperty("onMasterVolumeChanged")&&this._volumeListeners.push(n),this._opIdCache[n.id])return void this._log.warn("opid with id "+n.id+" already exists in patch!");this.ops.push(n),this._opIdCache[n.id]=n,this.emitEvent("onOpAdd",n,s),n.init&&n.init()}else this._log.error("addop: no op.....");return n},Wt.prototype.addOnAnimFrame=function(t){for(let e=0;e0&&n.portsIn[0].isLinked()&&n.portsOut.length>0&&n.portsOut[0].isLinked()&&n.portsIn[0].getType()==n.portsOut[0].getType()&&n.portsIn[0].links[0]&&(o=n.portsIn[0].links[0].getOtherPort(n.portsIn[0]),a=n.portsOut[0].links[0].getOtherPort(n.portsOut[0]));const h=this.ops[r];h.removeLinks(),h.emitEvent("onDelete",this.ops[r]),this.onDelete&&(this._log.warn("deprecated this.onDelete",this.onDelete),this.onDelete(h)),this.ops.splice(r,1),this.emitEvent("onOpDelete",h,i),h.onDelete&&h.onDelete(i),h.cleanUp(),null!==o&&null!==a&&this.link(o.parent,o.getName(),a.parent,a.getName()),delete this._opIdCache[t];break}}s||this._log.warn("core patch deleteop: not found...")},Wt.prototype.getFrameNum=function(){return this._frameNum},Wt.prototype.emitOnAnimFrameEvent=function(t){t=t||this.timer.getTime();for(let e=0;e=500&&0!==this._lastFrameTime&&!this._frameWasdelayed)return this._lastFrameTime=0,setTimeout(this.exec.bind(this),500),this.emitEvent("renderDelayStart"),void(this._frameWasdelayed=!0);if(this._renderOneFrame||0===this.config.fpsLimit||i>this._frameInterval||this._frameWasdelayed){CABLES.now();this.renderFrame(),this._frameInterval&&(this._frameNext=e-i%this._frameInterval)}this._frameWasdelayed&&(this.emitEvent("renderDelayEnd"),this._frameWasdelayed=!1),this._renderOneFrame&&(this.onOneFrameRendered&&this.onOneFrameRendered(),this.emitEvent("renderedOneFrame"),this._renderOneFrame=!1),this.config.doRequestAnimation&&(this._animReq=requestAnimationFrame(this.exec.bind(this)))},Wt.prototype.link=function(t,e,i,s,r,n){if(!t)return void this._log.warn("link: op1 is null ");if(!i)return void this._log.warn("link: op2 is null");const o=t.getPort(e,r),a=i.getPort(s,r);if(o)if(a){if(!o.shouldLink(o,a)||!a.shouldLink(o,a))return!1;if(kt.canLink(o,a)){const t=new kt(this);return t.link(o,a),this.emitEvent("onLink",o,a,t,n),t}}else this._log.warn("port not found! "+s+" of "+i.name+"("+i.objName+")");else this._log.warn("port not found! "+e+"("+t.objName+")")},Wt.prototype.serialize=function(t){const e={};t=t||{},e.ops=[],e.settings=this.settings;for(const t in this.ops){const i=this.ops[t];e.ops.push(i.getSerialized())}return t.asObject?e:JSON.stringify(e)},Wt.prototype.getOpById=function(t){return this._opIdCache[t]},Wt.prototype.getOpsByName=function(t){const e=[];for(const i in this.ops)this.ops[i].name==t&&e.push(this.ops[i]);return e},Wt.prototype.getOpsByObjName=function(t){const e=[];for(const i in this.ops)this.ops[i].objName==t&&e.push(this.ops[i]);return e},Wt.prototype.loadLib=function(t){C("/ui/libs/"+t+".js",(t,e)=>{const i=document.createElement("script");i.type="text/javascript",i.text=e,document.getElementsByTagName("head")[0].appendChild(i)},"GET")},Wt.prototype.reloadOp=function(t,e){let i=0;const s=[],r=[];for(const e in this.ops)this.ops[e].objName==t&&r.push(this.ops[e]);for(let e=0;e200&&this._log.warn("long op init ",t.ops[s].objName,a)}for(const t in this.ops)this.ops[t].onLoadedValueSet&&(this.ops[t].onLoadedValueSet(this.ops[t]._origData),this.ops[t].onLoadedValueSet=null,this.ops[t]._origData=null),this.ops[t].emitEvent("loadedValueSet");if(t.ops)for(let e=0;e{this.loading.finished(s)},100),this.config.onPatchLoaded&&this.config.onPatchLoaded(this),this.emitEvent("patchLoadEnd",i,t,e)},Wt.prototype.profile=function(t){this.profiler=new Ht(this);for(const e in this.ops)this.ops[e].profile(t)},Wt.prototype.setVariable=function(t,e){void 0!==this._variables[t]?this._variables[t].setValue(e):this._log.warn("variable "+t+" not found!")},Wt.prototype._sortVars=function(){if(!this.isEditorMode())return;const t={};Object.keys(this._variables).sort((t,e)=>t.localeCompare(e,"en",{sensitivity:"base"})).forEach(e=>{t[e]=this._variables[e]}),this._variables=t},Wt.prototype.hasVar=function(t){return void 0!==this._variables[t]},Wt.prototype.setVarValue=function(t,e,i){return this.hasVar(t)?this._variables[t].setValue(e):(this._variables[t]=new zt(t,e,i),this._sortVars(),this.emitEvent("variablesChanged")),this._variables[t]},Wt.prototype.getVarValue=function(t,e){if(this._variables.hasOwnProperty(t))return this._variables[t].getValue()},Wt.prototype.getVar=function(t){if(this._variables.hasOwnProperty(t))return this._variables[t]},Wt.prototype.deleteVar=function(t){for(let e=0;e=i._param.minValue&&e<=i._param.maxValue)try{i.setValueAtTime?i.setValueAtTime(e,s.currentTime):i.value=e}catch(e){throw t.log("Possible AudioParam problem with tone.js op: ",e),e.printStackTrace&&e.printStackTrace(),e}else t.log("Warning: The value for an audio parameter is out of range!");else if(i.minValue&&i.maxValue)if(e>=i.minValue&&e<=i.maxValue)try{i.setValueAtTime?i.setValueAtTime(e,s.currentTime):i.value=e}catch(e){throw t.log("AudioParam has minValue / maxValue defined, and value is in range, but setting the value failed! ",e),e.printStackTrace&&e.printStackTrace(),e}else t.log("Warning: The value for an audio parameter is out of range!");else try{i.setValueAtTime?i.setValueAtTime(e,s.currentTime):i.value=e}catch(e){throw t.log("Possible AudioParam problem (without minValue / maxValue): ",e),e.printStackTrace&&e.printStackTrace(),e}if(n.webAudio.previousAudioInNode&&n.webAudio.previousAudioInNode.disconnect){try{n.webAudio.previousAudioInNode.disconnect(i)}catch(e){throw t.log("Could not disconnect previous audio node: ",e),e}n.webAudio.previousAudioInNode=void 0}}else n.webAudio.previousAudioInNode},n},loadAudioFile:function(t,e,i,s,r){const n=jt.createAudioContext();let o=null;(r||void 0===r)&&(o=t.loading.start("audio",e),t.isEditorMode()&&gui.jobs().start({id:"loadaudio"+o,title:" loading audio ("+e+")"}));const a=new XMLHttpRequest;e&&(a.open("GET",e,!0),a.responseType="arraybuffer",a.onload=function(){t.loading.finished(o),t.isEditorMode()&&gui.jobs().finish("loadaudio"+o),n.decodeAudioData(a.response,i,s)},a.send())},isValidToneTime:function(t){try{new Tone.Time(t)}catch(t){return!1}return!0},isValidToneNote:function(t){try{Tone.Frequency(t)}catch(t){return!1}return!0}},Kt=function(t,e,i){this._patch=t,this.connector=i,this._log=new a("PatchConnectionReceiver")};Kt.prototype._addOp=function(t){let e=null;t.vars.uiAttribs&&(e=t.vars.uiAttribs);const i=this._patch.addOp(t.vars.objName,e,t.vars.opId,!0);i&&(i.id=t.vars.opId,t.vars.portsIn&&t.vars.portsIn.forEach(t=>{const e=i.getPortByName(t.name);e&&e.set(t.value)}))},Kt.prototype._receive=function(t){let e={};if(e=t.hasOwnProperty("event")?t:JSON.parse(t.data),e.event==u.PACO_OP_CREATE){if(this._patch.getOpById(e.vars.opId))return;this._log.verbose("op create:",e.vars.objName),window.gui?gui.serverOps.loadOpLibs(e.vars.objName,()=>{this._addOp(e)}):this._addOp(e)}else if(e.event==u.PACO_DESERIALIZE)e.vars.json&&(window.gui?gui.serverOps.loadProjectDependencies(e.vars.json,()=>{this._patch.deSerialize(e.vars.json,e.vars.genIds)}):this._patch.deSerialize(e.vars.json,e.vars.genIds));else if(e.event==u.PACO_LOAD)this._log.verbose("PACO load patch....."),this._patch.clear(),window.gui?gui.serverOps.loadProjectDependencies(JSON.parse(e.vars.patch),()=>{this._patch.deSerialize(e.vars.patch)}):this._patch.deSerialize(e.vars.patch);else if(e.event==u.PACO_CLEAR)this._patch.clear(),this._log.log("clear");else if(e.event==u.PACO_OP_DELETE){this._log.verbose("op delete",e.vars.objName);this._patch.getOpById(e.vars.op);this._patch.deleteOp(e.vars.op,!0)}else if(e.event==u.PACO_OP_ENABLE){const t=this._patch.getOpById(e.vars.op);t&&(t.enabled=!0)}else if(e.event==u.PACO_OP_DISABLE){const t=this._patch.getOpById(e.vars.op);t&&(t.enabled=!1)}else if(e.event==u.PACO_UIATTRIBS){const t=this._patch.getOpById(e.vars.op);t&&t.setUiAttrib(e.vars.uiAttribs)}else if(e.event==u.PACO_UNLINK){const t=this._patch.getOpById(e.vars.op1),i=this._patch.getOpById(e.vars.op2);if(!t||!i)return;const s=t.getPort(e.vars.port1),r=i.getPort(e.vars.port2);s&&r?s.removeLinkTo(r):this._log.warn("paco unlink could not find port...")}else if(e.event==u.PACO_LINK){const t=this._patch.getOpById(e.vars.op1),i=this._patch.getOpById(e.vars.op2);t&&i&&this._patch.link(t,e.vars.port1,i,e.vars.port2)}else if(e.event==u.PACO_VALUECHANGE){if("+ create new one"===e.vars.v)return;const t=this._patch.getOpById(e.vars.op);if(t){const i=t.getPort(e.vars.port);i&&i.set(e.vars.v)}}else if(e.event==u.PACO_VARIABLES){const t=this._patch.getOpById(e.vars.opId);t&&t.varName&&t.varName.set(e.vars.varName)}else if(e.event==u.PACO_TRIGGERS){const t=this._patch.getOpById(e.vars.opId);t&&t.varName&&t.varName.set(e.vars.varName)}else if(e.event==u.PACO_PORT_SETVARIABLE){const t=this._patch.getOpById(e.vars.opId);if(t){const i=t.getPortByName(e.vars.portName);i&&i.setVariable(e.vars.variableName)}}else if(e.event==u.PACO_PORT_SETANIMATED){const t=this._patch.getOpById(e.vars.opId);if(t){t.portsIn[e.vars.portIndex]&&e.vars.hasOwnProperty("targetState")&&this._patch.emitEvent("pacoPortValueSetAnimated",t,e.vars.portIndex,e.vars.targetState,e.vars.defaultValue)}}else if(e.event==u.PACO_PORT_ANIM_UPDATED){const t=this._patch.getOpById(e.vars.opId);if(t){const i=t.getPortByName(e.vars.portName);if(i){const t=i.getSerialized();t.anim=e.vars.anim,i.anim=null,i.deSerializeSettings(t),this._patch.emitEvent("pacoPortAnimUpdated",i)}}}else this._log.warn("unknown patchConnectionEvent!",t)};const Qt=function(t){this.connectors=[],this.paused=!1,t.addEventListener("onOpDelete",t=>{this.send(CABLES.PACO_OP_DELETE,{op:t.id,objName:t.objName})}),t.addEventListener("patchClearStart",()=>{this.paused=!0}),t.addEventListener("patchClearEnd",()=>{this.paused=!1}),t.addEventListener("patchLoadStart",()=>{this.paused=!0}),t.addEventListener("patchLoadEnd",(t,e,i)=>{this.paused=!1,this.send(CABLES.PACO_DESERIALIZE,{json:e,genIds:i})}),t.addEventListener("onOpAdd",t=>{const e=[];t.portsIn.forEach(t=>{const i={id:t.id,name:t.name,value:t.get()};e.push(i)});let i={};t.uiAttribs&&(i={...t.uiAttribs}),this.send(CABLES.PACO_OP_CREATE,{opId:t.id,objName:t.objName,uiAttribs:i,portsIn:e})}),t.addEventListener("onUnLink",(t,e)=>{this.send(CABLES.PACO_UNLINK,{op1:t.parent.id,op2:e.parent.id,port1:t.getName(),port2:e.getName()})}),t.addEventListener("onUiAttribsChange",(t,e)=>{e&&(delete e.extendTitle,delete e.history,delete e.translate,Object.keys(e).length>0&&this.send(CABLES.PACO_UIATTRIBS,{op:t.id,uiAttribs:e}))}),t.addEventListener("opVariableNameChanged",(t,e)=>{const i={opId:t.id,varName:e};this.send(CABLES.PACO_VARIABLES,i)}),t.addEventListener("opTriggerNameChanged",(t,e)=>{const i={opId:t.id,varName:e};this.send(CABLES.PACO_TRIGGERS,i)}),t.addEventListener("onLink",(t,e)=>{this.send(CABLES.PACO_LINK,{op1:t.parent.id,op2:e.parent.id,port1:t.name,port2:e.name})}),t.addEventListener("portSetVariable",(t,e,i)=>{const s={opId:t.id,portName:e.name,variableName:i};this.send(CABLES.PACO_PORT_SETVARIABLE,s)}),t.addEventListener("portAnimUpdated",(t,e,i)=>{if(t&&e){const s={opId:t.id,portName:e.name,anim:i.getSerialized()};this.send(CABLES.PACO_PORT_ANIM_UPDATED,s)}})};Qt.prototype.send=function(t,e){if(!this.paused&&(t!==CABLES.PACO_VALUECHANGE||"+ create new one"!==e.v))for(let i=0;i 300) + { + firsttime = true; + init(); + } + + lastTime = performance.now(); + + let v = anim.getValue(t); + + result.set(v); + next.trigger(); +}; + + +}; + +Ops.Anim.AnimNumber.prototype = new CABLES.Op(); +CABLES.OPS["e5b0b016-9663-4c9d-9365-f54ae3c5fbb6"]={f:Ops.Anim.AnimNumber,objName:"Ops.Anim.AnimNumber"}; + + + + +// ************************************************************** +// +// Ops.Anim.Bang +// +// ************************************************************** + +Ops.Anim.Bang = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inUpdate = op.inTrigger("update"), + inBang = op.inTriggerButton("Bang"), + inDuration = op.inValue("Duration", 0.1), + invert = op.inBool("Invert", false), + outTrigger = op.outTrigger("Trigger Out"), + outValue = op.outNumber("Value"); + +const anim = new CABLES.Anim(); +let startTime = CABLES.now(); +op.toWorkPortsNeedToBeLinked(inUpdate); + +inBang.onTriggered = function () +{ + startTime = CABLES.now(); + + anim.clear(); + anim.setValue(0, 1); + anim.setValue(inDuration.get(), 0); +}; + +inUpdate.onTriggered = function () +{ + let v = anim.getValue((CABLES.now() - startTime) / 1000); + if (invert.get()) outValue.set(1.0 - v); + else outValue.set(v); + + outTrigger.trigger(); +}; + + +}; + +Ops.Anim.Bang.prototype = new CABLES.Op(); +CABLES.OPS["92ca45a7-5b4b-4238-956e-23d79bdc659f"]={f:Ops.Anim.Bang,objName:"Ops.Anim.Bang"}; + + + + +// ************************************************************** +// +// Ops.Anim.BoolAnim +// +// ************************************************************** + +Ops.Anim.BoolAnim = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const anim = new CABLES.Anim(); + +const + exe = op.inTrigger("exe"), + bool = op.inValueBool("bool"), + pease = anim.createPort(op, "easing"), + duration = op.inValue("duration", 0.5), + dir = op.inValueSelect("Direction", ["Animate Both", "Only True", "Only False"], "Both"), + valueFalse = op.inValue("value false", 0), + valueTrue = op.inValue("value true", 1), + next = op.outTrigger("trigger"), + value = op.outNumber("value"), + finished = op.outBoolNum("finished"), + finishedTrigger = op.outTrigger("Finished Trigger"); + +const startTime = CABLES.now(); +op.toWorkPortsNeedToBeLinked(exe); +op.setPortGroup("Animation", [duration, pease]); +op.setPortGroup("Values", [valueFalse, valueTrue]); + +dir.onChange = bool.onChange = valueFalse.onChange = valueTrue.onChange = duration.onChange = setAnim; +setAnim(); + +function setAnim() +{ + finished.set(false); + const now = (CABLES.now() - startTime) / 1000; + const oldValue = anim.getValue(now); + anim.clear(); + + anim.setValue(now, oldValue); + + if (!bool.get()) + { + if (dir.get() != "Only True") anim.setValue(now + duration.get(), valueFalse.get()); + else anim.setValue(now, valueFalse.get()); + } + else + { + if (dir.get() != "Only False") anim.setValue(now + duration.get(), valueTrue.get()); + else anim.setValue(now, valueTrue.get()); + } +} + +exe.onTriggered = function () +{ + const t = (CABLES.now() - startTime) / 1000; + value.set(anim.getValue(t)); + + if (anim.hasEnded(t)) + { + if (!finished.get()) finishedTrigger.trigger(); + finished.set(true); + } + + next.trigger(); +}; + + +}; + +Ops.Anim.BoolAnim.prototype = new CABLES.Op(); +CABLES.OPS["06ad9d35-ccf5-4d31-889c-e23fa062588a"]={f:Ops.Anim.BoolAnim,objName:"Ops.Anim.BoolAnim"}; + + + + +// ************************************************************** +// +// Ops.Anim.FrameRangeAnimSwitcher +// +// ************************************************************** + +Ops.Anim.FrameRangeAnimSwitcher = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + idx = op.inValueInt("Index"), + inDur = op.inValue("Duration", 0.5), + resultTime1 = op.outNumber("Time 1"), + resultFade = op.outNumber("Time Fade"), + resultTime2 = op.outNumber("Time 2"); + +let anim = new CABLES.Anim(); +anim.createPort(op, "easing"); + +let startTime = 0; +let valuePorts = []; +let oldIdx = -1; + +idx.onChange = setIndex; + +for (let i = 0; i < 10; i++) +{ + let p = op.inValue("Value " + i); + valuePorts.push(p); + p.onChange = update; +} + +setIndex(); + +function update() +{ + if (!valuePorts[oldIdx]) return; + if (!valuePorts[idx.get()]) return; + + resultTime1.set(valuePorts[oldIdx].get()); + resultTime2.set(valuePorts[idx.get()].get()); + let fade = anim.getValue(CABLES.now() / 1000); + resultFade.set(fade); +} + +function setIndex() +{ + let now = (CABLES.now()) / 1000; + let startTime = now; + anim.clear(); + + if (oldIdx == -1)oldIdx = idx.get(); + + anim.setValue(now, 0); + anim.setValue(now + inDur.get(), 1, + function () + { + oldIdx = idx.get(); + let now = (CABLES.now()) / 1000; + anim.setValue(now, 0); + }); + update(); +} + + +}; + +Ops.Anim.FrameRangeAnimSwitcher.prototype = new CABLES.Op(); +CABLES.OPS["d801703b-af5f-4988-af90-39d57706c4b6"]={f:Ops.Anim.FrameRangeAnimSwitcher,objName:"Ops.Anim.FrameRangeAnimSwitcher"}; + + + + +// ************************************************************** +// +// Ops.Anim.FrameRangeAnim_v2 +// +// ************************************************************** + +Ops.Anim.FrameRangeAnim_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let inTime = op.inValue("Time"); +let inStr = op.inString("Frames"); +let inLoop = op.inValueBool("Loop"); +let inRewind = op.inTriggerButton("Rewind"); +let outValue = op.outNumber("result time"); +let outArr = op.outArray("Expanded Frames"); +let finished = op.outBoolNum("Finished", false); +let finishedTrigger = op.outTrigger("Finished Trigger"); +let outAnimLength = op.outNumber("Anim Length"); +let outProgress = op.outNumber("Progress"); + +let anim = new CABLES.Anim(); +let FPS = 30; + +let timeOffset = 0; +inStr.onChange = +inLoop.onChange = parse; + +inRewind.onTriggered = function () +{ + timeOffset = inTime.get(); +}; + +function setupAnim(frames) +{ + anim.clear(); + anim.loop = inLoop.get(); + + for (let i = 0; i < frames.length; i++) + { + anim.defaultEasing = CABLES.ANIM.EASING_ABSOLUTE; + if (i < frames.length - 1) + { + if (frames[i + 1] == frames[i] + 1 || frames[i + 1] == frames[i] - 1) + anim.defaultEasing = CABLES.ANIM.EASING_LINEAR; + } + + anim.setValue(i / FPS, frames[i] / FPS); + } +} + +function parse() +{ + let str = inStr.get(); + let frames = []; + let parts = str.split(","); + + for (let i = 0; i < parts.length; i++) + { + if (CABLES.UTILS.isNumeric(parts[i])) + { + frames.push(parseInt(parts[i], 10)); + } + else if (parts[i].indexOf("-") > -1) + { + let r = parts[i].split("-"); + r[0] = parseInt(r[0], 10); + r[1] = parseInt(r[1], 10); + + if (r[1] > r[0]) + for (var j = r[0]; j <= r[1]; j++) frames.push(j); + else + for (var j = r[0]; j >= r[1]; j--) frames.push(j); + } + } + + outArr.set(null); + outArr.set(frames); + outAnimLength.set(frames.length / FPS); + setupAnim(frames); +} + +inTime.onChange = function () +{ + let t = inTime.get() - timeOffset; + outValue.set(anim.getValue(t)); + + if (anim.keys.length > 1) + { + let l = anim.keys[anim.keys.length - 1].time - anim.keys[0].time; + let p = (t % l) / (l); + if (!inLoop.get()) p = Math.min(t / l, 1); + outProgress.set(p); + } + + if (anim.hasEnded(t)) + { + if (!finished.get()) finishedTrigger.trigger(); + finished.set(true); + } + else + { + finished.set(false); + } +}; + + +}; + +Ops.Anim.FrameRangeAnim_v2.prototype = new CABLES.Op(); +CABLES.OPS["c0613f9e-5ddb-479e-bc90-4ffc23f97860"]={f:Ops.Anim.FrameRangeAnim_v2,objName:"Ops.Anim.FrameRangeAnim_v2"}; + + + + +// ************************************************************** +// +// Ops.Anim.InOutInAnim +// +// ************************************************************** + +Ops.Anim.InOutInAnim = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const anim = new CABLES.Anim(); + +const + update = op.inTrigger("Update"), + duration1 = op.inValue("Duration Out", 0.25), + easing1 = anim.createPort(op, "Easing Out"), + value1 = op.inValue("Value Out", 0), + holdDuration = op.inValue("Hold duration", 0.0), + duration2 = op.inValue("Duration In", 0.25), + easing2 = anim.createPort(op, "Easing In"), + value2 = op.inValue("Value In", 1), + trigger = op.inTriggerButton("Start"), + next = op.outTrigger("Next"), + outVal = op.outNumber("Result", 0), + started = op.outTrigger("Started"), + middle = op.outTrigger("Middle"), + finished = op.outTrigger("finished"); + +let time = 0; +trigger.onTriggered = setupAnim; + +update.onTriggered = function () +{ + time = CABLES.now() / 1000.0; + if (anim.isStarted(time)) outVal.set(anim.getValue(time)); + else outVal.set(value2.get()); + + next.trigger(); +}; + +value2.onChange = function () +{ + outVal.set(value2.get()); +}; + +function setupAnim() +{ + anim.clear(); + // start + anim.setValue(time, value2.get(), function () + { + started.trigger(); + }); + // attack + anim.setValue(time + + duration1.get(), value1.get(), function () + { + + }); + // Hold + anim.setValue(time + + duration1.get() + holdDuration.get(), value1.get(), function () + { + middle.trigger(); + }); + // release + anim.setValue(time + + duration1.get() + + duration2.get() + holdDuration.get(), value2.get(), function () + { + finished.trigger(); + }); + + anim.keys[0].setEasing( + anim.easingFromString(easing1.get())); + + anim.keys[2].setEasing( + anim.easingFromString(easing2.get())); +} + + +}; + +Ops.Anim.InOutInAnim.prototype = new CABLES.Op(); +CABLES.OPS["ae46d30d-9ea6-417b-968b-e7b5726afdde"]={f:Ops.Anim.InOutInAnim,objName:"Ops.Anim.InOutInAnim"}; + + + + +// ************************************************************** +// +// Ops.Anim.LFO +// +// ************************************************************** + +Ops.Anim.LFO = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + time = op.inValue("Time"), + type = op.inValueSelect("Type", ["sine", "triangle", "ramp up", "ramp down", "block"], "sine"), + phase = op.inValue("Phase", 0), + amplitude = op.inValue("Amplitude", 1), + result = op.outNumber("Result"); + +let v = 0; +type.onChange = updateType; + +updateType(); + +const PI2 = Math.PI / 2; + +function updateType() +{ + if (type.get() == "sine") time.onChange = sine; + if (type.get() == "ramp up") time.onChange = rampUp; + if (type.get() == "ramp down") time.onChange = rampDown; + if (type.get() == "block") time.onChange = block; + if (type.get() == "triangle") time.onChange = triangle; +} + +function updateTime() +{ + return time.get() + phase.get(); +} + +function block() +{ + let t = updateTime() + 0.5; + v = t % 2.0; + if (v <= 1.0)v = -1; + else v = 1; + v *= amplitude.get(); + result.set(v); +} + +function rampUp() +{ + let t = (updateTime() + 1); + t *= 0.5; + v = t % 1.0; + v -= 0.5; + v *= 2.0; + v *= amplitude.get(); + result.set(v); +} + +function rampDown() +{ + let t = updateTime(); + v = t % 1.0; + v -= 0.5; + v *= -2.0; + v *= amplitude.get(); + result.set(v); +} + +function triangle() +{ + let t = updateTime(); + v = t % 2.0; + if (v > 1) v = 2.0 - v; + v -= 0.5; + v *= 2.0; + v *= amplitude.get(); + result.set(v); +} + +function sine() +{ + let t = updateTime() * Math.PI - (PI2); + v = Math.sin((t)); + v *= amplitude.get(); + result.set(v); +} + + +}; + +Ops.Anim.LFO.prototype = new CABLES.Op(); +CABLES.OPS["559bb980-78fb-47a7-a199-16f10808b150"]={f:Ops.Anim.LFO,objName:"Ops.Anim.LFO"}; + + + + +// ************************************************************** +// +// Ops.Anim.RandomAnim +// +// ************************************************************** + +Ops.Anim.RandomAnim = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + + min = op.inValue("min", 0), + max = op.inValue("max", 1), + seed = op.inValue("random seed", 0), + + duration = op.inValue("duration", 0.5), + pause = op.inValue("pause between", 0), + next = op.outTrigger("Next"), + result = op.outNumber("result"), + looped = op.outTrigger("Looped"); + +const anim = new CABLES.Anim(); +anim.createPort(op, "easing", reinit); + +op.setPortGroup("Timing", [duration, pause]); +op.setPortGroup("Value", [min, max, seed]); + +op.toWorkPortsNeedToBeLinked(exe); + +let counter = 0; + +min.onChange = + max.onChange = + pause.onChange = + seed.onChange = + duration.onChange = reinitLater; + +let needsReinit = true; + +function reinitLater() +{ + needsReinit = true; +} + +function getRandom() +{ + const minVal = (min.get()); + return Math.seededRandom() * (max.get() - minVal) + minVal; +} + +function reinit() +{ + Math.randomSeed = seed.get() + counter * 100; + init(getRandom()); + needsReinit = false; +} + +function init(v) +{ + anim.clear(); + + anim.setValue(CABLES.now() / 1000.0, v); + if (pause.get() !== 0.0) anim.setValue(CABLES.now() / 1000.0 + pause.get(), v); + + anim.setValue(duration.get() + CABLES.now() / 1000.0 + pause.get(), getRandom()); +} + +exe.onTriggered = updateExe; + +function updateExe() +{ + if (needsReinit)reinit(); + + const t = CABLES.now() / 1000.0; + const v = anim.getValue(t); + + if (anim.hasEnded(t)) + { + counter++; + anim.clear(); + init(v); + looped.trigger(); + } + result.set(v); + next.trigger(); +} + + +}; + +Ops.Anim.RandomAnim.prototype = new CABLES.Op(); +CABLES.OPS["2d2e5f0e-b69f-4789-9a48-1ee6ade5049a"]={f:Ops.Anim.RandomAnim,objName:"Ops.Anim.RandomAnim"}; + + + + +// ************************************************************** +// +// Ops.Anim.SimpleAnim +// +// ************************************************************** + +Ops.Anim.SimpleAnim = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + reset = op.inTriggerButton("reset"), + rewind = op.inTriggerButton("rewind"), + inStart = op.inValueFloat("start", 0), + inEnd = op.inValueFloat("end", 1), + duration = op.inValueFloat("duration", 0.5), + loop = op.inValueBool("loop"), + waitForReset = op.inValueBool("Wait for Reset", true), + next = op.outTrigger("Next"), + result = op.outNumber("result"), + finished = op.outNumber("finished"), + finishedTrigger = op.outTrigger("Finished Trigger"); + +const anim = new CABLES.Anim(); +let resetted = false; +anim.createPort(op, "easing", init); +let currentEasing = -1; +loop.onChange = init; +init(); + +duration.onChange = init; + + +function init() +{ + if (anim.keys.length != 3) + { + anim.setValue(0, 0); + anim.setValue(1, 0); + anim.setValue(2, 0); + } + + anim.keys[0].time = CABLES.now() / 1000.0; + anim.keys[0].value = inStart.get(); + if (anim.defaultEasing != currentEasing) anim.keys[0].setEasing(anim.defaultEasing); + + anim.keys[1].time = duration.get() + CABLES.now() / 1000.0; + anim.keys[1].value = inEnd.get(); + + if (anim.defaultEasing != currentEasing) anim.keys[1].setEasing(anim.defaultEasing); + + anim.loop = loop.get(); + if (anim.loop) + { + anim.keys[2].time = (2.0 * duration.get()) + CABLES.now() / 1000.0; + anim.keys[2].value = inStart.get(); + if (anim.defaultEasing != currentEasing) anim.keys[2].setEasing(anim.defaultEasing); + } + else + { + anim.keys[2].time = anim.keys[1].time; + anim.keys[2].value = anim.keys[1].value; + if (anim.defaultEasing != currentEasing) anim.keys[2].setEasing(anim.defaultEasing); + } + finished.set(false); + + currentEasing = anim.defaultEasing; +} + +reset.onTriggered = function () +{ + resetted = true; + init(); +}; + +rewind.onTriggered = function () +{ + anim.keys[0].time = CABLES.now() / 1000.0; + anim.keys[0].value = inStart.get(); + + anim.keys[1].time = CABLES.now() / 1000.0; + anim.keys[1].value = inStart.get(); + + anim.keys[2].time = CABLES.now() / 1000.0; + anim.keys[2].value = inStart.get(); + + result.set(inStart.get()); +}; + +exe.onTriggered = function () +{ + if (waitForReset.get() && !resetted) + { + result.set(inStart.get()); + return; + } + let t = CABLES.now() / 1000; + let v = anim.getValue(t); + result.set(v); + if (anim.hasEnded(t)) + { + if (!finished.get()) finishedTrigger.trigger(); + finished.set(true); + } + + next.trigger(); +}; + + +}; + +Ops.Anim.SimpleAnim.prototype = new CABLES.Op(); +CABLES.OPS["5b244b6e-c505-4743-b2cc-8119ef720028"]={f:Ops.Anim.SimpleAnim,objName:"Ops.Anim.SimpleAnim"}; + + + + +// ************************************************************** +// +// Ops.Anim.SineAnim +// +// ************************************************************** + +Ops.Anim.SineAnim = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + mode = op.inSwitch("Mode", ["Sine", "Cosine"], "Sine"), + phase = op.inValueFloat("phase", 0), + mul = op.inValueFloat("frequency", 1), + amplitude = op.inValueFloat("amplitude", 1), + trigOut = op.outTrigger("Trigger out"), + result = op.outNumber("result"); + +let selectIndex = 0; +const SINE = 0; +const COSINE = 1; + +op.toWorkPortsNeedToBeLinked(exe); + +exe.onTriggered = exec; +mode.onChange = onModeChange; + +exec(); +onModeChange(); + +function onModeChange() +{ + let modeSelectValue = mode.get(); + + if (modeSelectValue === "Sine") selectIndex = SINE; + else if (modeSelectValue === "Cosine") selectIndex = COSINE; + + exec(); +} + +function exec() +{ + if (selectIndex == SINE) result.set(amplitude.get() * Math.sin((op.patch.freeTimer.get() * mul.get()) + phase.get())); + else result.set(amplitude.get() * Math.cos((op.patch.freeTimer.get() * mul.get()) + phase.get())); + trigOut.trigger(); +} + + +}; + +Ops.Anim.SineAnim.prototype = new CABLES.Op(); +CABLES.OPS["736d3d0e-c920-449e-ade0-f5ca6018fb5c"]={f:Ops.Anim.SineAnim,objName:"Ops.Anim.SineAnim"}; + + + + +// ************************************************************** +// +// Ops.Anim.Smooth +// +// ************************************************************** + +Ops.Anim.Smooth = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Update"), + inMode = op.inBool("Separate inc/dec", false), + inVal = op.inValue("Value"), + next = op.outTrigger("Next"), + inDivisorUp = op.inValue("Inc factor", 4), + inDivisorDown = op.inValue("Dec factor", 4), + result = op.outNumber("Result", 0); + +let val = 0; +let goal = 0; +let oldVal = 0; +let lastTrigger = 0; + +op.toWorkPortsNeedToBeLinked(exec); + +let divisorUp; +let divisorDown; +let divisor = 4; +let finished = true; + +let selectIndex = 0; +const MODE_SINGLE = 0; +const MODE_UP_DOWN = 1; + +onFilterChange(); +getDivisors(); + +inMode.setUiAttribs({ "hidePort": true }); + +inDivisorUp.onChange = inDivisorDown.onChange = getDivisors; +inMode.onChange = onFilterChange; +update(); + +function onFilterChange() +{ + const selectedMode = inMode.get(); + if (!selectedMode) selectIndex = MODE_SINGLE; + else selectIndex = MODE_UP_DOWN; + + if (selectIndex == MODE_SINGLE) + { + inDivisorDown.setUiAttribs({ "greyout": true }); + inDivisorUp.setUiAttribs({ "title": "Inc/Dec factor" }); + } + else if (selectIndex == MODE_UP_DOWN) + { + inDivisorDown.setUiAttribs({ "greyout": false }); + inDivisorUp.setUiAttribs({ "title": "Inc factor" }); + } + + getDivisors(); + update(); +} + +function getDivisors() +{ + if (selectIndex == MODE_SINGLE) + { + divisorUp = inDivisorUp.get(); + divisorDown = inDivisorUp.get(); + } + else if (selectIndex == MODE_UP_DOWN) + { + divisorUp = inDivisorUp.get(); + divisorDown = inDivisorDown.get(); + } + + if (divisorUp <= 0.2 || divisorUp != divisorUp)divisorUp = 0.2; + if (divisorDown <= 0.2 || divisorDown != divisorDown)divisorDown = 0.2; +} + +inVal.onChange = function () +{ + finished = false; + let oldGoal = goal; + goal = inVal.get(); +}; + +inDivisorUp.onChange = function () +{ + getDivisors(); +}; + +function update() +{ + let tm = 1; + if (performance.now() - lastTrigger > 500 || lastTrigger === 0) val = inVal.get() || 0; + else tm = (performance.now() - lastTrigger) / (performance.now() - lastTrigger); + lastTrigger = performance.now(); + + if (val != val)val = 0; + + if (divisor <= 0)divisor = 0.0001; + + const diff = goal - val; + + if (diff >= 0) val += (diff) / (divisorDown * tm); + else val += (diff) / (divisorUp * tm); + + if (Math.abs(diff) < 0.00001)val = goal; + + if (divisor != divisor)val = 0; + if (val != val || val == -Infinity || val == Infinity)val = inVal.get(); + + if (oldVal != val) + { + result.set(val); + oldVal = val; + } + + if (val == goal && !finished) + { + finished = true; + result.set(val); + } + + next.trigger(); +} + +exec.onTriggered = function () +{ + update(); +}; + + +}; + +Ops.Anim.Smooth.prototype = new CABLES.Op(); +CABLES.OPS["5677b5b5-753a-4fbf-9e91-64c81ec68a2f"]={f:Ops.Anim.Smooth,objName:"Ops.Anim.Smooth"}; + + + + +// ************************************************************** +// +// Ops.Anim.Snap +// +// ************************************************************** + +Ops.Anim.Snap = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inVal = op.inValue("Delta"), + + snapVals = op.inArray("Snap at Values"), + snapDist = op.inValue("Snap Distance"), + snapDistRelease = op.inValue("Snap Distance Release"), + inSlow = op.inValue("Slowdown", 0.4), + inBlock = op.inValue("Block Input after snap"), + inReset = op.inTriggerButton("Reset"), + inMin = op.inValue("Min", 0), + inMax = op.inValue("Max", 0), + + inMul = op.inValue("Value Mul", 1), + inEnabled = op.inValueBool("Enabled", true), + + outVal = op.outNumber("Result"), + outDist = op.outNumber("Distance"), + outSnapped = op.outBoolNum("Snapped"), + outWasSnapped = op.outBoolNum("was snapped"); + +inVal.onChange = update; +inVal.changeAlways = true; + +let snapped = false; +let val = 0; +let hasError = false; +let timeout = 0; +let blocking = false; +let lastValue = -1; +let snappedArr = []; + +snapVals.onChange = checkError; + +inReset.onTriggered = function () +{ + val = 0; + outVal.set(val); + // update(); +}; + +function checkError() +{ + let snaps = snapVals.get(); + if (!snaps || snaps.length == 0) + { + op.setUiError("snapsnull", "needs array containing snap points"); + hasError = true; + return; + } + + if (hasError) + { + op.setUiError("snapsnull", null); + hasError = false; + setTimeout(update, 500); + } + + snappedArr = []; + for (let i = 0; i < snapVals.length; i++) + { + snappedArr[i] = false; + } +} + +function update() +{ + if (blocking) return; + let snaps = snapVals.get(); + + let d = 999999999; + let snapvalue = 0; + let currentIndex = -1; + + for (let i = 0; i < snaps.length; i++) + { + let dd = Math.abs(val - snaps[i]) + 0.01; + if (dd < d) + { + d = dd; + snapvalue = snaps[i]; + currentIndex = i; + } + + if (val > snaps[i] && !snappedArr[i]) + { + val = snaps[i]; + d = 0; + currentIndex = i; + } + } + + if (d === 0) return; + if (inVal.get() === 0) return; + + if (d < snapDistRelease.get()) + { + let vv = inVal.get() * Math.abs(((d / snapDistRelease.get()) * inSlow.get())) * inMul.get(); + val += vv; + + clearTimeout(timeout); + + timeout = setTimeout(function () + { + val = snapvalue; + outVal.set(val); + }, 250); + } + else + { + clearTimeout(timeout); + val += inVal.get(); + } + + if (!inEnabled.get()) + { + outVal.set(val); + lastValue = val; + } + + inVal.set(0); + + d = Math.abs(val - snapvalue); + outDist.set(d); + let wassnapped = false; + + if (d > snapDist.get()) + { + snapped = false; + wassnapped = false; + } + + if (!snapped) + { + if (d < snapDist.get()) + { + val = snapvalue; + if (inBlock.get() > 0) + { + blocking = true; + setTimeout(function () + { + blocking = false; + }, inBlock.get() * 1000); + } + snappedArr[currentIndex] = true; + snapped = true; + wassnapped = true; + } + else + { + snapped = false; + } + } + + outSnapped.set(snapped); + outWasSnapped.set(wassnapped); + + if (inMax.get() != inMin.get() != 0) + { + if (val > inMax.get())val = inMax.get(); + else if (val < inMin.get())val = inMin.get(); + } + + outVal.set(val); + lastValue = val; +} + + +}; + +Ops.Anim.Snap.prototype = new CABLES.Op(); +CABLES.OPS["7319d30d-bce2-4e66-8143-e4c0ff5a37a2"]={f:Ops.Anim.Snap,objName:"Ops.Anim.Snap"}; + + + + +// ************************************************************** +// +// Ops.Anim.StringTypeAnimation_v2 +// +// ************************************************************** + +Ops.Anim.StringTypeAnimation_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let text = op.inStringEditor("text", "hello world"); +let inRestart = op.inTriggerButton("Restart"); +let speed = op.inValue("Speed", 500); +let speedVariation = op.inValueSlider("Speed Variation"); +const showCursor = op.inBool("Show Cursor", true); + +let outText = op.outString("Result"); +let outChanged = op.outTrigger("Changed"); +let outFinished = op.outTrigger("Finished"); + +outText.set(" \n "); +let pos = 0; +let updateInterval = 0; +let cursorblink = true; +let finished = false; + +function setNewTimeout() +{ + clearTimeout(updateInterval); + let ms = speed.get() * (Math.random() * (speedVariation.get() * 2 - 1)); + if (text.get() && pos > text.get().length)ms = speed.get(); + updateInterval = setTimeout(update, speed.get() + ms); +} + +inRestart.onTriggered = function () +{ + finished = false; + pos = 0; + setNewTimeout(); +}; + +function update() +{ + if (!text.get() || text.get() === "" || text.get() === "0" || text.get() == "0") + { + outText.set(" "); + return; + } + + let t = text.get().substring(0, pos); + cursorblink = !cursorblink; + + if (pos > text.get().length && cursorblink) + { + if (showCursor.get()) + { + // t+=' '; + // pos++; + } + + if (!finished) + { + outFinished.trigger(); + finished = true; + } + } + else + { + finished = false; + if (showCursor.get()) + { + t += "_"; + } + pos++; + } + + outText.set(t); + outChanged.trigger(); + setNewTimeout(); +} + +text.onChange = function () +{ + finished = false; + pos = 0; + setNewTimeout(); + outText.set(""); +}; + + +}; + +Ops.Anim.StringTypeAnimation_v2.prototype = new CABLES.Op(); +CABLES.OPS["66723fea-7d5f-4509-98fc-8d892a8f8d89"]={f:Ops.Anim.StringTypeAnimation_v2,objName:"Ops.Anim.StringTypeAnimation_v2"}; + + + + +// ************************************************************** +// +// Ops.Anim.TimeDelta +// +// ************************************************************** + +Ops.Anim.TimeDelta = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTriggerButton("exe"), + smooth = op.inValueBool("Smooth", false), + seconds = op.inValueBool("Seconds", false), + trigger = op.outTrigger("trigger"), + result = op.outNumber("result"); + +let lastTime = CABLES.now(); +let diff = 0; +let smoothed = -1; + +exe.onTriggered = function () +{ + diff = (CABLES.now() - lastTime); + if (seconds.get()) diff /= 1000; + + if (smooth.get()) + { + if (smoothed == -1)smoothed = diff; + else + { + smoothed = smoothed * 0.8 + diff * 0.2; + diff = smoothed; + } + } + + result.set(diff); + lastTime = CABLES.now(); + trigger.trigger(); +}; + +exe.onTriggered(); + + +}; + +Ops.Anim.TimeDelta.prototype = new CABLES.Op(); +CABLES.OPS["fba0e516-b50e-4372-9a0c-dc605669ffed"]={f:Ops.Anim.TimeDelta,objName:"Ops.Anim.TimeDelta"}; + + + + +// ************************************************************** +// +// Ops.Anim.Timer_v2 +// +// ************************************************************** + +Ops.Anim.Timer_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inSpeed = op.inValue("Speed", 1), + playPause = op.inValueBool("Play", true), + reset = op.inTriggerButton("Reset"), + inSyncTimeline = op.inValueBool("Sync to timeline", false), + outTime = op.outNumber("Time"); + +op.setPortGroup("Controls", [playPause, reset, inSpeed]); + +const timer = new CABLES.Timer(); +let lastTime = null; +let time = 0; +let syncTimeline = false; + +playPause.onChange = setState; +setState(); + +function setState() +{ + if (playPause.get()) + { + timer.play(); + op.patch.addOnAnimFrame(op); + } + else + { + timer.pause(); + op.patch.removeOnAnimFrame(op); + } +} + +reset.onTriggered = doReset; + +function doReset() +{ + time = 0; + lastTime = null; + timer.setTime(0); + outTime.set(0); +} + +inSyncTimeline.onChange = function () +{ + syncTimeline = inSyncTimeline.get(); + playPause.setUiAttribs({ "greyout": syncTimeline }); + reset.setUiAttribs({ "greyout": syncTimeline }); +}; + +op.onAnimFrame = function (tt) +{ + if (timer.isPlaying()) + { + if (CABLES.overwriteTime !== undefined) + { + outTime.set(CABLES.overwriteTime * inSpeed.get()); + } + else + + if (syncTimeline) + { + outTime.set(tt * inSpeed.get()); + } + else + { + timer.update(); + const timerVal = timer.get(); + + if (lastTime === null) + { + lastTime = timerVal; + return; + } + + const t = Math.abs(timerVal - lastTime); + lastTime = timerVal; + + time += t * inSpeed.get(); + if (time != time)time = 0; + outTime.set(time); + } + } +}; + + +}; + +Ops.Anim.Timer_v2.prototype = new CABLES.Op(); +CABLES.OPS["aac7f721-208f-411a-adb3-79adae2e471a"]={f:Ops.Anim.Timer_v2,objName:"Ops.Anim.Timer_v2"}; + + + + +// ************************************************************** +// +// Ops.Api.FxHash.FxHash +// +// ************************************************************** + +Ops.Api.FxHash.FxHash = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +if (!CABLES.fakefxhash && !window.fxhash || CABLES.fakefxhash) +{ + CABLES.fakefxhash = true; +} + +const + isReal = !CABLES.fakefxhash, + alphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"; + +const + inHash = op.inString("Hash", ""), + inRandomizeHash = op.inTriggerButton("Randomize Hash"), + outHash = op.outString("fxhash"), + outRandom1 = op.outNumber("fxrand 1"), + outRandom2 = op.outNumber("fxrand 2"), + outRandom3 = op.outNumber("fxrand 3"), + outRandom4 = op.outNumber("fxrand 4"), + outArr = op.outArray("Random Numbers"), + outEmbedded = op.outBoolNum("fxhash environment", isReal); + +inHash.onChange = init; + +let inited = false; + +init(); + +inRandomizeHash.onTriggered = () => +{ + inHash.set(randomHash()); + op.refreshParams(); +}; + +function randomHash() +{ + let str = ""; + const all = alphabet.length - 1; + + for (let i = 0; i < 51; i++) + { + str += alphabet[Math.round(Math.random() * all)]; + } + return str; +} + +function init() +{ + if (isReal && inited) return; + if (!isReal) + { + window.fxhash = inHash.get() || randomHash(); + let b58dec = (str) => [...str].reduce((p, c) => p * alphabet.length + alphabet.indexOf(c) | 0, 0); + let fxhashTrunc = fxhash.slice(2); + let regex = new RegExp(".{" + ((fxhash.length / 4) | 0) + "}", "g"); + let hashes = fxhashTrunc.match(regex).map((h) => b58dec(h)); + + let sfc32 = (a, b, c, d) => + () => + { + a |= 0; b |= 0; c |= 0; d |= 0; + let t = (a + b | 0) + d | 0; + d = d + 1 | 0; + a = b ^ b >>> 9; + b = c + (c << 3) | 0; + c = c << 21 | c >>> 11; + c = c + t | 0; + return (t >>> 0) / 4294967296; + }; + + window.fxrand = sfc32(...hashes); + } + + inited = true; + + outHash.set(window.fxhash); + + outRandom1.set(0); + outRandom2.set(0); + outRandom3.set(0); + outRandom4.set(0); + + outRandom1.set(fxrand()); + outRandom2.set(fxrand()); + outRandom3.set(fxrand()); + outRandom4.set(fxrand()); + + const arr = []; + for (let i = 0; i < 1000; i++)arr.push(fxrand()); + outArr.set(arr); +} + + +}; + +Ops.Api.FxHash.FxHash.prototype = new CABLES.Op(); +CABLES.OPS["090355fe-6ad9-457c-8192-9e306a9fe1eb"]={f:Ops.Api.FxHash.FxHash,objName:"Ops.Api.FxHash.FxHash"}; + + + + +// ************************************************************** +// +// Ops.Api.SoundCloud.SoundCloud_v2 +// +// ************************************************************** + +Ops.Api.SoundCloud.SoundCloud_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + soundCloudUrl = op.inString("SoundCloud URL"), + clientId = op.inString("SoundCloud Client Id", "6f693b837b47b59a17403e79bcff3626"), + clientSecret = op.inString("SoundCloud Client Secret", "efdeff51dee9e7357e2a4394b49d340a"), + streamFormats = op.inDropDown("Formats", []), + streamUrl = op.outString("Stream URL"), + artworkUrl = op.outString("Artwork URL"), + title = op.outString("Title"), + result = op.outObject("Result"); + +streamUrl.ignoreValueSerialize = true; +artworkUrl.ignoreValueSerialize = true; +streamUrl.ignoreValueSerialize = true; +title.ignoreValueSerialize = true; +soundCloudUrl.onChange = streamFormats.onChange = resolve; + +let accessToken = null; + +const fetchData = (token) => +{ + op.setUiError("error", null); + + const baseUrl = "https://api.soundcloud.com"; + const resolveUrl = baseUrl + "/resolve.json?url=" + soundCloudUrl.get(); + fetch(resolveUrl, { + "headers": { + "Authorization": "OAuth " + token + } + }).then((response) => { return response.json(); }).then((data) => + { + const trackUrl = baseUrl + "/tracks/" + data.id + "/streams"; + fetch(trackUrl, { + "headers": { + "Authorization": "OAuth " + token + } + }).then((response) => { return response.json(); }).then((trackData) => + { + const availableFormats = Object.keys(trackData); + streamFormats.setUiAttribs({ "values": availableFormats }); + let formatUrl = trackData[availableFormats[0]]; + if (streamFormats.get() && trackData.hasOwnProperty(streamFormats.get())) + { + formatUrl = trackData[streamFormats.get()]; + } + try + { + streamUrl.set(formatUrl); + artworkUrl.set(data.artwork_url); + title.set(data.title); + result.set(data); + } + catch (e) + { + op.setUiError("error", "failed to load track from soundcloud"); + op.logError(e); + } + }); + }); +}; + +function resolve() +{ + op.setUiError("credentials", null); + if (!clientId.get() || !clientSecret.get()) + { + op.setUiError("credentials", "SoundClound credentials missing - provide client id and secret"); + } + if (soundCloudUrl.get()) + { + fetch("https://api.soundcloud.com/oauth2/token", { + "method": "POST", + "headers": { + "Content-Type": "application/x-www-form-urlencoded" + }, + "body": new URLSearchParams({ + "client_id": clientId.get(), + "client_secret": clientSecret.get(), + "grant_type": "client_credentials" + }) + }).then((response) => { return response.json(); }).then((data) => + { + const newToken = data.access_token; + accessToken = newToken; + fetchData(newToken); + }); + } +} + + +}; + +Ops.Api.SoundCloud.SoundCloud_v2.prototype = new CABLES.Op(); +CABLES.OPS["1b6b0679-4f26-4886-af31-ee696936ea8f"]={f:Ops.Api.SoundCloud.SoundCloud_v2,objName:"Ops.Api.SoundCloud.SoundCloud_v2"}; + + + + +// ************************************************************** +// +// Ops.Array.AnglesBetweenPoints +// +// ************************************************************** + +Ops.Array.AnglesBetweenPoints = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Points"), + inTheta = op.inFloat("Theta", 0), + inPhi = op.inFloat("Phi", 0), + outArr = op.outArray("Rotations"); + +let q = quat.create(); + +inTheta.onChange = +inPhi.onChange = +inArr.onChange = () => +{ + const arr = inArr.get(); + const result = []; + + if (!arr || arr.length == 0) + { + outArr.set(null); + return; + } + + let vUp = vec3.create(); + + let qprev = quat.create(); + let prevqs = []; + + for (let i = 0; i < arr.length - 3; i += 3) + { + let va = [arr[i + 0], arr[i + 1], arr[i + 2]]; + let vb = [arr[i + 3 + 0], arr[i + 3 + 1], arr[i + 3 + 2]]; + + const + x = vb[0] - va[0], + y = vb[1] - va[1], + z = vb[2] - va[2], + r = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2)), + theta = Math.acos(y / r) * (180 / Math.PI) + inTheta.get(), + phi = Math.atan2(x, z) * (180 / Math.PI) + inPhi.get(); + + result.push(phi, -theta, 0); + // beamContainer.transform.rotation = Quaternion.Euler(-90 + phi, -theta, 0f); + + /// /////////////////////////// + + // vec3.set(vb, + // vb[0] - va[0], + // vb[1] - va[1], + // vb[2] - va[2]); + + // vec3.normalize(vb, vb); + + // vec3.copy(va,vUp); + + // quat.rotationTo(q, va, vb); + + // result.push(q[0],q[1],q[2],q[3]); + } + + outArr.set(null); + outArr.set(result); +}; + + +}; + +Ops.Array.AnglesBetweenPoints.prototype = new CABLES.Op(); +CABLES.OPS["0d9eb214-c1a2-4ef5-8bcb-79b89fcfba57"]={f:Ops.Array.AnglesBetweenPoints,objName:"Ops.Array.AnglesBetweenPoints"}; + + + + +// ************************************************************** +// +// Ops.Array.AnimArray_v2 +// +// ************************************************************** + +Ops.Array.AnimArray_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTrigger = op.inTrigger("Update"), + inArr = op.inArray("Next Array"), + inDur = op.inFloat("Duration", 1), + next = op.outTrigger("Next"), + outArr = op.outArray("Matrix"); + +let lastTime = 0; +let startTime = 0; +let firsttime = true; +let cycle = 1; + +const anim = new CABLES.Anim(); +anim.createPort(op, "easing", init); +anim.loop = false; + +let lastArr = null; + +inDur.onChange = inArr.onChange = init; + +let arr1, arr2; +let result = []; + +inTrigger.onTriggered = () => +{ + let t = CABLES.now() / 1000; + const perc = anim.getValue(t); + if (arr1 && arr2) ipMat(perc); +}; + +inArr.onLinkChanged = () => +{ + if (inArr) inArr.copyLinkedUiAttrib("stride", outArr); +}; + +function copyArray(a) +{ + let b = []; + b.length = a.length; + for (let i = 0; i < a.length; i++) b[i] = a[i]; + return b; +} + +function init() +{ + if (!inArr.get()) return; + + // if (inArr.get() == lastArr) return; // cant dothat, then changes in array ref are not working... + // if (lastArr) + // if (inArr.get() == lastArr) + // return; + + lastArr = inArr.get(); + startTime = performance.now(); + anim.clear(CABLES.now() / 1000.0); + + anim.setValue(CABLES.now() / 1000.0, cycle); + + if (cycle == 1) cycle = 0; + else cycle = 1; + + if (result.length != lastArr.length)result = copyArray(lastArr); + + if (cycle == 0) + { + arr1 = inArr.get(); + arr2 = copyArray(result); + } + else + { + arr1 = copyArray(result); + arr2 = inArr.get(); + } + + anim.setValue(inDur.get() + CABLES.now() / 1000.0, cycle); + + firsttime = false; +} + +function ip(val1, val2, perc) +{ + return ((val2 - val1) * perc + val1); +} + +function ipMat(perc) +{ + if (!arr1 || !arr2 || arr1.length != arr2.length) + { + outArr.set(null); + op.logError("arrays wrong", arr1.length, arr2.length); + } + else + { + for (let i = 0; i < arr1.length; i++) + { + result[i] = ip(arr1[i], arr2[i], perc); + } + + outArr.set(null); + outArr.set(result); + } + next.trigger(); +} + + +}; + +Ops.Array.AnimArray_v2.prototype = new CABLES.Op(); +CABLES.OPS["048e852b-62ea-4314-b6f2-9ac5e7cbb066"]={f:Ops.Array.AnimArray_v2,objName:"Ops.Array.AnimArray_v2"}; + + + + +// ************************************************************** +// +// Ops.Array.Array1To3 +// +// ************************************************************** + +Ops.Array.Array1To3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArr = op.inArray("Array1x"), + outArr = op.outArray("Array3x", null, 3), + outTotalPoints = op.outNumber("Total points"), + outArrayLength = op.outNumber("Array length"); + +let arr = []; + +inArr.onChange = function () +{ + let theArray = inArr.get(); + if (!theArray) + { + outArr.set(null); + outTotalPoints.set(0); + outArrayLength.set(0); + return; + } + + if ((theArray.length) * 3 != arr.length) + { + arr.length = (theArray.length) * 3; + } + + for (let i = 0; i < theArray.length; i++) + { + arr[i * 3 + 0] = i; + arr[i * 3 + 1] = theArray[i]; + arr[i * 3 + 2] = 0; + } + + outArr.set(null); + outArr.set(arr); + outTotalPoints.set(arr.length / 3); + outArrayLength.set(arr.length); +}; + + +}; + +Ops.Array.Array1To3.prototype = new CABLES.Op(); +CABLES.OPS["0d67fdf1-8e60-465e-9897-6aae6676e4c9"]={f:Ops.Array.Array1To3,objName:"Ops.Array.Array1To3"}; + + + + +// ************************************************************** +// +// Ops.Array.Array1toX +// +// ************************************************************** + +Ops.Array.Array1toX = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array1x"), + format = op.inSwitch("Format", ["AB", "ABC", "ABCD"], "ABC"), + axisA = op.inSwitch("A", ["Input", "index", "0-1", "-1-1", "0", "1"], "Input"), + axisB = op.inSwitch("B", ["Input", "index", "0-1", "-1-1", "0", "1"], "0-1"), + axisC = op.inSwitch("C", ["Input", "index", "0-1", "-1-1", "0", "1"], "0"), + axisD = op.inSwitch("D", ["Input", "index", "0-1", "-1-1", "0", "1"], "0"), + outArr = op.outArray("Array3x"), + outTotalPoints = op.outNumber("Total points"), + outArrayLength = op.outNumber("Array length"); + +const arr = []; + +axisA.onChange = +axisB.onChange = +axisC.onChange = +axisD.onChange = +inArr.onChange = update; + +format.onChange = function () +{ + axisC.setUiAttribs({ "greyout": format.get().length < 3 }); + axisD.setUiAttribs({ "greyout": format.get().length < 4 }); + + update(); +}; + +function fillArr_0(off, num, stride) +{ + for (let i = 0; i < num; i += stride) + { + arr[i + off] = 0; + } +} + +function fillArr_1(off, num, stride) +{ + for (let i = 0; i < num; i += stride) + { + arr[i + off] = 1; + } +} + +function fillArr_input(off, num, stride) +{ + const theArray = inArr.get(); + for (let i = 0; i < num; i += stride) + { + arr[i + off] = theArray[i / stride]; + } +} + +function fillArr_01(off, num, stride) +{ + for (let i = 0; i < num; i += stride) + { + arr[i + off] = (i / (num)) || 0; + } +} + +function fillArr_index(off, num, stride) +{ + for (let i = 0; i < num; i += stride) + { + arr[i + off] = i / stride; + } +} + +function fillArr(off, meth, stride) +{ + if (meth == "0")fillArr_0(off, arr.length, stride); + if (meth == "0-1")fillArr_01(off, arr.length, stride); + if (meth == "1")fillArr_1(off, arr.length, stride); + if (meth == "Input")fillArr_input(off, arr.length, stride); + if (meth == "index")fillArr_index(off, arr.length, stride); +} + +function update() +{ + const theArray = inArr.get(); + if (!theArray) + { + outArr.set(null); + outTotalPoints.set(0); + outArrayLength.set(0); + return; + } + + const stride = format.get().length; + const l = theArray.length * stride; + arr.length = l; + + if (stride >= 2) fillArr(0, axisA.get(), stride); + if (stride >= 2) fillArr(1, axisB.get(), stride); + if (stride >= 3) fillArr(2, axisC.get(), stride); + if (stride >= 4) fillArr(3, axisD.get(), stride); + + // for(var i=0;i +{ + parametersChanged = true; +}; + +const DISCARD_FUNCS = { + "Sphere": (inArr) => + { + const newArr = []; + const radiusSquared = inSize.get() * inSize.get(); + let CONDITION = (a, b) => { return a > b; }; + if (inInvert.get()) CONDITION = (a, b) => { return a < b; }; + + for (let i = 0, len = inArr.length / 3; i < len; i += 1) + { + vec3.set(tempVec, inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + const distSquared = vec3.squaredDistance(tempVec, rootVec); + + if (CONDITION(distSquared, radiusSquared)) + { + newArr.push(inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + } + } + + return newArr; + }, + "Box": (inArr) => + { + const size = inSize.get(); + const newArr = []; + for (let i = 0, len = inArr.length / 3; i < len; i += 1) + { + vec3.set(tempVec, inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + + if ( + Math.abs(tempVec[1] - rootVec[1]) > size + || Math.abs(tempVec[0] - rootVec[0]) > size + || Math.abs(tempVec[2] - rootVec[2]) > size + ) + { + if (!inInvert.get()) newArr.push(inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + } + else + { + if (inInvert.get()) newArr.push(inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + } + } + + return newArr; + }, + "Axis X": (inArr) => + { + const size = inSize.get(); + const newArr = []; + for (let i = 0, len = inArr.length / 3; i < len; i += 1) + { + if (Math.abs(inArr[i * 3] - rootVec[0]) > size) + { + if (!inInvert.get()) newArr.push(inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + } + else + { + if (inInvert.get()) newArr.push(inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + } + } + + return newArr; + }, + "Axis Y": (inArr) => + { + const size = inSize.get(); + const newArr = []; + for (let i = 0, len = inArr.length / 3; i < len; i += 1) + { + if (Math.abs(inArr[i * 3 + 1] - rootVec[1]) > size) + { + if (!inInvert.get()) newArr.push(inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + } + else + { + if (inInvert.get()) newArr.push(inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + } + } + + return newArr; + }, + "Axis Z": (inArr) => + { + const size = inSize.get(); + const newArr = []; + for (let i = 0, len = inArr.length / 3; i < len; i += 1) + { + if (Math.abs(inArr[i * 3 + 2] - rootVec[2]) > size) + { + if (!inInvert.get()) newArr.push(inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + } + else + { + if (inInvert.get()) newArr.push(inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + } + } + + return newArr; + }, + "Axis X Infinite": (inArr) => + { + const size = inSize.get(); + const newArr = []; + for (let i = 0, len = inArr.length / 3; i < len; i += 1) + { + if (inArr[i * 3] - rootVec[0] > size) + { + if (!inInvert.get()) newArr.push(inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + } + else + { + if (inInvert.get()) newArr.push(inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + } + } + + return newArr; + }, + "Axis Y Infinite": (inArr) => + { + const size = inSize.get(); + const newArr = []; + for (let i = 0, len = inArr.length / 3; i < len; i += 1) + { + if (inArr[i * 3 + 1] - rootVec[1] > size) + { + if (!inInvert.get()) newArr.push(inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + } + else + { + if (inInvert.get()) newArr.push(inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + } + } + + return newArr; + }, + "Axis Z Infinite": (inArr) => + { + const size = inSize.get(); + const newArr = []; + for (let i = 0, len = inArr.length / 3; i < len; i += 1) + { + if (inArr[i * 3 + 2] - rootVec[2] > size) + { + if (!inInvert.get()) newArr.push(inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + } + else + { + if (inInvert.get()) newArr.push(inArr[i * 3 + 0], inArr[i * 3 + 1], inArr[i * 3 + 2]); + } + } + + return newArr; + }, +}; + +inTrigger.onTriggered = () => +{ + const inArr = inArray.get(); + drawHelpers(); + + + vec3.set(transVec, inPosX.get(), inPosY.get(), inPosZ.get()); + vec3.transformMat4(rootVec, transVec, cgl.mMatrix); + + if (!inArr) + { + outTrigger.trigger(); + outArray.set(null); + return; + } + + if (parametersChanged) + { + const newArr = DISCARD_FUNCS[inMode.get()](inArr); + + outArray.set(null); + outArray.set(newArr); + outLength.set(newArr.length); + + parametersChanged = false; + } + + + outX.set(rootVec[0]); + outY.set(rootVec[1]); + outZ.set(rootVec[2]); + outTrigger.trigger(); +}; + +const HELPER_FUNCS = { + "Sphere": () => { return CABLES.GL_MARKER.drawSphere(op, inSize.get()); }, + "Box": () => { return CABLES.GL_MARKER.drawCube(op, inSize.get(), inSize.get(), inSize.get()); }, + "Axis X": () => { return CABLES.GL_MARKER.drawCube(op, inSize.get(), 2, 2); }, + "Axis Y": () => { return CABLES.GL_MARKER.drawCube(op, 2, inSize.get(), 2); }, + "Axis Z": () => { return CABLES.GL_MARKER.drawCube(op, 2, 2, inSize.get()); }, + "Axis X Infinite": () => { return CABLES.GL_MARKER.drawCube(op, inSize.get(), 2, 2); }, + "Axis Y Infinite": () => { return CABLES.GL_MARKER.drawCube(op, 2, inSize.get(), 2); }, + "Axis Z Infinite": () => { return CABLES.GL_MARKER.drawCube(op, 2, 2, inSize.get()); }, +}; + +function drawHelpers() +{ + if (cgl.shouldDrawHelpers(op)) + { + gui.setTransformGizmo({ "posX": inPosX, "posY": inPosY, "posZ": inPosZ }); + cgl.pushModelMatrix(); + mat4.translate(cgl.mMatrix, cgl.mMatrix, rootVec); + HELPER_FUNCS[inMode.get()](); + cgl.popModelMatrix(); + } +} + + +}; + +Ops.Array.Array3AreaRemove.prototype = new CABLES.Op(); +CABLES.OPS["db93f8c7-6bad-467e-b38f-333e84838d1d"]={f:Ops.Array.Array3AreaRemove,objName:"Ops.Array.Array3AreaRemove"}; + + + + +// ************************************************************** +// +// Ops.Array.Array3FlipAxis +// +// ************************************************************** + +Ops.Array.Array3FlipAxis = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Points", 3), + inAxis1 = op.inSwitch("Axis 1", ["X", "Y", "Z"], "X"), + inAxis2 = op.inSwitch("Axis 2", ["X", "Y", "Z"], "Y"), + inAxis3 = op.inSwitch("Axis 3", ["X", "Y", "Z"], "Z"), + + inFlipX = op.inBool("Flip Order X", false), + inFlipY = op.inBool("Flip Order Y", false), + inFlipZ = op.inBool("Flip Order Z", false), + + result = op.outArray("Result"); + +const arr = []; + +inArr.onChange = +inFlipX.onChange = +inFlipY.onChange = +inFlipZ.onChange = +inAxis1.onChange = +inAxis2.onChange = +inAxis3.onChange = () => +{ + const oldArr = inArr.get(); + if (!oldArr || oldArr.length == 0) + { + result.set(null); + return; + } + + arr.length = oldArr.length; + + let len = oldArr.length; + + if (inAxis1.get() == "X") for (let i = 0; i < len; i += 3) arr[i + 0] = oldArr[i + 0]; + if (inAxis1.get() == "Y") for (let i = 0; i < len; i += 3) arr[i + 0] = oldArr[i + 1]; + if (inAxis1.get() == "Z") for (let i = 0; i < len; i += 3) arr[i + 0] = oldArr[i + 2]; + + if (inAxis2.get() == "X") for (let i = 0; i < len; i += 3) arr[i + 1] = oldArr[i + 0]; + if (inAxis2.get() == "Y") for (let i = 0; i < len; i += 3) arr[i + 1] = oldArr[i + 1]; + if (inAxis2.get() == "Z") for (let i = 0; i < len; i += 3) arr[i + 1] = oldArr[i + 2]; + + if (inAxis3.get() == "X") for (let i = 0; i < len; i += 3) arr[i + 2] = oldArr[i + 0]; + if (inAxis3.get() == "Y") for (let i = 0; i < len; i += 3) arr[i + 2] = oldArr[i + 1]; + if (inAxis3.get() == "Z") for (let i = 0; i < len; i += 3) arr[i + 2] = oldArr[i + 2]; + + + const maxi = len; + + if (inFlipX.get()) + for (let i = 0; i < len / 2; i += 3) + { + const temp = arr[i + 0]; + arr[i + 0] = arr[len - i]; + arr[len - i] = temp; + } + + if (inFlipY.get()) + for (let i = 0; i < len / 2; i += 3) + { + const temp = arr[i + 1]; + arr[i + 1] = arr[(len - i) + 1]; + arr[(len - i) + 1] = temp; + } + + + if (inFlipZ.get()) + for (let i = 0; i < len / 2; i += 3) + { + const temp = arr[i + 2]; + arr[i + 2] = arr[(len - i) + 2]; + arr[(len - i) + 2] = temp; + } + + + result.set(null); + result.set(arr); +}; + + +}; + +Ops.Array.Array3FlipAxis.prototype = new CABLES.Op(); +CABLES.OPS["1a9a0178-5906-423b-b8f3-0532499ba169"]={f:Ops.Array.Array3FlipAxis,objName:"Ops.Array.Array3FlipAxis"}; + + + + +// ************************************************************** +// +// Ops.Array.Array3GetAverage +// +// ************************************************************** + +Ops.Array.Array3GetAverage = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array", 3), + avgX = op.outNumber("Average X"), + avgY = op.outNumber("Average Y"), + avgZ = op.outNumber("Average Z"); + +inArr.onChange = function () +{ + let arr = inArr.get(); + if (!arr) + { + avgX.set(0); + avgY.set(0); + avgZ.set(0); + return; + } + let x = 0; + let y = 0; + let z = 0; + + for (let i = 0; i < arr.length; i += 3) + { + x += arr[i + 0]; + y += arr[i + 1]; + z += arr[i + 2]; + } + + x /= arr.length / 3; + y /= arr.length / 3; + z /= arr.length / 3; + + avgX.set(x); + avgY.set(y); + avgZ.set(z); +}; + + +}; + +Ops.Array.Array3GetAverage.prototype = new CABLES.Op(); +CABLES.OPS["9643edc7-e479-4b26-9f7a-343cdcdc81f4"]={f:Ops.Array.Array3GetAverage,objName:"Ops.Array.Array3GetAverage"}; + + + + +// ************************************************************** +// +// Ops.Array.Array3GetNumbers +// +// ************************************************************** + +Ops.Array.Array3GetNumbers = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + pArr = op.inArray("Array", 3), + pIndex = op.inValueInt("Index"), + outX = op.outNumber("X"), + outY = op.outNumber("Y"), + outZ = op.outNumber("Z"); + +pArr.onChange = + pIndex.onChange = update; + +function update() +{ + let arr = pArr.get(); + if (!arr) + { + outX.set(0); + outY.set(0); + outZ.set(0); + return; + } + let ind = Math.min(arr.length - 3, pIndex.get() * 3); + if (arr) + { + outX.set(arr[ind + 0]); + outY.set(arr[ind + 1]); + outZ.set(arr[ind + 2]); + } +} + + +}; + +Ops.Array.Array3GetNumbers.prototype = new CABLES.Op(); +CABLES.OPS["56882cc4-c40d-4dc0-bf7c-db1b5a7acad0"]={f:Ops.Array.Array3GetNumbers,objName:"Ops.Array.Array3GetNumbers"}; + + + + +// ************************************************************** +// +// Ops.Array.Array3InterpolateDistributed +// +// ************************************************************** + +Ops.Array.Array3InterpolateDistributed = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Update"), + inArr1 = op.inArray("Array 1", 3), + inArr2 = op.inArray("Array 2", 3), + inProgress = op.inValueSlider("Progress"), + arrOut = op.outArray("Result"), + outArrayLength = op.outNumber("Array length"); + +let resultArr = []; +let indexArray = []; + +inArr2.onChange = updateArr2; +inArr1.onChange = updateArr1; + + +function updateArr1() +{ + if (!inArr1.get()) + { + arrOut.set(null); + outArrayLength.set(0); + return; + } + resultArr.length = inArr1.get().length; +} + +function updateArr2() +{ + if (!inArr2.get()) + { + arrOut.set(null); + outArrayLength.set(0); + return; + } + + indexArray.length = Math.ceil(inArr2.get().length / 3); + + let arr2 = inArr2.get(); + + for (let i = 0; i < indexArray.length; i += 3) + { + let index2 = Math.floor(arr2.length / 3 * Math.random()); + // indexArray[i+0]=arr2[index2*3+0]; + // indexArray[i+1]=arr2[index2*3+1]; + // indexArray[i+2]=arr2[index2*3+2]; + indexArray[i / 3] = index2 * 3; + // indexArray[i+1]=arr2[index2*3+1]; + // indexArray[i+2]=arr2[index2*3+2]; + } + + // arrOut.set(null); + // arrOut.set(resultArr); + // updateArr1(); +} + +exec.onTriggered = function () +{ + let perc = inProgress.get(); + let val1 = 0, val2 = 0; + let arr1 = inArr1.get(); + let arr2 = inArr2.get(); + + let l1 = 0; + let l2 = 0; + if (arr1)l1 = arr1.length; + if (arr2)l2 = arr2.length; + + let l = Math.min(l1, l2); + + + for (let i = 0; i < l; i += 3) + { + val1 = arr1[i]; + val2 = arr2[indexArray[(i / 3)]]; + resultArr[i] = ((val2 - val1) * perc + val1); + + val1 = arr1[i + 1]; + val2 = arr2[indexArray[(i / 3)] + 1]; + resultArr[i + 1] = ((val2 - val1) * perc + val1); + + val1 = arr1[i + 2]; + val2 = arr2[indexArray[(i / 3)] + 2]; + resultArr[i + 2] = ((val2 - val1) * perc + val1); + } + + arrOut.set(null); + arrOut.set(resultArr); + outArrayLength.set(resultArr.length); +}; + + +}; + +Ops.Array.Array3InterpolateDistributed.prototype = new CABLES.Op(); +CABLES.OPS["a004a6e9-a05f-42dc-91d3-69aa88e67a87"]={f:Ops.Array.Array3InterpolateDistributed,objName:"Ops.Array.Array3InterpolateDistributed"}; + + + + +// ************************************************************** +// +// Ops.Array.Array3Multiply +// +// ************************************************************** + +Ops.Array.Array3Multiply = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array3x", 3), + mulX = op.inValue("Mul X", 1), + mulY = op.inValue("Mul Y", 1), + mulZ = op.inValue("Mul Z", 1), + outArr = op.outArray("Result"); + +let arr = []; + +mulY.onChange = mulX.onChange = mulZ.onChange = +inArr.onChange = function () +{ + let newArr = inArr.get(); + if (newArr) + { + if (arr.length != newArr.length)arr.length = newArr.length; + + for (let i = 0; i < newArr.length; i += 3) + { + arr[i + 0] = newArr[i + 0] * mulX.get(); + arr[i + 1] = newArr[i + 1] * mulY.get(); + arr[i + 2] = newArr[i + 2] * mulZ.get(); + } + + outArr.set(null); + outArr.set(arr); + } + else + { + outArr.set(null); + } +}; + + +}; + +Ops.Array.Array3Multiply.prototype = new CABLES.Op(); +CABLES.OPS["a1e4d85f-0955-4ada-819c-c597cec40365"]={f:Ops.Array.Array3Multiply,objName:"Ops.Array.Array3Multiply"}; + + + + +// ************************************************************** +// +// Ops.Array.Array3PushNumbers_v2 +// +// ************************************************************** + +Ops.Array.Array3PushNumbers_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exePort = op.inTriggerButton('Execute'), + inArrayPort = op.inArray('Array'), + value1Port = op.inValue('Value 1'), + value2Port = op.inValue('Value 2'), + value3Port = op.inValue('Value 3'), + + inReset=op.inTriggerButton("Reset"), + nextPort = op.outTrigger('Next'), + outArray=op.outArray("Result Array"); + +const newArr=[]; +exePort.onTriggered = update; + + +inReset.onTriggered= +inArrayPort.onChange=function() +{ + let arr=inArrayPort.get(); + if(!arr) + { + outArray.set([]); + return; + } + newArr.length=arr.length; + for(let i=0;i= inArr.length) + { + begin %= inArr.length; + } + + if (!inArr || size < 1) + { + outArrayPort.set(null); + return; + } + let end = size + begin; + + let newLen = Math.min(inArr.length, begin + end) - begin; + if (newLen < 0) + { + op.setUiError("idx", "invalid index/array length"); + newLen = 0; + } + else op.setUiError("idx", null); + newLen = Math.min(newLen, size); + + if (newLen > size) newLen = inArr.length; + newArr.length = newLen; + for (let i = begin; i < newLen + begin; i++) + { + newArr[i - begin] = inArr[i]; + } + + outArrayPort.set(null); + outArrayLength.set(newLen); + outArrayPort.set(newArr); +} + +// change listeners +inArrayPort.onChange = setOutarray; +beginPort.onChange = setOutarray; +sizePort.onChange = setOutarray; +circularPort.onChange = setOutarray; + + +}; + +Ops.Array.ArrayChunk.prototype = new CABLES.Op(); +CABLES.OPS["c7ee6c6e-ca88-4c24-b289-78bb922bf5f7"]={f:Ops.Array.ArrayChunk,objName:"Ops.Array.ArrayChunk"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayChunkDuplicate +// +// ************************************************************** + +Ops.Array.ArrayChunkDuplicate = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr=op.inArray("Array"), + inChunks=op.inInt("Chunk Size",3), + inRepeats=op.inInt("Repeats",10), + outArr=op.outArray("Result"); + + +inArr.onChange= +inChunks.onChange= +inRepeats.onChange=()=> +{ + let chu=inChunks.get(); + let reps=inRepeats.get(); + let arr=inArr.get(); + + if(!arr)return; + if(chu<=0)return; + if(chu<=0)return; + + let rArr=[]; + let count=0; + + for(let i=0;i-1); + } +} + +}; + +Ops.Array.ArrayContains_v2.prototype = new CABLES.Op(); +CABLES.OPS["b982d7e3-c9cf-41dd-aead-66daad785fa8"]={f:Ops.Array.ArrayContains_v2,objName:"Ops.Array.ArrayContains_v2"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayDivide +// +// ************************************************************** + +Ops.Array.ArrayDivide = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let inArray = op.inArray("Array In"); +let inValue = op.inValue("Value", 1.0); +let outArray = op.outArray("Array Out"); + +let newArr = []; +outArray.set(newArr); +inArray.onChange = inValue.onChange = inArray.onChange = function () +{ + let arr = inArray.get(); + if (!arr) return; + + let divide = inValue.get(); + + if (newArr.length != arr.length) newArr.length = arr.length; + + let i = 0; + for (i = 0; i < arr.length; i++) + { + newArr[i] = arr[i] / divide; + } + outArray.set(null); + outArray.set(newArr); +}; + + +}; + +Ops.Array.ArrayDivide.prototype = new CABLES.Op(); +CABLES.OPS["e9406477-1f1c-4cf3-8a64-f6009df05c7c"]={f:Ops.Array.ArrayDivide,objName:"Ops.Array.ArrayDivide"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayFloor +// +// ************************************************************** + +Ops.Array.ArrayFloor = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArray=op.inArray("In"), + outArray=op.outArray("Result"), + newArr=[]; + +outArray.set(newArr); + +inArray.onChange=function() +{ + var arr=inArray.get(); + + if(!arr) + { + outArray.set(null); + return; + } + + if(newArr.length!=arr.length)newArr.length=arr.length; + + for(var i=0;i +{ + const l = inLimit.get(); + + for (let i = 0; i < inPorts.length; i++) + if (inSlider.get()) inPorts[i].setUiAttribs({ "display": "range" }); + else inPorts[i].setUiAttribs({ "display": null }); + + op.refreshParams(); +}; + +inLimit.onChange = () => +{ + clearTimeout(to); + + to = setTimeout(() => + { + const l = inLimit.get(); + for (let i = 0; i < inPorts.length; i++) + { + inPorts[i].setUiAttribs({ "greyout": i >= l }); + } + }, 300); +}; + +function update() +{ + const l = Math.max(0, Math.ceil(Math.min(inLimit.get(), inPorts.length))); + arr.length = l; + for (let i = 0; i < l; i++) + { + arr[i] = inPorts[i].get(); + } + + outArr.set(null); + outArr.set(arr); + next.trigger(); +} + + +}; + +Ops.Array.ArrayFromNumbers.prototype = new CABLES.Op(); +CABLES.OPS["fb698158-3cf8-49d6-805e-6ea38fdab8c1"]={f:Ops.Array.ArrayFromNumbers,objName:"Ops.Array.ArrayFromNumbers"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayGetArray +// +// ************************************************************** + +Ops.Array.ArrayGetArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArrays = op.inArray("Array of Arrays"), + index = op.inValueInt("Index"), + result = op.outArray("Result Array"); + +inArrays.onChange = +index.onChange = update; + +function update() +{ + let theArray = inArrays.get(); + if (!theArray) + { + result.set(null); + return; + } + + let ind = Math.floor(index.get()); + if (ind < 0 || ind > theArray.length - 1) + { + result.set(null); + op.log("index wrong"); + return; + } + + result.set(null); + result.set(theArray[ind]); +} + + +}; + +Ops.Array.ArrayGetArray.prototype = new CABLES.Op(); +CABLES.OPS["b9d3f42b-3fbf-4522-9df2-a5c769a92d66"]={f:Ops.Array.ArrayGetArray,objName:"Ops.Array.ArrayGetArray"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayGetNumber +// +// ************************************************************** + +Ops.Array.ArrayGetNumber = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + array = op.inArray("array"), + index = op.inValueInt("index"), + value = op.outNumber("value"); + +array.ignoreValueSerialize = true; + +index.onChange = array.onChange = update; + +function update() +{ + if (array.get()) + { + let input = array.get()[index.get()]; + if (isNaN(input)) + { + value.set(0); + return; + } + value.set(parseFloat(input)); + } +} + + +}; + +Ops.Array.ArrayGetNumber.prototype = new CABLES.Op(); +CABLES.OPS["d1189078-70cf-437d-9a37-b2ebe89acdaf"]={f:Ops.Array.ArrayGetNumber,objName:"Ops.Array.ArrayGetNumber"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayGetObject +// +// ************************************************************** + +Ops.Array.ArrayGetObject = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + array = op.inArray("array"), + index = op.inValueInt("index"), + value = op.outObject("value"); + +let last = null; + +array.ignoreValueSerialize = true; +value.ignoreValueSerialize = true; + +index.onChange = update; +array.onChange = update; + +op.toWorkPortsNeedToBeLinked(array); + +function update() +{ + if (index.get() < 0) + { + value.set(null); + return; + } + + const arr = array.get(); + if (!arr) + { + value.set(null); + return; + } + + const ind = index.get(); + if (ind >= arr.length) + { + value.set(null); + return; + } + if (arr[ind]) + { + value.set(null); + value.set(arr[ind]); + last = arr[ind]; + } +} + + +}; + +Ops.Array.ArrayGetObject.prototype = new CABLES.Op(); +CABLES.OPS["44d34542-174c-47c6-b9c6-adde6fc371ac"]={f:Ops.Array.ArrayGetObject,objName:"Ops.Array.ArrayGetObject"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayGetString +// +// ************************************************************** + +Ops.Array.ArrayGetString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + array = op.inArray("array"), + index = op.inValueInt("index"), + result = op.outString("result"); + +array.ignoreValueSerialize = true; + +index.onChange = update; + +array.onChange = function () +{ + update(); +}; + +function update() +{ + const arr = array.get(); + if (arr) result.set(arr[index.get()]); +} + + +}; + +Ops.Array.ArrayGetString.prototype = new CABLES.Op(); +CABLES.OPS["be8f16c0-0c8a-48a2-a92b-45dbf88c76c1"]={f:Ops.Array.ArrayGetString,objName:"Ops.Array.ArrayGetString"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayGetTexture +// +// ************************************************************** + +Ops.Array.ArrayGetTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + array = op.inArray("array"), + index = op.inValueInt("index"), + value = op.outTexture("value"); + +let last = null; + +array.ignoreValueSerialize = true; +value.ignoreValueSerialize = true; + +index.onChange = update; +array.onChange = update; + +op.toWorkPortsNeedToBeLinked(array, value); + +const emptyTex = CGL.Texture.getEmptyTexture(op.patch.cgl); + +function update() +{ + if (index.get() < 0) + { + value.set(emptyTex); + return; + } + + let arr = array.get(); + if (!arr) + { + value.set(emptyTex); + return; + } + + let ind = index.get(); + if (ind >= arr.length) + { + value.set(emptyTex); + return; + } + if (arr[ind]) + { + value.set(emptyTex); + value.set(arr[ind]); + last = arr[ind]; + } +} + + +}; + +Ops.Array.ArrayGetTexture.prototype = new CABLES.Op(); +CABLES.OPS["afea522b-ab72-4574-b721-5d37f5abaf77"]={f:Ops.Array.ArrayGetTexture,objName:"Ops.Array.ArrayGetTexture"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayIndexBetween +// +// ************************************************************** + +Ops.Array.ArrayIndexBetween = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr=op.inArray("Array"), + inNum=op.inFloat("Value",0), + outIndex=op.outNumber("Index"); + +inArr.onChange= + inNum.onChange=update; + +function update() +{ + const arr=inArr.get(); + + if(!arr) + { + outIndex.set(-1); + return; + } + + const n=inNum.get(); + + if(narr[i] && n +{ + + const arr=inArr.get(); + + if(!arr) + { + outMax.set(0); + outMin.set(0); + return; + } + + let min=Number.MAX_VALUE; + let max=-Number.MAX_VALUE; + let minIndex=-1; + let maxIndex=-1; + + for(let i=0;imax) + { + maxIndex=i; + max=arr[i]; + } + + } + + outMax.set(max); + outIndexMax.set(maxIndex); + outMin.set(min); + outIndexMin.set(minIndex); + + +}; + +}; + +Ops.Array.ArrayIndexMinMax.prototype = new CABLES.Op(); +CABLES.OPS["240172a6-7dde-4dcc-b862-bbe764aec3f3"]={f:Ops.Array.ArrayIndexMinMax,objName:"Ops.Array.ArrayIndexMinMax"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayIteratorArray +// +// ************************************************************** + +Ops.Array.ArrayIteratorArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + arr = op.inArray("array"), + trigger = op.outTrigger("trigger"), + idx = op.outNumber("index"), + val = op.outArray("Result"); + +exe.onTriggered = function () +{ + const theArr = arr.get(); + + if (!theArr) + { + val.set(null); + return; + } + + for (let i = 0; i < theArr.length; i++) + { + idx.set(i); + val.set(theArr[i]); + trigger.trigger(); + } +}; + + +}; + +Ops.Array.ArrayIteratorArray.prototype = new CABLES.Op(); +CABLES.OPS["0efcd325-0ccf-452b-a87e-3c44d42f9165"]={f:Ops.Array.ArrayIteratorArray,objName:"Ops.Array.ArrayIteratorArray"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayIteratorNumbers +// +// ************************************************************** + +Ops.Array.ArrayIteratorNumbers = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe=op.inTrigger("exe"), + arr=op.inArray("array"), + trigger=op.outTrigger('trigger'), + idx=op.addOutPort(new CABLES.Port(op,"index")), + val=op.addOutPort(new CABLES.Port(op,"value")); + +exe.onTriggered=function() +{ + if(!arr.get())return; + + for(var i=0;i", "<", ">=", "<=", "==", "!=", + ">pass", "=pass", "<=pass", "==pass", "!=pass"], ">"), + numberIn = op.inValueFloat("Number for comparison", 0.5), + inValueIfTrue = op.inFloat("value if true", 1.0), + inValueIfFalse = op.inFloat("value if false", 0.0), + outArray = op.outArray("Array result"), + outArrayLength = op.outNumber("Array length"); + +op.toWorkPortsNeedToBeLinked(inArray_0); + +let logicFunc; +let showingError = false; + +let mathArray = []; +let selectIndex = 0; + +mathSelect.onChange = onFilterChange; + +inArray_0.onChange = numberIn.onChange = inValueIfFalse.onChange = +inValueIfTrue.onChange = update; + +onFilterChange(); + +function onFilterChange() +{ + let mathSelectValue = mathSelect.get(); + if (mathSelectValue === ">") logicFunc = function (val, comp, t, f) { if (val > comp) return t; return f; }; + else if (mathSelectValue === "<") logicFunc = function (val, comp, t, f) { if (val < comp) return t; return f; }; + else if (mathSelectValue === ">=") logicFunc = function (val, comp, t, f) { if (val >= comp) return t; return f; }; + else if (mathSelectValue === "<=") logicFunc = function (val, comp, t, f) { if (val <= comp) return t; return f; }; + else if (mathSelectValue === "==") logicFunc = function (val, comp, t, f) { if (val === comp) return t; return f; }; + else if (mathSelectValue === "!=") logicFunc = function (val, comp, t, f) { if (val !== comp) return t; return f; }; + else if (mathSelectValue === ">pass") logicFunc = function (val, comp, t, f) { if (val > comp) return val; return f; }; + else if (mathSelectValue === "=pass") logicFunc = function (val, comp, t, f) { if (val >= comp) return val; return f; }; + else if (mathSelectValue === "<=pass") logicFunc = function (val, comp, t, f) { if (val <= comp) return val; return f; }; + else if (mathSelectValue === "==pass") logicFunc = function (val, comp, t, f) { if (val === comp) return val; return f; }; + else if (mathSelectValue === "!=pass") logicFunc = function (val, comp, t, f) { if (val !== comp) return val; return f; }; + update(); + op.setUiAttrib({ "extendTitle": mathSelectValue }); +} + +function update() +{ + let array0 = inArray_0.get(); + + let mathNumberIn = numberIn.get(); + let valueFalse = inValueIfFalse.get(); + let valueTrue = inValueIfTrue.get(); + + mathArray.length = 0; + + if (!array0) + { + outArray.set(null); + outArrayLength.set(0); + return; + } + + mathArray.length = array0.length; + + let i = 0; + + for (i = 0; i < array0.length; i++) + { + mathArray[i] = logicFunc(array0[i], mathNumberIn, valueTrue, valueFalse); + } + + outArray.set(null); + outArray.set(mathArray); + outArrayLength.set(mathArray.length); +} + + +}; + +Ops.Array.ArrayLogic.prototype = new CABLES.Op(); +CABLES.OPS["502083f2-8ade-4cb5-b1c5-e5b60eb3255f"]={f:Ops.Array.ArrayLogic,objName:"Ops.Array.ArrayLogic"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayLogicArray +// +// ************************************************************** + +Ops.Array.ArrayLogicArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// this op expects 2 arrays. The user can then pick a +// logical comparison which will be applied to the +// two arrays. If arrays have a different length then a warning +// is given in the panel +// pass allows the value from array 0 through if the +// comparison evaulates to true else zero + +const inArray_0 = op.inArray("array 0"), + inArray_1 = op.inArray("array 1"), + inValueIfTrue = op.inFloat("value if true", 1.0), + inValueIfFalse = op.inFloat("value if false", 0.0), + mathSelect = op.inValueSelect("Comparison mode", [">", "<", ">=", "<=", "==", "!=", + ">pass", "=pass", "<=pass", "==pass", "!=pass"], ">"), + outArray = op.outArray("Array result"), + outArrayLength = op.outNumber("Array length"); + +op.toWorkPortsNeedToBeLinked(inArray_1, inArray_0); + +let logicFunc; +// cache for errors +let showingError = false; + +// create array to store multiplied result from both arrays +let mathArray = []; +let selectIndex = 0; + +mathSelect.onChange = onFilterChange; + +inArray_0.onChange = inArray_1.onChange = +inValueIfTrue.onChange = inValueIfFalse.onChange = update; + +onFilterChange(); +function onFilterChange() +{ + let mathSelectValue = mathSelect.get(); + if (mathSelectValue === ">") logicFunc = function (val, comp, t, f) { if (val > comp) return t; return f; }; + else if (mathSelectValue === "<") logicFunc = function (val, comp, t, f) { if (val < comp) return t; return f; }; + else if (mathSelectValue === ">=") logicFunc = function (val, comp, t, f) { if (val >= comp) return t; return f; }; + else if (mathSelectValue === "<=") logicFunc = function (val, comp, t, f) { if (val <= comp) return t; return f; }; + else if (mathSelectValue === "==") logicFunc = function (val, comp, t, f) { if (val === comp) return t; return f; }; + else if (mathSelectValue === "!=") logicFunc = function (val, comp, t, f) { if (val !== comp) return t; return f; }; + else if (mathSelectValue === ">pass") logicFunc = function (val, comp, t, f) { if (val > comp) return val; return f; }; + else if (mathSelectValue === "=pass") logicFunc = function (val, comp, t, f) { if (val >= comp) return val; return f; }; + else if (mathSelectValue === "<=pass") logicFunc = function (val, comp, t, f) { if (val <= comp) return val; return f; }; + else if (mathSelectValue === "==pass") logicFunc = function (val, comp, t, f) { if (val === comp) return val; return f; }; + else if (mathSelectValue === "!=pass") logicFunc = function (val, comp, t, f) { if (val !== comp) return val; return f; }; + + update(); + op.setUiAttrib({ "extendTitle": mathSelectValue }); +} + +function update() +{ + let array0 = inArray_0.get(); + let array1 = inArray_1.get(); + + let valueFalse = inValueIfFalse.get(); + let valueTrue = inValueIfTrue.get(); + + mathArray.length = 0; + + if (!array0 || !array1) + { + outArray.set(null); + outArrayLength.set(0); + return; + } + + if (array0.length !== array1.length) + { + outArray.set(null); + outArrayLength.set(0); + if (!showingError) + { + op.uiAttr({ "error": "Arrays do not have the same length !" }); + showingError = true; + } + return; + } + if (showingError) + { + showingError = false; + op.uiAttr({ "error": null }); + } + + mathArray.length = array0.length; + + let i = 0; + + for (i = 0; i < array0.length; i++) + { + mathArray[i] = logicFunc(array0[i], array1[i], valueTrue, valueFalse); + } + + outArray.set(null); + outArray.set(mathArray); + outArrayLength.set(mathArray.length); +} + + +}; + +Ops.Array.ArrayLogicArray.prototype = new CABLES.Op(); +CABLES.OPS["850a40f5-f623-438f-9ff8-461b1a9aeefc"]={f:Ops.Array.ArrayLogicArray,objName:"Ops.Array.ArrayLogicArray"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayLogicBetween_v2 +// +// ************************************************************** + +Ops.Array.ArrayLogicBetween_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArray = op.inArray("Array"), + inMin = op.inFloat("Min", 0), + inMax = op.inFloat("Max", 0.5), + inPass = op.inBool("pass value when true", false), + outArray = op.outArray("Result"); + +inArray.onChange = +inMin.onChange = +inMax.onChange = +inPass.onChange = +function update() +{ + let arr = inArray.get(); + if (!arr) return; + + let pass = inPass.get(); + const min = inMin.get(); + const max = inMax.get(); + + let newArr = []; + newArr.length = arr.length; + + if (!pass) + { + for (var i = 0; i < arr.length; i++) + { + if (arr[i] > min && arr[i] < max) + { + newArr[i] = 1.0; + } + else newArr[i] = 0.0; + } + } + else + { + for (var i = 0; i < arr.length; i++) + { + if (arr[i] > min && arr[i] < max) + { + newArr[i] = arr[i]; + } + else newArr[i] = 0.0; + } + } + outArray.set(null); + outArray.set(newArr); +}; + + +}; + +Ops.Array.ArrayLogicBetween_v2.prototype = new CABLES.Op(); +CABLES.OPS["c109a5d0-3338-4d7b-9dac-7c948d4663b8"]={f:Ops.Array.ArrayLogicBetween_v2,objName:"Ops.Array.ArrayLogicBetween_v2"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayMath +// +// ************************************************************** + +Ops.Array.ArrayMath = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArray_0 = op.inArray("array 0"), + NumberIn = op.inValueFloat("Number for math", 0.0), + mathSelect = op.inSwitch("Math function", ["+", "-", "*", "/", "%", "min", "max"], "+"), + outArray = op.outArray("Array result"), + outArrayLength = op.outNumber("Array length"); + +let mathFunc; + +let showingError = false; + +let mathArray = []; + +inArray_0.onChange = NumberIn.onChange = update; +mathSelect.onChange = onFilterChange; + +onFilterChange(); + +inArray_0.onLinkChanged = () => +{ + if (inArray_0) inArray_0.copyLinkedUiAttrib("stride", outArray); +}; + +function onFilterChange() +{ + let mathSelectValue = mathSelect.get(); + + if (mathSelectValue === "+") mathFunc = function (a, b) { return a + b; }; + else if (mathSelectValue === "-") mathFunc = function (a, b) { return a - b; }; + else if (mathSelectValue === "*") mathFunc = function (a, b) { return a * b; }; + else if (mathSelectValue === "/") mathFunc = function (a, b) { return a / b; }; + else if (mathSelectValue === "%") mathFunc = function (a, b) { return a % b; }; + else if (mathSelectValue === "min") mathFunc = function (a, b) { return Math.min(a, b); }; + else if (mathSelectValue === "max") mathFunc = function (a, b) { return Math.max(a, b); }; + update(); + op.setUiAttrib({ "extendTitle": mathSelectValue }); +} + +function update() +{ + let array0 = inArray_0.get(); + + mathArray.length = 0; + + if (!array0) + { + outArrayLength.set(0); + outArray.set(null); + return; + } + + let num = NumberIn.get(); + mathArray.length = array0.length; + + let i = 0; + + for (i = 0; i < array0.length; i++) + { + mathArray[i] = mathFunc(array0[i], num); + } + + outArray.set(null); + outArray.set(mathArray); + outArrayLength.set(mathArray.length); +} + + +}; + +Ops.Array.ArrayMath.prototype = new CABLES.Op(); +CABLES.OPS["c7617717-3114-452f-9625-e4fefd841e88"]={f:Ops.Array.ArrayMath,objName:"Ops.Array.ArrayMath"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayMathArray +// +// ************************************************************** + +Ops.Array.ArrayMathArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArray_0 = op.inArray("array 0"), + inArray_1 = op.inArray("array 1"), + mathSelect = op.inSwitch("Math function", ["+", "-", "*", "/", "%", "min", "max"], "+"), + outArray = op.outArray("Array result"), + outArrayLength = op.outNumber("Array length"); + +let mathFunc; + +let showingError = false; + +const mathArray = []; + +op.toWorkPortsNeedToBeLinked(inArray_1, inArray_0); + +mathSelect.onChange = onFilterChange; + +inArray_0.onChange = inArray_1.onChange = update; +onFilterChange(); + +function onFilterChange() +{ + const mathSelectValue = mathSelect.get(); + + if (mathSelectValue === "+") mathFunc = function (a, b) { return a + b; }; + else if (mathSelectValue === "-") mathFunc = function (a, b) { return a - b; }; + else if (mathSelectValue === "*") mathFunc = function (a, b) { return a * b; }; + else if (mathSelectValue === "/") mathFunc = function (a, b) { return a / b; }; + else if (mathSelectValue === "%") mathFunc = function (a, b) { return a % b; }; + else if (mathSelectValue === "min") mathFunc = function (a, b) { return Math.min(a, b); }; + else if (mathSelectValue === "max") mathFunc = function (a, b) { return Math.max(a, b); }; + update(); + op.setUiAttrib({ "extendTitle": mathSelectValue }); +} + +function update() +{ + const array0 = inArray_0.get(); + const array1 = inArray_1.get(); + + if (!array0 || !array1) + { + outArray.set(null); + outArrayLength.set(0); + return; + } + + const l = mathArray.length = array0.length; + + for (let i = 0; i < l; i++) + { + mathArray[i] = mathFunc(array0[i], array1[i]); + } + + outArray.set(null); + outArrayLength.set(mathArray.length); + outArray.set(mathArray); +} + + +}; + +Ops.Array.ArrayMathArray.prototype = new CABLES.Op(); +CABLES.OPS["f31a1764-ce14-41de-9b3f-dc2fe249bb52"]={f:Ops.Array.ArrayMathArray,objName:"Ops.Array.ArrayMathArray"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayMathExpression +// +// ************************************************************** + +Ops.Array.ArrayMathExpression = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inA = op.inArray("A"), + inB = op.inArray("B"), + inC = op.inArray("C"), + + inX = op.inFloat("X", 1), + inY = op.inFloat("Y", 1), + inZ = op.inFloat("Z", 1), + + inExpression = op.inString("Expression", "a*(b+c+d)"), + + outResultArray = op.outArray("Result Array"), + outLength = op.outNumber("Array Length"), + outExpressionIsValid = op.outBool("Expression Valid"); + +op.setPortGroup("Expression", [inExpression]); +op.setPortGroup("Parameters", [inA, inB, inC, inX, inY, inZ]); + +const functionChanged = false; +const inputsChanged = false; +const resultArray = []; +let currentFunction = inExpression.get(); +let functionValid = false; +let showingError = false; + +inA.onChange = inB.onChange = inC.onChange + = inX.onChange = inY.onChange = inZ.onChange = evaluateFunction; +inExpression.onChange = createFunction; + +function createFunction() +{ + try + { + currentFunction = new Function("m", "a", "b", "c", "x", "y", "z", "i", "len", `with(m) { return ${inExpression.get()} }`); + functionValid = true; + evaluateFunction(); + + outExpressionIsValid.set(functionValid); + } + catch (e) + { + functionValid = false; + + outExpressionIsValid.set(functionValid); + outResultArray.set(null); + + if (e instanceof ReferenceError || e instanceof SyntaxError) return; + } +} + +function evaluateFunction() +{ + const arrayA = inA.get(); + const arrayB = inB.get(); + const arrayC = inC.get(); + const arrays = [arrayA, arrayB, arrayC]; + + const x = inX.get(); + const y = inY.get(); + const z = inZ.get(); + + // * check if we have at least 2 arrays that are valid + if (arrays.filter(Boolean).length === 0) + { + outResultArray.set(null); + outLength.set(0); + outResultArray.set(null); + return; + } + else + { + const arrayLengths = arrays.map((arr) => (arr ? arr.length : undefined)); + const firstValidArrayLength = arrayLengths.find(Boolean); + const sameLength = arrayLengths.filter(Boolean).every((length) => length === firstValidArrayLength); + + let validArrays = []; + + if (sameLength) + { + op.setUiError("notsamelength", null); + const firstValidArray = arrays.find(Boolean); + validArrays = arrays.map((arr, index) => + { + // * map all undefined arrays to 0 values + if (!arr) arr = arrays.find(Boolean).map((x) => 0); + + return arr; + }); + + resultArray.length = firstValidArray.length; + + if (functionValid) + { + for (let i = 0; i < firstValidArray.length; i += 1) + { + resultArray[i] = currentFunction( + Math, + validArrays[0][i], validArrays[1][i], validArrays[2][i], + x, y, z, + i, + resultArray.length + ); + } + + outResultArray.set(null); + outResultArray.set(resultArray); + outLength.set(resultArray.length); + } + } + else + { + outResultArray.set(null); + outLength.set(0); + op.setUiError("notsamelength", "Arrays do not have the same length!", 2); + showingError = true; + } + } + + outExpressionIsValid.set(functionValid); +} + + +}; + +Ops.Array.ArrayMathExpression.prototype = new CABLES.Op(); +CABLES.OPS["663e32a2-45a1-4141-a387-d8a44d4977d5"]={f:Ops.Array.ArrayMathExpression,objName:"Ops.Array.ArrayMathExpression"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayMathExpressionTrigger +// +// ************************************************************** + +Ops.Array.ArrayMathExpressionTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTrigger = op.inTrigger("Update"), + inA = op.inArray("A"), + inB = op.inArray("B"), + inC = op.inArray("C"), + + inX = op.inFloat("X", 1), + inY = op.inFloat("Y", 1), + inZ = op.inFloat("Z", 1), + + inExpression = op.inString("Expression", "a*(b+c+d)"), + + outNext = op.outTrigger("Next"), + + outResultArray = op.outArray("Result Array"), + outLength = op.outNumber("Array Length"), + outExpressionIsValid = op.outBool("Expression Valid"); + +op.setPortGroup("Expression", [inExpression]); +op.setPortGroup("Parameters", [inA, inB, inC, inX, inY, inZ]); + +const functionChanged = false; +const inputsChanged = false; +const resultArray = []; +let currentFunction = inExpression.get(); +let functionValid = false; +let showingError = false; +let needsupdate = true; + +inA.onChange = inB.onChange = inC.onChange + = inX.onChange = inY.onChange = inZ.onChange = () => { needsupdate = true; }; + +inTrigger.onTriggered = evaluateFunction; +inExpression.onChange = createFunction; + +function createFunction() +{ + try + { + currentFunction = new Function("m", "a", "b", "c", "x", "y", "z", "i", "len", `with(m) { return ${inExpression.get()} }`); + functionValid = true; + evaluateFunction(); + + outExpressionIsValid.set(functionValid); + } + catch (e) + { + functionValid = false; + + outExpressionIsValid.set(functionValid); + outResultArray.set(null); + + if (e instanceof ReferenceError || e instanceof SyntaxError) return; + } +} + +function evaluateFunction() +{ + if (needsupdate) + { + const arrayA = inA.get(); + const arrayB = inB.get(); + const arrayC = inC.get(); + const arrays = [arrayA, arrayB, arrayC]; + + const x = inX.get(); + const y = inY.get(); + const z = inZ.get(); + + // * check if we have at least 2 arrays that are valid + if (arrays.filter(Boolean).length === 0) + { + outResultArray.set(null); + outLength.set(0); + outResultArray.set(null); + return; + } + else + { + const arrayLengths = arrays.map((arr) => (arr ? arr.length : undefined)); + const firstValidArrayLength = arrayLengths.find(Boolean); + const sameLength = arrayLengths.filter(Boolean).every((length) => length === firstValidArrayLength); + + let validArrays = []; + + if (sameLength) + { + op.setUiError("notsamelength", null); + const firstValidArray = arrays.find(Boolean); + validArrays = arrays.map((arr, index) => + { + // * map all undefined arrays to 0 values + if (!arr) arr = arrays.find(Boolean).map((x) => 0); + + return arr; + }); + + resultArray.length = firstValidArray.length; + + if (functionValid) + { + for (let i = 0; i < firstValidArray.length; i += 1) + { + resultArray[i] = currentFunction( + Math, + validArrays[0][i], validArrays[1][i], validArrays[2][i], + x, y, z, + i, + resultArray.length + ); + } + + outResultArray.set(null); + outResultArray.set(resultArray); + outLength.set(resultArray.length); + } + } + else + { + outResultArray.set(null); + outLength.set(0); + op.setUiError("notsamelength", "Arrays do not have the same length!", 2); + showingError = true; + } + } + + outExpressionIsValid.set(functionValid); + needsupdate = false; + } + outNext.trigger(); +} + + +}; + +Ops.Array.ArrayMathExpressionTrigger.prototype = new CABLES.Op(); +CABLES.OPS["e0d5da32-8463-4dfb-89f5-0d755167cd49"]={f:Ops.Array.ArrayMathExpressionTrigger,objName:"Ops.Array.ArrayMathExpressionTrigger"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayMax +// +// ************************************************************** + +Ops.Array.ArrayMax = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArray = op.inArray("Array In"); +const inValue = op.inValue("Value", 1.0); +const outArray = op.outArray("Array Out"); + +let newArr = []; +outArray.set(newArr); + +inValue.onChange = inArray.onChange = function () +{ + let arr = inArray.get(); + if (!arr) return; + + let inMax = inValue.get(); + + if (newArr.length != arr.length)newArr.length = arr.length; + + let i = 0; + for (i = 0; i < arr.length; i++) + { + newArr[i] = Math.max(arr[i], inMax); + } + outArray.set(null); + outArray.set(newArr); +}; + + +}; + +Ops.Array.ArrayMax.prototype = new CABLES.Op(); +CABLES.OPS["3bf1ead6-e8d2-43dd-a631-93f7a15fc270"]={f:Ops.Array.ArrayMax,objName:"Ops.Array.ArrayMax"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayMergeTrigger +// +// ************************************************************** + +Ops.Array.ArrayMergeTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Merge"), + next = op.outTrigger("Next"); + +const numArrays = 12; +const inArrs = []; +let needsUpdate = true; + +for (let i = 0; i < numArrays; i++) +{ + inArrs[i] = op.inArray("Array " + i); + inArrs[i].onChange = () => + { + needsUpdate = true; + }; +} + +const + outArr = op.outArray("Result"), + outArrayLength = op.outNumber("Array length"); + +let arr = []; + +exec.onTriggered = () => +{ + if (needsUpdate) + { + arr.length = 0; + + for (let i = 0; i < numArrays; i++) + { + const ar = inArrs[i].get(); + if (ar)arr = arr.concat(ar); + } + + outArr.set(null); + outArr.set(arr); + outArrayLength.set(arr.length); + } + + next.trigger(); +}; + + +}; + +Ops.Array.ArrayMergeTrigger.prototype = new CABLES.Op(); +CABLES.OPS["f45fdd5e-b20a-4553-a83b-57eed8a98c80"]={f:Ops.Array.ArrayMergeTrigger,objName:"Ops.Array.ArrayMergeTrigger"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayMerge_v3 +// +// ************************************************************** + +Ops.Array.ArrayMerge_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const numArrays = 8; +const inArrs = []; + +for (let i = 0; i < numArrays; i++) +{ + inArrs[i] = op.inArray("Array " + i); + inArrs[i].onChange = function () + { + update(); + }; +} + +const + outArr = op.outArray("Result"), + outArrayLength = op.outNumber("Array length"); + +let arr = []; + +function update() +{ + arr.length = 0; + + for (let i = 0; i < numArrays; i++) + { + const ar = inArrs[i].get(); + if (ar)arr = arr.concat(ar); + } + + outArr.set(null); + outArr.set(arr); + outArrayLength.set(arr.length); +} + + +}; + +Ops.Array.ArrayMerge_v3.prototype = new CABLES.Op(); +CABLES.OPS["753d053a-04a3-44c7-abf0-ae2676ced13e"]={f:Ops.Array.ArrayMerge_v3,objName:"Ops.Array.ArrayMerge_v3"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayMin +// +// ************************************************************** + +Ops.Array.ArrayMin = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArray = op.inArray("Array In"); +const inValue = op.inValue("Value", 1.0); +const outArray = op.outArray("Array Out"); + +let newArr = []; +outArray.set(newArr); + +inValue.onChange = inArray.onChange = function () +{ + let arr = inArray.get(); + if (!arr) return; + + let inMin = inValue.get(); + + if (newArr.length != arr.length)newArr.length = arr.length; + + let i = 0; + for (i = 0; i < arr.length; i++) + { + newArr[i] = Math.min(arr[i], inMin); + } + outArray.set(null); + outArray.set(newArr); +}; + + +}; + +Ops.Array.ArrayMin.prototype = new CABLES.Op(); +CABLES.OPS["fbb78acc-c004-4669-a277-98c47eb59598"]={f:Ops.Array.ArrayMin,objName:"Ops.Array.ArrayMin"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayModulo +// +// ************************************************************** + +Ops.Array.ArrayModulo = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArray = op.inArray("Array In"), + inValue = op.inValue("Value", 2.0), + outArray = op.outArray("Array Out"); + +let newArr = []; +outArray.set(newArr); +inArray.onChange = +inValue.onChange = inArray.onChange = function () +{ + let arr = inArray.get(); + if (!arr) return; + + let modulo = inValue.get(); + + if (newArr.length != arr.length) newArr.length = arr.length; + + let i = 0; + for (i = 0; i < arr.length; i++) + { + newArr[i] = arr[i] % modulo; + } + outArray.set(null); + outArray.set(newArr); +}; + + +}; + +Ops.Array.ArrayModulo.prototype = new CABLES.Op(); +CABLES.OPS["30a5568b-31da-4504-9525-578ee404993c"]={f:Ops.Array.ArrayModulo,objName:"Ops.Array.ArrayModulo"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayMultiply +// +// ************************************************************** + +Ops.Array.ArrayMultiply = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArray = op.inArray("In"), + inValue = op.inValue("Value", 1.0), + outArray = op.outArray("Result"); + +let newArr = []; +outArray.set(newArr); +inArray.onChange = +inValue.onChange = inArray.onChange = function () +{ + let arr = inArray.get(); + if (!arr) return; + + let mul = inValue.get(); + + if (newArr.length != arr.length)newArr.length = arr.length; + + for (let i = 0; i < arr.length; i++) + { + newArr[i] = arr[i] * mul; + } + + outArray.set(null); + outArray.set(newArr); +}; + +inArray.onLinkChanged = () => +{ + if (inArray) inArray.copyLinkedUiAttrib("stride", outArray); +}; + + +}; + +Ops.Array.ArrayMultiply.prototype = new CABLES.Op(); +CABLES.OPS["a01c344b-4129-4b01-9c8f-36cefe86d7cc"]={f:Ops.Array.ArrayMultiply,objName:"Ops.Array.ArrayMultiply"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayOfArrays +// +// ************************************************************** + +Ops.Array.ArrayOfArrays = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; + +const + inExec = op.inTriggerButton("Update"), + outArr = op.outArray("Result"); + +inExec.onTriggered = update; +const arrayPorts = []; +const finalArray = []; + +for (let i = 0; i < 10; i++) +{ + arrayPorts.push(op.inArray("Array " + i)); +} + + +function update() +{ + let count = 0; + for (let i = 0; i < arrayPorts.length; i++) if (arrayPorts[i].get()) + { + finalArray[count] = arrayPorts[i].get(); + count++; + } + + finalArray.length = count; + + outArr.set(null); + outArr.set(finalArray); +} + + +}; + +Ops.Array.ArrayOfArrays.prototype = new CABLES.Op(); +CABLES.OPS["7a7b84c7-39e9-4e00-84cc-a8d7049d8247"]={f:Ops.Array.ArrayOfArrays,objName:"Ops.Array.ArrayOfArrays"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayOfObjectsFilterByKeyValue +// +// ************************************************************** + +Ops.Array.ArrayOfObjectsFilterByKeyValue = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArray = op.inArray("Array"); +const inKeyToFilterBy = op.inString("Filter Key", ""); +const inKeyShouldEqual = op.inString("Filter Value", ""); +const inInvertEquality = op.inBool("Invert Filter", false); +const outArray = op.outArray("arrayOut"); + +const COMPARATOR_FUNC = (obj, comparator, key) => { return obj[key] == comparator; }; +const INV_COMPARATOR_FUNC = (obj, comparator, key) => { return (obj[key] != comparator); }; + +inArray.onChange = inInvertEquality.onChange += inKeyToFilterBy.onChange = inKeyShouldEqual.onChange = function () { + const inValue = inArray.get(); + if (!inValue) { + return; + } + + if (Array.isArray(inValue)) { + const key = inKeyToFilterBy.get(); + + if (!inKeyShouldEqual.get()) { + outArray.set(null); + outArray.set(inValue); + return; // no filter value given + } + + const comparatorFunction = !inInvertEquality.get() ? + COMPARATOR_FUNC : INV_COMPARATOR_FUNC; + + const filteredArray = []; + const keyToEqual = inKeyShouldEqual.get(); + for (let i = 0, len = inValue.length; i < len; i += 1) { + const obj = inValue[i]; + if (comparatorFunction(obj, keyToEqual, key)) { + filteredArray.push(obj); + } + } + + outArray.set(null); + outArray.set(filteredArray); + } + else + { + outArray.set(null); + } +}; + + +}; + +Ops.Array.ArrayOfObjectsFilterByKeyValue.prototype = new CABLES.Op(); +CABLES.OPS["0d4b9bba-2c00-49f7-b486-86e4cde2428e"]={f:Ops.Array.ArrayOfObjectsFilterByKeyValue,objName:"Ops.Array.ArrayOfObjectsFilterByKeyValue"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayOfObjectsFilterKeys +// +// ************************************************************** + +Ops.Array.ArrayOfObjectsFilterKeys = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArray = op.inArray("Array"); +const inKeysToKeep = op.inStringEditor("Keys",'1,2,3'); +const inSeperator = op.inString("Seperator", ","); +const inInvert = op.inBool("Invert Filter", false); +const outArray = op.outArray("Array Out"); + +const COMPARATOR_FUNC = (arr, key) => arr.includes(key); +const INV_COMPARATOR_FUNC = (arr, key) => !(arr.includes(key)); + +inArray.onChange = inKeysToKeep.onChange = inInvert.onChange = inSeperator.onChange = +function () { + if (!inKeysToKeep.get()) return; + const keys = inKeysToKeep.get().split(inSeperator.get()); + const inValue = inArray.get(); + + if (Array.isArray(inValue)) { + const newArray = []; + const comparatorFunc = !inInvert.get() ? COMPARATOR_FUNC : INV_COMPARATOR_FUNC + + for (let i = 0, len = inValue.length; i < len; i += 1) { + const obj = inValue[i]; + const objKeys = Object.keys(obj); + const newObj = {}; + + for (let j = 0, len2 = objKeys.length; j < len2; j += 1) { + const key = objKeys[j]; + if (comparatorFunc(keys, key)) + Object.assign(newObj, { [key]: obj[key] }); + } + + newArray.push(newObj); + } + + outArray.set(null); + outArray.set(newArray); + } + else { + outArray.set(null); + } +}; + + +}; + +Ops.Array.ArrayOfObjectsFilterKeys.prototype = new CABLES.Op(); +CABLES.OPS["8c9a7621-51c7-46b7-934b-1924cb0ff0b6"]={f:Ops.Array.ArrayOfObjectsFilterKeys,objName:"Ops.Array.ArrayOfObjectsFilterKeys"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayOfObjectsToString +// +// ************************************************************** + +Ops.Array.ArrayOfObjectsToString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArray = op.inArray("Array In"); +const outString = op.outString("String"); + +inArray.onChange = function() { + if (!inArray.get()) { + outString.set(""); + return; + } + + const arr = inArray.get(); + let result = ""; + + for (let i = 0; i < arr.length; i += 1) { + const objToString = JSON.stringify(arr[i]); + result += "\n" + objToString; + } + + outString.set(result); +} + +}; + +Ops.Array.ArrayOfObjectsToString.prototype = new CABLES.Op(); +CABLES.OPS["1593cd67-2a90-43ab-b95e-ad6bbe9af37e"]={f:Ops.Array.ArrayOfObjectsToString,objName:"Ops.Array.ArrayOfObjectsToString"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayPack +// +// ************************************************************** + +Ops.Array.ArrayPack = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const outArr = op.outArray("Result"); + +const NUM_PORTS = 8; +const inArrPorts = []; + +let showingError = false; + +for (let i = 0; i < NUM_PORTS; i++) +{ + let p = op.inArray("Array " + i); + p.onChange = update; + inArrPorts.push(p); +} + +function update() +{ + const arr = []; + const inArrays = []; + let i = 0; + + for (i = 0; i < NUM_PORTS; i++) + { + let a = inArrPorts[i].get(); + if (a) + { + inArrays.push(a); + if (a.length != inArrays[0].length) + { + if (!showingError)op.setUiError("arraylen", "Arrays do not have the same length !"); + outArr.set(null); + showingError = true; + return; + } + } + } + + if (inArrays.length === 0) + { + if (!showingError)op.setUiError("invalid", "No Valid Arrays"); + // op.uiAttr({ "error": "No Valid Arrays" }); + outArr.set(null); + showingError = true; + return; + } + + if (showingError) + { + op.setUiError("arraylen", null); + op.setUiError("invalid", null); + } + showingError = false; + + for (let j = 0; j < inArrays[0].length; j++) + for (i = 0; i < inArrays.length; i++) + arr.push(inArrays[i][j]); + + outArr.set(null); + outArr.set(arr); +} + + +}; + +Ops.Array.ArrayPack.prototype = new CABLES.Op(); +CABLES.OPS["51df396d-87be-4890-8fbd-c8bb3d364d3b"]={f:Ops.Array.ArrayPack,objName:"Ops.Array.ArrayPack"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayPack2 +// +// ************************************************************** + +Ops.Array.ArrayPack2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTriggerButton("Trigger in"), + inArr1 = op.inArray("Array 1"), + inArr2 = op.inArray("Array 2"), + exeOut = op.outTrigger("Trigger out"), + outArr = op.outArray("Array out", null, 2), + outArrayLength = op.outNumber("Array length"); + +let showingError = false; + +let arr = []; +let emptyArray = []; +let needsCalc = true; + +exe.onTriggered = update; + +inArr1.onChange = inArr2.onChange = calcLater; +function calcLater() +{ + needsCalc = true; +} + +function update() +{ + let array1 = inArr1.get(); + let array2 = inArr2.get(); + + if (!array1 && !array2) + { + outArr.set(null); + return; + } + if (needsCalc) + { + let arrlen = 0; + + if (!array1 || !array2) + { + if (array1) arrlen = array1.length; + else if (array2) arrlen = array2.length; + + if (emptyArray.length != arrlen) + for (var i = 0; i < arrlen; i++) emptyArray[i] = 0; + + if (!array1)array1 = emptyArray; + if (!array2)array2 = emptyArray; + } + + if (array1.length !== array2.length) + { + if (!showingError) + { + op.uiAttr({ "error": "Arrays do not have the same length !" }); + showingError = true; + } + return; + } + + if (showingError) + { + showingError = false; + op.uiAttr({ "error": null }); + } + + arr.length = array1.length; + for (var i = 0; i < array1.length; i++) + { + arr[i * 2 + 0] = array1[i]; + arr[i * 2 + 1] = array2[i]; + } + + needsCalc = false; + outArr.set(null); + outArr.set(arr); + outArrayLength.set(arr.length); + } + + exeOut.trigger(); +} + + +}; + +Ops.Array.ArrayPack2.prototype = new CABLES.Op(); +CABLES.OPS["0db296db-e4a7-4356-9593-858f7e1bc7f3"]={f:Ops.Array.ArrayPack2,objName:"Ops.Array.ArrayPack2"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayPack3 +// +// ************************************************************** + +Ops.Array.ArrayPack3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe = op.inTrigger("Trigger in"), + inArr1 = op.inArray("Array 1"), + inArr2 = op.inArray("Array 2"), + inArr3 = op.inArray("Array 3"), + exeOut = op.outTrigger("Trigger out"), + outArr = op.outArray("Array out", 3), + outNum = op.outNumber("Num Points"), + outArrayLength = op.outNumber("Array length"); + +let showingError = false; + +let arr = []; +let emptyArray = []; +let needsCalc = true; + +exe.onTriggered = update; + +inArr1.onChange = inArr2.onChange = inArr3.onChange = calcLater; + +function calcLater() +{ + needsCalc = true; +} + +function update() +{ + let array1 = inArr1.get(); + let array2 = inArr2.get(); + let array3 = inArr3.get(); + + if (!array1 && !array2 && !array3) + { + outArr.set(null); + outNum.set(0); + return; + } + // only update if array has changed + if (needsCalc) + { + let arrlen = 0; + + if (!array1 || !array2 || !array3) + { + if (array1) arrlen = array1.length; + else if (array2) arrlen = array2.length; + else if (array3) arrlen = array3.length; + + if (emptyArray.length != arrlen) + for (var i = 0; i < arrlen; i++) emptyArray[i] = 0; + + if (!array1)array1 = emptyArray; + if (!array2)array2 = emptyArray; + if (!array3)array3 = emptyArray; + } + + if ((array1.length !== array2.length) || (array2.length !== array3.length)) + { + op.setUiError("arraylen", "Arrays do not have the same length !"); + return; + } + op.setUiError("arraylen", null); + + arr.length = array1.length; + for (var i = 0; i < array1.length; i++) + { + arr[i * 3 + 0] = array1[i]; + arr[i * 3 + 1] = array2[i]; + arr[i * 3 + 2] = array3[i]; + } + + needsCalc = false; + outArr.set(null); + outArr.set(arr); + outNum.set(arr.length / 3); + outArrayLength.set(arr.length); + } + + exeOut.trigger(); +} + + +}; + +Ops.Array.ArrayPack3.prototype = new CABLES.Op(); +CABLES.OPS["2bcf32fe-3cbd-48fd-825a-61255bebda9b"]={f:Ops.Array.ArrayPack3,objName:"Ops.Array.ArrayPack3"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayPack3Simple +// +// ************************************************************** + +Ops.Array.ArrayPack3Simple = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr1 = op.inArray("Array 1"), + inArr2 = op.inArray("Array 2"), + inArr3 = op.inArray("Array 3"), + + outArr = op.outArray("Array out", 3), + outNum = op.outNumber("Num Points"), + outArrayLength = op.outNumber("Array length"); + +let showingError = false; + +let arr = []; +let emptyArray = []; +let needsCalc = true; + +inArr1.onChange = inArr2.onChange = inArr3.onChange = update; + +function update() +{ + let array1 = inArr1.get(); + let array2 = inArr2.get(); + let array3 = inArr3.get(); + + if (!array1 && !array2 && !array3) + { + outArr.set(null); + outNum.set(0); + return; + } + let arrlen = 0; + + if (!array1 || !array2 || !array3) + { + if (array1) arrlen = array1.length; + else if (array2) arrlen = array2.length; + else if (array3) arrlen = array3.length; + + if (emptyArray.length != arrlen) + for (var i = 0; i < arrlen; i++) emptyArray[i] = 0; + + if (!array1)array1 = emptyArray; + if (!array2)array2 = emptyArray; + if (!array3)array3 = emptyArray; + } + + if ((array1.length !== array2.length) || (array2.length !== array3.length)) + { + // + op.setUiError("arraylen", "Arrays do not have the same length !"); + return; + } + op.setUiError("arraylen", null); + + arr.length = array1.length; + for (var i = 0; i < array1.length; i++) + { + arr[i * 3 + 0] = array1[i]; + arr[i * 3 + 1] = array2[i]; + arr[i * 3 + 2] = array3[i]; + } + + needsCalc = false; + outArr.set(null); + outArr.set(arr); + outNum.set(arr.length / 3); + outArrayLength.set(arr.length); +} + + +}; + +Ops.Array.ArrayPack3Simple.prototype = new CABLES.Op(); +CABLES.OPS["9c48785b-4cac-472c-a70f-dbd3c240b782"]={f:Ops.Array.ArrayPack3Simple,objName:"Ops.Array.ArrayPack3Simple"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayPack4 +// +// ************************************************************** + +Ops.Array.ArrayPack4 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe = op.inTrigger("Trigger in"), + inArr1 = op.inArray("Array 1"), + inArr2 = op.inArray("Array 2"), + inArr3 = op.inArray("Array 3"), + inArr4 = op.inArray("Array 4"), + outTrigger = op.outTrigger("Trigger out"), + outArr = op.outArray("Array out", 4), + outArrayLength = op.outNumber("Array length"); + +let showingError = false; +let arr = []; +let emptyArray = []; +let needsCalc = true; + +exe.onTriggered = update; + +inArr1.onChange = inArr2.onChange = inArr3.onChange = inArr4.onChange = calcLater; +function calcLater() +{ + needsCalc = true; +} + +function update() +{ + outTrigger.trigger(); + let array1 = inArr1.get(); + let array2 = inArr2.get(); + let array3 = inArr3.get(); + let array4 = inArr4.get(); + + if (!array1 && !array2 && !array3 && !array4) + { + outArr.set(null); + return; + } + + if (needsCalc) + { + let arrlen = 0; + + if (!array1 || !array2 || !array3 || !array4) + { + if (array1) arrlen = array1.length; + else if (array2) arrlen = array2.length; + else if (array3) arrlen = array3.length; + else if (array4) arrlen = array4.length; + + if (emptyArray.length != arrlen) + for (var i = 0; i < arrlen; i++) emptyArray[i] = 0; + + if (!array1)array1 = emptyArray; + if (!array2)array2 = emptyArray; + if (!array3)array3 = emptyArray; + if (!array4)array4 = emptyArray; + } + + if ((array1.length !== array2.length) || (array2.length !== array3.length) + || (array3.length !== array4.length)) + { + if (!showingError) + { + op.setUiError("arrlength", "Arrays do not have the same length !"); + outArrayLength.set(0); + showingError = true; + } + return; + } + + if (showingError) + { + showingError = false; + op.setUiError("arrlength", null); + } + + arr.length = array1.length; + + for (var i = 0; i < array1.length; i++) + { + arr[i * 4 + 0] = array1[i]; + arr[i * 4 + 1] = array2[i]; + arr[i * 4 + 2] = array3[i]; + arr[i * 4 + 3] = array4[i]; + } + needsCalc = false; + outArr.set(null); + outArr.set(arr); + outArrayLength.set(arr.length); + } +} + + +}; + +Ops.Array.ArrayPack4.prototype = new CABLES.Op(); +CABLES.OPS["68ea2c83-05fc-47a7-aba8-3c400f1dd737"]={f:Ops.Array.ArrayPack4,objName:"Ops.Array.ArrayPack4"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayPack4Simple +// +// ************************************************************** + +Ops.Array.ArrayPack4Simple = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr1 = op.inArray("Array 1"), + inArr2 = op.inArray("Array 2"), + inArr3 = op.inArray("Array 3"), + inArr4 = op.inArray("Array 4"), + + outArr = op.outArray("Array out", 4), + outNum = op.outNumber("Num Points"), + outArrayLength = op.outNumber("Array length"); + +let showingError = false; + +let arr = []; +let emptyArray = []; +let needsCalc = true; + +inArr1.onChange = inArr2.onChange = inArr3.onChange = inArr4.onChange = update; + +function update() +{ + let array1 = inArr1.get(); + let array2 = inArr2.get(); + let array3 = inArr3.get(); + let array4 = inArr4.get(); + + if (!array1 && !array2 && !array3 && !array4) + { + outArr.set(null); + outNum.set(0); + return; + } + let arrlen = 0; + + if (!array1 || !array2 || !array3 || !array4) + { + if (array1) arrlen = array1.length; + else if (array2) arrlen = array2.length; + else if (array3) arrlen = array3.length; + else if (array4) arrlen = array4.length; + + if (emptyArray.length != arrlen) + for (let i = 0; i < arrlen; i++) emptyArray[i] = 0; + + if (!array1)array1 = emptyArray; + if (!array2)array2 = emptyArray; + if (!array3)array3 = emptyArray; + if (!array4)array4 = emptyArray; + } + + if ((array1.length !== array2.length) || (array2.length !== array3.length)) + { + // + op.setUiError("arraylen", "Arrays do not have the same length !"); + return; + } + op.setUiError("arraylen", null); + + arr.length = array1.length * 4; + for (let i = 0; i < array1.length; i++) + { + arr[i * 4 + 0] = array1[i]; + arr[i * 4 + 1] = array2[i]; + arr[i * 4 + 2] = array3[i]; + arr[i * 4 + 3] = array4[i]; + } + + needsCalc = false; + outArr.set(null); + outArr.set(arr); + outNum.set(arr.length / 4); + outArrayLength.set(arr.length); +} + + +}; + +Ops.Array.ArrayPack4Simple.prototype = new CABLES.Op(); +CABLES.OPS["6fe2bb0e-4bfc-42c1-8bc1-19fda052e091"]={f:Ops.Array.ArrayPack4Simple,objName:"Ops.Array.ArrayPack4Simple"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayPow +// +// ************************************************************** + +Ops.Array.ArrayPow = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// The pow function will not work correctly with neagtive numbers +// Use the ArrayAbs op to make numbers have only positive values +// to work correctly with this op + +let inArray = op.inArray("Array in"); +let inValue = op.inValue("Pow factor", 1.0); +let outArray = op.outArray("Array out"); + +let newArr = []; +outArray.set(newArr); + +inArray.onChange = +inValue.onChange = inArray.onChange = function () +{ + let arr = inArray.get(); + if (!arr) return; + + let pow = inValue.get(); + if (pow < 0.0) + { + pow = 0.0; + } + + if (newArr.length !== arr.length)newArr.length = arr.length; + + for (let i = 0; i < arr.length; i++) + { + newArr[i] = Math.pow(arr[i], pow); + } + outArray.set(null); + outArray.set(newArr); +}; + + +}; + +Ops.Array.ArrayPow.prototype = new CABLES.Op(); +CABLES.OPS["d60b6c52-d142-41dd-a38d-d185148be33f"]={f:Ops.Array.ArrayPow,objName:"Ops.Array.ArrayPow"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayPushString +// +// ************************************************************** + +Ops.Array.ArrayPushString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr=op.inArray("Array"), + inString=op.inString("String",""), + result=op.outArray("Result"); + +const arr=[]; + + inString.onChange= + inArr.onChange= + function() + { + const oldArr=inArr.get(); + result.set(null); + if(!oldArr)return; + + arr.length=oldArr.length+1; + for(let i=0;i +{ + if (!inScale.get()) + { + outQuantized.set(inValue.get()); + outError.set(0); + return; + } + + const arr = inScale.get(); + const quantized = closest(inValue.get(), arr); + outQuantized.set(quantized); + outError.set(quantized - inValue.get()); +}; + + +}; + +Ops.Array.ArrayQuantizer.prototype = new CABLES.Op(); +CABLES.OPS["fc05b6ed-6584-4e37-aec2-fc659012ff60"]={f:Ops.Array.ArrayQuantizer,objName:"Ops.Array.ArrayQuantizer"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayRandomSelection +// +// ************************************************************** + +Ops.Array.ArrayRandomSelection = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArray = op.inArray("Array"), + inNum = op.inValueInt("Elements", 10), + inSeed = op.inValue("Seed", 1), + result = op.outArray("Result"), + outArrayLength = op.outNumber("Array length"); + +let arr = []; +inSeed.onChange = inArray.onChange = inNum.onChange = update; + +function update() +{ + if (Math.floor(inNum.get()) < 0 || !inArray.get()) + { + result.set(null); + outArrayLength.set(0); + return; + } + + let oldArr = inArray.get(); + + arr.length = Math.floor(inNum.get()); + + let nums = []; + + for (var i = 0; i < Math.max(arr.length, oldArr.length); i++) + nums[i] = i % (oldArr.length); + + nums = CABLES.shuffleArray(nums); + + Math.randomSeed = inSeed.get(); + + for (var i = 0; i < inNum.get(); i++) + { + let index = nums[i]; + arr[i] = oldArr[index]; + } + result.set(null); + result.set(arr); + outArrayLength.set(arr.length); +} + + +}; + +Ops.Array.ArrayRandomSelection.prototype = new CABLES.Op(); +CABLES.OPS["3dc059c8-bcb3-4d63-b806-ce81215da3b5"]={f:Ops.Array.ArrayRandomSelection,objName:"Ops.Array.ArrayRandomSelection"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayReverse +// +// ************************************************************** + +Ops.Array.ArrayReverse = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Input"), + outArr = op.outArray("Result"); + +inArr.onChange = function () +{ + let arr = inArr.get(); + if (arr) + { + let arrCopy = arr.slice(); + outArr.set(arrCopy.reverse()); + } +}; + + +}; + +Ops.Array.ArrayReverse.prototype = new CABLES.Op(); +CABLES.OPS["88d8662f-2c01-42e6-943d-4d3cf90657b0"]={f:Ops.Array.ArrayReverse,objName:"Ops.Array.ArrayReverse"}; + + + + +// ************************************************************** +// +// Ops.Array.ArraySetArray +// +// ************************************************************** + +Ops.Array.ArraySetArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe=op.inTriggerButton("exe"), + array=op.inArray("array"), + index=op.inValueInt("index"), + value=op.inArray("new Array"), + values=op.outArray("values"); + +values.ignoreValueSerialize=true; + +function updateIndex() +{ + if(exe.isLinked())return; + update(); +} + +function copyArray(source) +{ + var dest=[]; + dest.length=source.length; + for (var i = 0, n = source.length; i < n; i++) dest[i] = source[i]; + + return dest; +} + + +function update() +{ + if(!array.get() || !value.get())return; + array.get()[index.get()]=copyArray(value.get()); + + values.set(null); + values.set(array.get()); +} + +exe.onTriggered=update; + + +}; + +Ops.Array.ArraySetArray.prototype = new CABLES.Op(); +CABLES.OPS["58ddcecb-3917-4118-81d3-344ee2b75469"]={f:Ops.Array.ArraySetArray,objName:"Ops.Array.ArraySetArray"}; + + + + +// ************************************************************** +// +// Ops.Array.ArraySetNumber3 +// +// ************************************************************** + +Ops.Array.ArraySetNumber3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTrigger = op.inTriggerButton("Execute"), + inArray = op.inArray("Array"), + inIndex = op.inInt("Index", 0), + inValueX = op.inFloat("X", 1), + inValueY = op.inFloat("Y", 1), + inValueZ = op.inFloat("Z", 1), + inReset = op.inTriggerButton("Reset"), + outArray = op.outArray("Result"); + +const newArr = []; + +inReset.onTriggered = function () +{ + copyArray(true); +}; +inArray.onChange = copyArray; + +inTrigger.onTriggered = +function () +{ + const arr = inArray.get(); + + if (!arr) return; + if (newArr.length != arr.length)newArr.length = arr.length; + + const idx = Math.floor(inIndex.get()); + + if (idx >= 0) + { + newArr[idx * 3 + 0] = inValueX.get(); + newArr[idx * 3 + 1] = inValueY.get(); + newArr[idx * 3 + 2] = inValueZ.get(); + } + + inArray.onChange = null; + outArray.set(null); + outArray.set(newArr); +}; + +function copyArray(force) +{ + const arr = inArray.get(); + + if (!arr) return; + + if (force === true || (arr && !outArray.get())) + { + if (newArr.length != arr.length) newArr.length = arr.length; + for (let i = 0; i < arr.length; i++) newArr[i] = arr[i]; + + outArray.set(null); + outArray.set(newArr); + } +} + + +}; + +Ops.Array.ArraySetNumber3.prototype = new CABLES.Op(); +CABLES.OPS["4edd6ccc-17c4-48c0-8eda-91bbc08e97db"]={f:Ops.Array.ArraySetNumber3,objName:"Ops.Array.ArraySetNumber3"}; + + + + +// ************************************************************** +// +// Ops.Array.ArraySetNumber_v2 +// +// ************************************************************** + +Ops.Array.ArraySetNumber_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTrigger = op.inTriggerButton("Execute"), + inArray = op.inArray("Array"), + inIndex = op.inInt("Index", 0), + inValue = op.inFloat("Number", 1), + outNext = op.outTrigger("Next"), + outArray = op.outArray("Result"); + +let arr = []; +inArray.onChange = () => +{ + arr = inArray.get(); +}; + +inTrigger.onTriggered = () => +{ + if (!arr) + { + outArray.set(null); + return; + } + + const newArr = []; + // if (newArr.length != arr.length) newArr.length = arr.length; + for (let i = 0; i < arr.length; i++) newArr[i] = arr[i]; + const idx = Math.floor(inIndex.get()); + + if (idx >= 0) + // if (idx >= 0 && idx < arr.length) + { + newArr[idx] = inValue.get(); + } + + arr = newArr; + outArray.set(null); + outArray.set(newArr); + outNext.trigger(); +}; + + +}; + +Ops.Array.ArraySetNumber_v2.prototype = new CABLES.Op(); +CABLES.OPS["a6366c3e-dab0-4b4c-b790-e66b82b93a25"]={f:Ops.Array.ArraySetNumber_v2,objName:"Ops.Array.ArraySetNumber_v2"}; + + + + +// ************************************************************** +// +// Ops.Array.ArraySetObject +// +// ************************************************************** + +Ops.Array.ArraySetObject = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe=op.inTriggerButton("exe"), + array=op.inArray("array"), + index=op.inValueInt("index"), + value=op.inObject("object"), + values=op.outArray("values"); + +values.ignoreValueSerialize=true; +exe.onTriggered=update; + +function updateIndex() +{ + if(exe.isLinked())return; + update(); +} + +function update() +{ + var arr=array.get(); + if(!arr)return; + arr[index.get()]=value.get(); + + values.set(null); + values.set(arr); +} + + + +}; + +Ops.Array.ArraySetObject.prototype = new CABLES.Op(); +CABLES.OPS["5cccb9a4-3653-4c58-b54e-932c4c585b5f"]={f:Ops.Array.ArraySetObject,objName:"Ops.Array.ArraySetObject"}; + + + + +// ************************************************************** +// +// Ops.Array.ArraySetString +// +// ************************************************************** + +Ops.Array.ArraySetString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTriggerButton("Execute"), + array = op.inArray("Array"), + index = op.inValueInt("Index"), + value = op.inString("String"), + values = op.outArray("Result"); + +values.ignoreValueSerialize = true; +exe.onTriggered = update; + +function updateIndex() +{ + if (exe.isLinked()) return; + update(); +} + +function update() +{ + const arr = array.get(); + if (!arr) return; + arr[index.get()] = value.get(); + + values.set(""); + values.set(arr); +} + + +}; + +Ops.Array.ArraySetString.prototype = new CABLES.Op(); +CABLES.OPS["2752b35e-592d-41db-b8dd-cdc43a7ccbe2"]={f:Ops.Array.ArraySetString,objName:"Ops.Array.ArraySetString"}; + + + + +// ************************************************************** +// +// Ops.Array.ArraySin +// +// ************************************************************** + +Ops.Array.ArraySin = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// this op allows the user to perform sin or cos +// math functions on an array +const inArray = op.inArray("array in"); +const mathSelect = op.inValueSelect("Math function", ["Sin", "Cos"], "Sin"); +const outArray = op.outArray("Array result"); + +const phase = op.inValue("Phase", 0.0); +const multiply = op.inValue("Frequency", 1.0); +const amplitude = op.inValue("Amplitude", 1.0); + +const mathArray = []; +let selectIndex = 0; + +const MATH_FUNC_SIN = 0; +const MATH_FUNC_COS = 1; + + +inArray.onChange = update; +multiply.onChange = update; +amplitude.onChange = update; +phase.onChange = update; +mathSelect.onChange = onFilterChange; + +function onFilterChange() +{ + const mathSelectValue = mathSelect.get(); + if (mathSelectValue === "Sin") selectIndex = MATH_FUNC_SIN; + else if (mathSelectValue === "Cos") selectIndex = MATH_FUNC_COS; + update(); +} + +function update() +{ + const arrayIn = inArray.get(); + + + if (!arrayIn) + { + mathArray.length = 0; + return; + } + + mathArray.length = arrayIn.length; + + const amp = amplitude.get(); + const mul = multiply.get(); + const pha = phase.get(); + + let i = 0; + if (selectIndex === MATH_FUNC_SIN) + { + for (i = 0; i < arrayIn.length; i++) + mathArray[i] = amp * Math.sin((arrayIn[i]) * mul + pha); + } + else if (selectIndex === MATH_FUNC_COS) + { + for (i = 0; i < arrayIn.length; i++) + mathArray[i] = amp * (Math.cos(arrayIn[i] * mul + pha)); + } + outArray.set(null); + outArray.set(mathArray); +} + + +}; + +Ops.Array.ArraySin.prototype = new CABLES.Op(); +CABLES.OPS["ded44bae-a24e-48c5-9585-4cb31f331ab6"]={f:Ops.Array.ArraySin,objName:"Ops.Array.ArraySin"}; + + + + +// ************************************************************** +// +// Ops.Array.ArraySmoothStep +// +// ************************************************************** + +Ops.Array.ArraySmoothStep = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArray = op.inArray("Array In"), + inMinimum = op.inValue("Min", 0.0), + inMaximum = op.inValue("Max", 1.0), + outArray = op.outArray("Array out"); + +let newArr = []; +outArray.set(newArr); + +inArray.onChange = +inMinimum.onChange = +inMaximum.onChange = inArray.onChange = function () +{ + let arr = inArray.get(); + if (!arr) return; + + let min = inMinimum.get(); + let max = inMaximum.get(); + + if (newArr.length != arr.length)newArr.length = arr.length; + + for (let i = 0; i < arr.length; i++) + { + newArr[i] = smoothstep(min, max, arr[i]); + } + outArray.set(null); + outArray.set(newArr); +}; + +function smoothstep(min, max, value) +{ + let x = Math.max(0.0, Math.min(1.0, (value - min) / (max - min))); + return x * x * (3 - 2 * x); +} + + +}; + +Ops.Array.ArraySmoothStep.prototype = new CABLES.Op(); +CABLES.OPS["eb95b563-937b-4189-a8c9-ba6776971719"]={f:Ops.Array.ArraySmoothStep,objName:"Ops.Array.ArraySmoothStep"}; + + + + +// ************************************************************** +// +// Ops.Array.ArraySqrt +// +// ************************************************************** + +Ops.Array.ArraySqrt = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArray = op.inArray("In"), + outArray = op.outArray("Result"); + +let newArr = []; +outArray.set(newArr); + +inArray.onChange = function () +{ + let arr = inArray.get(); + if (!arr) return; + + if (newArr.length != arr.length)newArr.length = arr.length; + + for (let i = 0; i < arr.length; i++) + { + newArr[i] = Math.sqrt(arr[i]); + } + outArray.set(null); + outArray.set(newArr); +}; + + +}; + +Ops.Array.ArraySqrt.prototype = new CABLES.Op(); +CABLES.OPS["93f3dc25-a1e7-46f5-9069-527c1bd2c3a3"]={f:Ops.Array.ArraySqrt,objName:"Ops.Array.ArraySqrt"}; + + + + +// ************************************************************** +// +// Ops.Array.ArraySubtract +// +// ************************************************************** + +Ops.Array.ArraySubtract = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let inArray = op.inArray("Array In"); +let inValue = op.inValue("Value", 1.0); +let outArray = op.outArray("Array Out"); + +let newArr = []; +outArray.set(newArr); +inArray.onChange = +inValue.onChange = inArray.onChange = function () +{ + let arr = inArray.get(); + if (!arr) return; + + let subtract = inValue.get(); + + if (newArr.length != arr.length)newArr.length = arr.length; + + let i = 0; + for (i = 0; i < arr.length; i++) + { + newArr[i] = arr[i] - subtract; + } + outArray.set(null); + outArray.set(newArr); +}; + + +}; + +Ops.Array.ArraySubtract.prototype = new CABLES.Op(); +CABLES.OPS["af78ab59-75d5-4ead-9a8d-27a63e1cbf3f"]={f:Ops.Array.ArraySubtract,objName:"Ops.Array.ArraySubtract"}; + + + + +// ************************************************************** +// +// Ops.Array.ArraySum +// +// ************************************************************** + +Ops.Array.ArraySum = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArray = op.inArray("In"), + inValue = op.inValue("Value", 1.0), + outArray = op.outArray("Result"); + +let newArr = []; +outArray.set(newArr); + +inValue.onChange = +inArray.onChange = function () +{ + let arr = inArray.get(); + if (!arr) return; + + let add = inValue.get(); + + if (newArr.length != arr.length)newArr.length = arr.length; + + for (let i = 0; i < arr.length; i++) + { + newArr[i] = arr[i] + add; + } + + outArray.set(null); + outArray.set(newArr); +}; + + +}; + +Ops.Array.ArraySum.prototype = new CABLES.Op(); +CABLES.OPS["c6b5bf63-0be8-4eea-acc0-9d32973e665a"]={f:Ops.Array.ArraySum,objName:"Ops.Array.ArraySum"}; + + + + +// ************************************************************** +// +// Ops.Array.ArraySumPrevious +// +// ************************************************************** + +Ops.Array.ArraySumPrevious = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr=op.inArray("Array"), + inPad=op.inFloat("Padding",0), + outArr=op.outArray("Result"); + +const newArr=[]; + +inPad.onChange= +inArr.onChange=()=> +{ + outArr.set(null); + let arr=inArr.get(); + if(!arr || arr.length<1)return; + + newArr.length=arr.length; + + newArr[0]=arr[0]; + + for(let i=1;i +{ + if (!inArray.get()) + { + outArray.set(null); + outLength.set(0); + return; + } + + const mode = inDedupeMode.get(); + const func = FUNCTIONS[mode]; + const newArray = func(inArray.get()); + + outArray.set(null); + outArray.set(newArray); + outLength.set(newArray.length); +}; + +function compareSingle(arr) +{ + const len = arr.length; + const seen = {}; + const deduped = []; + + for (let i = 0; i < len; i++) + { + if (!seen[arr[i]]) + { + deduped.push(arr[i]); + seen[arr[i]] = true; + } + } + + return deduped; +} + +const FUNCTIONS = { + "X": compareSingle, + "XY": compareVec2, + "XYZ": compareVec3, +}; + +function compareVec2(arr) +{ + const len = Math.floor(arr.length / 2); + const seen = {}; + const deduped = []; + + for (let i = 0; i < len; i += 1) + { + const key = [arr[i * 2], arr[i * 2 + 1]].join(); + + if (!seen[key]) + { + deduped.push(arr[i * 2], arr[i * 2 + 1]); + seen[key] = true; + } + } + + return deduped; +} + +function compareVec3(arr) +{ + const len = Math.floor(arr.length / 3); + const seen = {}; + const deduped = []; + + for (let i = 0; i < len; i += 1) + { + const key = [arr[i * 3], arr[i * 3 + 1], arr[i * 3 + 2]].join(); + + if (!seen[key]) + { + deduped.push(arr[i * 3], arr[i * 3 + 1], arr[i * 3 + 2]); + seen[key] = true; + } + } + + return deduped; +} + + +/* +// OLD CODE IN CASE OF SOMETHING GOING WRONG + +const inArray = op.inArray("array"); +const outArray = op.outArray("arrayOut"); + +inArray.onChange = function () +{ + const inValue = inArray.get(); + if (Array.isArray(inValue)) + { + const unique = inValue.filter((v, i, a) => a.indexOf(v) === i); + outArray.set(unique); + } + else + { + outArray.set(inValue); + } +}; + +*/ + + +}; + +Ops.Array.ArrayUnique.prototype = new CABLES.Op(); +CABLES.OPS["81204fcc-c416-4948-9cba-2218763db4fc"]={f:Ops.Array.ArrayUnique,objName:"Ops.Array.ArrayUnique"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayUniqueItemInfo +// +// ************************************************************** + +Ops.Array.ArrayUniqueItemInfo = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArray = op.inArray("array"); +const outObject = op.outObject("objectOut"); + +inArray.onChange = function () +{ + const inValue = inArray.get(); + const counts = {}; + if (Array.isArray(inValue)) + { + for (let i = 0; i < inValue.length; i++) + { + const value = inValue[i]; + if (counts.hasOwnProperty(value)) + { + counts[value]++; + } + else + { + counts[value] = 1; + } + } + outObject.set(counts); + } + else + { + outObject.set(inValue); + } +}; + + +}; + +Ops.Array.ArrayUniqueItemInfo.prototype = new CABLES.Op(); +CABLES.OPS["6c6927e6-abd3-4427-92b2-4095f6f0b1c0"]={f:Ops.Array.ArrayUniqueItemInfo,objName:"Ops.Array.ArrayUniqueItemInfo"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayUnpack2 +// +// ************************************************************** + +Ops.Array.ArrayUnpack2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArray1 = op.inArray("Array in xyz"), + outArray1 = op.outArray("Array 1 out"), + outArray2 = op.outArray("Array 2 out"), + outArrayLength = op.outNumber("Array lengths"); + +let showingError = false; + +const arr1 = []; +const arr2 = []; + +inArray1.onChange = update; + +function update() +{ + let array1 = inArray1.get(); + + if (!array1) + { + outArray1.set(null); + return; + } + + if (array1.length % 2 !== 0) + { + if (!showingError) + { + op.uiAttr({ "error": "Arrays length not divisible by 2 !" }); + outArrayLength.set(0); + showingError = true; + } + return; + } + if (array1.length === 0) + { + outArrayLength.set(0); + outArray1.set(null); + outArray2.set(null); + } + + if (showingError) + { + showingError = false; + op.uiAttr({ "error": null }); + } + + arr1.length = Math.floor(array1.length / 2); + arr2.length = Math.floor(array1.length / 2); + + for (let i = 0; i < array1.length / 2; i++) + { + arr1[i] = array1[i * 2]; + arr2[i] = array1[i * 2 + 1]; + } + + outArray1.set(null); + outArray2.set(null); + outArray1.set(arr1); + outArray2.set(arr2); + outArrayLength.set(arr1.length); +} + + +}; + +Ops.Array.ArrayUnpack2.prototype = new CABLES.Op(); +CABLES.OPS["3f789664-9937-4478-ba28-63ccb67e5114"]={f:Ops.Array.ArrayUnpack2,objName:"Ops.Array.ArrayUnpack2"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayUnpack3 +// +// ************************************************************** + +Ops.Array.ArrayUnpack3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArray1 = op.inArray("Array in xyz"), + outArray1 = op.outArray("Array 1 out"), + outArray2 = op.outArray("Array 2 out"), + outArray3 = op.outArray("Array 3 out"), + outArrayLength = op.outNumber("Array lengths"); + +let showingError = false; + +const arr1 = []; +const arr2 = []; +const arr3 = []; + +inArray1.onChange = update; + +function update() +{ + let array1 = inArray1.get(); + + if (!array1) + { + outArray1.set(null); + return; + } + + if (array1.length % 3 !== 0) + { + if (!showingError) + { + op.uiAttr({ "error": "Arrays length not divisible by 3 !" }); + outArrayLength.set(0); + showingError = true; + } + return; + } + + if (showingError) + { + showingError = false; + op.uiAttr({ "error": null }); + } + + arr1.length = Math.floor(array1.length / 3); + arr2.length = Math.floor(array1.length / 3); + arr3.length = Math.floor(array1.length / 3); + + for (let i = 0; i < array1.length / 3; i++) + { + arr1[i] = array1[i * 3]; + arr2[i] = array1[i * 3 + 1]; + arr3[i] = array1[i * 3 + 2]; + } + + outArray1.set(null); + outArray2.set(null); + outArray3.set(null); + outArray1.set(arr1); + outArray2.set(arr2); + outArray3.set(arr3); + outArrayLength.set(arr1.length); +} + + +}; + +Ops.Array.ArrayUnpack3.prototype = new CABLES.Op(); +CABLES.OPS["fa671f66-6957-41e6-ac35-d615b7c29285"]={f:Ops.Array.ArrayUnpack3,objName:"Ops.Array.ArrayUnpack3"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayUnpack4 +// +// ************************************************************** + +Ops.Array.ArrayUnpack4 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArray1 = op.inArray("Array in xyzw"), + outArray1 = op.outArray("Array 1 out"), + outArray2 = op.outArray("Array 2 out"), + outArray3 = op.outArray("Array 3 out"), + outArray4 = op.outArray("Array 4 out"), + outArrayLength = op.outNumber("Array lengths"); + +let showingError = false; + +const arr1 = []; +const arr2 = []; +const arr3 = []; +const arr4 = []; + +inArray1.onChange = update; + +function update() +{ + let array1 = inArray1.get(); + + if (!array1) + { + outArray1.set(null); + return; + } + + if (array1.length % 4 !== 0) + { + if (!showingError) + { + op.uiAttr({ "error": "Arrays length not divisible by 4 !" }); + outArrayLength.set(0); + showingError = true; + } + return; + } + + if (showingError) + { + showingError = false; + op.uiAttr({ "error": null }); + } + + arr1.length = Math.floor(array1.length / 4); + arr2.length = Math.floor(array1.length / 4); + arr3.length = Math.floor(array1.length / 4); + arr4.length = Math.floor(array1.length / 4); + + for (let i = 0; i < array1.length / 4; i++) + { + arr1[i] = array1[i * 4]; + arr2[i] = array1[i * 4 + 1]; + arr3[i] = array1[i * 4 + 2]; + arr4[i] = array1[i * 4 + 3]; + } + + outArray1.set(null); + outArray2.set(null); + outArray3.set(null); + outArray4.set(null); + outArray1.set(arr1); + outArray2.set(arr2); + outArray3.set(arr3); + outArray4.set(arr4); + outArrayLength.set(arr1.length); +} + + +}; + +Ops.Array.ArrayUnpack4.prototype = new CABLES.Op(); +CABLES.OPS["8d2127d8-f3e4-4036-8cd8-75c6a404b582"]={f:Ops.Array.ArrayUnpack4,objName:"Ops.Array.ArrayUnpack4"}; + + + + +// ************************************************************** +// +// Ops.Array.ArrayUnshiftString +// +// ************************************************************** + +Ops.Array.ArrayUnshiftString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array"), + inString = op.inString("String", ""), + result = op.outArray("Result"); + +const arr = []; + +inString.onChange = + inArr.onChange = + function () + { + const oldArr = inArr.get(); + result.set(null); + if (!oldArr) return; + + arr.length = oldArr.length + 1; + arr[0] = inString.get(); + + for (let i = 0; i < oldArr.length; i++) + { + arr[i + 1] = oldArr[i]; + } + + result.set(arr); + }; + + +}; + +Ops.Array.ArrayUnshiftString.prototype = new CABLES.Op(); +CABLES.OPS["b6b78f4f-487e-4372-bd35-aaaa097083ff"]={f:Ops.Array.ArrayUnshiftString,objName:"Ops.Array.ArrayUnshiftString"}; + + + + +// ************************************************************** +// +// Ops.Array.Array_v3 +// +// ************************************************************** + +Ops.Array.Array_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inLength = op.inValueInt("Array length", 10), + modeSelect = op.inSwitch("Mode select", ["Number", "1,2,3,4", "0-1"], "Number"), + inDefaultValue = op.inValueFloat("Default Value"), + inReverse=op.inBool("Reverse",false), + outArr = op.outArray("Array"), + outArrayLength = op.outNumber("Array length out"); + +let arr = []; +let selectIndex = 0; +const MODE_NUMBER = 0; +const MODE_1_TO_4 = 1; +const MODE_0_TO_1 = 2; + +modeSelect.onChange = onFilterChange; + +inReverse.onChange = + inDefaultValue.onChange = + inLength.onChange = reset; + +onFilterChange(); +reset(); + +function onFilterChange() +{ + let selectedMode = modeSelect.get(); + if (selectedMode === "Number") selectIndex = MODE_NUMBER; + else if (selectedMode === "1,2,3,4") selectIndex = MODE_1_TO_4; + else if (selectedMode === "0-1") selectIndex = MODE_0_TO_1; + + inDefaultValue.setUiAttribs({ "greyout": selectIndex !== MODE_NUMBER }); + + op.setUiAttrib({ "extendTitle": modeSelect.get() }); + + reset(); +} + +function reset() +{ + arr.length = 0; + + let arrLength = inLength.get(); + let valueForArray = inDefaultValue.get(); + let i; + + // mode 0 - fill all array values with one number + if (selectIndex === MODE_NUMBER) + { + for (i = 0; i < arrLength; i++) + { + arr[i] = valueForArray; + } + } + // mode 1 Continuous number array - increments up to array length + else if (selectIndex === MODE_1_TO_4) + { + for (i = 0; i < arrLength; i++) + { + arr[i] = i; + } + } + // mode 2 Normalized array + else if (selectIndex === MODE_0_TO_1) + { + for (i = 0; i < arrLength; i++) + { + arr[i] = i / (arrLength-1); + } + } + + if(inReverse.get())arr=arr.reverse(); + + outArr.set(null); + outArr.set(arr); + outArrayLength.set(arr.length); +} + + +}; + +Ops.Array.Array_v3.prototype = new CABLES.Op(); +CABLES.OPS["e4d31a46-bf64-42a8-be34-4cbb2bbc2600"]={f:Ops.Array.Array_v3,objName:"Ops.Array.Array_v3"}; + + + + +// ************************************************************** +// +// Ops.Array.AverageArray +// +// ************************************************************** + +Ops.Array.AverageArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArray = op.inArray("Array"), + inIterations = op.inValueInt("Iterations", 1), + inMode = op.inValueSelect("Mode", ["repeat", "clamp"], "repeat"), + outArray = op.outArray("Smoothed array"), + outArrayLength = op.outNumber("Array length"); + +let smoothed = []; + +inArray.onChange = update; +inIterations.onChange = update; + +function smooth(values) +{ + smoothed.length = values.length; + let curr, prev, next, improved, i, pi, ni, mode; + mode = inMode.get(); + + for (i = 0; i < smoothed.length; i++) + { + pi = i - 1; + ni = i + 1; + curr = values[i]; + + if (pi < 0) + { + if (mode == "repeat") + prev = values[values.length - 1]; + else if (mode == "clamp") + prev = curr; + } + else + prev = smoothed[pi]; + + if (ni == values.length) + { + if (mode == "repeat") + next = values[0]; + else if (mode == "clamp") + next = curr; + } + else + next = values[ni]; + + improved = (prev + curr + next) / 3; + smoothed[i] = improved; + } + return smoothed; +} + +function update() +{ + let array = inArray.get(), num = inIterations.get(), i; + + if (!array) + return; + + for (i = 0; i < num; i++) + array = smooth(array); + + outArray.set(null); + outArray.set(array); + outArrayLength.set(array.length); +} + + +}; + +Ops.Array.AverageArray.prototype = new CABLES.Op(); +CABLES.OPS["40011294-10c4-4174-aa18-1b891826f436"]={f:Ops.Array.AverageArray,objName:"Ops.Array.AverageArray"}; + + + + +// ************************************************************** +// +// Ops.Array.BoolStateArray +// +// ************************************************************** + +Ops.Array.BoolStateArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// constants +let ARRAY_LENGTH_DEFAULT = 10; +let INACTIVE_VALUE = 0; +let ACTIVE_VALUE = 1; + +// variables +let stateArray = []; + +// inputs +let arrayLengthPort = op.inValue("Array Length", ARRAY_LENGTH_DEFAULT); +let activeIndexPort = op.inValue("Active Index", 0); +let inactiveValuePort = op.inValue("Inactive Value", 0); +let activeValuePort = op.inValue("Active Value", 1); + +// outputs +let stateArrayPort = op.outArray("State Array"); + +// change listeners +arrayLengthPort.onChange = update; +activeIndexPort.onChange = update; +inactiveValuePort.onChange = update; +activeValuePort.onChange = update; + +// init +update(); + +// functions + +function update() +{ + let arrLength = Math.max(0, arrayLengthPort.get()); + let activeIndex = Math.round(activeIndexPort.get()); + let inactiveValue = inactiveValuePort.get(); + let activeValue = activeValuePort.get(); + for (let i = 0; i < arrLength; i++) + { + if (i === activeIndex) + { + stateArray[i] = activeValue; + } + else + { + stateArray[i] = inactiveValue; + } + } + stateArray.length = arrLength; + stateArrayPort.set(null); + stateArrayPort.set(stateArray); +} + + +}; + +Ops.Array.BoolStateArray.prototype = new CABLES.Op(); +CABLES.OPS["f8c30313-4251-4d39-bff3-fb1cc9234d54"]={f:Ops.Array.BoolStateArray,objName:"Ops.Array.BoolStateArray"}; + + + + +// ************************************************************** +// +// Ops.Array.CopyArray +// +// ************************************************************** + +Ops.Array.CopyArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTriggerButton("Exec"), + inArr = op.inArray("Array"), + inReset = op.inTriggerButton("Reset"), + + deflt = op.inArray("Default"), + outArr = op.outArray("Result"); + + +function copyArray(source) +{ + let dest = []; + dest.length = source.length; + for (let i = 0; i < source.length; i++) + { + dest[i] = source[i]; + } + return dest; +} + +inReset.onTriggered = +deflt.onChange = function () +{ + let arr = deflt.get(); + outArr.set(null); + if (arr) outArr.set(copyArray(arr)); +}; + +inExec.onTriggered = function () +{ + let arr = inArr.get(); + if (!arr || !arr.length) return; + const cop = copyArray(arr); + outArr.set(null); + outArr.set(cop); +}; + + +}; + +Ops.Array.CopyArray.prototype = new CABLES.Op(); +CABLES.OPS["2f9b834e-c357-4dc7-ac2e-966b11735ef8"]={f:Ops.Array.CopyArray,objName:"Ops.Array.CopyArray"}; + + + + +// ************************************************************** +// +// Ops.Array.CropArray +// +// ************************************************************** + +Ops.Array.CropArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + srcArrayPort = op.inArray("Source Array"), + inStartIndex = op.inInt("Start Index"), + newLengthPort = op.inInt("New Length"), + croppedArrayOutPort = op.outArray("Cropped Array"), + outArrayLength = op.outNumber("Array length"); + +inStartIndex.onChange = srcArrayPort.onChange = newLengthPort.onChange = setOutPort; + +function setOutPort() +{ + const srcArray = srcArrayPort.get(); + + if(!srcArray) + { + croppedArrayOutPort.set(null); + outArrayLength.set(0); + return; + } + var newLength = parseInt(newLengthPort.get()); + const start=Math.floor(Math.abs(inStartIndex.get())); + + if(start+newLength >= srcArray.length) newLength = srcArray.length-start; + if(start+newLength <= srcArray.length) + { + var croppedArr = srcArray.slice(start, start+newLength); + croppedArrayOutPort.set(null); + croppedArrayOutPort.set(croppedArr); + outArrayLength.set(croppedArr.length); + } + +} + +}; + +Ops.Array.CropArray.prototype = new CABLES.Op(); +CABLES.OPS["d8deecd3-418f-43dd-8edb-dfe238b5327c"]={f:Ops.Array.CropArray,objName:"Ops.Array.CropArray"}; + + + + +// ************************************************************** +// +// Ops.Array.CutArray +// +// ************************************************************** + +Ops.Array.CutArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const srcArrayPort = op.inArray("Source Array"); +const inStartIndex = op.inInt("Remove from Start"); +const inEndIndex = op.inInt("Remove From End"); +const croppedArrayOutPort = op.outArray("Cut Array"); +const outArrayLength = op.outNumber("Array Length"); + +inStartIndex.onChange = inEndIndex.onChange = srcArrayPort.onChange = setOutPort; + +function setOutPort() +{ + const srcArray = srcArrayPort.get(); + + if (!srcArray) + { + croppedArrayOutPort.set(null); + outArrayLength.set(0); + return; + } + + const oldLength = srcArray.length; + const start = Math.max(0, Number(inStartIndex.get())); + const end = Math.max(0, Number(inEndIndex.get())); + + const newArr = []; + + for (let i = start; i < oldLength - end; i += 1) + { + newArr.push(srcArray[i]); + } + + croppedArrayOutPort.set(null); + croppedArrayOutPort.set(newArr); + outArrayLength.set(newArr.length); +} + + +}; + +Ops.Array.CutArray.prototype = new CABLES.Op(); +CABLES.OPS["9e6ea32a-3f5d-417a-b437-05c59d47c56e"]={f:Ops.Array.CutArray,objName:"Ops.Array.CutArray"}; + + + + +// ************************************************************** +// +// Ops.Array.EaseArray +// +// ************************************************************** + +Ops.Array.EaseArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array"), + inMin = op.inValue("Min", 0), + inMax = op.inValue("Max", 1), + outArr = op.outArray("Result Array"), + anim = new CABLES.Anim(); + +anim.createPort(op, "Easing", updateAnimEasing); +anim.setValue(0, 0); +anim.setValue(1, 1); +let resultArr = []; +op.onLoaded = inMin.onChange = inMax.onChange = updateMinMax; + +inArr.onChange = updateArray; + +function updateMinMax() +{ + anim.keys[0].time = anim.keys[0].value = Math.min(inMin.get(), inMax.get()); + anim.keys[1].time = anim.keys[1].value = Math.max(inMin.get(), inMax.get()); +} + +function updateAnimEasing() +{ + anim.keys[0].setEasing(anim.defaultEasing); + updateArray(); +} + +function updateArray() +{ + const arr = inArr.get(); + if (!arr) + { + outArr.set(null); + return; + } + resultArr.length = arr.length; + + for (let i = 0; i < arr.length; i++) + { + resultArr[i] = anim.getValue(arr[i]); + } + outArr.set(null); + outArr.set(resultArr); +} + + +}; + +Ops.Array.EaseArray.prototype = new CABLES.Op(); +CABLES.OPS["3bda237e-819a-43d8-9fb8-0f32bd3f7cc8"]={f:Ops.Array.EaseArray,objName:"Ops.Array.EaseArray"}; + + + + +// ************************************************************** +// +// Ops.Array.FillArrayRandomDuplicates_v2 +// +// ************************************************************** + +Ops.Array.FillArrayRandomDuplicates_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array"), + inNum = op.inValueInt("Num Elements", 10), + inSeed = op.inValueFloat("Random seed", 1), + outArr = op.outArray("Result"); + +op.toWorkPortsNeedToBeLinked(inArr); + +let arr = []; + +inArr.onChange = + inNum.onChange = + inSeed.onChange = () => + { + let oldArr = inArr.get(); + + if (!oldArr) return outArr.set(null); + + let num = inNum.get(); + let numOld = oldArr.length; + + Math.randomSeed = inSeed.get(); + arr.length = num; + + for (let i = 0; i < num; i++) + { + let ind = Math.floor(Math.seededRandom() * numOld); + arr[i] = oldArr[ind]; + } + + outArr.set(null); + outArr.set(arr); + }; + + +}; + +Ops.Array.FillArrayRandomDuplicates_v2.prototype = new CABLES.Op(); +CABLES.OPS["cbf5f595-9fbe-45a9-a324-5089665e8e51"]={f:Ops.Array.FillArrayRandomDuplicates_v2,objName:"Ops.Array.FillArrayRandomDuplicates_v2"}; + + + + +// ************************************************************** +// +// Ops.Array.FilterArray +// +// ************************************************************** + +Ops.Array.FilterArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array"), + inArrayStide = op.inSwitch("Stride", ["X", "XY", "XYZ", "XYZW"], "XYZ"), + inEle = op.inSwitch("Compare Element", ["X", "Y", "Z", "W"], "Z"), + inMeth = op.inSwitch("Filter Method", [">", "<"], "<"), + inFilterNum = op.inFloat("Compare to", 0.5), + outArr = op.outArray("Result"); + +let compEl = 2; +let stride = 3; + +inEle.onChange = () => +{ + if (inEle.get() == "X")compEl = 0; + else if (inEle.get() == "Y")compEl = 1; + else if (inEle.get() == "Z")compEl = 2; + else if (inEle.get() == "W")compEl = 3; + + update(); +}; + +inArrayStide.onChange = () => +{ + if (inArrayStide.get() == "X")stride = 1; + else if (inArrayStide.get() == "XY")stride = 2; + else if (inArrayStide.get() == "XYZ")stride = 3; + else if (inArrayStide.get() == "XYZW")stride = 4; + + update(); +}; + +inMeth.onChange = +inFilterNum.onChange = +inArr.onChange = update; + +function update() +{ + const arr = inArr.get(); + const newArr = []; + if (!arr) return; + + if (inMeth.get() == "<") + { + for (let i = 0; i < arr.length; i += stride) + if (arr[i + compEl] < inFilterNum.get()) // comparison + for (let j = 0; j < stride; j++) + newArr.push(arr[i + j]); + } + else if (inMeth.get() == ">") + { + for (let i = 0; i < arr.length; i += stride) + if (arr[i + compEl] > inFilterNum.get()) // comparison + for (let j = 0; j < stride; j++) + newArr.push(arr[i + j]); + } + + outArr.set(null); + outArr.set(newArr); +} + + +}; + +Ops.Array.FilterArray.prototype = new CABLES.Op(); +CABLES.OPS["ea396c36-c070-44d8-ae0b-fd0bffa56b35"]={f:Ops.Array.FilterArray,objName:"Ops.Array.FilterArray"}; + + + + +// ************************************************************** +// +// Ops.Array.FilterValidArray +// +// ************************************************************** + +Ops.Array.FilterValidArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array"), + inLength = op.inBool("Invalid when length is 0", true), + + outArray = op.outArray("Last Valid Array"), + outValid = op.outBool("Is Valid"); + +inLength.onChange = +inArr.onChange = + update; + +function update() +{ + const arr = inArr.get(); + + let r = true; + + if (!arr || !arr.length) r = false; + else if (inLength.get() && arr.length == 0) r = false; + + if (r) + { + outArray.set([]); + outArray.set(arr); + } + + outValid.set(r); +} + + +}; + +Ops.Array.FilterValidArray.prototype = new CABLES.Op(); +CABLES.OPS["f2669593-eb06-48a6-b94c-4bc243747ee1"]={f:Ops.Array.FilterValidArray,objName:"Ops.Array.FilterValidArray"}; + + + + +// ************************************************************** +// +// Ops.Array.FlattenArray +// +// ************************************************************** + +Ops.Array.FlattenArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArr=op.inArray("Array"), + outArr=op.outArray("Result"); + + inArr.onChange=function() + { + var arr=inArr.get(); + outArr.set(null); + + if(!arr) + { + return; + } + + + var newArr=arr.slice(0); + newArr=newArr.flat(Infinity); + + outArr.set(newArr); + + + }; + + +}; + +Ops.Array.FlattenArray.prototype = new CABLES.Op(); +CABLES.OPS["bd5f43cf-7a69-4bff-85b3-08df62b899b4"]={f:Ops.Array.FlattenArray,objName:"Ops.Array.FlattenArray"}; + + + + +// ************************************************************** +// +// Ops.Array.GateArray_v2 +// +// ************************************************************** + +Ops.Array.GateArray_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const passThrough = op.inValueBool("Pass Through", true), + arrayIn = op.inArray("Array in"), + arrayOut = op.outArray("Array Out"); + +let oldArr = null; + +function copyArray(source) +{ + if (!source) return null; + const dest = []; + dest.length = source.length; + for (let i = 0; i < source.length; i++) + { + dest[i] = source[i]; + } + return dest; +} + +arrayIn.onChange = passThrough.onChange = function () +{ + if (passThrough.get()) + { + oldArr = copyArray(arrayIn.get()); + arrayOut.set(oldArr); + } + // else + // { + // arrayOut.set(oldArr); + // } +}; + + +}; + +Ops.Array.GateArray_v2.prototype = new CABLES.Op(); +CABLES.OPS["e28a489c-46b6-4279-928c-6b0cbaaaae2a"]={f:Ops.Array.GateArray_v2,objName:"Ops.Array.GateArray_v2"}; + + + + +// ************************************************************** +// +// Ops.Array.GetValuesFromArrayOfObjects +// +// ************************************************************** + +Ops.Array.GetValuesFromArrayOfObjects = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array"), + inKey = op.inString("Key"), + inignoreNonNums = op.inBool("Numbers Only", false), + inRemoveInvalid = op.inBool("Remove empty/invalid", false), + outArray = op.outArray("Result"); + +inRemoveInvalid.onChange = +inKey.onChange = +inArr.onChange = +inignoreNonNums.onChange = exec; + +function exec() +{ + const arr = inArr.get(); + + if (!arr) + { + outArray.set(null); + return; + } + + const newArr = []; + const key = inKey.get(); + const numsonly = inignoreNonNums.get(); + + op.setUiAttrib({ "extendTitle": inKey.get() }); + + const removeInvalid = inRemoveInvalid.get(); + + for (let i = 0; i < arr.length; i++) + { + const obj = arr[i]; + + if (obj) + { + if (!(key in obj)) continue; + + const v = obj[key]; + + if (removeInvalid) + { + if (v === "" || + v === null || + v === undefined + + ) continue; + } + + if (numsonly) + { + if (CABLES.UTILS.isNumeric(v)) newArr.push(parseFloat(v)); + } + else + { + newArr.push(v); + } + } + } + + outArray.set(null); + outArray.set(newArr); +} + + +}; + +Ops.Array.GetValuesFromArrayOfObjects.prototype = new CABLES.Op(); +CABLES.OPS["e068629a-7963-48b0-853f-a89348d03654"]={f:Ops.Array.GetValuesFromArrayOfObjects,objName:"Ops.Array.GetValuesFromArrayOfObjects"}; + + + + +// ************************************************************** +// +// Ops.Array.HSBtoRGBArray +// +// ************************************************************** + +Ops.Array.HSBtoRGBArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +function HSBtoRGB(hue, saturation, lightness) +{ + // based on algorithm from http://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB + const chroma = (1 - Math.abs((2 * lightness) - 1)) * saturation; + let huePrime = hue * 6; // / 60; + let secondComponent = chroma * (1 - Math.abs((huePrime % 2) - 1)); + + huePrime = Math.floor(huePrime) || 0; + let red = 0; + let green = 0; + let blue = 0; + + if (huePrime === 0) + { + red = chroma; + green = secondComponent; + blue = 0; + } + else if (huePrime === 1) + { + red = secondComponent; + green = chroma; + blue = 0; + } + else if (huePrime === 2) + { + red = 0; + green = chroma; + blue = secondComponent; + } + else if (huePrime === 3) + { + red = 0; + green = secondComponent; + blue = chroma; + } + else if (huePrime === 4) + { + red = secondComponent; + green = 0; + blue = chroma; + } + else if (huePrime >= 5) + { + red = chroma; + green = 0; + blue = secondComponent; + } + + const lightnessAdjustment = (lightness - (chroma / 2)); + + red += lightnessAdjustment; + green += lightnessAdjustment; + blue += lightnessAdjustment; + + return [red, green, blue]; +} + +const inTrigger = op.inTrigger("Trigger Input"); +const inHue = op.inArray("In Hue Array"); +const inSat = op.inArray("In Saturation Array"); +const inBright = op.inArray("In Brightness Array"); +const inAlpha = op.inArray("In Alpha Array"); + +const outTrigger = op.outTrigger("Trigger Output"); +const outArray = op.outArray("Result Array"); +const outLength = op.outNumber("Array Length", 0); +const outTupleLength = op.outNumber("RGBA Tuple Length", 0); + +let newArr = []; +const emptyArr = []; +outArray.set(newArr); +outLength.set(newArr.length); +outTupleLength.set(newArr.length / 4); + +outArray.ignoreValueSerialize = true; +inAlpha.ignoreValueSerialize = true; +inBright.ignoreValueSerialize = true; +inSat.ignoreValueSerialize = true; +inHue.ignoreValueSerialize = true; + +let shouldRecalculate = true; + +inTrigger.onTriggered = handleTrigger; +inHue.onChange = inSat.onChange = inBright.onChange = inAlpha.onChange = function () { shouldRecalculate = true; }; + +function handleTrigger() +{ + let arrH = inHue.get(); + let arrS = inSat.get(); + let arrB = inBright.get(); + let arrA = inAlpha.get(); + + if (!arrH && !arrS && !arrB && !arrA) + { + outArray.set(null); + outLength.set(0); + outTupleLength.set(0); + return; + } + + let length = 0; + + if (shouldRecalculate) + { + if ([arrH, arrS, arrB, arrA].some(function (array) { return !array; })) + { + if (arrH) length = arrH.length; + else if (arrS) length = arrS.length; + else if (arrB) length = arrB.length; + else if (arrA) length = arrA.length; + + emptyArr.length = length; + for (let i = 0; i < length; i += 1) emptyArr[i] = 0; + + if (!arrH) arrH = emptyArr.map(function (val) { return 0; }); + if (!arrS) arrS = emptyArr.map(function (val) { return 1; }); + if (!arrB) arrB = emptyArr.map(function (val) { return 0.5; }); + if (!arrA) arrA = emptyArr.map(function (val) { return 1; }); + } + else + { + length = arrH.length; + } + + const areSameLength = [arrH, arrS, arrB, arrA].every(function (val, i, arr) { return val.length === length; }); + + if (!areSameLength) + { + // op.log([arrH, arrS, arrB, arrA].map(a => a.length), length); + op.setUiError("arrlen", "Arrays don't have the same length!"); + } + else + { + op.setUiError("arrlen", null); + } + + newArr.length = length * 4; + + for (let i = 0; i < newArr.length / 4; i += 1) + { + const hsbArray = HSBtoRGB(arrH[i], arrS[i], arrB[i]); + newArr[i * 4 + 0] = hsbArray[0]; + newArr[i * 4 + 1] = hsbArray[1]; + newArr[i * 4 + 2] = hsbArray[2]; + newArr[i * 4 + 3] = arrA[i]; + } + + shouldRecalculate = false; + outArray.set(null); + outArray.set(newArr); + outLength.set(newArr.length); + outTupleLength.set(newArr.length / 4); + } + outTrigger.trigger(); +} + + +}; + +Ops.Array.HSBtoRGBArray.prototype = new CABLES.Op(); +CABLES.OPS["0f552671-7431-4031-97e3-211f2cf9f111"]={f:Ops.Array.HSBtoRGBArray,objName:"Ops.Array.HSBtoRGBArray"}; + + + + +// ************************************************************** +// +// Ops.Array.InfoArray +// +// ************************************************************** + +Ops.Array.InfoArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array"), + outMin = op.outNumber("Min"), + outMax = op.outNumber("Max"), + outAvg = op.outNumber("Average"); + +inArr.onChange = function () +{ + let arr = inArr.get(); + + let min = 999999999; + let max = -999999999; + let avg = 0; + + if (arr) + { + for (let i = 0; i < arr.length; i++) + { + avg += arr[i]; + min = Math.min(min, arr[i]); + max = Math.max(max, arr[i]); + } + avg /= arr.length; + } + outMin.set(min); + outMax.set(max); + outAvg.set(avg); +}; + + +}; + +Ops.Array.InfoArray.prototype = new CABLES.Op(); +CABLES.OPS["1db230c8-212f-4679-87d6-3531659363da"]={f:Ops.Array.InfoArray,objName:"Ops.Array.InfoArray"}; + + + + +// ************************************************************** +// +// Ops.Array.InfoArray2 +// +// ************************************************************** + +Ops.Array.InfoArray2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let inArr = op.inArray("Array", 2), + + outNum = op.outNumber("Num Items"), + + outMinX = op.outNumber("Min X"), + outMaxX = op.outNumber("Max X"), + outAvgX = op.outNumber("Average X"), + + outMinY = op.outNumber("Min Y"), + outMaxY = op.outNumber("Max Y"), + outAvgY = op.outNumber("Average Y"); + +inArr.onChange = function () +{ + let arr = inArr.get(); + + let minX = 999999999; + let maxX = -999999999; + let avgX = 0; + + let minY = 999999999; + let maxY = -999999999; + let avgY = 0; + outNum.set(0); + + if (arr) + { + outNum.set(arr.length / 2); + + for (let i = 0; i < arr.length; i += 2) + { + avgX += arr[i]; + minX = Math.min(minX, arr[i]); + maxX = Math.max(maxX, arr[i]); + + avgY += arr[i + 1]; + minY = Math.min(minY, arr[i + 1]); + maxY = Math.max(maxY, arr[i + 1]); + } + + avgX /= arr.length / 2; + avgY /= arr.length / 2; + } + + outMinX.set(minX); + outMaxX.set(maxX); + outAvgX.set(avgX); + + outMinY.set(minY); + outMaxY.set(maxY); + outAvgY.set(avgY); +}; + + +}; + +Ops.Array.InfoArray2.prototype = new CABLES.Op(); +CABLES.OPS["0ea5fb62-94e7-4a1b-928f-bdcab373c022"]={f:Ops.Array.InfoArray2,objName:"Ops.Array.InfoArray2"}; + + + + +// ************************************************************** +// +// Ops.Array.InfoArray3 +// +// ************************************************************** + +Ops.Array.InfoArray3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let inArr = op.inArray("Array"), + + outNum = op.outNumber("Num Items"), + + outMinX = op.outNumber("Min X"), + outMaxX = op.outNumber("Max X"), + outAvgX = op.outNumber("Average X"), + + outMinY = op.outNumber("Min Y"), + outMaxY = op.outNumber("Max Y"), + outAvgY = op.outNumber("Average Y"), + + outMinZ = op.outNumber("Min Z"), + outMaxZ = op.outNumber("Max Z"), + outAvgZ = op.outNumber("Average Z"); + +inArr.onChange = function () +{ + let arr = inArr.get(); + + let minX = 999999999; + let maxX = -999999999; + let avgX = 0; + + let minZ = 999999999; + let maxZ = -999999999; + let avgZ = 0; + + let minY = 999999999; + let maxY = -999999999; + let avgY = 0; + outNum.set(0); + + if (arr) + { + outNum.set(arr.length / 3); + + for (let i = 0; i < arr.length; i += 3) + { + avgX += arr[i]; + minX = Math.min(minX, arr[i]); + maxX = Math.max(maxX, arr[i]); + + avgY += arr[i + 1]; + minY = Math.min(minY, arr[i + 1]); + maxY = Math.max(maxY, arr[i + 1]); + + avgZ += arr[i + 2]; + minZ = Math.min(minZ, arr[i + 2]); + maxZ = Math.max(maxZ, arr[i + 2]); + } + + avgX /= arr.length / 3; + avgY /= arr.length / 3; + avgZ /= arr.length / 3; + } + + outMinX.set(minX); + outMaxX.set(maxX); + outAvgX.set(avgX); + + outMinY.set(minY); + outMaxY.set(maxY); + outAvgY.set(avgY); + + outMinZ.set(minZ); + outMaxZ.set(maxZ); + outAvgZ.set(avgZ); +}; + + +}; + +Ops.Array.InfoArray3.prototype = new CABLES.Op(); +CABLES.OPS["e2ace702-eed6-4b40-86f6-cea716ba8579"]={f:Ops.Array.InfoArray3,objName:"Ops.Array.InfoArray3"}; + + + + +// ************************************************************** +// +// Ops.Array.InterpolateArrays +// +// ************************************************************** + +Ops.Array.InterpolateArrays = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("Exe"), + inArr1 = op.inArray("Array 1"), + inArr2 = op.inArray("Array 2"), + inPerc = op.inValueSlider("perc"), + next = op.outTrigger("Next"), + outArr = op.outArray("Result"); + +let needsCalc = true; +let resultArr = []; + +function calcLater() +{ + needsCalc = true; +} + +inArr1.onChange = inArr2.onChange = inPerc.onChange = calcLater; + +exe.onTriggered = execute; + +function execute() +{ + let arr1 = inArr1.get(); + let arr2 = inArr2.get(); + + let val1; + let val2; + let m; + + if (!arr1 || !arr2 || arr1.length < arr2.length) + { + outArr.set(null); + return; + } + + if (needsCalc) + { + if (resultArr.length != arr1.length) resultArr.length = arr1.length; + + let perc = inPerc.get(); + + for (let i = 0; i < arr1.length; i++) + { + val1 = arr1[i]; + val2 = arr2[i]; + m = (val2 - val1) * perc + val1; + resultArr[i] = m; + } + needsCalc = false; + outArr.set(null); + outArr.set(resultArr); + } + + next.trigger(); +} + +// check that array input is string or not +inArr1.onLinkChanged = inArr2.onLinkChanged = function () +{ + let arr1 = inArr1.get(); + let arr2 = inArr2.get(); + + if (!arr1 || !arr2) + { + outArr.set(null); + return; + } + + let stringTest1 = arr1[0]; + let stringTest2 = arr2[0]; + + if (typeof stringTest1 === "string" || typeof stringTest2 === "string") + { + outArr.set(null); + } +}; + + +}; + +Ops.Array.InterpolateArrays.prototype = new CABLES.Op(); +CABLES.OPS["09296117-7312-4f80-982b-7b4a81d22cf8"]={f:Ops.Array.InterpolateArrays,objName:"Ops.Array.InterpolateArrays"}; + + + + +// ************************************************************** +// +// Ops.Array.InterpolateArraysRange +// +// ************************************************************** + +Ops.Array.InterpolateArraysRange = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe = op.inTrigger("Exe"); +const inArr1 = op.inArray("Array 1"); +const inArr2 = op.inArray("Array 2"); + +const inPos = op.inValueSlider("Pos"); +const inWidth = op.inValueSlider("Width"); + +const easing = op.inValueSelect("Easing", [ + "Linear", + "Expo in", "Expo out", "Expo in out", + "Cubic in", "Cubic out", "Cubic in out"], +"Linear"); + +const reverse = op.inValueBool("Reverse"); + +const next = op.outTrigger("Next"); +const outArr = op.outArray("Result"); + +const resultArr = []; +let easingFunction = null; + +easing.onChange = function () +{ + if (easing.get() == "Expo in") easingFunction = CABLES.easeExpoIn; + else if (easing.get() == "Expo out") easingFunction = CABLES.easeExpoOut; + else if (easing.get() == "Expo in out") easingFunction = CABLES.easeExpoInOut; + else if (easing.get() == "Cubic in") easingFunction = CABLES.easeCubicIn; + else if (easing.get() == "Cubic out") easingFunction = CABLES.easeCubicOut; + else if (easing.get() == "Cubic in out") easingFunction = CABLES.easeCubicInOut; + else easingFunction = null; +}; + +let needsUpdate = true; + +inArr1.onChange = +inArr2.onChange = +inPos.onChange = +inWidth.onChange = () => +{ + needsUpdate = true; +}; + +exe.onTriggered = function () +{ + const arr1 = inArr1.get(); + const arr2 = inArr2.get(); + + if (needsUpdate) + if (!arr1 || !arr2 || arr2.length < arr1.length) + { + outArr.set(null); + } + else + { + if (resultArr.length != arr1.length) resultArr.length = arr1.length; + const distNum = inWidth.get() * (resultArr.length * 4); + const pos = inPos.get() * (arr1.length + distNum); + + for (let i = 0; i < arr1.length; i++) + { + const val1 = arr1[i]; + const val2 = arr2[i]; + + let ppos = pos - i; + if (reverse.get())ppos = pos - (arr1.length - i); + let dist = ppos / distNum; + + if (dist > 1) resultArr[i] = val2; + else if (dist <= 0) resultArr[i] = val1; + else + { + if (easingFunction) dist = easingFunction(dist); + const m = ((val2 - val1) * dist + val1); + resultArr[i] = m; + } + } + + outArr.set(null); + outArr.set(resultArr); + } + + next.trigger(); + needsUpdate = false; +}; + + +}; + +Ops.Array.InterpolateArraysRange.prototype = new CABLES.Op(); +CABLES.OPS["f89f5664-7cfa-4598-b09c-e4320b588b45"]={f:Ops.Array.InterpolateArraysRange,objName:"Ops.Array.InterpolateArraysRange"}; + + + + +// ************************************************************** +// +// Ops.Array.InterpolateNumbersArray +// +// ************************************************************** + +Ops.Array.InterpolateNumbersArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inIndex = op.inValue("Index Position"), + inArr = op.inArray("Array"), + outX = op.outNumber("result"); + +inIndex.onChange = inArr.onChange = function () +{ + let i = Math.floor(inIndex.get()); + let fr = inIndex.get() - Math.floor(inIndex.get()); + let arr = inArr.get(); + + if (i < 0 || !arr) + { + return; + } + + if (i >= arr.length - 1) + { + outX.set(arr[arr.length - 1]); + return; + } + + let x = arr[i + 0]; + + let x2 = arr[i + 1]; + + x += (x2 - x) * fr; + + outX.set(x); +}; + + +}; + +Ops.Array.InterpolateNumbersArray.prototype = new CABLES.Op(); +CABLES.OPS["d0894a6b-f921-4542-aafc-3f1b21615a44"]={f:Ops.Array.InterpolateNumbersArray,objName:"Ops.Array.InterpolateNumbersArray"}; + + + + +// ************************************************************** +// +// Ops.Array.InterpolateNumbersArray3 +// +// ************************************************************** + +Ops.Array.InterpolateNumbersArray3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inIndex = op.inValue("Index Position"), + inArr = op.inArray("Array"), + outX = op.outNumber("X"), + outY = op.outNumber("Y"), + outZ = op.outNumber("Z"); + +inIndex.onChange = inArr.onChange = function () +{ + let i = inIndex.get(); + const arr = inArr.get(); + + if (i < 0 || !arr) + { + return; + } + + const maxIdx = Math.floor((arr.length / 3) - 1); + const intIdx = Math.floor(inIndex.get()); + if (intIdx == maxIdx) + { + outX.set(arr[arr.length - 3]); + outY.set(arr[arr.length - 2]); + outZ.set(arr[arr.length - 1]); + return; + } + + const fr = inIndex.get() - Math.floor(inIndex.get()); + i = Math.floor((inIndex.get())) * 3; + i %= (arr.length); + + let x = arr[i + 0]; + let y = arr[i + 1]; + let z = arr[i + 2]; + + const x2 = arr[i + 3]; + const y2 = arr[i + 4]; + const z2 = arr[i + 5]; + + x += (x2 - x) * fr; + y += (y2 - y) * fr; + z += (z2 - z) * fr; + + outX.set(x); + outY.set(y); + outZ.set(z); +}; + + +}; + +Ops.Array.InterpolateNumbersArray3.prototype = new CABLES.Op(); +CABLES.OPS["1feb4565-32c5-4fb9-b869-88502b461256"]={f:Ops.Array.InterpolateNumbersArray3,objName:"Ops.Array.InterpolateNumbersArray3"}; + + + + +// ************************************************************** +// +// Ops.Array.IteratorArray3 +// +// ************************************************************** + +Ops.Array.IteratorArray3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("Execute"), + arr = op.inArray("Array"), + pStep = op.inValue("Step"), + trigger = op.outTrigger("Trigger"), + idx = op.outNumber("Index"), + valX = op.outNumber("Value 1"), + valY = op.outNumber("Value 2"), + valZ = op.outNumber("Value 3"); + +let ar = arr.get() || []; + +let vstep = 1; +pStep.onChange = changeStep; +changeStep(); + +let i = 0; +let count = 0; + +arr.onChange = function () +{ + ar = arr.get() || []; +}; + +function changeStep() +{ + vstep = pStep.get() || 1; + if (vstep < 1.0)vstep = 1.0; + vstep = 3 * vstep; +} + +exe.onTriggered = function () +{ + count = 0; + + for (let i = 0, len = ar.length; i < len; i += vstep) + // for (var i = ar.length-1; i >=0; i-=vstep) + { + idx.set(count); + valX.set(ar[i + 0]); + valY.set(ar[i + 1]); + valZ.set(ar[i + 2]); + trigger.trigger(); + count++; + } +}; + + +}; + +Ops.Array.IteratorArray3.prototype = new CABLES.Op(); +CABLES.OPS["3f7db864-7409-418f-8c03-b2c966c050b3"]={f:Ops.Array.IteratorArray3,objName:"Ops.Array.IteratorArray3"}; + + + + +// ************************************************************** +// +// Ops.Array.LissajouseSpline +// +// ************************************************************** + +Ops.Array.LissajouseSpline = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inForm=op.inValueSelect("Formula",[1,2,3],1), + inA=op.inValueInt("A",5), + inB=op.inValueInt("B",4), + inC=op.inValueInt("C",1), + inD=op.inValueInt("D",2), + result=op.outArray("Result"), + outTotalPoints = op.outNumber("Total points"), + outArrayLength = op.outNumber("Array length"); + +inForm.onChange=inA.onChange=inB.onChange=inC.onChange=inD.onChange=calc; +calc(); + +function calc() +{ + var numPoints=13200; + var step=40; + + var arr=[]; + var x=0,y=0,z=0; + var form=parseInt(inForm.get()); + var th=0.03; + + for(var i = 0; i < numPoints; i+=step) + { + var index=i/step; + + if(form==1) + { + x=Math.sin( (i * inA.get()) * 0.001 ); + y=Math.cos( (i * inB.get()) * 0.001 ); + z=Math.sin( (i * inC.get()) * 0.001 ); + } + else if(form==2) + { + x=(Math.cos( (i * inA.get()) * 0.001 )+Math.cos( (i * inB.get()) * 0.001 ) )/2; + y=(Math.sin( (i * inA.get()) * 0.001 )+Math.sin( (i * inC.get()) * 0.001 ) )/2; + z=(Math.sin( (i * inD.get()) * 0.001 )); + } + else if(form==3) + { + x=(Math.sin( (i * inA.get()) * 0.001 )*(1+Math.cos( (i * inB.get()) * 0.001 ) ))/2; + y=(Math.sin( (i * inA.get()) * 0.001 )*(1+Math.sin( (i * inC.get()) * 0.001 ) ))/2; + z=(Math.sin( (i * inD.get()) * 0.001 )); + } + + arr[index*3+0] = x; + arr[index*3+1] = y; + arr[index*3+2] = z; + + if(index>10 && Math.abs(x-arr[0])= Math.max(old_max.get(), old_min.get())) + { + outArray[i] = new_max.get(); + } + else if (x <= Math.min(old_max.get(), old_min.get())) + { + outArray[i] = new_min.get(); + } + else + { + const nMin = new_min.get(); + const nMax = new_max.get(); + const oMin = old_min.get(); + const oMax = old_max.get(); + + let reverseInput = false; + const oldMin = Math.min(oMin, oMax); + const oldMax = Math.max(oMin, oMax); + if (oldMin !== oMin) reverseInput = true; + + let reverseOutput = false; + const newMin = Math.min(nMin, nMax); + const newMax = Math.max(nMin, nMax); + if (newMin !== nMin) reverseOutput = true; + + let portion = 0; + + if (reverseInput) + { + portion = (oldMax - x) * (newMax - newMin) / (oldMax - oldMin); + } + else + { + portion = (x - oldMin) * (newMax - newMin) / (oldMax - oldMin); + } + + if (reverseOutput) + { + r = newMax - portion; + } + else + { + r = portion + newMin; + } + + if (ease === 0) + { + outArray[i] = r; + } + else if (ease === 1) + { + x = Math.max(0, Math.min(1, (r - nMin) / (nMax - nMin))); + outArray[i] = nMin + x * x * (3 - 2 * x) * (nMax - nMin); // smoothstep + } + else if (ease === 2) + { + x = Math.max(0, Math.min(1, (r - nMin) / (nMax - nMin))); + outArray[i] = nMin + x * x * x * (x * (x * 6 - 15) + 10) * (nMax - nMin); // smootherstep + } + } + } + result.set(outArray); +} + +v.set(null); +old_min.set(0); +old_max.set(1); +new_min.set(-1); +new_max.set(1); + +v.onChange = exec; +old_min.onChange = exec; +old_max.onChange = exec; +new_min.onChange = exec; +new_max.onChange = exec; + +result.set(null); + +exec(); + + +}; + +Ops.Array.MapRangeArray.prototype = new CABLES.Op(); +CABLES.OPS["20f921bf-adc2-45fb-b387-834af4f5e19b"]={f:Ops.Array.MapRangeArray,objName:"Ops.Array.MapRangeArray"}; + + + + +// ************************************************************** +// +// Ops.Array.PaletteLibrary +// +// ************************************************************** + +Ops.Array.PaletteLibrary = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const outArrayPalette = op.outArray("Palette Array out"); + +const colors=[ +'#E6E2AF','#A7A37E','#EFECCA','#046380','002F2F', +'#468966','#FFF0A5','#FFB03B','#B64926','8E2800', +'#FCFFF5','#D1DBBD','#91AA9D','#3E606F','193441', +'#FF6138','#FFFF9D','#BEEB9F','#79BD8F','00A388', +'#105B63','#FFFAD5','#FFD34E','#DB9E36','BD4932', +'#225378','#1695A3','#ACF0F2','#F3FFE2','EB7F00', +'#2C3E50','#E74C3C','#ECF0F1','#3498DB','2980B9', +'#000000','#263248','#7E8AA2','#FFFFFF','FF9800', +'#004358','#1F8A70','#BEDB39','#FFE11A','FD7400', +'#DC3522','#D9CB9E','#374140','#2A2C2B','1E1E20', +'#7D8A2E','#C9D787','#FFFFFF','#FFC0A9','FF8598', +'#B9121B','#4C1B1B','#F6E497','#FCFAE1','BD8D46', +'#2E0927','#D90000','#FF2D00','#FF8C00','04756F', +'#595241','#B8AE9C','#FFFFFF','#ACCFCC','8A0917', +'#10222B','#95AB63','#BDD684','#E2F0D6','F6FFE0', +'#F6F792','#333745','#77C4D3','#DAEDE2','EA2E49', +'#703030','#2F343B','#7E827A','#E3CDA4','C77966', +'#2F2933','#01A2A6','#29D9C2','#BDF271','FFFFA6', +'#D8CAA8','#5C832F','#284907','#382513','363942', +'#FFF8E3','#CCCC9F','#33332D','#9FB4CC','DB4105', +'#85DB18','#CDE855','#F5F6D4','#A7C520','493F0B', +'#04BFBF','#CAFCD8','#F7E967','#A9CF54','588F27', +'#292929','#5B7876','#8F9E8B','#F2E6B6','412A22', +'#332532','#644D52','#F77A52','#FF974F','A49A87', +'#405952','#9C9B7A','#FFD393','#FF974F','F54F29', +'#2B3A42','#3F5765','#BDD4DE','#EFEFEF','FF530D', +'#962D3E','#343642','#979C9C','#F2EBC7','348899', +'#96CA2D','#B5E655','#EDF7F2','#4BB5C1','7FC6BC', +'#1C1D21','#31353D','#445878','#92CDCF','EEEFF7', +'#3E454C','#2185C5','#7ECEFD','#FFF6E5','FF7F66', +'#00585F','#009393','#FFFCC4','#F0EDBB','FF3800', +'#B4AF91','#787746','#40411E','#32331D','C03000', +'#63A69F','#F2E1AC','#F2836B','#F2594B','CD2C24', +'#88A825','#35203B','#911146','#CF4A30','ED8C2B', +'#F2385A','#F5A503','#E9F1DF','#4AD9D9','36B1BF', +'#CFC291','#FFF6C5','#A1E8D9','#FF712C','695D46', +'#FF5335','#B39C85','#306E73','#3B424D','1D181F', +'#000000','#333333','#FF358B','#01B0F0','AEEE00', +'#E8E595','#D0A825','#40627C','#26393D','FFFAE4', +'#E7E8D1','#D3CEAA','#FBF7E4','#424242','8E001C', +'#354242','#ACEBAE','#FFFF9D','#C9DE55','7D9100', +'#2F2933','#01A2A6','#29D9C2','#BDF271','FFFFA6', +'#DDDCC5','#958976','#611427','#1D2326','6A6A61', +'#6C6E58','#3E423A','#417378','#A4CFBE','F4F7D9', +'#E1E6FA','#C4D7ED','#ABC8E2','#375D81','183152', +'#6B0C22','#D9042B','#F4CB89','#588C8C','011C26', +'#304269','#91BED4','#D9E8F5','#FFFFFF','F26101', +'#96CEB4','#FFEEAD','#FF6F69','#FFCC5C','AAD8B0', +'#B0CC99','#677E52','#B7CA79','#F6E8B1','89725B', +'#334D5C','#45B29D','#EFC94C','#E27A3F','DF5A49', +'#16193B','#35478C','#4E7AC7','#7FB2F0','ADD5F7', +'#00261C','#044D29','#168039','#45BF55','96ED89', +'#36362C','#5D917D','#A8AD80','#E6D4A7','825534', +'#F9E4AD','#E6B098','#CC4452','#723147','31152B', +'#2C3E50','#FC4349','#D7DADB','#6DBCDB','FFFFFF', +'#002635','#013440','#AB1A25','#D97925','EFE7BE', +'#FF8000','#FFD933','#CCCC52','#8FB359','192B33', +'#272F32','#9DBDC6','#FFFFFF','#FF3D2E','DAEAEF', +'#B8ECD7','#083643','#B1E001','#CEF09D','476C5E', +'#002F32','#42826C','#A5C77F','#FFC861','C84663', +'#5C4B51','#8CBEB2','#F2EBBF','#F3B562','F06060', +'#5A1F00','#D1570D','#FDE792','#477725','A9CC66', +'#5E0042','#2C2233','#005869','#00856A','8DB500', +'#52656B','#FF3B77','#CDFF00','#FFFFFF','B8B89F', +'#801637','#047878','#FFB733','#F57336','C22121', +'#730046','#BFBB11','#FFC200','#E88801','C93C00', +'#24221F','#363F45','#4B5F6D','#5E7C88','FEB41C', +'#E64661','#FFA644','#998A2F','#2C594F','002D40', +'#C24704','#D9CC3C','#FFEB79','#A0E0A9','00ADA7', +'#484A47','#C1CE96','#ECEBF0','#687D77','353129', +'#588C7E','#F2E394','#F2AE72','#D96459','8C4646', +'#BAB293','#A39770','#EFE4BD','#A32500','2B2922', +'#6A7059','#FDEEA7','#9BCC93','#1A9481','003D5C', +'#174C4F','#207178','#FF9666','#FFE184','F5E9BE', +'#D5FBFF','#9FBCBF','#647678','#2F3738','59D8E6', +'#DB5800','#FF9000','#F0C600','#8EA106','59631E', +'#450003','#5C0002','#94090D','#D40D12','FF1D23', +'#211426','#413659','#656F8C','#9BBFAB','F2EFDF', +'#EA6045','#F8CA4D','#F5E5C0','#3F5666','2F3440', +'#F2F2F2','#C6E070','#91C46C','#287D7D','1C344D', +'#334D5C','#45B29D','#EFC94C','#E27A3F','DF5A49', +'#705B35','#C7B07B','#E8D9AC','#FFF6D9','570026', +'#F7F2B2','#ADCF4F','#84815B','#4A1A2C','8E3557', +'#1A1F2B','#30395C','#4A6491','#85A5CC','D0E4F2', +'#25064D','#36175E','#553285','#7B52AB','9768D1', +'#004056','#2C858D','#74CEB7','#C9FFD5','FFFFCB', +'#CFCA4C','#FCF5BF','#9FE5C2','#5EB299','745A33', +'#776045','#A8C545','#DFD3B6','#FFFFFF','0092B2', +'#CC3910','#F1F2C0','#CCC59E','#8FA68E','332F29', +'#FF6600','#C13B00','#5E6D70','#424E4F','1B1D1E', +'#690011','#BF0426','#CC2738','#F2D99C','E5B96F', +'#1B1D26','#425955','#778C7A','#F1F2D8','BFBD9F', +'#F6B1C3','#F0788C','#DE264C','#BC0D35','A20D1E', +'#597533','#332F28','#61B594','#E6DEA5','C44E18', +'#3FB8AF','#7FC7AF','#DAD8A7','#FF9E9D','FF3D7F', +'#0F2D40','#194759','#296B73','#3E8C84','D8F2F0', +'#42282F','#74A588','#D6CCAD','#DC9C76','D6655A', +'#002A4A','#17607D','#FFF1CE','#FF9311','D64700', +'#003056','#04518C','#00A1D9','#47D9BF','F2D03B', +'#13140F','#D4FF00','#E4FFE6','#68776C','00D6DD', +'#FCFAD0','#A1A194','#5B605F','#464646','A90641', +'#289976','#67CC8E','#B1FF91','#FFE877','FF5600', +'#302B1D','#3F522B','#737D26','#A99E46','D9CB84', +'#56626B','#6C9380','#C0CA55','#F07C6C','AD5472', +'#32450C','#717400','#DC8505','#EC5519','BE2805', +'#C7B773','#E3DB9A','#F5FCD0','#B1C2B3','778691', +'#E83A25','#FFE9A3','#98CC96','#004563','191B28', +'#3399CC','#67B8DE','#91C9E8','#B4DCED','E8F8FF', +'#1A212C','#1D7872','#71B095','#DEDBA7','D13F32', +'#7D2A35','#CC9258','#917A56','#B4BA6C','FEFFC2', +'#E7E9D1','#D3D4AA','#FCFAE6','#444444','901808', +'#FFFFFF','#AEAEAE','#E64C66','#2D3E50','1BBC9B', +'#E0FFB3','#61C791','#31797D','#2A2F36','F23C55', +'#EB5937','#1C1919','#403D3C','#456F74','D3CBBD', +'#E6DD00','#8CB302','#008C74','#004C66','332B40', +'#14A697','#F2C12E','#F29D35','#F27649','F25252', +'#261822','#40152A','#731630','#CC1E2C','FF5434', +'#261F27','#FEE169','#CDD452','#F9722E','C9313D', +'#5C4B51','#8CBEB2','#F2EBBF','#F3B562','F06060', +'#2F3837','#C5C7B6','#FFF8D3','#4C493E','222028', +'#E3CBAC','#9C9985','#C46D3B','#788880','324654', +'#3F0B1B','#7A1631','#CF423C','#FC7D49','FFD462', +'#14212B','#293845','#4F6373','#8F8164','D9D7AC', +'#98A89E','#BAC0AC','#FAFAC6','#FF4411','D40015', +'#FEFFFF','#3C3F36','#9FB03E','#EBE9DC','72918B', +'#CC6B32','#FFAB48','#FFE7AD','#A7C9AE','888A63', +'#262526','#404040','#8C8979','#F2F2F2','F60A20', +'#00305A','#004B8D','#0074D9','#4192D9','7ABAF2', +'#0C273D','#54D0ED','#FFFEF1','#70B85D','2C5E2E', +'#4C1B33','#EFE672','#98A942','#2D6960','141D14', +'#2F3540','#666A73','#F2EDE4','#D9D1C7','8C8681', +'#0D1F30','#3B6670','#8BADA3','#F0E3C0','DB6C0F', +'#FFBC67','#DA727E','#AC6C82','#685C79','455C7B', +'#092140','#024959','#F2C777','#F24738','BF2A2A', +'#133463','#365FB7','#799AE0','#F4EFDC','BA9B65', +'#C4D4CB','#55665E','#30282A','#542733','E84167', +'#CDDEC6','#4DAAAB','#1E4F6A','#2A423C','93A189', +'#EF5411','#FA5B0F','#FF6517','#FF6D1F','FF822E', +'#41434A','#6E9489','#DEDCC3','#F2F1E9','877963', +'#292929','#2BBFBD','#F2B33D','#F29B30','F22E2E', +'#F2385A','#F5A503','#E9F1DF','#56D9CD','3AA1BF', +'#D5F8B4','#A6E3A8','#8A9A85','#7E566B','422335', +'#3CBAC8','#93EDD4','#F3F5C4','#F9CB8F','F19181', +'#979926','#38CCB5','#EEFF8E','#FFD767','CC2A09', +'#404040','#024959','#037E8C','#F2EFDC','F24C27', +'#94B34D','#D3FF82','#363D52','#121D2B','111B1C', +'#282E33','#25373A','#164852','#495E67','FF3838', +'#313732','#8AA8B0','#DEDEDE','#FFFFFF','F26101', +'#FFFFFF','#E5E1D1','#52616D','#2C343B','C44741', +'#FFF6B8','#ABCCA7','#403529','#7A5E2F','A68236', +'#4F1025','#C5003E','#D9FF5B','#78AA00','15362D', +'#49404F','#596166','#D1FFCD','#A9BD8B','948A54', +'#FF2151','#FF7729','#FFAD29','#FFEBCA','1AB58A', +'#73603D','#BF8A49','#F2CA80','#5E5A59','0D0D0D', +'#3D4C53','#70B7BA','#F1433F','#E7E1D4','FFFFFF', +'#006D8D','#008A6E','#549E39','#8AB833','C0CF3A', +'#BDDFB3','#2BAA9C','#2F2E2E','#0F2625','465F3F', +'#F2F2F2','#BF0404','#8C0303','#590202','400101', +'#76A19A','#272123','#A68D60','#B0C5BB','D9593D', +'#0E3D59','#88A61B','#F29F05','#F25C05','D92525', +'#C1E1ED','#76C7C6','#273D3B','#131A19','E35C14', +'#2D112C','#530031','#820233','#CA293E','EF4339', +'#AF7575','#EFD8A1','#BCD693','#AFD7DB','3D9CA8', +'#D74B4B','#DCDDD8','#475F77','#354B5E','FFFFFF', +'#FFF6C9','#C8E8C7','#A4DEAB','#85CC9F','499E8D', +'#229396','#8BA88F','#C7C5A7','#F0DFD0','F23C3C', +'#57385C','#A75265','#EC7263','#FEBE7E','FFEDBC', +'#96526B','#D17869','#EBAD60','#F5CF66','8BAB8D', +'#0D1C33','#17373C','#2B6832','#4F9300','A1D700', +'#1B2B32','#37646F','#A3ABAF','#E1E7E8','B22E2F', +'#C5D9B2','#53A194','#572C2C','#3D2324','695A3B', +'#425957','#81AC8B','#F2E5A2','#F89883','D96666', +'#002E40','#2A5769','#FFFFFF','#FABD4A','FA9600', +'#FFFEFC','#E2E3DF','#515B5E','#2E3233','CAF200', +'#FFF0A3','#B8CC6E','#4B6000','#E4F8FF','004460', +'#3B596A','#427676','#3F9A82','#A1CD73','ECDB60', +'#F2E6CE','#8AB39F','#606362','#593325','1D1D1F', +'#212B40','#C2E078','#FFFFFF','#BADCDD','547B97', +'#0B3C4D','#0E5066','#136480','#127899','1A8BB3', +'#222130','#464D57','#D4E8D3','#FFFCFB','ED8917', +'#B33600','#FF8A00','#FFC887','#CC5400','B31E00', +'#012530','#28544B','#ACBD86','#FFD6A0','FF302C', +'#2E95A3','#50B8B4','#C6FFFA','#E2FFA8','D6E055', +'#112F41','#068587','#4FB99F','#F2B134','ED553B', +'#202B30','#4E7178','#4FA9B8','#74C0CF','F1F7E2', +'#302B2F','#696153','#FFA600','#9BB58F','FFD596', +'#458C6B','#F2D8A7','#D9A86C','#D94436','A62424', +'#22475E','#75B08A','#F0E797','#FF9D84','FF5460', +'#FFAA5C','#DA727E','#AC6C82','#685C79','455C7B', +'#686E75','#9BAAC1','#82787B','#E4F1DB','AAC19B', +'#F0C755','#E2AD3B','#BF5C00','#901811','5C110F', +'#FFFBDC','#BFBCA5','#7F7D6E','#3F3E37','E5E2C6', +'#BEBEBE','#F1E4D8','#594735','#94C7BA','D8F1E4', +'#1B1E26','#F2EFBD','#B6D051','#70A99A','2F6D7A', +'#F7E4A2','#A7BD5B','#DC574E','#8DC7B8','ED9355', +'#70E8CB','#FFE9C7','#FF5B5B','#545454','2D2D2F', +'#17111A','#321433','#660C47','#B33467','CCBB51', +'#2B2E2E','#595855','#A2ABA5','#CAE6E8','313F54', +'#023B47','#295E52','#F2E085','#FCAB55','EE7F38', +'#302C29','#D1D1BC','#A7C4BB','#6C8C84','466964', +'#212629','#067778','#49B8A8','#85EDB6','D9E5CD', +'#334D5C','#45B29D','#EFC94C','#E27A3F','DF4949', +'#2C3E50','#FC4349','#6DBCDB','#D7DADB','FFFFFF', +'#35262D','#FFFBFF','#E8ECED','#A4B7BB','76A0B0', +'#61E8D2','#FCEEB9','#302F25','#704623','BBE687', +'#E1E6B9','#C4D7A4','#ABC8A4','#375D3B','183128', +'#C98B2F','#803C27','#C56520','#E1B41B','807916', +'#A3D9B0','#93BF9E','#F2F0D5','#8C8474','40362E', +'#524656','#CF4747','#EA7A58','#E4DCCB','A6C4BC', +'#5C2849','#A73E5C','#EC4863','#FFDA66','1FCECB', +'#0EEAFF','#15A9FA','#1B76FF','#1C3FFD','2C1DFF', +'#010000','#393845','#9B96A3','#5C0009','940315', +'#468071','#FFE87A','#FFCA53','#FF893B','E62738', +'#404040','#024959','#037E8C','#F2EFDC','F24C27', +'#FF765E','#C2AE8B','#FCCF65','#FFE5C6','B7BDC4', +'#003647','#00717D','#F2D8A7','#A4A66A','515932', +'#FAFAC0','#C4BE90','#8C644C','#594D37','293033', +'#2B3A42','#3F5765','#BDD4DE','#EFEFEF','E74C3C', +'#3B3B3B','#A8877E','#FFA49D','#FF7474','FF476C', +'#0A3A4A','#196674','#33A6B2','#9AC836','D0E64B', +'#FFA340','#38001C','#571133','#017A74','00C2BA', +'#DCEBDD','#A0D5D6','#789AA1','#304345','AD9A27', +'#588C7E','#F2E394','#F2AE72','#D96459','8C4646', +'#F0E6B1','#B5D6AA','#99A37A','#70584B','3D3536', +'#2F400D','#8CBF26','#A8CA65','#E8E5B0','419184', +'#010712','#13171F','#1C1F26','#24262D','961227', +'#403F33','#6E755F','#AFC2AA','#FFDEA1','E64C10', +'#C74029','#FAE8CD','#128085','#385052','F0AD44', +'#CFF09E','#A8DBA8','#79BD9A','#3B8686','0B486B', +'#E0401C','#E6B051','#272F30','#F7EDB7','9E2B20', +'#FFE2C5','#FFEEDD','#FFDDAA','#FFC484','FFDD99', +'#FFFFE4','#F2E5BD','#B9BF8E','#A69F7C','8C6865', +'#5C8A2D','#AFD687','#FFFFFF','#00C3A9','008798', +'#4F3130','#FF1F3D','#5BE3E3','#FDFFF1','8B9698', +'#D23600','#D95100','#DE6D00','#EE8900','FCA600', +'#FFFFFA','#A1A194','#5B605F','#464646','FF6600', +'#F34A53','#FAE3B4','#AAC789','#437356','1E4147', +'#2A7A8C','#176273','#063540','#E6D9CF','403D3A', +'#21455B','#567D8C','#A59E8C','#8C8372','F2F2F2', +'#012340','#026873','#83A603','#BBBF45','F2F0CE', +'#FDFF98','#A7DB9E','#211426','#6B073B','DA8C25', +'#002F36','#142426','#D1B748','#EDDB43','FFFD84', +'#420000','#600000','#790000','#931111','BF1616', +'#3C989E','#5DB5A4','#F4CDA5','#F57A82','ED5276', +'#23A38F','#B7C11E','#EFF1C2','#F0563D','2E313D', +'#F5ECD9','#2BACB5','#B4CCB9','#E84D5B','3B3B3B', +'#A5EB3C','#60C21E','#159E31','#53DB50','C5FFCB', +'#263138','#406155','#7C9C71','#DBC297','FF5755', +'#0A111F','#263248','#7E8AA2','#E3E3E3','C73226', +'#003B59','#00996D','#A5D900','#F2E926','FF930E', +'#00A19A','#04BF9D','#F2E85C','#F53D54','404040', +'#324152','#47535E','#796466','#C1836A','DEA677', +'#036F73','#84CDC2','#FEF2D8','#F18C79','EF504F', +'#174040','#888C65','#D9CA9C','#D98162','A65858', +'#56797F','#87A0A4','#FCFBDC','#F2DDB6','A6937C', +'#A8BAA9','#FFF5CF','#DBCDAD','#B39C7D','806854', +'#60655F','#AB9675','#FFE0C9','#D4CCBA','CF8442', +'#BDDFB3','#009D57','#2C372E','#0F2925','465F3F', +'#3E3947','#735360','#D68684','#F1B0B0','EBD0C4', +'#0A7B83','#2AA876','#FFD265','#F19C65','CE4D45', +'#FFFFFF','#F4921E','#858585','#C5D2DB','3E6B85', +'#11151E','#212426','#727564','#B9AA81','690C07', +'#000000','#910000','#CBB370','#FFFBF1','21786C', +'#F78F00','#C43911','#75003C','#37154A','0F2459', +'#003354','#91BED4','#D9E8F5','#FFFFFF','F26101', +'#3DA8A4','#7ACCBE','#FFFFF7','#FF99A1','FF5879', +'#64C733','#F0F0F0','#3E879E','#57524D','36302B', +'#343844','#2AB69D','#E65848','#FDC536','FCF2D7', +'#E34517','#F5FF53','#B4E85E','#00BD72','0B4239', +'#A84B3A','#FF9F67','#233138','#FFF7F5','4C646B', +'#59535E','#FAEEFF','#F1BAF3','#5D4970','372049', +'#FF6F22','#D9984F','#FFE8A9','#3E4237','32948A', +'#5D7370','#7FA6A1','#B8D9B8','#D6EDBD','FFF5BC', +'#FFBE00','#FFDC00','#FFD10F','#FFDE20','E8CA00', +'#003840','#005A5B','#007369','#008C72','02A676', +'#E1E6FA','#C4D7ED','#ABC8E2','#375D81','183152', +'#BA2F1D','#FFF8A4','#F5E67F','#264A59','1E2C30', +'#222526','#FFBB6E','#F28D00','#D94F00','80203B', +'#EBD096','#D1B882','#5D8A66','#1A6566','21445B', +'#F00807','#5F6273','#A4ABBF','#CCC9D1','E2E1E9', +'#DFE0AF','#A4BAA2','#569492','#41505E','383245', +'#152737','#2B4E69','#799AA5','#FFFFF0','682321', +'#C44C51','#FFB6B8','#FFEFB6','#A2B5BF','5F8CA3', +'#5ADED4','#4DAAAB','#26596A','#163342','6C98A1', +'#FF5B2B','#B1221C','#34393E','#8CC6D7','FFDA8C', +'#3D4D4D','#99992E','#E6E666','#F2FFBF','800033', +'#242424','#437346','#97D95C','#D9FF77','E9EB9B', +'#FFEBB0','#FFB05A','#F84322','#C33A1A','9F3818', +'#4D2B2F','#E57152','#E8DE67','#FFEFC3','C0CCAB', +'#A82221','#DB5E31','#EDA23E','#F2CB67','BFB840', +'#3B3140','#BFB8A3','#F2E0C9','#F2B9AC','D97E7E', +'#43464D','#9197A6','#D3DCF2','#7690CF','48577D', +'#EFDFBB','#9EBEA6','#335D6A','#D64F2A','7A8A7F', +'#000001','#313634','#C7CECF','#5C0402','941515', +'#334D5C','#45B29D','#EFC94C','#E27A3F','DF5A49', +'#F5F4E1','#D6C9B5','#B4AA97','#D44917','82877A', +'#19162B','#1C425C','#6ABDC4','#F0E4C5','D6C28F', +'#00132B','#7F9DB0','#C5E2ED','#FFFFFF','F95900', +'#1F3642','#6D968D','#B6CCB8','#FFE2B3','56493F', +'#08A689','#82BF56','#C7D93D','#E9F2A0','F2F2F2', +'#DE3961','#A4E670','#FFFFDC','#B3EECC','00ADA7', +'#849972','#D9D094','#A6A23E','#4F2F1D','8F5145', +'#F41C54','#FF9F00','#FBD506','#A8BF12','00AAB5', +'#00585F','#009393','#F5F3DC','#454445','FF5828', +'#FF6138','#FFFF9D','#BEEB9F','#79BD8F','00A388', +'#140B04','#332312','#B59D75','#E3D2B4','FFF7EA', +'#ED3B3B','#171F26','#77B59C','#F2E7B1','635656', +'#46594B','#A6977C','#D9B384','#734F30','260B01', +'#CCB8A3','#FF8FB1','#FFF5EA','#4E382F','B29882', +'#B70000','#FFFFFF','#FFCA3D','#94C4F4','0092B3', +'#053B44','#06736C','#A53539','#B9543C','EAD075', +'#E8C1B9','#FFB3AB','#FFCAB8','#E8B69C','FFCEAB', +'#E7F2DF','#69043B','#59023B','#231E2D','161726', +'#E82B1E','#E5DEAF','#A0B688','#557A66','453625', +'#F1E6D4','#BA3D49','#791F33','#9F9694','E3E1DC', +'#CED59F','#F1EDC0','#B1BEA4','#647168','282828', +'#2C3E50','#E74C3C','#ECF0F1','#3498DB','646464', +'#DE7047','#FFDE8D','#FFFFFF','#CDDE47','528540', +'#8EAB99','#40232B','#D95829','#D97338','DEC085', +'#E9662C','#EBAF3C','#00AC65','#068894','2B2B2B', +'#46483C','#A0AA8F','#EBE3CB','#FFFFFF','F26101', +'#170F0E','#290418','#505217','#FFD372','FFF1AF', +'#263545','#C4273C','#D7DADB','#6DBCDB','FFFFFF', +'#DCFAC0','#B1E1AE','#85C79C','#56AE8B','00968B', +'#075807','#097609','#70AF1A','#B9D40B','E5EB0B', +'#521000','#712800','#744E1D','#879666','F1D98C', +'#261F26','#3F3B40','#6C7367','#BFBF8A','F2E086', +'#2C3E50','#FC4349','#D7DADB','#6DBCDB','FFFFFF', +'#506D7D','#94CCB9','#FFECA7','#FFB170','F07D65', +'#3F4036','#8DA681','#F2E1C2','#BF2806','8C1D04', +'#990700','#CC542E','#FF964F','#FFCB7C','787730', +'#195073','#7F8C1F','#EE913F','#F2E5BD','9FD7C7', +'#1B3E59','#F2F0F0','#FFAC00','#BF0404','730202', +'#EA6045','#F8CA4D','#F5E5C0','#3F5666','2F3440', +'#F95759','#FDA099','#FFFFFF','#D9F3CB','8AC2B0', +'#265573','#386D73','#81A68A','#9FBF8F','D4D9B0', +'#E1DA36','#FFEA1B','#6FE4DA','#1DB0BC','007BBC', +'#013859','#185E65','#F9CC7F','#F15C25','9E1617', +'#36CC7C','#D6FFBE','#94D794','#228765','77A668', +'#94201F','#D4421F','#478A80','#D9E061','F08835', +'#F16233','#00B5B5','#F0F0F0','#3E4651','5C6D7E', +'#2E806C','#76CC99','#E0FFED','#FF5F3A','D2413C', +'#00393B','#00766C','#44A18E','#E5EDB6','F6695B', +'#734854','#F2F2E9','#D9D7C5','#A69580','736766', +'#03497E','#0596D5','#9DEBFC','#8D7754','FEB228', +'#F0E14C','#FFBB20','#FA7B12','#E85305','59CC0D', +'#FE4365','#FC9D9A','#F9CDAD','#C8C8A9','83AF9B', +'#00557C','#186D94','#3488AD','#81C1DC','BBE5F3', +'#DEE8D7','#918773','#420A1A','#240001','4D493A', +'#FFFFFF','#CAC535','#97AF25','#158471','41342C', +'#041F3D','#0B2E41','#165751','#448C61','9AC16D', +'#FA8C01','#FF6405','#577700','#082400','A0A600', +'#78C0F9','#FFDDCE','#FFFFFF','#FFDBE6','FE86A4', +'#351330','#CC2A41','#E7CAA4','#759A8A','524549', +'#02151A','#043A47','#087891','#C8C8C8','B31D14', +'#F34A53','#FAE3B4','#AAC789','#437356','1E4147', +'#58838C','#DAD7C7','#BF996B','#BF5841','A61C1C', +'#556354','#E68F0D','#8C948A','#495450','42423F', +'#323640','#5B6470','#8C94A1','#BDC7D6','DFE2FF', +'#FF0000','#FF950B','#2FA88C','#DEEB00','4B2C04', +'#0F3D48','#174C5B','#366774','#ECECE7','E96151', +'#3DBB7E','#A3CD39','#FBAC1D','#F96C1E','EE4036', +'#23363B','#A44F3F','#F8983D','#8D9151','BBC946', +'#4B5657','#969481','#D2C9B0','#F4E3C1','B6B835', +'#E8980C','#B1F543','#F2FF00','#FF5E00','59BBAB', +'#849696','#FEFFFB','#232D33','#17384D','FF972C', +'#555555','#7BB38E','#F4F1D7','#F8AB65','F15C4C', +'#1D3C42','#67BFAD','#F2EC99','#F2C48D','F25050', +'#334D5C','#45B29D','#EFC94C','#E27A3F','DF4949', +'#B8E1F2','#249AA7','#ABD25E','#F8C830','F1594A', +'#FDEDD0','#BCF1ED','#FF634D','#FD795B','FFF0AA', +'#FFFFFF','#E5E1D1','#52616D','#2C343B','C44741', +'#FFFFF1','#D5FF9B','#8FB87F','#5A7B6C','374E5A', +'#010340','#0E1E8C','#0003C7','#1510F0','1441F7', +'#002A4A','#17607D','#FFF1CE','#FF9311','E33200', +'#871E31','#CCC097','#9E9D7B','#687061','262626', +'#F16663','#F48D6C','#F2E07B','#8ABE9B','4A6D8B', +'#001F11','#204709','#0C8558','#FFD96A','FF4533', +'#1D1626','#F2E0BD','#BFAA8F','#8C786C','594C4C', +'#685D47','#913420','#1E2729','#C1D9C5','FEEFB1', +'#1D7561','#FC8448','#FF4138','#A8282B','38141B', +'#BF0633','#FF484E','#FF9273','#D1D0B4','E5ECED', +'#8E9E63','#E6DBB0','#F5EED7','#C4BCA0','176573', +'#665446','#809994','#AECCB6','#DEF2C4','E6683F', +'#3D0D26','#660A3E','#891C56','#B0276F','C93482', +'#082136','#00294D','#004B8D','#0068C4','2998FF', +'#3C4631','#9A746F','#F8A2AB','#F1C6B3','EAE9C0', +'#FF534E','#FFD7AC','#BED194','#499989','176785', +'#006D80','#BDA44D','#3C2000','#84CECC','78A419', +'#352C2B','#3C555C','#9E9657','#FFEBCD','CD5510', +'#2C3E50','#FC4349','#6DBCDB','#D7DADB','FFFFFF', +'#523631','#D1BE91','#605E3A','#4D462F','592F39', +'#18293B','#5B5A56','#F2DEA0','#D0B580','FFFBFF', +'#C8DBB6','#ECEBB7','#CCC68A','#B8B165','827A5D ', +'#7DA88C','#EBE9A0','#BED24B','#859132','35323C', +'#E8574C','#F27B29','#E6A51B','#D9CC3C','399977', +'#324032','#B7C22C','#FFFFE1','#22A8B5','2A3F42', +'#B3A589','#FFB896','#FFF9B1','#9AB385','11929E', +'#272433','#343F4F','#3D6066','#77994D','B2D249', +'#250701','#6D4320','#B0925F','#E7DEC0','82ABB8', +'#023550','#028A9E','#04BFBF','#EFEFEF','FF530D', +'#594732','#40342A','#7A422E','#D4CA9A','EDE5AE', +'#013C4D','#BA5B22','#DB913C','#F0B650','FAD46B', +'#143840','#5C6B63','#A69E89','#E0C297','D96523', +'#3FB8AF','#7FC7AF','#DAD8A7','#FFB38B','FF3F34', +'#CA3995','#F58220','#FFDF05','#BED73D','61BC46', +'#FFE1D0','#FFBFB4','#FF837E','#FF4242','BF1616', +'#C4EEFF','#7BA32D','#094201','#A41717','C48726', +'#001325','#187072','#90BD90','#D7D8A2','F2E4C2', +'#1A4F63','#068587','#6FB07F','#FCB03C','FC5B3F', +'#97B350','#333230','#736D61','#BAAB90','FFE5BA', +'#403D33','#807966','#CCC2A3','#8C0000','590000', +'#5F8A42','#86AD59','#F6FAA1','#F28410','D66011', +'#BF355D','#ED8168','#FAB66A','#F2DC86','83BFA1', +'#E1F03E','#FFBA14','#DB3A0F','#A1003D','630024', +'#212226','#45433F','#687067','#BDBB99','F0EAC3', +'#FE4365','#FC9D9A','#F9CDAD','#C8C8A9','83AF9B', +'#293B47','#5F7A87','#FFFFFF','#CBFF48','00ADA9', +'#282A33','#697371','#FFE7A6','#F5BA52','FA8000', +'#0C304A','#2B79A1','#F3F4F1','#85A71E','BFD841', +'#008B83','#4DAE83','#A0AE79','#FFE499','FF665E', +'#5D7359','#E0D697','#D6AA5C','#8C5430','661C0E', +'#324452','#97BDBF','#F2DFBB','#F28705','BF3604', +'#EEEFB9','#6ACFAE','#369C93','#232928','B03831', +'#332F45','#015770','#2A8782','#9FD6AE','FFFED2', +'#2B2830','#5C504F','#ABAB8E','#D9D7A3','C7BE88', +'#DC941B','#EDC266','#B6952C','#E1D3A6','E9A119', +'#00305A','#00448D','#0074D9','#4192D9','7ABAF2', +'#344459','#485F73','#5DA6A6','#A9D9CB','F2EAD0', +'#060719','#4D1B2F','#9E332E','#EB6528','FC9D1C', +'#96CEB4','#FFEEAD','#FF6F69','#FFCC5C','AAD8B0', +'#05F2F2','#04BFBF','#EEF1D9','#A60201','7E100E', +'#E6F1F5','#636769','#AAB3B6','#6E7476','4B4E50', +'#DA0734','#F1A20D','#4AABB1','#FCF3E7','3F1833', +'#202D44','#FC4349','#6DBCDB','#D7DADB','FFFFFF', +'#CC3B37','#398899','#FFFCE8','#FF857F','CCC1A3', +'#5DBEA9','#EFEDDF','#EF7247','#4E3F35','D1CBBA', +'#FFC62D','#E49400','#DD5200','#EFE38A','91B166', +'#B67D14','#F2921F','#F0B23E','#A62409','441208', +'#C71B1B','#D6BA8A','#017467','#E08F23','0B0D0C', +'#474143','#A69E9D','#E7E2DA','#FFFFFF','E7E8E7', +'#435772','#2DA4A8','#FEAA3A','#FD6041','CF2257', +'#6DD19D','#99E89D','#D0E8A1','#FFF9C0','D40049', +'#FAF1D5','#DEC9AC','#CCA18B','#11282D','A5C4BB', +'#000000','#141414','#1C1919','#1A1716','24201F', +'#D5D8DD','#5CA2BE','#135487','#2A4353','989DA4', +'#73161E','#BF0F30','#BFB093','#037F8C','0A2140', +'#195962','#F56F6C','#FFFFFF','#252932','191C21', +'#F8EFB6','#FEBAC5','#6CD1EA','#FACFD7','C2EAE9', +'#91D6BC','#768C6A','#755F31','#B37215','FFBA4B', +'#F2E6BB','#DD4225','#202724','#63BD99','F8FDD8', +'#762B1B','#807227','#CCBF7A','#FFEF98','60B0A1', +'#707864','#C1D74E','#F5FF7C','#DFE6B4','A6B89C', +'#FFF3D2','#97B48F','#E87657','#FF9B6F','E8D495', +'#33262E','#733230','#CC5539','#E6D27F','86A677', +'#122430','#273E45','#FFFCE2','#EBD2B5','E63531', +'#30394F','#FF434C','#6ACEEB','#EDE8DF','FFFBED', +'#0A3A4A','#196A73','#32A6A6','#A1BF36','C8D94A', +'#FFF7CC','#CCC28F','#70995C','#33664D','142933', +'#43464D','#9197A6','#D3DCF2','#7690CF','48577D', +'#DFE0AF','#A4BAA2','#569492','#41505E','383245', +'#B52841','#FFC051','#FF8939','#E85F4D','590051', +'#473C35','#A36D5C','#9C968B','#D9CEAD','8A866A', +'#DB4C39','#2D3638','#109489','#44D487','D0DB86', +'#6F8787','#AEC2AE','#E6DFAE','#B0B57B','888F51', +'#C8385A','#FFCF48','#ECEABE','#1FCECB','1CA9C9', +'#42282E','#75A48B','#D9CFB0','#DC9B74','D6665A', +'#362F2D','#4C4C4C','#94B73E','#B5C0AF','FAFDF2', +'#98293A','#B14A58','#C86C6B','#DE9D76','EFC77F', +'#C1D301','#76AB01','#0E6A00','#083500','042200', +'#453F22','#7A6B26','#CCAD5C','#A1191F','4E1716', +'#541E32','#8E3557','#88A33E','#C2BD86','F7F2B2', +'#2B1B2E','#54344D','#FFFFD6','#B89E95','6E444F', +'#6EC1A5','#9FBEA6','#F5D3A3','#FF9F88','FB7878', +'#2F252C','#D3CCB2','#99AD93','#6E6751','5C3122', +'#BE333F','#F2E9CE','#C8C5B1','#939F88','307360', +'#F0F1F2','#232625','#647362','#B3D929','D2D9B8', +'#FA2B31','#FFBF1F','#FFF146','#ABE319','00C481', +'#09455C','#527E7C','#F5FFCC','#E0EB6E','C4D224', +'#F2DA91','#F2B950','#F29D35','#D96704','BF4904', +'#A2CFA5','#E0E7AB','#F5974E','#E96B56','D24344', +'#150033','#310D42','#5C2445','#AB6946','FFCE4C', +'#23A38F','#B7C11E','#EFF1C2','#F0563D','2E313D', +'#FF2468','#E0D4B1','#FFFFE3','#00A5A6','005B63', +'#65A683','#218777','#3F585F','#47384D','F53357', +'#000623','#28475C','#4A6C74','#8BA693','F0E3C0', +'#E65322','#D19552','#B8BF73','#B6DB83','FFF991', +'#112F41','#068587','#6FB07F','#FCB03C','FC5B3F', +'#C89B41','#A16B2B','#77312B','#1C2331','152C52', +'#C24366','#D9C099','#FFF8D8','#A8E0BA','00ADA7', +'#CC0000','#006600','#FFFFEC','#9C9178','6C644F', +'#3D0319','#720435','#C1140E','#FC5008','32241B', +'#CFC7A4','#5A9E94','#005275','#002344','A38650', +'#FFEBC3','#CC3A00','#FF3600','#FF851B','800C00', +'#EFC164','#F3835D','#F35955','#286275','00434C', +'#E9F29D','#B7C29D','#878E8F','#67617A','51456B', +'#445859','#03A696','#49C4BE','#F1F2E4','FF7746', +'#FA726C','#FFD794','#BAD174','#3BA686','5F6F8C', +'#4D2B1F','#635D61','#7992A2','#97BFD5','BFDCF5', +'#CC4D00','#E6CF73','#668059','#264D4D','00CCB3', +'#4385F5','#DC4437','#FCBE1F','#109D59','FFFFFF', +'#271F2E','#A4A680','#F2EBC9','#D9B166','A66B38', +'#0B2C3C','#FF6666','#DADFE1','#FFFFFF','444444', +'#CFF09E','#A8DBA8','#79BD9A','#3B8686','0B486B', +'#302B26','#A6B827','#EDE9DD','#98D3D4','594E7A', +'#4B0505','#720707','#BFB694','#004659','00292B', +'#B52C38','#EBD1B0','#536682','#D9964B','DE6846', +'#F2F1DF','#F2B705','#F2C84B','#BF820F','734002', +'#26140C','#3D2216','#784E3D','#AB8574','D6BCB1', +'#26221D','#8C2C0F','#E6E5B8','#BFB38D','402D1F', +'#1F8181','#F2BC79','#F28972','#BF1B39','730240', +'#002635','#013440','#AB1A25','#D97925','EFE7BE', +'#8EC447','#FFFFFF','#96D3D4','#636466','2D2D2E', +'#2D1E1E','#4B3C37','#96A576','#CDE196','FFFFBE', +'#F06060','#FA987D','#F7F2CB','#72CCA7','10A296', +'#1D8281','#44BF87','#FBD258','#F29A3F','DB634F', +'#DEDE91','#EF9950','#F34E52','#C91452','492449', +'#6D8EAD','#1F3447','#1A0B07','#362416','CFCDB4', +'#00CD73','#008148','#2D9668','#3ECD8E','004E2C', +'#3D8080','#628282','#858383','#A38282','C28080', +'#475159','#839795','#B2BDB7','#CCC9C0','F2F2F2', +'#0E6870','#C6B599','#C65453','#FFDDB4','EDAA7D', +'#CEF0B7','#A8DBA8','#79BD9A','#3B8686','0B486B', +'#292C44','#FF5349','#F0F0F1','#18CDCA','4F80E1', +'#272A2B','#383737','#473B39','#692B28','940500', +'#D6C274','#DB9E46','#25706B','#3D2423','AB362E', +'#FFA68F','#FF4867','#FFF9C8','#B5EBB9','18B29D', +'#A1A16A','#727D59','#366353','#133C40','03212E', +'#D45354','#A9DC3A','#2FCAD8','#818B85','CDCDC1', +'#F14B6A','#3D3C3E','#22BDAF','#BAD7D4','F4F4F4', +'#FFE2C5','#FFEEDD','#FFDDAA','#FFC484','FFDD99', +'#9FFF4A','#1ABF93','#087363','#004040','2F1933', +'#FFDB97','#B28F4E','#FFFDFB','#466CB2','97BBFF', +'#991C00','#E09A25','#FFFCDB','#008B83','262B30', +'#44281A','#00ACAE','#F5EFD5','#F37606','EE4717', +'#FF5952','#FCEEC9','#96D6D9','#4FAAC9','176075', +'#5C4B51','#8CBEB2','#F2EBBF','#A5C88F','EF847B', +'#105F73','#F7F3B2','#C6CC33','#F28322','CC5404', +'#137072','#56B292','#B7F5AB','#FBFFC0','BF223D', +'#E3F23E','#6C821C','#A6A53F','#E0E0AC','33302E', +'#00215E','#003CAA','#1967F7','#5E4000','AA7400', +'#273A3D','#54695C','#AD9970','#FFBF87','FF8F60', +'#FFAA00','#C2B93E','#808F5D','#576157','302F30', +'#BE1405','#F2DCAC','#AABEAA','#736E41','413C2D', +'#6B1229','#C76A61','#FAB99A','#F7D9B5','CCB1A7', +'#2D9993','#58B3A3','#83BFA3','#B0D9A8','FFFCB6', +'#334D5C','#45B29D','#EFC94C','#E27A3F','DF5A49', +'#F30B55','#010326','#012840','#54717F','F2E6CE', +'#2A3411','#73662C','#BC9847','#FFDFB2','6B0031', +'#637D74','#403D3A','#8C3B3B','#AB6937','D4A960', +'#010A26','#011640','#B6D6F2','#FFFFFF','E83338', +'#924847','#EB986C','#E4C678','#9C7885','372C2C', +'#022440','#3F95AA','#4EC6DE','#EAE2DF','F7572F', +'#2B1D2E','#323657','#076473','#54B087','D6F567', +'#052229','#004043','#BCC373','#E3FF55','D0D90C', +'#4C514A','#907A62','#879796','#755854','B09880', +'#1D2939','#1CAF9A','#FFFFFF','#EE4F4B','D1DC48', +'#004B67','#41CCB4','#FFEA95','#FF7C5D','C70151', +'#C0272D','#FCFBE7','#9FD3DA','#008C9A','05484F', +'#213130','#FF5E3D','#C9C83E','#FDFFF1','559398', +'#B1E4FC','#366D78','#39D5F1','#FFFFFF','D9FF03', +'#DECE6C','#FCF9B6','#BFE3B5','#5D826E','262E2B', +'#520A17','#668F91','#F5E6AC','#AB8E5B','52301C', +'#2D3032','#DD5F18','#FBA922','#F7F7F7','404333', +'#0C2538','#2B434F','#638270','#BCC98E','EDE059', +'#E85066','#F28E76','#E6CEB0','#5A8C81','382837', +'#BF2633','#A6242F','#D9CEAD','#C0B18F','011C26', +'#002A4A','#17607D','#FFF1CE','#FF9311','E33200', +'#0A8B91','#485956','#C4B98F','#FFF9BC','EEDF2E', +'#B89A7B','#9BBAAC','#F2D649','#D95D50','DBDBDB', +'#BD7938','#8D4421','#643001','#532700','3A1C00', +'#E1E6FA','#C4D7ED','#ABC8E2','#375D81','183152', +'#2E4259','#F7483B','#ECF0F1','#03C8FA','737373', +'#364656','#5D6B74','#94A4A5','#F2F5E9','FF8C31', +'#3E5916','#93A605','#F28705','#F25C05','E5EFFA', +'#248077','#74AD8D','#C82754','#F7BB21','F9E2B7', +'#20736A','#8BD9CA','#B1D95B','#93A651','403E34', +'#D74B4B','#DCDDD8','#475F77','#354B5E','FFFFFF', +'#252F33','#415C4F','#869C80','#93C2CC','CEEAEE', +'#012840','#79C7D9','#9BF2EA','#497358','9DBF8E', +'#EE7E94','#F8B4C4','#C7CAC9','#D8505C','41424', +'#282828','#505050','#FFFFFF','#2DCEDB','F20000', +'#004358','#1F8A70','#BEDB39','#FF5347','FD7400', +'#470C3B','#802F56','#C0576F','#E38679','FFBD83', +'#573328','#B05A3A','#FF8548','#29332E','0F1B1C', +'#461F2D','#E1FFBB','#BAD47F','#849C23','52533F', +'#333A40','#4C5E5E','#ADD0E5','#CDE4FF','729EBF', +'#DE5605','#F7A035','#B1DEB5','#EFECCA','65ABA6', +'#76D6D2','#F9E270','#EF6F56','#F4EED8','596B56', +'#403E3F','#F2F2F2','#D9D9D9','#9DAABB','8C8C8C', +'#059E9A','#F4F2ED','#F5A243','#DB3E3B','585857', +'#FFBF41','#EE8943','#C02221','#FFF4D3','249CA9', +'#024E76','#39A6B2','#FCE138','#F5B824','F08106', +'#FF0067','#FF3D6A','#E7FF04','#9CFF00','56FF00', +'#003540','#0D3F40','#487360','#8FA671','F2D795', +'#FF493C','#FFFFFF','#B3ECEF','#31C4F5','ADEB41', +'#244358','#4A8B87','#7CBCAE','#F0D4AF','C5252B', +'#EA5930','#F8AF1E','#F5E5C0','#097380','372560', +'#A1DBB2','#FEE5AD','#FACA66','#F7A541','F45D4C', +'#2C4A47','#6C9A7F','#BB523D','#C89D11','81810B', +'#F0F1F2','#232625','#647362','#FF5629','D2D9B8', +'#7C9B5F','#B8D197','#E3FFF3','#9BDEC7','568F84', +'#E54E45','#DBC390','#F2F2EF','#13A3A5','403833', +'#77A7FB','#E57368','#FBCB43','#34B67A','FFFFFF', +'#001A2E','#8F0000','#FFFFFF','#8A874B','41594F', +'#312F40','#49A69C','#EFEAC5','#E89063','BF5656', +'#047C8C','#018B8D','#F3BF81','#F49B78','F1706D', +'#00303E','#7096AD','#C1D1DE','#FFF9EF','EC4911', +'#2D6891','#70A0BF','#F5EEDC','#DC4C1A','F0986C', +'#040002','#3D1309','#E8B96A','#BC5D15','5C0F00', +'#8B929C','#5E6070','#514454','#3B313D','FF2479', +'#142D58','#447F6E','#E1B65B','#C8782A','9E3E17', +'#22104D','#2D1E5E','#483A85','#7067AB','A49CFA', +'#919C86','#9E373E','#2B2E36','#D1B993','C45A3B', +'#332F45','#015770','#2A8782','#9FD6AE','FFFED2', +'#37C78F','#FEE293','#FF4D38','#CC2249','380C2A', +'#47282C','#8C8468','#C9B37F','#DBDAB7','C4C49C', +'#14191A','#2D2B21','#A69055','#CCB287','FFB88C', +'#F5E3CD','#696158','#B6A898','#877D71','504A43', +'#005151','#009393','#F56200','#454445','969692', +'#D95F47','#FFF2C1','#80A894','#106153','072C36', +'#9E352C','#E6E8A9','#93C28C','#2E5A5C','2B2623', +'#03013A','#334A94','#6B9EDF','#83C3F2','99E6FF', +'#372A26','#4D4D4D','#6DA0A7','#9ED5A8','C7F5FF', +'#03658C','#022E40','#F2B705','#F28705','F25C05', +'#FF3B16','#E87826','#E8BA4A','#80A272','003045', +'#00748E','#E3DFBB','#F4BA4D','#E3753C','DA3B3A', +'#25401E','#56732C','#84A63C','#B8D943','EAF2AC', +'#449BB5','#043D5D','#EB5055','#68C39F','FFFCF5', +'#108F97','#FF8B6B','#FFE39F','#16866D','103636', +'#1A4F63','#068F86','#6FD57F','#FCB03C','FC5B3F', +'#381C19','#472E29','#948658','#F0E99A','362E29', +'#D7E8F7','#BBD0E3','#9CB7CF','#6A8BAB','375D81', +'#0F1C28','#136972','#67BFA7','#F3CF5B','F07444', +'#FFFFFF','#4EA9A0','#969514','#FE9C03','FCDE8E', +'#2F2D30','#656566','#65537A','#51386E','2A2333', +'#4C2916','#F05A28','#FBAF3F','#38B449','FFFFFF', +'#132537','#006C80','#EBCAB8','#FE8315','FA3113', +'#ECEEE1','#A8DACF','#F05B4F','#D8403A','221E1F', +'#00305A','#004B8C','#0074D9','#4192D9','7ABAF2', +'#72CF3F','#85FF00','#23E000','#2FB81B','00FF1C', +'#45CEEF','#FFF5A5','#FFD4DA','#99D2E4','D8CAB4', +'#FF5B00','#A1716C','#728296','#439AAB','00CABD', +'#EB6C2D','#D9C8A2','#939C80','#496158','232F38', +'#D94214','#FFF2C1','#80A894','#52736B','093844', +'#4D1B2F','#9E332E','#EB6528','#FC9D1C','FFCA50', +'#FFEEB0','#9AE8A4','#C7C12D','#F76245','ED1C43', +'#FFFAED','#D4DBFF','#879AC9','#242942','FF8800', +'#022840','#013440','#517360','#9DA67C','F2DC99', +'#331A0F','#519994','#BA4B3C','#EEDDAA','789F63', +'#577867','#EDCE82','#D68644','#AB3229','662845', +'#435A66','#88A6AF','#F5F2EB','#D9CDB8','424342', +'#FF8840','#958D4F','#737B55','#595540','513E38', +'#9D805A','#EBC99D','#FFE6C5','#9DCEEA','4B809E', +'#272D40','#364659','#55736D','#9DBF8E','D0D991', +'#23A38F','#B7C11E','#EFF1C2','#F0563D','2E313D', +'#98C000','#3D4C53','#EA2E49','#FFE11A','0CDBE8', +'#A20E30','#E93C4F','#DCDCD4','#ADBCC3','2D4255', +'#1C2640','#263357','#384C80','#4E6AB3','5979CD', +'#D94214','#FFF2C1','#80A894','#52736B','093844', +'#3B596A','#427676','#3F9A82','#A1CD73','ECDB60', +'#1E1E1F','#424143','#67666A','#807F83','CBC9CF', +'#E04946','#3BA686','#B6D15D','#FFD495','FA847E', +'#FFEBB0','#FFB05A','#F84322','#C33A1A','9F3818', +'#FFA136','#FF814A','#E6635A','#785D6B','534557', +'#CDCF91','#EBEACC','#D6D5B8','#6D7D80','41545E', +'#011526','#011C40','#4E8DA6','#F2EA79','F2B33D', +'#353230','#3F4E51','#7B8F70','#99B2BE','F6F4EA', +'#063559','#0D8C7F','#8FBF4D','#F2D13E','D95929', +'#158000','#199900','#20BF00','#24D900','29FF00', +'#0B0D0E','#137074','#7EB7A3','#F1DDBB','EC6766', +'#02151A','#043A47','#087891','#C8C8C8','B31D14', +'#59361F','#5C992E','#A3CC52','#E6E673','FF5933', +'#FE4365','#FC9D9A','#F9CDAD','#C8C8A9','83AF9B', +'#4B1E18','#F9E5C2','#BBB082','#829993','4F5D4E', +'#032843','#1F595B','#508C6D','#71A670','A6DB89', +'#191724','#4C4547','#8C594E','#D18952','FDB157', +'#191919','#182828','#60702D','#AAB232','E6FA87', +'#212A3F','#434F5B','#F2F2F2','#8AB839','2E2E2E', +'#004158','#026675','#038B8B','#F1EEC9','F09979', +'#023059','#3F7EA6','#F2F2F2','#D99E32','BF5E0A', +'#F21E52','#FFFFFF','#3D3B42','#0C6F73','63CFD4', +'#452743','#E7635E','#F8E9A8','#89E0AD','00928C', +'#FAAD63','#D1714D','#785E48','#39403B','3D1C24', +'#4C0016','#FFF7EB','#DCCEA7','#A17345','104F53', +'#BF2431','#F24150','#2A4557','#3B848C','EFF2E4', +'#3B3013','#8F6031','#E88833','#9C0C0A','FDF3C1', +'#1E2422','#88BEB1','#FF006D','#DAFFFF','718A94', +'#F1F4F7','#AF9F7B','#775E43','#40413C','251C17', +'#00182E','#0C6BA1','#D4D6D4','#FFFDEB','FF7500', +'#FFAB4A','#CCBAAB','#1E2129','#3D5E6E','47A3A3', +'#66B3A7','#C0D4B6','#EEF0BD','#F0563D','2C2F3B', +'#332525','#907465','#EDC5B5','#878C6D','63674A', +'#F04C16','#DBDBD0','#EDBD1F','#4CB09C','313B4A', +'#2B211D','#611C26','#C5003E','#8EB7A8','F1E4B7', +'#1A1F2B','#30395C','#4A6491','#85A5CC','D0E4F2', +'#03497E','#0596D5','#9DEBFC','#999999','FE4B28', +'#2F4159','#465E73','#88A649','#F2ECE4','D98841', +'#323A46','#22282F','#EB4A33','#FFFFFF','E9F0F5', +'#2C3E50','#FC4349','#6DBCDB','#D7DADB','FFFFFF', +'#F29727','#E05723','#B0382F','#982E4B','713045', +'#4D584A','#465943','#428552','#3E754E','4C694B', +'#47191C','#59574B','#829690','#B5B09A','E1E3CB', +'#1D5123','#B1C661','#FFDA68','#FE9257','F64448', +'#59323C','#260126','#F2EEB3','#BFAF80','8C6954', +'#4E0805','#9E0522','#FFF4D4','#B8C591','447622', +'#424862','#FB9A63','#BFC4D5','#F6FBF4','FEBC98', +'#FF2468','#E0D4B1','#FFFFE3','#00A5A6','005B63', +'#1C2F40','#4C6173','#8094A6','#D9D1BA','F2E9D8', +'#DFD7B7','#EB7707','#5C5445','#3B2323','9CBFC7', +'#262E3B','#9C8878','#CFCAAA','#FBF8FF','992435', +'#FFBC67','#DA727E','#AC6C82','#685C79','455C7B', +'#404A69','#516C8A','#8AC0DE','#FFFFFF','FFAC00', +'#485B61','#4B8C74','#74C476','#A4E66D','CFFC83', +'#A31180','#C42795','#DE52B4','#EA88CE','FFBFE5', +'#E64D2E','#FFF5F1','#7893AD','#576B9C','2D2A52', +'#BF0436','#8C0327','#590219','#F2CBA1','8C674C', +'#CF5B6F','#FFF8C8','#CAD9B1','#8FB3A0','648991', +'#341D44','#744D90','#BB8CDD','#3E4417','88904D', +'#00293E','#003D4E','#006269','#00918F','00BAB5', +'#43212E','#D9666F','#F2D57E','#A9A688','516057', +'#2A3B30','#ABFFD1','#EBFFF5','#9DFEFF','273B40', +'#A63343','#E65159','#F5E9DB','#F4F7CF','BAD984', +'#1BA68C','#54BFAC','#F2EDA7','#F2E530','D94625', +'#1A2A40','#3F7369','#F2DEA0','#CE5251','EA895E', +'#1E9382','#70A758','#EFF1C2','#F0563D','2E313D', +'#A991E8','#FFB4BB','#ACF7FF','#A2E891','FFEDAE', +'#225B66','#17A3A5','#8DBF67','#FCCB5F','FC6E59', +'#282624','#BFB7AA','#403D39','#807A71','ABA398', +'#334D5C','#45B29D','#EFC94C','#E27A3F','DF4949', +'#440008','#605521','#988432','#D9A54E','9E3711', +'#649670','#36291E','#69AD6C','#92E67C','C5FF84', +'#42342C','#738076','#B2B39B','#DFE5E1','294359', +'#1A3838','#3F7A51','#82A352','#D1C062','FFBE59', +'#7D8C22','#B3BF67','#F2E49B','#D9DFF4','6791BF', +'#8A7D6D','#2D2D38','#E86E48','#FFFFE8','9CC9C9', +'#CFC949','#FFF5BF','#A9E6C4','#6AB39F','665841', +'#A1172D','#FDFFBA','#A7DB9E','#275C57','1F1B19', +'#FF6C0D','#F29E00','#E6C10F','#44996F','216273', +'#2C3E50','#FA4248','#D7DADB','#6DBCDB','FFFFFF', +'#627369','#99B397','#E2F2C6','#91CCAD','376266', +'#04496E','#66CAFF','#A3FC7E','#70D44A','2C6B0F', +'#1BA68C','#97BF3F','#F2ECD8','#F2B035','F2522E', +'#A2D9B1','#7CBF9E','#F2F1B9','#8C8575','193741', +'#024959','#037E8C','#F2EFDC','#E74C30','363636', +'#212625','#9CA6A2','#D0D9D6','#BF0404','C2C6AF', +'#00FFFF','#00FF00','#FFFF00','#FF5100','FF007C', +'#212629','#CDCF19','#FFF77D','#96C4AB','CF2A56', +'#CFF9FF','#BFC7BB','#787051','#332730','57324F', +'#98CACB','#FDEFBE','#F0542B','#736E5B','ABA68E', +'#F2F1EB','#BFB9A4','#262222','#802A30','8C0303', +'#65356B','#AB434F','#C76347','#FFA24C','519183', +'#78BF82','#A4D17C','#CFD96C','#EBD464','FFD970', +'#806265','#FFA256','#F7DD77','#E0D054','ABA73C', +'#8F323C','#123943','#80BDDB','#4189AB','C98127', +'#683820','#8C9A89','#E7D6A2','#BEAA65','9A8234', +'#021B21','#032C36','#065F73','#E8DFD6','FF2A1D', +'#2D6C73','#3FA693','#B4D9CB','#9ABF49','C6D93B', +'#141F26','#2B4040','#405950','#A69E86','F2D9BB', +'#4A8279','#003330','#610400','#003B06','02730F', +'#69B5E1','#D4E4F5','#EAF2F8','#BEDBED','000000', +'#893660','#EF7261','#68D693','#A0D7E2','299CA8', +'#073A59','#2D9AA6','#F2E2DC','#F23322','A61B1B', +'#2A3A48','#3E6372','#B2D4DC','#FAFAFF','FF6900', +'#F3BD8D','#F1A280','#BE6D6B','#704A5B','3E263C', +'#1C2742','#3C91C7','#5A9ABE','#95C5DE','E0EEFB', +'#426261','#465A59','#577573','#739A97','9AC1C0', +'#002A4A','#17607D','#FFF1CE','#FF9311','D64700', +'#589373','#BFBD99','#F2D6B3','#C2512F','241E1E', +'#1F518B','#1488C8','#F7E041','#E2413E','B5292A', +'#549494','#E85649','#232C2E','#E6E8D2','706558', +'#392133','#FFECBE','#D9D098','#C4AB6D','AB7D3A', +'#F0F0F0','#1C1C1C','#A2FDF5','#1CCDC7','27EDDF', +'#011526','#025959','#027353','#03A678','03A696', +'#004358','#1F8A70','#BEDB39','#FFE11A','FD7400', +'#37465D','#F2F2F2','#9DC02E','#779324','051A37', +'#580022','#AA2C30','#FFBE8D','#487B80','011D24', +'#F9F9F9','#03A678','#E9EDEB','#F44647','00707F', +'#800000','#BF0000','#E2D6C2','#F6EDD8','FFFFFF', +'#F7F6AF','#1B2124','#D62822','#97D6A6','468263', +'#432852','#992255','#FF3D4C','#28656E','00968F', +'#444344','#52BBB2','#2B344D','#EE5555','F8F7EE', +'#45334A','#796B7D','#CCC4B0','#FFF1B5','FFA3A3', +'#5A4B53','#9C3C58','#DE2B5B','#D86A41','D2A825', +'#14151C','#0C242B','#297059','#84D66E','D1FB7A', +'#272D40','#364659','#55736D','#9DBF8E','D0D991', +'#23A38F','#B7C11E','#EFF1C2','#F0563D','2E313D', +'#2E064D','#80176B','#B356A1','#59580B','FFFF00', +'#CC3333','#FF9D33','#F7F7F0','#3EBBA7','00747A', +'#5C4B51','#8CBEB2','#F2EBBF','#F3B562','BD6060', +'#0D3E58','#1C848C','#19C0C2','#F3EDD6','DA6260', +'#022629','#2A5945','#FAFFED','#E6DCC0','B3371C', +'#F4FAC7','#7BAD8D','#FFB159','#F77F45','C2454E', +'#A2C1C6','#86B1B7','#AECBAD','#CFDCB0','D6E1D1', +'#B0DAFF','#325B80','#64B7FF','#586D80','5092CC', +'#0F808C','#6C8C26','#F2A71B','#F26A1B','D91818', +'#FFBC6C','#FE9F6C','#BD716E','#74495F','3B2C4D', +'#FF4D41','#F2931F','#E6CA21','#91B321','1E8C65', +'#302821','#453629','#5C4837','#8A735F','BDA895', +'#415457','#5F7B7F','#9ACCAF','#E6EBC4','F9F7C8', +'#474143','#A69E9D','#E7E2DA','#FFFFFF','E7E8E7', +'#805939','#BD9962','#E6CD7D','#578072','2D4B4D', +'#03588C','#1763A6','#419CA6','#54BF83','8DBF41', +'#00CCFF','#A1FCFF','#040438','#004878','C9FAFF', +'#534C64','#B7DECF','#F0F3D7','#7E858C','D96557', +'#7F7364','#CBB08E','#CBC1B7','#789DCB','646F7F', +'#5C2849','#A73E5C','#EC7263','#FE9551','FFD285', +'#FF0012','#FF7D00','#FFD900','#5BE300','0084B0', +'#F24C32','#F29471','#FCDFA6','#36B898','3D7585', +'#083157','#0A6C87','#459C97','#92CCA5','C9F0B1', +'#DC941B','#EDC266','#B6952C','#E1D3A6','E9A119', +'#323836','#BAD1B5','#DBE8CF','#F0F7E8','FFFEF5', +'#081724','#589494','#8EBBB4','#D0DCD0','F5EED2', +'#50781C','#9CAD1C','#EAF7E6','#40A5DE','0B5191', +'#537F79','#78A68F','#CBD49C','#FED457','CB252A', +'#F23C13','#CBAB78','#FFFFFF','#898373','1F1C17', +'#450003','#5C0002','#94090D','#D40D12','FFED75', +'#0770A2','#82D9F7','#FEFEFE','#AEC844','F36622', +'#30394F','#FF434C','#6ACEEB','#EDE8DF','0E6569', +'#FF6B6B','#556270','#C7F464','#4ECDC4','EDC8BB', +'#D9B500','#FFED9C','#BFCC85','#748F74','454545', +'#452E32','#A34B1B','#B5A187','#EDDF9A','A7CC31', +'#2C2B33','#596664','#909980','#CCC08D','FF8A00', +'#C21F1F','#FFFFFC','#E34446','#FFFFDB','E36D6F', +'#282828','#00AAB5','#C1C923','#F41C54','F5F0F0', +'#3A3F40','#202627','#151B1E','#EFF4FF','41444D', +'#DEBB73','#4D0017','#010000','#4D0F30','9A002F', +'#EB9328','#FFA754','#FFD699','#FFF5DC','4FA6B3', +'#025E73','#037F8C','#D9D59A','#D9BD6A','590202', +'#636266','#E0CEA4','#E8A579','#7D6855','42403E', +'#FF0000','#FF4000','#FF7F00','#FFBF00','FFFF00', +'#FFFFFF','#74ADA6','#1E5E6F','#241B1F','68A81E', +'#5A0532','#FF6745','#FFC861','#9DAE64','27404A', +'#ACCBBC','#467847','#E8E4C1','#A60303','730202', +'#5C4B51','#8CBEB2','#F2EBBF','#F3B562','F06060', +'#0D2557','#93A8C9','#FFFFFF','#F5DED5','558D96', +'#F53C4A','#565157','#10CFC8','#F2EEE7','F5D662', +'#FFD97B','#E65029','#A60027','#660033','191C26', +'#595408','#A6800D','#A66D03','#A63F03','730C02', +'#2E031F','#590424','#8C072B','#BF0A2B','DEEFC5', +'#E0C882','#A6874E','#BFA169','#D9B779','F2D399', +'#D88681','#A67673','#746566','#535A5D','324F54', +'#FC297D','#FB607A','#FDA286','#FDC188','FEE78A', +'#FFECA1','#B3B27F','#4C5E52','#2F3436','FFBE2C', +'#D93312','#B3AB82','#45735F','#394D47','2C3233', +'#324143','#6595A3','#C8E3E8','#FCFFED','B6C28B', +'#477984','#FEF5EB','#C03C44','#EEAA4D','313E4A', +'#334D5C','#45B29D','#EFC94C','#E27A3F','DF4949', +'#630B11','#33322F','#2A2927','#1E1D1C','000000', +'#D94214','#FFF2C1','#80A894','#52736B','093844', +'#051E21','#00302D','#856434','#F28C28','FFAD4E', +'#D7DADD','#DDDEE3','#E1E1E9','#EDEFF4','F2F3F8', +'#BF495E','#41A693','#F2EC9B','#D9CF48','D9583B', +'#067072','#14A589','#DECFA6','#BAAE8C','F94B06', +'#423A38','#47B8C8','#E7EEE2','#BDB9B1','D7503E', +'#730324','#DFE3E6','#B4C4D4','#8BA2BD','456382', +'#537374','#F9BD7F','#EBD7A5','#ADC9A5','5C9E99', +'#88B59E','#B6DEC8','#39464D','#C04229','ABD1AB', +'#11A7FC','#95D127','#F2E415','#FF8638','EE3551', +'#212640','#5D718C','#4B95A6','#60BFBF','EFF2D8', +'#D8A64D','#9B5422','#351411','#5B0D0D','991C11', +'#53324F','#668D6E','#F2E0A0','#F19B7A','F0756E', +'#DFE0AF','#A4BAA2','#569492','#41505E','383245', +'#7BBADE','#93DE7F','#FFED5D','#F29E4A','FF7050', +'#133800','#1B4F1B','#398133','#5C9548','93E036', +'#D9D7AD','#91A685','#FF6A00','#37485C','1C232E', +'#008767','#FFB27A','#FF6145','#AB2141','5E1638', +'#727B7F','#CCEAEA','#7A7556','#2E2125','44CACC', +'#FFFFED','#FF2C38','#FF9A3A','#FFF040','67D9FF', +'#007148','#60A859','#9BDA6A','#C7F774','F9FFEF', +'#092740','#45698B','#90B0CC','#F1FAFF','8FD36F', +'#E2FFA0','#7D8076','#FAFFED','#C2CCBE','8F7D70', +'#00736A','#00BC9F','#F1EEC7','#FEA301','F2561A', +'#26282E','#AD5138','#F7F7F7','#DDDAE0','8594AE', +'#1A191F','#35352F','#484042','#4E5252','E64D38', +'#49454A','#E69B02','#FAF4C6','#B1D631','324052', +'#5F1A2B','#1D2834','#6F8B78','#E4D49E','C96466', +'#012D3D','#38AD9E','#FFEB9E','#FF6867','D0DBED', +'#0D1F36','#104954','#1E9C89','#38CC85','60EB7B', +'#8C4E03','#9FA66A','#F2EC94','#F23005','8B0F03', +'#000001','#20201F','#E2E2E4','#590402','B80000', +'#344059','#465973','#F2D272','#A69460','595139', +'#33454C','#608F85','#B6E5CB','#8BAF95','54584E', +'#FBFEF6','#B7BFA4','#687F70','#1A3841','BF3847', +'#D7E836','#86FFC7','#FFB048','#E8366C','593BFF', +'#34A9FF','#5982DB','#665EB8','#684682','632E62', +'#004056','#2C858D','#74CEB7','#C9FFD5','FFFFCB', +'#BFB978','#84945C','#516967','#4D3130','281B24', +'#103B73','#20638C','#3786A6','#4EABBF','EBEFF2', +'#9FB1BF','#1D2D63','#1C5357','#1F6E56','196331', +'#FFEBBA','#C3BD91','#88947B','#4C3F3F','2A2727', +'#347373','#4EA6A6','#91D9D9','#FFFFFD','F2E205', +'#828948','#EFDFC2','#006971','#DC533E','840000', +'#000137','#29003F','#79003D','#D04D14','F89801', +'#370005','#4B0005','#5F0005','#730005','870005', +'#C3AE8D','#F25260','#2D5F73','#6BADC9','8FCED6', +'#9E1B36','#F7EDBA','#E69B3D','#EB3355','3D241D', +'#1D8281','#44BF87','#FBD258','#F29A3F','DB634F', +'#035C75','#1B808C','#31A6A8','#F3F1BC','F3AD14', +'#FF7500','#665130','#EBB643','#CEDAA8','668E84', +'#384D3A','#3E6653','#728053','#A68357','D97C71', +'#012326','#17455C','#E1CAAB','#FE8333','FA4913', +'#1A2944','#2DA7C7','#56ACBA','#98C4C9','CBD5D2', +'#BF3542','#CDC5BA','#EBE3D6','#3C3C3C','2E2E2E', +'#231921','#695F74','#BEB4CB','#EBEBF0','D2DCEB', +'#34373F','#686C75','#F3E9D0','#BEB7A7','8E867C', +'#661510','#D9351A','#F2C76F','#BF9727','204D3F', +'#3CFFEE','#24AABC','#356781','#2C3D51','1C1F24', +'#DA3537','#FFFCC4','#00585F','#6A6A61','2A2C2B', +'#AE3135','#D1AF87','#8C826B','#3D3C33','F2F0CE', +'#FF0894','#FF5E9F','#FF91A7','#FFB5CA','F5F0BA', +'#99878D','#323232','#646464','#7E4A5C','372129', +'#3FB8AF','#7FC7AF','#DAD8A7','#FFB38B','FF3F34', +'#402B3C','#6AA6A6','#D9CCA7','#F2B263','F26835', +'#6AA690','#F2BC1B','#F2DC99','#F29057','BF1F1F', +'#F4FAC7','#7BAD8D','#FFB158','#F77F45','C2454E', +'#E5533C','#F5E346','#93D06D','#50AC6A','227864', +'#39588A','#A9BDD7','#FFFFFF','#FFEADD','FFD0BB', +'#B0B595','#615F4F','#828567','#91A380','EAFFCD', +'#00427F','#0066BD','#66B5CC','#F0E4C5','D6C28F', +'#FF6313','#F9E4B3','#C29689','#74474B','45232E', +'#00585F','#009393','#FFFCC4','#C7C49B','EB0A00', +'#091840','#44A2FF','#F7F7EA','#B3CC63','4C6620', +'#5CBBE3','#FCF1BC','#5C8182','#383A47','B4F257', +'#9E9E9E','#E5E1D1','#E0393D','#253746','425563', +'#4D9453','#FFFFB1','#ADDE4E','#FF9D27','A62A16', +'#B70046','#FF850B','#FFEBC5','#109679','675A4C', +'#363636','#0599B0','#A4BD0A','#FFA615','FF2E00', +'#7D8077','#BBBFB2','#FAFFED','#E82A33','E3DEBC', +'#FD9F44','#FC5C65','#007269','#03A679','FAF0B9', +'#134B57','#81A489','#F1D8B5','#F2A054','C04D31', +'#946E49','#394042','#EDDBAC','#872A0C','BA8E3A', +'#404040','#024959','#037E8C','#FFFFFF','F24C27', +'#2A3342','#163C6E','#4E5F61','#E6A015','EDE7BE', +'#445060','#829AB5','#849E91','#C14543','D6D5D1', +'#8A9126','#B7BF5E','#FFE9C4','#F5B776','F58E45', +'#9B2D1E','#3C3A28','#78A080','#9BCD9E','FFFFAE', +'#FF6138','#FFFF9D','#BEEB9F','#79BD8F','00A388', +'#990000','#FF6600','#FF9900','#996633','CC9966', +'#DCE6DA','#B8CCBB','#98B3A5','#7A9994','62858C', +'#0B1C29','#3B7C8F','#73A5A3','#98C1B7','F0EBD2', +'#F6CB51','#E25942','#13A89E','#3F4953','F2E7DA', +'#282F36','#FFFEFC','#BDA21D','#BFBC5B','D2E098', +'#8C182D','#DE7140','#FCB95A','#FAE285','6A7349', +'#6B9100','#FFE433','#FF841F','#E03D19','A6001C', +'#FFEAA7','#D9D697','#9FC49F','#718C6A','543122', +'#CFF09E','#A8DBA8','#79BD9A','#3B8686','0B486B', +'#0C2233','#065471','#0A91AB','#FFC045','F2F2F2', +'#BEE8E0','#373C40','#2E2621','#73320B','FF5E00', +'#1B2C35','#A3BFC6','#FF005D','#222A30','293A42', +'#FF8400','#3B4044','#494948','#E6E1D8','F7F2E9', +'#6A482D','#518C86','#F6BF3D','#EF7C27','BF2424', +'#261C2B','#292B39','#226468','#608D80','829D8F', +'#B2AD9A','#110E00','#363226','#A9A695','ECE9D8', +'#1B1B26','#26394D','#286480','#13B3BF','A3FF57', +'#F2C2A7','#F5E5C5','#593D28','#422C21','93DEDB', +'#001028','#033140','#1E5A5B','#7BA78C','EBEDC6', +'#544E6E','#808CB0','#ABD1D9','#D9FFF7','DDF556', +'#323A45','#596677','#758194','#FFFFFF','E74C3C', +'#45291A','#AB926D','#DBD1BC','#4999C3','5FCBEC', +'#6B151D','#2E1615','#A8553A','#DB8F5A','F2C18E', +'#000623','#28475C','#4A6C74','#8BA693','F0E3B1', +'#60807B','#81B37A','#BCCC5F','#FFEE65','E64964', +'#FFFFFA','#A1A194','#5B605F','#464646','FF6600', +'#1E1B17','#577270','#9C9A79','#C7BDA1','580E0C', +'#452F27','#5E504A','#6B6865','#9BBAB2','B0FFED', +'#1B5257','#F7F6C3','#F28159','#CC5850','4F1C2E', +'#FAA51B','#BF511F','#2C445E','#2F6D82','5EE4EB', +'#BF3952','#59364A','#556D73','#D9D1A9','D95F5F', +'#024959','#037E8C','#F2EFDC','#E74C30','363636', +'#221A26','#544759','#A197A6','#F27405','D93D04', +'#C4A44A','#E6D399','#9AB8A9','#7C8A7F','4E4B44', +'#FFFEC8','#B1BF99','#5B604D','#39382B','26181E', +'#4E3C51','#21A68D','#3BBF9A','#F2E8B6','F25749', +'#102144','#1B325E','#254580','#3C63B0','5D8AEA', +'#2A3A48','#3E6372','#B2D4DC','#FAFAFF','FF4B00', +'#FFF1BF','#F20058','#FFAEAC','#000001','7D7A96', +'#FDFFC6','#F2F096','#FF0080','#DE0049','521218', +'#5B0E00','#FBB500','#FBD864','#807D1A','59233C', +'#1E1E1F','#424143','#67666A','#807F83','CBC9CF', +'#3C3658','#3EC8B7','#7CD0B4','#B9D8B1','F7E0AE', +'#FFFFFF','#99B75F','#D5DD98','#EBF4DB','D8D8D8', +'#248A8A','#C9FA58','#F9E555','#FAAC38','F2572A', +'#086B63','#77A490','#E2D8C1','#BFAE95','7C7159', +'#5C4B51','#8CBEB2','#F2EBBF','#A5C88F','EF847B', +'#17162F','#89346D','#C76058','#FFB248','E8C475', +'#6E8F4A','#65D9C5','#F2E7B6','#EDA430','AB3E2C', +'#30394F','#FF434C','#6ACEEB','#EDE8DF','0E6569', +'#8E1B13','#F9E4B3','#849689','#46464A','29232E', +'#686B30','#AB9A52','#E8BA67','#D68F4F','BA512E', +'#E54E45','#DBC390','#F2F2EF','#13A3A5','403833', +'#65BA99','#59A386','#F1DDBB','#D6C4A6','E74C3C', +'#A6FFBC','#4ACFAF','#00A995','#006161','003D4C', +'#33271E','#8B7653','#C8D9A0','#FDEE9D','233331', +'#048789','#503D2E','#D44D27','#E2A72E','EFEBC8', +'#E5FF1E','#A9D943','#75A660','#698070','494D4B', +'#2DEBA2','#91F57F','#EBAA69','#E70049','2B0027', +'#990000','#336699','#DDDDDD','#999999','333333', +'#F13A4B','#3D3C3E','#22BDAF','#F4F4F4','D7D7D7', +'#F53A59','#001D2D','#15A88C','#B7D9C8','F3F5F4',]; + +outArrayPalette.set(colors); + +}; + +Ops.Array.PaletteLibrary.prototype = new CABLES.Op(); +CABLES.OPS["a96020ac-0832-478e-bbb7-d6246d0eeedf"]={f:Ops.Array.PaletteLibrary,objName:"Ops.Array.PaletteLibrary"}; + + + + +// ************************************************************** +// +// Ops.Array.ParseArray_v2 +// +// ************************************************************** + +Ops.Array.ParseArray_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const text = op.inStringEditor("text", "1,2,3"), + separator = op.inString("separator", ","), + toNumber = op.inValueBool("Numbers", true), + trim = op.inValueBool("Trim", true), + splitNewLines = op.inBool("Split Lines", false), + parsed = op.outTrigger("Parsed"), + arr = op.outArray("array"), + len = op.outNumber("length"); + +text.setUiAttribs({ "ignoreBigPort": true }); + +text.onChange = separator.onChange = toNumber.onChange = trim.onChange = parse; + +splitNewLines.onChange = () => +{ + separator.setUiAttribs({ "greyout": splitNewLines.get() }); + parse(); +}; + +parse(); + +function parse() +{ + if (!text.get()) + { + arr.set(null); + arr.set([]); + len.set(0); + return; + } + + let textInput = text.get(); + if (trim.get() && textInput) + { + textInput = textInput.replace(/^\s+|\s+$/g, ""); + textInput = textInput.trim(); + } + + let r; + let sep = separator.get(); + if (separator.get() === "\\n") sep = "\n"; + if (splitNewLines.get()) r = textInput.split("\n"); + else r = textInput.split(sep); + + if (r[r.length - 1] === "") r.length -= 1; + + len.set(r.length); + + if (trim.get()) + { + for (let i = 0; i < r.length; i++) + { + r[i] = r[i].replace(/^\s+|\s+$/g, ""); + r[i] = r[i].trim(); + } + } + + op.setUiError("notnum", null); + if (toNumber.get()) + { + let hasStrings = false; + for (let i = 0; i < r.length; i++) + { + r[i] = Number(r[i]); + if (!CABLES.UTILS.isNumeric(r[i])) + { + hasStrings = true; + } + } + if (hasStrings) + { + op.setUiError("notnum", "Parse Error / Not all values numerical!"); + } + } + + arr.set(null); + arr.set(r); + parsed.trigger(); +} + + +}; + +Ops.Array.ParseArray_v2.prototype = new CABLES.Op(); +CABLES.OPS["c974de41-4ce4-4432-b94d-724741109c71"]={f:Ops.Array.ParseArray_v2,objName:"Ops.Array.ParseArray_v2"}; + + + + +// ************************************************************** +// +// Ops.Array.PerlinArray +// +// ************************************************************** + +Ops.Array.PerlinArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArrayX = op.inArray("Array in X"), + inTimeArray = op.inArray("Array time"), + inTime = op.inFloat("Time in Y", 0), + seed = op.inFloatSlider("Seed 0-1", 0.0), + inFrequency = op.inFloat("Frequency", 10), + outArray = op.outArray("Array out"), + outArrayLength = op.outNumber("Array length out"); + +let showingError = false; + +let newArr = []; +outArray.set(newArr); + +seed.set(Math.random()); + +inArrayX.onChange = inTimeArray.onChange = inTime.onChange = inFrequency.onChange = update; + +seed.onChange = function () +{ + Math.randomSeed = seed.get(); + noise.seed(Math.seededRandom()); + update(); +}; + +function update() +{ + let arr = inArrayX.get(); + let arrTime = inTimeArray.get(); + + let time = inTime.get(); + let mult = inFrequency.get(); + + if (arrTime) + { + if (!arr || !arrTime) + { + outArray.set(null); + return; + } + if (arr.length != arrTime.length) + { + if (!showingError) + { + op.uiAttr({ "error": "Arrays do not have the same length !" }); + outArrayLength.set(0); + showingError = true; + } + outArray.set(null); + return; + } + if (showingError) + { + showingError = false; + op.uiAttr({ "error": null }); + } + + if (newArr.length != arr.length)newArr.length = arr.length; + + for (var i = 0; i < arr.length; i++) + { + newArr[i] = noise.perlin2(arr[i] * mult, arrTime[i] + time); + } + } + else if (!arrTime) + { + if (!arr) + { + outArray.set(null); + return; + } + + if (newArr.length != arr.length)newArr.length = arr.length; + + for (var i = 0; i < arr.length; i++) + { + newArr[i] = noise.perlin2(arr[i] * mult, time); + } + } + + outArray.set(null); + outArray.set(newArr); + outArrayLength.set(newArr.length); +} + + +}; + +Ops.Array.PerlinArray.prototype = new CABLES.Op(); +CABLES.OPS["ed55556e-f319-47cc-bce6-ea015b45650b"]={f:Ops.Array.PerlinArray,objName:"Ops.Array.PerlinArray"}; + + + + +// ************************************************************** +// +// Ops.Array.Phyllotaxis +// +// ************************************************************** + +Ops.Array.Phyllotaxis = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exec=op.inTrigger("Render"); +const inNum=op.inValueInt("Num",400); +const inC=op.inValue("Scale",0.1); +const inI=op.inValue("Param",100); + +const outArr=op.outArray("Coordinates"); + +const arr=[]; + +inNum.onChange=update; +inC.onChange=update; +inI.onChange=update; + +function update() +{ + arr.length=Math.floor(inNum.get()*3); + + var n=inNum.get(); + var c=inC.get(); + + var ii=inI.get(); + + for (var i = 0; i < n; i++) + { + var a = i * ii; + var r = c * Math.sqrt(i); + var x = r * Math.cos(a); + var y = r * Math.sin(a); + var hu = i/3.0 % 360; + + arr[i*3+0]=x; + arr[i*3+1]=y; + arr[i*3+2]=0; + } + outArr.set(null); + outArr.set(arr); +} + +update(); + +}; + +Ops.Array.Phyllotaxis.prototype = new CABLES.Op(); +CABLES.OPS["312b5220-c0f9-4003-9072-e400f216251a"]={f:Ops.Array.Phyllotaxis,objName:"Ops.Array.Phyllotaxis"}; + + + + +// ************************************************************** +// +// Ops.Array.PointArray.CircularPoints +// +// ************************************************************** + +Ops.Array.PointArray.CircularPoints = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + radius = op.inValue("Radius", 1), + segments = op.inValue("Round Segments", 40), + percent = op.inFloat("Rounds", 1), + inRoundOffset = op.inFloat("Radius Add Round", 0.1), + inPointRadOffset = op.inFloat("Radius Add Point", 0.1), + inOffset = op.inFloat("Offset", 0), + inPointOffset = op.inFloat("Point Offset XY", 0.1), + inPointOffsetZ = op.inFloat("Point Offset Z", 0.1), + inOffsetRot = op.inFloat("Offset Rotation"), + outArr = op.outArray("Points", 3), + outRotArr = op.outArray("Rotation", 3), + outTotalPoints = op.outNumber("Total points"), + outArrayLength = op.outNumber("Array lengths"); + +inOffset.onChange = + inOffsetRot.onChange = + inPointRadOffset.onChange = + inPointOffset.onChange = + radius.onChange = + inPointOffsetZ.onChange = + inRoundOffset.onChange = + percent.onChange = + segments.onChange = calcArray; + +function calcArray() +{ + const segs = Math.max(3, Math.floor(segments.get())); + const points = []; + const rots = []; + + const roundOffset = inRoundOffset.get(); + + let count = 0; + const offsetRot = inOffsetRot.get(); + const r = radius.get(); + const pointOff = inPointRadOffset.get() / 100; + const roundOff = inRoundOffset.get(); + const offZ = inPointOffsetZ.get(); + let progressOffset = 0.0; + + for (let i = 0; i < segs * percent.get(); i++) + { + progressOffset = i * inPointOffset.get() + inOffset.get(); + const radiusOff = Math.floor(i / segs) * roundOff; + + let degInRad = (360 / segs) * (i + progressOffset) * CGL.DEG2RAD; + let posx = Math.cos(degInRad) * (r + radiusOff + pointOff * i); + let posy = Math.sin(degInRad) * (r + radiusOff + pointOff * i); + + rots.push(0, 0, degInRad * CGL.RAD2DEG - offsetRot); + + points.push(posx, posy, i * offZ); + } + + outArr.set(null); + outArr.set(points); + + outRotArr.set(null); + outRotArr.set(rots); + + outTotalPoints.set(points.length / 3); + outArrayLength.set(points.length); +} + +calcArray(); + + +}; + +Ops.Array.PointArray.CircularPoints.prototype = new CABLES.Op(); +CABLES.OPS["5d2de367-c2b8-4702-abf0-b16bbeb22f37"]={f:Ops.Array.PointArray.CircularPoints,objName:"Ops.Array.PointArray.CircularPoints"}; + + + + +// ************************************************************** +// +// Ops.Array.PointArray.FillPointArrayDuplicates +// +// ************************************************************** + +Ops.Array.PointArray.FillPointArrayDuplicates = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array"), + inNumPoints = op.inValueInt("Num Elements", 1000), + inCalc = op.inTriggerButton("Calculate"), + outArr = op.outArray("Result"); +op.toWorkPortsNeedToBeLinked(inArr); + +let arr = []; + +inCalc.onTriggered = function () +{ + let num = inNumPoints.get(); + + arr.length = num * 3; + + let oldArr = inArr.get(); + if (!oldArr) + { + outArr.set(null); + return; + } + let numOld = oldArr.length; + + let i = 0; + for (i = 0; i < numOld; i++) + { + arr[i] = oldArr[i]; + } + + Math.randomSeed = 5711; + + while (i < (num - 1) * 3) + { + let ind = Math.floor(Math.seededRandom() * (numOld / 3)) * 3; + + arr[i + 0] = oldArr[ind + 0]; + arr[i + 1] = oldArr[ind + 1]; + arr[i + 2] = oldArr[ind + 2]; + i += 3; + } + + outArr.set(null); + outArr.set(arr); +}; + + +}; + +Ops.Array.PointArray.FillPointArrayDuplicates.prototype = new CABLES.Op(); +CABLES.OPS["dae7416d-b130-487e-bdd3-ca5a18278d47"]={f:Ops.Array.PointArray.FillPointArrayDuplicates,objName:"Ops.Array.PointArray.FillPointArrayDuplicates"}; + + + + +// ************************************************************** +// +// Ops.Array.PointArray.RedistributeSplinePoints +// +// ************************************************************** + +Ops.Array.PointArray.RedistributeSplinePoints = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array3x"), + num = op.inValueInt("Num Points", 100), + inExec = op.inTriggerButton("Calculate"), + inNormalized = op.inValueBool("Normalized"), + result = op.outArray("Result"), + outSplineLength = op.outNumber("Spline Length"); + +const + animX = new CABLES.Anim(), + animY = new CABLES.Anim(), + animZ = new CABLES.Anim(); + +let needsMapping = true; +let newArray = []; +let totalSplineLength = 0; + +function dist(x1, y1, z1, x2, y2, z2) +{ + let xd = x1 - x2; + let yd = y1 - y2; + let zd = z1 - z2; + return Math.sqrt(xd * xd + yd * yd + zd * zd); +} + +function splineLength(arr) +{ + let l = 0; + for (let i = 3; i < arr.length; i += 3) + { + l += dist(arr[i - 3], arr[i - 2], arr[i - 1], arr[i + 0], arr[i + 1], arr[i + 2]); + } + + return l; +} + +function mapArrays() +{ + animX.clear(); + animY.clear(); + animZ.clear(); + let arr = inArr.get(); + if (!arr) + { + result.set([]); + return; + } + totalSplineLength = splineLength(arr); + outSplineLength.set(totalSplineLength); + + let distPos = 0; + + for (let i = 0; i < arr.length; i += 3) + { + let p = i / (arr.length - 3); + if (i > 0) + { + distPos += dist(arr[i - 3], arr[i - 2], arr[i - 1], arr[i + 0], arr[i + 1], arr[i + 2]); + } + + animX.setValue(distPos, arr[i + 0]); + animY.setValue(distPos, arr[i + 1]); + animZ.setValue(distPos, arr[i + 2]); + } + + needsMapping = false; +} + +function buildResultArray() +{ + let n = Math.max(0, num.get()); + if (n === 0) + { + result.set([]); + return; + } + + newArray.length = n * 3; + + for (let i = 0; i < n; i++) + { + newArray[i * 3 + 0] = animX.getValue(i / n * totalSplineLength); + newArray[i * 3 + 1] = animY.getValue(i / n * totalSplineLength); + newArray[i * 3 + 2] = animZ.getValue(i / n * totalSplineLength); + } + + result.set(null); + result.set(newArray); +} + +inArr.onChange = function () +{ + needsMapping = true; +}; + +inExec.onTriggered = function () +{ + if (needsMapping)mapArrays(); + buildResultArray(); +}; + + +}; + +Ops.Array.PointArray.RedistributeSplinePoints.prototype = new CABLES.Op(); +CABLES.OPS["f17bae71-6047-49ea-af17-f7690e6e4d36"]={f:Ops.Array.PointArray.RedistributeSplinePoints,objName:"Ops.Array.PointArray.RedistributeSplinePoints"}; + + + + +// ************************************************************** +// +// Ops.Array.RandomArrays +// +// ************************************************************** + +Ops.Array.RandomArrays = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const numValues = op.inValueInt("Num Values", 100); +const inModeSwitch = op.inSwitch("Mode", ["A", "AB", "ABC", "ABCD"], "A"); +const inSeed = op.inValueFloat("Random Seed ", 0); +const inInteger = op.inBool("Integer", false); +const outValues = op.outArray("Array Out"); + +const letters = ["A", "B", "C", "D"]; + +const inArray = letters.map(function (value) +{ + return { + "min": op.inValueFloat("Min " + value, -1), + "max": op.inValueFloat("Max " + value, 1), + }; +}); + +for (let i = 0; i < inArray.length; i += 1) +{ + const portObj = inArray[i]; + const keys = Object.keys(portObj); + + op.setPortGroup("Value Range " + letters[i], keys.map(function (key) { return portObj[key]; })); + + if (i > 0) keys.forEach(function (key) { portObj[key].setUiAttribs({ "greyout": true }); }); +} + + +inModeSwitch.onChange = function () +{ + const mode = inModeSwitch.get(); + const modes = inModeSwitch.uiAttribs.values; + + outValues.setUiAttribs({ "stride": inModeSwitch.get().length }); + + const index = modes.indexOf(mode); + + inArray.forEach(function (portObj, i) + { + const keys = Object.keys(portObj); + keys.forEach(function (key, j) + { + if (i <= index) portObj[key].setUiAttribs({ "greyout": false }); + else portObj[key].setUiAttribs({ "greyout": true }); + }); + }); + init(); +}; + +const outTotalPoints = op.outNumber("Chunks Amount"); +const outArrayLength = op.outNumber("Array length"); + +outValues.ignoreValueSerialize = true; + +numValues.onChange = inSeed.onChange = inInteger.onChange = init; + +const minMaxArray = []; + +init(); + +function init() +{ + const arr = []; + const mode = inModeSwitch.get(); + const modes = inModeSwitch.uiAttribs.values; + const index = modes.indexOf(mode); + + Math.randomSeed = inSeed.get(); + + const dimension = index + 1; + const length = Math.floor(Math.abs(numValues.get() * dimension)); + + arr.length = length; + const tupleLength = length / dimension; + const isInteger = inInteger.get(); + + // optimization: we only need to fetch the max min for each component once + for (let i = 0; i < dimension; i += 1) + { + const portObj = inArray[i]; + const max = portObj.max.get(); + const min = portObj.min.get(); + minMaxArray[i] = [min, max]; + } + + for (let j = 0; j < tupleLength; j += 1) + { + for (let k = 0; k < dimension; k += 1) + { + const min = minMaxArray[k][0]; + const max = minMaxArray[k][1]; + const index = j * dimension + k; + + if (isInteger) arr[index] = Math.floor(Math.seededRandom() * ((max + 1) - min) + min); + else arr[index] = Math.seededRandom() * (max - min) + min; + } + } + + outValues.set(null); + + outValues.set(arr); + outTotalPoints.set(arr.length / dimension); + outArrayLength.set(arr.length); +} + +// assign change handler +inArray.forEach(function (obj) +{ + Object.keys(obj).forEach(function (key) + { + const x = obj[key]; + x.onChange = init; + }); +}); + + +}; + +Ops.Array.RandomArrays.prototype = new CABLES.Op(); +CABLES.OPS["8a9fa2c6-c229-49a9-9dc8-247001539217"]={f:Ops.Array.RandomArrays,objName:"Ops.Array.RandomArrays"}; + + + + +// ************************************************************** +// +// Ops.Array.RandomNumbersArray3_v2 +// +// ************************************************************** + +Ops.Array.RandomNumbersArray3_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + numValues = op.inValueInt("numValues", 100), + min = op.inValueFloat("Min", -1), + max = op.inValueFloat("Max", 1), + seed = op.inValueFloat("random seed"), + closed = op.inValueBool("Last == First"), + inInteger = op.inValueBool("Integer", false), + values = op.outArray("values", null, 3), + outTotalPoints = op.outNumber("Total points"), + outArrayLength = op.outNumber("Array length"); + +op.setPortGroup("Value Range", [min, max]); +op.setPortGroup("", [seed, closed]); + +values.ignoreValueSerialize = true; + +closed.onChange = + max.onChange = + min.onChange = + numValues.onChange = + seed.onChange = + inInteger.onChange = init; + +const arr = []; +init(); + +function init() +{ + Math.randomSeed = seed.get(); + + const isInteger = inInteger.get(); + + const arrLength = arr.length = Math.max(0, Math.floor(Math.abs((numValues.get() || 0) * 3))); + + if (arrLength === 0) + { + values.set(null); + outTotalPoints.set(0); + outArrayLength.set(0); + return; + } + + const minIn = min.get(); + const maxIn = max.get(); + + for (let i = 0; i < arrLength; i += 3) + { + if (!isInteger) + { + arr[i + 0] = Math.seededRandom() * (maxIn - minIn) + minIn; + arr[i + 1] = Math.seededRandom() * (maxIn - minIn) + minIn; + arr[i + 2] = Math.seededRandom() * (maxIn - minIn) + minIn; + } + else + { + arr[i + 0] = Math.floor(Math.seededRandom() * ((maxIn - minIn) + 1) + minIn); + arr[i + 1] = Math.floor(Math.seededRandom() * ((maxIn - minIn) + 1) + minIn); + arr[i + 2] = Math.floor(Math.seededRandom() * ((maxIn - minIn) + 1) + minIn); + } + } + + if (closed.get() && arrLength > 3) + { + arr[arrLength - 3 + 0] = arr[0]; + arr[arrLength - 3 + 1] = arr[1]; + arr[arrLength - 3 + 2] = arr[2]; + } + + values.set(null); + values.set(arr); + outTotalPoints.set(arrLength / 3); + outArrayLength.set(arrLength); +} + + +}; + +Ops.Array.RandomNumbersArray3_v2.prototype = new CABLES.Op(); +CABLES.OPS["45b2113a-1ca0-41d8-8d90-db3e394b669c"]={f:Ops.Array.RandomNumbersArray3_v2,objName:"Ops.Array.RandomNumbersArray3_v2"}; + + + + +// ************************************************************** +// +// Ops.Array.RandomNumbersArray4_v2 +// +// ************************************************************** + +Ops.Array.RandomNumbersArray4_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + numValues = op.inValueInt("numValues", 100), + min = op.inValueFloat("Min", 0), + max = op.inValueFloat("Max", 1), + seed = op.inValueFloat("random seed"), + closed = op.inValueBool("Last == First"), + inInteger = op.inValueBool("Integer", false), + values = op.outArray("values", null, 4), + outTotalPoints = op.outNumber("Tuple Amount"), + outArrayLength = op.outNumber("Array length"); + +op.setPortGroup("Value Range", [min, max]); +op.setPortGroup("", [seed, closed]); + +values.ignoreValueSerialize = true; + +closed.onChange = max.onChange = + min.onChange = + numValues.onChange = + seed.onChange = + values.onLinkChanged = + inInteger.onChange = init; + +let arr = []; +init(); + +function init() +{ + Math.randomSeed = seed.get(); + + let isInteger = inInteger.get(); + + let arrLength = arr.length = Math.floor(Math.abs(numValues.get() * 4)); + if (arrLength === 0) + { + values.set(null); + outTotalPoints.set(0); + outArrayLength.set(0); + return; + } + + let minIn = min.get(); + let maxIn = max.get(); + + for (let i = 0; i < arrLength; i += 4) + { + if (!isInteger) + { + arr[i + 0] = Math.seededRandom() * (maxIn - minIn) + minIn; + arr[i + 1] = Math.seededRandom() * (maxIn - minIn) + minIn; + arr[i + 2] = Math.seededRandom() * (maxIn - minIn) + minIn; + arr[i + 3] = Math.seededRandom() * (maxIn - minIn) + minIn; + } + else + { + arr[i + 0] = Math.floor(Math.seededRandom() * ((maxIn - minIn) + 1) + minIn); + arr[i + 1] = Math.floor(Math.seededRandom() * ((maxIn - minIn) + 1) + minIn); + arr[i + 2] = Math.floor(Math.seededRandom() * ((maxIn - minIn) + 1) + minIn); + arr[i + 3] = Math.floor(Math.seededRandom() * ((maxIn - minIn) + 1) + minIn); + } + } + + if (closed.get() && arrLength > 4) + { + arr[arrLength - 4 + 0] = arr[0]; + arr[arrLength - 4 + 1] = arr[1]; + arr[arrLength - 4 + 2] = arr[2]; + arr[arrLength - 4 + 3] = arr[2]; + } + + values.set(null); + values.set(arr); + outTotalPoints.set(arrLength / 4); + outArrayLength.set(arrLength); +} + + +}; + +Ops.Array.RandomNumbersArray4_v2.prototype = new CABLES.Op(); +CABLES.OPS["23c28491-06d3-4ea8-9e0d-c615b0783817"]={f:Ops.Array.RandomNumbersArray4_v2,objName:"Ops.Array.RandomNumbersArray4_v2"}; + + + + +// ************************************************************** +// +// Ops.Array.RandomNumbersArray_v3 +// +// ************************************************************** + +Ops.Array.RandomNumbersArray_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + numValues = op.inValueInt("numValues", 10), + min = op.inValueFloat("Min", 0), + max = op.inValueFloat("Max", 1), + seed = op.inValueFloat("random seed"), + values = op.outArray("values", 100), + outArrayLength = op.outNumber("Array length"), + inInteger = op.inValueBool("Integer", false); + +values.ignoreValueSerialize = true; +op.setPortGroup("Value Range", [min, max]); +op.setPortGroup("", [seed]); + +max.onChange = + min.onChange = + numValues.onChange = + seed.onChange = + values.onLinkChanged = + inInteger.onChange = init; + +let arr = []; +init(); + +function init() +{ + Math.randomSeed = seed.get(); + let isInteger = inInteger.get(); + + let arrLength = arr.length = Math.max(0, Math.abs(parseInt(numValues.get() || 0))); + + let minIn = min.get(); + let maxIn = max.get(); + + if (arrLength === 0) + { + values.set(null); + outArrayLength.set(0); + return; + } + if (!isInteger) + { + for (var i = 0; i < arrLength; i++) + { + arr[i] = Math.seededRandom() * (maxIn - minIn) + minIn; + } + } + else + { + for (var i = 0; i < arrLength; i++) + { + arr[i] = Math.floor(Math.seededRandom() * ((maxIn - minIn) + 1) + minIn); + } + } + + values.set(null); + values.set(arr); + outArrayLength.set(arrLength); +} + + +}; + +Ops.Array.RandomNumbersArray_v3.prototype = new CABLES.Op(); +CABLES.OPS["e8609213-0803-4338-ab20-f95d0d65a110"]={f:Ops.Array.RandomNumbersArray_v3,objName:"Ops.Array.RandomNumbersArray_v3"}; + + + + +// ************************************************************** +// +// Ops.Array.RandomWordsArray +// +// ************************************************************** + +Ops.Array.RandomWordsArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let arr = ["apple", "baby", "back", "ball", "bear", "bed", "bell", "bird", + "birthday", "boat", "box", "boy", "bread", "brother", "cake", "car", + "cables", "cat", "chair", "chicken", "children", "Christmas", "coat", "corn", + "cow", "day", "dog", "doll", "door", "duck", "egg", "eye", "farm", "farmer", + "father", "feet", "fire", "fish", "floor", "flower", "game", "garden", "girl", + "good-bye", "grass", "ground", "hand", "head", "hill", "home", "horse", "house", + "kitty", "leg", "letter", "man", "men", "milk", "money", "morning", "mother", + "name", "nest", "night", "paper", "party", "picture", "pig", "rabbit", "rain", + "ring", "robin", "Santa Claus", "school", "seed", "sheep", "shoe", "sister", + "snow", "song", "squirrel", "stick", "street", "sun", "table", "thing", "time", + "top", "toy", "tree", "watch", "water", "way", "wind", "window", "wood"]; + +arr = CABLES.shuffleArray(arr); + +let values = op.outArray("Words", arr); + + +}; + +Ops.Array.RandomWordsArray.prototype = new CABLES.Op(); +CABLES.OPS["98057c3a-f6ec-48a6-8e8a-4b8316a0dcf1"]={f:Ops.Array.RandomWordsArray,objName:"Ops.Array.RandomWordsArray"}; + + + + +// ************************************************************** +// +// Ops.Array.ReduceArray3_v3 +// +// ************************************************************** + +Ops.Array.ReduceArray3_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + arr = op.inArray("Array"), + inMeth = op.inSwitch("Remove", ["Xth Item", "Random", "Duplicates"], "Xth Item"), + num = op.inValueInt("Every xth Item", 2), + inThresh = op.inFloatSlider("Threshold", 0.5), + inSeed = op.inFloat("Seed", 1), + outArr = op.outArray("Result Array"); + +num.onChange = + inThresh.onChange = + inSeed.onChange = + arr.onChange = update; + +const newArray = []; + +let updateMethod = updateXth; + +inMeth.onChange = () => +{ + if (inMeth.get() == "Xth Item")updateMethod = updateXth; + if (inMeth.get() == "Random")updateMethod = updateRandom; + if (inMeth.get() == "Duplicates")updateMethod = updateDupes; + + update(); +}; + +function update() +{ + const theArray = arr.get(); + if (!theArray) return; + + let newArray = updateMethod(theArray); + + outArr.set(null); + outArr.set(newArray); +} + +function updateDupes(theArray) +{ + const noDupesArr = []; + + for (let i = 0; i < theArray.length; i += 3) + { + let found = false; + for (let j = 0; j < noDupesArr.length; j += 3) + { + if ( + theArray[i] == noDupesArr[j] && + theArray[i + 1] == noDupesArr[j + 1] && + theArray[i + 2] == noDupesArr[j + 2] + ) + { + found = true; + break; + } + } + + if (!found) + { + noDupesArr.push(theArray[i], theArray[i + 1], theArray[i + 2]); + } + } + return noDupesArr; +} + +function updateRandom(theArray) +{ + Math.randomSeed = inSeed.get(); + + const newArray = []; + + const thresh = inThresh.get(); + + for (let i = 0; i < theArray.length; i += 3) + { + if (Math.seededRandom() > thresh) + newArray.push(theArray[i + 0], theArray[i + 1], theArray[i + 2]); + } + + return newArray; +} + +function updateXth(theArray) +{ + const step = Math.max(0, Math.floor(num.get())); + const newArray = []; + + if (step === 0) + { + outArr.set(null); + outArr.set([]); + return; + } + + for (let i = 0; i < theArray.length; i += step * 3) + newArray.push(theArray[i + 0], theArray[i + 1], theArray[i + 2]); + + return newArray; +} + + +}; + +Ops.Array.ReduceArray3_v3.prototype = new CABLES.Op(); +CABLES.OPS["5ba30060-2e42-4441-8b15-49279dc3bb67"]={f:Ops.Array.ReduceArray3_v3,objName:"Ops.Array.ReduceArray3_v3"}; + + + + +// ************************************************************** +// +// Ops.Array.ReverseArray3 +// +// ************************************************************** + +Ops.Array.ReverseArray3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// inputs +let inArrPort = op.inArray("Array"); + +// outputs +let outArrayPort = op.outArray("Reversed Array", []); + +// change listeners +inArrPort.onChange = function () +{ + let inArr = inArrPort.get(); + let reversedArr = []; + if (inArr && inArr.length >= 3) + { + // in case the array is not dividable by 3, get rid of the rest + // e.g. length = 31 -> ignore the last value + // length = 30 -> perfect fit for [x, y, z, ...] + let iStart = (Math.floor(inArr.length / 3) * 3) - 3; + for (let i = iStart; i >= 0; i -= 3) + { + reversedArr.push(inArr[i], inArr[i + 1], inArr[i + 2]); + } + } + + outArrayPort.set(null); + outArrayPort.set(reversedArr); +}; + + +}; + +Ops.Array.ReverseArray3.prototype = new CABLES.Op(); +CABLES.OPS["5b0feea0-06ee-4e9d-befb-41793ab4fa2c"]={f:Ops.Array.ReverseArray3,objName:"Ops.Array.ReverseArray3"}; + + + + +// ************************************************************** +// +// Ops.Array.RingBuffer +// +// ************************************************************** + +Ops.Array.RingBuffer = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let DEFAULT_LENGTH = 10; + +const + inVal = op.inValue("Value"), + inWrite = op.inTriggerButton("Write"), + inNum = op.inValueInt("Length", DEFAULT_LENGTH), + inReset = op.inTriggerButton("Reset Index"), + outArr = op.outArray("Result"), + outIndex = op.outNumber("Index"); + +let index = 0; +let arr = []; +inNum.onChange = updateLength; +updateLength(); + +function updateLength() +{ + arr.length = Math.floor(inNum.get()); + for (let i = 0; i < arr.length; i++) arr[i] = 0; + outArr.set(null); + outArr.set(arr); +} + +inWrite.onTriggered = function () +{ + index = Math.floor(index % inNum.get()); + arr[index] = inVal.get(); + outIndex.set(index); + outArr.set(null); + outArr.set(arr); + index++; +}; + +inReset.onTriggered = function () +{ + index = 0; +}; + + +}; + +Ops.Array.RingBuffer.prototype = new CABLES.Op(); +CABLES.OPS["38b77ea5-b44b-48b3-9433-09a83753a209"]={f:Ops.Array.RingBuffer,objName:"Ops.Array.RingBuffer"}; + + + + +// ************************************************************** +// +// Ops.Array.RotateArray +// +// ************************************************************** + +Ops.Array.RotateArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArray = op.inArray("Array in"); +const count = op.inValueInt("Rotate amount", 0); +const outArray = op.outArray("ArrayOut"); + +let newArr = []; +outArray.set(newArr); + +count.onChange = +inArray.onChange = function () +{ + let arr = inArray.get(); + if (!arr) return; + + let rotateIndex = -count.get(); + + newArr = rotate(inArray.get(), rotateIndex, 0); + outArray.set(null); + outArray.set(newArr); +}; + +// https://gist.github.com/aubergene/7ecfe624199e68f60258 +function rotate(array, n, guard) +{ + let head, tail; + n = (n === null) || guard ? 1 : n; + n %= array.length; + tail = array.slice(n); + + head = array.slice(0, n); + return tail.concat(head); +} + + +}; + +Ops.Array.RotateArray.prototype = new CABLES.Op(); +CABLES.OPS["e435d07b-8545-4469-befb-868510adcb76"]={f:Ops.Array.RotateArray,objName:"Ops.Array.RotateArray"}; + + + + +// ************************************************************** +// +// Ops.Array.RouteArray +// +// ************************************************************** + +Ops.Array.RouteArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; + +const + NUM_PORTS = 10, + DEFAULT_ARRAY_DEFAULT = [], + indexPort = op.inInt('index'), + arrayPort = op.inArray('array in'), + defaultArrayPort = op.inArray('default array', DEFAULT_ARRAY_DEFAULT), + arrayPorts = createOutPorts(DEFAULT_ARRAY_DEFAULT); + +indexPort.onChange = arrayPort.onChange = defaultArrayPort.onChange = update; + +setDefaultValues(); +update(); + +function createOutPorts() +{ + var arr = []; + for(var i=0; i port.set(null)); + if(defaultArrayPort.get()) + { + arrayPorts.forEach(port => port.set(defaultValue)); + } +}; + +function update() +{ + setDefaultValues(); + var index = indexPort.get(); + var value = arrayPort.get(); + + index = Math.floor(index); + index = clamp(index, 0, NUM_PORTS-1); + arrayPorts[index].set(value); +}; + +function clamp(value, min, max) +{ + return Math.min(Math.max(value, min), max); +}; + + +}; + +Ops.Array.RouteArray.prototype = new CABLES.Op(); +CABLES.OPS["6597c011-7b2a-4d7c-93f5-40fcc2047cfe"]={f:Ops.Array.RouteArray,objName:"Ops.Array.RouteArray"}; + + + + +// ************************************************************** +// +// Ops.Array.SetNumberArray +// +// ************************************************************** + +Ops.Array.SetNumberArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe = op.inTriggerButton("exe"), + array = op.inArray("array"), + index = op.inValueInt("index"), + value = op.inValueFloat("value"), + values = op.outArray("values"); + +exe.onTriggered = update; + +let newArr = []; + +function update() +{ + let arr = array.get(); + + if (!Array.isArray(arr)) + { + values.set(null); + return; + } + + newArr.length = arr.length; + for (let i = 0; i < arr.length; i++)newArr[i] = arr[i]; + + newArr[Math.floor(index.get())] = value.get(); + + values.set(null); + values.set(newArr); +} + + +}; + +Ops.Array.SetNumberArray.prototype = new CABLES.Op(); +CABLES.OPS["ed39fd33-1b8d-4d04-a44d-4a22e4477a0a"]={f:Ops.Array.SetNumberArray,objName:"Ops.Array.SetNumberArray"}; + + + + +// ************************************************************** +// +// Ops.Array.SetNumbersArray3 +// +// ************************************************************** + +Ops.Array.SetNumbersArray3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe = op.inTriggerButton("exe"), + array = op.inArray("array"), + index = op.inValueInt("index"), + value1 = op.inValueFloat("Value 1"), + value2 = op.inValueFloat("Value 2"), + value3 = op.inValueFloat("Value 3"), + values = op.outArray("values"); + +let newArr = []; + +function update() +{ + let arr = array.get(); + if (!arr) return; + + newArr.length = arr.length; + for (let i = 0; i < arr.length; i++) newArr[i] = arr[i]; + + const idx = 3 * Math.abs(Math.floor(index.get())); + newArr[idx + 0] = value1.get(); + newArr[idx + 1] = value2.get(); + newArr[idx + 2] = value3.get(); + + values.set(null); + values.set(newArr); +} + +exe.onTriggered = update; + + +}; + +Ops.Array.SetNumbersArray3.prototype = new CABLES.Op(); +CABLES.OPS["c3b2d0c9-0aa5-4605-948a-a53784fa8f1a"]={f:Ops.Array.SetNumbersArray3,objName:"Ops.Array.SetNumbersArray3"}; + + + + +// ************************************************************** +// +// Ops.Array.ShuffleArray3_v2 +// +// ************************************************************** + +Ops.Array.ShuffleArray3_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array3"), + inSeed = op.inFloat("Seed", 1), + outArr = op.outArray("Result"); + +const newArr = []; +const rndArr = []; +inArr.onChange = update; +inSeed.onChange = update; + +function fisherYatesShuffle(array) +{ + let i = 0; + let j = 0; + let temp = null; + + for (i = array.length - 1; i >= 0; i -= 1) + { + j = Math.floor(Math.seededRandom() * (i + 1)); + temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } +} + +function update() +{ + const arr = inArr.get(); + + if (!arr || arr.length % 3 !== 0) return; + if (arr.length != newArr.length) newArr.length = arr.length; + + let i = 0; + let j = 0; + const temp = null; + Math.randomSeed = inSeed.get() + 1; + + for (i = 0; i < arr.length; i += 3) rndArr[i / 3] = i; + + for (let i = 0; i < 4; i++) fisherYatesShuffle(rndArr); + + for (i = 0; i < arr.length; i += 3) + { + j = rndArr[i / 3]; + + newArr[i + 0] = arr[j + 0]; + newArr[i + 1] = arr[j + 1]; + newArr[i + 2] = arr[j + 2]; + } + + outArr.set(null); + outArr.set(newArr); +} + + +}; + +Ops.Array.ShuffleArray3_v2.prototype = new CABLES.Op(); +CABLES.OPS["147f0224-3241-423d-927c-14306134befa"]={f:Ops.Array.ShuffleArray3_v2,objName:"Ops.Array.ShuffleArray3_v2"}; + + + + +// ************************************************************** +// +// Ops.Array.ShuffleArray_v2 +// +// ************************************************************** + +Ops.Array.ShuffleArray_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array3"), + inSeed = op.inFloat("Seed", 1), + outArr = op.outArray("Result"); + +let newArr = []; +let rndArr = []; +inArr.onChange = update; +inSeed.onChange = update; + +function fisherYatesShuffle(array) +{ + let i = 0; + let j = 0; + let temp = null; + + for (i = array.length - 1; i > 0; i -= 1) + { + j = Math.floor(Math.seededRandom() * (i + 1)); + temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } +} + +function update() +{ + const arr = inArr.get(); + + if (!arr) + { + outArr.set(null); + return; + } + if (arr.length != newArr.length) + { + rndArr.length = + newArr.length = arr.length; + } + + let j = 0; + let temp = null; + Math.randomSeed = inSeed.get(); + + for (let i = 0; i < arr.length; i++) + { + rndArr[i] = i; + } + + fisherYatesShuffle(rndArr); + + for (let i = 0; i < arr.length; i++) + { + j = rndArr[i]; + newArr[i] = arr[j]; + } + + outArr.set(null); + outArr.set(newArr); +} + + +}; + +Ops.Array.ShuffleArray_v2.prototype = new CABLES.Op(); +CABLES.OPS["ea752da3-79f4-4674-95bf-722634365f53"]={f:Ops.Array.ShuffleArray_v2,objName:"Ops.Array.ShuffleArray_v2"}; + + + + +// ************************************************************** +// +// Ops.Array.SimplexArray +// +// ************************************************************** + +Ops.Array.SimplexArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArrayX = op.inArray("Array in X "), + inTimeArray = op.inArray("Array time"), + inTime = op.inFloat("Time in Y", 0), + seed = op.inFloatSlider("Seed 0-1", 0.5), + inFrequency = op.inFloat("Frequency", 10), + outArray = op.outArray("Array out"), + outArrayLength = op.outNumber("Array length out"); + +let showingError = false; + +let newArr = []; +outArray.set(newArr); + +seed.set(Math.random()); + +inArrayX.onChange = inTime.onChange = inFrequency.onChange = update; + +seed.onChange = function () +{ + Math.randomSeed = seed.get(); + noise.seed(Math.seededRandom()); + update(); +}; +function update() +{ + let arr = inArrayX.get(); + let arrTime = inTimeArray.get(); + + let time = inTime.get(); + let mult = inFrequency.get(); + + if (arrTime) + { + if (!arr || !arrTime) + { + outArray.set(null); + return; + } + if (arr.length != arrTime.length) + { + if (!showingError) + { + op.uiAttr({ "error": "Arrays do not have the same length !" }); + outArrayLength.set(0); + showingError = true; + } + outArray.set(null); + return; + } + if (showingError) + { + showingError = false; + op.uiAttr({ "error": null }); + } + + if (newArr.length != arr.length)newArr.length = arr.length; + + for (var i = 0; i < arr.length; i++) + { + newArr[i] = noise.simplex2(arr[i] * mult, arrTime[i] + time); + } + } + else if (!arrTime) + { + if (!arr) + { + outArray.set(null); + return; + } + + if (newArr.length != arr.length)newArr.length = arr.length; + + for (var i = 0; i < arr.length; i++) + { + newArr[i] = noise.simplex2(arr[i] * mult, time); + } + } + + outArray.set(null); + outArray.set(newArr); + outArrayLength.set(newArr.length); +} + + +}; + +Ops.Array.SimplexArray.prototype = new CABLES.Op(); +CABLES.OPS["094af2fe-c511-4c89-b384-4cc7c4c7b626"]={f:Ops.Array.SimplexArray,objName:"Ops.Array.SimplexArray"}; + + + + +// ************************************************************** +// +// Ops.Array.SmoothArray +// +// ************************************************************** + +Ops.Array.SmoothArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// look at http://sol.gfxile.net/interpolation/ +const exec = op.inTrigger("Execute"), + inArray = op.inArray("Array In"), + inModeBool = op.inBool("Separate inc/dec", false), + incFactor = op.inValue("Inc factor", 4), + decFactor = op.inValue("Dec factor", 4), + next = op.outTrigger("Next"), + outArray = op.outArray("Array Out"); + +let goal = []; +let reset = false; +let lastTrigger = 0; + +let newArr = []; +outArray.set(newArr); + +let divisorUp; +let divisorDown; + +let selectedMode = false; + +onFilterChange(); +getDivisors(); +function onFilterChange() +{ + selectedMode = inModeBool.get(); + + if (!selectedMode) + { + decFactor.setUiAttribs({ "greyout": true }); + incFactor.setUiAttribs({ "title": "Inc/Dec factor" }); + } + else + { + decFactor.setUiAttribs({ "greyout": false }); + incFactor.setUiAttribs({ "title": "Inc factor" }); + } + + getDivisors(); + update(); +} + +function getDivisors() +{ + divisorUp = incFactor.get(); + + if (selectedMode == false) divisorDown = incFactor.get(); + else divisorDown = decFactor.get(); + + if (divisorUp <= 0 || divisorUp != divisorUp)divisorUp = 0.0001; + if (divisorDown <= 0 || divisorDown != divisorDown)divisorDown = 0.0001; + if (divisorUp <= 1.0) divisorUp = 1.0; + if (divisorDown <= 1.0) divisorDown = 1.0; +} + +inArray.onLinkChanged = () => +{ + if (inArray) inArray.copyLinkedUiAttrib("stride", outArray); +}; + +inArray.onChange = function () +{ + let arr = inArray.get(); + if (!arr) return; + + for (let i = 0; i < arr.length; i++) + { + goal[i] = arr[i] || 0; + } +}; + +let oldVal = 0; + +function update() +{ + let arr = inArray.get(); + if (!arr) return; + + if (newArr.length != arr.length) + { + newArr.length = arr.length || 0; + reset = true; + } + + let tm = 1; + if (CABLES.now() - lastTrigger > 500 || lastTrigger === 0)reset = true; + else tm = (CABLES.now() - lastTrigger) / 17; + lastTrigger = CABLES.now(); + + if (reset) + { + for (var i = 0; i < arr.length; i++) + { + newArr[i] = arr[i]; + } + reset = false; + } + + for (var i = 0; i < arr.length; i++) + { + let val = newArr[i]; + + let diff = goal[i] - val; + + if (diff >= 0) + val += (diff) / (divisorDown * tm); + else + val += (diff) / (divisorUp * tm); + + if (val > 0 && val < 0.000000001)val = 0; + if (!val) val = 0; + + if (newArr[i] != val) + { + newArr[i] = val; + oldVal = val; + } + } + outArray.set(null); + outArray.set(newArr); + + next.trigger(); +} + +exec.onTriggered = function () +{ + update(); +}; + +incFactor.onChange = decFactor.onChange = getDivisors; +inModeBool.onChange = onFilterChange; +update(); + + +}; + +Ops.Array.SmoothArray.prototype = new CABLES.Op(); +CABLES.OPS["8fd2ed9b-02e5-4349-b7bc-6665ca240ffa"]={f:Ops.Array.SmoothArray,objName:"Ops.Array.SmoothArray"}; + + + + +// ************************************************************** +// +// Ops.Array.SortArray +// +// ************************************************************** + +Ops.Array.SortArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const arrayIn = op.inArray("Array to sort"), + sortMode = op.inSwitch("Sorting mode", ["Sort ascending", "Sort descending"], "Sort ascending"), + arrayOut = op.outArray("Sorted array"); +let arrOut = []; + +arrayIn.onChange = sortMode.onChange = update; +update(); + +function update() +{ + let arrIn = arrayIn.get(); + + arrOut.length = 0; + + if (!arrIn) + { + arrayOut.set(null); + return; + } + + arrOut.length = arrIn.length; + + let i; + for (i = 0; i < arrIn.length; i++) + { + arrOut[i] = arrIn[i]; + } + + if (sortMode.get() === "Sort ascending") + { + arrOut.sort(function (a, b) { return a - b; }); + } + else + { + arrOut.sort(function (a, b) { return b - a; }); + } + + arrayOut.set(null); + arrayOut.set(arrOut); +} + + +}; + +Ops.Array.SortArray.prototype = new CABLES.Op(); +CABLES.OPS["9ab49d2c-b4e4-4fc2-9e6e-8e664e094369"]={f:Ops.Array.SortArray,objName:"Ops.Array.SortArray"}; + + + + +// ************************************************************** +// +// Ops.Array.SortArray3 +// +// ************************************************************** + +Ops.Array.SortArray3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let inArr = op.inArray("Array"); +let what = op.inValueSelect("What", ["None", "X", "Y", "Z", "XYZ"]); +what.set("X"); +let outArr = op.outArray("Result"); + +let comparator = compareX; +let arrArr = []; + +op.toWorkPortsNeedToBeLinked(inArr); + +function compareX(a, b) { return a[0] - b[0]; } + +function compareY(a, b) { return a[1] - b[1]; } + +// function compareZ(a, b){ return b[2]-a[2]; } +function compareZ(a, b) { return a[2] - b[2]; } + +function compareXYZ(a, b) { return (a[0] + a[1] + a[2]) - (b[0] + b[1] + b[2]); } + +function sliceArray() +{ + let size = 3; + arrArr.length = 0; + let bigarray = inArr.get(); + for (let i = 0; i < bigarray.length; i += size) + { + arrArr.push(bigarray.slice(i, i + size)); + } +} + +inArr.onChange = recalc; + +function recalc() +{ + if (!Array.isArray(inArr.get())) + { + outArr.set(null); + return; + } + if (!comparator) + { + outArr.set(null); + outArr.set(inArr.get()); + return; + } + + let start = performance.now(); + + sliceArray(); + + arrArr.sort(comparator); + outArr.set(null); + + if (arrArr.flat)arrArr = arrArr.flat(); + else arrArr = [].concat.apply([], arrArr); + + outArr.set(null); + outArr.set(arrArr); +} + +what.onChange = function () +{ + // if(what.get()=='None')comparator=null; + if (what.get() == "X")comparator = compareX; + if (what.get() == "Y")comparator = compareY; + if (what.get() == "Z")comparator = compareZ; + if (what.get() == "XYZ")comparator = compareXYZ; + recalc(); +}; + + +}; + +Ops.Array.SortArray3.prototype = new CABLES.Op(); +CABLES.OPS["b0fbc366-09a8-4695-87b3-5946210bf722"]={f:Ops.Array.SortArray3,objName:"Ops.Array.SortArray3"}; + + + + +// ************************************************************** +// +// Ops.Array.SortArray3ByDistance +// +// ************************************************************** + +Ops.Array.SortArray3ByDistance = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array"), + outArr = op.outArray("Result"); + +function dist(x1, y1, z1, x2, y2, z2) +{ + let xd = x2 - x1; + let yd = y2 - y1; + let zd = z2 - z1; + return Math.abs(Math.sqrt(xd * xd + yd * yd + zd * zd)); +} + +inArr.onChange = function () +{ + if (!inArr.get()) return; + + let arr = inArr.get(); + + if (arr.length == 0) return; + + let data = []; + let i = 0; + for (i = 0; i < arr.length; i += 3) + { + data[i / 3] = { + "x": arr[i + 0], + "y": arr[i + 1], + "z": arr[i + 2], + "found": false, + "pos": 0 + }; + } + + let lastPoint = data[0]; + data[0].found = true; + + for (i = 0; i < data.length; i++) + { + let smallest = null; + let smallDist = 999999999; + + for (let j = 0; j < data.length; j++) + { + let d = dist( + lastPoint.x, lastPoint.y, lastPoint.z, + data[j].x, data[j].y, data[j].z + ); + + if (d < smallDist && !data[j].found) + { + smallDist = d; + smallest = data[j]; + } + } + + if (smallest) + { + smallest.pos = i; + smallest.found = true; + lastPoint = smallest; + } + } + + data.sort(function (a, b) + { + return a.pos - b.pos; + }); + + let outArray = []; + for (i = 0; i < data.length; i++) + { + outArray[i * 3 + 0] = data[i].x; + outArray[i * 3 + 1] = data[i].y; + outArray[i * 3 + 2] = data[i].z; + } + outArr.set(outArray); +}; + + +}; + +Ops.Array.SortArray3ByDistance.prototype = new CABLES.Op(); +CABLES.OPS["d67e094b-0206-4ab6-b97f-98a1242b334c"]={f:Ops.Array.SortArray3ByDistance,objName:"Ops.Array.SortArray3ByDistance"}; + + + + +// ************************************************************** +// +// Ops.Array.SortArrayObjectsByKey +// +// ************************************************************** + +Ops.Array.SortArrayObjectsByKey = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const arrayIn = op.inArray('Array to sort'); +const propIn = op.inString('Sort property'); +const sortMode = op.inSwitch('Sorting mode', ['Sort ascending', 'Sort descending'], 'Sort ascending'); +const arrayOut = op.outArray('Sorted array'); + +let arrOut = []; + +arrayIn.onChange = propIn.onChange = sortMode.onChange = update; + +update(); + +function update() { + const path = propIn.get(); + + if (!arrayIn.get() || !path) { + arrayOut.set(null); + return; + } + + arrOut = arrayIn.get(); + + if (sortMode.get() === 'Sort ascending') { + arrOut.sort(function(a, b) { + const properties = Array.isArray(path) ? path : path.split('.'); + const propA = properties.reduce((prev, curr) => prev && prev[curr], a); + const propB = properties.reduce((prev, curr) => prev && prev[curr], b); + if (propA < propB) { + return -1; + } else if ( propA > propB) { + return 1; + } else { + return 0; + } + }); + } else { + arrOut.sort(function(a, b) { + const properties = Array.isArray(path) ? path : path.split('.'); + const propA = properties.reduce((prev, curr) => prev && prev[curr], a); + const propB = properties.reduce((prev, curr) => prev && prev[curr], b); + if (propA < propB) { + return 1; + } else if ( propA > propB) { + return -1; + } else { + return 0; + } + }); + } + + arrayOut.set(null); + arrayOut.set(arrOut); +} + + +}; + +Ops.Array.SortArrayObjectsByKey.prototype = new CABLES.Op(); +CABLES.OPS["6a5a6674-9247-47ea-b9e1-0438ca07529a"]={f:Ops.Array.SortArrayObjectsByKey,objName:"Ops.Array.SortArrayObjectsByKey"}; + + + + +// ************************************************************** +// +// Ops.Array.SortArrayWithIndices +// +// ************************************************************** + +Ops.Array.SortArrayWithIndices = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + arrayIn = op.inArray("Array to sort"), + sortMode = op.inSwitch("Sorting mode", ["Ascending", "Descending"], "Ascending"), + arrayOut = op.outArray("Sorted array"), + arrayOutIdx = op.outArray("Sorted Indices"); + +let arrOut = []; +let indices = []; + +arrayIn.onChange = sortMode.onChange = update; +update(); + +function update() +{ + let arrIn = arrayIn.get(); + + arrOut.length = 0; + + if (!arrIn) + { + arrayOut.set(null); + return; + } + + arrOut.length = arrIn.length; + indices.length = arrIn.length; + + for (let i = 0; i < arrIn.length; ++i) indices[i] = i; + + for (let i = 0; i < arrIn.length; i++) + { + arrOut[i] = arrIn[i]; + } + + if (sortMode.get() === "Sort ascending") + { + indices.sort(function (a, b) { return arrOut[a] < arrOut[b] ? -1 : arrOut[a] > arrOut[b] ? 1 : 0; }); + + // arrOut.sort(function (a, b) { return a - b; }); + } + else + { + indices.sort(function (a, b) { return arrOut[a] > arrOut[b] ? -1 : arrOut[a] < arrOut[b] ? 1 : 0; }); + } + + arrayOut.set(null); + arrayOut.set(arrOut); + arrayOutIdx.set(null); + arrayOutIdx.set(indices); +} + + +}; + +Ops.Array.SortArrayWithIndices.prototype = new CABLES.Op(); +CABLES.OPS["83f78f91-027b-4251-9cd9-70ac676059ff"]={f:Ops.Array.SortArrayWithIndices,objName:"Ops.Array.SortArrayWithIndices"}; + + + + +// ************************************************************** +// +// Ops.Array.SplineLengthArray3 +// +// ************************************************************** + +Ops.Array.SplineLengthArray3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array3x"), + inCalc = op.inTriggerButton("Calculate"), + outValue = op.outNumber("Length"); + +let needsCalc = true; + +inArr.onChange = function () +{ + needsCalc = true; +}; + +inCalc.onTriggered = function () +{ + if (needsCalc) + { + needsCalc = false; + let arr = inArr.get(); + if (!arr || arr.length < 3) + { + outValue.set(0); + return; + } + + let l = 0; + for (let i = 3; i < arr.length; i += 3) + { + let xd = arr[i - 3] - arr[i + 0]; + let yd = arr[i - 2] - arr[i + 1]; + let zd = arr[i - 1] - arr[i + 2]; + l += Math.sqrt(xd * xd + yd * yd + zd * zd); + } + + if (l != l)l = 0; + outValue.set(l); + } +}; + + +}; + +Ops.Array.SplineLengthArray3.prototype = new CABLES.Op(); +CABLES.OPS["894db700-f220-427d-99fe-553db0a60034"]={f:Ops.Array.SplineLengthArray3,objName:"Ops.Array.SplineLengthArray3"}; + + + + +// ************************************************************** +// +// Ops.Array.SplinePositionAtDistanceArray3 +// +// ************************************************************** + +Ops.Array.SplinePositionAtDistanceArray3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTriggerButton("Calculate"), + inArr = op.inArray("Array3x"), + inDist = op.inValue("Distance"), + inNormalized = op.inValueBool("Normalized"), + + outNext = op.outTrigger("Next"), + outX = op.outNumber("X"), + outY = op.outNumber("Y"), + outZ = op.outNumber("Z"), + + outSplineLength = op.outNumber("Spline Length"); + +let animX = new CABLES.Anim(); +let animY = new CABLES.Anim(); +let animZ = new CABLES.Anim(); + +let needsMapping = true; + +function dist(x1, y1, z1, x2, y2, z2) +{ + let xd = x1 - x2; + let yd = y1 - y2; + let zd = z1 - z2; + return Math.sqrt(xd * xd + yd * yd + zd * zd); +} + +function splineLength(arr) +{ + let l = 0; + for (let i = 3; i < arr.length; i += 3) + { + l += dist(arr[i - 3], arr[i - 2], arr[i - 1], arr[i + 0], arr[i + 1], arr[i + 2]); + } + + outSplineLength.set(l); + return l; +} + +function mapArrays() +{ + animX.clear(); + animY.clear(); + animZ.clear(); + let arr = inArr.get(); + let sl = splineLength(arr); + + let distPos = 0; + + for (let i = 0; i < arr.length; i += 3) + { + let p = i / (arr.length - 3); + if (i > 0) + { + distPos += dist(arr[i - 3], arr[i - 2], arr[i - 1], arr[i + 0], arr[i + 1], arr[i + 2]); + } + + animX.setValue(distPos, arr[i + 0]); + animY.setValue(distPos, arr[i + 1]); + animZ.setValue(distPos, arr[i + 2]); + } + + needsMapping = false; +} + +inArr.onChange = function () +{ + needsMapping = true; +}; + +inExec.onTriggered = function () +{ + if (needsMapping)mapArrays(); + + let d = inDist.get(); + if (inNormalized.get())d *= outSplineLength.get(); + + outX.set(animX.getValue(d)); + outY.set(animY.getValue(d)); + outZ.set(animZ.getValue(d)); + + outNext.trigger(); +}; + + +}; + +Ops.Array.SplinePositionAtDistanceArray3.prototype = new CABLES.Op(); +CABLES.OPS["02100bb5-fe07-4c1b-8792-67f9add7afff"]={f:Ops.Array.SplinePositionAtDistanceArray3,objName:"Ops.Array.SplinePositionAtDistanceArray3"}; + + + + +// ************************************************************** +// +// Ops.Array.SplinesToLineStripArray +// +// ************************************************************** + +Ops.Array.SplinesToLineStripArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArrays = op.inArray("Array"), + outArr = op.outArray("Result"); + +inArrays.onChange = function () +{ + let inArr = inArrays.get(); + + let arr = []; + + if (!inArr) return; + + for (let i = 0; i < inArr.length; i++) + { + let pointArray = inArr[i]; + + for (let j = 3; j < pointArray.length - 3; j += 3) + { + arr.push(pointArray[j - 3]); + arr.push(pointArray[j - 2]); + arr.push(pointArray[j - 1]); + arr.push(pointArray[j + 0]); + arr.push(pointArray[j + 1]); + arr.push(pointArray[j + 2]); + } + } + + outArr.set(null); + outArr.set(arr); +}; + + +}; + +Ops.Array.SplinesToLineStripArray.prototype = new CABLES.Op(); +CABLES.OPS["0877ac11-4ebc-484c-aa10-276040756d0a"]={f:Ops.Array.SplinesToLineStripArray,objName:"Ops.Array.SplinesToLineStripArray"}; + + + + +// ************************************************************** +// +// Ops.Array.StringToCharArray +// +// ************************************************************** + +Ops.Array.StringToCharArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + strIn = op.inString("String", "test"), + convertToNumbersBool = op.inBool("Convert to numbers", false), + arrOut = op.outArray("Array out"); + +const arr = []; + +function update() +{ + const str = strIn.get(); + if (str !== undefined && str !== null) + { + const strLength = str.length; + + arr.length = 0; + arr.length = strLength; + if (convertToNumbersBool.get()) + { + for (let i = 0; i < strLength; i++) + { + arr[i] = str.charCodeAt(i); + } + } + else + { + for (let i = 0; i < strLength; i++) + { + arr[i] = str.charAt(i); + } + } + + op.setUiError("null", null); + arrOut.set(null); + arrOut.set(arr); + } + else + { + op.setUiError("null", "input is not of type string"); + arrOut.set(null); + } +} + +update(); +strIn.onChange = convertToNumbersBool.onChange = update; + + +}; + +Ops.Array.StringToCharArray.prototype = new CABLES.Op(); +CABLES.OPS["02ca1ecb-b087-4000-90f9-de96dca2f459"]={f:Ops.Array.StringToCharArray,objName:"Ops.Array.StringToCharArray"}; + + + + +// ************************************************************** +// +// Ops.Array.SubdivideArray1 +// +// ************************************************************** + +Ops.Array.SubdivideArray1 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let inArr = op.inArray("Points"); +let subDivs = op.inInt("Num Subdivs", 5); +let bezier = op.inValueBool("Smooth", true); +let bezierEndPoints = op.inValueBool("Bezier Start/End Points", true); + +let result = op.outArray("Result"); + +op.toWorkPortsNeedToBeLinked(inArr); + +subDivs.onChange = calc; +bezier.onChange = calc; +inArr.onChange = calc; +bezierEndPoints.onChange = calc; + +function ip(x0, x1, x2, t)// Bezier +{ + let r = (x0 * (1 - t) * (1 - t) + 2 * x1 * (1 - t) * t + x2 * t * t); + return r; +} + +let arr = []; + +function calc() +{ + if (!inArr.get()) + { + result.set(null); + return; + } + const subd = Math.floor(subDivs.get()); + let inPoints = inArr.get(); + + if (inPoints.length < 3) return; + + let i = 0; + let j = 0; + let k = 0; + let count = 0; + + if (subd > 0 && !bezier.get()) + { + const newLen = (inPoints.length - 1) * subd; + if (newLen != arr.length) + { + arr.length = newLen; + } + + count = 0; + for (i = 0; i < inPoints.length - 1; i++) + { + for (j = 0; j < subd; j++) + { + arr[count] = + inPoints[i] + (inPoints[i + 1] - inPoints[i]) * j / subd; + count++; + } + } + } + else + if (subd > 0 && bezier.get()) + { + let newLen = (inPoints.length - 6) * (subd - 1); + if (bezierEndPoints.get())newLen += 6; + + if (newLen != arr.length) arr.length = Math.floor(Math.abs(newLen)); + count = 0; + + if (bezierEndPoints.get()) + { + arr[0] = inPoints[0]; + count = 1; + } + + for (i = 1; i < inPoints.length - 1; i++) + { + for (j = 0; j < subd; j++) + { + let p = ip( + (inPoints[i - 1] + inPoints[i]) / 2, + inPoints[i + 0], + (inPoints[i + 1] + inPoints[i]) / 2, + j / subd + ); + arr[count] = p; + count++; + } + } + + if (bezierEndPoints.get()) + { + arr[count] = inPoints[inPoints.length - 1]; + } + } + result.set(null); + result.set(arr); +} + + +}; + +Ops.Array.SubdivideArray1.prototype = new CABLES.Op(); +CABLES.OPS["fa10c94d-d14e-41d3-b690-26d7cac5f146"]={f:Ops.Array.SubdivideArray1,objName:"Ops.Array.SubdivideArray1"}; + + + + +// ************************************************************** +// +// Ops.Array.SubdivideArray3_v2 +// +// ************************************************************** + +Ops.Array.SubdivideArray3_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Points"), + subDivs = op.inInt("Num Subdivs", 5), + bezier = op.inValueBool("Smooth", true), + inLoop = op.inValueBool("Loop", false), + bezierEndPoints = op.inValueBool("Bezier Start/End Points", true), + result = op.outArray("Result"); + +op.toWorkPortsNeedToBeLinked(inArr); + +let arr = []; + +subDivs.onChange = + inLoop.onChange = + bezier.onChange = + inArr.onChange = + bezierEndPoints.onChange = calc; + +function ip(x0, x1, x2, t)// Bezier +{ + const r = (x0 * (1 - t) * (1 - t) + 2 * x1 * (1 - t) * t + x2 * t * t); + return r; +} + +function calc() +{ + inLoop.setUiAttribs({ "greyout": !bezier.get() }); + bezierEndPoints.setUiAttribs({ "greyout": !bezier.get() }); + + if (!inArr.get()) + { + result.set(null); + return; + } + const subd = Math.floor(subDivs.get()); + const inPoints = inArr.get(); + + if (inPoints.length < 3) return; + + let i = 0; + let j = 0; + let k = 0; + let count = 0; + + if (subd > 0 && !bezier.get()) + { + const newLen = (inPoints.length - 3) * subd + 3; + if (newLen != arr.length) + { + arr.length = newLen; + } + + count = 0; + for (i = 0; i < inPoints.length - 3; i += 3) + { + for (j = 0; j < subd; j++) + { + for (k = 0; k < 3; k++) + { + arr[count] = + inPoints[i + k] + (inPoints[i + k + 3] - inPoints[i + k]) * j / subd; + count++; + } + } + } + arr[newLen - 3] = inPoints[inPoints.length - 3]; + arr[newLen - 2] = inPoints[inPoints.length - 2]; + arr[newLen - 1] = inPoints[inPoints.length - 1]; + } + else + if (subd > 0 && bezier.get()) + { + let newLen = (inPoints.length - 6) * (subd - 1); + if (bezierEndPoints.get())newLen += 6; + + if (newLen != arr.length) arr.length = Math.floor(Math.abs(newLen)); + count = 0; + + if (bezierEndPoints.get()) + { + arr[0] = inPoints[0]; + arr[1] = inPoints[1]; + arr[2] = inPoints[2]; + count = 3; + } + + const doLoop = inLoop.get(); + + function idx(i) + { + if (doLoop) return i % (inPoints.length - 3); + else return i; + } + + let endi = inPoints.length - 3; + if (doLoop)endi = inPoints.length; + + for (i = 3; i < endi; i += 3) + { + for (j = 0; j < subd; j++) + { + for (k = 0; k < 3; k++) + { + const p = ip( + (inPoints[idx(i + k - 3)] + inPoints[idx(i + k)]) / 2, + inPoints[idx(i + k + 0)], + (inPoints[idx(i + k + 3)] + inPoints[idx(i + k + 0)]) / 2, + j / subd + ); + arr[count] = p; + count++; + } + } + } + + if (doLoop) + { + arr[count + 0] = arr[0]; + arr[count + 1] = arr[1]; + arr[count + 2] = arr[2]; + count++; count++; count++; + } + + if (bezierEndPoints.get()) + { + arr[count - 0] = inPoints[inPoints.length - 3]; + arr[count + 1] = inPoints[inPoints.length - 2]; + arr[count + 2] = inPoints[inPoints.length - 1]; + } + } + if (subd == 0) + { + arr = Array.from(inPoints); + } + + result.set(null); + result.set(arr); +} + + +}; + +Ops.Array.SubdivideArray3_v2.prototype = new CABLES.Op(); +CABLES.OPS["d8bb5727-35e4-4e2a-999b-112ebc659720"]={f:Ops.Array.SubdivideArray3_v2,objName:"Ops.Array.SubdivideArray3_v2"}; + + + + +// ************************************************************** +// +// Ops.Array.SwitchArray +// +// ************************************************************** + +Ops.Array.SwitchArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let idx = op.inValueInt("Index"); +let valuePorts = []; +let result = op.outArray("Result"); + +idx.onChange = update; + +for (let i = 0; i < 10; i++) +{ + let p = op.inArray("Array " + i); + valuePorts.push(p); + p.onChange = update; +} + +function update() +{ + if (idx.get() >= 0 && valuePorts[idx.get()]) + { + result.set(valuePorts[idx.get()].get()); + } +} + + +}; + +Ops.Array.SwitchArray.prototype = new CABLES.Op(); +CABLES.OPS["3fab881c-c2cf-42a0-9c42-2d8edfd93f57"]={f:Ops.Array.SwitchArray,objName:"Ops.Array.SwitchArray"}; + + + + +// ************************************************************** +// +// Ops.Array.SwitchArrayOnTrigger +// +// ************************************************************** + +Ops.Array.SwitchArrayOnTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let N_PORTS = 8; + +// input ports +const + inTrigger1 = op.inTriggerButton("Trigger 1"), + inArray1 = op.inArray("Array 1"), + inTrigger2 = op.inTriggerButton("Trigger 2"), + inArray2 = op.inArray("Array 2"), + inTrigger3 = op.inTriggerButton("Trigger 3"), + inArray3 = op.inArray("Array 3"), + inTrigger4 = op.inTriggerButton("Trigger 4"), + inArray4 = op.inArray("Array 4"), + inTrigger5 = op.inTriggerButton("Trigger 5"), + inArray5 = op.inArray("Array 5"), + inTrigger6 = op.inTriggerButton("Trigger 6"), + inArray6 = op.inArray("Array 6"), + inTrigger7 = op.inTriggerButton("Trigger 7"), + inArray7 = op.inArray("Array 7"), + inTrigger8 = op.inTriggerButton("Trigger 8"), + inArray8 = op.inArray("Array 8"); + +// output ports +let outArray = op.outArray("Out Array"); + +// change listeners +inTrigger1.onTriggered = function () +{ + outArray.set(inArray1.get()); +}; +inTrigger2.onTriggered = function () +{ + outArray.set(inArray2.get()); +}; +inTrigger3.onTriggered = function () +{ + outArray.set(inArray3.get()); +}; +inTrigger4.onTriggered = function () +{ + outArray.set(inArray4.get()); +}; +inTrigger5.onTriggered = function () +{ + outArray.set(inArray5.get()); +}; +inTrigger6.onTriggered = function () +{ + outArray.set(inArray6.get()); +}; +inTrigger7.onTriggered = function () +{ + outArray.set(inArray7.get()); +}; +inTrigger8.onTriggered = function () +{ + outArray.set(inArray8.get()); +}; + + +}; + +Ops.Array.SwitchArrayOnTrigger.prototype = new CABLES.Op(); +CABLES.OPS["08e0cc91-8fda-48c1-a98e-2bf7265d6683"]={f:Ops.Array.SwitchArrayOnTrigger,objName:"Ops.Array.SwitchArrayOnTrigger"}; + + + + +// ************************************************************** +// +// Ops.Array.TextureBufferArray +// +// ************************************************************** + +Ops.Array.TextureBufferArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inExec = op.inTrigger("Write"); + +const inTexture = op.inTexture("Texture"); +const inNum = op.inValueInt("Num", 8); + +const outArr = op.outArray("Result"); + +const inSort = op.inValueBool("Order"); +const inClear = op.inValueBool("Clear", true); + +const cgl = op.patch.cgl; +const frameBuf = cgl.gl.createFramebuffer(); +const renderbuffer = cgl.gl.createRenderbuffer(); +let index = 0; +const textures = []; +let quadMesh = null; +let inited = false; +const sorted = []; + +inNum.onChange = init; + +const bgFrag = "" + .endl() + "UNI float a;" + .endl() + "UNI sampler2D tex;" + .endl() + "IN vec2 texCoord;" + .endl() + "void main()" + .endl() + "{" + .endl() + " vec4 col=texture2D(tex,texCoord);" + .endl() + " outColor= col;" + .endl() + "}"; +const bgShader = new CGL.Shader(cgl, "imgcompose bg"); +bgShader.setSource(bgShader.getDefaultVertexShader(), bgFrag); +const textureUniform = new CGL.Uniform(bgShader, "t", "tex", 0); + +inExec.onTriggered = render; + +function init() +{ + if (inNum.get() == 0) return; + for (let i = 0; i < textures.length; i++) + { + textures[i].delete(); + } + + if (!inTexture.get()) return; + textures.length = inNum.get(); + sorted.length = inNum.get(); + + // op.log(inTexture.get()); + + for (let i = 0; i < inNum.get(); i++) + { + textures[i] = inTexture.get().clone(); + // textures[i].updateMipMap(); + } + + // cgl.gl.bindFramebuffer(cgl.gl.FRAMEBUFFER, null); + + // cgl.gl.bindFramebuffer(cgl.gl.FRAMEBUFFER, frameBuf); + cgl.gl.bindFramebuffer(cgl.gl.FRAMEBUFFER, frameBuf); + cgl.gl.framebufferTexture2D(cgl.gl.FRAMEBUFFER, cgl.gl.COLOR_ATTACHMENT0, cgl.gl.TEXTURE_2D, textures[0].tex, 0); + + // cgl.gl.bindRenderbuffer(cgl.gl.RENDERBUFFER, renderbuffer); + + // cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, null); + // cgl.gl.bindRenderbuffer(cgl.gl.RENDERBUFFER, null); + cgl.gl.bindFramebuffer(cgl.gl.FRAMEBUFFER, null); + + // textures[0].updateMipMap(); + + inited = true; +} + +function createMesh() +{ + const geom = new CGL.Geometry("textureEffect rect"); + + geom.vertices = [ + 1.0, 1.0, 0.0, + -1.0, 1.0, 0.0, + 1.0, -1.0, 0.0, + -1.0, -1.0, 0.0 + ]; + + geom.texCoords = [ + 1.0, 1.0, + 0.0, 1.0, + 1.0, 0.0, + 0.0, 0.0 + ]; + + geom.verticesIndices = [ + 0, 1, 2, + 2, 1, 3 + ]; + + quadMesh = new CGL.Mesh(cgl, geom); +} + +function render() +{ + if (!inTexture.get()) + { + op.log("no tex 1"); + return; + } + + if (!inTexture.get().tex) + { + op.log("no tex 2"); + return; + } + + if (!quadMesh)createMesh(); + if (!inited || !frameBuf)init(); + if (!textures[0] || textures.length == 0) + { + op.log("no tex"); + return; + } + + if (!textures[0].compareSettings(inTexture.get()))init(); + // if(inTexture.get().width!=textures[0].width)init(); + // if(inTexture.get().height!=textures[0].height)init(); + + index %= inNum.get(); + + cgl.gl.bindFramebuffer(cgl.gl.FRAMEBUFFER, frameBuf); + cgl.gl.framebufferTexture2D(cgl.gl.FRAMEBUFFER, cgl.gl.COLOR_ATTACHMENT0, cgl.gl.TEXTURE_2D, textures[index].tex, 0); + cgl.pushGlFrameBuffer(frameBuf); + + cgl.pushDepthTest(false); + + if (inClear.get()) + { + cgl.gl.clearColor(0, 0, 0, 1); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); + } + + cgl.pushModelMatrix(); + + cgl.pushPMatrix(); + cgl.gl.viewport(0, 0, inTexture.get().width, inTexture.get().height); + mat4.perspective(cgl.pMatrix, 45, inTexture.get().width / inTexture.get().height, 0.1, 1100.0); + + cgl.pushPMatrix(); + mat4.identity(cgl.pMatrix); + + cgl.pushViewMatrix(); + mat4.identity(cgl.vMatrix); + + cgl.pushModelMatrix(); + mat4.identity(cgl.mMatrix); + + // here be rendering + + cgl.pushShader(bgShader); + // cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, inTexture.get().tex); + // cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, ); + + quadMesh.render(cgl.getShader()); + + cgl.gl.bindFramebuffer(cgl.gl.FRAMEBUFFER, cgl.popGlFrameBuffer()); + + cgl.popShader(); + + cgl.popDepthTest(); + cgl.popModelMatrix(); + + cgl.popPMatrix(); + cgl.popModelMatrix(); + cgl.popViewMatrix(); + + cgl.popPMatrix(); + cgl.resetViewPort(); + + op.patch.cgl.gl.bindTexture(op.patch.cgl.gl.TEXTURE_2D, textures[index].tex); + // this._colorTextures[i].updateMipMap(); + textures[index].updateMipMap(); + op.patch.cgl.gl.bindTexture(op.patch.cgl.gl.TEXTURE_2D, null); + + if (inSort.get()) + { + for (let i = 0; i < textures.length; i++) + { + sorted[textures.length - i - 1] = textures[(index + i + 1) % inNum.get()]; + } + + outArr.set(null); + outArr.set(sorted); + } + else + { + outArr.set(null); + outArr.set(textures); + } + index++; +} + + +}; + +Ops.Array.TextureBufferArray.prototype = new CABLES.Op(); +CABLES.OPS["04dc13d2-e339-4e1d-82c5-9c9ff1b175b8"]={f:Ops.Array.TextureBufferArray,objName:"Ops.Array.TextureBufferArray"}; + + + + +// ************************************************************** +// +// Ops.Array.TransformArray3 +// +// ************************************************************** + +Ops.Array.TransformArray3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTriggerButton("Transform"), + inArr = op.inArray("Array", 3), + transX = op.inFloat("Translate X"), + transY = op.inFloat("Translate Y"), + transZ = op.inFloat("Translate Z"), + scaleX = op.inFloat("Scale X", 1), + scaleY = op.inFloat("Scale Y", 1), + scaleZ = op.inFloat("Scale Z", 1), + rotX = op.inFloat("Rotation X"), + rotY = op.inFloat("Rotation Y"), + rotZ = op.inFloat("Rotation Z"), + next = op.outTrigger("Next"), + outArr = op.outArray("Result", 3); + +op.setPortGroup("Translation", [transX, transY, transZ]); +op.setPortGroup("Scale", [scaleX, scaleY, scaleZ]); +op.setPortGroup("Rotation", [rotX, rotY, rotZ]); + +let resultArr = []; +let needsCalc = true; + +let rotVec = vec3.create(); +let emptyVec = vec3.create(); +let transVec = vec3.create(); +let centerVec = vec3.create(); + +inExec.onTriggered = doTransform; + +inArr.onChange = +transX.onChange = transY.onChange = transZ.onChange = +scaleX.onChange = scaleY.onChange = scaleZ.onChange = +rotX.onChange = rotY.onChange = rotZ.onChange = calcLater; + +function calcLater() +{ + needsCalc = true; +} + +function doTransform() +{ + let arr = inArr.get(); + if (!arr) + { + outArr.set(null); + return; + } + if (needsCalc) + { + resultArr.length = arr.length; + + const nrotx = rotX.get(); + const nroty = rotY.get(); + const nrotz = rotZ.get(); + const scx = scaleX.get(); + const scy = scaleY.get(); + const scz = scaleZ.get(); + const transx = transX.get(); + const transy = transY.get(); + const transz = transZ.get(); + const doRot = nrotx || nroty || nrotz; + + for (let i = 0; i < arr.length; i += 3) + { + resultArr[i + 0] = arr[i + 0] * scx; + resultArr[i + 1] = arr[i + 1] * scy; + resultArr[i + 2] = arr[i + 2] * scz; + + resultArr[i + 0] = resultArr[i + 0] + transx; + resultArr[i + 1] = resultArr[i + 1] + transy; + resultArr[i + 2] = resultArr[i + 2] + transz; + + if (doRot) + { + vec3.set(rotVec, + resultArr[i + 0], + resultArr[i + 1], + resultArr[i + 2]); + + if (nrotx != 0) vec3.rotateX(rotVec, rotVec, transVec, nrotx * CGL.DEG2RAD); + if (nroty != 0) vec3.rotateY(rotVec, rotVec, transVec, nroty * CGL.DEG2RAD); + if (nrotz != 0) vec3.rotateZ(rotVec, rotVec, transVec, nrotz * CGL.DEG2RAD); + + resultArr[i + 0] = rotVec[0]; + resultArr[i + 1] = rotVec[1]; + resultArr[i + 2] = rotVec[2]; + } + } + + needsCalc = false; + outArr.set(null); + outArr.set(resultArr); + } + next.trigger(); +} + + +}; + +Ops.Array.TransformArray3.prototype = new CABLES.Op(); +CABLES.OPS["b18040d6-13d7-4f55-950f-3f95cafa4e90"]={f:Ops.Array.TransformArray3,objName:"Ops.Array.TransformArray3"}; + + + + +// ************************************************************** +// +// Ops.Array.WeaveArrays +// +// ************************************************************** + +Ops.Array.WeaveArrays = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// inputs +let inPort1 = op.inArray("Array 1"); +let inPort2 = op.inArray("Array 2"); +let chunkSizePort = op.inValue("Chunk Size", 1); + +// outputs +let outPort = op.outArray("Combined Array"); + +// change listeners +inPort1.onChange = update; +inPort2.onChange = update; +chunkSizePort.onChange = update; + +// functions + +function update() +{ + let newArr = []; + let arr1 = inPort1.get(); + let arr2 = inPort2.get(); + + let chunkSize = chunkSizePort.get(); + if (chunkSize < 1) + { + chunkSize = 1; + // TODO: Show warning in gui!? + } + // array 2 is empty -> just use array 1 + if (arr1 && !arr2) + { + newArr = arr1.slice(0); + } + // array 1 is empty -> just use array 2 + if (!arr1 && arr2) // normally else if + { + newArr = arr2.slice(0); + } + + // array 1 and 2 are not empty -> combine them + else if (arr1 && arr2) + { + for (let i = 0; i < Math.max(arr1.length, arr2.length); i += chunkSize) + { + for (let j = 0; j < chunkSize && j + i < arr1.length; j++) + { + newArr.push(arr1[i + j]); + } + for (let k = 0; k < chunkSize && k + i < arr2.length; k++) + { + newArr.push(arr2[i + k]); + } + } + } + outPort.set(null); + outPort.set(newArr); +} + + +}; + +Ops.Array.WeaveArrays.prototype = new CABLES.Op(); +CABLES.OPS["ad6d77b7-d81d-4115-a2f2-5160adaaef3a"]={f:Ops.Array.WeaveArrays,objName:"Ops.Array.WeaveArrays"}; + + + + +// ************************************************************** +// +// Ops.Arrays.ArrayToArrays +// +// ************************************************************** + +Ops.Arrays.ArrayToArrays = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array"), + inStride = op.inInt("Stride", 6), + outArr = op.outArray("Result"); + +inArr.onChange = () => +{ + const stride = inStride.get(); + const result = []; + const arr = inArr.get(); + if (!arr) return outArr.set(null); + + let count = 0; + for (let i = 0; i < arr.length; i += stride) + { + const newArr = []; + for (let j = 0; j < stride; j++) + { + newArr[j] = arr[i + j] || 0; + } + result[count] = newArr; + count++; + } + + outArr.set(null); + outArr.set(result); +}; + + +}; + +Ops.Arrays.ArrayToArrays.prototype = new CABLES.Op(); +CABLES.OPS["037a9886-c185-4ab2-8c7e-b9f85b1e678c"]={f:Ops.Arrays.ArrayToArrays,objName:"Ops.Arrays.ArrayToArrays"}; + + + + +// ************************************************************** +// +// Ops.Audio.BpmTap +// +// ************************************************************** + +Ops.Audio.BpmTap = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const DEFAULT_BPM = 127; + +const exe = op.inTrigger("exe"); +const tap = op.inTriggerButton("tap"); +const sync = op.inTriggerButton("sync"); +const nudgeLeft = op.inTriggerButton("nudgeLeft"); +const nudgeRight = op.inTriggerButton("nudgeRight"); + +const beat = op.outTrigger("beat"); +// const bpm = this.addOutPort(new CABLES.Port(this, "Bpm", CABLES.OP_PORT_TYPE_VALUE, { "display": "editor" }),0); +const bpm = op.outNumber("Bpm", DEFAULT_BPM); +const outStates = op.outArray("States"); +const beatNum = op.outNumber("Beat Index"); + +const DEFAULT_MILLIS = bpmToMillis(DEFAULT_BPM); +const NUDGE_VALUE = 0.5; // to add / substract from avg bpm + +let lastFlash = -1; +let lastTap = -1; + +const taps = []; + +let avgBpm = DEFAULT_BPM; +let avgMillis = getAvgMillis(); + +let beatCounter = 1; // [1, 2, 3, 4] +const states = [1, 0, 0, 0]; + +exe.onTriggered = function () +{ + if (op.patch.freeTimer.get() * 1000 < lastFlash) + { + lastFlash = op.patch.freeTimer.get() * 1000; + } + + if (op.patch.freeTimer.get() * 1000 > lastFlash + avgMillis) + { + beat.trigger(); + incrementState(); + outStates.set(null); + outStates.set(states); + + if (taps.length > 0) bpm.set(millisToBpm(avgMillis)); + lastFlash = op.patch.freeTimer.get() * 1000; + } +}; + +function incrementState() +{ + beatCounter++; + if (beatCounter > 4) + { + beatCounter = 1; + } + for (let i = 0; i < 4; i++) + { + states[i] = 0; + } + states[beatCounter - 1] = 1; + + beatNum.set(beatCounter - 1); +} + +function tapPressed() +{ + // start new tap session + if (op.patch.freeTimer.get() * 1000 - lastTap > 1000) + { + taps.length = 0; + beatCounter = 0; + } + else + { + taps.push(op.patch.freeTimer.get() * 1000 - lastTap); + } + lastTap = op.patch.freeTimer.get() * 1000; + avgMillis = getAvgMillis(); +} + +function millisToBpm(millis) +{ + return Number(60 * 1000 / millis).toFixed(2); +} + +function bpmToMillis(bpms) +{ + return 60 * 1000 / bpms; +} + +function getAvgMillis() +{ + if (taps.length >= 1) + { + let sum = 0.0; + for (let i = 0; i < taps.length; i++) + { + sum += taps[i]; + } + return sum / taps.length; + } + else + { + return DEFAULT_MILLIS; + } +} + +function syncPressed() +{ + // on next execute everything will be reset to first beat + lastFlash = -1; + beatCounter = 0; +} + +function nudgeLeftPressed() +{ + avgBpm += NUDGE_VALUE; + avgMillis = bpmToMillis(avgBpm); +} + +function nudgeRightPressed() +{ + avgBpm -= NUDGE_VALUE; + avgMillis = bpmToMillis(avgBpm); +} + +tap.onTriggered = tapPressed; +sync.onTriggered = syncPressed; +nudgeLeft.onTriggered = nudgeLeftPressed; +nudgeRight.onTriggered = nudgeRightPressed; + + +}; + +Ops.Audio.BpmTap.prototype = new CABLES.Op(); +CABLES.OPS["86096ee6-08f7-4463-b7c3-41cf7bc80de7"]={f:Ops.Audio.BpmTap,objName:"Ops.Audio.BpmTap"}; + + + + +// ************************************************************** +// +// Ops.Audio.MidiJson +// +// ************************************************************** + +Ops.Audio.MidiJson = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inObj = op.inObject("MidiJson"), + inTime = op.inValue("Time"), + outBeat = op.outNumber("Beat"), + outTrackNames = op.outArray("Track Names"), + outNames = op.outArray("Names"), + outProgress = op.outArray("Progress"), + outVelocity = op.outArray("Velocity"), + outNumTracks = op.outNumber("Num Tracks"), + outBPM = op.outNumber("BPM"), + outData = op.outObject("Data"); + +let midi = null; +let arrNames = []; +let arrProgress = []; +let arrVelocity = []; +let bpm = 0; + +inObj.onChange = function () +{ + midi = null; + outNumTracks.set(0); + + midi = inObj.get(); + if (!midi) return; + if (!midi.tracks) return; + + outNumTracks.set(midi.tracks.length); + + let arrTrackNames = []; + for (let i = 0; i < midi.tracks.length; i++) + { + arrTrackNames[i] = midi.tracks[i].name || "?"; + } + + outTrackNames.set(null); + outTrackNames.set(arrTrackNames); + + arrNames.length = midi.tracks.length; + + bpm = midi.header.bpm; + outBPM.set(midi.header.bpm); + + for (let t = 0; t < midi.tracks.length; t++) + { + for (let n = 0; n < midi.tracks[t].notes.length; n++) + { + let note = midi.tracks[t].notes[n]; + note.timeEnd = note.time + note.duration; + } + } +}; + +inTime.onChange = function () +{ + if (!midi) return; + if (!midi.tracks) return; + + let time = inTime.get(); + outNames.set(null); + outProgress.set(null); + outVelocity.set(null); + outData.set(null); + + let beat = Math.round(inTime.get() / 60 * (bpm)); + + for (let t = 0; t < midi.tracks.length; t++) + { + arrNames[t] = ""; + arrProgress[t] = 0; + arrVelocity[t] = 0; + + for (let n = 0; n < midi.tracks[t].notes.length; n++) + { + let note = midi.tracks[t].notes[n]; + + if ( + time > note.time && + time < note.timeEnd) + { + arrProgress[t] = (time - note.time) / (note.duration); + arrNames[t] = note.name; + arrVelocity[t] = note.velocity; + + const data = + { + "beat": 0, + "names": arrNames, + "progress": arrProgress, + "velocity": arrVelocity, + "midi": note.midi, + "beat": beat + + }; + + outData.set(data); + } + } + } + + outNames.set(arrNames); + outNames.setUiAttribs({ "stride": arrNames.length }); + outProgress.set(arrProgress); + outVelocity.set(arrVelocity); + + outBeat.set(beat); +}; + + +}; + +Ops.Audio.MidiJson.prototype = new CABLES.Op(); +CABLES.OPS["695aef03-8ab0-48a1-b3ee-2c6c01a21640"]={f:Ops.Audio.MidiJson,objName:"Ops.Audio.MidiJson"}; + + + + +// ************************************************************** +// +// Ops.Audio.MidiJsonNote_v2 +// +// ************************************************************** + +Ops.Audio.MidiJsonNote_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inData = op.inObject("Data"), + // inFilter = op.inSwitch("Filter", ["Note Name", "Midi"], "Note Name"), + inNote = op.inString("Note"), + // inNoteMidi = op.inInt("Midi"), + inChannel = op.inValueString("Channel", -1), + inStartBeat = op.inValueInt("Beat Start", 0), + inEndBeat = op.inValueInt("Beat End", 0), + + outCount = op.outNumber("Count"), + outProgress = op.outNumber("Progress"), + outTimeSince = op.outNumber("Time since last"), + outTrigger = op.outTrigger("Trigger"), + outReset = op.outTrigger("Reseted"); + +let lastBeat = 0; +let counter = 0; +let oldNames = null; +let oldProgress = null; +let lastHit = 0; +let notfound = true; +// let NoteOrMidi = true; +// inFilter.onChange = updateUi; +// updateUi(); + +// function updateUi() +// { +// inNote.setUiAttribs({ "greyout": inFilter.get() != "Note Name" }); +// inNoteMidi.setUiAttribs({ "greyout": inFilter.get() != "Midi" }); + +// NoteOrMidi = inFilter.get() == "Note Name"; +// } + +inNote.onChange = () => +{ + op.setUiAttrib({ "extendTitle": "" + inNote.get() }); +}; + +inData.onChange = function () +{ + const data = inData.get(); + if (!data) return; + const beat = data.beat; + + if (inStartBeat.get() != inEndBeat.get()) + { + if (beat < inStartBeat.get()) return; + if (beat > inEndBeat.get()) return; + } + + const names = data.names; + const progress = data.progress; + if (!names) return; + if (!progress) return; + + if (beat < lastBeat) + { + counter = 0; + lastHit = 0; + notfound = true; + outTimeSince.set(0); + outReset.trigger(); + } + lastBeat = beat; + + const note = inNote.get(); + + if (!oldNames) + { + oldNames = []; + oldProgress = []; + oldNames.length = names.length; + oldProgress.length = names.length; + } + + let startChn = 0; + let endChn = names.length; + + if (inChannel.get() >= 0) + { + startChn = inChannel.get(); + endChn = startChn + 1; + } + + let prog = 0; + let progCount = 0; + + for (let i = startChn; i < endChn; i++) + { + if ((NoteOrMidi && names[i] == note)) + { + if ((oldNames[i] != note) || notfound) // ( oldNames[i]==note && progress[i] port.set(defaultValue)); +} + +function update() +{ + setDefaultValues(); + let index = indexPort.get(); + let value = valuePort.get(); + index = Math.round(index); + index = CABLES.clamp(index, 0, NUM_PORTS - 1); + valuePorts[index].set(value); +} + + +}; + +Ops.Boolean.RouteBoolean.prototype = new CABLES.Op(); +CABLES.OPS["88b3f5ec-0e45-4651-89ca-33173d001ab6"]={f:Ops.Boolean.RouteBoolean,objName:"Ops.Boolean.RouteBoolean"}; + + + + +// ************************************************************** +// +// Ops.Boolean.ToggleBoolValue +// +// ************************************************************** + +Ops.Boolean.ToggleBoolValue = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + bool = op.inValueBool("in bool"), + outbool = op.outBoolNum("out bool"); + +bool.changeAlways = true; + +bool.onChange = function () +{ + outbool.set(!(bool.get() == true)); +}; + + +}; + +Ops.Boolean.ToggleBoolValue.prototype = new CABLES.Op(); +CABLES.OPS["7b1abd02-3aad-4106-9848-7f4c3cfab6a9"]={f:Ops.Boolean.ToggleBoolValue,objName:"Ops.Boolean.ToggleBoolValue"}; + + + + +// ************************************************************** +// +// Ops.Boolean.ToggleBool_v2 +// +// ************************************************************** + +Ops.Boolean.ToggleBool_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + trigger = op.inTriggerButton("trigger"), + reset = op.inTriggerButton("reset"), + outBool = op.outBool("result"), + inDefault = op.inBool("Default", false); + +let theBool = false; + +op.onLoadedValueSet = () => +{ + outBool.set(inDefault.get()); +}; + +trigger.onTriggered = function () +{ + theBool = !theBool; + outBool.set(theBool); +}; + +reset.onTriggered = function () +{ + theBool = inDefault.get(); + outBool.set(theBool); +}; + + +}; + +Ops.Boolean.ToggleBool_v2.prototype = new CABLES.Op(); +CABLES.OPS["4313d9bb-96b6-43bc-9190-6068cfb2593c"]={f:Ops.Boolean.ToggleBool_v2,objName:"Ops.Boolean.ToggleBool_v2"}; + + + + +// ************************************************************** +// +// Ops.Boolean.TriggerBoolean +// +// ************************************************************** + +Ops.Boolean.TriggerBoolean = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTriggerTrue = op.inTriggerButton("True"), + inTriggerFalse = op.inTriggerButton("false"), + outResult = op.outBoolNum("Result"); + +inTriggerTrue.onTriggered = function () +{ + outResult.set(true); +}; + +inTriggerFalse.onTriggered = function () +{ + outResult.set(false); +}; + + +}; + +Ops.Boolean.TriggerBoolean.prototype = new CABLES.Op(); +CABLES.OPS["31f65abe-9d6c-4ba6-a291-ef2de41d2087"]={f:Ops.Boolean.TriggerBoolean,objName:"Ops.Boolean.TriggerBoolean"}; + + + + +// ************************************************************** +// +// Ops.Boolean.TriggerChangedFalse +// +// ************************************************************** + +Ops.Boolean.TriggerChangedFalse = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let val = op.inValueBool("Value", false); +let next = op.outTrigger("Next"); + +let oldVal = 0; + +val.onChange = function () +{ + let newVal = val.get(); + if (oldVal && !newVal) + { + oldVal = false; + next.trigger(); + } + else + { + oldVal = true; + } +}; + + +}; + +Ops.Boolean.TriggerChangedFalse.prototype = new CABLES.Op(); +CABLES.OPS["6387bcb0-6091-4199-8ab7-f96ad4aa3c7d"]={f:Ops.Boolean.TriggerChangedFalse,objName:"Ops.Boolean.TriggerChangedFalse"}; + + + + +// ************************************************************** +// +// Ops.Boolean.TriggerChangedTrue +// +// ************************************************************** + +Ops.Boolean.TriggerChangedTrue = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let val = op.inValueBool("Value", false); +let next = op.outTrigger("Next"); +let oldVal = 0; + +val.onChange = function () +{ + let newVal = val.get(); + if (!oldVal && newVal) + { + oldVal = true; + next.trigger(); + } + else + { + oldVal = false; + } +}; + + +}; + +Ops.Boolean.TriggerChangedTrue.prototype = new CABLES.Op(); +CABLES.OPS["385197e1-8b34-4d1c-897f-d1386d99e3b3"]={f:Ops.Boolean.TriggerChangedTrue,objName:"Ops.Boolean.TriggerChangedTrue"}; + + + + +// ************************************************************** +// +// Ops.Boolean.TriggerOnChangeBoolean +// +// ************************************************************** + +Ops.Boolean.TriggerOnChangeBoolean = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inBool = op.inValueBool("Value"), + outTrue = op.outTrigger("True"), + outFalse = op.outTrigger("False"); + +inBool.onChange = function () +{ + if (inBool.get()) outTrue.trigger(); + else outFalse.trigger(); +}; + + +}; + +Ops.Boolean.TriggerOnChangeBoolean.prototype = new CABLES.Op(); +CABLES.OPS["dba19c07-e3c4-4971-a991-c9e6212ca1c8"]={f:Ops.Boolean.TriggerOnChangeBoolean,objName:"Ops.Boolean.TriggerOnChangeBoolean"}; + + + + +// ************************************************************** +// +// Ops.Browser.BrowserInfo_v3 +// +// ************************************************************** + +Ops.Browser.BrowserInfo_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + isMobile = op.outBool("Is Mobile", false), + isTouch = op.outBool("Is Touchscreen", false), + isIe = op.outBool("Is IE", false), + isEdge = op.outBool("Is Edge", false), + isChrome = op.outBool("Is Chrome", false), + isFirefox = op.outBool("Is Firefox", false), + isOpera = op.outBool("Is Opera", false), + isSafari = op.outBool("Is Safari", false), + isWindows = op.outBool("Is Windows", false), + isLinux = op.outBool("Is Linux", false), + isMac = op.outBool("Is Mac", false), + isIos = op.outBool("Is iOS", false), + isAndroid = op.outBool("Is Android", false), + isElectron = op.outBool("Is Electron", false), + outOS = op.outString("Operating System", ""), + outBrowserName = op.outString("Browser Name", ""), + outVersion = op.outString("OS Version", ""), + outNav = op.outString("Language"), + outUA = op.outString("User Agent"); + +op.setPortGroup("Browsers", [isIe, isEdge, isChrome, isFirefox, isOpera, isSafari]); +op.setPortGroup("Operating Systems", [isWindows, isLinux, isMac, isIos, isAndroid, isElectron]); +op.setPortGroup("Textual Information", [outOS, outBrowserName, outNav, outVersion, outUA]); +const pf = platform; + +const osFamily = pf.os.family; + +const isOperaBool = pf.name === "Opera"; +const isSafariBool = pf.name === "Safari"; +const isIEBool = pf.name === "IE"; +const isEdgeBool = pf.name === "Microsoft Edge"; +const isChromeBool = pf.name === "Chrome" || pf.name === "Chrome Mobile"; +const isBlinkBool = pf.layout === "Blink"; +const isFirefoxBool = pf.name === "Firefox" || pf.name === "Firefox Mobile" || pf.name === "Firefox for iOS"; + +const isLinuxBool = osFamily === "Linux" + || osFamily === "Ubuntu" + || osFamily === "SuSE" + || osFamily === "Fedora" + || osFamily === "OpenBSD" + || osFamily === "Debian" + || osFamily === "Red Hat"; + +const isMacBool = osFamily === "Mac" || osFamily === "Macintosh" || osFamily === "Mac OS X" || osFamily === "OS X"; +const isWindowsBool = osFamily === "Windows" || osFamily === "Windows 98;"; +const isAndroidBool = osFamily === "Android"; +const isIosBool = osFamily === "iOS"; +const isMobileBool = (osFamily === "webOS" // LG mobile phones + || osFamily === "Windows Phone" + || osFamily === "Android" + || osFamily === "iOS") + || + (pf.name === "Chrome Mobile" + || pf.name === "Firefox for iOS" + || pf.name === "Firefox Mobile" + || pf.name === "IE Mobile" + || pf.name === "Opera Mobile"); +const isElectronBool = pf.name === "Electron"; + +const isTouchDevice = ( + ("ontouchstart" in window) || + (navigator.maxTouchPoints > 0) || + (navigator.msMaxTouchPoints > 0)); + +isMobile.set(isMobileBool); +isTouch.set(isTouchDevice); + +isIe.set(isIEBool); +isEdge.set(isEdgeBool); +isChrome.set(isChromeBool); +isFirefox.set(isFirefoxBool); +isOpera.set(isOperaBool); +isSafari.set(isSafariBool); + +isMac.set(isMacBool); +isLinux.set(isLinuxBool); +isWindows.set(isWindowsBool); +isIos.set(isIosBool); +isAndroid.set(isAndroidBool); +isElectron.set(isElectronBool); + +outNav.set(navigator.language || navigator.userLanguage); +outUA.set(pf.ua); +outVersion.set(pf.os.version); +outOS.set(pf.os.toString()); +outBrowserName.set(pf.name); + + +}; + +Ops.Browser.BrowserInfo_v3.prototype = new CABLES.Op(); +CABLES.OPS["ec3e0121-b2c2-4c31-bbda-a6982080f73f"]={f:Ops.Browser.BrowserInfo_v3,objName:"Ops.Browser.BrowserInfo_v3"}; + + + + +// ************************************************************** +// +// Ops.Browser.JsMemory +// +// ************************************************************** + +Ops.Browser.JsMemory = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Update"), + outUsed = op.outNumber("Used Heap Size", 0), + outTotal = op.outNumber("Total Heap Size", 0); + +if (performance.memory && performance.memory.usedJSHeapSize) + inExec.onTriggered = update; + +function update() +{ + outUsed.set(performance.memory.usedJSHeapSize / 1024 / 1024); + outTotal.set(performance.memory.totalJSHeapSize / 1024 / 1024); +} + + +}; + +Ops.Browser.JsMemory.prototype = new CABLES.Op(); +CABLES.OPS["7176f9c7-1ee8-419e-b58b-178cca9265e7"]={f:Ops.Browser.JsMemory,objName:"Ops.Browser.JsMemory"}; + + + + +// ************************************************************** +// +// Ops.Browser.WebShare +// +// ************************************************************** + +Ops.Browser.WebShare = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inText = op.inString("Text", "check out undev"), + inUrl = op.inString("URL", "https://undev.studio"), + inBase64 = op.inString("Base64 File"), + inDataUrl = op.inString("Data URL"), + inFileType = op.inString("Filetype", "image/png"), + inFileName = op.inString("Filename", "screenshot.png"), + exec = op.inTriggerButton("Share"), + outStatus = op.outString("Status", "none"), + outSupport = op.outBoolNum("Supported", !!navigator.share); + +op.setPortGroup("File", [inBase64, inDataUrl, inFileType, inFileName]); + +if (!navigator.share) +{ + op.setUiError("noShare", "webshare api not supported on this device", 1); +} + +exec.onTriggered = () => +{ + op.setUiError("noShare", null); + if (!navigator.share) + { + op.setUiError("noShare", "webshare api not supported on this device", 1); + outSupport.set(false); + return; + } + outSupport.set(true); + + const shareData = {}; + shareData.text = inText.get(); + shareData.url = inUrl.get(); + + let url = inDataUrl.get(); + if (inBase64.get()) + { + url = "data:" + inFileType.get() + ";base64," + inBase64.get(); + } + + if (url) + { + fetch(url) + .then((res) => res.blob()) + .then((blob) => + { + shareData.files = [ + new File( + [blob], + inFileName.get(), + { + "type": inFileType.get(), + "lastModified": new Date().getTime() + } + ) + ]; + if (!navigator.canShare(shareData)) + { + op.setUiError("noShare", "browser can't share files", 1); + op.log("browser cant share files", shareData); + delete shareData.files; + } + if (!navigator.canShare(shareData)) + { + op.setUiError("noShare", "browser can't share data", 1); + op.log("browser cant share data", shareData); + outStatus.set("error"); + } + else + { + doShare(shareData); + } + }); + } + else + { + doShare(shareData); + } +}; + +function doShare(shareData) +{ + navigator.share(shareData) + .then(() => + { + outStatus.set("success"); + }) + .catch((error) => + { + outStatus.set("error"); + op.setUiError("noShare", "Error sharing", error); + op.log("Error sharing", error); + }); +} + + +}; + +Ops.Browser.WebShare.prototype = new CABLES.Op(); +CABLES.OPS["2e24a18f-161a-480c-a86b-4232c59f68c4"]={f:Ops.Browser.WebShare,objName:"Ops.Browser.WebShare"}; + + + + +// ************************************************************** +// +// Ops.Cables.AssetPathURL +// +// ************************************************************** + +Ops.Cables.AssetPathURL = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + fn = op.inString("Filename", ""), + path = op.outString("Path"); + +fn.onChange = update; + +update(); + +function update() +{ + let filename = fn.get(); + + if (!fn.get()) + { + path.set(""); + return; + } + + let patchId = null; + if (op.storage && op.storage.blueprint && op.storage.blueprint.patchId) + { + patchId = op.storage.blueprint.patchId; + } + filename = op.patch.getAssetPath(patchId) + filename; + let url = op.patch.getFilePath(filename); + path.set(url); +} + + +}; + +Ops.Cables.AssetPathURL.prototype = new CABLES.Op(); +CABLES.OPS["e502ae39-c87e-4516-9e78-cb71333bcfff"]={f:Ops.Cables.AssetPathURL,objName:"Ops.Cables.AssetPathURL"}; + + + + +// ************************************************************** +// +// Ops.Cables.CustomOp_v2 +// +// ************************************************************** + +Ops.Cables.CustomOp_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const defaultCode = "\ +// you can use custom javascript code here, it will be bound to the\n\ +// scope of the current op, which is available as `op`.\n\ +// \n\ +// have a look at the documentation at:\n\ +// https://docs.cables.gl/dev_hello_op/dev_hello_op.html\n\ +\n\ +"; + +const inJS = op.inStringEditor("JavaScript"); +inJS.setUiAttribs({ "editorSyntax": "js" }); +inJS.set(defaultCode); +const inLib = op.inUrl("Library", [".js"]); + +const portsData = op.inString("portsData", "{}"); +portsData.setUiAttribs({ "hidePort": true }); +portsData.setUiAttribs({ "hideParam": true }); +const protectedPorts = [inJS.id, inLib.id, portsData.id]; + +let wasPasted = false; + +op.setUiError("error", null); + +const init = function () +{ + if (op.uiAttribs) + { + wasPasted = op.uiAttribs.pasted; + } + restorePorts(); + loadLibAndExecute(); + inLib.onChange = inJS.onChange = loadLibAndExecute; + if (wasPasted) wasPasted = false; +}; + +op.onLoadedValueSet = init; +op.patch.on("onOpAdd", (newOp, fromDeserizalize) => +{ + if (op == newOp && !fromDeserizalize) + { + init(); + } +}); + +op.onError = function (ex) +{ + if (op.patch.isEditorMode()) + { + op.setUiError("error", ex); + const str = inJS.get(); + const badLines = []; + let htmlWarning = ""; + const lines = str.match(/^.*((\r\n|\n|\r)|$)/gm); + + let anonLine = ""; + const exLines = ex.stack.split("\n"); + for (let i = 0; i < exLines.length; i++) + { + // firefox + if (exLines[i].includes("Function:")) + { + anonLine = exLines[i]; + break; + } + // chrome + if (exLines[i].includes("anonymous")) + { + anonLine = exLines[i]; + break; + } + } + + let lineFields = anonLine.split(":"); + let errorLine = lineFields[lineFields.length - 2]; + + badLines.push(errorLine - 2); + + for (const i in lines) + { + const j = parseInt(i, 10) + 1; + const line = j + ": " + lines[i]; + + let isBadLine = false; + for (const bj in badLines) + if (badLines[bj] == j) isBadLine = true; + + if (isBadLine) htmlWarning += ""; + htmlWarning += line.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """) + .replaceAll("'", "'"); + if (isBadLine) htmlWarning += ""; + } + + ex.customMessage = htmlWarning; + ex.stack = ""; + op.patch.emitEvent("exceptionOp", ex, op.name); + } +}; + +const getEvalFunction = () => +{ + op.setUiError("error", null); + let errorEl = document.getElementById("customop-error-" + op.id); + if (errorEl) + { + errorEl.remove(); + } + try + { + return new Function("op", inJS.get()); + } + catch (err) + { + op.onError(err); + if (op.patch.isEditorMode()) + { + errorEl = document.createElement("script"); + errorEl.id = "customop-error-" + op.id; + errorEl.type = "text/javascript"; + errorEl.innerHTML = inJS.get(); + document.body.appendChild(errorEl); + } + else + { + op.logError("error creating javascript function", err); + } + return null; + } +}; + +function loadLibAndExecute() +{ + if (inLib.get()) + { + let scriptTag = document.getElementById("customop_lib_" + op.id); + if (scriptTag) + { + scriptTag.remove(); + } + scriptTag = document.createElement("script"); + scriptTag.id = "customlib_" + op.id; + scriptTag.type = "text/javascript"; + scriptTag.src = op.patch.getFilePath(String(inLib.get())); + scriptTag.onload = function () + { + op.logVerbose("done loading library", inLib.get()); + execute(); + }; + document.body.appendChild(scriptTag); + } + else if (inJS.get() && inJS.get() !== defaultCode) + { + execute(); + } +} + +const removeInPort = (port) => +{ + port.removeLinks(); + for (let ipi = 0; ipi < op.portsIn.length; ipi++) + { + if (op.portsIn[ipi] == port) + { + op.portsIn.splice(ipi, 1); + return; + } + } +}; + +const removeOutPort = (port) => +{ + port.removeLinks(); + for (let ipi = 0; ipi < op.portsOut.length; ipi++) + { + if (op.portsOut[ipi] == port) + { + op.portsOut.splice(ipi, 1); + return; + } + } +}; + +const execute = () => +{ + const evalFunction = getEvalFunction(); + if (evalFunction) + { + try + { + const oldLinksIn = {}; + const oldValuesIn = {}; + const oldLinksOut = {}; + const removeInPorts = []; + const removeOutPorts = []; + op.portsIn.forEach((port) => + { + if (!protectedPorts.includes(port.id)) + { + oldLinksIn[port.name] = []; + oldValuesIn[port.name] = port.get(); + port.links.forEach((link) => + { + const linkInfo = { + "op": link.portOut.parent, + "portName": link.portOut.name + }; + oldLinksIn[port.name].push(linkInfo); + }); + removeInPorts.push(port); + } + }); + op.portsOut.forEach((port) => + { + oldLinksOut[port.name] = []; + port.links.forEach((link) => + { + const linkInfo = { + "op": link.portIn.parent, + "portName": link.portIn.name + }; + oldLinksOut[port.name].push(linkInfo); + }); + removeOutPorts.push(port); + }); + removeInPorts.forEach((port) => + { + removeInPort(port); + }); + removeOutPorts.forEach((port) => + { + removeOutPort(port); + }); + if (removeOutPorts.length > 0 || removeInPorts.length > 0) + { + this.emitEvent("onUiAttribsChange", {}); + this.emitEvent("onPortRemoved", {}); + } + evalFunction(this); + + op.portsIn.forEach((port) => + { + if (!protectedPorts.includes(port.id)) + { + port.onLinkChanged = savePortData; + + if (oldLinksIn[port.name]) + { + oldLinksIn[port.name].forEach((link) => + { + op.patch.link(op, port.name, link.op, link.portName); + }); + } + + if (typeof port.onChange == "function") + { + const oldHandler = port.onChange; + port.onChange = (p, v) => + { + if (!port.isLinked()) savePortData(); + oldHandler(p, v); + }; + } + else + { + port.onChange = () => + { + if (!port.isLinked()) savePortData(); + }; + } + + // for backwards compatibility, do not add default handler (handled above) + if (typeof port.onValueChanged == "function") + { + const oldValueHandler = port.onValueChanged; + port.onValueChanged = (p, v) => + { + if (!port.isLinked()) savePortData(); + oldValueHandler(p, v); + }; + } + + if (oldValuesIn[port.name]) + { + port.set(oldValuesIn[port.name]); + } + } + }); + op.portsOut.forEach((port) => + { + port.onLinkChanged = savePortData; + + if (oldLinksOut[port.name]) + { + oldLinksOut[port.name].forEach((link) => + { + op.patch.link(op, port.name, link.op, link.portName); + }); + } + }); + if (wasPasted) + { + wasPasted = false; + } + savePortData(); + } + catch (e) + { + if (op.patch.isEditorMode()) + { + op.onError(e); + const name = "Ops.Custom.CUSTOM" + op.id.replace(/-/g, ""); + const code = inJS.get(); + let codeHead = "Ops.Custom = Ops.Custom || {};\n"; + codeHead += name + " = " + name + " || {};\n"; + codeHead += name + " = function()\n{\nCABLES.Op.apply(this,arguments);\nconst op=this;\n"; + let codeFoot = "\n\n};\n\n" + name + ".prototype = new CABLES.Op();\n"; + codeFoot += "new " + name + "();\n"; + const opCode = codeHead + code + codeFoot; + const errorEl = document.createElement("script"); + errorEl.id = "customop-error-" + op.id; + errorEl.type = "text/javascript"; + errorEl.innerHTML = opCode; + document.body.appendChild(errorEl); + } + else + { + op.logError("error executing javascript code", e); + } + } + } +}; + +function savePortData() +{ + const newPortsData = { "portsIn": {}, "portsOut": {} }; + op.portsIn.forEach((port) => + { + if (!protectedPorts.includes(port.id)) + { + let v = port.get(); + if (port.ignoreValueSerialize)v = null; + const portData = { + "name": port.name, + "title": port.title, + "value": v, + "type": port.type, + "links": [] + }; + port.links.forEach((link) => + { + const linkData = { + "objOut": link.portOut.parent.id, + "portOut": link.portOut.name + }; + portData.links.push(linkData); + }); + newPortsData.portsIn[port.name] = portData; + } + }); + + op.portsOut.forEach((port) => + { + if (!protectedPorts.includes(port.id)) + { + let v = port.get(); + if (port.ignoreValueSerialize)v = null; + + const portData = { + "name": port.name, + "title": port.title, + "value": v, + "type": port.type, + "links": [] + }; + port.links.forEach((link) => + { + const linkData = { + "objIn": link.portIn.parent.id, + "portIn": link.portIn.name + }; + portData.links.push(linkData); + }); + newPortsData.portsOut[port.name] = portData; + } + }); + + let serializedPortsData = "{}"; + try + { + serializedPortsData = JSON.stringify(newPortsData); + } + catch (e) + { + op.log("failed to stringify new port data", newPortsData); + } + portsData.set(serializedPortsData); +} + +const getOldPorts = () => +{ + const jsonData = portsData.get(); + let oldPorts = {}; + try + { + oldPorts = JSON.parse(jsonData); + } + catch (e) + { + op.log("failed to parse old port data", jsonData); + } + + let oldPortsIn = {}; + let oldPortsOut = {}; + + if (oldPorts.portsOut) + { + oldPortsOut = oldPorts.portsOut; + } + if (oldPorts.portsIn) + { + oldPortsIn = oldPorts.portsIn; + } + return { "portsIn": oldPortsIn, "portsOut": oldPortsOut }; +}; + +const restorePorts = () => +{ + const oldPorts = getOldPorts(); + const portInKeys = Object.keys(oldPorts.portsIn); + if (op.patch.isEditorMode()) CABLES.UI.undo.pause(); + for (let i = 0; i < portInKeys.length; i++) + { + const oldPortIn = oldPorts.portsIn[portInKeys[i]]; + const newPort = op.addInPort(new CABLES.Port(op, oldPortIn.name, oldPortIn.type)); + + if (!wasPasted && Array.isArray(oldPortIn.links)) + { + oldPortIn.links.forEach((link) => + { + let parent = op.patch.getOpById(link.objOut); + if (parent) + { + op.patch.link(parent, link.portOut, op, newPort.name); + } + }); + } + if (!newPort.isLinked()) + { + newPort.set(oldPortIn.value); + } + newPort.onLinkChanged = savePortData; + + if (oldPortIn.title) + { + newPort.setUiAttribs({ "title": oldPortIn.title }); + } + } + + const portOutKeys = Object.keys(oldPorts.portsOut); + for (let i = 0; i < portOutKeys.length; i++) + { + const oldPortOut = oldPorts.portsOut[portOutKeys[i]]; + const newPort = op.addOutPort(new CABLES.Port(op, oldPortOut.name, oldPortOut.type)); + if (!wasPasted && Array.isArray(oldPortOut.links)) + { + oldPortOut.links.forEach((link) => + { + let parent = op.patch.getOpById(link.objIn); + if (parent) + { + op.patch.link(op, newPort.name, parent, link.portIn); + } + }); + if (!newPort.isLinked()) + { + newPort.set(oldPortOut.value); + } + newPort.onLinkChanged = savePortData; + + if (oldPortOut.title) + { + newPort.setUiAttribs({ "title": oldPortOut.title }); + } + } + } + if (op.patch.isEditorMode()) CABLES.UI.undo.resume(); +}; + + +}; + +Ops.Cables.CustomOp_v2.prototype = new CABLES.Op(); +CABLES.OPS["19166505-2619-4012-ad85-d2de60f27274"]={f:Ops.Cables.CustomOp_v2,objName:"Ops.Cables.CustomOp_v2"}; + + + + +// ************************************************************** +// +// Ops.Cables.ExitError +// +// ************************************************************** + +Ops.Cables.ExitError = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inId = op.inString("ID", "fail"), + inMessage = op.inString("Message", "a critical error happened!"), + exit = op.inTriggerButton("Exit"); + +exit.onTriggered = () => +{ + op.patch.exitError(inId.get(), inMessage.get()); +}; + + +}; + +Ops.Cables.ExitError.prototype = new CABLES.Op(); +CABLES.OPS["e1ad65d5-1f84-45d7-8291-925474bd2bd9"]={f:Ops.Cables.ExitError,objName:"Ops.Cables.ExitError"}; + + + + +// ************************************************************** +// +// Ops.Cables.FPS_v2 +// +// ************************************************************** + +Ops.Cables.FPS_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + active = op.inBool("Active", true), + outFPS = op.outNumber("FPS"), + outMS = op.outNumber("MS"); + +const listener = op.patch.addEventListener("performance", update); + +op.onDelete = function () +{ + op.patch.removeEventListener(listener); +}; + +function update(p) +{ + if (active.get()) + { + outFPS.set(p.fps); + outMS.set(p.ms); + } +} + + +}; + +Ops.Cables.FPS_v2.prototype = new CABLES.Op(); +CABLES.OPS["6dbb866c-b57a-4875-9f1d-22172162eaa8"]={f:Ops.Cables.FPS_v2,objName:"Ops.Cables.FPS_v2"}; + + + + +// ************************************************************** +// +// Ops.Cables.PatchInfo_v2 +// +// ************************************************************** + +Ops.Cables.PatchInfo_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const outConfig = op.outObject("Config"); +const outName = op.outString("Name"); +const outPatchId = op.outString("Patch Id"); +const outNamespace = op.outString("Namespace"); +const outSaveDate = op.outNumber("Last Saved"); +const outExportDate = op.outNumber("Last Exported"); + +const patch = getPatch(); + +outConfig.set(patch.config); +outName.set(patch.name); +outPatchId.set(getPatchId()); +outNamespace.set(patch.namespace); +outSaveDate.set(getLastSaveDate()); +outExportDate.set(getLastExportDate()); + +function getPatchId() +{ + let id = null; + if (patch && patch._id) id = patch._id; + if (patch && patch.config && patch.config.patch && patch.config.patch._id) id = patch.config.patch._id; + if (window.gui && window.gui.patchId) id = window.gui.patchId; + if (window.CABLES && window.CABLES.patchId) id = window.CABLES.patchId; + if (CABLES.patchId) id = CABLES.patchId; + return id; +} + +function getLastSaveDate() +{ + let date = null; + if (patch && patch.config && patch.config.patch) date = patch.config.patch.updated; + if (window.gui && window.gui.project) date = window.gui.project().updated; + return new Date(date).getTime(); +} + +function getLastExportDate() +{ + let date = null; + if (patch && patch.config && patch.config.patch) + { + if (patch.config.patch.deployments && patch.config.patch.deployments.lastDeployment) + { + date = patch.config.patch.deployments.lastDeployment.date; + } + } + if (window.gui && window.gui.project) + { + const p = window.gui.project(); + if (p.deployments && p.deployments.lastDeployment) + { + date = p.deployments.lastDeployment.date; + } + } + return new Date(date).getTime(); +} + +function getPatch() +{ + let thePatch = null; + if (CABLES && CABLES.exportedPatch) thePatch = CABLES.exportedPatch; + if (CABLES && CABLES.patch) thePatch = CABLES.patch; + if (op.patch) thePatch = op.patch; + return thePatch; +} + + +}; + +Ops.Cables.PatchInfo_v2.prototype = new CABLES.Op(); +CABLES.OPS["7187c2f2-67a9-479e-92c4-0e415443f504"]={f:Ops.Cables.PatchInfo_v2,objName:"Ops.Cables.PatchInfo_v2"}; + + + + +// ************************************************************** +// +// Ops.Cables.UIMode +// +// ************************************************************** + +Ops.Cables.UIMode = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const outUI = op.outBool("UI", op.patch.isEditorMode()); +const outRemoteViewer = op.outBool("Remote Viewer", window.gui ? window.gui.isRemoteClient : false); + + +}; + +Ops.Cables.UIMode.prototype = new CABLES.Op(); +CABLES.OPS["7c110d60-829f-4b06-b3e4-0af911550570"]={f:Ops.Cables.UIMode,objName:"Ops.Cables.UIMode"}; + + + + +// ************************************************************** +// +// Ops.Color.ColorPalettes +// +// ************************************************************** + +Ops.Color.ColorPalettes = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const index = op.inValueInt("Index", 0); +const textureOut = op.outTexture("Texture"); +const inLinear = op.inValueBool("Smooth"); +const arrOut = op.outArray("Color Array"); + +let canvas = document.createElement("canvas"); +canvas.id = "canvas_" + CABLES.generateUUID(); +canvas.width = 5; +canvas.height = 8; +canvas.style.display = "none"; + +let body = document.getElementsByTagName("body")[0]; +body.appendChild(canvas); +let ctx = canvas.getContext("2d"); + +index.onChange = +inLinear.onChange = buildTextureLater; + +let arr = []; +arr.length = 5 * 3; +let lastFilter = null; + +buildTextureLater(); + +function hexToR(h) +{ + return parseInt((cutHex(h)).substring(0, 2), 16); +} + +function hexToG(h) +{ + return parseInt((cutHex(h)).substring(2, 4), 16); +} + +function hexToB(h) +{ + return parseInt((cutHex(h)).substring(4, 6), 16); +} + +function cutHex(h) +{ + return (h.charAt(0) == "#") ? h.substring(1, 7) : h; +} + +function buildTextureLater() +{ + op.patch.cgl.addNextFrameOnceCallback(buildTexture); +} + +function buildTexture() +{ + let ind = Math.round(index.get()) * 5; + if (ind >= colors.length - 5)ind = 0; + if (ind < 0)ind = 0; + if (ind != ind)ind = 0; + + for (let i = 0; i < 5; i++) + { + let r = hexToR(colors[ind + i]); + let g = hexToG(colors[ind + i]); + let b = hexToB(colors[ind + i]); + + arr[i * 3 + 0] = r / 255; + arr[i * 3 + 1] = g / 255; + arr[i * 3 + 2] = b / 255; + + ctx.fillStyle = "rgb(" + r + "," + g + "," + b + ")"; + ctx.fillRect( + canvas.width / 5 * i, + 0, + canvas.width / 5, + canvas.height + ); + } + + let filter = CGL.Texture.FILTER_NEAREST; + if (inLinear.get())filter = CGL.Texture.FILTER_LINEAR; + + if (lastFilter == filter && textureOut.get()) textureOut.get().initTexture(canvas, filter); + else textureOut.set(new CGL.Texture.createFromImage(op.patch.cgl, canvas, { "filter": filter })); + + arrOut.set(null); + arrOut.set(arr); + textureOut.get().unpackAlpha = false; + lastFilter = filter; +} + +op.onDelete = function () +{ + canvas.remove(); +}; + +const colors = [ + "#E6E2AF", "#A7A37E", "#EFECCA", "#046380", "002F2F", + "#468966", "#FFF0A5", "#FFB03B", "#B64926", "8E2800", + "#FCFFF5", "#D1DBBD", "#91AA9D", "#3E606F", "193441", + "#FF6138", "#FFFF9D", "#BEEB9F", "#79BD8F", "00A388", + "#105B63", "#FFFAD5", "#FFD34E", "#DB9E36", "BD4932", + "#225378", "#1695A3", "#ACF0F2", "#F3FFE2", "EB7F00", + "#2C3E50", "#E74C3C", "#ECF0F1", "#3498DB", "2980B9", + "#000000", "#263248", "#7E8AA2", "#FFFFFF", "FF9800", + "#004358", "#1F8A70", "#BEDB39", "#FFE11A", "FD7400", + "#DC3522", "#D9CB9E", "#374140", "#2A2C2B", "1E1E20", + "#7D8A2E", "#C9D787", "#FFFFFF", "#FFC0A9", "FF8598", + "#B9121B", "#4C1B1B", "#F6E497", "#FCFAE1", "BD8D46", + "#2E0927", "#D90000", "#FF2D00", "#FF8C00", "04756F", + "#595241", "#B8AE9C", "#FFFFFF", "#ACCFCC", "8A0917", + "#10222B", "#95AB63", "#BDD684", "#E2F0D6", "F6FFE0", + "#F6F792", "#333745", "#77C4D3", "#DAEDE2", "EA2E49", + "#703030", "#2F343B", "#7E827A", "#E3CDA4", "C77966", + "#2F2933", "#01A2A6", "#29D9C2", "#BDF271", "FFFFA6", + "#D8CAA8", "#5C832F", "#284907", "#382513", "363942", + "#FFF8E3", "#CCCC9F", "#33332D", "#9FB4CC", "DB4105", + "#85DB18", "#CDE855", "#F5F6D4", "#A7C520", "493F0B", + "#04BFBF", "#CAFCD8", "#F7E967", "#A9CF54", "588F27", + "#292929", "#5B7876", "#8F9E8B", "#F2E6B6", "412A22", + "#332532", "#644D52", "#F77A52", "#FF974F", "A49A87", + "#405952", "#9C9B7A", "#FFD393", "#FF974F", "F54F29", + "#2B3A42", "#3F5765", "#BDD4DE", "#EFEFEF", "FF530D", + "#962D3E", "#343642", "#979C9C", "#F2EBC7", "348899", + "#96CA2D", "#B5E655", "#EDF7F2", "#4BB5C1", "7FC6BC", + "#1C1D21", "#31353D", "#445878", "#92CDCF", "EEEFF7", + "#3E454C", "#2185C5", "#7ECEFD", "#FFF6E5", "FF7F66", + "#00585F", "#009393", "#FFFCC4", "#F0EDBB", "FF3800", + "#B4AF91", "#787746", "#40411E", "#32331D", "C03000", + "#63A69F", "#F2E1AC", "#F2836B", "#F2594B", "CD2C24", + "#88A825", "#35203B", "#911146", "#CF4A30", "ED8C2B", + "#F2385A", "#F5A503", "#E9F1DF", "#4AD9D9", "36B1BF", + "#CFC291", "#FFF6C5", "#A1E8D9", "#FF712C", "695D46", + "#FF5335", "#B39C85", "#306E73", "#3B424D", "1D181F", + "#000000", "#333333", "#FF358B", "#01B0F0", "AEEE00", + "#E8E595", "#D0A825", "#40627C", "#26393D", "FFFAE4", + "#E7E8D1", "#D3CEAA", "#FBF7E4", "#424242", "8E001C", + "#354242", "#ACEBAE", "#FFFF9D", "#C9DE55", "7D9100", + "#2F2933", "#01A2A6", "#29D9C2", "#BDF271", "FFFFA6", + "#DDDCC5", "#958976", "#611427", "#1D2326", "6A6A61", + "#6C6E58", "#3E423A", "#417378", "#A4CFBE", "F4F7D9", + "#E1E6FA", "#C4D7ED", "#ABC8E2", "#375D81", "183152", + "#6B0C22", "#D9042B", "#F4CB89", "#588C8C", "011C26", + "#304269", "#91BED4", "#D9E8F5", "#FFFFFF", "F26101", + "#96CEB4", "#FFEEAD", "#FF6F69", "#FFCC5C", "AAD8B0", + "#B0CC99", "#677E52", "#B7CA79", "#F6E8B1", "89725B", + "#334D5C", "#45B29D", "#EFC94C", "#E27A3F", "DF5A49", + "#16193B", "#35478C", "#4E7AC7", "#7FB2F0", "ADD5F7", + "#00261C", "#044D29", "#168039", "#45BF55", "96ED89", + "#36362C", "#5D917D", "#A8AD80", "#E6D4A7", "825534", + "#F9E4AD", "#E6B098", "#CC4452", "#723147", "31152B", + "#2C3E50", "#FC4349", "#D7DADB", "#6DBCDB", "FFFFFF", + "#002635", "#013440", "#AB1A25", "#D97925", "EFE7BE", + "#FF8000", "#FFD933", "#CCCC52", "#8FB359", "192B33", + "#272F32", "#9DBDC6", "#FFFFFF", "#FF3D2E", "DAEAEF", + "#B8ECD7", "#083643", "#B1E001", "#CEF09D", "476C5E", + "#002F32", "#42826C", "#A5C77F", "#FFC861", "C84663", + "#5C4B51", "#8CBEB2", "#F2EBBF", "#F3B562", "F06060", + "#5A1F00", "#D1570D", "#FDE792", "#477725", "A9CC66", + "#5E0042", "#2C2233", "#005869", "#00856A", "8DB500", + "#52656B", "#FF3B77", "#CDFF00", "#FFFFFF", "B8B89F", + "#801637", "#047878", "#FFB733", "#F57336", "C22121", + "#730046", "#BFBB11", "#FFC200", "#E88801", "C93C00", + "#24221F", "#363F45", "#4B5F6D", "#5E7C88", "FEB41C", + "#E64661", "#FFA644", "#998A2F", "#2C594F", "002D40", + "#C24704", "#D9CC3C", "#FFEB79", "#A0E0A9", "00ADA7", + "#484A47", "#C1CE96", "#ECEBF0", "#687D77", "353129", + "#588C7E", "#F2E394", "#F2AE72", "#D96459", "8C4646", + "#BAB293", "#A39770", "#EFE4BD", "#A32500", "2B2922", + "#6A7059", "#FDEEA7", "#9BCC93", "#1A9481", "003D5C", + "#174C4F", "#207178", "#FF9666", "#FFE184", "F5E9BE", + "#D5FBFF", "#9FBCBF", "#647678", "#2F3738", "59D8E6", + "#DB5800", "#FF9000", "#F0C600", "#8EA106", "59631E", + "#450003", "#5C0002", "#94090D", "#D40D12", "FF1D23", + "#211426", "#413659", "#656F8C", "#9BBFAB", "F2EFDF", + "#EA6045", "#F8CA4D", "#F5E5C0", "#3F5666", "2F3440", + "#F2F2F2", "#C6E070", "#91C46C", "#287D7D", "1C344D", + "#334D5C", "#45B29D", "#EFC94C", "#E27A3F", "DF5A49", + "#705B35", "#C7B07B", "#E8D9AC", "#FFF6D9", "570026", + "#F7F2B2", "#ADCF4F", "#84815B", "#4A1A2C", "8E3557", + "#1A1F2B", "#30395C", "#4A6491", "#85A5CC", "D0E4F2", + "#25064D", "#36175E", "#553285", "#7B52AB", "9768D1", + "#004056", "#2C858D", "#74CEB7", "#C9FFD5", "FFFFCB", + "#CFCA4C", "#FCF5BF", "#9FE5C2", "#5EB299", "745A33", + "#776045", "#A8C545", "#DFD3B6", "#FFFFFF", "0092B2", + "#CC3910", "#F1F2C0", "#CCC59E", "#8FA68E", "332F29", + "#FF6600", "#C13B00", "#5E6D70", "#424E4F", "1B1D1E", + "#690011", "#BF0426", "#CC2738", "#F2D99C", "E5B96F", + "#1B1D26", "#425955", "#778C7A", "#F1F2D8", "BFBD9F", + "#F6B1C3", "#F0788C", "#DE264C", "#BC0D35", "A20D1E", + "#597533", "#332F28", "#61B594", "#E6DEA5", "C44E18", + "#3FB8AF", "#7FC7AF", "#DAD8A7", "#FF9E9D", "FF3D7F", + "#0F2D40", "#194759", "#296B73", "#3E8C84", "D8F2F0", + "#42282F", "#74A588", "#D6CCAD", "#DC9C76", "D6655A", + "#002A4A", "#17607D", "#FFF1CE", "#FF9311", "D64700", + "#003056", "#04518C", "#00A1D9", "#47D9BF", "F2D03B", + "#13140F", "#D4FF00", "#E4FFE6", "#68776C", "00D6DD", + "#FCFAD0", "#A1A194", "#5B605F", "#464646", "A90641", + "#289976", "#67CC8E", "#B1FF91", "#FFE877", "FF5600", + "#302B1D", "#3F522B", "#737D26", "#A99E46", "D9CB84", + "#56626B", "#6C9380", "#C0CA55", "#F07C6C", "AD5472", + "#32450C", "#717400", "#DC8505", "#EC5519", "BE2805", + "#C7B773", "#E3DB9A", "#F5FCD0", "#B1C2B3", "778691", + "#E83A25", "#FFE9A3", "#98CC96", "#004563", "191B28", + "#3399CC", "#67B8DE", "#91C9E8", "#B4DCED", "E8F8FF", + "#1A212C", "#1D7872", "#71B095", "#DEDBA7", "D13F32", + "#7D2A35", "#CC9258", "#917A56", "#B4BA6C", "FEFFC2", + "#E7E9D1", "#D3D4AA", "#FCFAE6", "#444444", "901808", + "#FFFFFF", "#AEAEAE", "#E64C66", "#2D3E50", "1BBC9B", + "#E0FFB3", "#61C791", "#31797D", "#2A2F36", "F23C55", + "#EB5937", "#1C1919", "#403D3C", "#456F74", "D3CBBD", + "#E6DD00", "#8CB302", "#008C74", "#004C66", "332B40", + "#14A697", "#F2C12E", "#F29D35", "#F27649", "F25252", + "#261822", "#40152A", "#731630", "#CC1E2C", "FF5434", + "#261F27", "#FEE169", "#CDD452", "#F9722E", "C9313D", + "#5C4B51", "#8CBEB2", "#F2EBBF", "#F3B562", "F06060", + "#2F3837", "#C5C7B6", "#FFF8D3", "#4C493E", "222028", + "#E3CBAC", "#9C9985", "#C46D3B", "#788880", "324654", + "#3F0B1B", "#7A1631", "#CF423C", "#FC7D49", "FFD462", + "#14212B", "#293845", "#4F6373", "#8F8164", "D9D7AC", + "#98A89E", "#BAC0AC", "#FAFAC6", "#FF4411", "D40015", + "#FEFFFF", "#3C3F36", "#9FB03E", "#EBE9DC", "72918B", + "#CC6B32", "#FFAB48", "#FFE7AD", "#A7C9AE", "888A63", + "#262526", "#404040", "#8C8979", "#F2F2F2", "F60A20", + "#00305A", "#004B8D", "#0074D9", "#4192D9", "7ABAF2", + "#0C273D", "#54D0ED", "#FFFEF1", "#70B85D", "2C5E2E", + "#4C1B33", "#EFE672", "#98A942", "#2D6960", "141D14", + "#2F3540", "#666A73", "#F2EDE4", "#D9D1C7", "8C8681", + "#0D1F30", "#3B6670", "#8BADA3", "#F0E3C0", "DB6C0F", + "#FFBC67", "#DA727E", "#AC6C82", "#685C79", "455C7B", + "#092140", "#024959", "#F2C777", "#F24738", "BF2A2A", + "#133463", "#365FB7", "#799AE0", "#F4EFDC", "BA9B65", + "#C4D4CB", "#55665E", "#30282A", "#542733", "E84167", + "#CDDEC6", "#4DAAAB", "#1E4F6A", "#2A423C", "93A189", + "#EF5411", "#FA5B0F", "#FF6517", "#FF6D1F", "FF822E", + "#41434A", "#6E9489", "#DEDCC3", "#F2F1E9", "877963", + "#292929", "#2BBFBD", "#F2B33D", "#F29B30", "F22E2E", + "#F2385A", "#F5A503", "#E9F1DF", "#56D9CD", "3AA1BF", + "#D5F8B4", "#A6E3A8", "#8A9A85", "#7E566B", "422335", + "#3CBAC8", "#93EDD4", "#F3F5C4", "#F9CB8F", "F19181", + "#979926", "#38CCB5", "#EEFF8E", "#FFD767", "CC2A09", + "#404040", "#024959", "#037E8C", "#F2EFDC", "F24C27", + "#94B34D", "#D3FF82", "#363D52", "#121D2B", "111B1C", + "#282E33", "#25373A", "#164852", "#495E67", "FF3838", + "#313732", "#8AA8B0", "#DEDEDE", "#FFFFFF", "F26101", + "#FFFFFF", "#E5E1D1", "#52616D", "#2C343B", "C44741", + "#FFF6B8", "#ABCCA7", "#403529", "#7A5E2F", "A68236", + "#4F1025", "#C5003E", "#D9FF5B", "#78AA00", "15362D", + "#49404F", "#596166", "#D1FFCD", "#A9BD8B", "948A54", + "#FF2151", "#FF7729", "#FFAD29", "#FFEBCA", "1AB58A", + "#73603D", "#BF8A49", "#F2CA80", "#5E5A59", "0D0D0D", + "#3D4C53", "#70B7BA", "#F1433F", "#E7E1D4", "FFFFFF", + "#006D8D", "#008A6E", "#549E39", "#8AB833", "C0CF3A", + "#BDDFB3", "#2BAA9C", "#2F2E2E", "#0F2625", "465F3F", + "#F2F2F2", "#BF0404", "#8C0303", "#590202", "400101", + "#76A19A", "#272123", "#A68D60", "#B0C5BB", "D9593D", + "#0E3D59", "#88A61B", "#F29F05", "#F25C05", "D92525", + "#C1E1ED", "#76C7C6", "#273D3B", "#131A19", "E35C14", + "#2D112C", "#530031", "#820233", "#CA293E", "EF4339", + "#AF7575", "#EFD8A1", "#BCD693", "#AFD7DB", "3D9CA8", + "#D74B4B", "#DCDDD8", "#475F77", "#354B5E", "FFFFFF", + "#FFF6C9", "#C8E8C7", "#A4DEAB", "#85CC9F", "499E8D", + "#229396", "#8BA88F", "#C7C5A7", "#F0DFD0", "F23C3C", + "#57385C", "#A75265", "#EC7263", "#FEBE7E", "FFEDBC", + "#96526B", "#D17869", "#EBAD60", "#F5CF66", "8BAB8D", + "#0D1C33", "#17373C", "#2B6832", "#4F9300", "A1D700", + "#1B2B32", "#37646F", "#A3ABAF", "#E1E7E8", "B22E2F", + "#C5D9B2", "#53A194", "#572C2C", "#3D2324", "695A3B", + "#425957", "#81AC8B", "#F2E5A2", "#F89883", "D96666", + "#002E40", "#2A5769", "#FFFFFF", "#FABD4A", "FA9600", + "#FFFEFC", "#E2E3DF", "#515B5E", "#2E3233", "CAF200", + "#FFF0A3", "#B8CC6E", "#4B6000", "#E4F8FF", "004460", + "#3B596A", "#427676", "#3F9A82", "#A1CD73", "ECDB60", + "#F2E6CE", "#8AB39F", "#606362", "#593325", "1D1D1F", + "#212B40", "#C2E078", "#FFFFFF", "#BADCDD", "547B97", + "#0B3C4D", "#0E5066", "#136480", "#127899", "1A8BB3", + "#222130", "#464D57", "#D4E8D3", "#FFFCFB", "ED8917", + "#B33600", "#FF8A00", "#FFC887", "#CC5400", "B31E00", + "#012530", "#28544B", "#ACBD86", "#FFD6A0", "FF302C", + "#2E95A3", "#50B8B4", "#C6FFFA", "#E2FFA8", "D6E055", + "#112F41", "#068587", "#4FB99F", "#F2B134", "ED553B", + "#202B30", "#4E7178", "#4FA9B8", "#74C0CF", "F1F7E2", + "#302B2F", "#696153", "#FFA600", "#9BB58F", "FFD596", + "#458C6B", "#F2D8A7", "#D9A86C", "#D94436", "A62424", + "#22475E", "#75B08A", "#F0E797", "#FF9D84", "FF5460", + "#FFAA5C", "#DA727E", "#AC6C82", "#685C79", "455C7B", + "#686E75", "#9BAAC1", "#82787B", "#E4F1DB", "AAC19B", + "#F0C755", "#E2AD3B", "#BF5C00", "#901811", "5C110F", + "#FFFBDC", "#BFBCA5", "#7F7D6E", "#3F3E37", "E5E2C6", + "#BEBEBE", "#F1E4D8", "#594735", "#94C7BA", "D8F1E4", + "#1B1E26", "#F2EFBD", "#B6D051", "#70A99A", "2F6D7A", + "#F7E4A2", "#A7BD5B", "#DC574E", "#8DC7B8", "ED9355", + "#70E8CB", "#FFE9C7", "#FF5B5B", "#545454", "2D2D2F", + "#17111A", "#321433", "#660C47", "#B33467", "CCBB51", + "#2B2E2E", "#595855", "#A2ABA5", "#CAE6E8", "313F54", + "#023B47", "#295E52", "#F2E085", "#FCAB55", "EE7F38", + "#302C29", "#D1D1BC", "#A7C4BB", "#6C8C84", "466964", + "#212629", "#067778", "#49B8A8", "#85EDB6", "D9E5CD", + "#334D5C", "#45B29D", "#EFC94C", "#E27A3F", "DF4949", + "#2C3E50", "#FC4349", "#6DBCDB", "#D7DADB", "FFFFFF", + "#35262D", "#FFFBFF", "#E8ECED", "#A4B7BB", "76A0B0", + "#61E8D2", "#FCEEB9", "#302F25", "#704623", "BBE687", + "#E1E6B9", "#C4D7A4", "#ABC8A4", "#375D3B", "183128", + "#C98B2F", "#803C27", "#C56520", "#E1B41B", "807916", + "#A3D9B0", "#93BF9E", "#F2F0D5", "#8C8474", "40362E", + "#524656", "#CF4747", "#EA7A58", "#E4DCCB", "A6C4BC", + "#5C2849", "#A73E5C", "#EC4863", "#FFDA66", "1FCECB", + "#0EEAFF", "#15A9FA", "#1B76FF", "#1C3FFD", "2C1DFF", + "#010000", "#393845", "#9B96A3", "#5C0009", "940315", + "#468071", "#FFE87A", "#FFCA53", "#FF893B", "E62738", + "#404040", "#024959", "#037E8C", "#F2EFDC", "F24C27", + "#FF765E", "#C2AE8B", "#FCCF65", "#FFE5C6", "B7BDC4", + "#003647", "#00717D", "#F2D8A7", "#A4A66A", "515932", + "#FAFAC0", "#C4BE90", "#8C644C", "#594D37", "293033", + "#2B3A42", "#3F5765", "#BDD4DE", "#EFEFEF", "E74C3C", + "#3B3B3B", "#A8877E", "#FFA49D", "#FF7474", "FF476C", + "#0A3A4A", "#196674", "#33A6B2", "#9AC836", "D0E64B", + "#FFA340", "#38001C", "#571133", "#017A74", "00C2BA", + "#DCEBDD", "#A0D5D6", "#789AA1", "#304345", "AD9A27", + "#588C7E", "#F2E394", "#F2AE72", "#D96459", "8C4646", + "#F0E6B1", "#B5D6AA", "#99A37A", "#70584B", "3D3536", + "#2F400D", "#8CBF26", "#A8CA65", "#E8E5B0", "419184", + "#010712", "#13171F", "#1C1F26", "#24262D", "961227", + "#403F33", "#6E755F", "#AFC2AA", "#FFDEA1", "E64C10", + "#C74029", "#FAE8CD", "#128085", "#385052", "F0AD44", + "#CFF09E", "#A8DBA8", "#79BD9A", "#3B8686", "0B486B", + "#E0401C", "#E6B051", "#272F30", "#F7EDB7", "9E2B20", + "#FFE2C5", "#FFEEDD", "#FFDDAA", "#FFC484", "FFDD99", + "#FFFFE4", "#F2E5BD", "#B9BF8E", "#A69F7C", "8C6865", + "#5C8A2D", "#AFD687", "#FFFFFF", "#00C3A9", "008798", + "#4F3130", "#FF1F3D", "#5BE3E3", "#FDFFF1", "8B9698", + "#D23600", "#D95100", "#DE6D00", "#EE8900", "FCA600", + "#FFFFFA", "#A1A194", "#5B605F", "#464646", "FF6600", + "#F34A53", "#FAE3B4", "#AAC789", "#437356", "1E4147", + "#2A7A8C", "#176273", "#063540", "#E6D9CF", "403D3A", + "#21455B", "#567D8C", "#A59E8C", "#8C8372", "F2F2F2", + "#012340", "#026873", "#83A603", "#BBBF45", "F2F0CE", + "#FDFF98", "#A7DB9E", "#211426", "#6B073B", "DA8C25", + "#002F36", "#142426", "#D1B748", "#EDDB43", "FFFD84", + "#420000", "#600000", "#790000", "#931111", "BF1616", + "#3C989E", "#5DB5A4", "#F4CDA5", "#F57A82", "ED5276", + "#23A38F", "#B7C11E", "#EFF1C2", "#F0563D", "2E313D", + "#F5ECD9", "#2BACB5", "#B4CCB9", "#E84D5B", "3B3B3B", + "#A5EB3C", "#60C21E", "#159E31", "#53DB50", "C5FFCB", + "#263138", "#406155", "#7C9C71", "#DBC297", "FF5755", + "#0A111F", "#263248", "#7E8AA2", "#E3E3E3", "C73226", + "#003B59", "#00996D", "#A5D900", "#F2E926", "FF930E", + "#00A19A", "#04BF9D", "#F2E85C", "#F53D54", "404040", + "#324152", "#47535E", "#796466", "#C1836A", "DEA677", + "#036F73", "#84CDC2", "#FEF2D8", "#F18C79", "EF504F", + "#174040", "#888C65", "#D9CA9C", "#D98162", "A65858", + "#56797F", "#87A0A4", "#FCFBDC", "#F2DDB6", "A6937C", + "#A8BAA9", "#FFF5CF", "#DBCDAD", "#B39C7D", "806854", + "#60655F", "#AB9675", "#FFE0C9", "#D4CCBA", "CF8442", + "#BDDFB3", "#009D57", "#2C372E", "#0F2925", "465F3F", + "#3E3947", "#735360", "#D68684", "#F1B0B0", "EBD0C4", + "#0A7B83", "#2AA876", "#FFD265", "#F19C65", "CE4D45", + "#FFFFFF", "#F4921E", "#858585", "#C5D2DB", "3E6B85", + "#11151E", "#212426", "#727564", "#B9AA81", "690C07", + "#000000", "#910000", "#CBB370", "#FFFBF1", "21786C", + "#F78F00", "#C43911", "#75003C", "#37154A", "0F2459", + "#003354", "#91BED4", "#D9E8F5", "#FFFFFF", "F26101", + "#3DA8A4", "#7ACCBE", "#FFFFF7", "#FF99A1", "FF5879", + "#64C733", "#F0F0F0", "#3E879E", "#57524D", "36302B", + "#343844", "#2AB69D", "#E65848", "#FDC536", "FCF2D7", + "#E34517", "#F5FF53", "#B4E85E", "#00BD72", "0B4239", + "#A84B3A", "#FF9F67", "#233138", "#FFF7F5", "4C646B", + "#59535E", "#FAEEFF", "#F1BAF3", "#5D4970", "372049", + "#FF6F22", "#D9984F", "#FFE8A9", "#3E4237", "32948A", + "#5D7370", "#7FA6A1", "#B8D9B8", "#D6EDBD", "FFF5BC", + "#FFBE00", "#FFDC00", "#FFD10F", "#FFDE20", "E8CA00", + "#003840", "#005A5B", "#007369", "#008C72", "02A676", + "#E1E6FA", "#C4D7ED", "#ABC8E2", "#375D81", "183152", + "#BA2F1D", "#FFF8A4", "#F5E67F", "#264A59", "1E2C30", + "#222526", "#FFBB6E", "#F28D00", "#D94F00", "80203B", + "#EBD096", "#D1B882", "#5D8A66", "#1A6566", "21445B", + "#F00807", "#5F6273", "#A4ABBF", "#CCC9D1", "E2E1E9", + "#DFE0AF", "#A4BAA2", "#569492", "#41505E", "383245", + "#152737", "#2B4E69", "#799AA5", "#FFFFF0", "682321", + "#C44C51", "#FFB6B8", "#FFEFB6", "#A2B5BF", "5F8CA3", + "#5ADED4", "#4DAAAB", "#26596A", "#163342", "6C98A1", + "#FF5B2B", "#B1221C", "#34393E", "#8CC6D7", "FFDA8C", + "#3D4D4D", "#99992E", "#E6E666", "#F2FFBF", "800033", + "#242424", "#437346", "#97D95C", "#D9FF77", "E9EB9B", + "#FFEBB0", "#FFB05A", "#F84322", "#C33A1A", "9F3818", + "#4D2B2F", "#E57152", "#E8DE67", "#FFEFC3", "C0CCAB", + "#A82221", "#DB5E31", "#EDA23E", "#F2CB67", "BFB840", + "#3B3140", "#BFB8A3", "#F2E0C9", "#F2B9AC", "D97E7E", + "#43464D", "#9197A6", "#D3DCF2", "#7690CF", "48577D", + "#EFDFBB", "#9EBEA6", "#335D6A", "#D64F2A", "7A8A7F", + "#000001", "#313634", "#C7CECF", "#5C0402", "941515", + "#334D5C", "#45B29D", "#EFC94C", "#E27A3F", "DF5A49", + "#F5F4E1", "#D6C9B5", "#B4AA97", "#D44917", "82877A", + "#19162B", "#1C425C", "#6ABDC4", "#F0E4C5", "D6C28F", + "#00132B", "#7F9DB0", "#C5E2ED", "#FFFFFF", "F95900", + "#1F3642", "#6D968D", "#B6CCB8", "#FFE2B3", "56493F", + "#08A689", "#82BF56", "#C7D93D", "#E9F2A0", "F2F2F2", + "#DE3961", "#A4E670", "#FFFFDC", "#B3EECC", "00ADA7", + "#849972", "#D9D094", "#A6A23E", "#4F2F1D", "8F5145", + "#F41C54", "#FF9F00", "#FBD506", "#A8BF12", "00AAB5", + "#00585F", "#009393", "#F5F3DC", "#454445", "FF5828", + "#FF6138", "#FFFF9D", "#BEEB9F", "#79BD8F", "00A388", + "#140B04", "#332312", "#B59D75", "#E3D2B4", "FFF7EA", + "#ED3B3B", "#171F26", "#77B59C", "#F2E7B1", "635656", + "#46594B", "#A6977C", "#D9B384", "#734F30", "260B01", + "#CCB8A3", "#FF8FB1", "#FFF5EA", "#4E382F", "B29882", + "#B70000", "#FFFFFF", "#FFCA3D", "#94C4F4", "0092B3", + "#053B44", "#06736C", "#A53539", "#B9543C", "EAD075", + "#E8C1B9", "#FFB3AB", "#FFCAB8", "#E8B69C", "FFCEAB", + "#E7F2DF", "#69043B", "#59023B", "#231E2D", "161726", + "#E82B1E", "#E5DEAF", "#A0B688", "#557A66", "453625", + "#F1E6D4", "#BA3D49", "#791F33", "#9F9694", "E3E1DC", + "#CED59F", "#F1EDC0", "#B1BEA4", "#647168", "282828", + "#2C3E50", "#E74C3C", "#ECF0F1", "#3498DB", "646464", + "#DE7047", "#FFDE8D", "#FFFFFF", "#CDDE47", "528540", + "#8EAB99", "#40232B", "#D95829", "#D97338", "DEC085", + "#E9662C", "#EBAF3C", "#00AC65", "#068894", "2B2B2B", + "#46483C", "#A0AA8F", "#EBE3CB", "#FFFFFF", "F26101", + "#170F0E", "#290418", "#505217", "#FFD372", "FFF1AF", + "#263545", "#C4273C", "#D7DADB", "#6DBCDB", "FFFFFF", + "#DCFAC0", "#B1E1AE", "#85C79C", "#56AE8B", "00968B", + "#075807", "#097609", "#70AF1A", "#B9D40B", "E5EB0B", + "#521000", "#712800", "#744E1D", "#879666", "F1D98C", + "#261F26", "#3F3B40", "#6C7367", "#BFBF8A", "F2E086", + "#2C3E50", "#FC4349", "#D7DADB", "#6DBCDB", "FFFFFF", + "#506D7D", "#94CCB9", "#FFECA7", "#FFB170", "F07D65", + "#3F4036", "#8DA681", "#F2E1C2", "#BF2806", "8C1D04", + "#990700", "#CC542E", "#FF964F", "#FFCB7C", "787730", + "#195073", "#7F8C1F", "#EE913F", "#F2E5BD", "9FD7C7", + "#1B3E59", "#F2F0F0", "#FFAC00", "#BF0404", "730202", + "#EA6045", "#F8CA4D", "#F5E5C0", "#3F5666", "2F3440", + "#F95759", "#FDA099", "#FFFFFF", "#D9F3CB", "8AC2B0", + "#265573", "#386D73", "#81A68A", "#9FBF8F", "D4D9B0", + "#E1DA36", "#FFEA1B", "#6FE4DA", "#1DB0BC", "007BBC", + "#013859", "#185E65", "#F9CC7F", "#F15C25", "9E1617", + "#36CC7C", "#D6FFBE", "#94D794", "#228765", "77A668", + "#94201F", "#D4421F", "#478A80", "#D9E061", "F08835", + "#F16233", "#00B5B5", "#F0F0F0", "#3E4651", "5C6D7E", + "#2E806C", "#76CC99", "#E0FFED", "#FF5F3A", "D2413C", + "#00393B", "#00766C", "#44A18E", "#E5EDB6", "F6695B", + "#734854", "#F2F2E9", "#D9D7C5", "#A69580", "736766", + "#03497E", "#0596D5", "#9DEBFC", "#8D7754", "FEB228", + "#F0E14C", "#FFBB20", "#FA7B12", "#E85305", "59CC0D", + "#FE4365", "#FC9D9A", "#F9CDAD", "#C8C8A9", "83AF9B", + "#00557C", "#186D94", "#3488AD", "#81C1DC", "BBE5F3", + "#DEE8D7", "#918773", "#420A1A", "#240001", "4D493A", + "#FFFFFF", "#CAC535", "#97AF25", "#158471", "41342C", + "#041F3D", "#0B2E41", "#165751", "#448C61", "9AC16D", + "#FA8C01", "#FF6405", "#577700", "#082400", "A0A600", + "#78C0F9", "#FFDDCE", "#FFFFFF", "#FFDBE6", "FE86A4", + "#351330", "#CC2A41", "#E7CAA4", "#759A8A", "524549", + "#02151A", "#043A47", "#087891", "#C8C8C8", "B31D14", + "#F34A53", "#FAE3B4", "#AAC789", "#437356", "1E4147", + "#58838C", "#DAD7C7", "#BF996B", "#BF5841", "A61C1C", + "#556354", "#E68F0D", "#8C948A", "#495450", "42423F", + "#323640", "#5B6470", "#8C94A1", "#BDC7D6", "DFE2FF", + "#FF0000", "#FF950B", "#2FA88C", "#DEEB00", "4B2C04", + "#0F3D48", "#174C5B", "#366774", "#ECECE7", "E96151", + "#3DBB7E", "#A3CD39", "#FBAC1D", "#F96C1E", "EE4036", + "#23363B", "#A44F3F", "#F8983D", "#8D9151", "BBC946", + "#4B5657", "#969481", "#D2C9B0", "#F4E3C1", "B6B835", + "#E8980C", "#B1F543", "#F2FF00", "#FF5E00", "59BBAB", + "#849696", "#FEFFFB", "#232D33", "#17384D", "FF972C", + "#555555", "#7BB38E", "#F4F1D7", "#F8AB65", "F15C4C", + "#1D3C42", "#67BFAD", "#F2EC99", "#F2C48D", "F25050", + "#334D5C", "#45B29D", "#EFC94C", "#E27A3F", "DF4949", + "#B8E1F2", "#249AA7", "#ABD25E", "#F8C830", "F1594A", + "#FDEDD0", "#BCF1ED", "#FF634D", "#FD795B", "FFF0AA", + "#FFFFFF", "#E5E1D1", "#52616D", "#2C343B", "C44741", + "#FFFFF1", "#D5FF9B", "#8FB87F", "#5A7B6C", "374E5A", + "#010340", "#0E1E8C", "#0003C7", "#1510F0", "1441F7", + "#002A4A", "#17607D", "#FFF1CE", "#FF9311", "E33200", + "#871E31", "#CCC097", "#9E9D7B", "#687061", "262626", + "#F16663", "#F48D6C", "#F2E07B", "#8ABE9B", "4A6D8B", + "#001F11", "#204709", "#0C8558", "#FFD96A", "FF4533", + "#1D1626", "#F2E0BD", "#BFAA8F", "#8C786C", "594C4C", + "#685D47", "#913420", "#1E2729", "#C1D9C5", "FEEFB1", + "#1D7561", "#FC8448", "#FF4138", "#A8282B", "38141B", + "#BF0633", "#FF484E", "#FF9273", "#D1D0B4", "E5ECED", + "#8E9E63", "#E6DBB0", "#F5EED7", "#C4BCA0", "176573", + "#665446", "#809994", "#AECCB6", "#DEF2C4", "E6683F", + "#3D0D26", "#660A3E", "#891C56", "#B0276F", "C93482", + "#082136", "#00294D", "#004B8D", "#0068C4", "2998FF", + "#3C4631", "#9A746F", "#F8A2AB", "#F1C6B3", "EAE9C0", + "#FF534E", "#FFD7AC", "#BED194", "#499989", "176785", + "#006D80", "#BDA44D", "#3C2000", "#84CECC", "78A419", + "#352C2B", "#3C555C", "#9E9657", "#FFEBCD", "CD5510", + "#2C3E50", "#FC4349", "#6DBCDB", "#D7DADB", "FFFFFF", + "#523631", "#D1BE91", "#605E3A", "#4D462F", "592F39", + "#18293B", "#5B5A56", "#F2DEA0", "#D0B580", "FFFBFF", + "#C8DBB6", "#ECEBB7", "#CCC68A", "#B8B165", "827A5D ", + "#7DA88C", "#EBE9A0", "#BED24B", "#859132", "35323C", + "#E8574C", "#F27B29", "#E6A51B", "#D9CC3C", "399977", + "#324032", "#B7C22C", "#FFFFE1", "#22A8B5", "2A3F42", + "#B3A589", "#FFB896", "#FFF9B1", "#9AB385", "11929E", + "#272433", "#343F4F", "#3D6066", "#77994D", "B2D249", + "#250701", "#6D4320", "#B0925F", "#E7DEC0", "82ABB8", + "#023550", "#028A9E", "#04BFBF", "#EFEFEF", "FF530D", + "#594732", "#40342A", "#7A422E", "#D4CA9A", "EDE5AE", + "#013C4D", "#BA5B22", "#DB913C", "#F0B650", "FAD46B", + "#143840", "#5C6B63", "#A69E89", "#E0C297", "D96523", + "#3FB8AF", "#7FC7AF", "#DAD8A7", "#FFB38B", "FF3F34", + "#CA3995", "#F58220", "#FFDF05", "#BED73D", "61BC46", + "#FFE1D0", "#FFBFB4", "#FF837E", "#FF4242", "BF1616", + "#C4EEFF", "#7BA32D", "#094201", "#A41717", "C48726", + "#001325", "#187072", "#90BD90", "#D7D8A2", "F2E4C2", + "#1A4F63", "#068587", "#6FB07F", "#FCB03C", "FC5B3F", + "#97B350", "#333230", "#736D61", "#BAAB90", "FFE5BA", + "#403D33", "#807966", "#CCC2A3", "#8C0000", "590000", + "#5F8A42", "#86AD59", "#F6FAA1", "#F28410", "D66011", + "#BF355D", "#ED8168", "#FAB66A", "#F2DC86", "83BFA1", + "#E1F03E", "#FFBA14", "#DB3A0F", "#A1003D", "630024", + "#212226", "#45433F", "#687067", "#BDBB99", "F0EAC3", + "#FE4365", "#FC9D9A", "#F9CDAD", "#C8C8A9", "83AF9B", + "#293B47", "#5F7A87", "#FFFFFF", "#CBFF48", "00ADA9", + "#282A33", "#697371", "#FFE7A6", "#F5BA52", "FA8000", + "#0C304A", "#2B79A1", "#F3F4F1", "#85A71E", "BFD841", + "#008B83", "#4DAE83", "#A0AE79", "#FFE499", "FF665E", + "#5D7359", "#E0D697", "#D6AA5C", "#8C5430", "661C0E", + "#324452", "#97BDBF", "#F2DFBB", "#F28705", "BF3604", + "#EEEFB9", "#6ACFAE", "#369C93", "#232928", "B03831", + "#332F45", "#015770", "#2A8782", "#9FD6AE", "FFFED2", + "#2B2830", "#5C504F", "#ABAB8E", "#D9D7A3", "C7BE88", + "#DC941B", "#EDC266", "#B6952C", "#E1D3A6", "E9A119", + "#00305A", "#00448D", "#0074D9", "#4192D9", "7ABAF2", + "#344459", "#485F73", "#5DA6A6", "#A9D9CB", "F2EAD0", + "#060719", "#4D1B2F", "#9E332E", "#EB6528", "FC9D1C", + "#96CEB4", "#FFEEAD", "#FF6F69", "#FFCC5C", "AAD8B0", + "#05F2F2", "#04BFBF", "#EEF1D9", "#A60201", "7E100E", + "#E6F1F5", "#636769", "#AAB3B6", "#6E7476", "4B4E50", + "#DA0734", "#F1A20D", "#4AABB1", "#FCF3E7", "3F1833", + "#202D44", "#FC4349", "#6DBCDB", "#D7DADB", "FFFFFF", + "#CC3B37", "#398899", "#FFFCE8", "#FF857F", "CCC1A3", + "#5DBEA9", "#EFEDDF", "#EF7247", "#4E3F35", "D1CBBA", + "#FFC62D", "#E49400", "#DD5200", "#EFE38A", "91B166", + "#B67D14", "#F2921F", "#F0B23E", "#A62409", "441208", + "#C71B1B", "#D6BA8A", "#017467", "#E08F23", "0B0D0C", + "#474143", "#A69E9D", "#E7E2DA", "#FFFFFF", "E7E8E7", + "#435772", "#2DA4A8", "#FEAA3A", "#FD6041", "CF2257", + "#6DD19D", "#99E89D", "#D0E8A1", "#FFF9C0", "D40049", + "#FAF1D5", "#DEC9AC", "#CCA18B", "#11282D", "A5C4BB", + "#000000", "#141414", "#1C1919", "#1A1716", "24201F", + "#D5D8DD", "#5CA2BE", "#135487", "#2A4353", "989DA4", + "#73161E", "#BF0F30", "#BFB093", "#037F8C", "0A2140", + "#195962", "#F56F6C", "#FFFFFF", "#252932", "191C21", + "#F8EFB6", "#FEBAC5", "#6CD1EA", "#FACFD7", "C2EAE9", + "#91D6BC", "#768C6A", "#755F31", "#B37215", "FFBA4B", + "#F2E6BB", "#DD4225", "#202724", "#63BD99", "F8FDD8", + "#762B1B", "#807227", "#CCBF7A", "#FFEF98", "60B0A1", + "#707864", "#C1D74E", "#F5FF7C", "#DFE6B4", "A6B89C", + "#FFF3D2", "#97B48F", "#E87657", "#FF9B6F", "E8D495", + "#33262E", "#733230", "#CC5539", "#E6D27F", "86A677", + "#122430", "#273E45", "#FFFCE2", "#EBD2B5", "E63531", + "#30394F", "#FF434C", "#6ACEEB", "#EDE8DF", "FFFBED", + "#0A3A4A", "#196A73", "#32A6A6", "#A1BF36", "C8D94A", + "#FFF7CC", "#CCC28F", "#70995C", "#33664D", "142933", + "#43464D", "#9197A6", "#D3DCF2", "#7690CF", "48577D", + "#DFE0AF", "#A4BAA2", "#569492", "#41505E", "383245", + "#B52841", "#FFC051", "#FF8939", "#E85F4D", "590051", + "#473C35", "#A36D5C", "#9C968B", "#D9CEAD", "8A866A", + "#DB4C39", "#2D3638", "#109489", "#44D487", "D0DB86", + "#6F8787", "#AEC2AE", "#E6DFAE", "#B0B57B", "888F51", + "#C8385A", "#FFCF48", "#ECEABE", "#1FCECB", "1CA9C9", + "#42282E", "#75A48B", "#D9CFB0", "#DC9B74", "D6665A", + "#362F2D", "#4C4C4C", "#94B73E", "#B5C0AF", "FAFDF2", + "#98293A", "#B14A58", "#C86C6B", "#DE9D76", "EFC77F", + "#C1D301", "#76AB01", "#0E6A00", "#083500", "042200", + "#453F22", "#7A6B26", "#CCAD5C", "#A1191F", "4E1716", + "#541E32", "#8E3557", "#88A33E", "#C2BD86", "F7F2B2", + "#2B1B2E", "#54344D", "#FFFFD6", "#B89E95", "6E444F", + "#6EC1A5", "#9FBEA6", "#F5D3A3", "#FF9F88", "FB7878", + "#2F252C", "#D3CCB2", "#99AD93", "#6E6751", "5C3122", + "#BE333F", "#F2E9CE", "#C8C5B1", "#939F88", "307360", + "#F0F1F2", "#232625", "#647362", "#B3D929", "D2D9B8", + "#FA2B31", "#FFBF1F", "#FFF146", "#ABE319", "00C481", + "#09455C", "#527E7C", "#F5FFCC", "#E0EB6E", "C4D224", + "#F2DA91", "#F2B950", "#F29D35", "#D96704", "BF4904", + "#A2CFA5", "#E0E7AB", "#F5974E", "#E96B56", "D24344", + "#150033", "#310D42", "#5C2445", "#AB6946", "FFCE4C", + "#23A38F", "#B7C11E", "#EFF1C2", "#F0563D", "2E313D", + "#FF2468", "#E0D4B1", "#FFFFE3", "#00A5A6", "005B63", + "#65A683", "#218777", "#3F585F", "#47384D", "F53357", + "#000623", "#28475C", "#4A6C74", "#8BA693", "F0E3C0", + "#E65322", "#D19552", "#B8BF73", "#B6DB83", "FFF991", + "#112F41", "#068587", "#6FB07F", "#FCB03C", "FC5B3F", + "#C89B41", "#A16B2B", "#77312B", "#1C2331", "152C52", + "#C24366", "#D9C099", "#FFF8D8", "#A8E0BA", "00ADA7", + "#CC0000", "#006600", "#FFFFEC", "#9C9178", "6C644F", + "#3D0319", "#720435", "#C1140E", "#FC5008", "32241B", + "#CFC7A4", "#5A9E94", "#005275", "#002344", "A38650", + "#FFEBC3", "#CC3A00", "#FF3600", "#FF851B", "800C00", + "#EFC164", "#F3835D", "#F35955", "#286275", "00434C", + "#E9F29D", "#B7C29D", "#878E8F", "#67617A", "51456B", + "#445859", "#03A696", "#49C4BE", "#F1F2E4", "FF7746", + "#FA726C", "#FFD794", "#BAD174", "#3BA686", "5F6F8C", + "#4D2B1F", "#635D61", "#7992A2", "#97BFD5", "BFDCF5", + "#CC4D00", "#E6CF73", "#668059", "#264D4D", "00CCB3", + "#4385F5", "#DC4437", "#FCBE1F", "#109D59", "FFFFFF", + "#271F2E", "#A4A680", "#F2EBC9", "#D9B166", "A66B38", + "#0B2C3C", "#FF6666", "#DADFE1", "#FFFFFF", "444444", + "#CFF09E", "#A8DBA8", "#79BD9A", "#3B8686", "0B486B", + "#302B26", "#A6B827", "#EDE9DD", "#98D3D4", "594E7A", + "#4B0505", "#720707", "#BFB694", "#004659", "00292B", + "#B52C38", "#EBD1B0", "#536682", "#D9964B", "DE6846", + "#F2F1DF", "#F2B705", "#F2C84B", "#BF820F", "734002", + "#26140C", "#3D2216", "#784E3D", "#AB8574", "D6BCB1", + "#26221D", "#8C2C0F", "#E6E5B8", "#BFB38D", "402D1F", + "#1F8181", "#F2BC79", "#F28972", "#BF1B39", "730240", + "#002635", "#013440", "#AB1A25", "#D97925", "EFE7BE", + "#8EC447", "#FFFFFF", "#96D3D4", "#636466", "2D2D2E", + "#2D1E1E", "#4B3C37", "#96A576", "#CDE196", "FFFFBE", + "#F06060", "#FA987D", "#F7F2CB", "#72CCA7", "10A296", + "#1D8281", "#44BF87", "#FBD258", "#F29A3F", "DB634F", + "#DEDE91", "#EF9950", "#F34E52", "#C91452", "492449", + "#6D8EAD", "#1F3447", "#1A0B07", "#362416", "CFCDB4", + "#00CD73", "#008148", "#2D9668", "#3ECD8E", "004E2C", + "#3D8080", "#628282", "#858383", "#A38282", "C28080", + "#475159", "#839795", "#B2BDB7", "#CCC9C0", "F2F2F2", + "#0E6870", "#C6B599", "#C65453", "#FFDDB4", "EDAA7D", + "#CEF0B7", "#A8DBA8", "#79BD9A", "#3B8686", "0B486B", + "#292C44", "#FF5349", "#F0F0F1", "#18CDCA", "4F80E1", + "#272A2B", "#383737", "#473B39", "#692B28", "940500", + "#D6C274", "#DB9E46", "#25706B", "#3D2423", "AB362E", + "#FFA68F", "#FF4867", "#FFF9C8", "#B5EBB9", "18B29D", + "#A1A16A", "#727D59", "#366353", "#133C40", "03212E", + "#D45354", "#A9DC3A", "#2FCAD8", "#818B85", "CDCDC1", + "#F14B6A", "#3D3C3E", "#22BDAF", "#BAD7D4", "F4F4F4", + "#FFE2C5", "#FFEEDD", "#FFDDAA", "#FFC484", "FFDD99", + "#9FFF4A", "#1ABF93", "#087363", "#004040", "2F1933", + "#FFDB97", "#B28F4E", "#FFFDFB", "#466CB2", "97BBFF", + "#991C00", "#E09A25", "#FFFCDB", "#008B83", "262B30", + "#44281A", "#00ACAE", "#F5EFD5", "#F37606", "EE4717", + "#FF5952", "#FCEEC9", "#96D6D9", "#4FAAC9", "176075", + "#5C4B51", "#8CBEB2", "#F2EBBF", "#A5C88F", "EF847B", + "#105F73", "#F7F3B2", "#C6CC33", "#F28322", "CC5404", + "#137072", "#56B292", "#B7F5AB", "#FBFFC0", "BF223D", + "#E3F23E", "#6C821C", "#A6A53F", "#E0E0AC", "33302E", + "#00215E", "#003CAA", "#1967F7", "#5E4000", "AA7400", + "#273A3D", "#54695C", "#AD9970", "#FFBF87", "FF8F60", + "#FFAA00", "#C2B93E", "#808F5D", "#576157", "302F30", + "#BE1405", "#F2DCAC", "#AABEAA", "#736E41", "413C2D", + "#6B1229", "#C76A61", "#FAB99A", "#F7D9B5", "CCB1A7", + "#2D9993", "#58B3A3", "#83BFA3", "#B0D9A8", "FFFCB6", + "#334D5C", "#45B29D", "#EFC94C", "#E27A3F", "DF5A49", + "#F30B55", "#010326", "#012840", "#54717F", "F2E6CE", + "#2A3411", "#73662C", "#BC9847", "#FFDFB2", "6B0031", + "#637D74", "#403D3A", "#8C3B3B", "#AB6937", "D4A960", + "#010A26", "#011640", "#B6D6F2", "#FFFFFF", "E83338", + "#924847", "#EB986C", "#E4C678", "#9C7885", "372C2C", + "#022440", "#3F95AA", "#4EC6DE", "#EAE2DF", "F7572F", + "#2B1D2E", "#323657", "#076473", "#54B087", "D6F567", + "#052229", "#004043", "#BCC373", "#E3FF55", "D0D90C", + "#4C514A", "#907A62", "#879796", "#755854", "B09880", + "#1D2939", "#1CAF9A", "#FFFFFF", "#EE4F4B", "D1DC48", + "#004B67", "#41CCB4", "#FFEA95", "#FF7C5D", "C70151", + "#C0272D", "#FCFBE7", "#9FD3DA", "#008C9A", "05484F", + "#213130", "#FF5E3D", "#C9C83E", "#FDFFF1", "559398", + "#B1E4FC", "#366D78", "#39D5F1", "#FFFFFF", "D9FF03", + "#DECE6C", "#FCF9B6", "#BFE3B5", "#5D826E", "262E2B", + "#520A17", "#668F91", "#F5E6AC", "#AB8E5B", "52301C", + "#2D3032", "#DD5F18", "#FBA922", "#F7F7F7", "404333", + "#0C2538", "#2B434F", "#638270", "#BCC98E", "EDE059", + "#E85066", "#F28E76", "#E6CEB0", "#5A8C81", "382837", + "#BF2633", "#A6242F", "#D9CEAD", "#C0B18F", "011C26", + "#002A4A", "#17607D", "#FFF1CE", "#FF9311", "E33200", + "#0A8B91", "#485956", "#C4B98F", "#FFF9BC", "EEDF2E", + "#B89A7B", "#9BBAAC", "#F2D649", "#D95D50", "DBDBDB", + "#BD7938", "#8D4421", "#643001", "#532700", "3A1C00", + "#E1E6FA", "#C4D7ED", "#ABC8E2", "#375D81", "183152", + "#2E4259", "#F7483B", "#ECF0F1", "#03C8FA", "737373", + "#364656", "#5D6B74", "#94A4A5", "#F2F5E9", "FF8C31", + "#3E5916", "#93A605", "#F28705", "#F25C05", "E5EFFA", + "#248077", "#74AD8D", "#C82754", "#F7BB21", "F9E2B7", + "#20736A", "#8BD9CA", "#B1D95B", "#93A651", "403E34", + "#D74B4B", "#DCDDD8", "#475F77", "#354B5E", "FFFFFF", + "#252F33", "#415C4F", "#869C80", "#93C2CC", "CEEAEE", + "#012840", "#79C7D9", "#9BF2EA", "#497358", "9DBF8E", + "#EE7E94", "#F8B4C4", "#C7CAC9", "#D8505C", "41424", + "#282828", "#505050", "#FFFFFF", "#2DCEDB", "F20000", + "#004358", "#1F8A70", "#BEDB39", "#FF5347", "FD7400", + "#470C3B", "#802F56", "#C0576F", "#E38679", "FFBD83", + "#573328", "#B05A3A", "#FF8548", "#29332E", "0F1B1C", + "#461F2D", "#E1FFBB", "#BAD47F", "#849C23", "52533F", + "#333A40", "#4C5E5E", "#ADD0E5", "#CDE4FF", "729EBF", + "#DE5605", "#F7A035", "#B1DEB5", "#EFECCA", "65ABA6", + "#76D6D2", "#F9E270", "#EF6F56", "#F4EED8", "596B56", + "#403E3F", "#F2F2F2", "#D9D9D9", "#9DAABB", "8C8C8C", + "#059E9A", "#F4F2ED", "#F5A243", "#DB3E3B", "585857", + "#FFBF41", "#EE8943", "#C02221", "#FFF4D3", "249CA9", + "#024E76", "#39A6B2", "#FCE138", "#F5B824", "F08106", + "#FF0067", "#FF3D6A", "#E7FF04", "#9CFF00", "56FF00", + "#003540", "#0D3F40", "#487360", "#8FA671", "F2D795", + "#FF493C", "#FFFFFF", "#B3ECEF", "#31C4F5", "ADEB41", + "#244358", "#4A8B87", "#7CBCAE", "#F0D4AF", "C5252B", + "#EA5930", "#F8AF1E", "#F5E5C0", "#097380", "372560", + "#A1DBB2", "#FEE5AD", "#FACA66", "#F7A541", "F45D4C", + "#2C4A47", "#6C9A7F", "#BB523D", "#C89D11", "81810B", + "#F0F1F2", "#232625", "#647362", "#FF5629", "D2D9B8", + "#7C9B5F", "#B8D197", "#E3FFF3", "#9BDEC7", "568F84", + "#E54E45", "#DBC390", "#F2F2EF", "#13A3A5", "403833", + "#77A7FB", "#E57368", "#FBCB43", "#34B67A", "FFFFFF", + "#001A2E", "#8F0000", "#FFFFFF", "#8A874B", "41594F", + "#312F40", "#49A69C", "#EFEAC5", "#E89063", "BF5656", + "#047C8C", "#018B8D", "#F3BF81", "#F49B78", "F1706D", + "#00303E", "#7096AD", "#C1D1DE", "#FFF9EF", "EC4911", + "#2D6891", "#70A0BF", "#F5EEDC", "#DC4C1A", "F0986C", + "#040002", "#3D1309", "#E8B96A", "#BC5D15", "5C0F00", + "#8B929C", "#5E6070", "#514454", "#3B313D", "FF2479", + "#142D58", "#447F6E", "#E1B65B", "#C8782A", "9E3E17", + "#22104D", "#2D1E5E", "#483A85", "#7067AB", "A49CFA", + "#919C86", "#9E373E", "#2B2E36", "#D1B993", "C45A3B", + "#332F45", "#015770", "#2A8782", "#9FD6AE", "FFFED2", + "#37C78F", "#FEE293", "#FF4D38", "#CC2249", "380C2A", + "#47282C", "#8C8468", "#C9B37F", "#DBDAB7", "C4C49C", + "#14191A", "#2D2B21", "#A69055", "#CCB287", "FFB88C", + "#F5E3CD", "#696158", "#B6A898", "#877D71", "504A43", + "#005151", "#009393", "#F56200", "#454445", "969692", + "#D95F47", "#FFF2C1", "#80A894", "#106153", "072C36", + "#9E352C", "#E6E8A9", "#93C28C", "#2E5A5C", "2B2623", + "#03013A", "#334A94", "#6B9EDF", "#83C3F2", "99E6FF", + "#372A26", "#4D4D4D", "#6DA0A7", "#9ED5A8", "C7F5FF", + "#03658C", "#022E40", "#F2B705", "#F28705", "F25C05", + "#FF3B16", "#E87826", "#E8BA4A", "#80A272", "003045", + "#00748E", "#E3DFBB", "#F4BA4D", "#E3753C", "DA3B3A", + "#25401E", "#56732C", "#84A63C", "#B8D943", "EAF2AC", + "#449BB5", "#043D5D", "#EB5055", "#68C39F", "FFFCF5", + "#108F97", "#FF8B6B", "#FFE39F", "#16866D", "103636", + "#1A4F63", "#068F86", "#6FD57F", "#FCB03C", "FC5B3F", + "#381C19", "#472E29", "#948658", "#F0E99A", "362E29", + "#D7E8F7", "#BBD0E3", "#9CB7CF", "#6A8BAB", "375D81", + "#0F1C28", "#136972", "#67BFA7", "#F3CF5B", "F07444", + "#FFFFFF", "#4EA9A0", "#969514", "#FE9C03", "FCDE8E", + "#2F2D30", "#656566", "#65537A", "#51386E", "2A2333", + "#4C2916", "#F05A28", "#FBAF3F", "#38B449", "FFFFFF", + "#132537", "#006C80", "#EBCAB8", "#FE8315", "FA3113", + "#ECEEE1", "#A8DACF", "#F05B4F", "#D8403A", "221E1F", + "#00305A", "#004B8C", "#0074D9", "#4192D9", "7ABAF2", + "#72CF3F", "#85FF00", "#23E000", "#2FB81B", "00FF1C", + "#45CEEF", "#FFF5A5", "#FFD4DA", "#99D2E4", "D8CAB4", + "#FF5B00", "#A1716C", "#728296", "#439AAB", "00CABD", + "#EB6C2D", "#D9C8A2", "#939C80", "#496158", "232F38", + "#D94214", "#FFF2C1", "#80A894", "#52736B", "093844", + "#4D1B2F", "#9E332E", "#EB6528", "#FC9D1C", "FFCA50", + "#FFEEB0", "#9AE8A4", "#C7C12D", "#F76245", "ED1C43", + "#FFFAED", "#D4DBFF", "#879AC9", "#242942", "FF8800", + "#022840", "#013440", "#517360", "#9DA67C", "F2DC99", + "#331A0F", "#519994", "#BA4B3C", "#EEDDAA", "789F63", + "#577867", "#EDCE82", "#D68644", "#AB3229", "662845", + "#435A66", "#88A6AF", "#F5F2EB", "#D9CDB8", "424342", + "#FF8840", "#958D4F", "#737B55", "#595540", "513E38", + "#9D805A", "#EBC99D", "#FFE6C5", "#9DCEEA", "4B809E", + "#272D40", "#364659", "#55736D", "#9DBF8E", "D0D991", + "#23A38F", "#B7C11E", "#EFF1C2", "#F0563D", "2E313D", + "#98C000", "#3D4C53", "#EA2E49", "#FFE11A", "0CDBE8", + "#A20E30", "#E93C4F", "#DCDCD4", "#ADBCC3", "2D4255", + "#1C2640", "#263357", "#384C80", "#4E6AB3", "5979CD", + "#D94214", "#FFF2C1", "#80A894", "#52736B", "093844", + "#3B596A", "#427676", "#3F9A82", "#A1CD73", "ECDB60", + "#1E1E1F", "#424143", "#67666A", "#807F83", "CBC9CF", + "#E04946", "#3BA686", "#B6D15D", "#FFD495", "FA847E", + "#FFEBB0", "#FFB05A", "#F84322", "#C33A1A", "9F3818", + "#FFA136", "#FF814A", "#E6635A", "#785D6B", "534557", + "#CDCF91", "#EBEACC", "#D6D5B8", "#6D7D80", "41545E", + "#011526", "#011C40", "#4E8DA6", "#F2EA79", "F2B33D", + "#353230", "#3F4E51", "#7B8F70", "#99B2BE", "F6F4EA", + "#063559", "#0D8C7F", "#8FBF4D", "#F2D13E", "D95929", + "#158000", "#199900", "#20BF00", "#24D900", "29FF00", + "#0B0D0E", "#137074", "#7EB7A3", "#F1DDBB", "EC6766", + "#02151A", "#043A47", "#087891", "#C8C8C8", "B31D14", + "#59361F", "#5C992E", "#A3CC52", "#E6E673", "FF5933", + "#FE4365", "#FC9D9A", "#F9CDAD", "#C8C8A9", "83AF9B", + "#4B1E18", "#F9E5C2", "#BBB082", "#829993", "4F5D4E", + "#032843", "#1F595B", "#508C6D", "#71A670", "A6DB89", + "#191724", "#4C4547", "#8C594E", "#D18952", "FDB157", + "#191919", "#182828", "#60702D", "#AAB232", "E6FA87", + "#212A3F", "#434F5B", "#F2F2F2", "#8AB839", "2E2E2E", + "#004158", "#026675", "#038B8B", "#F1EEC9", "F09979", + "#023059", "#3F7EA6", "#F2F2F2", "#D99E32", "BF5E0A", + "#F21E52", "#FFFFFF", "#3D3B42", "#0C6F73", "63CFD4", + "#452743", "#E7635E", "#F8E9A8", "#89E0AD", "00928C", + "#FAAD63", "#D1714D", "#785E48", "#39403B", "3D1C24", + "#4C0016", "#FFF7EB", "#DCCEA7", "#A17345", "104F53", + "#BF2431", "#F24150", "#2A4557", "#3B848C", "EFF2E4", + "#3B3013", "#8F6031", "#E88833", "#9C0C0A", "FDF3C1", + "#1E2422", "#88BEB1", "#FF006D", "#DAFFFF", "718A94", + "#F1F4F7", "#AF9F7B", "#775E43", "#40413C", "251C17", + "#00182E", "#0C6BA1", "#D4D6D4", "#FFFDEB", "FF7500", + "#FFAB4A", "#CCBAAB", "#1E2129", "#3D5E6E", "47A3A3", + "#66B3A7", "#C0D4B6", "#EEF0BD", "#F0563D", "2C2F3B", + "#332525", "#907465", "#EDC5B5", "#878C6D", "63674A", + "#F04C16", "#DBDBD0", "#EDBD1F", "#4CB09C", "313B4A", + "#2B211D", "#611C26", "#C5003E", "#8EB7A8", "F1E4B7", + "#1A1F2B", "#30395C", "#4A6491", "#85A5CC", "D0E4F2", + "#03497E", "#0596D5", "#9DEBFC", "#999999", "FE4B28", + "#2F4159", "#465E73", "#88A649", "#F2ECE4", "D98841", + "#323A46", "#22282F", "#EB4A33", "#FFFFFF", "E9F0F5", + "#2C3E50", "#FC4349", "#6DBCDB", "#D7DADB", "FFFFFF", + "#F29727", "#E05723", "#B0382F", "#982E4B", "713045", + "#4D584A", "#465943", "#428552", "#3E754E", "4C694B", + "#47191C", "#59574B", "#829690", "#B5B09A", "E1E3CB", + "#1D5123", "#B1C661", "#FFDA68", "#FE9257", "F64448", + "#59323C", "#260126", "#F2EEB3", "#BFAF80", "8C6954", + "#4E0805", "#9E0522", "#FFF4D4", "#B8C591", "447622", + "#424862", "#FB9A63", "#BFC4D5", "#F6FBF4", "FEBC98", + "#FF2468", "#E0D4B1", "#FFFFE3", "#00A5A6", "005B63", + "#1C2F40", "#4C6173", "#8094A6", "#D9D1BA", "F2E9D8", + "#DFD7B7", "#EB7707", "#5C5445", "#3B2323", "9CBFC7", + "#262E3B", "#9C8878", "#CFCAAA", "#FBF8FF", "992435", + "#FFBC67", "#DA727E", "#AC6C82", "#685C79", "455C7B", + "#404A69", "#516C8A", "#8AC0DE", "#FFFFFF", "FFAC00", + "#485B61", "#4B8C74", "#74C476", "#A4E66D", "CFFC83", + "#A31180", "#C42795", "#DE52B4", "#EA88CE", "FFBFE5", + "#E64D2E", "#FFF5F1", "#7893AD", "#576B9C", "2D2A52", + "#BF0436", "#8C0327", "#590219", "#F2CBA1", "8C674C", + "#CF5B6F", "#FFF8C8", "#CAD9B1", "#8FB3A0", "648991", + "#341D44", "#744D90", "#BB8CDD", "#3E4417", "88904D", + "#00293E", "#003D4E", "#006269", "#00918F", "00BAB5", + "#43212E", "#D9666F", "#F2D57E", "#A9A688", "516057", + "#2A3B30", "#ABFFD1", "#EBFFF5", "#9DFEFF", "273B40", + "#A63343", "#E65159", "#F5E9DB", "#F4F7CF", "BAD984", + "#1BA68C", "#54BFAC", "#F2EDA7", "#F2E530", "D94625", + "#1A2A40", "#3F7369", "#F2DEA0", "#CE5251", "EA895E", + "#1E9382", "#70A758", "#EFF1C2", "#F0563D", "2E313D", + "#A991E8", "#FFB4BB", "#ACF7FF", "#A2E891", "FFEDAE", + "#225B66", "#17A3A5", "#8DBF67", "#FCCB5F", "FC6E59", + "#282624", "#BFB7AA", "#403D39", "#807A71", "ABA398", + "#334D5C", "#45B29D", "#EFC94C", "#E27A3F", "DF4949", + "#440008", "#605521", "#988432", "#D9A54E", "9E3711", + "#649670", "#36291E", "#69AD6C", "#92E67C", "C5FF84", + "#42342C", "#738076", "#B2B39B", "#DFE5E1", "294359", + "#1A3838", "#3F7A51", "#82A352", "#D1C062", "FFBE59", + "#7D8C22", "#B3BF67", "#F2E49B", "#D9DFF4", "6791BF", + "#8A7D6D", "#2D2D38", "#E86E48", "#FFFFE8", "9CC9C9", + "#CFC949", "#FFF5BF", "#A9E6C4", "#6AB39F", "665841", + "#A1172D", "#FDFFBA", "#A7DB9E", "#275C57", "1F1B19", + "#FF6C0D", "#F29E00", "#E6C10F", "#44996F", "216273", + "#2C3E50", "#FA4248", "#D7DADB", "#6DBCDB", "FFFFFF", + "#627369", "#99B397", "#E2F2C6", "#91CCAD", "376266", + "#04496E", "#66CAFF", "#A3FC7E", "#70D44A", "2C6B0F", + "#1BA68C", "#97BF3F", "#F2ECD8", "#F2B035", "F2522E", + "#A2D9B1", "#7CBF9E", "#F2F1B9", "#8C8575", "193741", + "#024959", "#037E8C", "#F2EFDC", "#E74C30", "363636", + "#212625", "#9CA6A2", "#D0D9D6", "#BF0404", "C2C6AF", + "#00FFFF", "#00FF00", "#FFFF00", "#FF5100", "FF007C", + "#212629", "#CDCF19", "#FFF77D", "#96C4AB", "CF2A56", + "#CFF9FF", "#BFC7BB", "#787051", "#332730", "57324F", + "#98CACB", "#FDEFBE", "#F0542B", "#736E5B", "ABA68E", + "#F2F1EB", "#BFB9A4", "#262222", "#802A30", "8C0303", + "#65356B", "#AB434F", "#C76347", "#FFA24C", "519183", + "#78BF82", "#A4D17C", "#CFD96C", "#EBD464", "FFD970", + "#806265", "#FFA256", "#F7DD77", "#E0D054", "ABA73C", + "#8F323C", "#123943", "#80BDDB", "#4189AB", "C98127", + "#683820", "#8C9A89", "#E7D6A2", "#BEAA65", "9A8234", + "#021B21", "#032C36", "#065F73", "#E8DFD6", "FF2A1D", + "#2D6C73", "#3FA693", "#B4D9CB", "#9ABF49", "C6D93B", + "#141F26", "#2B4040", "#405950", "#A69E86", "F2D9BB", + "#4A8279", "#003330", "#610400", "#003B06", "02730F", + "#69B5E1", "#D4E4F5", "#EAF2F8", "#BEDBED", "000000", + "#893660", "#EF7261", "#68D693", "#A0D7E2", "299CA8", + "#073A59", "#2D9AA6", "#F2E2DC", "#F23322", "A61B1B", + "#2A3A48", "#3E6372", "#B2D4DC", "#FAFAFF", "FF6900", + "#F3BD8D", "#F1A280", "#BE6D6B", "#704A5B", "3E263C", + "#1C2742", "#3C91C7", "#5A9ABE", "#95C5DE", "E0EEFB", + "#426261", "#465A59", "#577573", "#739A97", "9AC1C0", + "#002A4A", "#17607D", "#FFF1CE", "#FF9311", "D64700", + "#589373", "#BFBD99", "#F2D6B3", "#C2512F", "241E1E", + "#1F518B", "#1488C8", "#F7E041", "#E2413E", "B5292A", + "#549494", "#E85649", "#232C2E", "#E6E8D2", "706558", + "#392133", "#FFECBE", "#D9D098", "#C4AB6D", "AB7D3A", + "#F0F0F0", "#1C1C1C", "#A2FDF5", "#1CCDC7", "27EDDF", + "#011526", "#025959", "#027353", "#03A678", "03A696", + "#004358", "#1F8A70", "#BEDB39", "#FFE11A", "FD7400", + "#37465D", "#F2F2F2", "#9DC02E", "#779324", "051A37", + "#580022", "#AA2C30", "#FFBE8D", "#487B80", "011D24", + "#F9F9F9", "#03A678", "#E9EDEB", "#F44647", "00707F", + "#800000", "#BF0000", "#E2D6C2", "#F6EDD8", "FFFFFF", + "#F7F6AF", "#1B2124", "#D62822", "#97D6A6", "468263", + "#432852", "#992255", "#FF3D4C", "#28656E", "00968F", + "#444344", "#52BBB2", "#2B344D", "#EE5555", "F8F7EE", + "#45334A", "#796B7D", "#CCC4B0", "#FFF1B5", "FFA3A3", + "#5A4B53", "#9C3C58", "#DE2B5B", "#D86A41", "D2A825", + "#14151C", "#0C242B", "#297059", "#84D66E", "D1FB7A", + "#272D40", "#364659", "#55736D", "#9DBF8E", "D0D991", + "#23A38F", "#B7C11E", "#EFF1C2", "#F0563D", "2E313D", + "#2E064D", "#80176B", "#B356A1", "#59580B", "FFFF00", + "#CC3333", "#FF9D33", "#F7F7F0", "#3EBBA7", "00747A", + "#5C4B51", "#8CBEB2", "#F2EBBF", "#F3B562", "BD6060", + "#0D3E58", "#1C848C", "#19C0C2", "#F3EDD6", "DA6260", + "#022629", "#2A5945", "#FAFFED", "#E6DCC0", "B3371C", + "#F4FAC7", "#7BAD8D", "#FFB159", "#F77F45", "C2454E", + "#A2C1C6", "#86B1B7", "#AECBAD", "#CFDCB0", "D6E1D1", + "#B0DAFF", "#325B80", "#64B7FF", "#586D80", "5092CC", + "#0F808C", "#6C8C26", "#F2A71B", "#F26A1B", "D91818", + "#FFBC6C", "#FE9F6C", "#BD716E", "#74495F", "3B2C4D", + "#FF4D41", "#F2931F", "#E6CA21", "#91B321", "1E8C65", + "#302821", "#453629", "#5C4837", "#8A735F", "BDA895", + "#415457", "#5F7B7F", "#9ACCAF", "#E6EBC4", "F9F7C8", + "#474143", "#A69E9D", "#E7E2DA", "#FFFFFF", "E7E8E7", + "#805939", "#BD9962", "#E6CD7D", "#578072", "2D4B4D", + "#03588C", "#1763A6", "#419CA6", "#54BF83", "8DBF41", + "#00CCFF", "#A1FCFF", "#040438", "#004878", "C9FAFF", + "#534C64", "#B7DECF", "#F0F3D7", "#7E858C", "D96557", + "#7F7364", "#CBB08E", "#CBC1B7", "#789DCB", "646F7F", + "#5C2849", "#A73E5C", "#EC7263", "#FE9551", "FFD285", + "#FF0012", "#FF7D00", "#FFD900", "#5BE300", "0084B0", + "#F24C32", "#F29471", "#FCDFA6", "#36B898", "3D7585", + "#083157", "#0A6C87", "#459C97", "#92CCA5", "C9F0B1", + "#DC941B", "#EDC266", "#B6952C", "#E1D3A6", "E9A119", + "#323836", "#BAD1B5", "#DBE8CF", "#F0F7E8", "FFFEF5", + "#081724", "#589494", "#8EBBB4", "#D0DCD0", "F5EED2", + "#50781C", "#9CAD1C", "#EAF7E6", "#40A5DE", "0B5191", + "#537F79", "#78A68F", "#CBD49C", "#FED457", "CB252A", + "#F23C13", "#CBAB78", "#FFFFFF", "#898373", "1F1C17", + "#450003", "#5C0002", "#94090D", "#D40D12", "FFED75", + "#0770A2", "#82D9F7", "#FEFEFE", "#AEC844", "F36622", + "#30394F", "#FF434C", "#6ACEEB", "#EDE8DF", "0E6569", + "#FF6B6B", "#556270", "#C7F464", "#4ECDC4", "EDC8BB", + "#D9B500", "#FFED9C", "#BFCC85", "#748F74", "454545", + "#452E32", "#A34B1B", "#B5A187", "#EDDF9A", "A7CC31", + "#2C2B33", "#596664", "#909980", "#CCC08D", "FF8A00", + "#C21F1F", "#FFFFFC", "#E34446", "#FFFFDB", "E36D6F", + "#282828", "#00AAB5", "#C1C923", "#F41C54", "F5F0F0", + "#3A3F40", "#202627", "#151B1E", "#EFF4FF", "41444D", + "#DEBB73", "#4D0017", "#010000", "#4D0F30", "9A002F", + "#EB9328", "#FFA754", "#FFD699", "#FFF5DC", "4FA6B3", + "#025E73", "#037F8C", "#D9D59A", "#D9BD6A", "590202", + "#636266", "#E0CEA4", "#E8A579", "#7D6855", "42403E", + "#FF0000", "#FF4000", "#FF7F00", "#FFBF00", "FFFF00", + "#FFFFFF", "#74ADA6", "#1E5E6F", "#241B1F", "68A81E", + "#5A0532", "#FF6745", "#FFC861", "#9DAE64", "27404A", + "#ACCBBC", "#467847", "#E8E4C1", "#A60303", "730202", + "#5C4B51", "#8CBEB2", "#F2EBBF", "#F3B562", "F06060", + "#0D2557", "#93A8C9", "#FFFFFF", "#F5DED5", "558D96", + "#F53C4A", "#565157", "#10CFC8", "#F2EEE7", "F5D662", + "#FFD97B", "#E65029", "#A60027", "#660033", "191C26", + "#595408", "#A6800D", "#A66D03", "#A63F03", "730C02", + "#2E031F", "#590424", "#8C072B", "#BF0A2B", "DEEFC5", + "#E0C882", "#A6874E", "#BFA169", "#D9B779", "F2D399", + "#D88681", "#A67673", "#746566", "#535A5D", "324F54", + "#FC297D", "#FB607A", "#FDA286", "#FDC188", "FEE78A", + "#FFECA1", "#B3B27F", "#4C5E52", "#2F3436", "FFBE2C", + "#D93312", "#B3AB82", "#45735F", "#394D47", "2C3233", + "#324143", "#6595A3", "#C8E3E8", "#FCFFED", "B6C28B", + "#477984", "#FEF5EB", "#C03C44", "#EEAA4D", "313E4A", + "#334D5C", "#45B29D", "#EFC94C", "#E27A3F", "DF4949", + "#630B11", "#33322F", "#2A2927", "#1E1D1C", "000000", + "#D94214", "#FFF2C1", "#80A894", "#52736B", "093844", + "#051E21", "#00302D", "#856434", "#F28C28", "FFAD4E", + "#D7DADD", "#DDDEE3", "#E1E1E9", "#EDEFF4", "F2F3F8", + "#BF495E", "#41A693", "#F2EC9B", "#D9CF48", "D9583B", + "#067072", "#14A589", "#DECFA6", "#BAAE8C", "F94B06", + "#423A38", "#47B8C8", "#E7EEE2", "#BDB9B1", "D7503E", + "#730324", "#DFE3E6", "#B4C4D4", "#8BA2BD", "456382", + "#537374", "#F9BD7F", "#EBD7A5", "#ADC9A5", "5C9E99", + "#88B59E", "#B6DEC8", "#39464D", "#C04229", "ABD1AB", + "#11A7FC", "#95D127", "#F2E415", "#FF8638", "EE3551", + "#212640", "#5D718C", "#4B95A6", "#60BFBF", "EFF2D8", + "#D8A64D", "#9B5422", "#351411", "#5B0D0D", "991C11", + "#53324F", "#668D6E", "#F2E0A0", "#F19B7A", "F0756E", + "#DFE0AF", "#A4BAA2", "#569492", "#41505E", "383245", + "#7BBADE", "#93DE7F", "#FFED5D", "#F29E4A", "FF7050", + "#133800", "#1B4F1B", "#398133", "#5C9548", "93E036", + "#D9D7AD", "#91A685", "#FF6A00", "#37485C", "1C232E", + "#008767", "#FFB27A", "#FF6145", "#AB2141", "5E1638", + "#727B7F", "#CCEAEA", "#7A7556", "#2E2125", "44CACC", + "#FFFFED", "#FF2C38", "#FF9A3A", "#FFF040", "67D9FF", + "#007148", "#60A859", "#9BDA6A", "#C7F774", "F9FFEF", + "#092740", "#45698B", "#90B0CC", "#F1FAFF", "8FD36F", + "#E2FFA0", "#7D8076", "#FAFFED", "#C2CCBE", "8F7D70", + "#00736A", "#00BC9F", "#F1EEC7", "#FEA301", "F2561A", + "#26282E", "#AD5138", "#F7F7F7", "#DDDAE0", "8594AE", + "#1A191F", "#35352F", "#484042", "#4E5252", "E64D38", + "#49454A", "#E69B02", "#FAF4C6", "#B1D631", "324052", + "#5F1A2B", "#1D2834", "#6F8B78", "#E4D49E", "C96466", + "#012D3D", "#38AD9E", "#FFEB9E", "#FF6867", "D0DBED", + "#0D1F36", "#104954", "#1E9C89", "#38CC85", "60EB7B", + "#8C4E03", "#9FA66A", "#F2EC94", "#F23005", "8B0F03", + "#000001", "#20201F", "#E2E2E4", "#590402", "B80000", + "#344059", "#465973", "#F2D272", "#A69460", "595139", + "#33454C", "#608F85", "#B6E5CB", "#8BAF95", "54584E", + "#FBFEF6", "#B7BFA4", "#687F70", "#1A3841", "BF3847", + "#D7E836", "#86FFC7", "#FFB048", "#E8366C", "593BFF", + "#34A9FF", "#5982DB", "#665EB8", "#684682", "632E62", + "#004056", "#2C858D", "#74CEB7", "#C9FFD5", "FFFFCB", + "#BFB978", "#84945C", "#516967", "#4D3130", "281B24", + "#103B73", "#20638C", "#3786A6", "#4EABBF", "EBEFF2", + "#9FB1BF", "#1D2D63", "#1C5357", "#1F6E56", "196331", + "#FFEBBA", "#C3BD91", "#88947B", "#4C3F3F", "2A2727", + "#347373", "#4EA6A6", "#91D9D9", "#FFFFFD", "F2E205", + "#828948", "#EFDFC2", "#006971", "#DC533E", "840000", + "#000137", "#29003F", "#79003D", "#D04D14", "F89801", + "#370005", "#4B0005", "#5F0005", "#730005", "870005", + "#C3AE8D", "#F25260", "#2D5F73", "#6BADC9", "8FCED6", + "#9E1B36", "#F7EDBA", "#E69B3D", "#EB3355", "3D241D", + "#1D8281", "#44BF87", "#FBD258", "#F29A3F", "DB634F", + "#035C75", "#1B808C", "#31A6A8", "#F3F1BC", "F3AD14", + "#FF7500", "#665130", "#EBB643", "#CEDAA8", "668E84", + "#384D3A", "#3E6653", "#728053", "#A68357", "D97C71", + "#012326", "#17455C", "#E1CAAB", "#FE8333", "FA4913", + "#1A2944", "#2DA7C7", "#56ACBA", "#98C4C9", "CBD5D2", + "#BF3542", "#CDC5BA", "#EBE3D6", "#3C3C3C", "2E2E2E", + "#231921", "#695F74", "#BEB4CB", "#EBEBF0", "D2DCEB", + "#34373F", "#686C75", "#F3E9D0", "#BEB7A7", "8E867C", + "#661510", "#D9351A", "#F2C76F", "#BF9727", "204D3F", + "#3CFFEE", "#24AABC", "#356781", "#2C3D51", "1C1F24", + "#DA3537", "#FFFCC4", "#00585F", "#6A6A61", "2A2C2B", + "#AE3135", "#D1AF87", "#8C826B", "#3D3C33", "F2F0CE", + "#FF0894", "#FF5E9F", "#FF91A7", "#FFB5CA", "F5F0BA", + "#99878D", "#323232", "#646464", "#7E4A5C", "372129", + "#3FB8AF", "#7FC7AF", "#DAD8A7", "#FFB38B", "FF3F34", + "#402B3C", "#6AA6A6", "#D9CCA7", "#F2B263", "F26835", + "#6AA690", "#F2BC1B", "#F2DC99", "#F29057", "BF1F1F", + "#F4FAC7", "#7BAD8D", "#FFB158", "#F77F45", "C2454E", + "#E5533C", "#F5E346", "#93D06D", "#50AC6A", "227864", + "#39588A", "#A9BDD7", "#FFFFFF", "#FFEADD", "FFD0BB", + "#B0B595", "#615F4F", "#828567", "#91A380", "EAFFCD", + "#00427F", "#0066BD", "#66B5CC", "#F0E4C5", "D6C28F", + "#FF6313", "#F9E4B3", "#C29689", "#74474B", "45232E", + "#00585F", "#009393", "#FFFCC4", "#C7C49B", "EB0A00", + "#091840", "#44A2FF", "#F7F7EA", "#B3CC63", "4C6620", + "#5CBBE3", "#FCF1BC", "#5C8182", "#383A47", "B4F257", + "#9E9E9E", "#E5E1D1", "#E0393D", "#253746", "425563", + "#4D9453", "#FFFFB1", "#ADDE4E", "#FF9D27", "A62A16", + "#B70046", "#FF850B", "#FFEBC5", "#109679", "675A4C", + "#363636", "#0599B0", "#A4BD0A", "#FFA615", "FF2E00", + "#7D8077", "#BBBFB2", "#FAFFED", "#E82A33", "E3DEBC", + "#FD9F44", "#FC5C65", "#007269", "#03A679", "FAF0B9", + "#134B57", "#81A489", "#F1D8B5", "#F2A054", "C04D31", + "#946E49", "#394042", "#EDDBAC", "#872A0C", "BA8E3A", + "#404040", "#024959", "#037E8C", "#FFFFFF", "F24C27", + "#2A3342", "#163C6E", "#4E5F61", "#E6A015", "EDE7BE", + "#445060", "#829AB5", "#849E91", "#C14543", "D6D5D1", + "#8A9126", "#B7BF5E", "#FFE9C4", "#F5B776", "F58E45", + "#9B2D1E", "#3C3A28", "#78A080", "#9BCD9E", "FFFFAE", + "#FF6138", "#FFFF9D", "#BEEB9F", "#79BD8F", "00A388", + "#990000", "#FF6600", "#FF9900", "#996633", "CC9966", + "#DCE6DA", "#B8CCBB", "#98B3A5", "#7A9994", "62858C", + "#0B1C29", "#3B7C8F", "#73A5A3", "#98C1B7", "F0EBD2", + "#F6CB51", "#E25942", "#13A89E", "#3F4953", "F2E7DA", + "#282F36", "#FFFEFC", "#BDA21D", "#BFBC5B", "D2E098", + "#8C182D", "#DE7140", "#FCB95A", "#FAE285", "6A7349", + "#6B9100", "#FFE433", "#FF841F", "#E03D19", "A6001C", + "#FFEAA7", "#D9D697", "#9FC49F", "#718C6A", "543122", + "#CFF09E", "#A8DBA8", "#79BD9A", "#3B8686", "0B486B", + "#0C2233", "#065471", "#0A91AB", "#FFC045", "F2F2F2", + "#BEE8E0", "#373C40", "#2E2621", "#73320B", "FF5E00", + "#1B2C35", "#A3BFC6", "#FF005D", "#222A30", "293A42", + "#FF8400", "#3B4044", "#494948", "#E6E1D8", "F7F2E9", + "#6A482D", "#518C86", "#F6BF3D", "#EF7C27", "BF2424", + "#261C2B", "#292B39", "#226468", "#608D80", "829D8F", + "#B2AD9A", "#110E00", "#363226", "#A9A695", "ECE9D8", + "#1B1B26", "#26394D", "#286480", "#13B3BF", "A3FF57", + "#F2C2A7", "#F5E5C5", "#593D28", "#422C21", "93DEDB", + "#001028", "#033140", "#1E5A5B", "#7BA78C", "EBEDC6", + "#544E6E", "#808CB0", "#ABD1D9", "#D9FFF7", "DDF556", + "#323A45", "#596677", "#758194", "#FFFFFF", "E74C3C", + "#45291A", "#AB926D", "#DBD1BC", "#4999C3", "5FCBEC", + "#6B151D", "#2E1615", "#A8553A", "#DB8F5A", "F2C18E", + "#000623", "#28475C", "#4A6C74", "#8BA693", "F0E3B1", + "#60807B", "#81B37A", "#BCCC5F", "#FFEE65", "E64964", + "#FFFFFA", "#A1A194", "#5B605F", "#464646", "FF6600", + "#1E1B17", "#577270", "#9C9A79", "#C7BDA1", "580E0C", + "#452F27", "#5E504A", "#6B6865", "#9BBAB2", "B0FFED", + "#1B5257", "#F7F6C3", "#F28159", "#CC5850", "4F1C2E", + "#FAA51B", "#BF511F", "#2C445E", "#2F6D82", "5EE4EB", + "#BF3952", "#59364A", "#556D73", "#D9D1A9", "D95F5F", + "#024959", "#037E8C", "#F2EFDC", "#E74C30", "363636", + "#221A26", "#544759", "#A197A6", "#F27405", "D93D04", + "#C4A44A", "#E6D399", "#9AB8A9", "#7C8A7F", "4E4B44", + "#FFFEC8", "#B1BF99", "#5B604D", "#39382B", "26181E", + "#4E3C51", "#21A68D", "#3BBF9A", "#F2E8B6", "F25749", + "#102144", "#1B325E", "#254580", "#3C63B0", "5D8AEA", + "#2A3A48", "#3E6372", "#B2D4DC", "#FAFAFF", "FF4B00", + "#FFF1BF", "#F20058", "#FFAEAC", "#000001", "7D7A96", + "#FDFFC6", "#F2F096", "#FF0080", "#DE0049", "521218", + "#5B0E00", "#FBB500", "#FBD864", "#807D1A", "59233C", + "#1E1E1F", "#424143", "#67666A", "#807F83", "CBC9CF", + "#3C3658", "#3EC8B7", "#7CD0B4", "#B9D8B1", "F7E0AE", + "#FFFFFF", "#99B75F", "#D5DD98", "#EBF4DB", "D8D8D8", + "#248A8A", "#C9FA58", "#F9E555", "#FAAC38", "F2572A", + "#086B63", "#77A490", "#E2D8C1", "#BFAE95", "7C7159", + "#5C4B51", "#8CBEB2", "#F2EBBF", "#A5C88F", "EF847B", + "#17162F", "#89346D", "#C76058", "#FFB248", "E8C475", + "#6E8F4A", "#65D9C5", "#F2E7B6", "#EDA430", "AB3E2C", + "#30394F", "#FF434C", "#6ACEEB", "#EDE8DF", "0E6569", + "#8E1B13", "#F9E4B3", "#849689", "#46464A", "29232E", + "#686B30", "#AB9A52", "#E8BA67", "#D68F4F", "BA512E", + "#E54E45", "#DBC390", "#F2F2EF", "#13A3A5", "403833", + "#65BA99", "#59A386", "#F1DDBB", "#D6C4A6", "E74C3C", + "#A6FFBC", "#4ACFAF", "#00A995", "#006161", "003D4C", + "#33271E", "#8B7653", "#C8D9A0", "#FDEE9D", "233331", + "#048789", "#503D2E", "#D44D27", "#E2A72E", "EFEBC8", + "#E5FF1E", "#A9D943", "#75A660", "#698070", "494D4B", + "#2DEBA2", "#91F57F", "#EBAA69", "#E70049", "2B0027", + "#990000", "#336699", "#DDDDDD", "#999999", "333333", + "#F13A4B", "#3D3C3E", "#22BDAF", "#F4F4F4", "D7D7D7", + "#F53A59", "#001D2D", "#15A88C", "#B7D9C8", "F3F5F4",]; + + +}; + +Ops.Color.ColorPalettes.prototype = new CABLES.Op(); +CABLES.OPS["31d33a1e-9a0a-49f7-8bc8-9e83ab71e23e"]={f:Ops.Color.ColorPalettes,objName:"Ops.Color.ColorPalettes"}; + + + + +// ************************************************************** +// +// Ops.Color.HSBtoRGB +// +// ************************************************************** + +Ops.Color.HSBtoRGB = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inH = op.inValueSlider("Hue"), + inS = op.inValueSlider("Saturation", 1), + inV = op.inValueSlider("Brightness", 0.5), + outR = op.outNumber("R"), + outG = op.outNumber("G"), + outB = op.outNumber("B"); + +inH.onChange = inS.onChange = inV.onChange = update; +update(); + +function update() +{ + let hue = (inH.get()); + let saturation = (inS.get()); + let lightness = (inV.get()); + + // based on algorithm from http://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB + + let chroma = (1 - Math.abs((2 * lightness) - 1)) * saturation; + let huePrime = hue * 6; // / 60; + let secondComponent = chroma * (1 - Math.abs((huePrime % 2) - 1)); + + huePrime = Math.floor(huePrime) || 0; + let red = 0; + let green = 0; + let blue = 0; + + if (huePrime === 0) + { + red = chroma; + green = secondComponent; + blue = 0; + } + else if (huePrime === 1) + { + red = secondComponent; + green = chroma; + blue = 0; + } + else if (huePrime === 2) + { + red = 0; + green = chroma; + blue = secondComponent; + } + else if (huePrime === 3) + { + red = 0; + green = secondComponent; + blue = chroma; + } + else if (huePrime === 4) + { + red = secondComponent; + green = 0; + blue = chroma; + } + else if (huePrime >= 5) + { + red = chroma; + green = 0; + blue = secondComponent; + } + let lightnessAdjustment = (lightness - (chroma / 2)); + red += lightnessAdjustment; + green += lightnessAdjustment; + blue += lightnessAdjustment; + + outR.set(red); + outG.set(green); + outB.set(blue); + + // return [Math.round(red * 255), Math.round(green * 255), Math.round(blue * 255)]; +} + + +}; + +Ops.Color.HSBtoRGB.prototype = new CABLES.Op(); +CABLES.OPS["909ee871-b0f3-477f-bee2-d0ab40bb5804"]={f:Ops.Color.HSBtoRGB,objName:"Ops.Color.HSBtoRGB"}; + + + + +// ************************************************************** +// +// Ops.Color.HexToRGB_v2 +// +// ************************************************************** + +Ops.Color.HexToRGB_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + hex = op.inString("Hex", "#ff0000"), + asBytes = op.inValueBool("Bytes"), + outR = op.outNumber("R"), + outG = op.outNumber("G"), + outB = op.outNumber("B"); + +function hexToR(h) +{ + return parseInt((cutHex(h)).substring(0, 2), 16) || 0; +} +function hexToG(h) +{ + return parseInt((cutHex(h)).substring(2, 4), 16) || 0; +} +function hexToB(h) +{ + return parseInt((cutHex(h)).substring(4, 6), 16) || 0; +} +function cutHex(h) +{ + return (h.charAt(0) == "#") ? h.substring(1, 7) : h; +} + +hex.onChange = parse; +asBytes.onChange = parse; + +function parse() +{ + let str = hex.get() || ""; + let r = hexToR(str); + let g = hexToG(str); + let b = hexToB(str); + + if (!asBytes.get()) + { + r /= 255; + g /= 255; + b /= 255; + } + + outR.set(r); + outB.set(b); + outG.set(g); +} + + +}; + +Ops.Color.HexToRGB_v2.prototype = new CABLES.Op(); +CABLES.OPS["9877f198-8dac-48e5-9310-244ef1a8dec5"]={f:Ops.Color.HexToRGB_v2,objName:"Ops.Color.HexToRGB_v2"}; + + + + +// ************************************************************** +// +// Ops.Color.RGBtoHSB +// +// ************************************************************** + +Ops.Color.RGBtoHSB = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inR = op.inValueSlider("R", 0), + inG = op.inValueSlider("G", 0), + inB = op.inValueSlider("B", 0), + outH = op.outNumber("Hue"), + outS = op.outNumber("Saturation"), + outB = op.outNumber("Brightness"); + +inR.onChange = inG.onChange = inB.onChange = update; + +/** + * Converts an RGB color value to HSV. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSV_color_space. + * Assumes r, g, and b are contained in the set [0, 255] and + * returns h, s, and v in the set [0, 1]. + * + * @param Number r The red color value + * @param Number g The green color value + * @param Number b The blue color value + * @return Array The HSV representation + */ + +function update() +{ + let r = (inR.get()); + let g = (inG.get()); + let b = (inB.get()); + + // public static float[] RGBtoHSB(var r, var g, var b, float[] hsbvals) { + let hue, saturation, brightness; + // if (hsbvals == null) { + // hsbvals = []; + // } + let cmax = (r > g) ? r : g; + if (b > cmax) cmax = b; + let cmin = (r < g) ? r : g; + if (b < cmin) cmin = b; + + brightness = (cmax); + if (cmax != 0) + saturation = ((cmax - cmin)) / (cmax); + else + saturation = 0; + if (saturation == 0) + hue = 0; + else + { + let redc = ((cmax - r)) / ((cmax - cmin)); + let greenc = ((cmax - g)) / ((cmax - cmin)); + let bluec = ((cmax - b)) / ((cmax - cmin)); + if (r == cmax) + hue = bluec - greenc; + else if (g == cmax) + hue = 2.0 + redc - bluec; + else + hue = 4.0 + greenc - redc; + hue /= 6.0; + if (hue < 0) + hue += 1.0; + } + + // hsbvals[0] = hue; + // hsbvals[1] = saturation; + // hsbvals[2] = brightness; + // return hsbvals; + // 942 } + // var max = Math.max(r, g, b), min = Math.min(r, g, b); + // var h, s, v = max; + + // var d = max - min; + // s = max == 0 ? 0 : d / max; + + // if (max == min) { + // h = 0; // achromatic + // } else { + // switch (max) { + // case r: h = (g - b) / d + (g < b ? 6 : 0); break; + // case g: h = (b - r) / d + 2; break; + // case b: h = (r - g) / d + 4; break; + // } + + // h /= 6; + // } + + outH.set(hue); + outS.set(saturation); + outB.set(brightness / 2.0); +} + +update(); + + +}; + +Ops.Color.RGBtoHSB.prototype = new CABLES.Op(); +CABLES.OPS["22dd3a12-79ff-49ce-abe6-d3b5a3b06ff3"]={f:Ops.Color.RGBtoHSB,objName:"Ops.Color.RGBtoHSB"}; + + + + +// ************************************************************** +// +// Ops.Color.RgbToHex +// +// ************************************************************** + +Ops.Color.RgbToHex = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + r = op.inValueSlider("r", Math.random()), + g = op.inValueSlider("g", Math.random()), + b = op.inValueSlider("b", Math.random()), + result=op.outString("Result"); + +r.setUiAttribs({ colorPick: true }); + +r.onChange= +g.onChange= +b.onChange=()=> +{ + + const red=parseInt(r.get()*255); + const green=parseInt(g.get()*255); + const blue=parseInt(b.get()*255); + + result.set(((blue | green << 8 | red << 16) | 1 << 24).toString(16).slice(1)); +}; + +}; + +Ops.Color.RgbToHex.prototype = new CABLES.Op(); +CABLES.OPS["c0233dfa-ef4c-4451-b86e-3b2aadc8e9a5"]={f:Ops.Color.RgbToHex,objName:"Ops.Color.RgbToHex"}; + + + + +// ************************************************************** +// +// Ops.Date.DateAndTime +// +// ************************************************************** + +Ops.Date.DateAndTime = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let UPDATE_RATE_DEFAULT = 500; +let UPDATE_RATE_MIN = 50; +let updateRate = UPDATE_RATE_DEFAULT; + +const + outYear = op.outNumber("Year"), + outMonth = op.outNumber("Month"), + outDay = op.outNumber("Day"), + outHours = op.outNumber("Hours"), + outMinutes = op.outNumber("Minutes"), + outSeconds = op.outNumber("Seconds"), + outTimestemp = op.outNumber("Timestamp"), + updateRatePort = op.inInt("Update Rate", UPDATE_RATE_DEFAULT); + +let d = new Date(); + +let timeout = setTimeout(update, UPDATE_RATE_DEFAULT); +update(); + +function update() +{ + d = new Date(); + + outSeconds.set(d.getSeconds()); + outMinutes.set(d.getMinutes()); + outHours.set(d.getHours()); + outDay.set(d.getDate()); + outMonth.set(d.getMonth()); + outYear.set(d.getFullYear()); + + timeout = setTimeout(update, updateRate); + + outTimestemp.set(Date.now()); +} + +updateRatePort.onChange = function () +{ + let newUpdateRate = updateRatePort.get(); + if (newUpdateRate && newUpdateRate >= UPDATE_RATE_MIN) + { + updateRate = newUpdateRate; + } +}; + +op.onDelete = function () +{ + clearTimeout(timeout); +}; + + +}; + +Ops.Date.DateAndTime.prototype = new CABLES.Op(); +CABLES.OPS["beff95ec-7b50-4b6e-80b8-a7e4ab97d8cc"]={f:Ops.Date.DateAndTime,objName:"Ops.Date.DateAndTime"}; + + + + +// ************************************************************** +// +// Ops.Date.DateCalc +// +// ************************************************************** + +Ops.Date.DateCalc = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTimestamp = op.inValue("timestamp"), + inDiff = op.inInt("difference"), + diffType = op.inDropDown("type", ["years", "months", "days", "hours", "minutes", "seconds"]), + inTrigger = op.inTrigger("update"), + + outDate = op.outObject("Date"), + outResult = op.outNumber("Timestamp"); + +inTimestamp.onChange = + inDiff.onChange = + diffType.onChange = + inTrigger.onChange = update; + +function update() +{ + let ts = inTimestamp.get(); + if (!inTimestamp.isLinked()) + { + ts = Date.now(); + } + const diff = inDiff.get(); + const date = new Date(ts); + switch (diffType.get()) + { + case "years": + date.setYear(date.getYear() + diff); + break; + case "months": + date.setMonth(date.getMonth() + diff); + break; + case "days": + date.setDate(date.getDate() + diff); + break; + case "hours": + date.setHours(date.getHours() + diff); + break; + case "minutes": + date.setMinutes(date.getMinutes() + diff); + break; + case "seconds": + date.setSeconds(date.getSeconds() + diff); + break; + + default: + // code + } + outResult.set(date.getTime()); + outDate.set(date); +} + + +}; + +Ops.Date.DateCalc.prototype = new CABLES.Op(); +CABLES.OPS["1420b781-7b09-4102-b1fd-2cb841e57b95"]={f:Ops.Date.DateCalc,objName:"Ops.Date.DateCalc"}; + + + + +// ************************************************************** +// +// Ops.Date.DateDifference +// +// ************************************************************** + +Ops.Date.DateDifference = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + ts1 = op.inValue("Timestamp 1"), + ts2 = op.inValue("Timestamp 2"), + stopAtZero = op.inValueBool("Stop at 0"), + outYear = op.outNumber("Year"), + outMonth = op.outNumber("Month"), + outDay = op.outNumber("Day"), + outHours = op.outNumber("Hours"), + outMinutes = op.outNumber("Minutes"), + outSeconds = op.outNumber("Seconds"), + outMilliSeconds = op.outNumber("Milliseconds"), + outDiff = op.outNumber("Diff"); + +ts1.onChange = update; +ts2.onChange = update; + +function update() +{ + let d = new Date(ts1.get() - ts2.get()); + outDiff.set(d.getTime()); + if (stopAtZero.get()) + { + if (d.getTime() < 0)d = new Date(0); + } + + outMilliSeconds.set(d.getMilliseconds()); + outSeconds.set(d.getSeconds()); + outMinutes.set(d.getMinutes()); + outHours.set(d.getHours() - 1); + outDay.set(d.getDate() - 1); + outMonth.set(d.getMonth()); + outYear.set(d.getFullYear() - 1970); +} + + +}; + +Ops.Date.DateDifference.prototype = new CABLES.Op(); +CABLES.OPS["34cd865c-cc4d-4c58-afb2-626773eb412e"]={f:Ops.Date.DateDifference,objName:"Ops.Date.DateDifference"}; + + + + +// ************************************************************** +// +// Ops.Date.DateFormatter +// +// ************************************************************** + +Ops.Date.DateFormatter = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inTimestamp = op.inValue("Timestamp"); +const inDate = op.inObject("Date"); +const inFormat = op.inString("Format", "YYYY-MM-DD"); +const outString = op.outString("StringDate"); + +inTimestamp.onChange = function () +{ + const ts = inTimestamp.get(); + update(new Date(ts)); +}; +inDate.onChange = function () +{ + const date = inDate.get(); + update(date); +}; +inFormat.onChange = function () +{ + update(new Date()); +}; + +function update(date) +{ + const m = moment(date); + const f = inFormat.get(); + outString.set(m.format(f)); +} + + +}; + +Ops.Date.DateFormatter.prototype = new CABLES.Op(); +CABLES.OPS["8933d01f-39ac-428c-a64b-902c534a4fc0"]={f:Ops.Date.DateFormatter,objName:"Ops.Date.DateFormatter"}; + + + + +// ************************************************************** +// +// Ops.Date.DateIsoToTimestamp +// +// ************************************************************** + +Ops.Date.DateIsoToTimestamp = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const date = op.inString("datetime"); +const timestamp = op.outNumber("timestamp"); + +date.onChange = function() { + const parsed = Date.parse(date.get()); + timestamp.set(parsed); +} + +}; + +Ops.Date.DateIsoToTimestamp.prototype = new CABLES.Op(); +CABLES.OPS["cedf9c37-f864-4416-9675-ecc15f07025d"]={f:Ops.Date.DateIsoToTimestamp,objName:"Ops.Date.DateIsoToTimestamp"}; + + + + +// ************************************************************** +// +// Ops.Date.DateTimestamp +// +// ************************************************************** + +Ops.Date.DateTimestamp = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inYear = op.inValueInt("Year"), + inMonth = op.inValueInt("Month"), + inDay = op.inValueInt("Day"), + inHour = op.inValueInt("Hour"), + inMinute = op.inValueInt("Minute"), + outTimestamp = op.outNumber("Timestamp"); + +inYear.onChange = +inMonth.onChange = +inDay.onChange = +inHour.onChange = +inMinute.onChange = setDate; + +function setDate() +{ + const d = new Date(); + + const datum = new Date(Date.UTC( + inYear.get(), + inMonth.get() - 1, + inDay.get(), + inHour.get(), + inMinute.get() + ) + d.getTimezoneOffset() * 60 * 1000); + + outTimestamp.set(datum.getTime()); +} + + +}; + +Ops.Date.DateTimestamp.prototype = new CABLES.Op(); +CABLES.OPS["e86a668b-db87-472e-9484-3fd102ccbf8a"]={f:Ops.Date.DateTimestamp,objName:"Ops.Date.DateTimestamp"}; + + + + +// ************************************************************** +// +// Ops.Debug.Console +// +// ************************************************************** + +Ops.Debug.Console = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + visible = op.inValueBool("visible", true), + inClear = op.inTriggerButton("Clear"), + outEle = op.outObject("Element", null, "element"); + +let eleLog = null; +let canvas = op.patch.cgl.canvas.parentElement; + +let oldLog = console.log; +let oldLogError = console.error; +let oldLogWarn = console.warn; + +console.log = thelog; +console.error = thelog; +console.warn = thelog; + +addElement(); + +op.onDelete = function () +{ + removeElement(); + console.log = oldLog; + console.error = oldLogError; + console.warn = oldLogWarn; +}; + +visible.onChange = function () +{ + if (visible.get()) eleLog.style.display = "block"; + else eleLog.style.display = "none"; +}; + +function addElement() +{ + if (eleLog)removeElement(); + eleLog = document.createElement("div"); + eleLog.style.padding = "0px"; + eleLog.style.position = "absolute"; + eleLog.style.overflow = "scroll"; + if (CABLES.UI) + { + eleLog.style.width = "100%"; + eleLog.style.height = "50%"; + } + else + { + eleLog.style.width = "100vw"; + eleLog.style.height = "50vh"; + } + eleLog.style["background-color"] = "rgba(0,0,0,0.74)"; + eleLog.style["box-sizing"] = "border-box"; + eleLog.style.padding = "5px"; + eleLog.style["z-index"] = "9999"; + eleLog.style.color = "#fff"; + + canvas.appendChild(eleLog); +} + +function removeElement() +{ + canvas.removeChild(eleLog); + eleLog = null; +} + +function thelog() +{ + if (!eleLog)addElement(); + oldLog.apply(console, arguments); + + try + { + let html = ""; + for (let i = 0; i < arguments.length; i++) + { + if (typeof arguments[i] == "object") html += (JSON && JSON.stringify ? JSON.stringify(arguments[i], undefined, 2) : arguments[i]) + " "; + else html += arguments[i] + " "; + } + eleLog.innerHTML += html + ""; + } + catch (e) {} + eleLog.scrollTop = eleLog.scrollHeight; +} + +inClear.onTriggered = () => +{ + eleLog.innerHTML = ""; +}; + + +}; + +Ops.Debug.Console.prototype = new CABLES.Op(); +CABLES.OPS["1e650a0b-672f-4dca-bcf0-5df281a2d31e"]={f:Ops.Debug.Console,objName:"Ops.Debug.Console"}; + + + + +// ************************************************************** +// +// Ops.Debug.ConsoleLog +// +// ************************************************************** + +Ops.Debug.ConsoleLog = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inNumber=op.inFloat("Number",0), + inString=op.inString("String",""); + + +inNumber.onChange=function() +{ + console.log(inNumber.get()); +}; + +inString.onChange=function() +{ + console.log(inString.get()); +}; + +}; + +Ops.Debug.ConsoleLog.prototype = new CABLES.Op(); +CABLES.OPS["545e7225-73b0-4d40-923b-4b39940403a8"]={f:Ops.Debug.ConsoleLog,objName:"Ops.Debug.ConsoleLog"}; + + + + +// ************************************************************** +// +// Ops.Debug.GlLogErrors +// +// ************************************************************** + +Ops.Debug.GlLogErrors = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Exec"), + inLimit = op.inInt("Limit Error Logs Num", 1), + inStop = op.inBool("Stop trigger after limit", false), + inShowHistory = op.inTriggerButton("show gl history"), + next = op.outTrigger("Next"); + +const gl = op.patch.cgl.gl; +const cgl = op.patch.cgl; + +const originals = {}; +let shouldStart = true; +let count = 0; +let errorCount = 0; +let history = []; +let countFrames = 0; + +exec.onLinkChanged = +next.onLinkChanged = () => +{ + end(); + shouldStart = true; +}; + + +let showHistory = false; + +inShowHistory.onTriggered = () => +{ + showHistory = true; +}; + +let glConsts = {}; + +for (let i in op.patch.cgl.gl) +{ + if (i == i.toUpperCase() && typeof op.patch.cgl.gl[i] == "number") + { + glConsts[op.patch.cgl.gl[i]] = i; + } +} + +function showCodeModal(title, code, type) +{ + if (!CABLES.UI || !CABLES.UI.ModalDialog) + { + console.log(title, code); + } + + let html = ""; + html += "

Code

"; + html += "" + title + " "; + html += "

"; + html += "

"; + + code = code || ""; + code = code.replace(/\/g, ">"); // for > + + html += "
" + code + "
"; + + new CABLES.UI.ModalDialog({ + "title": title, + "html": html + }); + + Array.from(document.querySelectorAll("pre code")).forEach(function (block) + { + hljs.highlightBlock(block); + }); +} + +exec.onTriggered = function () +{ + count = 0; + if (shouldStart) start(); + + if (errorCount >= inLimit.get() && inStop.get()) return; + + next.trigger(); + + countFrames++; + shouldStart = false; + + if (showHistory) + { + if (CABLES.UI) showCodeModal("gl history", getHistoryAsString(), "javascript"); + + showHistory = false; + } + history.length = 0; +}; + +function glGetError() +{ + return op.patch.cgl.gl.getError(); + // return originals["getError"].apply(this, arguments); +} + +function getHistoryString(i) +{ + let str = history[i].f + "( "; + for (let j in history[i].a) + { + if (j != 0)str += ", "; + + const typ = typeof history[i].a[j]; + + if (typ == "number" || typ == "boolean") + { + let argStr = history[i].a[j]; + + if (glConsts[history[i].a[j]]) argStr = "gl." + glConsts[history[i].a[j]]; + str += argStr; + } + else if (typ == "string") + { + let argStr = history[i].a[j] + ""; + if (argStr.length > 20)argStr = argStr.substr(0, 20) + "...\""; + argStr = argStr.replace(/(\r\n|\n|\r)/gm, ""); + + str += "\"" + argStr + "\""; + } + else + { + let argStr = ""; + if (history[i].a[j] instanceof Float32Array) argStr = "{Float32Array(" + history[i].a[j].length + ")}"; + else if (history[i].a[j] instanceof Uint16Array) argStr = "{Uint16Array(" + history[i].a[j].length + ")}"; + else if (history[i].a[j] instanceof Uint8Array) argStr = "{Uint8Array(" + history[i].a[j].length + ")}"; + else argStr = JSON.stringify(history[i].a[j]) + ""; + + if (argStr == "{}") argStr = history[i].a[j]; + + if (argStr.length > 20)argStr = argStr.substr(0, 20) + "..."; + str += argStr; + } + } + str += " );"; + return str; +} + +function getHistoryAsString() +{ + let str = ""; + for (let i = 0; i < history.length; i++) + { + str += "gl." + getHistoryString(i) + "\n"; + } + return str; +} + +function profile(func, funcName) +{ + return function () + { + if (errorCount >= inLimit.get()) return; + + count++; + // const start = performance.now(), + let returnVal = func.apply(this, arguments); + + history.push({ "f": funcName, "a": arguments }); + + // op.patch.cgl.gl.getError(); + const error = glGetError(); + + if (error != gl.NO_ERROR) + { + let errStr = ""; + if (error == gl.OUT_OF_MEMORY) errStr = "OUT_OF_MEMORY"; + if (error == gl.INVALID_ENUM) errStr = "INVALID_ENUM"; + if (error == gl.INVALID_OPERATION) errStr = "INVALID_OPERATION"; + if (error == gl.INVALID_FRAMEBUFFER_OPERATION) errStr = "INVALID_FRAMEBUFFER_OPERATION"; + if (error == gl.INVALID_VALUE) errStr = "INVALID_VALUE"; + if (error == gl.CONTEXT_LOST_WEBGL) + { + this.aborted = true; + errStr = "CONTEXT_LOST_WEBGL"; + } + if (error == gl.NO_ERROR) errStr = "NO_ERROR"; + + console.warn("GL ERROR in frame " + countFrames + ", " + count + "th command: ", funcName); + console.log("arguments", arguments); + + console.log("gl error [" + this.canvas.id + "]: ", error, errStr); + op.patch.printTriggerStack(); + console.log((new Error()).stack); + + op.patch.printTriggerStack(); + if (errorCount == 0) + { + for (let i = 0; i < history.length; i++) + { + let str = getHistoryString(i); + console.log("[GL] " + i + ": gl." + str); + } + } + + const error2 = glGetError(); + console.log("err after", error2); + errorCount++; + + if (errorCount == inLimit.get()) console.log("gl Errors stopping after " + inLimit.get() + " errors"); + } + + return returnVal; + }; +} + +function start() +{ + for (const i in gl) + { + if (typeof gl[i] == "function" && i != "getError") + { + originals[i] = gl[i]; + const orig = originals[i]; + + gl[i] = profile(gl[i], "" + i); + } + } +} + +function end() +{ + cgl.debugOneFrame = false; + for (const i in gl) + if (originals[i] && typeof gl[i] == "function") + gl[i] = originals[i]; +} + + +}; + +Ops.Debug.GlLogErrors.prototype = new CABLES.Op(); +CABLES.OPS["26be55ca-23c0-4f22-bdea-0fd4c63b2067"]={f:Ops.Debug.GlLogErrors,objName:"Ops.Debug.GlLogErrors"}; + + + + +// ************************************************************** +// +// Ops.Debug.GlStates +// +// ************************************************************** + +Ops.Debug.GlStates = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const cgl = op.patch.cgl; + +const + exec = op.inTrigger("Update"), + next = op.outTrigger("Next"), + + outError = op.outBoolNum("glGetError"), + + depth = op.outBoolNum("Depthtest"), + depthStack = op.outBoolNum("Stack Depthtest"), + + depthWrite = op.outBoolNum("Depth Writing"), + depthWriteStack = op.outBoolNum("Stack Depth Writing"), + + depthFunc = op.outBoolNum("DepthFunc"), + depthFuncStack = op.outBoolNum("Stack DepthFunc"), + + blend = op.outBoolNum("Blend"), + blendStack = op.outBoolNum("Blend Stack"), + + cull = op.outBoolNum("Cull Mode"), + culling = op.outBoolNum("Face Culling"), + isShadowPass = op.outBool("Is Shadowpass"); + +exec.onTriggered = function () +{ + depth.set(cgl.gl.isEnabled(cgl.gl.DEPTH_TEST)); + depthStack.set(cgl.stateDepthTest()); + + depthWrite.set(cgl.gl.getParameter(cgl.gl.DEPTH_WRITEMASK)); + depthWriteStack.set(cgl.stateDepthWrite()); + + depthFunc.set(depthFuncToString(cgl.gl.getParameter(cgl.gl.DEPTH_FUNC))); + depthFuncStack.set(depthFuncToString(cgl.stateDepthFunc())); + + blend.set(cgl.gl.isEnabled(cgl.gl.BLEND)); + blendStack.set(cgl.stateBlend()); + + culling.set(cgl.gl.isEnabled(cgl.gl.CULL_FACE)); + + cull.set(cullModeToString(cgl.gl.getParameter(cgl.gl.CULL_FACE_MODE))); + + outError.set(errorToString(cgl.gl.getError())); + isShadowPass.set(cgl.frameStore.shadowPass); + + op.log(cgl._textureslots); + next.trigger(); +}; + +function errorToString(e) +{ + if (e == cgl.gl.NO_ERROR) return "NO_ERROR"; + if (e == cgl.gl.OUT_OF_MEMORY) return "OUT_OF_MEMORY"; + if (e == cgl.gl.INVALID_ENUM) return "INVALID_ENUM"; + if (e == cgl.gl.INVALID_OPERATION) return "INVALID_OPERATION"; + if (e == cgl.gl.INVALID_FRAMEBUFFER_OPERATION) return "INVALID_FRAMEBUFFER_OPERATION"; + if (e == cgl.gl.INVALID_VALUE) return "INVALID_VALUE"; + if (e == cgl.gl.CONTEXT_LOST_WEBGL) return "CONTEXT_LOST_WEBGL"; +} + +function cullModeToString(c) +{ + if (c == cgl.gl.FRONT) return "FRONT"; + if (c == cgl.gl.BACK) return "BACK"; + if (c == cgl.gl.FRONT_AND_BACK) return "FRONT_AND_BACK"; +} + +function depthFuncToString(f) +{ + if (f == cgl.gl.NEVER) return "NEVER"; + if (f == cgl.gl.LESS) return "LESS"; + if (f == cgl.gl.EQUAL) return "EQUAL"; + if (f == cgl.gl.LEQUAL) return "LEQUAL"; + if (f == cgl.gl.GREATER) return "GREATER"; + if (f == cgl.gl.NOTEQUAL) return "NOTEQUAL"; + if (f == cgl.gl.GEQUAL) return "GEQUAL"; + if (f == cgl.gl.ALWAYS) return "ALWAYS"; +} + + +}; + +Ops.Debug.GlStates.prototype = new CABLES.Op(); +CABLES.OPS["3e2bc72c-8af4-4fdb-a998-555aaf62cc9d"]={f:Ops.Debug.GlStates,objName:"Ops.Debug.GlStates"}; + + + + +// ************************************************************** +// +// Ops.Debug.ProfileGL +// +// ************************************************************** + +Ops.Debug.ProfileGL = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exec = op.inTrigger("Exec"); +const next = op.outTrigger("Next"); +const dump = op.inTriggerButton("Debug one Frame"); + +const gl = op.patch.cgl.gl; +const cgl = op.patch.cgl; + +const originals = {}; +const counts = {}; +const durations = {}; +let branches = {}; +let dumpFrame = false; + +const started = false; + +// const query = null; +// const ext = gl.getExtension("EXT_disjoint_timer_query_webgl2"); + +exec.onTriggered = function () +{ + if (dumpFrame) + { + start(); + resetStats(); + } + + next.trigger(); + + if (dumpFrame) + { + end(); + const rows = []; + let numGlCalls = 0; + for (const i in originals) + if (counts[i] > 0) + { + rows.push([i, counts[i], durations[i]]); + numGlCalls += counts[i]; + } + + console.table(rows); + + const rowsBranches = []; + for (const i in branches) + { + let count = 0; + for (const j in branches[i].counts) count += branches[i].counts[j]; + + op.log("branch", i, branches[i].counts); + rowsBranches.push([i, count, Math.round(count / numGlCalls * 100) + "%"]); + } + console.table(rowsBranches); + + op.log(CABLES.profilerBranchesTimes); + + resetStats(); + dumpFrame = false; + } +}; + +function profile(func, funcName) +{ + return function () + { + const start = performance.now(), + returnVal = func.apply(this, arguments), + duration = performance.now() - start; + + if (CABLES.profilerBranches && CABLES.profilerBranches.length > 0) + { + let branchName = CABLES.profilerBranches.join(" / "); + if (CABLES.profilerBranches.length == 0)branchName = "_unknown"; + branches[branchName] = branches[branchName] || {}; + branches[branchName].counts = branches[branchName].counts || {}; + branches[branchName].counts[funcName] = branches[branchName].counts[funcName] || 0; + branches[branchName].counts[funcName]++; + } + + durations[funcName] += duration; + counts[funcName]++; + return returnVal; + }; +} + +function resetStats() +{ + branches = {}; + CABLES.profilerBranchesTimes = {}; + + for (const i in originals) + { + durations[i] = 0; + counts[i] = 0; + } +} + +function start() +{ + op.log("-----------------------------"); + cgl.debugOneFrame = true; + for (const i in gl) + { + if (typeof gl[i] == "function") + { + originals[i] = gl[i]; + const orig = originals[i]; + + gl[i] = profile(gl[i], "" + i); + } + } +} + +function end() +{ + cgl.debugOneFrame = false; + for (const i in gl) + if (typeof gl[i] == "function") + gl[i] = originals[i]; +} + +dump.onTriggered = function () +{ + dumpFrame = true; +}; + + +}; + +Ops.Debug.ProfileGL.prototype = new CABLES.Op(); +CABLES.OPS["498a7c04-a1df-4318-8a60-048a7836710e"]={f:Ops.Debug.ProfileGL,objName:"Ops.Debug.ProfileGL"}; + + + + +// ************************************************************** +// +// Ops.Debug.StopWatch +// +// ************************************************************** + +Ops.Debug.StopWatch = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("exec"), + next = op.outTrigger("next"), + timeUsed = op.outNumber("Time used"), + outTImes = op.outArray("Times"); + +let times = []; +times.length = 100; +for (let i = 0; i < times.length; i++) +{ + times[i] = 0; +} + +let count = 0; +outTImes.set(times); + +exec.onTriggered = function () +{ + let start = performance.now(); + next.trigger(); + let end = performance.now(); + + let l = end - start; + times[count] = l; + count++; + if (count >= 100)count = 0; + + timeUsed.set(l); + outTImes.set(null); + outTImes.set(times); +}; + + +}; + +Ops.Debug.StopWatch.prototype = new CABLES.Op(); +CABLES.OPS["5dd205e6-b475-4a3b-9a3b-d242847f4b81"]={f:Ops.Debug.StopWatch,objName:"Ops.Debug.StopWatch"}; + + + + +// ************************************************************** +// +// Ops.Debug.Trace +// +// ************************************************************** + +Ops.Debug.Trace = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; + +const exePort = op.inTriggerButton("Trace"); + +exePort.onTriggered = console.trace; + + +}; + +Ops.Debug.Trace.prototype = new CABLES.Op(); +CABLES.OPS["1b52e2b7-b3a4-400e-9a97-1b27ce80deed"]={f:Ops.Debug.Trace,objName:"Ops.Debug.Trace"}; + + + + +// ************************************************************** +// +// Ops.Dev.Array.ArraySpreadSheet +// +// ************************************************************** + +Ops.Dev.Array.ArraySpreadSheet = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + spread = op.inArray("Spreadsheet"), + inNumColumns = op.inInt("Num Columns", 3), + outp = op.inSwitch("Format", ["Flat", "Objects", "Arrays"], "Flat"), + result = op.outArray("Array"), + outColNames = op.outArray("Column Names"); + +// spread.hidePort(); +spread.setUiAttribs({ "hidePort": true }); +inNumColumns.setUiAttribs({ "hidePort": true }); +outp.setUiAttribs({ "hidePort": true }); +// inNumColumns.hidePort(); + +outp.onChange = +spread.onChange = update; + +inNumColumns.onChange = updateUi; +updateUi(); + +function updateUi() +{ + spread.setUiAttribs({ + "display": "spreadsheet", + "spread_numColumns": inNumColumns.get() + }); +} + +function update() +{ + result.set(null); + + if (!spread.get()) return; + + outColNames.set(spread.get().colNames); + + if (outp.get() == "Flat") + { + result.set(asFlat()); + } + else if (outp.get() == "Objects" || outp.get() == "Arrays") + { + result.set(asObjectArray(outp.get() == "Objects")); + } +} + +function asFlat() +{ + const data = spread.get(); + data.cells = data.cells || []; + + if (!data.cols) return; + + const arr = []; + arr.length = data.cells.length * data.cols || 1; + let lastRow = 0; + for (let y = 0; y < data.cells.length; y++) + { + if (data.cells[y]) + for (let x = 0; x < data.cells[0].length; x++) + { + let v = data.cells[y][x] || null; + if (CABLES.UTILS.isNumeric(v)) v = parseFloat(v); + if (v !== "" && v !== null) lastRow = y; + + arr[x + (y * data.cols)] = v; + } + } + + let arrSize = (lastRow + 1) * data.cols; + + arr.length = arrSize; + + return arr; +} + +function asObjectArray(objects) +{ + const data = spread.get() || {}; + data.cells = data.cells || []; + + const arr = []; + arr.length = data.cells.length; + let lastRow = 0; + for (let y = 0; y < data.cells.length; y++) + { + let o = []; + if (objects) o = {}; + arr[y] = o; + + if (data.cells[y]) + for (let x = 0; x < data.cols; x++) + { + let v = data.cells[y][x] || null; + if (CABLES.UTILS.isNumeric(v)) v = parseFloat(v); + if (v !== "" && v !== null) lastRow = y; + + if (objects) o[getColName(data, x)] = v; + else o[x] = v; + } + } + arr.length = lastRow + 1; + + return arr; +} + +function getColName(data, c) +{ + if (data && data.colNames && data.colNames.length > c && data.colNames[c]) + { + return data.colNames[c]; + } + + let str = ""; + + while (c >= 0) + { + str = "abcdefghijklmnopqrstuvwxyz"[c % 26] + str; + c = Math.floor(c / 26) - 1; + } + + return str; +} + + +}; + +Ops.Dev.Array.ArraySpreadSheet.prototype = new CABLES.Op(); +CABLES.OPS["e8f8f23c-e7d3-44bf-9f1f-86230f4e533a"]={f:Ops.Dev.Array.ArraySpreadSheet,objName:"Ops.Dev.Array.ArraySpreadSheet"}; + + + + +// ************************************************************** +// +// Ops.Dev.Blueprint +// +// ************************************************************** + +Ops.Dev.Blueprint = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const patchIdIn = op.inString("externalPatchId", ""); +const subPatchIdIn = op.inString("subPatchId", ""); +const activeIn = op.inBool("active", false); +const gotoIn = op.inTriggerButton("Open patch"); +const resolveIn = op.inTriggerButton("Convert to SubPatch"); +const portsData = op.inString("portsData", "{}"); + +const loadingOut = op.outBool("loading", false); +let loadingId = null; +patchIdIn.setUiAttribs({ "hidePort": true, "greyout": true }); +subPatchIdIn.setUiAttribs({ "hidePort": true, "greyout": true }); +portsData.setUiAttribs({ "hidePort": true }); +portsData.setUiAttribs({ "hideParam": true }); + +gotoIn.setUiAttribs({ "greyout": true }); +gotoIn.setUiAttribs({ "hidePort": true }); + +resolveIn.setUiAttribs({ "greyout": true }); +resolveIn.setUiAttribs({ "hidePort": true }); + +let wasPasted = false; + +subPatchIdIn.onChange = () => +{ + if (!activeIn.get()) + { + op.setUiError("fetchOps", null); + } + if (!loadingOut.get() && activeIn.get() && patchIdIn.get() && subPatchIdIn.get()) + { + update(); + } +}; + +if (op.patch.isEditorMode()) +{ + gotoIn.onTriggered = function () + { + if (CABLES && CABLES.sandbox && CABLES.sandbox.getCablesUrl()) + { + window.open(CABLES.sandbox.getCablesUrl() + "/edit/" + patchIdIn.get(), "_blank"); + } + }; + + resolveIn.onTriggered = () => + { + if (CABLES && CABLES.CMD && CABLES.CMD.PATCH) + { + CABLES.CMD.PATCH.convertBlueprintToSubpatch(this); + } + }; + + patchIdIn.onChange = function () + { + if (patchIdIn.get()) + { + gotoIn.setUiAttribs({ "greyout": false }); + if (!activeIn.get()) + { + op.setUiError("fetchOps", null); + } + if (!loadingOut.get() && activeIn.get() && subPatchIdIn.get()) + { + update(); + } + } + else + { + gotoIn.setUiAttribs({ "greyout": true }); + } + }; +} + +const protectedPorts = [patchIdIn.id, subPatchIdIn.id, activeIn.id, portsData.id, loadingOut.id, gotoIn.id, resolveIn.id]; + +if (!activeIn.get()) +{ + op.setUiError("inactive", "blueprint is inactive", 0); +} + +const restorePorts = () => +{ + const oldPorts = getOldPorts(); + const portInKeys = Object.keys(oldPorts.portsIn); + if (op.patch.isEditorMode()) CABLES.UI.undo.pause(); + const newPorts = []; + for (let i = 0; i < portInKeys.length; i++) + { + const oldPortIn = oldPorts.portsIn[portInKeys[i]]; + const newPort = op.addInPort(new CABLES.Port(op, oldPortIn.name, oldPortIn.type)); + if (!wasPasted && Array.isArray(oldPortIn.links)) + { + oldPortIn.links.forEach((link) => + { + let parent = op.patch.getOpById(link.objOut); + if (parent) + { + const newLink = op.patch.link(parent, link.portOut, op, newPort.name); + if (newLink) newLink.ignoreInSerialize = true; + } + else + { + parent = op.patch.ops.find((subOp) => + { + return subOp.storage && + subOp.storage.blueprint && + subOp.storage.blueprint.originalOpId == link.objOut && + op.storage && + op.storage.blueprint && + subOp.storage.blueprint.blueprintOpId == op.storage.blueprint.blueprintOpId; + }); + if (parent) + { + const newLink = op.patch.link(parent, link.portOut, op, newPort.name); + if (newLink) newLink.ignoreInSerialize = true; + } + } + }); + } + if (!newPort.isLinked()) + { + newPort.set(oldPortIn.value); + } + newPort.onLinkChanged = savePortData; + + if (oldPortIn.title) + { + newPort.setUiAttribs({ "title": oldPortIn.title }); + } + newPorts.push(newPort); + } + op.setPortGroup("Blueprint Ports", newPorts); + + const portOutKeys = Object.keys(oldPorts.portsOut); + for (let i = 0; i < portOutKeys.length; i++) + { + const oldPortOut = oldPorts.portsOut[portOutKeys[i]]; + const newPort = op.addOutPort(new CABLES.Port(op, oldPortOut.name, oldPortOut.type)); + if (!wasPasted && Array.isArray(oldPortOut.links)) + { + oldPortOut.links.forEach((link) => + { + let parent = op.patch.getOpById(link.objIn); + if (parent) + { + const newLink = op.patch.link(op, newPort.name, parent, link.portIn); + if (newLink) newLink.ignoreInSerialize = true; + } + else + { + parent = op.patch.ops.find((subOp) => + { + return subOp.storage && + subOp.storage.blueprint && + subOp.storage.blueprint.originalOpId == link.objIn && + op.storage && + op.storage.blueprint && + subOp.storage.blueprint.blueprintOpId == op.storage.blueprint.blueprintOpId; + }); + if (parent) + { + const newLink = op.patch.link(op, newPort.name, parent, link.portIn); + if (newLink) newLink.ignoreInSerialize = true; + } + } + }); + newPort.onLinkChanged = savePortData; + + if (oldPortOut.title) + { + newPort.setUiAttribs({ "title": oldPortOut.title }); + } + } + } + if (op.patch.isEditorMode()) CABLES.UI.undo.resume(); +}; + +activeIn.onChange = () => +{ + if (!loadingOut.get()) + { + if (activeIn.get()) + { + op.setUiError("inactive", null); + update(); + } + else + { + op.setUiError("fetchOps", null); + op.setUiError("inactive", "blueprint is inactive", 0); + removeImportedOps(); + if (wasPasted) wasPasted = false; + } + } +}; + +op.onLoaded = () => +{ + if (op.uiAttribs) + { + wasPasted = op.uiAttribs.pasted; + } + cleanupPorts(); + restorePorts(); +}; + +op.onDelete = removeImportedOps; + +function update() +{ + loadingOut.set(true); + const patch = op.patch; + const patchId = patchIdIn.get(); + const subPatchId = subPatchIdIn.get(); + const blueprintId = patchId + "-" + subPatchId; + + loadingId = op.patch.loading.start("blueprint", blueprintId); + + if (patch.isEditorMode()) + { + const options = { + "blueprintId": blueprintId, + "patchId": patchId, + "subPatchId": subPatchId, + "opId": op.id, + "blueprintSubpatchId": op.uiAttribs.subPatch + }; + + CABLES.sandbox.getBlueprintOps(options, (err, response) => + { + op.setUiError("fetchOps", null); + if (!err) + { + removeImportedOps(); + const blueprintData = {}; + blueprintData.ops = response.data.ops; + blueprintData.settings = op.patch.settings; + deSerializeBlueprint(blueprintData, subPatchId, true); + } + else + { + if (err.code === 403) + { + op.setUiError("fetchOps", "You do not have permission to use this Blueprint"); + } + else if (err.code === 404 && (gui.patchId === patchId)) + { + op.setUiError("fetchOps", "Save the patch and reload before using this Blueprint"); + } + else + { + op.setUiError("fetchOps", "Error fetching Blueprint, code: " + err.code + " (" + err.msg + ")"); + } + } + loadingOut.set(false); + op.patch.loading.finished(loadingId); + if (wasPasted) + { + wasPasted = false; + } + }); + } + else if (CABLES.talkerAPI) + { + // use this to workaround /viewer/ and /p/ not being "isEditorMode" but also not having exported assets + const callbackTalkerApi = (options, next) => + { + if (options.blueprint && options.blueprint.data.blueprintOpId === op.id) + { + const blueprintData = options.blueprint; + blueprintData.settings = op.patch.settings; + blueprintData.ops = blueprintData.data.ops; + deSerializeBlueprint(blueprintData, subPatchId, false); + loadingOut.set(false); + op.patch.loading.finished(loadingId); + if (wasPasted) + { + wasPasted = false; + } + CABLES.talkerAPI.removeEventListener(callbackTalkerApi); + } + }; + CABLES.talkerAPI.addEventListener("blueprint", callbackTalkerApi); + CABLES.talkerAPI.send("sendBlueprint", { "url": "/" + blueprintId + "/" + patchId + "/" + subPatchId + "/" + op.id + "/" + op.uiAttribs.subPatch }); + } + else + { + let exportId = op.id; + if (CABLES.blueprints && CABLES.blueprints[exportId]) + { + const blueprintData = CABLES.blueprints[exportId]; + blueprintData.settings = op.patch.settings; + // for some reason we have to do this in a 0ms timeout to make + // sure nested blueprints are not loaded before this one created all the ops... + setTimeout(() => + { + deSerializeBlueprint(blueprintData, subPatchId, false); + loadingOut.set(false); + op.patch.loading.finished(loadingId); + if (wasPasted) + { + wasPasted = false; + } + }, 0); + } + else + { + const blueprintUrl = op.patch.config.prefixJsPath + op.patch.getJsPath() + exportId + ".json"; + CABLES.ajax( + blueprintUrl, + function (err, data) + { + if (!err) + { + const blueprintData = JSON.parse(data); + blueprintData.settings = op.patch.settings; + deSerializeBlueprint(blueprintData, subPatchId, false); + } + else + { + op.logError("failed to load blueprint from", blueprintUrl, err); + } + loadingOut.set(false); + op.patch.loading.finished(loadingId); + if (wasPasted) + { + wasPasted = false; + } + } + ); + } + } +} + +function deSerializeBlueprint(data, subPatchId, editorMode) +{ + resolveIn.setUiAttribs({ "greyout": true }); + if (Array.isArray(data.ops) && data.ops.length > 0) + { + let listenerId; + const cb = () => + { + const parentSubPatch = op.patch.ops.find((subOp) => + { + return subOp.storage && + subOp.storage.blueprint && + subOp.storage.blueprint.isParentSubPatch && + subOp.storage.blueprint.blueprintOpId == op.id; + } + ); + if (parentSubPatch) + { + op.setUiAttrib({ "extendTitle": parentSubPatch.uiAttribs.title }); + setupPorts(parentSubPatch); + } + op.patch.removeEventListener(listenerId); + if (editorMode) + { + CABLES.UI.undo.resume(); + if (originalSaveState === true) + { + gui.setStateSaved(); + } + resolveIn.setUiAttribs({ "greyout": false }); + } + }; + + let originalSaveState = null; + if (editorMode) + { + originalSaveState = gui.getSavedState(); + CABLES.UI.undo.pause(); + + gui.serverOps.loadProjectDependencies(data, () => + { + listenerId = op.patch.addEventListener("patchLoadEnd", cb); + data.settings = op.patch.settings; + data.namespace = op.patch.namespace; + data.name = op.patch.name; + op.patch.deSerialize(data, false); + const originalSubPatchId = gui.patchView.getCurrentSubPatch(); + gui.patchView.setCurrentSubPatch(originalSubPatchId); + }); + } + else + { + listenerId = op.patch.addEventListener("patchLoadEnd", cb); + op.patch.deSerialize(data, false); + } + } +} + +function removeImportedOps() +{ + const parentSubPatch = op.patch.ops.find((subOp) => + { + return subOp.storage && + subOp.storage.blueprint && + subOp.storage.blueprint.isParentSubPatch && + subOp.storage.blueprint.blueprintOpId == op.id; + } + ); + if (parentSubPatch) + { + if (op.patch.isEditorMode()) CABLES.UI.undo.pause(); + op.patch.deleteOp(parentSubPatch.id, parentSubPatch.storage.blueprint.blueprintOpId); + if (op.patch.isEditorMode()) CABLES.UI.undo.resume(); + } +} + +const getOldPorts = () => +{ + const oldPorts = JSON.parse(portsData.get()); + let oldPortsOut = {}; + if (oldPorts.portsOut) + { + oldPortsOut = oldPorts.portsOut; + } + let oldPortsIn = {}; + if (oldPorts.portsIn) + { + oldPortsIn = oldPorts.portsIn; + } + return { "portsIn": oldPortsIn, "portsOut": oldPortsOut }; +}; + +const cleanupPorts = () => +{ + const removeInPorts = []; + const removeOutPorts = []; + + op.portsIn.forEach((port) => + { + if (!protectedPorts.includes(port.id)) + { + removeInPorts.push(port); + } + }); + op.portsOut.forEach((port) => + { + if (!protectedPorts.includes(port.id)) + { + removeOutPorts.push(port); + } + }); + + removeInPorts.forEach((port) => + { + removeInPort(port); + op.emitEvent("onPortRemoved", {}); + }); + + removeOutPorts.forEach((port) => + { + removeOutPort(port); + op.emitEvent("onPortRemoved", {}); + }); + + if (removeOutPorts.length > 0 || removeInPorts.length > 0) + { + op.emitEvent("onUiAttribsChange", {}); + } +}; + +const removeInPort = (port) => +{ + port.removeLinks(); + for (let ipi = 0; ipi < op.portsIn.length; ipi++) + { + if (op.portsIn[ipi] == port) + { + op.portsIn.splice(ipi, 1); + return; + } + } +}; + +const removeOutPort = (port) => +{ + port.removeLinks(); + for (let ipi = 0; ipi < op.portsOut.length; ipi++) + { + if (op.portsOut[ipi] == port) + { + op.portsOut.splice(ipi, 1); + return; + } + } +}; + +function setupPorts(parentSubPatch) +{ + const subPatchDataPort = parentSubPatch.portsIn.find((port) => { return port.name === "dataStr"; }); + if (!subPatchDataPort) return; + if (!subPatchDataPort.get()) return; + + const oldPorts = getOldPorts(); + cleanupPorts(); + + const subPatchData = JSON.parse(subPatchDataPort.get()); + const subPatchPortsIn = subPatchData.ports || []; + const subPatchPortsOut = subPatchData.portsOut || []; + let i = 0; + + if (op.patch.isEditorMode()) CABLES.UI.undo.pause(); + const newPorts = []; + for (i = 0; i < subPatchPortsIn.length; i++) + { + if (!op.getPortByName(subPatchPortsIn[i].name)) + { + const subPatchPort = parentSubPatch.portsIn.find((port) => { return port.name == subPatchPortsIn[i].name; }); + const newPort = op.addInPort(new CABLES.Port(op, subPatchPort.name, subPatchPort.type)); + + if (subPatchPort) + { + switch (subPatchPort.type) + { + case CABLES.OP_PORT_TYPE_FUNCTION: + newPort.onTriggered = () => + { + subPatchPort.onTriggered(); + }; + break; + default: + newPort.onChange = () => + { + subPatchPort.set(newPort.get()); + if (!newPort.isLinked()) + { + savePortData(); + } + }; + } + } + + if (oldPorts.portsIn.hasOwnProperty(newPort.name)) + { + if (!wasPasted && Array.isArray(oldPorts.portsIn[newPort.name].links)) + { + oldPorts.portsIn[newPort.name].links.forEach((link) => + { + let parent = op.patch.getOpById(link.objOut); + if (parent) + { + const newLink = op.patch.link(parent, link.portOut, op, newPort.name); + if (newLink) newLink.ignoreInSerialize = true; + } + else + { + parent = op.patch.ops.find((subOp) => + { + return subOp.storage && + subOp.storage.blueprint && + subOp.storage.blueprint.originalOpId == link.objOut && + op.storage && + op.storage.blueprint && + subOp.storage.blueprint.blueprintOpId == op.storage.blueprint.blueprintOpId; + }); + if (parent) + { + const newLink = op.patch.link(parent, link.portOut, op, newPort.name); + if (newLink) newLink.ignoreInSerialize = true; + } + } + }); + } + if (!newPort.isLinked()) + { + newPort.set(oldPorts.portsIn[newPort.name].value); + } + } + newPort.onLinkChanged = savePortData; + + if (subPatchPort.title) + { + newPort.setUiAttribs({ "title": subPatchPortsIn[i].title }); + } + else if (subPatchPort.uiAttribs && subPatchPort.uiAttribs.title) + { + newPort.setUiAttribs({ "title": subPatchPort.uiAttribs.title }); + } + if (subPatchPort.uiAttribs && subPatchPort.uiAttribs.objType) + { + newPort.setUiAttribs({ "objType": subPatchPort.uiAttribs.objType }); + } + newPorts.push(newPort); + } + } + op.setPortGroup("Blueprint Ports", newPorts); + + for (i = 0; i < subPatchPortsOut.length; i++) + { + if (!op.getPortByName(subPatchPortsOut[i].name)) + { + const patchPortIn = parentSubPatch.portsIn.find((port) => { return port.name === "patchId"; }); + const patchOutputOP = op.patch.getSubPatchOp(patchPortIn.value, "Ops.Ui.PatchOutput"); + if (patchOutputOP.portsIn) + { + const subPatchPort = patchOutputOP.portsIn.find((port) => { return port.name == subPatchPortsOut[i].name; }); + const newPort = op.addOutPort(new CABLES.Port(op, subPatchPort.name, subPatchPort.type)); + newPort.ignoreValueSerialize = true; + + if (subPatchPort) + { + switch (subPatchPort.type) + { + case CABLES.OP_PORT_TYPE_FUNCTION: + subPatchPort.onTriggered = () => + { + newPort.trigger(); + }; + break; + default: + subPatchPort.onChange = () => + { + newPort.set(subPatchPort.get()); + }; + } + newPort.set(subPatchPort.get()); + } + + if (oldPorts.portsOut.hasOwnProperty(newPort.name)) + { + if (!wasPasted && Array.isArray(oldPorts.portsOut[newPort.name].links)) + { + oldPorts.portsOut[newPort.name].links.forEach((link) => + { + let parent = op.patch.getOpById(link.objIn); + if (parent) + { + const newLink = op.patch.link(op, newPort.name, parent, link.portIn); + if (newLink) newLink.ignoreInSerialize = true; + } + else + { + parent = op.patch.ops.find((subOp) => + { + return subOp.storage && + subOp.storage.blueprint && + subOp.storage.blueprint.originalOpId == link.objIn && + op.storage && + op.storage.blueprint && + subOp.storage.blueprint.blueprintOpId == op.storage.blueprint.blueprintOpId; + }); + if (parent) + { + const newLink = op.patch.link(op, newPort.name, parent, link.portIn); + if (newLink) newLink.ignoreInSerialize = true; + } + } + }); + } + } + newPort.onLinkChanged = savePortData; + + if (subPatchPort.title) + { + newPort.setUiAttribs({ "title": subPatchPortsOut[i].title }); + } + else if (subPatchPort.uiAttribs && subPatchPort.uiAttribs.title) + { + newPort.setUiAttribs({ "title": subPatchPort.uiAttribs.title }); + } + + if (subPatchPort.uiAttribs && subPatchPort.uiAttribs.objType) + { + newPort.setUiAttribs({ "objType": subPatchPort.uiAttribs.objType }); + } + } + } + } + savePortData(); + if (op.patch.isEditorMode()) CABLES.UI.undo.resume(); +} + +function savePortData() +{ + const newPortsData = { "portsIn": {}, "portsOut": {} }; + op.portsIn.forEach((port) => + { + if (!protectedPorts.includes(port.id)) + { + const portData = { + "name": port.name, + "title": port.title, + "type": port.type, + "links": [] + }; + if (!port.links || port.links.length === 0) portData.value = port.get(); + port.links.forEach((link) => + { + link.ignoreInSerialize = true; + const linkData = { + "objOut": link.portOut.parent.id, + "portOut": link.portOut.name + }; + portData.links.push(linkData); + }); + newPortsData.portsIn[port.name] = portData; + } + }); + + op.portsOut.forEach((port) => + { + if (!protectedPorts.includes(port.id)) + { + const portData = { + "name": port.name, + "title": port.title, + "type": port.type, + "links": [] + }; + if (!port.links || port.links.length === 0) + { + let portValue = port.get(); + try + { + JSON.stringify(portValue); + } + catch (e) + { + portValue = null; + } + portData.value = portValue; + } + port.links.forEach((link) => + { + link.ignoreInSerialize = true; + const linkData = { + "objIn": link.portIn.parent.id, + "portIn": link.portIn.name + }; + portData.links.push(linkData); + }); + newPortsData.portsOut[port.name] = portData; + } + }); + const serializedPortsData = JSON.stringify(newPortsData); + portsData.set(serializedPortsData); +} + + +}; + +Ops.Dev.Blueprint.prototype = new CABLES.Op(); +CABLES.OPS["3b25fb24-2a1f-4e5a-a18e-e08911a94030"]={f:Ops.Dev.Blueprint,objName:"Ops.Dev.Blueprint"}; + + + + +// ************************************************************** +// +// Ops.Dev.BranchProfiler +// +// ************************************************************** + +Ops.Dev.BranchProfiler = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Exec"), + outNext = op.outTrigger("Next"), + outProfilerStack = op.outObject("Profiler Data"); + +op.patch.cgl.frameStore.branchProfiler = op.patch.cgl.frameStore.branchProfiler || {}; + +inExec.onTriggered = () => +{ + op.patch.cgl.frameStore.branchProfiler = {}; + + op.patch.cgl.frameStore.branchStack = op.patch.cgl.frameStore.branchStack || new CABLES.BranchStack(); + + op.patch.cgl.frameStore.branchStack.start(); + + outNext.trigger(); + + op.patch.cgl.frameStore.branchStack.finish(); + + outProfilerStack.set(op.patch.cgl.frameStore.branchStack); +}; + + +}; + +Ops.Dev.BranchProfiler.prototype = new CABLES.Op(); +CABLES.OPS["5bc375f6-59f6-40f6-bc26-7b23e28d8bf2"]={f:Ops.Dev.BranchProfiler,objName:"Ops.Dev.BranchProfiler"}; + + + + +// ************************************************************** +// +// Ops.Dev.BranchProfilerBranch +// +// ************************************************************** + +Ops.Dev.BranchProfilerBranch = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Exec"), + inName = op.inString("Branch Name", "default"), + outNext = op.outTrigger("Next"), + outDur = op.outNumber("Duration"); + +op.patch.cgl.frameStore.branchProfiler = op.patch.cgl.frameStore.branchProfiler || {}; + +inExec.onTriggered = () => +{ + op.patch.cgl.frameStore.branchStack = op.patch.cgl.frameStore.branchStack || new CABLES.BranchStack(); + + const c = op.patch.cgl.frameStore.branchStack.push(inName.get()); + + outNext.trigger(); + + if (op.patch.cgl.frameStore.branchStack.current == c) op.patch.cgl.frameStore.branchStack.pop(); + + outDur.set(c.dur); +}; + + +}; + +Ops.Dev.BranchProfilerBranch.prototype = new CABLES.Op(); +CABLES.OPS["2082b704-0283-4645-b741-1e1955f28b66"]={f:Ops.Dev.BranchProfilerBranch,objName:"Ops.Dev.BranchProfilerBranch"}; + + + + +// ************************************************************** +// +// Ops.Dev.BranchProfilerBranchEnd +// +// ************************************************************** + +Ops.Dev.BranchProfilerBranchEnd = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Exec"), + outNext = op.outTrigger("Next"); + +op.patch.cgl.frameStore.branchProfiler = op.patch.cgl.frameStore.branchProfiler || {}; + +inExec.onTriggered = ()=> +{ + if(op.patch.cgl.frameStore.branchStack) op.patch.cgl.frameStore.branchStack.pop(); + outNext.trigger(); +}; + + +}; + +Ops.Dev.BranchProfilerBranchEnd.prototype = new CABLES.Op(); +CABLES.OPS["2c5f3947-9962-49ee-b09b-084bf8717f00"]={f:Ops.Dev.BranchProfilerBranchEnd,objName:"Ops.Dev.BranchProfilerBranchEnd"}; + + + + +// ************************************************************** +// +// Ops.Dev.ColorAreaSDF_v5 +// +// ************************************************************** + +Ops.Dev.ColorAreaSDF_v5 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"colorarea_frag":"\nvec3 MOD_size=vec3(MOD_inSizeAmountFalloffSizeX.x);\n#ifdef MOD_DOSCALE\n MOD_size*=MOD_scale.xyz;\n#endif\n\nvec3 MOD_col=MOD_color;\n\n#ifdef MOD_USE_TEX\n MOD_col=texture(MOD_tex,gl_FragCoord.xy/float(textureSize(MOD_tex,0).xy)).rgb;\n#endif\n\n\n\n#ifdef MOD_AREA_SPHERE\n float MOD_de=MOD_sdSphere(MOD_pos.xyz-MOD_vertPos.xyz,MOD_size.x);\n#endif\n\n#ifdef MOD_AREA_BOX\n float MOD_r=MOD_scale.w;\n MOD_r*=MOD_inSizeAmountFalloffSizeX.x;\n float MOD_de=MOD_sdRoundBox(MOD_pos.xyz-MOD_vertPos.xyz,MOD_size-MOD_r,MOD_r);\n#endif\n\n#ifdef MOD_AREA_TRIPRISM\n float MOD_de=MOD_sdTriPrism(MOD_pos.xyz-MOD_vertPos.xyz,vec2(MOD_size.x,MOD_size.z));\n#endif\n\n#ifdef MOD_AREA_HEXPRISM\n float MOD_de=MOD_sdHexPrism(MOD_pos.xyz-MOD_vertPos.xyz,vec2(MOD_size.x,MOD_size.z));\n#endif\n\n\n\n// #ifndef MOD_AREA_SPHERE\n// #ifndef MOD_AREA_BOX\n// float MOD_de=1.0-smoothstep(MOD_inSizeAmountFalloffSizeX.z*MOD_inSizeAmountFalloffSizeX.x,MOD_inSizeAmountFalloffSizeX.x,MOD_de);\n// #endif\n// #endif\n\n#ifdef MOD_AREA_AXIS_X\n float MOD_de=abs(MOD_pos.x-MOD_vertPos.x);\n#endif\n#ifdef MOD_AREA_AXIS_Y\n float MOD_de=abs(MOD_pos.y-MOD_vertPos.y);\n#endif\n#ifdef MOD_AREA_AXIS_Z\n float MOD_de=abs(MOD_pos.z-MOD_vertPos.z);\n#endif\n\n#ifdef MOD_AREA_AXIS_X_INFINITE\n float MOD_de=MOD_pos.x-MOD_vertPos.x;\n#endif\n#ifdef MOD_AREA_AXIS_Y_INFINITE\n float MOD_de=MOD_pos.y-MOD_vertPos.y;\n#endif\n#ifdef MOD_AREA_AXIS_Z_INFINITE\n float MOD_de=MOD_pos.z-MOD_vertPos.z;\n#endif\n\n\nMOD_de=1.0-MOD_map(\n MOD_de,\n 0.0, MOD_inSizeAmountFalloffSizeX.z,\n 0.0,1.0\n );\n\n\n#ifdef MOD_AREA_INVERT\n MOD_de=1.0-MOD_de;\n#endif\n\n#ifdef MOD_BLEND_NORMAL\n col.rgb=mix(col.rgb,MOD_col, MOD_de*MOD_inSizeAmountFalloffSizeX.y);\n#endif\n\n\n#ifdef MOD_BLEND_MULTIPLY\n col.rgb=mix(col.rgb,col.rgb*MOD_col,MOD_de*MOD_inSizeAmountFalloffSizeX.y);\n#endif\n\n#ifdef MOD_BLEND_ADD\n col.rgb+=MOD_de*MOD_inSizeAmountFalloffSizeX.y*MOD_col;\n#endif\n\n\n#ifdef MOD_BLEND_OPACITY\n col.a*=(1.0-MOD_de*MOD_inSizeAmountFalloffSizeX.y);\n#endif\n\n#ifdef MOD_BLEND_DISCARD\n if(MOD_de*MOD_inSizeAmountFalloffSizeX.y>=0.999)discard;\n#endif\n\n// col.rgb=vec3(distance(MOD_vertPos.xyz,MOD_pos.xyz))*0.1\n// col.rgb=MOD_pos.xyz;","colorarea_head_frag":"IN vec4 MOD_vertPos;\n\nfloat MOD_map(float value,float min1,float max1,float min2,float max2)\n{\n return max(min2,min(max2,min2 + (value - min1) * (max2 - min2) / (max1 - min1)));\n\n}\n\n\nfloat MOD_sdSphere( vec3 p, float s )\n{\n return length(p)-s;\n}\n\n\nfloat MOD_sdRoundBox( vec3 p, vec3 b, float r )\n{\n vec3 q = abs(p) - b;\n return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0) - r;\n}\n\nfloat MOD_sdTriPrism( vec3 p, vec2 h )\n{\n vec3 q = abs(p);\n return max(q.z-h.y,max(q.x*0.866025+p.y*0.5,-p.y)-h.x*0.5);\n}\n\nfloat MOD_sdHexPrism( vec3 p, vec2 h )\n{\n const vec3 k = vec3(-0.8660254, 0.5, 0.57735);\n p = abs(p);\n p.xy -= 2.0*min(dot(k.xy, p.xy), 0.0)*k.xy;\n vec2 d = vec2(\n length(p.xy-vec2(clamp(p.x,-k.z*h.x,k.z*h.x), h.x))*sign(p.y-h.x),\n p.z-h.y );\n return min(max(d.x,d.y),0.0) + length(max(d,0.0));\n}\n\n",}; +const + render = op.inTrigger("Render"), + inArea = op.inValueSelect("Area", ["Sphere", "Box", "Tri Prism", "Hex Prism", "Axis X", "Axis Y", "Axis Z", "Axis X Infinite", "Axis Y Infinite", "Axis Z Infinite"], "Sphere"), + inSize = op.inValue("Size", 1), + roundNess = op.inFloatSlider("Roundness", 0), + inAmount = op.inValueSlider("Amount", 0.5), + inFalloff = op.inFloat("Falloff", 0), + inInvert = op.inValueBool("Invert"), + inBlend = op.inSwitch("Blend ", ["Normal", "Multiply", "Opacity", "Add", "Discard"], "Normal"), + r = op.inValueSlider("r", Math.random()), + g = op.inValueSlider("g", Math.random()), + b = op.inValueSlider("b", Math.random()), + x = op.inValue("x"), + y = op.inValue("y"), + z = op.inValue("z"), + doScale = op.inBool("Change Size", false), + sizeX = op.inFloat("Size X", 1), + sizeY = op.inFloat("Size Y", 1), + sizeZ = op.inFloat("Size Z", 1), + inTex = op.inTexture("Texture"), + + inWorldSpace = op.inValueBool("WorldSpace", true), + inPrio = op.inBool("Priority", true), + next = op.outTrigger("Next"); + +op.setPortGroup("Scale", [doScale, sizeX, sizeZ, sizeY]); +op.setPortGroup("Position", [x, y, z]); +op.setPortGroup("Color", [inBlend, r, g, b]); +r.setUiAttribs({ "colorPick": true }); + +const cgl = op.patch.cgl; + +const srcHeadVert = "" + .endl() + "OUT vec4 MOD_vertPos;" + .endl(); + +const srcBodyVert = "" + .endl() + "#ifndef MOD_WORLDSPACE" + .endl() + " MOD_vertPos=vec4(vPosition,1.0);" + .endl() + "#endif" + + .endl() + "#ifdef MOD_WORLDSPACE" + .endl() + " MOD_vertPos=mMatrix*pos;" + .endl() + "#endif" + .endl(); + +inWorldSpace.onChange = + inTex.onLinkChanged = + inArea.onChange = + inInvert.onChange = + doScale.onChange = + inBlend.onChange = updateDefines; + +render.onTriggered = doRender; + +const vertModTitle = "vert_" + op.name; +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "priority": 2, + "title": vertModTitle, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": srcHeadVert, + "srcBodyVert": srcBodyVert +}); + +mod.addModule({ + "title": op.name, + "name": "MODULE_COLOR", + "srcHeadFrag": attachments.colorarea_head_frag, + "srcBodyFrag": attachments.colorarea_frag +}); + +mod.addUniform("4f", "MOD_inSizeAmountFalloffSizeX", inSize, inAmount, inFalloff, 0); +mod.addUniform("3f", "MOD_color", r, g, b); +mod.addUniform("3f", "MOD_pos", x, y, z); +mod.addUniform("4f", "MOD_scale", sizeX, sizeY, sizeZ, roundNess); +mod.addUniform("t", "MOD_tex"); + +updateDefines(); + +inPrio.onChange = updatePrio; +updatePrio(); + +function updatePrio() +{ + mod.removeModule(vertModTitle); + + const vmod = { + // "priority": 0, + "title": vertModTitle, + "name": "MODULE_VERTEX_POSITION", + srcHeadVert, + srcBodyVert + }; + + if (inPrio.get()) vmod.priority = 2; + + mod.addModule(vmod); +} + +function updateDefines() +{ + mod.toggleDefine("MOD_BLEND_NORMAL", inBlend.get() == "Normal"); + mod.toggleDefine("MOD_BLEND_OPACITY", inBlend.get() == "Opacity"); + mod.toggleDefine("MOD_BLEND_MULTIPLY", inBlend.get() == "Multiply"); + mod.toggleDefine("MOD_BLEND_DISCARD", inBlend.get() == "Discard"); + mod.toggleDefine("MOD_BLEND_ADD", inBlend.get() == "Add"); + + mod.toggleDefine("MOD_AREA_SIZE", doScale.get()); + + mod.toggleDefine("MOD_AREA_INVERT", inInvert.get()); + mod.toggleDefine("MOD_WORLDSPACE", inWorldSpace.get()); + + mod.toggleDefine("MOD_AREA_AXIS_X", inArea.get() == "Axis X"); + mod.toggleDefine("MOD_AREA_AXIS_Y", inArea.get() == "Axis Y"); + mod.toggleDefine("MOD_AREA_AXIS_Z", inArea.get() == "Axis Z"); + mod.toggleDefine("MOD_AREA_AXIS_X_INFINITE", inArea.get() == "Axis X Infinite"); + mod.toggleDefine("MOD_AREA_AXIS_Y_INFINITE", inArea.get() == "Axis Y Infinite"); + mod.toggleDefine("MOD_AREA_AXIS_Z_INFINITE", inArea.get() == "Axis Z Infinite"); + mod.toggleDefine("MOD_AREA_SPHERE", inArea.get() == "Sphere"); + mod.toggleDefine("MOD_AREA_BOX", inArea.get() == "Box"); + mod.toggleDefine("MOD_AREA_TRIPRISM", inArea.get() == "Tri Prism"); + mod.toggleDefine("MOD_AREA_HEXPRISM", inArea.get() == "Hex Prism"); + + mod.toggleDefine("MOD_DOSCALE", doScale.get()); + + // mod.removeUniform("3f", "MOD_scale",sizeX,sizeY,sizeZ); + sizeX.setUiAttribs({ "greyout": !doScale.get() }); + sizeY.setUiAttribs({ "greyout": !doScale.get() }); + sizeZ.setUiAttribs({ "greyout": !doScale.get() }); + + roundNess.setUiAttribs({ "greyout": inArea.get() != "Box" }); + + mod.toggleDefine("MOD_USE_TEX", inTex.isLinked()); +} + +function drawHelpers() +{ + if (cgl.frameStore.shadowPass) return; + if (cgl.shouldDrawHelpers(op)) gui.setTransformGizmo({ "posX": x, "posY": y, "posZ": z }); +} + +function doRender() +{ + // if(doScale.get()) mod.setUniformValue("MOD_scale",[sizeX.get(),sizeY.get(),sizeZ.get()]); + mod.bind(); + + let tex = inTex.get(); + + if (!tex) tex = CGL.Texture.getEmptyTexture(cgl).tex; + else tex = tex.tex; + + mod.pushTexture("MOD_tex", tex); + + drawHelpers(); + next.trigger(); + + mod.unbind(); +} + + +}; + +Ops.Dev.ColorAreaSDF_v5.prototype = new CABLES.Op(); +CABLES.OPS["3ea4bb8a-d2a0-4600-9d98-83d5a091ea4f"]={f:Ops.Dev.ColorAreaSDF_v5,objName:"Ops.Dev.ColorAreaSDF_v5"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.Geometry.CopyGeometry +// +// ************************************************************** + +Ops.Dev.Gl.Geometry.CopyGeometry = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + geometry = op.inObject("Geometry"), + outGeom = op.outObject("Result"); + +geometry.onChange = update; + +function update() +{ + let oldGeom = geometry.get(); + + if (oldGeom) + { + let geom = oldGeom.copy(); + + outGeom.set(geom); + } + else outGeom.set(null); +} + + +}; + +Ops.Dev.Gl.Geometry.CopyGeometry.prototype = new CABLES.Op(); +CABLES.OPS["b15f57c2-4b0c-45de-962b-dd249779addf"]={f:Ops.Dev.Gl.Geometry.CopyGeometry,objName:"Ops.Dev.Gl.Geometry.CopyGeometry"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.Abs +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.Abs = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + invec = op.inObject("input", null, "sg_float"), + outvec = op.outObject("result", null, "sg_float"); + +new CGL.ShaderGraphOp(this); +op.shaderFunc = "abs"; + +invec.onLinkChanged = () => +{ + CGL.ShaderGraphOp.getMaxGenTypeFromPorts([invec], [invec, outvec]); +}; + + +}; + +Ops.Dev.Gl.ShaderGraph.Abs.prototype = new CABLES.Op(); +CABLES.OPS["2543cfb4-c1e2-44f1-bfd4-de6cc8143b8b"]={f:Ops.Dev.Gl.ShaderGraph.Abs,objName:"Ops.Dev.Gl.ShaderGraph.Abs"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.Color +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.Color = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inColor = op.inDropDown("Color", ["Red", "Green", "Blue", "Cyan", "Pink", "Yellow", "White", "Black"], "Red"); +const outvec = op.outObject("result", null, "sg_vec4"); + +const sg = new CGL.ShaderGraphOp(this); +inColor.onChange = update; +update(); + +function update() +{ + if (inColor.get() == "Red") op.shaderVar = "vec4(1.,0.,0.,1.)"; + if (inColor.get() == "Green") op.shaderVar = "vec4(0.,1.,0.,1.)"; + if (inColor.get() == "Blue") op.shaderVar = "vec4(0.,0.,1.,1.)"; + if (inColor.get() == "Cyan") op.shaderVar = "vec4(0.,1.,1.,1.)"; + if (inColor.get() == "Pink") op.shaderVar = "vec4(1.,0.,1.,1.)"; + if (inColor.get() == "Yellow") op.shaderVar = "vec4(1.,1.,0.,1.)"; + + sg.updateGraph(); +} + + +}; + +Ops.Dev.Gl.ShaderGraph.Color.prototype = new CABLES.Op(); +CABLES.OPS["afb10809-c7cc-410a-8402-97604b548914"]={f:Ops.Dev.Gl.ShaderGraph.Color,objName:"Ops.Dev.Gl.ShaderGraph.Color"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.Cos +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.Cos = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + invec = op.inObject("input", null, "sg_float"), + outvec = op.outObject("result", null, "sg_float"); + +new CGL.ShaderGraphOp(this); +op.shaderFunc = "cos"; + +invec.onLinkChanged = () => +{ + CGL.ShaderGraphOp.getMaxGenTypeFromPorts([invec], [invec, outvec]); +}; + + +}; + +Ops.Dev.Gl.ShaderGraph.Cos.prototype = new CABLES.Op(); +CABLES.OPS["3596827c-fc80-4109-b98e-9183d7589286"]={f:Ops.Dev.Gl.ShaderGraph.Cos,objName:"Ops.Dev.Gl.ShaderGraph.Cos"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.Cross +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.Cross = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + invec = op.inObject("value a", null, "sg_vec3"), + invecb = op.inObject("value b", null, "sg_vec3"), + outvec = op.outObject("result", null, "sg_vec3"); + +new CGL.ShaderGraphOp(this); +op.shaderFunc = "cross"; + + +}; + +Ops.Dev.Gl.ShaderGraph.Cross.prototype = new CABLES.Op(); +CABLES.OPS["6c041b4c-2692-4068-b86e-47476f3ad261"]={f:Ops.Dev.Gl.ShaderGraph.Cross,objName:"Ops.Dev.Gl.ShaderGraph.Cross"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.CustomShaderGraphOp +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.CustomShaderGraphOp = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inCode = op.inStringEditor("Code", "float main(vec3 rgb)\n{\nreturn rgb*2.0;\n}", "glsl"); + +const sgOp = new CGL.ShaderGraphOp(this); + +op.shaderSrc = inCode.get(); +op.shaderFunc = ""; + +inCode.onChange = () => +{ + const info = sgOp.parseCode(inCode.get()); + sgOp.updatePorts(info); +}; + + +}; + +Ops.Dev.Gl.ShaderGraph.CustomShaderGraphOp.prototype = new CABLES.Op(); +CABLES.OPS["a4145b55-6ef9-4084-b32f-7eb224a7661c"]={f:Ops.Dev.Gl.ShaderGraph.CustomShaderGraphOp,objName:"Ops.Dev.Gl.ShaderGraph.CustomShaderGraphOp"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.Distance +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.Distance = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + invec = op.inObject("value a", null, "sg_float"), + invecb = op.inObject("value b", null, "sg_float"), + outvec = op.outObject("result", null, "sg_float"); + +new CGL.ShaderGraphOp(this); +op.shaderFunc = "distance"; + +invecb.onLinkChanged = +invec.onLinkChanged = () => +{ + CGL.ShaderGraphOp.getMaxGenTypeFromPorts([invec, invecb], [invec, invecb]); +}; + + +}; + +Ops.Dev.Gl.ShaderGraph.Distance.prototype = new CABLES.Op(); +CABLES.OPS["bfb67ec3-a1b6-410f-a52c-0eba05b83453"]={f:Ops.Dev.Gl.ShaderGraph.Distance,objName:"Ops.Dev.Gl.ShaderGraph.Distance"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.Dot +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.Dot = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + invec = op.inObject("value a", null, "sg_genType"), + invecb = op.inObject("value b", null, "sg_genType"), + outvec = op.outObject("result", null, "sg_float"); + +new CGL.ShaderGraphOp(this); +op.shaderFunc = "dot"; + +invecb.onLinkChanged = +invec.onLinkChanged = () => +{ + CGL.ShaderGraphOp.getMaxGenTypeFromPorts([invec, invecb], [invec, invecb]); +}; + + +}; + +Ops.Dev.Gl.ShaderGraph.Dot.prototype = new CABLES.Op(); +CABLES.OPS["aaa64cf2-b96f-40c7-be24-12d5de08cff7"]={f:Ops.Dev.Gl.ShaderGraph.Dot,objName:"Ops.Dev.Gl.ShaderGraph.Dot"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.FragColor +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.FragColor = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"shader_frag":"void setColor(vec4 col)\n{\n #ifdef SETCOLOR_ALPHA\n col.a=1.0;\n #endif\n {{MODULE_COLOR}}\n outColor=col;\n}",}; +const sgOp = new CGL.ShaderGraphOp(this, attachments.shader_frag); + +const inAlpha = op.inBool("Alpha always one", true); + +inAlpha.onChange = updateDefines; +updateDefines(); + +function updateDefines() +{ + sgOp.toggleDefine("SETCOLOR_ALPHA", inAlpha.get()); +} + + +}; + +Ops.Dev.Gl.ShaderGraph.FragColor.prototype = new CABLES.Op(); +CABLES.OPS["38ad0d02-7973-437b-8372-7f3f77bfad48"]={f:Ops.Dev.Gl.ShaderGraph.FragColor,objName:"Ops.Dev.Gl.ShaderGraph.FragColor"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.InputColor +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.InputColor = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inName = op.inString("Name", "myColor"), + uni1 = op.inFloat("R", 0), + uni2 = op.inFloat("G", 0), + uni3 = op.inFloat("B", 0), + uni4 = op.inFloat("A", 1), + inType = op.inSwitch("Type", ["Uniform", "Static"], "Uniform"), + result = op.outObject("vec4", null, "sg_vec4"); + +uni1.setUiAttribs({ "colorPick": true }); + +const sgOp = new CGL.ShaderGraphOp(this); + +inName.onChange = +inType.onChange = updateUniDefs; + +updateUniDefs(); + +uni1.onChange = + uni2.onChange = + uni3.onChange = + uni4.onChange = () => + { + if (inType.get() == "Static")sgOp.updateGraph(); + }; + +function updateUniDefs() +{ + const varname = (inName.get() || "myColor") + "_" + CGL.ShaderGraph.getNewId(); + op.shaderVar = varname; + op.shaderUniforms = + [{ + "type": "4f", + "name": varname, + "ports": [uni1, uni2, uni3, uni4], + "static": inType.get() == "Static" + }]; + + op.setUiAttrib({ "extendTitle": inName.get() }); + + sgOp.updateGraph(); +} + + +}; + +Ops.Dev.Gl.ShaderGraph.InputColor.prototype = new CABLES.Op(); +CABLES.OPS["ad57d840-4fc7-43cf-9095-35e52fde5c14"]={f:Ops.Dev.Gl.ShaderGraph.InputColor,objName:"Ops.Dev.Gl.ShaderGraph.InputColor"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.InputTexture +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.InputTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; + +const + inTex = op.inTexture("Texture"), + inName = op.inString("Name", "myTexture"), + result = op.outObject("vec4", null, "sg_sampler2D"); + +const sgOp = new CGL.ShaderGraphOp(this); +inName.onChange = +inTex.onChange = updateUniDefs; + +updateUniDefs(); + +function updateUniDefs() +{ + const varname = (inName.get() || "myVec4") + "_" + CGL.ShaderGraph.getNewId(); + op.shaderVar = varname; + op.shaderUniforms = + [{ + "type": "t", + "name": varname, + "ports": [inTex] + }]; + + op.setUiAttrib({ "extendTitle": inName.get() }); + + sgOp.updateGraph(); +} + + +}; + +Ops.Dev.Gl.ShaderGraph.InputTexture.prototype = new CABLES.Op(); +CABLES.OPS["025e1fe0-43be-4d57-b6f8-5a3e314068d1"]={f:Ops.Dev.Gl.ShaderGraph.InputTexture,objName:"Ops.Dev.Gl.ShaderGraph.InputTexture"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.InputVec4 +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.InputVec4 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inName = op.inString("Name", "myVec4"), + uni1 = op.inFloat("Number X", 0), + uni2 = op.inFloat("Number Y", 0), + uni3 = op.inFloat("Number Z", 0), + uni4 = op.inFloat("Number W", 1), + inType = op.inSwitch("Type", ["Uniform", "Static"], "Uniform"), + result = op.outObject("vec4", null, "sg_vec4"); + +const sgOp = new CGL.ShaderGraphOp(this); + +inName.onChange = +inType.onChange = updateUniDefs; + +updateUniDefs(); + +uni1.onChange = + uni2.onChange = + uni3.onChange = + uni4.onChange = () => + { + if (inType.get() == "Static")sgOp.updateGraph(); + }; + +function updateUniDefs() +{ + const varname = (inName.get() || "myVec4") + "_" + CGL.ShaderGraph.getNewId(); + op.shaderVar = varname; + op.shaderUniforms = + [{ + "type": "4f", + "name": varname, + "ports": [uni1, uni2, uni3, uni4], + "static": inType.get() == "Static" + }]; + + op.setUiAttrib({ "extendTitle": inName.get() }); + + sgOp.updateGraph(); +} + + +}; + +Ops.Dev.Gl.ShaderGraph.InputVec4.prototype = new CABLES.Op(); +CABLES.OPS["4e089d60-006b-4879-9b45-b9616c7fc18d"]={f:Ops.Dev.Gl.ShaderGraph.InputVec4,objName:"Ops.Dev.Gl.ShaderGraph.InputVec4"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.Max +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.Max = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + invec = op.inObject("value a", null, "sg_float"), + invecb = op.inObject("value b", null, "sg_float"), + outvec = op.outObject("result", null, "sg_float"); + +new CGL.ShaderGraphOp(this); +op.shaderFunc = "max"; + +invecb.onLinkChanged = +invec.onLinkChanged = () => +{ + CGL.ShaderGraphOp.getMaxGenTypeFromPorts([invec, invecb], [invec, invecb, outvec]); +}; + + +}; + +Ops.Dev.Gl.ShaderGraph.Max.prototype = new CABLES.Op(); +CABLES.OPS["285b5693-5038-44a2-82f4-989266ac8655"]={f:Ops.Dev.Gl.ShaderGraph.Max,objName:"Ops.Dev.Gl.ShaderGraph.Max"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.Min +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.Min = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + invec = op.inObject("value a", null, "sg_float"), + invecb = op.inObject("value b", null, "sg_float"), + outvec = op.outObject("result", null, "sg_float"); + +new CGL.ShaderGraphOp(this); +op.shaderFunc = "min"; + +invecb.onLinkChanged = +invec.onLinkChanged = () => +{ + CGL.ShaderGraphOp.getMaxGenTypeFromPorts([invec, invecb], [invec, invecb, outvec]); +}; + + +}; + +Ops.Dev.Gl.ShaderGraph.Min.prototype = new CABLES.Op(); +CABLES.OPS["58c146e1-8512-4f1c-b23f-52099b566978"]={f:Ops.Dev.Gl.ShaderGraph.Min,objName:"Ops.Dev.Gl.ShaderGraph.Min"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.Mix +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.Mix = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inx=op.inObject("x",null,"sg_float"), + iny=op.inObject("y",null,"sg_float"), + ina=op.inObject("a",null,"sg_float"), + result=op.outObject("result",null,"sg_float"); + +new CGL.ShaderGraphOp(this); +op.shaderFunc="mix"; + +inx.onLinkChanged= +iny.onLinkChanged= +ina.onLinkChanged=()=> +{ + CGL.ShaderGraphOp.getMaxGenTypeFromPorts([inx,iny],[inx,iny,result]); +}; + + +}; + +Ops.Dev.Gl.ShaderGraph.Mix.prototype = new CABLES.Op(); +CABLES.OPS["b4b9f9d3-10c1-4a8e-8282-d05df9e92801"]={f:Ops.Dev.Gl.ShaderGraph.Mix,objName:"Ops.Dev.Gl.ShaderGraph.Mix"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.Multiply +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.Multiply = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inputa = op.inObject("a", null, "sg_genType"), + inputb = op.inObject("b", null, "sg_genType"), + outvec = op.outObject("result", null, "sg_genType"); + +inputa.setUiAttribs({ "ignoreObjTypeErrors": true }); +inputb.setUiAttribs({ "ignoreObjTypeErrors": true }); + +new CGL.ShaderGraphOp(this); + +inputb.onLinkChanged = +inputa.onLinkChanged = () => +{ + const t = CGL.ShaderGraphOp.getMaxGenTypeFromPorts([inputb, inputa]); + + inputa.setUiAttribs({ "objType": t }); + outvec.setUiAttribs({ "objType": t }); + inputb.setUiAttribs({ "objType": t }); +}; + +op.shaderCodeOperator = "*"; + + +}; + +Ops.Dev.Gl.ShaderGraph.Multiply.prototype = new CABLES.Op(); +CABLES.OPS["84316631-39d6-45f7-8b03-2499dc22f3bb"]={f:Ops.Dev.Gl.ShaderGraph.Multiply,objName:"Ops.Dev.Gl.ShaderGraph.Multiply"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.Normalize +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.Normalize = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + invec = op.inObject("input", null, "sg_float"), + outvec = op.outObject("result", null, "sg_float"); + +new CGL.ShaderGraphOp(this); +op.shaderFunc = "normalize"; + +invec.onLinkChanged = () => +{ + CGL.ShaderGraphOp.getMaxGenTypeFromPorts([invec], [invec, outvec]); +}; + + +}; + +Ops.Dev.Gl.ShaderGraph.Normalize.prototype = new CABLES.Op(); +CABLES.OPS["2358fdab-8261-45f0-bb63-ddef88ad4fa3"]={f:Ops.Dev.Gl.ShaderGraph.Normalize,objName:"Ops.Dev.Gl.ShaderGraph.Normalize"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.PerlinNoise3D +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.PerlinNoise3D = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"perlin_glsl":"\n//\nfloat Interpolation_C2( float x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); } // 6x^5-15x^4+10x^3\t( Quintic Curve. As used by Perlin in Improved Noise. http://mrl.nyu.edu/~perlin/paper445.pdf )\nvec2 Interpolation_C2( vec2 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec3 Interpolation_C2( vec3 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2( vec4 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2_InterpAndDeriv( vec2 x ) { return x.xyxy * x.xyxy * ( x.xyxy * ( x.xyxy * ( x.xyxy * vec2( 6.0, 0.0 ).xxyy + vec2( -15.0, 30.0 ).xxyy ) + vec2( 10.0, -60.0 ).xxyy ) + vec2( 0.0, 30.0 ).xxyy ); }\nvec3 Interpolation_C2_Deriv( vec3 x ) { return x * x * (x * (x * 30.0 - 60.0) + 30.0); }\nfloat Falloff_Xsq_C1( float xsq ) { xsq = 1.0 - xsq; return xsq*xsq; }\t// ( 1.0 - x*x )^2 ( Used by Humus for lighting falloff in Just Cause 2. GPUPro 1 )\nfloat Falloff_Xsq_C2( float xsq ) { xsq = 1.0 - xsq; return xsq*xsq*xsq; }\t// ( 1.0 - x*x )^3. NOTE: 2nd derivative is 0.0 at x=1.0, but non-zero at x=0.0\nvec4 Falloff_Xsq_C2( vec4 xsq ) { xsq = 1.0 - xsq; return xsq*xsq*xsq; }\n\n\nvoid FAST32_hash_3D( vec3 gridcell, out vec4 lowz_hash, out vec4 highz_hash )\t//\tgenerates a random number for each of the 8 cell corners\n{\n// gridcell is assumed to be an integer coordinate\n//\tTODO: \tthese constants need tweaked to find the best possible noise.\n //\t\t\tprobably requires some kind of brute force computational searching or something....\n const vec2 OFFSET = vec2( 50.0, 161.0 );\n const float DOMAIN = 69.0;\n const float SOMELARGEFLOAT = 635.298681;\n const float ZINC = 48.500388;\n\n //\ttruncate the domain\n gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;\n vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );\n\n //\tcalculate the noise\n vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;\n P *= P;\n P = P.xzxz * P.yyww;\n highz_hash.xy = vec2( 1.0 / ( SOMELARGEFLOAT + vec2( gridcell.z, gridcell_inc1.z ) * ZINC ) );\n lowz_hash = fract( P * highz_hash.xxxx );\n highz_hash = fract( P * highz_hash.yyyy );\n}\n\n\n\nvoid FAST32_hash_3D( \tvec3 gridcell,out vec4 lowz_hash_0,out vec4 lowz_hash_1,out vec4 lowz_hash_2,out vec4 highz_hash_0,out vec4 highz_hash_1,out vec4 highz_hash_2\t)\t\t//\tgenerates 3 random numbers for each of the 8 cell corners\n{\n // gridcell is assumed to be an integer coordinate\n\n //\tTODO: \tthese constants need tweaked to find the best possible noise.\n //\t\t\tprobably requires some kind of brute force computational searching or something....\n const vec2 OFFSET = vec2( 50.0, 161.0 );\n const float DOMAIN = 69.0;\n const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );\n const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );\n\n //\ttruncate the domain\n gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;\n vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );\n\n //\tcalculate the noise\n vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;\n P *= P;\n P = P.xzxz * P.yyww;\n vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );\n vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );\n lowz_hash_0 = fract( P * lowz_mod.xxxx );\n highz_hash_0 = fract( P * highz_mod.xxxx );\n lowz_hash_1 = fract( P * lowz_mod.yyyy );\n highz_hash_1 = fract( P * highz_mod.yyyy );\n lowz_hash_2 = fract( P * lowz_mod.zzzz );\n highz_hash_2 = fract( P * highz_mod.zzzz );\n}\n\n\n//\n//\tPerlin Noise 3D ( gradient noise )\n//\tReturn value range of -1.0->1.0\n//\thttp://briansharpe.files.wordpress.com/2011/11/perlinsample.jpg\n//\nfloat perlin3D( vec3 P )\n{\n P*=8.0;\n\n //\testablish our grid cell and unit position\n vec3 Pi = floor(P);\n vec3 Pf = P - Pi;\n vec3 Pf_min1 = Pf - 1.0;\n\n //\n //\tclassic noise.\n //\trequires 3 random values per point.\n //\n\n //\tcalculate the hash.\n //\t( various hashing methods listed in order of speed )\n vec4 hashx0, hashy0, hashz0, hashx1, hashy1, hashz1;\n FAST32_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n //SGPP_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n\n //\tcalculate the gradients\n vec4 grad_x0 = hashx0 - 0.49999;\n vec4 grad_y0 = hashy0 - 0.49999;\n vec4 grad_z0 = hashz0 - 0.49999;\n vec4 grad_x1 = hashx1 - 0.49999;\n vec4 grad_y1 = hashy1 - 0.49999;\n vec4 grad_z1 = hashz1 - 0.49999;\n vec4 grad_results_0 = inversesqrt( grad_x0 * grad_x0 + grad_y0 * grad_y0 + grad_z0 * grad_z0 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x0 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y0 + Pf.zzzz * grad_z0 );\n vec4 grad_results_1 = inversesqrt( grad_x1 * grad_x1 + grad_y1 * grad_y1 + grad_z1 * grad_z1 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x1 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y1 + Pf_min1.zzzz * grad_z1 );\n\n\n //\tClassic Perlin Interpolation\n vec3 blend = Interpolation_C2( Pf );\n vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n float final = dot( res0, blend2.zxzx * blend2.wwyy );\n final *= 1.1547005383792515290182975610039;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range *= 1.0/sqrt(0.75)\n return final;\n\n\n\n}\n",}; + + +const sgOp = new CGL.ShaderGraphOp(this, attachments.perlin_glsl); + + +}; + +Ops.Dev.Gl.ShaderGraph.PerlinNoise3D.prototype = new CABLES.Op(); +CABLES.OPS["bba73873-2b81-419b-899f-323e7dc159ea"]={f:Ops.Dev.Gl.ShaderGraph.PerlinNoise3D,objName:"Ops.Dev.Gl.ShaderGraph.PerlinNoise3D"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.Pow +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.Pow = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + invec = op.inObject("input", null, "sg_float"), + inpow = op.inObject("power", null, "sg_float"), + outvec = op.outObject("result", null, "sg_float"); + +new CGL.ShaderGraphOp(this); +op.shaderFunc = "pow"; + +inpow.onLinkChanged = () => +{ + return invec.onLinkChanged = () => + { + CGL.ShaderGraphOp.getMaxGenTypeFromPorts([invec, inpow], [invec, inpow, outvec]); + }; +}; + + +}; + +Ops.Dev.Gl.ShaderGraph.Pow.prototype = new CABLES.Op(); +CABLES.OPS["eab198bd-b8e9-467e-ad05-8175b41a9732"]={f:Ops.Dev.Gl.ShaderGraph.Pow,objName:"Ops.Dev.Gl.ShaderGraph.Pow"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.SG_Noise +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.SG_Noise = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"shader_frag":"\nfloat noise(vec2 a)\n{\n return fract(sin(dot(a, vec2(12.9898, 78.233))) * 43758.5453);\n}",}; +new CGL.ShaderGraphOp(this,attachments.shader_frag); + + +}; + +Ops.Dev.Gl.ShaderGraph.SG_Noise.prototype = new CABLES.Op(); +CABLES.OPS["7400ed85-8931-4669-b0bc-620623860864"]={f:Ops.Dev.Gl.ShaderGraph.SG_Noise,objName:"Ops.Dev.Gl.ShaderGraph.SG_Noise"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.SampleTexture +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.SampleTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"sampletex_frag":"vec4 sampleTex(sampler2D tex,vec2 texCoord)\n{\n return texture(tex,texCoord);\n}",}; +const sgOp = new CGL.ShaderGraphOp(this, attachments.sampletex_frag); + + +}; + +Ops.Dev.Gl.ShaderGraph.SampleTexture.prototype = new CABLES.Op(); +CABLES.OPS["3eb89130-b02e-432c-9633-d1ab4635a783"]={f:Ops.Dev.Gl.ShaderGraph.SampleTexture,objName:"Ops.Dev.Gl.ShaderGraph.SampleTexture"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.SetPosition +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.SetPosition = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"position_vert":"void setPosition(vec4 pos)\n{\n // vec3 tangent=attrTangent;\n pos.w=1.0;\n // vec3 bitangent=attrBiTangent;\n mat4 mMatrix=modelMatrix;\n\n {{MODULE_VERTEX_POSITION}}\n\n texCoord=attrTexCoord;\n\n gl_Position = projMatrix * (viewMatrix*mMatrix) * pos;\n}",}; +const sgOp = new CGL.ShaderGraphOp(this, attachments.position_vert); + + +}; + +Ops.Dev.Gl.ShaderGraph.SetPosition.prototype = new CABLES.Op(); +CABLES.OPS["8772c543-f2f6-4684-8792-2a615cf861b0"]={f:Ops.Dev.Gl.ShaderGraph.SetPosition,objName:"Ops.Dev.Gl.ShaderGraph.SetPosition"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.Sin +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.Sin = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + invec=op.inObject("input",null,"sg_float"), + outvec=op.outObject("result",null,"sg_float"); + +new CGL.ShaderGraphOp(this); +op.shaderFunc="sin"; + +invec.onLinkChanged=()=> +{ + CGL.ShaderGraphOp.getMaxGenTypeFromPorts([invec],[invec,outvec]); + +}; + + +}; + +Ops.Dev.Gl.ShaderGraph.Sin.prototype = new CABLES.Op(); +CABLES.OPS["19e60bc9-4ddf-4c24-a6e6-ca48a3856676"]={f:Ops.Dev.Gl.ShaderGraph.Sin,objName:"Ops.Dev.Gl.ShaderGraph.Sin"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.Sum +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.Sum = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inputa = op.inObject("a", null, "sg_float"), + inputb = op.inObject("b", null, "sg_float"), + outvec = op.outObject("result", null, "sg_float"); + +new CGL.ShaderGraphOp(this); +op.shaderCodeOperator = "+"; + +inputa.setUiAttribs({ "ignoreObjTypeErrors": true }); +inputb.setUiAttribs({ "ignoreObjTypeErrors": true }); + +inputb.onLinkChanged = +inputa.onLinkChanged = () => +{ + CGL.ShaderGraphOp.getMaxGenTypeFromPorts([inputb, inputa], [inputb, inputa, outvec]); +}; + + +}; + +Ops.Dev.Gl.ShaderGraph.Sum.prototype = new CABLES.Op(); +CABLES.OPS["5bca04f9-bb17-4bd0-bcd1-0427ee3b2933"]={f:Ops.Dev.Gl.ShaderGraph.Sum,objName:"Ops.Dev.Gl.ShaderGraph.Sum"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.Swizzle +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.Swizzle = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inp = op.inObject("vec", null, "sg_vec4", null, "sg_vec4"), + inType = op.inSwitch("Type", ["float", "vec2", "vec3", "vec4"], "vec4"), + xChannel = op.inSwitch("X", ["X", "Y", "Z", "W"], "X"), + yChannel = op.inSwitch("Y", ["X", "Y", "Z", "W"], "Y"), + zChannel = op.inSwitch("Z", ["X", "Y", "Z", "W"], "Z"), + wChannel = op.inSwitch("W", ["X", "Y", "Z", "W"], "W"), + result = op.outObject("Result", null, "sg_vec4"); + +inType.onChange = + xChannel.onChange = + yChannel.onChange = + zChannel.onChange = + wChannel.onChange = updateUi; + +const sgOp = new CGL.ShaderGraphOp(this); +updateUi(); + +function updateUi() +{ + yChannel.setUiAttribs({ "greyout": inType.get() == "float" }); + zChannel.setUiAttribs({ "greyout": inType.get() == "float" || inType.get() == "vec2" }); + wChannel.setUiAttribs({ "greyout": inType.get() == "float" || inType.get() == "vec2" || inType.get() == "vec3" }); + + result.setUiAttribs({ "objType": "sg_" + inType.get() }); + + let swizzStr = xChannel.get().toLowerCase(); + let str = ""; + + // if (inType.get() == "float") + // { + // str = swizzStr; + // str = inType.get() + " swizzle(" + inType.get() + " vec){return " + vec + "; }"; + // } + // else + { + if (inType.get() == "float") swizzStr = "vec"; + if (inType.get() == "vec2" || inType.get() == "vec3" || inType.get() == "vec4") swizzStr += "vec." + yChannel.get().toLowerCase(); + if (inType.get() == "vec3" || inType.get() == "vec4") swizzStr += "vec." + zChannel.get().toLowerCase(); + if (inType.get() == "vec4") swizzStr += "vec." + wChannel.get().toLowerCase(); + + str = inType.get() + " swizzle(" + inType.get() + " vec){return " + swizzStr + "; }"; + } + + // console.log(str); + sgOp.parseCode(str); + // console.log(sgOp.info); + sgOp.updateGraph(); +} + + +}; + +Ops.Dev.Gl.ShaderGraph.Swizzle.prototype = new CABLES.Op(); +CABLES.OPS["8a25f41b-6ded-4aaf-bd1f-219d644040d0"]={f:Ops.Dev.Gl.ShaderGraph.Swizzle,objName:"Ops.Dev.Gl.ShaderGraph.Swizzle"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.TexCoord +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.TexCoord = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +op.outObject("texCoord",null,"sg_vec2"); +op.shaderVar="texCoord"; + +new CGL.ShaderGraphOp(this); + + +}; + +Ops.Dev.Gl.ShaderGraph.TexCoord.prototype = new CABLES.Op(); +CABLES.OPS["3a7e40e5-29bd-4e17-abbd-1570ab4cfb1d"]={f:Ops.Dev.Gl.ShaderGraph.TexCoord,objName:"Ops.Dev.Gl.ShaderGraph.TexCoord"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.ShaderGraph.VertexPosition +// +// ************************************************************** + +Ops.Dev.Gl.ShaderGraph.VertexPosition = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +op.outObject("vposition", null, "sg_vec3"); +op.shaderVar = "vPosition"; + +new CGL.ShaderGraphOp(this); + + +}; + +Ops.Dev.Gl.ShaderGraph.VertexPosition.prototype = new CABLES.Op(); +CABLES.OPS["b2d21d20-a29a-441d-9ffa-0535a771042f"]={f:Ops.Dev.Gl.ShaderGraph.VertexPosition,objName:"Ops.Dev.Gl.ShaderGraph.VertexPosition"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.Shadergraph.Length +// +// ************************************************************** + +Ops.Dev.Gl.Shadergraph.Length = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + invec = op.inObject("input", null, "sg_genType"), + outvec = op.outObject("result", null, "sg_float"); + +new CGL.ShaderGraphOp(this); +op.shaderFunc = "length"; + +invec.onLinkChanged = () => +{ + invec.copyLinkedUiAttrib("objType", invec); +}; + + +}; + +Ops.Dev.Gl.Shadergraph.Length.prototype = new CABLES.Op(); +CABLES.OPS["27f420c0-aecc-447c-927c-3536abc8849a"]={f:Ops.Dev.Gl.Shadergraph.Length,objName:"Ops.Dev.Gl.Shadergraph.Length"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.Shadergraph.Shadergraph +// +// ************************************************************** + +Ops.Dev.Gl.Shadergraph.Shadergraph = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Exec"), + inFrag = op.inObject("Fragment", null, "sg_void"), + inVertex = op.inObject("Vertex", null, "sg_void"), + next = op.outTrigger("Next"), + outshader = op.outObject("Shader"), + outSrcFrag = op.outString("Source Fragment"), + outSrcVert = op.outString("Source Vertex"); + +const cgl = op.patch.cgl; +const sg = new CGL.ShaderGraph(this, inFrag, inVertex); +const shader = new CGL.Shader(cgl, op.name); +let needsUpdate = true; + +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG", "MODULE_BEGIN_VERTEX"]); +outshader.set(shader); + +let uniformTextures = []; + +sg.on("compiled", () => +{ + outSrcFrag.set(sg.getSrcFrag()); + outSrcVert.set(sg.getSrcVert()); + needsUpdate = true; +}); + +inExec.onTriggered = () => +{ + if (needsUpdate) + { + uniformTextures = []; + shader.removeAllUniforms(); + + shader.setSource(sg.getSrcVert(), sg.getSrcFrag()); + + const unis = sg.getUniforms(); + for (let i = 0; i < unis.length; i++) + { + const su = unis[i]; + shader.removeUniform(su.name); + + let uni = null; + if (su.ports) uni = shader.addUniformFrag(su.type, su.name, su.ports[0], su.ports[1], su.ports[2], su.ports[3]); + else console.log("uni has no ports", su.ports); + + if (su.type == "t")uniformTextures.push({ "uni": uni, "port": su.ports[0] }); + } + needsUpdate = false; + } + + for (let i = 0; i < uniformTextures.length; i++) + shader.pushTexture(uniformTextures[i].uni, uniformTextures[i].port.get()); + + cgl.pushShader(shader); + + next.trigger(); + + shader.popTextures(); + cgl.popShader(); +}; + + +}; + +Ops.Dev.Gl.Shadergraph.Shadergraph.prototype = new CABLES.Op(); +CABLES.OPS["aef36334-477a-4173-af03-d4e162d31bfb"]={f:Ops.Dev.Gl.Shadergraph.Shadergraph,objName:"Ops.Dev.Gl.Shadergraph.Shadergraph"}; + + + + +// ************************************************************** +// +// Ops.Dev.Gl.TextureEffects.ChromaKeyAlpha +// +// ************************************************************** + +Ops.Dev.Gl.TextureEffects.ChromaKeyAlpha = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"chromakey_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI vec3 color;\nUNI float weightMul;\n\n\n{{MODULE_BEGIN_FRAG}}\n\nvec3 rgb2hsv(vec4 rgb)\n{\n\tfloat Cmax = max(rgb.r, max(rgb.g, rgb.b));\n\tfloat Cmin = min(rgb.r, min(rgb.g, rgb.b));\n float delta = Cmax - Cmin;\n\n\tvec3 hsv = vec3(0., 0., Cmax);\n\n\tif (Cmax > Cmin)\n\t{\n\t\thsv.y = delta / Cmax;\n\n\t\tif (rgb.r == Cmax)\n\t\t\thsv.x = (rgb.g - rgb.b) / delta;\n\t\telse\n\t\t{\n\t\t\tif (rgb.g == Cmax)\n\t\t\t\thsv.x = 2. + (rgb.b - rgb.r) / delta;\n\t\t\telse\n\t\t\t\thsv.x = 4. + (rgb.r - rgb.g) / delta;\n\t\t}\n\t\thsv.x = fract(hsv.x / 6.);\n\t}\n\treturn hsv;\n}\n\nfloat chromaKey(vec4 col)\n{\n vec4 backgroundColor = vec4(color,0.0);\n vec3 weights = vec3(4.*weightMul, 1., 2.*weightMul);\n\n vec3 hsv = rgb2hsv(col);\n vec3 target = rgb2hsv(backgroundColor);\n float dist = length(weights * (target - hsv));\n\n return 1. - clamp(3. * dist - 1.5, 0., 1.);\n}\n\nfloat random(vec2 co)\n{\n return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * (43758.5453));\n}\n\nvoid main()\n{\n vec4 col=vec4(1.0,1.0,0.0,1.0);\n {{MODULE_COLOR}}\n col=texture(tex,texCoord);\n\n // #ifdef MODE_R\n // float maxrb = max( col.g, col.b );\n // float perc = min(1.0,(col.r*weightMul-maxrb)*2.0);\n // #endif\n\n // #ifdef MODE_G\n // float maxrb = max( col.r, col.b );\n // float perc = min(1.0,(col.g*weightMul-maxrb)*2.0);\n // col.g=min(maxrb,col.g);\n // #endif\n\n // #ifdef MODE_COLOR\n float perc=chromaKey(col);\n // #endif\n\n float len=length(col);\n col=normalize(col)*len;\n\n col.a=1.0-perc;\n outColor= col;\n}\n\n\n\n",}; +const + render = op.inTrigger("Render"), + w = op.inValueSlider("WeightMul", 0.6), + inR = op.inFloat("R", Math.random()), + inG = op.inFloat("G", Math.random()), + inB = op.inFloat("B", Math.random()), + trigger = op.outTrigger("Next"); + +op.setPortGroup("Color", [inR, inG, inB]); +inR.setUiAttribs({ "colorPick": true }); + +const + cgl = op.patch.cgl, + shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.chromakey_frag); + +new CGL.Uniform(shader, "t", "tex", 0), +new CGL.Uniform(shader, "3f", "color", inR, inG, inB), +new CGL.Uniform(shader, "f", "weightMul", w); + +render.onTriggered = function () +{ + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Dev.Gl.TextureEffects.ChromaKeyAlpha.prototype = new CABLES.Op(); +CABLES.OPS["5614f8a5-7267-4ed6-9cf9-b4a3c7531f7d"]={f:Ops.Dev.Gl.TextureEffects.ChromaKeyAlpha,objName:"Ops.Dev.Gl.TextureEffects.ChromaKeyAlpha"}; + + + + +// ************************************************************** +// +// Ops.Dev.GlArrayCurlNoise +// +// ************************************************************** + +Ops.Dev.GlArrayCurlNoise = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"curlnoise_frag":"UNI float z;\nUNI float x;\nUNI float y;\nUNI float scale;\nIN vec2 texCoord;\nUNI sampler2D tex;\n\nUNI float amount;\nUNI float timeDelta;\nUNI float offset;\n\n{{CGL.BLENDMODES}}\n{{CGL.RANDOM_TEX}}\n\nfloat Interpolation_C2( float x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); } // 6x^5-15x^4+10x^3\t( Quintic Curve. As used by Perlin in Improved Noise. http://mrl.nyu.edu/~perlin/paper445.pdf )\nvec2 Interpolation_C2( vec2 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec3 Interpolation_C2( vec3 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2( vec4 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2_InterpAndDeriv( vec2 x ) { return x.xyxy * x.xyxy * ( x.xyxy * ( x.xyxy * ( x.xyxy * vec2( 6.0, 0.0 ).xxyy + vec2( -15.0, 30.0 ).xxyy ) + vec2( 10.0, -60.0 ).xxyy ) + vec2( 0.0, 30.0 ).xxyy ); }\nvec3 Interpolation_C2_Deriv( vec3 x ) { return x * x * (x * (x * 30.0 - 60.0) + 30.0); }\n\n\nvoid FAST32_hash_3D( \tvec3 gridcell,\n out vec4 lowz_hash_0,\n out vec4 lowz_hash_1,\n out vec4 lowz_hash_2,\n out vec4 highz_hash_0,\n out vec4 highz_hash_1,\n out vec4 highz_hash_2\t)\t\t//\tgenerates 3 random numbers for each of the 8 cell corners\n{\n // gridcell is assumed to be an integer coordinate\n\n //\tTODO: \tthese constants need tweaked to find the best possible noise.\n //\t\t\tprobably requires some kind of brute force computational searching or something....\n const vec2 OFFSET = vec2( 50.0, 161.0 );\n const float DOMAIN = 69.0;\n const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );\n const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );\n\n //\ttruncate the domain\n gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;\n vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );\n\n //\tcalculate the noise\n vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;\n P *= P;\n P = P.xzxz * P.yyww;\n vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );\n vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );\n lowz_hash_0 = fract( P * lowz_mod.xxxx );\n highz_hash_0 = fract( P * highz_mod.xxxx );\n lowz_hash_1 = fract( P * lowz_mod.yyyy );\n highz_hash_1 = fract( P * highz_mod.yyyy );\n lowz_hash_2 = fract( P * lowz_mod.zzzz );\n highz_hash_2 = fract( P * highz_mod.zzzz );\n}\n\n//\n//\tPerlin Noise 3D ( gradient noise )\n//\tReturn value range of -1.0->1.0\n//\thttp://briansharpe.files.wordpress.com/2011/11/perlinsample.jpg\n//\nfloat Perlin3D( vec3 P )\n{\n //\testablish our grid cell and unit position\n vec3 Pi = floor(P);\n vec3 Pf = P - Pi;\n vec3 Pf_min1 = Pf - 1.0;\n\n#if 1\n //\n //\tclassic noise.\n //\trequires 3 random values per point. with an efficent hash function will run faster than improved noise\n //\n\n //\tcalculate the hash.\n //\t( various hashing methods listed in order of speed )\n vec4 hashx0, hashy0, hashz0, hashx1, hashy1, hashz1;\n FAST32_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n //SGPP_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n\n //\tcalculate the gradients\n vec4 grad_x0 = hashx0 - 0.49999;\n vec4 grad_y0 = hashy0 - 0.49999;\n vec4 grad_z0 = hashz0 - 0.49999;\n vec4 grad_x1 = hashx1 - 0.49999;\n vec4 grad_y1 = hashy1 - 0.49999;\n vec4 grad_z1 = hashz1 - 0.49999;\n vec4 grad_results_0 = inversesqrt( grad_x0 * grad_x0 + grad_y0 * grad_y0 + grad_z0 * grad_z0 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x0 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y0 + Pf.zzzz * grad_z0 );\n vec4 grad_results_1 = inversesqrt( grad_x1 * grad_x1 + grad_y1 * grad_y1 + grad_z1 * grad_z1 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x1 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y1 + Pf_min1.zzzz * grad_z1 );\n\n#if 1\n //\tClassic Perlin Interpolation\n vec3 blend = Interpolation_C2( Pf );\n vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n float final = dot( res0, blend2.zxzx * blend2.wwyy );\n final *= 1.1547005383792515290182975610039;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range *= 1.0/sqrt(0.75)\n return final;\n#else\n //\tClassic Perlin Surflet\n //\thttp://briansharpe.wordpress.com/2012/03/09/modifications-to-classic-perlin-noise/\n Pf *= Pf;\n Pf_min1 *= Pf_min1;\n vec4 vecs_len_sq = vec4( Pf.x, Pf_min1.x, Pf.x, Pf_min1.x ) + vec4( Pf.yy, Pf_min1.yy );\n float final = dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf.zzzz ) ), grad_results_0 ) + dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf_min1.zzzz ) ), grad_results_1 );\n final *= 2.3703703703703703703703703703704;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range *= 1.0/cube(0.75)\n return final;\n#endif\n\n#else\n //\n //\timproved noise.\n //\trequires 1 random value per point. Will run faster than classic noise if a slow hashing function is used\n //\n\n //\tcalculate the hash.\n //\t( various hashing methods listed in order of speed )\n vec4 hash_lowz, hash_highz;\n FAST32_hash_3D( Pi, hash_lowz, hash_highz );\n //BBS_hash_3D( Pi, hash_lowz, hash_highz );\n //SGPP_hash_3D( Pi, hash_lowz, hash_highz );\n\n //\n //\t\"improved\" noise using 8 corner gradients. Faster than the 12 mid-edge point method.\n //\tKen mentions using diagonals like this can cause \"clumping\", but we'll live with that.\n //\t[1,1,1] [-1,1,1] [1,-1,1] [-1,-1,1]\n //\t[1,1,-1] [-1,1,-1] [1,-1,-1] [-1,-1,-1]\n //\n hash_lowz -= 0.5;\n vec4 grad_results_0_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_lowz );\n hash_lowz = abs( hash_lowz ) - 0.25;\n vec4 grad_results_0_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_lowz );\n vec4 grad_results_0_2 = Pf.zzzz * sign( abs( hash_lowz ) - 0.125 );\n vec4 grad_results_0 = grad_results_0_0 + grad_results_0_1 + grad_results_0_2;\n\n hash_highz -= 0.5;\n vec4 grad_results_1_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_highz );\n hash_highz = abs( hash_highz ) - 0.25;\n vec4 grad_results_1_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_highz );\n vec4 grad_results_1_2 = Pf_min1.zzzz * sign( abs( hash_highz ) - 0.125 );\n vec4 grad_results_1 = grad_results_1_0 + grad_results_1_1 + grad_results_1_2;\n\n //\tblend the gradients and return\n vec3 blend = Interpolation_C2( Pf );\n vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n return dot( res0, blend2.zxzx * blend2.wwyy ) * (2.0 / 3.0);\t//\t(optionally) mult by (2.0/3.0) to scale to a strict -1.0->1.0 range\n#endif\n}\n\n\nvoid main()\n{\n vec4 base=texture(tex,texCoord);\n\n\n vec3 rnd=\n vec3(\n Perlin3D( ( (base.xyz+20.0) + vec3(x,y,z)) *scale ),\n Perlin3D( ( (base.xyz-20.0) + vec3(x,y,z)) *scale ),\n Perlin3D( ( (base.xyz+60.0) + vec3(x,y,z)) *scale )\n );\n\n\n vec3 noise=(cgl_random3(texCoord.xy)-0.5)*offset;\n rnd+=\n vec3(\n Perlin3D( ( (base.xyz+20.0+noise.x) + vec3(x,y,z)) *scale ),\n Perlin3D( ( (base.xyz-20.0+noise.y) + vec3(x,y,z)) *scale ),\n Perlin3D( ( (base.xyz+60.0+noise.z) + vec3(x,y,z)) *scale )\n );\n\n\n // rnd=\n // (\n // vec3(\n // Perlin3D( ( (base.xyz+20.0) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz-20.0) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz+60.0) + vec3(x,y,z)) *scale )\n // )+\n // vec3(\n // Perlin3D( ( (base.xyz+20.0+(offset*scale)) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz-20.0+(offset*scale)) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz+60.0+(offset*scale)) + vec3(x,y,z)) *scale )\n // )*0.25+\n // vec3(\n // Perlin3D( ( (base.xyz+20.0-(offset*scale)) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz-20.0-(offset*scale)) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz+60.0-(offset*scale)) + vec3(x,y,z)) *scale )\n // )*0.25+\n // vec3(\n // Perlin3D( ( (base.xyz+20.0-(offset*scale)) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz-20.0+(offset*scale)) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz+60.0-(offset*scale)) + vec3(x,y,z)) *scale )\n // )*0.25+\n // vec3(\n // Perlin3D( ( (base.xyz+20.0+(offset*scale)) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz-20.0-(offset*scale)) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz+60.0+(offset*scale)) + vec3(x,y,z)) *scale )\n // )*0.25\n\n // )/2.0;\n\n\n\n\n\n\n\n #ifdef MOD_NORM_SPEED\n rnd=normalize(rnd)*0.2;\n #endif\n #ifndef MOD_NORM_SPEED\n // rnd*=timeDelta;\n #endif\n\n // rnd=clamp(rnd,vec3(-0.01),vec3(0.01));\n // rnd*=0.01;\n // float cl=0.03;\n // rnd.x=clamp(rnd.x,-cl,cl);\n // rnd.y=clamp(rnd.y,-cl,cl);\n // rnd.z=clamp(rnd.z,-cl,cl);\n\n rnd*=timeDelta;\n\n vec3 coord=base.xyz+rnd;\n // coord.x+=( Perlin3D( ( (base.xyz+20.0) + vec3(x,y,z)) *scale )*timeDelta);\n // coord.y+=( Perlin3D( ( (base.xyz-20.0) + vec3(x,y,z)) *scale )*timeDelta);\n // coord.z+=( Perlin3D( ( (base.xyz+30.0) + vec3(x,y,z)) *scale )*timeDelta);\n\n // additional noise on top\n // coord.x+=Perlin3D(vec3(texCoord.x))*0.001;\n // coord.y+=Perlin3D(vec3(texCoord.y))*0.001;\n // coord.z+=Perlin3D(vec3(texCoord.y,texCoord.x,texCoord.y))*0.001;\n\n\n outColor=vec4(coord,1.0);\n\n\n // outColor=cgl_blend(base,col,amount);\n}\n",}; +const + render = op.inTrigger("Render"), + inTex = op.inTexture("GlArray"), + scale = op.inValue("Scale", 1), + time = op.inValue("Time", 0), + + inNormSpeed = op.inBool("Normalize Speed", false), + + x = op.inValue("X", 0), + y = op.inValue("Y", 0), + z = op.inValue("Z", 0), + a = op.inValue("a", 1), + + inOffset = op.inFloatSlider("offset", 0), + trigger = op.outTrigger("trigger"), + outTex = op.outTexture("Result"); + +let lastTime = time.get(); +render.onTriggered = dorender; + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); +const texMath = new CGL.ShaderTextureMath(cgl, op.objName, { "texturePort": inTex }); + +shader.setSource(shader.getDefaultVertexShader(), attachments.curlnoise_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uniformR = new CGL.Uniform(shader, "f", "x", x), + uniformG = new CGL.Uniform(shader, "f", "y", y), + uniformB = new CGL.Uniform(shader, "f", "z", z), + uniformA = new CGL.Uniform(shader, "f", "scale", scale), + uniformTimeDelta = new CGL.Uniform(shader, "f", "timeDelta", 0), + uniforoffs = new CGL.Uniform(shader, "f", "offset", inOffset); + +inNormSpeed.onChange = updateDefines; +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("MOD_NORM_SPEED", inNormSpeed.get()); +} + +function dorender() +{ + uniformTimeDelta.set(time.get() - lastTime); + lastTime = time.get(); + + outTex.set(null); + const finTex = texMath.render(shader); + outTex.set(finTex); + trigger.trigger(); +} + + +}; + +Ops.Dev.GlArrayCurlNoise.prototype = new CABLES.Op(); +CABLES.OPS["25467f40-8f78-4dca-ba6c-951ae49cac59"]={f:Ops.Dev.GlArrayCurlNoise,objName:"Ops.Dev.GlArrayCurlNoise"}; + + + + +// ************************************************************** +// +// Ops.Dev.GlArrayMath +// +// ************************************************************** + +Ops.Dev.GlArrayMath = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"rgbMath_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D tex2;\nUNI float r;\nUNI float g;\nUNI float b;\nUNI float a;\n\nvoid main()\n{\n vec4 col=texture(tex,texCoord);\n vec4 v=vec4(r,g,b,a);\n\n #ifdef MOD_USE_TEX\n v=texture(tex2,texCoord);\n #endif\n\n\n #ifdef MOD_OP_SUB_CX\n #ifdef MOD_CHAN_R\n col.r=col.r-v.r;\n #endif\n #ifdef MOD_CHAN_G\n col.g=col.g-v.g;\n #endif\n #ifdef MOD_CHAN_B\n col.b=col.b-v.b;\n #endif\n #ifdef MOD_CHAN_A\n col.a=col.a-v.a;\n #endif\n #endif\n\n #ifdef MOD_OP_SUB_XC\n #ifdef MOD_CHAN_R\n col.r=v.r-col.r;\n #endif\n #ifdef MOD_CHAN_G\n col.g=v.g-col.g;\n #endif\n #ifdef MOD_CHAN_B\n col.b=v.b-col.b;\n #endif\n #ifdef MOD_CHAN_A\n col.a=v.a-col.a;\n #endif\n #endif\n\n #ifdef MOD_OP_ADD\n #ifdef MOD_CHAN_R\n col.r+=v.r;\n #endif\n #ifdef MOD_CHAN_G\n col.g+=v.g;\n #endif\n #ifdef MOD_CHAN_B\n col.b+=v.b;\n #endif\n #ifdef MOD_CHAN_A\n col.a+=v.a;\n #endif\n #endif\n\n #ifdef MOD_OP_MUL\n #ifdef MOD_CHAN_R\n col.r*=v.r;\n #endif\n #ifdef MOD_CHAN_G\n col.g*=v.g;\n #endif\n #ifdef MOD_CHAN_B\n col.b*=v.b;\n #endif\n #ifdef MOD_CHAN_A\n col.a*=v.a;\n #endif\n #endif\n\n #ifdef MOD_OP_DIV_XC\n #ifdef MOD_CHAN_R\n col.r=v.r/col.r;\n #endif\n #ifdef MOD_CHAN_G\n col.g=v.g/col.g;\n #endif\n #ifdef MOD_CHAN_B\n col.b=v.b/col.b;\n #endif\n #ifdef MOD_CHAN_A\n col.a=v.a/col.a;\n #endif\n #endif\n\n #ifdef MOD_OP_DIV_CX\n #ifdef MOD_CHAN_R\n col.r=col.r/v.r;\n #endif\n #ifdef MOD_CHAN_G\n col.g=col.g/v.g;\n #endif\n #ifdef MOD_CHAN_B\n col.b=col.b/v.b;\n #endif\n #ifdef MOD_CHAN_A\n col.a=col.a/v.a;\n #endif\n #endif\n\n #ifdef MOD_OP_MODULO\n col=mod(col,v);\n #endif\n\n\n outColor= col;\n}\n",}; +const + render = op.inTrigger("Render"), + inTex = op.inTexture("GlArray"), + inOp = op.inSwitch("Operation", ["c-x", "x-c", "c+x", "c*x", "x/c", "c/x", "c%x"], "c*x"), + chanR = op.inBool("R Active", true), + chanG = op.inBool("G Active", true), + chanB = op.inBool("B Active", true), + chanA = op.inBool("A Active", false), + inTex2 = op.inTexture("Value"), + r = op.inValue("r", 1), + g = op.inValue("g", 1), + b = op.inValue("b", 1), + a = op.inValue("a", 1), + trigger = op.outTrigger("trigger"), + outTex = op.outTexture("Result"); + +render.onTriggered = dorender; + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); +const texMath = new CGL.ShaderTextureMath(cgl, op.objName, { "texturePort": inTex }); + +shader.setSource(shader.getDefaultVertexShader(), attachments.rgbMath_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const textureUniform2 = new CGL.Uniform(shader, "t", "tex2", 1); + +const uniformR = new CGL.Uniform(shader, "f", "r", r); +const uniformG = new CGL.Uniform(shader, "f", "g", g); +const uniformB = new CGL.Uniform(shader, "f", "b", b); +const uniformA = new CGL.Uniform(shader, "f", "a", a); + +chanR.onChange = + chanG.onChange = + chanB.onChange = + chanA.onChange = + inTex2.onChange = + inOp.onChange = updateDefines; +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("MOD_OP_SUB_CX", inOp.get() === "c-x"); + shader.toggleDefine("MOD_OP_SUB_XC", inOp.get() === "x-c"); + + shader.toggleDefine("MOD_OP_ADD", inOp.get() === "c+x"); + shader.toggleDefine("MOD_OP_MUL", inOp.get() === "c*x"); + + shader.toggleDefine("MOD_OP_DIV_XC", inOp.get() === "x/c"); + shader.toggleDefine("MOD_OP_DIV_CX", inOp.get() === "c/x"); + + shader.toggleDefine("MOD_OP_MODULO", inOp.get() === "c%x"); + + shader.toggleDefine("MOD_USE_TEX", inTex2.get()); + + shader.toggleDefine("MOD_CHAN_R", chanR.get()); + r.setUiAttribs({ "greyout": !chanR.get() || inTex2.get() }); + + shader.toggleDefine("MOD_CHAN_G", chanG.get()); + g.setUiAttribs({ "greyout": !chanG.get() || inTex2.get() }); + + shader.toggleDefine("MOD_CHAN_B", chanB.get()); + b.setUiAttribs({ "greyout": !chanB.get() || inTex2.get() }); + + shader.toggleDefine("MOD_CHAN_A", chanA.get()); + a.setUiAttribs({ "greyout": !chanA.get() || inTex2.get() }); +} + +function dorender() +{ + shader.popTextures(); + if (inTex.get()) shader.pushTexture(textureUniform, inTex.get().tex); + if (inTex2.get()) shader.pushTexture(textureUniform2, inTex2.get().tex); + + const finTex = texMath.render(shader); + + outTex.set(null); + outTex.set(finTex); + trigger.trigger(); +} + + +}; + +Ops.Dev.GlArrayMath.prototype = new CABLES.Op(); +CABLES.OPS["0204b33a-2917-4eea-9c31-3b185e4fe638"]={f:Ops.Dev.GlArrayMath,objName:"Ops.Dev.GlArrayMath"}; + + + + +// ************************************************************** +// +// Ops.Dev.GlArrayModulo +// +// ************************************************************** + +Ops.Dev.GlArrayModulo = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"rgbMath_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\n\nUNI float modX;\nUNI float modY;\nUNI float modZ;\n\nvoid main()\n{\n vec4 col=texture(tex,texCoord);\n\n #ifdef MOD_MODULO_X\n col.x=mod(col.x,modX);\n #endif\n\n #ifdef MOD_MODULO_Z\n col.y=mod(col.y,modY);\n #endif\n\n #ifdef MOD_MODULO_Z\n col.z=mod(col.z,modZ);\n #endif\n\n outColor= col;\n}\n",}; +const + render = op.inTrigger("Render"), + inTex = op.inTexture("GlArray"), + + inDoModX = op.inBool("X",true), + inModX = op.inValue("Modulo X", 1), + + inDoModY = op.inBool("Y",true), + inModY = op.inValue("Modulo Y", 1), + + inDoModZ = op.inBool("Z",true), + inModZ = op.inValue("Modulo Z", 1), + + trigger = op.outTrigger("trigger"), + outTex = op.outTexture("Result"); + +render.onTriggered = dorender; + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); +const texMath = new CGL.ShaderTextureMath(cgl, op.objName, { "texturePort": inTex }); + +shader.setSource(shader.getDefaultVertexShader(), attachments.rgbMath_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uniModX = new CGL.Uniform(shader, "f", "modX", inModX), + uniModY = new CGL.Uniform(shader, "f", "modY", inModY), + uniModZ = new CGL.Uniform(shader, "f", "modZ", inModZ); + +inDoModX.onChange = +inDoModY.onChange = +inDoModZ.onChange = updateDefines; + +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("MOD_MODULO_X", inDoModX.get()); + inModX.setUiAttribs({ "greyout": !inDoModX.get() }); + + shader.toggleDefine("MOD_MODULO_Y", inDoModY.get()); + inModY.setUiAttribs({ "greyout": !inDoModY.get() }); + + shader.toggleDefine("MOD_MODULO_Z", inDoModZ.get()); + inModZ.setUiAttribs({ "greyout": !inDoModZ.get() }); +} + +function dorender() +{ + const finTex = texMath.render(shader); + outTex.set(finTex); + trigger.trigger(); +} + + +}; + +Ops.Dev.GlArrayModulo.prototype = new CABLES.Op(); +CABLES.OPS["a017cc92-2354-45df-820f-ed6aad3bbb0e"]={f:Ops.Dev.GlArrayModulo,objName:"Ops.Dev.GlArrayModulo"}; + + + + +// ************************************************************** +// +// Ops.Dev.GlArrayNormalize +// +// ************************************************************** + +Ops.Dev.GlArrayNormalize = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"rgbMath_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\n\nUNI float modX;\nUNI float modY;\nUNI float modZ;\n\nvoid main()\n{\n vec4 col=texture(tex,texCoord);\n\ncol.xyz=normalize(col.xyz);\n\n outColor= col;\n}\n",}; +const + render = op.inTrigger("Render"), + inTex = op.inTexture("GlArray"), + + trigger = op.outTrigger("trigger"), + outTex = op.outTexture("Result"); + +render.onTriggered = dorender; + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); +const texMath = new CGL.ShaderTextureMath(cgl, op.objName, { "texturePort": inTex }); + +shader.setSource(shader.getDefaultVertexShader(), attachments.rgbMath_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); + + + +function dorender() +{ + const finTex = texMath.render(shader); + outTex.set(finTex); + trigger.trigger(); +} + + +}; + +Ops.Dev.GlArrayNormalize.prototype = new CABLES.Op(); +CABLES.OPS["c7ee53af-2d34-4ca9-bcea-5cbf7f5aab4e"]={f:Ops.Dev.GlArrayNormalize,objName:"Ops.Dev.GlArrayNormalize"}; + + + + +// ************************************************************** +// +// Ops.Dev.GlArrayRandom +// +// ************************************************************** + +Ops.Dev.GlArrayRandom = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"randoms_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\n\nUNI float seed;\n\nUNI float rmin;\nUNI float rmax;\nUNI float gmin;\nUNI float gmax;\nUNI float bmin;\nUNI float bmax;\n\n{{CGL.BLENDMODES}}\n{{MODULES_HEAD}}\n\n{{CGL.RANDOM_TEX}}\n\nfloat map(float value, float min1, float max1, float min2, float max2) {\n return min2 + (value - min1) * (max2 - min2) / (max1 - min1);\n}\n\n\nvoid main()\n{\n vec4 rnd=vec4((cgl_random3(texCoord.xy + vec2(seed))), 1.0);\n\n rnd.r=map(rnd.x, 0., 1., rmin, rmax);\n rnd.y=map(rnd.y, 0., 1., gmin, gmax);\n rnd.z=map(rnd.z, 0., 1., bmin, bmax);\n rnd.a=1.0;\n\n // vec4 base¿=texture(tex,texCoord);\n // vec4 col¿=vec4( _blend(base.rgb,rnd.rgb) ,1.0);\n\n // outColor=vec4( mix( col.rgb, base.rgb ,1.0-base.a*amount),1.0);\n outColor=rnd;\n}",}; +const + render = op.inTrigger("Render"), + next = op.outTrigger("Next"), + inNum = op.inInt("Length", 10000), + inLayout = op.inSwitch("Layout", ["Square", "Vertical", "Horizontal"], "Square"), + + inRMin = op.inFloat("X Min", 0), + inRMax = op.inFloat("X Max", 1), + + inGMin = op.inFloat("Y Min", 0), + inGMax = op.inFloat("Y Max", 1), + + inBMin = op.inFloat("Z Min", 0), + inBMax = op.inFloat("Z Max", 1), + + inSeed = op.inFloat("Seed", 1), + + outTex = op.outTexture("Result"); + +render.onTriggered = dorender; + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); +let texMath = null;// = new CGL.ShaderTextureMath(cgl, op.objName, { "width":100,"height":100 }); + +updateSize(); + +shader.setSource(shader.getDefaultVertexShader(), attachments.randoms_frag); +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uniformRMin = new CGL.Uniform(shader, "f", "rmin", inRMin), + uniformRMax = new CGL.Uniform(shader, "f", "rmax", inRMax), + uniformGMin = new CGL.Uniform(shader, "f", "gmin", inGMin), + uniformGMax = new CGL.Uniform(shader, "f", "gmax", inGMax), + uniformBMin = new CGL.Uniform(shader, "f", "bmin", inBMin), + uniformBMax = new CGL.Uniform(shader, "f", "bmax", inBMax), + uniformSeed = new CGL.Uniform(shader, "f", "seed", inSeed); + +updateDefines(); + +inLayout.onChange = + inNum.onChange = updateSize; + +function updateSize() +{ + let w = Math.ceil(Math.sqrt(inNum.get())); // square texture size + let h = w; + const max = op.patch.cgl.gl.getParameter(op.patch.cgl.gl.MAX_TEXTURE_SIZE); + + if (inLayout.get() === "Vertical" || inLayout.get() === "Horizontal") + { + if (inNum.get() < max) + { + w = 1; + h = inNum.get(); + } + else + { + w = Math.ceil(inNum.get() / max); + h = max; + } + } + + if (inLayout.get() === "Horizontal") + { + let x = w; + w = h; + h = x; + } + + texMath = new CGL.ShaderTextureMath(cgl, op.objName, { "width": w, "height": h }); +} + +function updateDefines() +{ + +} + +function dorender() +{ + const finTex = texMath.render(shader); + outTex.set(finTex); + next.trigger(); +} + + +}; + +Ops.Dev.GlArrayRandom.prototype = new CABLES.Op(); +CABLES.OPS["041f5b18-74b4-4a03-9987-4451bd334464"]={f:Ops.Dev.GlArrayRandom,objName:"Ops.Dev.GlArrayRandom"}; + + + + +// ************************************************************** +// +// Ops.Dev.GlPatch +// +// ************************************************************** + +Ops.Dev.GlPatch = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Render"), + refresh = op.inTriggerButton("Refresh"), + debug = op.inTriggerButton("debug"), + next = op.inTrigger("Next"); + +const p = new CABLES.GLGUI.GlPatch(op.patch.cgl); +const api = new CABLES.GLGUI.GlPatchAPI(op.patch, p); + +let firstTime = true; + +refresh.onTriggered = function () +{ + api.reset(); +}; + +render.onTriggered = function () +{ + if (firstTime) + { + api.reset(); + firstTime = false; + } + + p.render( + op.patch.cgl.canvasWidth, + op.patch.cgl.canvasHeight + ); + next.trigger(); +}; + +debug.onTriggered = () => +{ + let count = 0; + for (const i in p._glOpz) + { + p._glOpz[i].updateVisible(); + p._glOpz[i].updatePosition(); + + for (const k in p._glOpz[i]._links) + { + count++; + if (p._glOpz[i]._links[k]) p._glOpz[i]._links[k].update(); + console.log(p._glOpz[i]._links[k]); + + p._glOpz[i]._links[k]._cable.updateLineStyle(); + p._glOpz[i]._links[k]._cable._updateLinePos(); + } + } +}; + + +}; + +Ops.Dev.GlPatch.prototype = new CABLES.Op(); +CABLES.OPS["ad6e3e6b-9d88-4378-b09f-6b57999d4f91"]={f:Ops.Dev.GlPatch,objName:"Ops.Dev.GlPatch"}; + + + + +// ************************************************************** +// +// Ops.Dev.GltfExplodeNodes +// +// ************************************************************** + +Ops.Dev.GltfExplodeNodes = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Update"), + inFilter = op.inString("Filter", ""), + + inSeed = op.inFloat("Seed", 1), + + axisX = op.inFloat("Axis X", 0), + axisY = op.inFloat("Axis Y", 0), + axisZ = op.inFloat("Axis Z", 0), + + rotationX = op.inFloat("Rotation X", 0), + rotationY = op.inFloat("Rotation Y", 0), + rotationZ = op.inFloat("Rotation Z", 0), + + pivotOffsetX = op.inFloat("Random Pivot Offset X", 0), + pivotOffsetY = op.inFloat("Random Pivot Offset Y", 0), + pivotOffsetZ = op.inFloat("Random Pivot Offset Z", 0), + + next = op.outTrigger("Next"), + outNum = op.outNumber("Found"); + +const cgl = op.patch.cgl; + +const mat = mat4.create(); + +inExec.onTriggered = function () +{ + if (!cgl.frameStore.currentScene) return; + + let node = null; + + const ax = axisX.get(); + const ay = axisY.get(); + const az = axisZ.get(); + + Math.randomSeed = inSeed.get(); + let found = 0; + + for (let i = 0; i < cgl.frameStore.currentScene.nodes.length; i++) + { + if (cgl.frameStore.currentScene.nodes[i].name.indexOf(inFilter.get()) >= 0) + { + node = cgl.frameStore.currentScene.nodes[i]; + + found++; + + const oldTrans = vec3.create(); + + mat4.getTranslation(oldTrans, node.mat); + + // const v = Math.sin(time + (Math.seededRandom() * offs)) * ampl; + // node.addTranslate = [v * ax, v * ay, v * az]; + node.addTranslate = [oldTrans[0] * axisX.get(), oldTrans[1] * axisY.get(), oldTrans[2] * axisZ.get()]; + + mat4.identity(mat); + mat4.rotateX(mat, mat, rotationX.get() * (Math.seededRandom() * 301) * CGL.DEG2RAD); + mat4.rotateY(mat, mat, rotationY.get() * (Math.seededRandom() * 301) * CGL.DEG2RAD); + mat4.rotateZ(mat, mat, rotationZ.get() * (Math.seededRandom() * 301) * CGL.DEG2RAD); + + mat4.translate(mat, mat, [(Math.seededRandom() - 0.5) * pivotOffsetX.get(), (Math.seededRandom() - 0.5) * pivotOffsetY.get(), (Math.seededRandom() - 0.5) * pivotOffsetZ.get()]); + + node.addMulMat = mat; + } + } + + outNum.set(found); + + next.trigger(); +}; + + +}; + +Ops.Dev.GltfExplodeNodes.prototype = new CABLES.Op(); +CABLES.OPS["5652c2ef-2a9f-48f6-80ef-70e154db04b5"]={f:Ops.Dev.GltfExplodeNodes,objName:"Ops.Dev.GltfExplodeNodes"}; + + + + +// ************************************************************** +// +// Ops.Dev.Graphics.Meshes.Circle_v2 +// +// ************************************************************** + +Ops.Dev.Graphics.Meshes.Circle_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Trigger"), + radius = op.inValue("radius", 0.5), + innerRadius = op.inValueSlider("innerRadius", 0), + segments = op.inValueInt("segments", 40), + percent = op.inValueSlider("percent", 1), + steps = op.inValue("steps", 0), + invertSteps = op.inValueBool("invertSteps", false), + mapping = op.inSwitch("mapping", ["flat", "round"], "flat"), + drawSpline = op.inValueBool("Spline", false), + doRender = op.inValueBool("Render", true), + trigger = op.outTrigger("next"), + geomOut = op.outObject("geometry", null, "geometry"); + +op.setPortGroup("Size", [radius, innerRadius]); +op.setPortGroup("Display", [percent, steps, invertSteps]); + +mapping.onChange = + segments.onChange = + radius.onChange = + innerRadius.onChange = + percent.onChange = + steps.onChange = + invertSteps.onChange = + drawSpline.onChange = calcLater; + +geomOut.ignoreValueSerialize = true; + +let geom = new CGL.Geometry("circle"); +let mesh = null; +const lastSegs = -1; + +let oldPrim = 0; +let shader = null; +let needsCalc = true; + +render.onTriggered = renderMesh; + +op.preRender = () => +{ + renderMesh(); +}; + +render.onLinkChanged = () => +{ + if (!trigger.isLinked()) + { + if (mesh) mesh.dispose(); + mesh = null; + geomOut.set(null); + } +}; + +function renderMesh() +{ + const cgl = op.patch.cg; + if (!CGL.TextureEffect.checkOpNotInTextureEffect(op)) return; + + if (needsCalc)calc(); + shader = cgl.getShader(); + if (!shader) return; + oldPrim = shader.glPrimitive; + + if (drawSpline.get()) shader.glPrimitive = cgl.gl.LINE_STRIP; + + if (mesh && doRender.get())mesh.render(shader); + trigger.trigger(); + + shader.glPrimitive = oldPrim; +} + +function calc() +{ + const segs = Math.max(3, Math.floor(segments.get())); + + geom.clear(); + + const faces = []; + const texCoords = []; + const vertexNormals = []; + const tangents = []; + const biTangents = []; + + let i = 0, degInRad = 0; + let oldPosX = 0, oldPosY = 0; + let oldPosXTexCoord = 0, oldPosYTexCoord = 0; + + let oldPosXIn = 0, oldPosYIn = 0; + let oldPosXTexCoordIn = 0, oldPosYTexCoordIn = 0; + + let posxTexCoordIn = 0, posyTexCoordIn = 0; + let posxTexCoord = 0, posyTexCoord = 0; + let posx = 0, posy = 0; + + const perc = Math.max(0.0, percent.get()); + const verts = []; + + if (drawSpline.get()) + { + let lastX = 0; + let lastY = 0; + const tc = []; + for (i = 0; i <= segs * perc; i++) + { + degInRad = (360 / segs) * i * CGL.DEG2RAD; + posx = Math.cos(degInRad) * radius.get(); + posy = Math.sin(degInRad) * radius.get(); + + posyTexCoord = 0.5; + + if (i > 0) + { + verts.push(lastX); + verts.push(lastY); + verts.push(0); + posxTexCoord = 1.0 - (i - 1) / segs; + + tc.push(posxTexCoord, posyTexCoord); + } + verts.push(posx); + verts.push(posy); + verts.push(0); + + lastX = posx; + lastY = posy; + } + geom.setPointVertices(verts); + } + else + if (innerRadius.get() <= 0) + { + for (i = 0; i <= segs * perc; i++) + { + degInRad = (360 / segs) * i * CGL.DEG2RAD; + posx = Math.cos(degInRad) * radius.get(); + posy = Math.sin(degInRad) * radius.get(); + + if (mapping.get() == "flat") + { + posxTexCoord = (Math.cos(degInRad) + 1.0) / 2; + posyTexCoord = 1.0 - (Math.sin(degInRad) + 1.0) / 2; + posxTexCoordIn = 0.5; + posyTexCoordIn = 0.5; + } + else if (mapping.get() == "round") + { + posxTexCoord = 1.0 - i / segs; + posyTexCoord = 0; + posxTexCoordIn = posxTexCoord; + posyTexCoordIn = 1; + } + + faces.push( + [posx, posy, 0], + [oldPosX, oldPosY, 0], + [0, 0, 0] + ); + + texCoords.push(posxTexCoord, posyTexCoord, oldPosXTexCoord, oldPosYTexCoord, posxTexCoordIn, posyTexCoordIn); + vertexNormals.push(0, 0, 1, 0, 0, 1, 0, 0, 1); + tangents.push(1, 0, 0, 1, 0, 0, 1, 0, 0); + biTangents.push(0, -1, 0, 0, -1, 0, 0, -1, 0); + + oldPosXTexCoord = posxTexCoord; + oldPosYTexCoord = posyTexCoord; + + oldPosX = posx; + oldPosY = posy; + } + + geom = CGL.Geometry.buildFromFaces(faces, "circle"); + geom.vertexNormals = vertexNormals; + geom.tangents = tangents; + geom.biTangents = biTangents; + geom.texCoords = texCoords; + } + else + { + let count = 0; + const numSteps = segs * perc; + const pos = 0; + + for (i = 0; i <= numSteps; i++) + { + count++; + + degInRad = (360 / segs) * i * CGL.DEG2RAD; + posx = Math.cos(degInRad) * radius.get(); + posy = Math.sin(degInRad) * radius.get(); + + const posxIn = Math.cos(degInRad) * innerRadius.get() * radius.get(); + const posyIn = Math.sin(degInRad) * innerRadius.get() * radius.get(); + + if (mapping.get() == "round") + { + posxTexCoord = 1.0 - i / segs; + posyTexCoord = 0; + posxTexCoordIn = posxTexCoord; + posyTexCoordIn = 1; + } + + if (steps.get() === 0.0 || + (count % parseInt(steps.get(), 10) === 0 && !invertSteps.get()) || + (count % parseInt(steps.get(), 10) !== 0 && invertSteps.get())) + { + faces.push( + [posx, posy, 0], + [oldPosX, oldPosY, 0], + [posxIn, posyIn, 0] + ); + + faces.push( + [posxIn, posyIn, 0], + [oldPosX, oldPosY, 0], + [oldPosXIn, oldPosYIn, 0] + ); + + texCoords.push( + posxTexCoord, 0, + oldPosXTexCoord, 0, + posxTexCoordIn, 1, + + posxTexCoord, 1, + oldPosXTexCoord, 0, + oldPosXTexCoordIn, 1); + + vertexNormals.push( + 0, 0, 1, 0, 0, 1, 0, 0, 1, + 0, 0, 1, 0, 0, 1, 0, 0, 1 + ); + tangents.push( + 1, 0, 0, 1, 0, 0, 1, 0, 0, + 1, 0, 0, 1, 0, 0, 1, 0, 0 + ); + biTangents.push( + 0, -1, 0, 0, -1, 0, 0, -1, 0, + 0, -1, 0, 0, -1, 0, 0, -1, 0); + } + + oldPosXTexCoordIn = posxTexCoordIn; + oldPosYTexCoordIn = posyTexCoordIn; + + oldPosXTexCoord = posxTexCoord; + oldPosYTexCoord = posyTexCoord; + + oldPosX = posx; + oldPosY = posy; + + oldPosXIn = posxIn; + oldPosYIn = posyIn; + } + + geom = CGL.Geometry.buildFromFaces(faces, "circle"); + geom.vertexNormals = vertexNormals; + geom.tangents = tangents; + geom.biTangents = biTangents; + + if (mapping.get() == "flat") geom.mapTexCoords2d(); + else geom.texCoords = texCoords; + } + + geomOut.set(null); + geomOut.set(geom); + + if (geom.vertices.length == 0) return; + if (mesh) mesh.dispose(); + mesh = op.patch.cg.createMesh(geom); + needsCalc = false; +} + +function calcLater() +{ + needsCalc = true; +} + +op.onDelete = function () +{ + if (mesh)mesh.dispose(); +}; + + +}; + +Ops.Dev.Graphics.Meshes.Circle_v2.prototype = new CABLES.Op(); +CABLES.OPS["e1dc7dd7-269e-4f6f-8522-35e641d7af9a"]={f:Ops.Dev.Graphics.Meshes.Circle_v2,objName:"Ops.Dev.Graphics.Meshes.Circle_v2"}; + + + + +// ************************************************************** +// +// Ops.Dev.InstancedModulo +// +// ************************************************************** + +Ops.Dev.InstancedModulo = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"colorize_frag":"\n\n\n\nvec4 MOD_col=texture(MOD_texture,MOD_coord);\n\n#ifdef METH_ADD\ncol.rgb+=MOD_col.rgb*MOD_strength;\n#endif\n#ifdef METH_MUL\ncol.rgb*=MOD_col.rgb*MOD_strength;\n#endif\n\n#ifdef MOD_DEBUG\n col.rg=mod(MOD_coord,1.0).rg;\n#endif\n","colorize_head_frag":"\nIN vec2 MOD_coord;\n\nUNI sampler2D MOD_texture;\nUNI float MOD_strength;","displace_vert":"\n#ifdef INSTANCING\n\nvec4 MOD_p=vec4(instMat[3][0],instMat[3][1],instMat[3][2],0.0);\n// MOD_coord=MOD_p.xy*(1.0/MOD_scale)+MOD_offset-vec2(0.5,0.5);\n\nMOD_p*=viewMatrix;\n\n// pos.x=mod(MOD_p.x,20.0);\n\nmMatrix[3].x=-viewMatrix[3].x+mod(viewMatrix[3].x-mMatrix[3].x,MOD_size.x)-(MOD_size.x/2.0)-MOD_pos.x;\nmMatrix[3].y=-2.0*viewMatrix[3].y+mod(viewMatrix[3].y-mMatrix[3].y,MOD_size.y)-(MOD_size.y/2.0)-MOD_pos.y;\n// mMatrix[3].y=mMatrix[3].y;\nmMatrix[3].z=mMatrix[3].z;\n\n\n#endif\n\n","displace_head_vert":"OUT vec2 MOD_coord;\n\n// #ifdef MOD_COLORIZE\n// OUT vec3 MOD_dispColor;\n// #endif",}; +const + inTrigger = op.inTrigger("Trigger"), + inWidth = op.inFloat("Width", 0), + inHeight = op.inFloat("Height", 0), + inX = op.inFloat("Pos X", 0), + inY = op.inFloat("Pos Y", 0), + next = op.outTrigger("Next"); + +inTrigger.onTriggered = render; + +const cgl = op.patch.cgl; + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "title": op.name, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": attachments.displace_head_vert || "", + "srcBodyVert": attachments.displace_vert || "" +}); + +// mod.addModule({ +// "title": op.name, +// "name": "MODULE_COLOR", +// "srcHeadFrag": attachments.colorize_head_frag, +// "srcBodyFrag": attachments.colorize_frag +// }); + +mod.addUniformVert("2f", "MOD_size", inWidth, inHeight); +mod.addUniformVert("2f", "MOD_pos", inX, inY); + +function updateDefines() +{ +} + +function render() +{ + mod.bind(); + next.trigger(); + mod.unbind(); +} + + +}; + +Ops.Dev.InstancedModulo.prototype = new CABLES.Op(); +CABLES.OPS["7d944e9c-c21a-460b-be18-17aa3233fde3"]={f:Ops.Dev.InstancedModulo,objName:"Ops.Dev.InstancedModulo"}; + + + + +// ************************************************************** +// +// Ops.Dev.Json.ObjectSpreadSheet +// +// ************************************************************** + +Ops.Dev.Json.ObjectSpreadSheet = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + spread = op.inArray("Spreadsheet"), + inNumColumns = op.inInt("Num Columns", 2), + result = op.outObject("Result"); + +spread.setUiAttribs({ "hidePort": true }); +inNumColumns.setUiAttribs({ "hidePort": true }); + +spread.onChange = update; +inNumColumns.onChange = updateUi; + +updateUi(); + +function updateUi() +{ + spread.setUiAttribs({ + "display": "spreadsheet", + "spread_numColumns": inNumColumns.get() + }); + update(); +} + +function update() +{ + result.set(null); + + if (!spread.get()) return; + + const data = spread.get(); + data.cells = data.cells || []; + + const obj = {}; + + for (let y = 0; y < data.cells.length; y++) + { + if (data.cells[y]) + { + if (data.cols == 2) + { + let v = data.cells[y][1] || null; + if (CABLES.UTILS.isNumeric(v)) v = parseFloat(v); + + if (data.cells[y][0]) obj[data.cells[y][0]] = v; + } + + if (data.cols > 2) + { + let row = {}; + + for (let x = 1; x < data.cols; x++) + { + let v = data.cells[y][x] || null; + if (CABLES.UTILS.isNumeric(v)) v = parseFloat(v); + + row[getColName(data, x)] = v; + } + if (data.cells[y] && data.cells[y][0] && row) obj[data.cells[y][0]] = row; + } + } + } + result.set(obj); +} + +function getColName(data, c) +{ + if (data && data.colNames && data.colNames.length > c && data.colNames[c]) + { + return data.colNames[c]; + } + + let str = ""; + + while (c >= 0) + { + str = "abcdefghijklmnopqrstuvwxyz"[c % 26] + str; + c = Math.floor(c / 26) - 1; + } + + return str; +} + + +}; + +Ops.Dev.Json.ObjectSpreadSheet.prototype = new CABLES.Op(); +CABLES.OPS["09667032-43c9-4f7c-8740-76a90f8ac356"]={f:Ops.Dev.Json.ObjectSpreadSheet,objName:"Ops.Dev.Json.ObjectSpreadSheet"}; + + + + +// ************************************************************** +// +// Ops.Dev.ParticleSystem +// +// ************************************************************** + +Ops.Dev.ParticleSystem = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"particle_frag":"IN vec2 texCoord;\n\nUNI sampler2D texOldPos;\nUNI sampler2D texSpawnPos;\nUNI sampler2D texTiming;\n\nUNI sampler2D texFeedbackVel;\nUNI sampler2D texSpawnVel;\n\nUNI float mass;\nUNI float reset;\n\nUNI vec3 pos;\nUNI vec3 scale;\nUNI vec3 gravity;\n\nUNI vec2 lifeTime;\nUNI float time;\nUNI float timeDiff;\n\n\n\nUNI vec4 velocity; // xyz: xyz / w: inherit velocity\n\n\nUNI float spread;\n\n{{MODULES_HEAD}}\n{{CGL.RANDOM_LOW}}\n\nvoid main()\n{\n vec4 oldPos=texture(texOldPos,texCoord);\n vec4 vtiming=texture(texTiming,texCoord);\n vec4 oldVelocity=texture(texFeedbackVel,texCoord);\n vec4 newPos=oldPos;//vec4(1.0);\n\n // respawn!!\n if( time>vtiming.g || reset==1.0 )\n {\n newPos.rgb =pos;\n vec3 rnd=(cgl_random3(texCoord+gl_FragCoord.x/gl_FragCoord.y+time));\n\n rnd=texture(texSpawnPos,rnd.xy).rgb;\n\n oldVelocity=texture(texSpawnVel,texCoord);\n\n newPos.rgb+=rnd;\n\n vtiming.r=time;\n\n vtiming.g=(cgl_random(time*texCoord)*(lifeTime.y-lifeTime.x))+lifeTime.x+time;\n\n if(reset==1.0)\n vtiming.g=time+cgl_random(time*22.0*texCoord)*lifeTime.y;\n }\n\n vtiming.a=1.0;\n\n float lifeProgress=( (time-vtiming.r) / (vtiming.g-vtiming.r));\n\n vec3 grav=gravity*mass*lifeProgress;\n\n\n\n // newPos.rgb+=timeDiff*velocity.rgb*3.0;\n\n newPos.rgb+=grav*timeDiff;\n newPos.rgb+=velocity.xyz*timeDiff;\n\n // newPos.g-=time*0.01;\n\n\n // newPos.rgb+=normalize(newPos.rgb-oldPos.rgb)*0.2;\n\n // newPos.rgb+=(oldVelocity.rgb)*smoothstep(0.0,1.0,lifeProgress)*0.9;\n // newPos.rgb+=(oldVelocity.rgb)*(1.0-smoothstep(0.0,1.0,lifeProgress)*0.1);\n\n newPos.rgb-=((1.0-lifeProgress)*timeDiff*40.8*velocity.w)*oldVelocity.rgb;\n\n\n // gl_Position\n // r:x\n // g:y\n // b:z\n outColor0=vec4(newPos.rgb,1.0);\n\n // timing\n // r: starttime\n // g: endtime\n outColor1=vtiming;\n\n // timing output\n // r: life progress\n outColor2=vec4(vec3(lifeProgress ),1.);\n\n // velocity\n // oldVelocity.rgb*=1.995;\n outColor3=oldVelocity;\n\n\n // outColor0=vec4(1.0,0.3,0.0,1.0);\n // outColor1=vec4(0.0,1.0,0.0,1.0);\n // outColor2=vec4(0.0,0.0,1.0,1.0);\n // outColor3=vec4(1.0,1.0,0.0,1.0);\n\n\n}",}; +const + emptyTex = CGL.Texture.getEmptyTexture(op.patch.cgl), + exec = op.inTrigger("Execute"), + inNumParticles = op.inInt("Num Particles", 10000), + inReset = op.inTriggerButton("Reset"), + + // inTime=op.inFloat("Time",0), + inLifeTimeMin = op.inFloat("Min Lifetime", 0.5), + inLifeTimeMax = op.inFloat("Max Lifetime", 2), + + inMass = op.inFloat("Mass", 0), + + posX = op.inFloatSlider("Position X", 0), + posY = op.inFloatSlider("Position Y", 0), + posZ = op.inFloatSlider("Position Z", 0), + + moveX = op.inFloatSlider("Velocity X", 0), + moveY = op.inFloatSlider("Velocity Y", 1), + moveZ = op.inFloatSlider("Velocity Z", 0), + + gravX = op.inFloatSlider("Gravity X", 0), + gravY = op.inFloatSlider("Gravity Y", 1), + gravZ = op.inFloatSlider("Gravity Z", 0), + + inherVel = op.inFloatSlider("Inherit Velocity", 0), + + inTexOldPos = op.inTexture("Feedback Positions"), + inTexSpawn = op.inTexture("Spawn Positions"), + inTexSpawnVel = op.inTexture("Spawn Velocity"), + + next = op.outTrigger("Next"), + outTexPos = op.outTexture("Positions", emptyTex), + outTexTiming = op.outTexture("Timing", emptyTex), + outTest = op.outTexture("Test", emptyTex), + outTexSize = op.outNumber("Tex Size"); + +op.setPortGroup("Constant Velocity", [moveX, moveY, moveZ]); +op.setPortGroup("Position", [posX, posY, posZ]); + +let lastX = 0; +let lastY = 0; +let lastZ = 0; + +let texTiming = null; +let texPos = null; +let lastTime = CABLES.now(); + +const tcPos = new CGL.CopyTexture(op.patch.cgl, "particlesys_pos", + { + "shader": attachments.particle_frag, + "numRenderBuffers": 4, + "isFloatingPointTexture": true, + "filter": CGL.Texture.FILTER_NEAREST + }); + +const tcTiming = new CGL.CopyTexture(op.patch.cgl, "particlesys_timing", { "isFloatingPointTexture": true, "filter": CGL.Texture.FILTER_NEAREST }); + +// only used when no input texture is given, just for simple systems... +const tcFeedback = new CGL.CopyTexture(op.patch.cgl, "particlesys_feedback", { "isFloatingPointTexture": true, "filter": CGL.Texture.FILTER_NEAREST }); +const tcFeedbackVel = new CGL.CopyTexture(op.patch.cgl, "particlesys_feedbackvel", { "isFloatingPointTexture": true, "filter": CGL.Texture.FILTER_NEAREST }); + +const + cgl = op.patch.cgl, + uniTexOldPos = new CGL.Uniform(tcPos.bgShader, "t", "texOldPos", 0), + uniTexSpawn = new CGL.Uniform(tcPos.bgShader, "t", "texSpawnPos", 1), + uniTexTiming = new CGL.Uniform(tcPos.bgShader, "t", "texTiming", 2), + uniTexSpawnVel = new CGL.Uniform(tcPos.bgShader, "t", "texSpawnVel", 3), + uniTexFeedbackVel = new CGL.Uniform(tcPos.bgShader, "t", "texFeedbackVel", 4), + + uniTime = new CGL.Uniform(tcPos.bgShader, "f", "time", 0), + uniLifeTime = new CGL.Uniform(tcPos.bgShader, "2f", "lifeTime", inLifeTimeMin, inLifeTimeMax), + uniTimeDiff = new CGL.Uniform(tcPos.bgShader, "f", "timeDiff", 0), + + uniVel = new CGL.Uniform(tcPos.bgShader, "4f", "velocity", moveX, moveY, moveZ, inherVel), + uniPos = new CGL.Uniform(tcPos.bgShader, "3f", "pos", posX, posY, posZ), + unigrav = new CGL.Uniform(tcPos.bgShader, "3f", "gravity", gravX, gravY, gravZ), + uniMass = new CGL.Uniform(tcPos.bgShader, "f", "mass", inMass), + + uniReset = new CGL.Uniform(tcPos.bgShader, "f", "reset", 0); + +inReset.onTriggered = () => +{ + uniReset.setValue(1); +}; + +inNumParticles.onChange = createTextures; + +const texBlack = new CGL.Texture(cgl, { + "isFloatingPointTexture": true, + "width": 8, + "height": 8 }); + +function createTextures() +{ + const size = Math.ceil(Math.sqrt(inNumParticles.get())); + outTexSize.set(size); + + console.log(size); + + texTiming = new CGL.Texture(cgl, { + "isFloatingPointTexture": true, + "filter": CGL.Texture.FILTER_NEAREST, + "width": size, + "height": size }); + texPos = new CGL.Texture(cgl, { + "isFloatingPointTexture": true, + "filter": CGL.Texture.FILTER_NEAREST, + "width": size, + "height": size }); +} + +exec.onTriggered = () => +{ + let firsttime = false; + // if (!inTexOldPos.get()) return; + if (!texTiming) + { + firsttime = true; + createTextures(); + uniReset.setValue(1); + } + + tcPos.bgShader.popTextures(); + + uniTime.setValue(op.patch.freeTimer.get()); + + if (!inTexOldPos.isLinked()) + { + + } + + if (firsttime)tcPos.bgShader.pushTexture(uniTexOldPos, texPos.tex); + else + { + if (inTexOldPos.isLinked()) + tcPos.bgShader.pushTexture(uniTexOldPos, inTexOldPos.get().tex); + else + tcPos.bgShader.pushTexture(uniTexOldPos, tcFeedback.copy(outTexPos.get())); + } + + if (inTexSpawn.get()) tcPos.bgShader.pushTexture(uniTexSpawn, inTexSpawn.get().tex); + else tcPos.bgShader.pushTexture(uniTexSpawn, texBlack.tex); + + if (inTexSpawnVel.get()) tcPos.bgShader.pushTexture(uniTexSpawnVel, inTexSpawnVel.get().tex); + + if (tcPos.fb) tcPos.bgShader.pushTexture(uniTexFeedbackVel, tcFeedbackVel.copy(tcPos.fb.getTextureColorNum(3))); + + if (firsttime)tcPos.bgShader.pushTexture(uniTexTiming, texTiming.tex); + else + if (tcPos.fb && tcPos.fb.getTextureColorNum(1))tcPos.bgShader.pushTexture(uniTexTiming, tcTiming.copy(tcPos.fb.getTextureColorNum(1))); + + tcPos.copy(texPos); + + uniReset.setValue(0); + + uniTimeDiff.setValue((CABLES.now() - lastTime) / 1000); + lastTime = CABLES.now(); + + lastX = moveX.get(); + lastY = moveY.get(); + lastZ = moveZ.get(); + + outTexPos.set(emptyTex); + outTexPos.set(tcPos.fb.getTextureColorNum(0)); + + outTexTiming.set(emptyTex); + outTexTiming.set(tcPos.fb.getTextureColorNum(2)); + + outTest.set(texPos); + outTest.set(tcPos.fb.getTextureColorNum(3)); + + next.trigger(); +}; + +// + + +}; + +Ops.Dev.ParticleSystem.prototype = new CABLES.Op(); +CABLES.OPS["bd94c323-a211-4fb6-a8aa-b724b610d885"]={f:Ops.Dev.ParticleSystem,objName:"Ops.Dev.ParticleSystem"}; + + + + +// ************************************************************** +// +// Ops.Dev.String.ConcatMultiArray +// +// ************************************************************** + +Ops.Dev.String.ConcatMultiArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const addSpacesCheckBox = op.inBool("add spaces", false), + newLineX = op.inBool("new lines", false), + result = op.outString("concat string"), + outArr = op.outArray("Result"), + outLines=op.outNumber("Total Lines"); + +const + stringPorts = [], + arrayPorts = []; + +stringPorts.onChange = + addSpacesCheckBox.onChange = + newLineX.onChange = update; + +for (let i = 0; i < 8; i++) +{ + let p = op.inString("String " + i); + let pA = op.inArray("Array " + i); + stringPorts.push(p); + arrayPorts.push(pA); + + p.onChange = + pA.onChange = update; +} + +function update() +{ + let str = ""; + let nl = ""; + let space = addSpacesCheckBox.get(); + let line = 0; + let numLines = 1; + let countStringLines=0; + + for (let i = 0; i < arrayPorts.length; i++) + { + if(arrayPorts[i].get()) numLines = Math.max(numLines, arrayPorts[i].get().length); + } + + for (let j = 0; j < numLines; j++) + { + for (let i = 0; i < stringPorts.length; i++) + { + const inString = stringPorts[i].get(); + const inArray = arrayPorts[i].get(); + if (!inString && !inArray) continue; + if (i > 0 && space) str += " "; + + str += inString; + if (inArray) + { + if(space)str += " "; + str += inArray[j]; + } + } + if (newLineX.get() ) + { + str += "\n"; + countStringLines++; + } + + } + + result.set(str); + outLines.set(countStringLines); +} + + +}; + +Ops.Dev.String.ConcatMultiArray.prototype = new CABLES.Op(); +CABLES.OPS["9420ebd1-e0e9-44a6-825e-402b9b1ce71f"]={f:Ops.Dev.String.ConcatMultiArray,objName:"Ops.Dev.String.ConcatMultiArray"}; + + + + +// ************************************************************** +// +// Ops.Dev.SvgPathToPoints +// +// ************************************************************** + +Ops.Dev.SvgPathToPoints = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr = op.inString("SVG Path"), + inStepSize = op.inFloat("Bezier Stepsize", 3), + outArr = op.outArray("Points A"), + outHoles = op.outArray("Points B"); + +inStepSize.onChange = +inStr.onChange = () => +{ + let str = inStr.get(); + + if (!str || str.length < 2) return; + + str = str.replace(/([A-Z,a-z])/g, " $1 "); + + const cmds = fromPathToArray(str); + + // create a list of closed contours + const polys = []; + cmds.forEach(({ type, x, y, x1, y1, x2, y2 }) => + { + switch (type) + { + case "M": + polys.push(new Polygon()); + polys[polys.length - 1].moveTo({ x, y }); + break; + case "L": + polys[polys.length - 1].moveTo({ x, y }); + break; + case "C": + polys[polys.length - 1].cubicTo({ x, y }, { "x": x1, "y": y1 }, { "x": x2, "y": y2 }); + break; + case "Q": + polys[polys.length - 1].conicTo({ x, y }, { "x": x1, "y": y1 }); + break; + case "Z": + polys[polys.length - 1].close(); + break; + } + }); + + // sort contours by descending area + polys.sort((a, b) => Math.abs(b.area) - Math.abs(a.area)); + // classify contours to find holes and their 'parents' + const root = []; + for (let i = 0; i < polys.length; ++i) + { + let parent = null; + for (let j = i - 1; j >= 0; --j) + { + // a contour is a hole if it is inside its parent and has different winding + if (polys[j].inside(polys[i].points[0]) && polys[i].area * polys[j].area < 0) + { + parent = polys[j]; + break; + } + } + if (parent) + { + parent.children.push(polys[i]); + } + else + { + root.push(polys[i]); + } + } + + const totalPoints = polys.reduce((sum, p) => sum + p.points.length, 0); + const vertexData = new Float32Array(totalPoints * 2); + let vertexCount = 0; + const indices = []; + + // function process(poly) { + // // construct input for earcut + // const coords = []; + // const holes = []; + // poly.points.forEach(({x, y}) => coords.push(x, y)); + // poly.children.forEach(child => { + // // children's children are new, separate shapes + // child.children.forEach(process); + + // holes.push(coords.length / 2); + // child.points.forEach(({x, y}) => coords.push(x, y)); + // }); + + // // add vertex data + // vertexData.set(coords, vertexCount * 2); + // // add index data + // earcut(coords, holes).forEach(i => indices.push(i + vertexCount)); + // vertexCount += coords.length / 2; + // } + // root.forEach(process); + + const coords = []; + const holes = []; + + for (let i = 0; i < polys.length; i++) + { + const arr = []; + for (let j = 0; j < polys[i].points.length; j++) + { + arr.push(polys[i].points[j].x, polys[i].points[j].y, 0); + } + coords.push(arr); + + if (polys[i].children) + { + for (let j = 0; j < polys[i].children.length; j++) + { + const hole = []; + + for (let k = 0; k < polys[i].children[j].points.length; k++) + { + hole.push( + polys[i].children[j].points[k].x, + polys[i].children[j].points[k].y, + 0); + } + + holes.push(hole); + if (j > 0) coords.push([]); + } + } + + // if (!polys[i].children || polys[i].children.length == 0)holes.push([]); + + // polys[i].children.forEach((child) => + // { + // const hole = []; + // child.points.forEach(({ x, y }) => hole.push(x, y, 0)); + + // holes.push(hole); + // coords.push([]); + // }); + + // for(let i=holes.length;i 0) + { + let it = items.shift(); + if (PATH_COMMANDS.hasOwnProperty(it)) + { + currentCommand = it; + } + else + { + items.unshift(it); + } + + currentElement = { "type": currentCommand }; + PATH_COMMANDS[currentCommand].forEach((prop) => + { + it = items.shift(); // TODO sanity check + currentElement[prop] = parseFloat(it); + }); + if (currentCommand === "M") + { + currentCommand = "L"; + } + else if (currentCommand === "m") + { + currentCommand = "l"; + } + segments.push(currentElement); + } + return segments; +} + +// https://stackoverflow.com/questions/50554803/triangulate-path-data-from-opentype-js-using-earcut + +const MAX_BEZIER_STEPS = 15; +// this is for inside checks - doesn't have to be particularly +// small because glyphs have finite resolution +const EPSILON = 1e-6; + +class Polygon +{ + constructor() + { + this.points = []; + this.children = []; + this.area = 0.0; + + this.BEZIER_STEP_SIZE = inStepSize.get(); + } + + moveTo(p) + { + this.points.push(p); + } + + lineTo(p) + { + this.points.push(p); + } + + close() + { + let cur = this.points[this.points.length - 1]; + this.points.forEach((next) => + { + this.area += 0.5 * cross(cur, next); + cur = next; + }); + } + + conicTo(p, p1) + { + const p0 = this.points[this.points.length - 1]; + const dist = distance(p0, p1) + distance(p1, p); + const steps = Math.max(2, Math.min(MAX_BEZIER_STEPS, dist / this.BEZIER_STEP_SIZE)); + for (let i = 1; i <= steps; ++i) + { + const t = i / steps; + this.points.push(lerp(lerp(p0, p1, t), lerp(p1, p, t), t)); + } + } + + cubicTo(p, p1, p2) + { + const p0 = this.points[this.points.length - 1]; + const dist = distance(p0, p1) + distance(p1, p2) + distance(p2, p); + const steps = Math.max(2, Math.min(MAX_BEZIER_STEPS, dist / this.BEZIER_STEP_SIZE)); + for (let i = 1; i <= steps; ++i) + { + const t = i / steps; + const a = lerp(lerp(p0, p1, t), lerp(p1, p2, t), t); + const b = lerp(lerp(p1, p2, t), lerp(p2, p, t), t); + this.points.push(lerp(a, b, t)); + } + } + + inside(p) + { + let count = 0, cur = this.points[this.points.length - 1]; + this.points.forEach((next) => + { + const p0 = (cur.y < next.y ? cur : next); + const p1 = (cur.y < next.y ? next : cur); + if (p0.y < p.y + EPSILON && p1.y > p.y + EPSILON) + { + if ((p1.x - p0.x) * (p.y - p0.y) > (p.x - p0.x) * (p1.y - p0.y)) + { + count += 1; + } + } + cur = next; + }); + return (count % 2) !== 0; + } +} + +function distance(p1, p2) +{ + const dx = p1.x - p2.x, dy = p1.y - p2.y; + return Math.sqrt(dx * dx + dy * dy); +} + +function lerp(p1, p2, t) +{ + return { "x": (1 - t) * p1.x + t * p2.x, "y": (1 - t) * p1.y + t * p2.y }; +} + +function cross(p1, p2) +{ + return p1.x * p2.y - p1.y * p2.x; +} + + +}; + +Ops.Dev.SvgPathToPoints.prototype = new CABLES.Op(); +CABLES.OPS["43bcfbe3-7460-4b22-9a42-be787adf180d"]={f:Ops.Dev.SvgPathToPoints,objName:"Ops.Dev.SvgPathToPoints"}; + + + + +// ************************************************************** +// +// Ops.Dev.TestOp +// +// ************************************************************** + +Ops.Dev.TestOp = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"sdsdsd":"",}; +// your new op +// have a look at the documentation at: +// https://docs.cables.gl/dev_hello_op/dev_hello_op.html + +// sss + +const a = op.inFloat("name", 0); +const aa = op.inFloat("aaaa", 0); +const trig = op.inTrigger("Render"); + +const cgl = op.patch.cgl; +const meshRect = new CGL.WireframeRect(cgl); + +trig.onTriggered = function () +{ + meshRect.render(); +}; + + +}; + +Ops.Dev.TestOp.prototype = new CABLES.Op(); +CABLES.OPS["274d0d70-00a0-4a19-88ca-e480b5143715"]={f:Ops.Dev.TestOp,objName:"Ops.Dev.TestOp"}; + + + + +// ************************************************************** +// +// Ops.Dev.VertexTexture.RgbCurlNoise +// +// ************************************************************** + +Ops.Dev.VertexTexture.RgbCurlNoise = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"curl_frag":"UNI float z;\nUNI float x;\nUNI float y;\nUNI float scale;\nIN vec2 texCoord;\nUNI sampler2D tex;\n\n// UNI float amount;\nUNI float timeDelta;\nUNI vec3 offset;\n\n{{CGL.BLENDMODES}}\n{{CGL.RANDOM_TEX}}\n\nfloat Interpolation_C2( float x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); } // 6x^5-15x^4+10x^3\t( Quintic Curve. As used by Perlin in Improved Noise. http://mrl.nyu.edu/~perlin/paper445.pdf )\nvec2 Interpolation_C2( vec2 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec3 Interpolation_C2( vec3 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2( vec4 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2_InterpAndDeriv( vec2 x ) { return x.xyxy * x.xyxy * ( x.xyxy * ( x.xyxy * ( x.xyxy * vec2( 6.0, 0.0 ).xxyy + vec2( -15.0, 30.0 ).xxyy ) + vec2( 10.0, -60.0 ).xxyy ) + vec2( 0.0, 30.0 ).xxyy ); }\nvec3 Interpolation_C2_Deriv( vec3 x ) { return x * x * (x * (x * 30.0 - 60.0) + 30.0); }\n\n\nvoid FAST32_hash_3D( \tvec3 gridcell,\n out vec4 lowz_hash_0,\n out vec4 lowz_hash_1,\n out vec4 lowz_hash_2,\n out vec4 highz_hash_0,\n out vec4 highz_hash_1,\n out vec4 highz_hash_2\t)\t\t//\tgenerates 3 random numbers for each of the 8 cell corners\n{\n // gridcell is assumed to be an integer coordinate\n\n //\tTODO: \tthese constants need tweaked to find the best possible noise.\n //\t\t\tprobably requires some kind of brute force computational searching or something....\n const vec2 OFFSET = vec2( 50.0, 161.0 );\n const float DOMAIN = 69.0;\n const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );\n const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );\n\n //\ttruncate the domain\n gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;\n vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );\n\n //\tcalculate the noise\n vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;\n P *= P;\n P = P.xzxz * P.yyww;\n vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );\n vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );\n lowz_hash_0 = fract( P * lowz_mod.xxxx );\n highz_hash_0 = fract( P * highz_mod.xxxx );\n lowz_hash_1 = fract( P * lowz_mod.yyyy );\n highz_hash_1 = fract( P * highz_mod.yyyy );\n lowz_hash_2 = fract( P * lowz_mod.zzzz );\n highz_hash_2 = fract( P * highz_mod.zzzz );\n}\n\n//\n//\tPerlin Noise 3D ( gradient noise )\n//\tReturn value range of -1.0->1.0\n//\thttp://briansharpe.files.wordpress.com/2011/11/perlinsample.jpg\n//\nfloat Perlin3D( vec3 P )\n{\n //\testablish our grid cell and unit position\n vec3 Pi = floor(P);\n vec3 Pf = P - Pi;\n vec3 Pf_min1 = Pf - 1.0;\n\n#if 1\n //\n //\tclassic noise.\n //\trequires 3 random values per point. with an efficent hash function will run faster than improved noise\n //\n\n //\tcalculate the hash.\n //\t( various hashing methods listed in order of speed )\n vec4 hashx0, hashy0, hashz0, hashx1, hashy1, hashz1;\n FAST32_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n //SGPP_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n\n //\tcalculate the gradients\n vec4 grad_x0 = hashx0 - 0.49999;\n vec4 grad_y0 = hashy0 - 0.49999;\n vec4 grad_z0 = hashz0 - 0.49999;\n vec4 grad_x1 = hashx1 - 0.49999;\n vec4 grad_y1 = hashy1 - 0.49999;\n vec4 grad_z1 = hashz1 - 0.49999;\n vec4 grad_results_0 = inversesqrt( grad_x0 * grad_x0 + grad_y0 * grad_y0 + grad_z0 * grad_z0 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x0 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y0 + Pf.zzzz * grad_z0 );\n vec4 grad_results_1 = inversesqrt( grad_x1 * grad_x1 + grad_y1 * grad_y1 + grad_z1 * grad_z1 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x1 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y1 + Pf_min1.zzzz * grad_z1 );\n\n#if 1\n //\tClassic Perlin Interpolation\n vec3 blend = Interpolation_C2( Pf );\n vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n float final = dot( res0, blend2.zxzx * blend2.wwyy );\n final *= 1.1547005383792515290182975610039;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range *= 1.0/sqrt(0.75)\n return final;\n#else\n //\tClassic Perlin Surflet\n //\thttp://briansharpe.wordpress.com/2012/03/09/modifications-to-classic-perlin-noise/\n Pf *= Pf;\n Pf_min1 *= Pf_min1;\n vec4 vecs_len_sq = vec4( Pf.x, Pf_min1.x, Pf.x, Pf_min1.x ) + vec4( Pf.yy, Pf_min1.yy );\n float final = dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf.zzzz ) ), grad_results_0 ) + dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf_min1.zzzz ) ), grad_results_1 );\n final *= 2.3703703703703703703703703703704;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range *= 1.0/cube(0.75)\n return final;\n#endif\n\n#else\n //\n //\timproved noise.\n //\trequires 1 random value per point. Will run faster than classic noise if a slow hashing function is used\n //\n\n //\tcalculate the hash.\n //\t( various hashing methods listed in order of speed )\n vec4 hash_lowz, hash_highz;\n FAST32_hash_3D( Pi, hash_lowz, hash_highz );\n //BBS_hash_3D( Pi, hash_lowz, hash_highz );\n //SGPP_hash_3D( Pi, hash_lowz, hash_highz );\n\n //\n //\t\"improved\" noise using 8 corner gradients. Faster than the 12 mid-edge point method.\n //\tKen mentions using diagonals like this can cause \"clumping\", but we'll live with that.\n //\t[1,1,1] [-1,1,1] [1,-1,1] [-1,-1,1]\n //\t[1,1,-1] [-1,1,-1] [1,-1,-1] [-1,-1,-1]\n //\n hash_lowz -= 0.5;\n vec4 grad_results_0_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_lowz );\n hash_lowz = abs( hash_lowz ) - 0.25;\n vec4 grad_results_0_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_lowz );\n vec4 grad_results_0_2 = Pf.zzzz * sign( abs( hash_lowz ) - 0.125 );\n vec4 grad_results_0 = grad_results_0_0 + grad_results_0_1 + grad_results_0_2;\n\n hash_highz -= 0.5;\n vec4 grad_results_1_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_highz );\n hash_highz = abs( hash_highz ) - 0.25;\n vec4 grad_results_1_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_highz );\n vec4 grad_results_1_2 = Pf_min1.zzzz * sign( abs( hash_highz ) - 0.125 );\n vec4 grad_results_1 = grad_results_1_0 + grad_results_1_1 + grad_results_1_2;\n\n //\tblend the gradients and return\n vec3 blend = Interpolation_C2( Pf );\n vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n return dot( res0, blend2.zxzx * blend2.wwyy ) * (2.0 / 3.0);\t//\t(optionally) mult by (2.0/3.0) to scale to a strict -1.0->1.0 range\n#endif\n}\n\n\nvoid main()\n{\n vec4 base=texture(tex,texCoord);\n\n\n vec3 rnd=\n vec3(\n Perlin3D( ( (base.xyz+20.0) + vec3(x,y,z)) *scale ),\n Perlin3D( ( (base.xyz-20.0) + vec3(x,y,z)) *scale ),\n Perlin3D( ( (base.xyz+60.0) + vec3(x,y,z)) *scale )\n );\n\nfloat seed=1.0;\n vec3 noise=(cgl_random3(texCoord.xy)-0.5)*seed;\n rnd+=\n vec3(\n Perlin3D( ( (base.xyz+20.0+noise.x+offset.x) + vec3(x,y,z)) *scale ),\n Perlin3D( ( (base.xyz-20.0+noise.y+offset.y) + vec3(x,y,z)) *scale ),\n Perlin3D( ( (base.xyz+60.0+noise.z+offset.z) + vec3(x,y,z)) *scale )\n );\n\n\n // rnd=\n // (\n // vec3(\n // Perlin3D( ( (base.xyz+20.0) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz-20.0) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz+60.0) + vec3(x,y,z)) *scale )\n // )+\n // vec3(\n // Perlin3D( ( (base.xyz+20.0+(offset*scale)) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz-20.0+(offset*scale)) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz+60.0+(offset*scale)) + vec3(x,y,z)) *scale )\n // )*0.25+\n // vec3(\n // Perlin3D( ( (base.xyz+20.0-(offset*scale)) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz-20.0-(offset*scale)) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz+60.0-(offset*scale)) + vec3(x,y,z)) *scale )\n // )*0.25+\n // vec3(\n // Perlin3D( ( (base.xyz+20.0-(offset*scale)) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz-20.0+(offset*scale)) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz+60.0-(offset*scale)) + vec3(x,y,z)) *scale )\n // )*0.25+\n // vec3(\n // Perlin3D( ( (base.xyz+20.0+(offset*scale)) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz-20.0-(offset*scale)) + vec3(x,y,z)) *scale ),\n // Perlin3D( ( (base.xyz+60.0+(offset*scale)) + vec3(x,y,z)) *scale )\n // )*0.25\n\n // )/2.0;\n\n\n\n\n\n\n\n #ifdef MOD_NORM_SPEED\n rnd=normalize(rnd)*0.2;\n #endif\n #ifndef MOD_NORM_SPEED\n // rnd*=timeDelta;\n #endif\n\n // rnd=clamp(rnd,vec3(-0.01),vec3(0.01));\n // rnd*=0.01;\n // float cl=0.03;\n // rnd.x=clamp(rnd.x,-cl,cl);\n // rnd.y=clamp(rnd.y,-cl,cl);\n // rnd.z=clamp(rnd.z,-cl,cl);\n\n rnd*=timeDelta;\n\n vec3 coord=base.xyz+rnd*0.3;\n // coord.x+=( Perlin3D( ( (base.xyz+20.0) + vec3(x,y,z)) *scale )*timeDelta);\n // coord.y+=( Perlin3D( ( (base.xyz-20.0) + vec3(x,y,z)) *scale )*timeDelta);\n // coord.z+=( Perlin3D( ( (base.xyz+30.0) + vec3(x,y,z)) *scale )*timeDelta);\n\n // additional noise on top\n // coord.x+=Perlin3D(vec3(texCoord.x))*0.001;\n // coord.y+=Perlin3D(vec3(texCoord.y))*0.001;\n // coord.z+=Perlin3D(vec3(texCoord.y,texCoord.x,texCoord.y))*0.001;\n\n\n outColor=vec4(coord,1.0);\n\n\n // outColor=cgl_blend(base,coord,1.0);\n}\n",}; +const + render = op.inTrigger("Render"), + scale = op.inFloat("Scale", 1), + time = op.inFloat("Time", 0), + posX = op.inFloat("Pos X", 0), + posY = op.inFloat("Pos Y", 0), + posZ = op.inFloat("Pos Z", 0), + + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.curl_frag); +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + // textureMaskUniform = new CGL.Uniform(shader, "t", "texMask", 1), + + uniSeed = new CGL.Uniform(shader, "3f", "offset", posX, posX, posX), + uniTime = new CGL.Uniform(shader, "f", "time", time), + uniScale = new CGL.Uniform(shader, "f", "scale", scale), + uniTimeDelta = new CGL.Uniform(shader, "f", "timeDelta", 1); + +time.onChange = + scale.onChange = updateDefines; + +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("MOD_NORM_SPEED", true); +} + +let lastTime = 0; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + uniTimeDelta.set(time.get() - lastTime); + lastTime = time.get(); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Dev.VertexTexture.RgbCurlNoise.prototype = new CABLES.Op(); +CABLES.OPS["10bc3a93-47c6-48ea-aebb-20f990153e62"]={f:Ops.Dev.VertexTexture.RgbCurlNoise,objName:"Ops.Dev.VertexTexture.RgbCurlNoise"}; + + + + +// ************************************************************** +// +// Ops.Dev.VizBranchProfiler +// +// ************************************************************** + +Ops.Dev.VizBranchProfiler = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inObj = op.inObject("Profiler Data"), + + inRender = op.inSwitch("Render", ["Patch", "Canvas", "Both"], "Patch"), + inWidth = op.inInt("Width", 500), + inHeight = op.inInt("Height", 200), + outCanvas = op.outObject("Canvas", null, "element"), + outTotalDur = op.outNumber("Duration"), + inUpdate = op.inTriggerButton("Update"); + +op.setUiAttrib({ "height": 100, "width": 500, "resizable": true }); + +op.setPortGroup("Canvas", [inWidth, inHeight]); + +const colors = ["#D183BF", "#9091D6", "#FFC395", "#F0D165", "#63A8E8", "#CF5D9D", "#66C984", "#D66AA6", "#515151", "#7AC4E0"]; + +let colorCycle = 0; +let totalDur = 1; +let root = null; +let doUpdate = true; +let canvas = null; +let render2Canvas = false; +let canvasWidth = 0; +let canvasHeight = 0; + +inRender.onChange = updateUi; + +inHeight.onChange = inWidth.onChange = setupCanvas; + +function setupCanvas() +{ + if (render2Canvas && (!canvas || canvasHeight != inHeight.get() || canvasWidth != inWidth.get())) + { + if (canvas)canvas.remove(); + canvas = document.createElement("canvas"); + + canvasWidth = inWidth.get(); + canvasHeight = inHeight.get(); + canvas.setAttribute("width", canvasWidth); + canvas.setAttribute("height", canvasHeight); + } +} + +function updateUi() +{ + render2Canvas = inRender.get() != "Patch"; + + inWidth.setUiAttribs({ "greyout": !render2Canvas }); + inHeight.setUiAttribs({ "greyout": !render2Canvas }); + + setupCanvas(); +} + +function getWidth(layer, d) +{ + // if (d < 0.2) d = 0.004; + return layer.width * (d / totalDur); +} + +inUpdate.onTriggered = () => +{ + doUpdate = true; + + if (render2Canvas && inObj.get() && inObj.get().root) + { + const layer = { "width": inWidth.get(), "height": inHeight.get(), "x": 0, "y": 0 }; + const ctx = canvas.getContext("2d"); + + totalDur = inObj.get().root.dur; + // console.log(inObj.get()); + // console.log(inObj.get().root.dur) + clear(ctx, layer); + drawBranch(ctx, layer, inObj.get().root, 0, 0); + outCanvas.set(null); + outCanvas.set(canvas); + } + + outTotalDur.set(totalDur); +}; + +function clear(ctx, layer) +{ + ctx.fillStyle = "#222"; + ctx.fillRect( + layer.x, layer.y, + layer.width, layer.height); +} + +function drawBranch(ctx, layer, b, level, posx) +{ + if (!b) return; + + colorCycle++; + colorCycle %= (colors.length - 1); + + let rowHeight = (layer.height / 10); + let posy = rowHeight * level; + + ctx.fillStyle = colors[colorCycle]; + ctx.fillRect( + layer.x + posx, posy + layer.y, + getWidth(layer, b.dur), rowHeight); + + let fontSize = 18; + ctx.fillStyle = "#222"; + ctx.font = "normal " + fontSize + "px sourceCodePro"; + + let durs = "(" + Math.round(b.dur * 100) / 100 + "ms)"; + if (b.dur < 0.2)durs = ""; + ctx.fillText(b.name + durs, layer.x + posx, layer.y + posy + fontSize); + + let xadd = 0; + for (let i = 0; i < b.childs.length; i++) + { + drawBranch(ctx, layer, b.childs[i], level + 1, posx + xadd); + xadd += getWidth(layer, b.childs[i].dur); + } +} + +op.renderVizLayer = (ctx, layer) => +{ + if (!inObj.get().root) return; + clear(ctx, layer); + + colorCycle = 0; + + // console.log(totalDur); + if (doUpdate) + { + doUpdate = false; + totalDur = inObj.get().root.dur; + root = inObj.get().root; + // console.log(root); + } + + drawBranch(ctx, layer, root, 0, 0); +}; + + +}; + +Ops.Dev.VizBranchProfiler.prototype = new CABLES.Op(); +CABLES.OPS["236fb6ea-4e98-4039-b831-98dc2ff2844b"]={f:Ops.Dev.VizBranchProfiler,objName:"Ops.Dev.VizBranchProfiler"}; + + + + +// ************************************************************** +// +// Ops.Dev.WebGpu.Computetest +// +// ************************************************************** + +Ops.Dev.WebGpu.Computetest = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"compute_wgsl":"// struct Matrix {\n// size : vec2,\n// numbers: array,\n// }\n\n@group(0) @binding(0) var resultMatrix : array;\n\n@compute @workgroup_size(50,1)\nfn main(@builtin(global_invocation_id) global_id : vec3)\n{\n // Guard against out-of-bounds work group sizes\n // if (global_id.x >= u32(firstMatrix.size.x) || global_id.y >= u32(secondMatrix.size.y))\n // return;\n // }\n\n // resultMatrix.size = vec2(firstMatrix.size.x, secondMatrix.size.y);\n\n // let resultCell = vec2(global_id.x, global_id.y);\n // var result = 0.0;\n // for (var i = 0u; i < u32(firstMatrix.size.y); i = i + 1u) {\n // let a = i + resultCell.x * u32(firstMatrix.size.y);\n // let b = resultCell.y + i * u32(secondMatrix.size.y);\n // result = result + firstMatrix.numbers[a] * secondMatrix.numbers[b];\n // }\n\n // let index = resultCell.y + resultCell.x * u32(secondMatrix.size.y);\n // resultMatrix.numbers[index] = result;\n\n resultMatrix[global_id.x] = f32(global_id.x);\n}",}; +const + compute=op.inTrigger("Computer"), + next=op.outTrigger("Next"); + +let comp=null; +compute.onTriggered=()=> +{ + if(!comp) + { + comp=new CABLES.CGP.GpuCompute(op.patch.cg,"c0mput",attachments.compute_wgsl); + + comp.compute(); + } + +} + +}; + +Ops.Dev.WebGpu.Computetest.prototype = new CABLES.Op(); +CABLES.OPS["7f179cc1-a1bd-4989-9fe2-6b6f8a95a6d7"]={f:Ops.Dev.WebGpu.Computetest,objName:"Ops.Dev.WebGpu.Computetest"}; + + + + +// ************************************************************** +// +// Ops.Dev.WebGpu.WebGpuCanvas +// +// ************************************************************** + +Ops.Dev.WebGpu.WebGpuCanvas = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"tri_wgsl_frag":"@fragment\n\nfn main() -> @location(0) vec4\n{\n return vec4(1.0, 0.0, 0.0, 1.0);\n}","tri_wgsl_vert":"@vertex\n\nfn main(@builtin(vertex_index) VertexIndex : u32)\n -> @builtin(position) vec4\n {\n var pos = array, 3>(\n vec2(0.0, 0.5),\n vec2(-0.5, -0.5),\n vec2(0.5, -0.5));\n\n return vec4(pos[VertexIndex], 0.0, 1.0);\n}\n",}; +const + next = op.outTrigger("Next"), + supported = op.outBoolNum("Supported", false), + outLimits = op.outObject("Limits"); + +let device = null; +let context = null, pipeline = null; + +const canvas = document.createElement("canvas"); +canvas.id = "webgpucanvas"; +canvas.setAttribute("tabindex", 4); +canvas.style.width = 128 + "px"; +canvas.style.height = 128 + "px"; +canvas.style.right = 0 + "px"; +canvas.style["z-index"] = "22222"; +canvas.style.border = "1px solid red"; +canvas.style.position = "absolute"; + +const container = document.getElementById("cablescanvas"); +container.appendChild(canvas); + +// canvas.addEventListener("blur", () => { if (supported.get())canvas.style.border = "1px solid black"; }); +// canvas.addEventListener("focus", () => { if (supported.get())canvas.style.border = "1px solid white"; }); + +const pm = mat4.create(); + +let renderTarget = null; +let depthTexture = null; +let canvasInfo = {}; + +let sizeWidth = 0; +let sizeHeight = 0; + +op.patch.cgp = op.patch.cgp || new CABLES.CGP.Context(op.patch); +const cgp = op.patch.cgp; +const sampleCount = 1; + +cgp.canvas = canvas; + +if (CABLES.UI) +{ + gui.canvasManager.addContext(cgp); + // setTimeout(() => + // { + // gui.emitEvent("resizecanvas"); + // gui.setLayout(); + // }, 200); +} + +let stopped = false; +op.onDelete = () => +{ + stopped = true; + canvas.remove(); + device = + op.patch.cgp.device = + op.patch.cgp.adapter = + op.patch.cgp.pipeline = null; +}; + +if (!navigator.gpu) +{ + const warn = "Your browser does not support webGPU"; + op.setUiError("nowebgpu", warn); + console.log(warn); +} + +if (navigator.gpu) + navigator.gpu.requestAdapter().then((adapter) => + { + if (!adapter) + { + op.warn("webgpu: could not get adapter..."); + supported.set(false); + return; + } + adapter.requestDevice().then((_device) => + { + canvas.style.border = "1px solid black"; + + cgp.setCanvas(canvas); + cgp.setSize(container.clientWidth, container.clientHeight); + + supported.set(true); + device = _device; + + // + + const limits = {}; + for (let i in device.limits) limits[i] = device.limits[i]; + outLimits.set(limits); + + // + + cgp.device = device; + cgp.adapter = adapter; + cgp.canvas = canvas; + + console.log(adapter); + console.log(device); + + context = canvas.getContext("webgpu"); + cgp.context = context; + + createTargets(cgp); + // pipeline = device.createRenderPipeline({ + // "layout": "auto", + // "vertex": + // { + // "module": device.createShaderModule( + // { + // "code": attachments.tri_wgsl_vert, + // }), + // "entryPoint": "main", + // }, + // "fragment": + // { + // "module": device.createShaderModule( + // { + // "code": attachments.tri_wgsl_frag, + // }), + // "entryPoint": "main", + // "targets": + // [ + // { + // "format": presentationFormat, + // }, + // ], + // }, + // "primitive": { + // "topology": "triangle-list", + // }, + // }); + // cgp.pipeline = pipeline; + + // canvasInfo.depthTextureView = depthTexture.createView(); + cgp.canvasInfo = canvasInfo; + + requestAnimationFrame(frame); + }); + }); + +function createTargets(cgp) +{ + const devicePixelRatio = 1;// window.devicePixelRatio || 1; + + sizeWidth = canvas.clientWidth * devicePixelRatio; + sizeHeight = canvas.clientHeight * devicePixelRatio; + + cgp.setSize(sizeWidth, sizeHeight); + + console.log("re create targets"); + // const presentationSize = [ + // canvas.clientWidth * devicePixelRatio, + // canvas.clientHeight * devicePixelRatio, + // ]; + + console.log("presentationSize", sizeWidth, sizeHeight); + const presentationFormat = navigator.gpu.getPreferredCanvasFormat(cgp.adapter); + cgp.presentationFormat = presentationFormat; + + context.configure({ + device, + "format": presentationFormat + }); + + if (renderTarget)renderTarget.destroy(); + if (depthTexture)depthTexture.destroy(); + + renderTarget = device.createTexture( + { + "size": [sizeWidth, sizeHeight], + "format": presentationFormat, + "sampleCount": sampleCount, + "usage": GPUTextureUsage.RENDER_ATTACHMENT, + }); + // canvasInfo.renderTarget = newRenderTarget; + // canvasInfo.renderTargetView = newRenderTarget.createView(); + // }); + + depthTexture = device.createTexture({ + "size": [sizeWidth, sizeHeight], + "format": "depth24plus", + "sampleCount": sampleCount, + "usage": GPUTextureUsage.RENDER_ATTACHMENT, + }); +} + +function frame() +{ + if (stopped) return; + if (!device) + { + requestAnimationFrame(frame); + + return; + } + + const devicePixelRatio = 1;// window.devicePixelRatio || 1; + if (sizeWidth != canvas.clientWidth * devicePixelRatio || sizeHeight != canvas.clientHeight * devicePixelRatio) + { + createTargets(cgp); + } + + // mat4.perspective(cgp.pMatrix, 45, canvas.clientWidth / canvas.clientHeight, 0.1, 1110.0); + // mat4.copy(cgp.pMatrix, pm); + + const commandEncoder = device.createCommandEncoder(); + + cgp.textureView = renderTarget.createView(); + cgp.canvasInfo.depthTextureView = depthTexture.createView(); + + // cgp.textureView = textureView; + const renderPassDescriptor = { + "colorAttachments": [ + { + "view": context.getCurrentTexture().createView(), + "loadOp": "clear", + // "resolveTarget": context.getCurrentTexture().createView(), + // "clearValue": { "r": 0.8, "g": 0.2, "b": 0.8, "a": 1.0 }, + "storeOp": "store", + }, + ], + "depthStencilAttachment": { + "view": cgp.canvasInfo.depthTextureView, + // "depthTexture": cgp.canvasInfo.depthTexture, + + "depthClearValue": 1, + "depthLoadOp": "clear", + "depthStoreOp": "store", + }, + }; + cgp.renderPassDescriptor = renderPassDescriptor; + cgp.passEncoder = commandEncoder.beginRenderPass(cgp.renderPassDescriptor); + + op.patch.cg = cgp; + // cgp.passEncoders = []; + cgp.renderStart(); + + const oldCgl = op.patch.cgl; + op.patch.cgl = null; // force crash if something tries to use it + next.trigger(); + + op.patch.cgl = oldCgl; + + cgp.renderEnd(); + + // for(let i=0;i,\n viewMatrix: mat4x4,\n projMatrix: mat4x4,\n};\n\nstruct FSUniforms\n{\n color:vec3//,\n // lightDirection: vec3,\n};\n\n@group(0) @binding(0) var vsUniforms: VSUniforms;\n@group(0) @binding(1) var fsUniforms: FSUniforms;\n\n\n\nstruct MyVSInput\n{\n @location(0) position: vec3,\n @location(1) normal: vec3,\n @location(2) texcoord: vec2,\n};\n\nstruct MyVSOutput\n{\n @builtin(position) position: vec4,\n @location(0) normal: vec3,\n @location(1) texcoord: vec2,\n};\n\n@vertex\nfn myVSMain(v: MyVSInput) -> MyVSOutput\n{\n var vsOut: MyVSOutput;\n var pos =vec4(v.position, 1.0);// vsUniforms.worldViewProjection * v.position;\n // vsOut.normal = (vsUniforms.worldInverseTranspose * vec4(v.normal, 0.0)).xyz;\n\n var mvMatrix=vsUniforms.viewMatrix * vsUniforms.modelMatrix;\n vsOut.position = vsUniforms.projMatrix * mvMatrix * pos;\n\n vsOut.normal = v.normal;\n vsOut.texcoord = v.texcoord;\n return vsOut;\n}\n\n\n\n\n\n// @group(0) @binding(2) var diffuseSampler: sampler;\n// @group(0) @binding(3) var diffuseTexture: texture_2d;\n\n@fragment\nfn myFSMain(v: MyVSOutput) -> @location(0) vec4\n{\n // var diffuseColor = textureSample(diffuseTexture, diffuseSampler, v.texcoord);\n // var a_normal = normalize(v.normal);\n // var l = dot(a_normal, fsUniforms.lightDirection) * 0.5 + 0.5;\n // return vec4(diffuseColor.rgb * l, diffuseColor.a);\n // return vec4(fsUniforms.color, 1.0);\n return vec4(v.normal.xyz+fsUniforms.color*0.001 , 1.0);\n}\n\n",}; +// !! https://alain.xyz/blog/raw-webgpu +// https://github.com/gfxfundamentals/webgpufundamentals/blob/main/webgpu/webgpu-cube.html + +const + inTrigger = op.inTrigger("Render"), + inGeom = op.inObject("Geometry", null, "geometry"), + next = op.outTrigger("Next"); + +let cgp = op.patch.cgp; +let needsbuild = true; + +let bindGroup; +let positionBuffer; +let normalBuffer; +let texcoordBuffer; +let indicesBuffer; +let geom = null; +let pipeline; +let renderPassDescriptor; +let numIndices = 0; + +let depthTexture, depthTextureView; + +let vsUniformBuffer; +let fsUniformBuffer; +let vsUniformValues; +let fsUniformValues; +let matModel; +let matView; +let matProj; + +let mesh = null; +let shader = null; +let pipe = null; + +inTrigger.onTriggered = () => +{ + cgp = op.patch.cgp; + if (needsbuild)rebuild(); + + if (geom && cgp.renderPassDescriptor) + { + mat4.copy(matModel, cgp.mMatrix); + mat4.copy(matView, cgp.vMatrix); + mat4.copy(matProj, cgp.pMatrix); + + cgp.device.queue.writeBuffer( + vsUniformBuffer, + 0, + vsUniformValues.buffer, + vsUniformValues.byteOffset, + vsUniformValues.byteLength + ); + + // const colorTexture = cgp.context.getCurrentTexture(); + // renderPassDescriptor.colorAttachments[0].view = colorTexture.createView(); + + // const commandEncoder = cgp.device.createCommandEncoder(); + // const passEncoder = commandEncoder.beginRenderPass(cgp.renderPassDescriptor); + + // cgp.passEncoder.setPipeline(pipeline); + cgp.passEncoder.setPipeline(pipeline); + + cgp.passEncoder.setBindGroup(0, bindGroup); + cgp.passEncoder.setVertexBuffer(0, positionBuffer); + cgp.passEncoder.setVertexBuffer(1, normalBuffer); + cgp.passEncoder.setVertexBuffer(2, texcoordBuffer); + cgp.passEncoder.setIndexBuffer(indicesBuffer, "uint32"); + + cgp.passEncoder.drawIndexed(numIndices); + // else cgp.passEncoder.draw(geom.vertices.length ); + + // passEncoder.end(); + + // cgp.passEncoders.push(commandEncoder.finish()); + } + + cgp.pushShader(shader); + next.trigger(); + cgp.popShader(); +}; + +inGeom.onChange = () => +{ + needsbuild = true; +}; + +// @group(0) @binding(2) var diffuseSampler: sampler; +// @group(0) @binding(3) var diffuseTexture: texture_2d; + +function createShaderModule(device, code) +{ + cgp.pushErrorScope("validation"); + + const shaderModule = device.createShaderModule({ code }); + // const error = await device.popErrorScope(); + // if (error) { + // throw new Error(error.message); + // } + + cgp.popErrorScope("cgp_pipeline createshadermodule"); + + return shaderModule; +} + +function createBuffer(device, data, usage) +{ + const buffer = device.createBuffer({ + "size": data.byteLength, + "usage": usage, + "mappedAtCreation": true, + }); + const dst = new data.constructor(buffer.getMappedRange()); + dst.set(data); + buffer.unmap(); + return buffer; +} + +function rebuild() +{ + geom = inGeom.get(); + if (!geom) return; + + positionBuffer = createBuffer(cgp.device, new Float32Array(geom.vertices), GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST); + normalBuffer = createBuffer(cgp.device, new Float32Array(geom.vertexNormals), GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST); + texcoordBuffer = createBuffer(cgp.device, new Float32Array(geom.texcoords), GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST); + + let vi = geom.verticesIndices; + if (!geom.isIndexed()) + { + vi = Array.from(Array(geom.vertices.length / 3).keys()); + } + + numIndices = vi.length; + indicesBuffer = createBuffer(cgp.device, new Uint32Array(vi), GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST); + + if (!shader)shader = new CGP.Shader(cgp, "testshad0r"); + + shader.shaderModule = createShaderModule(cgp.device, attachments.mesh_wgsl); + + cgp.pushErrorScope(); + + if (!pipe)pipe = new CGP.Pipeline(cgp); + + const pipeCfg = pipe.getPiplelineObject(shader, mesh); + console.log(pipeCfg); + pipeline = cgp.device.createRenderPipeline(pipeCfg); + + cgp.popErrorScope(op.name); + + const vUniformBufferSize = 3 * 16 * 4; // 2 mat4s * 16 floats per mat * 4 bytes per float + const fUniformBufferSize = 2 * 3 * 4; // 1 vec3 * 3 floats per vec3 * 4 bytes per float + + vsUniformBuffer = cgp.device.createBuffer({ + "size": vUniformBufferSize, + "usage": GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, + }); + + fsUniformBuffer = cgp.device.createBuffer({ + "size": fUniformBufferSize, + "usage": GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, + }); + + vsUniformValues = new Float32Array(vUniformBufferSize / 4); + fsUniformValues = new Float32Array(fUniformBufferSize / 4); + + matModel = vsUniformValues.subarray(0, 16); + matView = vsUniformValues.subarray(16, 32); + matProj = vsUniformValues.subarray(32, 48); + + fsUniformValues[1] = 1.0; + fsUniformValues[0] = 1.0; + const lightDirection = fsUniformValues.subarray(0, 3); + + // console.log("pipeline bindgrouplayout ", pipeline.getBindGroupLayout(0)); + + bindGroup = cgp.device.createBindGroup( + { + "layout": pipeline.getBindGroupLayout(0), + "entries": [ + { "binding": 0, "resource": { "buffer": vsUniformBuffer } }, + { "binding": 1, "resource": { "buffer": fsUniformBuffer } } + // { binding: 2, resource: sampler }, + // { binding: 3, resource: tex.createView() }, + ], + }); + + cgp.device.queue.writeBuffer( + vsUniformBuffer, + 0, + vsUniformValues.buffer, + vsUniformValues.byteOffset, + vsUniformValues.byteLength + ); + cgp.device.queue.writeBuffer( + fsUniformBuffer, + 0, + fsUniformValues.buffer, + fsUniformValues.byteOffset, + fsUniformValues.byteLength + ); + + const textureView = cgp.context.getCurrentTexture().createView(); + + needsbuild = false; +} + + +}; + +Ops.Dev.WebGpu.WebGpuMesh.prototype = new CABLES.Op(); +CABLES.OPS["daf22c14-6ba3-4c63-83d2-27e9e60d3dbf"]={f:Ops.Dev.WebGpu.WebGpuMesh,objName:"Ops.Dev.WebGpu.WebGpuMesh"}; + + + + +// ************************************************************** +// +// Ops.Dev.WebGpu.WebGpuMinimalMaterial +// +// ************************************************************** + +Ops.Dev.WebGpu.WebGpuMinimalMaterial = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"mat_wgsl":"struct VSUniforms\n{\n modelMatrix: mat4x4,\n viewMatrix: mat4x4,\n projMatrix: mat4x4,\n};\n\nstruct FSUniforms\n{\n color:vec4\n};\n\n@group(0) @binding(0) var vsUniforms: VSUniforms;\n@group(0) @binding(1) var fsUniforms: FSUniforms;\n\nstruct MyVSInput\n{\n @location(0) position: vec3,\n @location(1) normal: vec3,\n @location(2) texcoord: vec2,\n};\n\nstruct MyVSOutput\n{\n @builtin(position) position: vec4,\n @location(0) normal: vec3,\n @location(1) texcoord: vec2,\n};\n\n@vertex\nfn myVSMain(v: MyVSInput) -> MyVSOutput\n{\n var vsOut: MyVSOutput;\n var pos =vec4(v.position, 1.0);\n\n var mvMatrix=vsUniforms.viewMatrix * vsUniforms.modelMatrix;\n vsOut.position = vsUniforms.projMatrix * mvMatrix * pos;\n\n vsOut.normal = v.normal;\n vsOut.texcoord = v.texcoord;\n return vsOut;\n}\n\n@fragment\nfn myFSMain(v: MyVSOutput) -> @location(0) vec4\n{\n return fsUniforms.color;\n}\n\n",}; +const + inTrigger = op.inTrigger("Render"), + r = op.inValueSlider("r", Math.random()), + g = op.inValueSlider("g", Math.random()), + b = op.inValueSlider("b", Math.random()), + a = op.inValueSlider("a", 1), + next = op.outTrigger("Next"); + +r.setUiAttribs({ "colorPick": true }); + +let shader = null; + +inTrigger.onTriggered = () => +{ + const cgp = op.patch.cg; + if (!shader) + { + shader = new CGP.Shader(cgp, op.name); + shader.setSource(attachments.mat_wgsl); + + shader.addUniformFrag("4f", "color", r, g, b, a); + } + + cgp.pushShader(shader); + + next.trigger(); + + cgp.popShader(shader); +}; + + +}; + +Ops.Dev.WebGpu.WebGpuMinimalMaterial.prototype = new CABLES.Op(); +CABLES.OPS["681ffbbf-cdf4-4d4f-ad7c-934b3a601a80"]={f:Ops.Dev.WebGpu.WebGpuMinimalMaterial,objName:"Ops.Dev.WebGpu.WebGpuMinimalMaterial"}; + + + + +// ************************************************************** +// +// Ops.Dev.WebGpu.WebGpuTexture +// +// ************************************************************** + +Ops.Dev.WebGpu.WebGpuTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + trigger = op.inTrigger("trigger"), + filename = op.inUrl("File", [".jpg", ".png", ".webp", ".jpeg", ".avif"]), + result = op.outTexture("Texture"); + +let needsReload = false; + +filename.onChange = () => +{ + needsReload = true; +}; + +trigger.onTriggered = () => +{ + if (needsReload) + { + needsReload = false; + + CGP.Texture.load(op.patch.cgp, filename.get(), (t) => + { + result.set(t); + }); + } +}; + + +}; + +Ops.Dev.WebGpu.WebGpuTexture.prototype = new CABLES.Op(); +CABLES.OPS["3a952a05-8b7b-4dab-9c08-f2c00f6cd899"]={f:Ops.Dev.WebGpu.WebGpuTexture,objName:"Ops.Dev.WebGpu.WebGpuTexture"}; + + + + +// ************************************************************** +// +// Ops.Device.Mobile.ShakeGesture +// +// ************************************************************** + +Ops.Device.Mobile.ShakeGesture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + accX = op.outNumber("Acceleration X"), + accY = op.outNumber("Acceleration Y"), + accZ = op.outNumber("Acceleration Z"); + +let lastTime = 0; +let lastTimeAcc = 0; + +let obj = {}; + +registerEvents(); + +let lastX = 0; +let lastY = 0; +let lastZ = 0; + +function moved(event) +{ + if (CABLES.now() - lastTimeAcc > 30) + { + lastTimeAcc = CABLES.now(); + + let deltaX = lastX - event.accelerationIncludingGravity.x; + let deltaY = lastY - event.accelerationIncludingGravity.y; + let deltaZ = lastZ - event.accelerationIncludingGravity.z; + + accX.set(Math.abs(deltaX)); + accY.set(Math.abs(deltaY)); + accZ.set(Math.abs(deltaZ)); + + lastX = event.accelerationIncludingGravity.x; + lastY = event.accelerationIncludingGravity.y; + lastZ = event.accelerationIncludingGravity.z; + } +} + +function registerEvents() +{ + window.addEventListener("devicemotion", moved, true); +} + +op.onDelete = function () +{ + window.removeEventListener("devicemotion", moved); +}; + + +}; + +Ops.Device.Mobile.ShakeGesture.prototype = new CABLES.Op(); +CABLES.OPS["7b32f8ad-ff4a-4634-927b-ede9955e3b53"]={f:Ops.Device.Mobile.ShakeGesture,objName:"Ops.Device.Mobile.ShakeGesture"}; + + + + +// ************************************************************** +// +// Ops.Devices.GamePad.GamePad +// +// ************************************************************** + +Ops.Devices.GamePad.GamePad = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let data = op.inObject("GamePad Data"); +let outID = op.outString("ID"); +let digitalAnalog = op.inValueBool("Analog to Digital", true); +let outAxes = op.outArray("Axes"); + +let pressedLeft = op.outBoolNum("Pad Left"); +let pressedRight = op.outBoolNum("Pad Right"); +let pressedUp = op.outBoolNum("Pad Up"); +let pressedDown = op.outBoolNum("Pad Down"); + +let pressedButton1 = op.outBoolNum("Button 1"); +let pressedButton2 = op.outBoolNum("Button 2"); +let pressedButton3 = op.outBoolNum("Button 3"); +let pressedButton4 = op.outBoolNum("Button 4"); + +let outLeftShoulder = op.outNumber("Left Shoulder"); +let outLeftShoulderBottom = op.outNumber("Left Shoulder Bottom"); + +let outRightShoulder = op.outNumber("Right Shoulder"); +let outRightShoulderBottom = op.outNumber("Right Shoulder Bottom"); + +data.onChange = function () +{ + if (data.get()) + { + outID.set(data.get().id); + if (data.get().axes)outAxes.set(data.get().axes); + + let buttons = data.get().buttons; + if (buttons) + { + pressedButton1.set(buttons[0].pressed); + pressedButton2.set(buttons[1].pressed); + pressedButton3.set(buttons[2].pressed); + pressedButton4.set(buttons[3].pressed); + } + + if (digitalAnalog.get()) + { + let axes = data.get().axes; + if (axes) + { + if (axes[0] < -0.5)pressedLeft.set(true); + else pressedLeft.set(false || buttons[14].pressed); + if (axes[0] > 0.5)pressedRight.set(true); + else pressedRight.set(false || buttons[15].pressed); + + if (axes[1] < -0.5)pressedUp.set(true); + else pressedUp.set(false || buttons[12].pressed); + if (axes[1] > 0.5)pressedDown.set(true); + else pressedDown.set(false || buttons[13].pressed); + } + } + else + { + pressedLeft.set(buttons[14].pressed); + pressedRight.set(buttons[15].pressed); + pressedDown.set(buttons[13].pressed); + pressedUp.set(buttons[12].pressed); + } + + outLeftShoulder.set(buttons[4].value); + outLeftShoulderBottom.set(buttons[6].value); + + outRightShoulder.set(buttons[5].value); + outRightShoulderBottom.set(buttons[7].value); + } +}; + +// gamepad.BUTTONS = { +// FACE_1: 0, // Face (main) buttons +// FACE_2: 1, +// FACE_3: 2, +// FACE_4: 3, +// LEFT_SHOULDER: 4, // Top shoulder buttons +// RIGHT_SHOULDER: 5, +// LEFT_SHOULDER_BOTTOM: 6, // Bottom shoulder buttons +// RIGHT_SHOULDER_BOTTOM: 7, +// SELECT: 8, +// START: 9, +// LEFT_ANALOGUE_STICK: 10, // Analogue sticks (if depressible) +// RIGHT_ANALOGUE_STICK: 11, +// PAD_TOP: 12, // Directional (discrete) pad +// PAD_BOTTOM: 13, +// PAD_LEFT: 14, +// PAD_RIGHT: 15 +// }; + +// gamepad.AXES = { +// LEFT_ANALOGUE_HOR: 0, +// LEFT_ANALOGUE_VERT: 1, +// RIGHT_ANALOGUE_HOR: 2, +// RIGHT_ANALOGUE_VERT: 3 +// }; + + +}; + +Ops.Devices.GamePad.GamePad.prototype = new CABLES.Op(); +CABLES.OPS["3acf39ed-53cc-45eb-8516-43319839d457"]={f:Ops.Devices.GamePad.GamePad,objName:"Ops.Devices.GamePad.GamePad"}; + + + + +// ************************************************************** +// +// Ops.Devices.GamePad.GamePadJoystickAxis +// +// ************************************************************** + +Ops.Devices.GamePad.GamePadJoystickAxis = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inAxis = op.inArray("Axis"), + inAxisNum = op.inValueInt("Index"), + outX = op.outNumber("X"), + outY = op.outNumber("Y"), + inDeadZone = op.outNumber("DeadZone", 0.1), + outAngle = op.outNumber("Angle"); + +inAxis.onChange = function () +{ + let arr = inAxis.get(); + if (!arr) return; + + let idx = inAxisNum.get() * 2; + + let x = 0; + let y = 0; + + if (arr[idx + 0] > 0)x = CABLES.map(arr[idx + 0], inDeadZone.get(), 1, 0, 1); + else x = CABLES.map(arr[idx + 0], -1, -inDeadZone.get(), -1, 0); + + if (arr[idx + 1] > 0)y = CABLES.map(arr[idx + 1], inDeadZone.get(), 1, 0, 1); + else y = CABLES.map(arr[idx + 1], -1, -inDeadZone.get(), -1, 0); + + outX.set(x); + outY.set(y); + + if (x != 0 || y != 0) + { + let theta = Math.atan2(x, y); + + let angle = theta * 180 / Math.PI * -1; + outAngle.set(360 - (angle + 180)); + } +}; + + +}; + +Ops.Devices.GamePad.GamePadJoystickAxis.prototype = new CABLES.Op(); +CABLES.OPS["05be9e0d-c6bd-42f6-9f2c-16ae5ad4db7a"]={f:Ops.Devices.GamePad.GamePadJoystickAxis,objName:"Ops.Devices.GamePad.GamePadJoystickAxis"}; + + + + +// ************************************************************** +// +// Ops.Devices.GamePad.GamePads +// +// ************************************************************** + +Ops.Devices.GamePad.GamePads = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + outNumPads = op.outNumber("Num Gamepads"), + pad0 = op.outObject("Pad 0"), + pad1 = op.outObject("Pad 1"), + pad2 = op.outObject("Pad 2"), + pad3 = op.outObject("Pad 3"); + +exe.onTriggered = function () +{ + let gamePads = navigator.getGamepads(); + let count = 0; + + for (let gp = 0; gp < gamePads.length; gp++) + { + if (gamePads[gp]) + { + count++; + + if (gp == 0) + { + pad0.set(null); + pad0.set(gamePads[gp]); + } + if (gp == 1) + { + pad1.set(null); + pad1.set(gamePads[gp]); + } + if (gp == 2) + { + pad2.set(null); + pad2.set(gamePads[gp]); + } + if (gp == 3) + { + pad3.set(null); + pad3.set(gamePads[gp]); + } + } + } + + outNumPads.set(count); +}; + +exe.onTriggered(); + + +}; + +Ops.Devices.GamePad.GamePads.prototype = new CABLES.Op(); +CABLES.OPS["76b42a0b-21a4-4eef-b20c-5a969a2189f0"]={f:Ops.Devices.GamePad.GamePads,objName:"Ops.Devices.GamePad.GamePads"}; + + + + +// ************************************************************** +// +// Ops.Devices.Keyboard.CursorKeys +// +// ************************************************************** + +Ops.Devices.Keyboard.CursorKeys = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + canvasOnly = op.inValueBool("canvas only", true), + keysCursor = op.inValueBool("Cursor Keys", true), + keysWasd = op.inValueBool("WASD", true), + inActive = op.inBool("Active", true), + pressedUp = op.outBoolNum("Up"), + pressedDown = op.outBoolNum("Down"), + pressedLeft = op.outBoolNum("Left"), + pressedRight = op.outBoolNum("Right"); + +const cgl = op.patch.cgl; + +function onKeyDown(e) +{ + if (keysWasd.get()) + { + if (e.keyCode == 87) pressedUp.set(true); + if (e.keyCode == 83) pressedDown.set(true); + if (e.keyCode == 65) pressedLeft.set(true); + if (e.keyCode == 68) pressedRight.set(true); + } + if (keysCursor.get()) + { + if (e.keyCode == 38) pressedUp.set(true); + if (e.keyCode == 40) pressedDown.set(true); + if (e.keyCode == 37) pressedLeft.set(true); + if (e.keyCode == 39) pressedRight.set(true); + } +} + +function onKeyUp(e) +{ + if (keysWasd.get()) + { + if (e.keyCode == 87) pressedUp.set(false); + if (e.keyCode == 83) pressedDown.set(false); + if (e.keyCode == 65) pressedLeft.set(false); + if (e.keyCode == 68) pressedRight.set(false); + } + if (keysCursor.get()) + { + if (e.keyCode == 38) pressedUp.set(false); + if (e.keyCode == 40) pressedDown.set(false); + if (e.keyCode == 37) pressedLeft.set(false); + if (e.keyCode == 39) pressedRight.set(false); + } +} + +op.onDelete = function () +{ + cgl.canvas.removeEventListener("keyup", onKeyUp, false); + cgl.canvas.removeEventListener("keydown", onKeyDown, false); + document.removeEventListener("keyup", onKeyUp, false); + document.removeEventListener("keydown", onKeyDown, false); +}; + +function addListener() +{ + if (canvasOnly.get()) addCanvasListener(); + else addDocumentListener(); +} + +function onBlur() +{ + pressedUp.set(false); + pressedDown.set(false); + pressedLeft.set(false); + pressedRight.set(false); +} + +inActive.onChange = () => +{ + pressedUp.set(false); + pressedDown.set(false); + pressedLeft.set(false); + pressedRight.set(false); +}; + +function removeListeners() +{ + cgl.canvas.removeEventListener("blur", onBlur); + document.removeEventListener("keydown", onKeyDown, false); + document.removeEventListener("keyup", onKeyUp, false); + cgl.canvas.removeEventListener("keydown", onKeyDown, false); + cgl.canvas.removeEventListener("keyup", onKeyUp, false); +} + +function addCanvasListener() +{ + cgl.canvas.addEventListener("blur", onBlur); + + cgl.canvas.addEventListener("keydown", onKeyDown, false); + cgl.canvas.addEventListener("keyup", onKeyUp, false); +} + +function addDocumentListener() +{ + document.addEventListener("keydown", onKeyDown, false); + document.addEventListener("keyup", onKeyUp, false); +} + +canvasOnly.onChange = function () +{ + removeListeners(); + addListener(); +}; + +canvasOnly.set(true); +addCanvasListener(); + + +}; + +Ops.Devices.Keyboard.CursorKeys.prototype = new CABLES.Op(); +CABLES.OPS["65930ca9-c923-453f-b8c4-144eda13fa0a"]={f:Ops.Devices.Keyboard.CursorKeys,objName:"Ops.Devices.Keyboard.CursorKeys"}; + + + + +// ************************************************************** +// +// Ops.Devices.Keyboard.KeyPressLearn +// +// ************************************************************** + +Ops.Devices.Keyboard.KeyPressLearn = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const learnedKeyCode = op.inValueInt("key code"); +const canvasOnly = op.inValueBool("canvas only", true); +const modKey = op.inValueSelect("Mod Key", ["none", "alt"], "none"); +const inEnable = op.inValueBool("Enabled", true); +const preventDefault = op.inValueBool("Prevent Default"); +const learn = op.inTriggerButton("learn"); +const onPress = op.outTrigger("on press"); +const onRelease = op.outTrigger("on release"); +const outPressed = op.outBoolNum("Pressed", false); +const outKey = op.outString("Key"); + +const cgl = op.patch.cgl; +let learning = false; + +modKey.onChange = learnedKeyCode.onChange = updateKeyName; + +function onKeyDown(e) +{ + if (learning) + { + learnedKeyCode.set(e.keyCode); + if (CABLES.UI) + { + op.refreshParams(); + } + // op.log("Learned key code: " + learnedKeyCode.get()); + learning = false; + removeListeners(); + addListener(); + + if (CABLES.UI)gui.emitEvent("portValueEdited", op, learnedKeyCode, learnedKeyCode.get()); + } + else + { + if (e.keyCode == learnedKeyCode.get()) + { + if (modKey.get() == "alt") + { + if (e.altKey === true) + { + onPress.trigger(); + outPressed.set(true); + if (preventDefault.get())e.preventDefault(); + } + } + else + { + onPress.trigger(); + outPressed.set(true); + if (preventDefault.get())e.preventDefault(); + } + } + } +} + +function onKeyUp(e) +{ + if (e.keyCode == learnedKeyCode.get()) + { + // op.log("Key released, key code: " + e.keyCode); + onRelease.trigger(); + outPressed.set(false); + } +} + +op.onDelete = function () +{ + cgl.canvas.removeEventListener("keyup", onKeyUp, false); + cgl.canvas.removeEventListener("keydown", onKeyDown, false); + document.removeEventListener("keyup", onKeyUp, false); + document.removeEventListener("keydown", onKeyDown, false); +}; + +learn.onTriggered = function () +{ + // op.log("Listening for key..."); + learning = true; + addDocumentListener(); + + setTimeout(function () + { + learning = false; + removeListeners(); + addListener(); + }, 3000); +}; + +function addListener() +{ + if (canvasOnly.get()) addCanvasListener(); + else addDocumentListener(); +} + +function removeListeners() +{ + document.removeEventListener("keydown", onKeyDown, false); + document.removeEventListener("keyup", onKeyUp, false); + cgl.canvas.removeEventListener("keydown", onKeyDown, false); + cgl.canvas.removeEventListener("keyup", onKeyUp, false); + outPressed.set(false); +} + +function addCanvasListener() +{ + cgl.canvas.addEventListener("keydown", onKeyDown, false); + cgl.canvas.addEventListener("keyup", onKeyUp, false); +} + +function addDocumentListener() +{ + document.addEventListener("keydown", onKeyDown, false); + document.addEventListener("keyup", onKeyUp, false); +} + +inEnable.onChange = function () +{ + if (!inEnable.get()) + { + removeListeners(); + } + else + { + addListener(); + } +}; + +canvasOnly.onChange = function () +{ + removeListeners(); + addListener(); +}; + +function updateKeyName() +{ + let keyName = CABLES.keyCodeToName(learnedKeyCode.get()); + const modKeyName = modKey.get(); + if (modKeyName && modKeyName !== "none") + { + keyName = modKeyName.charAt(0).toUpperCase() + modKeyName.slice(1) + "-" + keyName; + } + op.setUiAttribs({ "extendTitle": keyName }); + outKey.set(keyName); +} + +addCanvasListener(); + + +}; + +Ops.Devices.Keyboard.KeyPressLearn.prototype = new CABLES.Op(); +CABLES.OPS["f069c0db-4051-4eae-989e-6ef7953787fd"]={f:Ops.Devices.Keyboard.KeyPressLearn,objName:"Ops.Devices.Keyboard.KeyPressLearn"}; + + + + +// ************************************************************** +// +// Ops.Devices.Keyboard.KeyPress_v2 +// +// ************************************************************** + +Ops.Devices.Keyboard.KeyPress_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inArea = op.inValueSelect("Area", ["Canvas", "Document", "Parent Element"], "Canvas"); +const preventDefault = op.inBool("Prevent Default", false); +const inEnable = op.inBool("Enabled", true); +const onPress = op.outTrigger("On Press"); +const keyCode = op.outNumber("Key Code"); +const outKey = op.outString("Key"); + +const cgl = op.patch.cgl; +let listenerElement = null; + +inArea.onChange = inEnable.onChange = () => +{ + if (inEnable.get()) + { + addListeners(); + } + else + { + removeListeners(); + } +}; + +op.onDelete = () => +{ + removeListeners(); +}; + +function onKeyPress(e) +{ + const keyName = CABLES.keyCodeToName(e.keyCode); + op.setUiAttribs({ "extendTitle": keyName }); + outKey.set(keyName); + keyCode.set(e.keyCode); + onPress.trigger(); + if (preventDefault.get()) e.preventDefault(); +} + +function addListeners() +{ + if (listenerElement) removeListeners(); + + listenerElement = cgl.canvas; + if (inArea.get() === "Document") listenerElement = document.body; + if (inArea.get() === "Parent Element") listenerElement = cgl.canvas.parentElement; + + listenerElement.addEventListener("keydown", onKeyPress); +} + +function removeListeners() +{ + if (!listenerElement) return; + listenerElement.removeEventListener("keydown", onKeyPress); + listenerElement = null; +} + +addListeners(); + + +}; + +Ops.Devices.Keyboard.KeyPress_v2.prototype = new CABLES.Op(); +CABLES.OPS["023d1e35-1231-4c50-a044-4a0e63609ba5"]={f:Ops.Devices.Keyboard.KeyPress_v2,objName:"Ops.Devices.Keyboard.KeyPress_v2"}; + + + + +// ************************************************************** +// +// Ops.Devices.Keyboard.QWERTYtoMidi +// +// ************************************************************** + +Ops.Devices.Keyboard.QWERTYtoMidi = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let canvasOnly = op.addInPort(new CABLES.Port(op, "canvas only", CABLES.OP_PORT_TYPE_VALUE, { "display": "bool" })); + +let noteNumberPort = op.outValue("Note Number"); +let velocityPort = op.outValue("Velocity"); +let channelPort = op.outValue("Channel"); +let commandPort = op.outValue("Command"); + +let cgl = op.patch.cgl; + +function midiMessageReceived(msgs) +{ + for (let i = 0; i < msgs.length; i++) + { + let cmd = msgs[i].data[0] >> 4; + let channel = msgs[i].data[0] & 0xf; + let noteNumber = msgs[i].data[1]; + let velocity = msgs[i].data[2]; + + noteNumberPort.set(noteNumber); + velocityPort.set(velocity); + channelPort.set(channel); + commandPort.set(cmd); + + /* + if (cmd==8) { + //myNode.noteOff(0); + } else if (cmd == 9) { + //myNode.noteOn(0); + } + */ + } +} + +/* + * Midikeys.js + * > Turn your keyboard into a midi keyboard, compatible with the Web MIDI API. + * Copyright 2012 Nick Thompson + * MIT License + * https://gist.github.com/3995530 + */ + +// Keycode to MIDI note values +let map = {}; + +map[81] = 72; // q C5 +map[87] = 74; // w D5 +map[69] = 76; // e E5 +map[82] = 77; // r F5 +map[84] = 79; // t G5 +map[89] = 81; // y A5 +map[85] = 83; // u B5 +map[73] = 84; // i C6 +map[79] = 86; // o D6 +map[80] = 88; // p E6 +map[219] = 89; // [ F6 +map[221] = 91; // ] G6 + +map[83] = 61; // s C#4 +map[68] = 63; // d D#4 +map[71] = 66; // g F#4 +map[72] = 68; // h G#4 +map[74] = 70; // j A#4 +map[76] = 73; // l C#5 +map[186] = 75; // ; D#5 + +map[90] = 60; // z C4 +map[88] = 62; // x D4 +map[67] = 64; // c E4 +map[86] = 65; // v F4 +map[66] = 67; // b G4 +map[78] = 69; // n A4 +map[77] = 71; // m B4 +map[188] = 72; // , C5 +map[190] = 74; // . D5 +map[191] = 76; // / E5 + +// Keep track of keydown and keyup events so that the keydown event doesn't +// send messages repeatedly until keyup. +let flags = {}; + +function sendMessage(e, command) +{ + // Check the event key against the midi map. + let note = map[(typeof e.which === "number") ? e.which : e.keyCode]; + + // If the key doesn't exist in the midi map, or we're trying to send a + // noteOn event without having most recently sent a noteOff, end here. + if (note === undefined || (flags[note] && command === 0x9)) + { + return false; + } + + // Build the data + let data = new Uint8Array(3); + + data[0] = (command << 4) + 0x00; // Send the command on channel 0 + data[1] = note; // Attach the midi note + data[2] = 127; // Keyboard keys default to 127 velocity. + + // Package the message + let msg = { + "data": data, + "timestamp": 0 + }; + + // Send it + api.onmessage.call(window, [msg]); + + // Update the flag table + if (command === 0x9) + { + flags[note] = true; + } + else + { + flags[note] = false; + } +} + +// MIDIKeys api object, to be exposed as window.Keys +let api = { + + // Expose the onmessage parameter like on a MIDIInput object + "onmessage": null + +}; + +let MIDIKeys = api; + +// Including Midikeys.js in your project file packages fake MIDI messages the same as a normal message, +// so you can then just attach your message handler to MIDI keys and you're done + +MIDIKeys.onmessage = midiMessageReceived; + +function onKeyDown(e) +{ + sendMessage(e, 0x09); +} + +function onKeyUp(e) +{ + sendMessage(e, 0x08); +} + +function addListener() +{ + if (canvasOnly.get()) + { + addCanvasListener(); + } + else + { + addDocumentListener(); + } +} + +function removeListeners() +{ + document.removeEventListener("keydown", onKeyDown, false); + document.removeEventListener("keyup", onKeyUp, false); + cgl.canvas.removeEventListener("keydown", onKeyDown, false); + cgl.canvas.removeEventListener("keyup", onKeyUp, false); +} + +function addCanvasListener() +{ + cgl.canvas.addEventListener("keydown", onKeyDown, false); + cgl.canvas.addEventListener("keyup", onKeyUp, false); +} + +function addDocumentListener() +{ + document.addEventListener("keydown", onKeyDown, false); + document.addEventListener("keyup", onKeyUp, false); +} + +canvasOnly.onChange = function () +{ + removeListeners(); + addListener(); +}; + +canvasOnly.set(true); +addCanvasListener(); + + +}; + +Ops.Devices.Keyboard.QWERTYtoMidi.prototype = new CABLES.Op(); +CABLES.OPS["0aecef8b-3bcb-44ac-ae62-38ce8cd4051e"]={f:Ops.Devices.Keyboard.QWERTYtoMidi,objName:"Ops.Devices.Keyboard.QWERTYtoMidi"}; + + + + +// ************************************************************** +// +// Ops.Devices.Midi.DeviceList +// +// ************************************************************** + +Ops.Devices.Midi.DeviceList = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const outNumDevices = op.outValue("Num Devices"); +const outSupport = op.outValueBool("Midi Support"); +const outNames = op.outArray("Device Names"); + +let midi = null; + +function onMIDIFailure() +{ + outSupport.set(false); +} + +if (navigator.requestMIDIAccess) navigator.requestMIDIAccess({ "sysex": false }).then(onMIDISuccess, onMIDIFailure); +else onMIDIFailure(); + +function onMIDISuccess(midiAccess) +{ + let arr = []; + midi = midiAccess; + outSupport.set(true); + let inputs = midi.inputs.values(); + + let devices = []; + let numDevices = 0; + + for (let input = inputs.next(); input && !input.done; input = inputs.next()) + { + arr.push(input.value.name); + numDevices++; + } + + outNames.set(arr); + outNumDevices.set(numDevices); +} + + +}; + +Ops.Devices.Midi.DeviceList.prototype = new CABLES.Op(); +CABLES.OPS["6e52048f-557d-4332-9d5e-2201f728cb23"]={f:Ops.Devices.Midi.DeviceList,objName:"Ops.Devices.Midi.DeviceList"}; + + + + +// ************************************************************** +// +// Ops.Devices.Midi.MidiCC +// +// ************************************************************** + +Ops.Devices.Midi.MidiCC = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +/* UTIL */ +const MIDIChannels = Array.from(Array(16).keys(), (i) => { return i + 1; }); +/* IN */ +const inEvent = op.inObject("MIDI Event In"); +const midiChannelDropdown = op.inValueSelect("MIDI Channel", MIDIChannels, 1); +const ccIndexDropdown = op.inValueInt("CC Index", 0); +const normalizeDropdown = op.inSwitch("Normalize", ["none", "0 to 1", "-1 to 1"], "none"); +const learn = op.inTriggerButton("learn"); +const clear = op.inTriggerButton("clear"); + +op.setPortGroup("MIDI", [inEvent, midiChannelDropdown]); +op.setPortGroup("CC", [ccIndexDropdown, normalizeDropdown]); +op.setPortGroup("", [learn, clear]); + +const ccArray = Array.from(Array(128).keys(), (key) => { return 0; }); + +/* OUT */ +const eventOut = op.outObject("Event"); +const triggerOut = op.outTrigger("Trigger Out"); +const ccIndexOut = op.outNumber("CC Index Out"); +const ccValueOut = op.outNumber("CC Value Out"); +const arrayOut = op.outArray("Value Array"); + +op.setPortGroup("MIDI/Trigger Out", [eventOut, triggerOut]); +op.setPortGroup("CC Out", [ccIndexOut, ccValueOut]); + +arrayOut.set(ccArray); + +ccIndexDropdown.set(0); +midiChannelDropdown.set(1); +normalizeDropdown.set(normalizeDropdown.get("none")); + +let learning = false; +learn.onTriggered = () => +{ + learning = true; +}; + +clear.onTriggered = () => +{ + ccIndexDropdown.set(0); + midiChannelDropdown.set(1); + normalizeDropdown.set(normalizeDropdown.get("none")); + op.refreshParams(); +}; + +inEvent.onChange = () => +{ + const event = inEvent.get(); + if (!event) return; + if (event.messageType !== "CC") return; + + const [, ccIndex, ccValue] = event.data; + if (learning) + { + ccIndexDropdown.set(ccIndex); + midiChannelDropdown.set(event.channel + 1); + + learning = false; + + if (CABLES.UI) + { + gui.emitEvent("portValueEdited", op, ccIndexDropdown, ccIndexDropdown.get()); + gui.emitEvent("portValueEdited", op, midiChannelDropdown, midiChannelDropdown.get()); + + op.uiAttr({ "info": `bound to CC: ${ccIndexDropdown.get()}` }); + op.refreshParams(); + } + } + + if (event.channel === midiChannelDropdown.get() - 1) + { + if (normalizeDropdown.get() === "0 to 1") + { + ccArray[ccIndex] = ccValue / 127; + } + else if (normalizeDropdown.get() === "-1 to 1") + { + ccArray[ccIndex] = ccValue / (127 / 2) - 1; + } + else if (normalizeDropdown.get() === "none") + { + ccArray[ccIndex] = ccValue; + } + + if (ccIndex === ccIndexDropdown.get()) + { + ccIndexOut.set(ccIndex); + let value = ccValue; + ccArray[ccIndex] = ccValue; + if (normalizeDropdown.get() === "0 to 1") + { + value = ccValue / 127; + ccValueOut.set(value); + ccArray[ccIndex] = ccValue; + triggerOut.trigger(); + } + else if (normalizeDropdown.get() === "-1 to 1") + { + value = ccValue / (127 / 2) - 1; + triggerOut.trigger(); + ccValueOut.set(value); + ccArray[ccIndex] = ccValue; + } + else if (normalizeDropdown.get() === "none") + { + triggerOut.trigger(); + ccValueOut.set(value); + ccArray[ccIndex] = ccValue; + } + else + { + ccArray[ccIndex] = 0; + ccValue.set(0); + } + } + } + + arrayOut.set(null); + arrayOut.set(ccArray); + eventOut.set(null); + eventOut.set(event); +}; + + +}; + +Ops.Devices.Midi.MidiCC.prototype = new CABLES.Op(); +CABLES.OPS["28616ffc-a761-4792-9076-8625f9ccc965"]={f:Ops.Devices.Midi.MidiCC,objName:"Ops.Devices.Midi.MidiCC"}; + + + + +// ************************************************************** +// +// Ops.Devices.Midi.MidiCCOut +// +// ************************************************************** + +Ops.Devices.Midi.MidiCCOut = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const MIDIChannels = Array.from(Array(16).keys(), i => i + 1); +const clamp = (val, min, max) => Math.min(Math.max(val, min), max); +const CC_STATUS_BYTE = 0xb; + +const inChannel = op.inDropDown("MIDI Channel", MIDIChannels, "1"); +const inCcIndex = op.inInt("CC Index", 1); +const inCCValue = op.inInt("CC Value", 0); +const inMin = op.inFloat("Min In Value", 0); +const inMax = op.inFloat("Max In Value", 1); + +op.setPortGroup("General",[inChannel]); +op.setPortGroup("CC", [inCCValue, inCcIndex]); +op.setPortGroup("Value Range", [inMin,inMax]); + +const outEvent = op.outObject("MIDI Event Out"); + +inCCValue.onChange = function() { + const val = inCCValue.get(); + + const ccValue = Math.floor(CABLES.map(val,inMin.get(), inMax.get(), 0, 127)); + const ccIndex = clamp(inCcIndex.get(), 1, 127); + + + const event = { + deviceName: null, + output: null, + inputId: 0, + messageType: "CC", + data: [CC_STATUS_BYTE << 4 | (inChannel.get() - 1), ccIndex, ccValue], + index: ccIndex, + value: ccValue, + channel: inChannel.get() - 1, + } + + outEvent.set(null); + outEvent.set(event); +} + +}; + +Ops.Devices.Midi.MidiCCOut.prototype = new CABLES.Op(); +CABLES.OPS["f63adc97-7f4a-4cad-a53a-a20ad1e9b30e"]={f:Ops.Devices.Midi.MidiCCOut,objName:"Ops.Devices.Midi.MidiCCOut"}; + + + + +// ************************************************************** +// +// Ops.Devices.Midi.MidiChord3 +// +// ************************************************************** + +Ops.Devices.Midi.MidiChord3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +/* UTIL */ +const NOTE_OFF = 0x8; +const NOTE_ON = 0x9; +const NOTE_VALUES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]; + +const MIDIChannels = Array.from(Array(16).keys()).map((i) => { return i + 1; }); + +function getMIDINote(dataByte1LSB) +{ + return dataByte1LSB <= 126 + ? `${NOTE_VALUES[dataByte1LSB % 12]}${Math.floor(dataByte1LSB / 12) - 2} - ${dataByte1LSB}` + : "NO NOTE"; +} + +const noteValues = Array.from(Array(128).keys(), (key) => { return getMIDINote(key); }); + +/* IN */ +const inEvent = op.inObject("MIDI Event In"); +const midiChannelDropdown = op.inValueSelect("MIDI Channel", MIDIChannels, 1); +const noteDropdown = op.inValueSelect("Note 1", noteValues, 0); +const noteDropdown2 = op.inValueSelect("Note 2", noteValues, 0); +const noteDropdown3 = op.inValueSelect("Note 3", noteValues, 0); +const noteDropdowns = [noteDropdown, noteDropdown2, noteDropdown3]; + +const normalizeDropdown = op.inValueSelect( + "Normalize Velocity", + ["none", "0 to 1", "-1 to 1"], + "none" +); + +const learn = op.inTriggerButton("learn"); +const reset = op.inTriggerButton("reset"); + +op.setPortGroup("MIDI", [inEvent, midiChannelDropdown]); +op.setPortGroup("Notes", [...noteDropdowns, normalizeDropdown]); +op.setPortGroup("", [learn, reset]); +/* OUT */ + +const eventOut = op.outObject("MIDI Event Out"); +const triggerOut = op.outTrigger("Trigger Out"); + +const noteIndexOut1 = op.outNumber("Note Out 1"); +const velocityOut1 = op.outNumber("Velocity 1"); +const gateOut1 = op.outValueBool("Gate 1"); + +const out1 = { + "noteIndexOut": noteIndexOut1, + "velocityOut": velocityOut1, + "gateOut": gateOut1, +}; + +const noteIndexOut2 = op.outValue("Note Out 2"); +const velocityOut2 = op.outValue("Velocity 2"); +const gateOut2 = op.outValueBool("Gate 2"); + +const out2 = { + "noteIndexOut": noteIndexOut2, + "velocityOut": velocityOut2, + "gateOut": gateOut2, +}; + +const noteIndexOut3 = op.outValue("Note Out 3"); +const velocityOut3 = op.outValue("Velocity 3"); +const gateOut3 = op.outValueBool("Gate 3"); + +const out3 = { + "noteIndexOut": noteIndexOut3, + "velocityOut": velocityOut3, + "gateOut": gateOut3, +}; + +const outs = [out1, out2, out3]; +noteDropdown.set(0); +midiChannelDropdown.set(1); + +op.setPortGroup("MIDI/Trigger Out", [eventOut, triggerOut]); +op.setPortGroup("Note 1", [noteIndexOut1, velocityOut1, gateOut1]); +op.setPortGroup("Note 2", [noteIndexOut2, velocityOut2, gateOut2]); +op.setPortGroup("Note 3", [noteIndexOut3, velocityOut3, gateOut3]); + +let learning = false; +let learnCount = 0; +let learnedNotes = []; + +learn.onTriggered = () => +{ + learning = true; +}; + +reset.onTriggered = () => +{ + learning = false; + learnCount = 0; + learnedNotes = []; + noteDropdowns.forEach((nd) => { return nd.set(0); }); + op.refreshParams(); +}; + +inEvent.onChange = () => +{ + const event = inEvent.get(); + if (!event) return; + if (event.messageType !== "Note") return; + if (!event.newNote) return; + + const [statusByte] = event.data; + + const { newNote, velocity, channel } = event; + const [noteIndex, noteName] = newNote; + const midiNote = getMIDINote(noteIndex); + const msgType = statusByte >> 4; + + if (learning && learnCount < 3) + { + if (msgType === NOTE_OFF) + { + eventOut.set(event); + return; + } + + if (!learnedNotes.includes(midiNote)) noteDropdowns[learnCount].set(midiNote); + else + { + eventOut.set(event); + return; + } + + learnedNotes.push(midiNote); + if (learnCount === 0) midiChannelDropdown.set(event.channel + 1); + + if (CABLES.UI) + { + op.uiAttr({ "info": `bound to Note: ${noteDropdowns[learnCount].get()}` }); + op.refreshParams(); + } + + learnCount += 1; + learning = learnCount < 3; + } + + if (channel === midiChannelDropdown.get() - 1) + { + const chordIndex = noteDropdowns.map((nd) => { return nd.get(); }).indexOf(midiNote); + + if (chordIndex === -1) + { + eventOut.set(event); + return; + } + + const { + gateOut, noteIndexOut, velocityOut, + } = outs[chordIndex]; + + if (msgType === NOTE_OFF || velocity === 0) + { + gateOut.set(false); + if (velocity === 0) velocityOut.set(0); + } + + if (msgType === NOTE_ON) + { + gateOut.set(true); + triggerOut.trigger(); + noteIndexOut.set(noteIndex); + + if (normalizeDropdown.get() === "0 to 1") + { + // (max'-min')/(max-min)*(value-min)+min' + velocityOut.set(1 / 126 * (velocity - 1)); + } + + else if (normalizeDropdown.get() === "-1 to 1") + { + // (max'-min')/(max-min)*(value-min)+min' + const normalizedValue = 2 / 126 * (velocity - 1) - 1; + velocityOut.set(normalizedValue); + } + else if (normalizeDropdown.get() === "none") velocityOut.set(velocity); + } + } + + eventOut.set(event); +}; + + +}; + +Ops.Devices.Midi.MidiChord3.prototype = new CABLES.Op(); +CABLES.OPS["58388fbb-3161-417f-8c12-49d4c8ee7a19"]={f:Ops.Devices.Midi.MidiChord3,objName:"Ops.Devices.Midi.MidiChord3"}; + + + + +// ************************************************************** +// +// Ops.Devices.Midi.MidiClock +// +// ************************************************************** + +Ops.Devices.Midi.MidiClock = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const eventIn = op.inObject("MIDI Event In"); +const timingIn = op.inValueSelect("Timing", ["straight", "dotted", "triplet"], "straight"); +const eventOut = op.outObject("MIDI Event Out"); +const beatOut = op.outTrigger("Tick Out"); +const clockStartOut = op.outTrigger("Clock Start"); +const clockStopOut = op.outTrigger("Clock Stop"); +const clockContinueOut = op.outTrigger("Clock Continue"); + +let outBPM = op.outValue("BPM"); +let outBeatDuration = op.outValue("Tick Duration"); +let outSubTick = op.outValue("Sub Tick"); + +const fullNoteOut = op.outTrigger("1/1"); +const halfNoteOut = op.outTrigger("1/2"); +const quarterNoteOut = op.outTrigger("1/4"); +const eigthNoteOut = op.outTrigger("1/8"); +const sixteenthNoteOut = op.outTrigger("1/16"); + +const outs = { + "full": fullNoteOut, + "half": halfNoteOut, + "quarter": quarterNoteOut, + "eigth": eigthNoteOut, + "sixteenth": sixteenthNoteOut, +}; + +const CLOCK = 0xf8; +const CLOCK_START = 0xfa; +const CLOCK_CONTINUE = 0xfb; +const CLOCK_STOP = 0xfc; + +const STRAIGHT_TICKS = { + "full": 96, + "half": 48, + "quarter": 24, + "eigth": 12, + "sixteenth": 6, +}; + +const TICKS = { + "straight": STRAIGHT_TICKS, + "dotted": { + "full": STRAIGHT_TICKS.full + STRAIGHT_TICKS.full / 2, + "half": STRAIGHT_TICKS.half + STRAIGHT_TICKS.half / 2, + "quarter": STRAIGHT_TICKS.quarter + STRAIGHT_TICKS.quarter / 2, + "eigth": STRAIGHT_TICKS.eigth + STRAIGHT_TICKS.eigth / 2, + "sixteenth": STRAIGHT_TICKS.sixteenth + STRAIGHT_TICKS.sixteenth / 2, + }, + "triplet": { + "full": (STRAIGHT_TICKS.full * 2) / 3, + "half": (STRAIGHT_TICKS.half * 2) / 3, + "quarter": (STRAIGHT_TICKS.quarter * 2) / 3, + "eigth": (STRAIGHT_TICKS.eigth * 2) / 3, + "sixteenth": (STRAIGHT_TICKS.sixteenth * 2) / 3, + } +}; + +let tickCount = 0; +let lastBeat = 0; + +eventIn.onChange = () => +{ + const event = eventIn.get(); + if (!event) return; + + const [statusByte, , ] = event.data; + if (statusByte === CLOCK_START) + { + tickCount = 0; + clockStartOut.trigger(); + } + else if (statusByte === CLOCK_STOP) + { + clockStopOut.trigger(); + } + else if (statusByte === CLOCK || statusByte === CLOCK_CONTINUE) + { + if (statusByte === CLOCK_CONTINUE) clockContinueOut.trigger(); + + const { + full, half, quarter, eigth, sixteenth, + } = TICKS[timingIn.get()]; + if (tickCount % 24 === 0) + { + if (lastBeat !== 0) + { + const diff = CABLES.now() - lastBeat; + const bpm = 60000 / diff; + outBPM.set(bpm); + outBeatDuration.set(15 / bpm); + } + + lastBeat = CABLES.now(); + } + if (tickCount % full === 0) outs.full.trigger(); + if (tickCount % half === 0) outs.half.trigger(); + if (tickCount % quarter === 0) outs.quarter.trigger(); + if (tickCount % eigth === 0) outs.eigth.trigger(); + if (tickCount % sixteenth === 0) outs.sixteenth.trigger(); + beatOut.trigger(); + tickCount += 1; + outSubTick.set(tickCount % 24); + } + + eventOut.set(event); +}; + + +}; + +Ops.Devices.Midi.MidiClock.prototype = new CABLES.Op(); +CABLES.OPS["5eea2f30-4e10-42a7-a761-63fb274cdb4f"]={f:Ops.Devices.Midi.MidiClock,objName:"Ops.Devices.Midi.MidiClock"}; + + + + +// ************************************************************** +// +// Ops.Devices.Midi.MidiInputDevice_v2 +// +// ************************************************************** + +Ops.Devices.Midi.MidiInputDevice_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// http://www.keithmcmillen.com/blog/making-music-in-the-browser-web-midi-api/ + +// https://ccrma.stanford.edu/~craig/articles/linuxmidi/misc/essenmidi.html + +/* INPUTS */ + +const deviceSelect = op.inValueSelect("Device", ["none"]); + +let learning = false; +const learn = op.inTriggerButton("Learn"); +const resetIn = op.inTriggerButton("Panic"); + +op.setPortGroup("Device Select", [deviceSelect]); +op.setPortGroup("Controls", [learn, resetIn]); +/* OPS */ +const opPrefix = "Ops.Devices.Midi.Midi"; +const OPS = { + "CC": { "NAMESPACE": `${opPrefix}CC`, "IN_PORT": "CC Index" }, + "NRPN": { "NAMESPACE": `${opPrefix}NRPN`, "IN_PORT": "NRPN Index" }, + "Note": { "NAMESPACE": `${opPrefix}Note`, "IN_PORT": "Note" }, +}; +/* OUTPUTS */ +const OUTPUT_KEYS = [ + "Event", + "Note", + "CC", + + // "Channel Pressure", + // "Poly Key Pressure", + "NRPN", + // 'SysEx', + // "Pitchbend", + "Program Change", + "Clock", +]; + +// unused midi signals +const NOT_YET_USED = ["Pitchbend", "Channel Pressure", "Poly Key Pressure", "SysEx"]; + +// create outputs from keys specified above +const OUTPUTS = OUTPUT_KEYS.reduce((acc, cur) => +{ + acc[cur] = op.outObject(cur); + return acc; +}, {}); + +op.setPortGroup("MIDI Event", [OUTPUTS.Event]); +op.setPortGroup( + "MIDI Event by Type", + Object.keys(OUTPUTS).map((key) => { return key !== "Event" && OUTPUTS[key]; }).filter(Boolean), +); + +/* CONSTANTS */ +/* http://www.indiana.edu/~emusic/etext/MIDI/chapter3_MIDI3.shtml */ +const NOTE_VALUES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]; + +/* MIDI STATUS BYTES */ +const NOTE_OFF = 0x8; +const NOTE_ON = 0x9; +const POLY_KEY_PRESSURE = 0xa; +const CC = 0xb; +const PROGRAM_CHANGE = 0xc; +const CHANNEL_PRESSURE = 0xd; +const PITCH_BEND = 0xe; +const CLOCK = 0xf8; +const CLOCK_START = 0xfa; +const CLOCK_CONTINUE = 0xfb; +const CLOCK_STOP = 0xfc; +const CLOCK_SIGNALS = [CLOCK, CLOCK_START, CLOCK_CONTINUE, CLOCK_STOP]; + +const MESSAGE_TYPES = { + [NOTE_OFF]: "Note", + [NOTE_ON]: "Note", + [POLY_KEY_PRESSURE]: "Poly Key Pressure", + [CC]: "CC", + [PROGRAM_CHANGE]: "Program Change", + [CHANNEL_PRESSURE]: "Channel Pressure", + [PITCH_BEND]: "Pitchbend", + [CLOCK]: "Clock", +}; + +/* UTILITY FUNCTIONS */ +function getMIDIChannel(statusByte) +{ + return statusByte & 0x0f; +} + +function getMessageType(statusByte) +{ + return MESSAGE_TYPES[statusByte >> 4] || "UNKNOWN"; +} + +function getMIDINote(dataByte1LSB) +{ + return dataByte1LSB <= 126 + ? `${NOTE_VALUES[dataByte1LSB % 12]}${Math.floor(dataByte1LSB / 12) - 2} - ${dataByte1LSB}` + : "NO NOTE"; +} + +const NRPN_CCS = [98, 99, 6, 38]; +const NRPN_VALUE_MSB = 6; +const NRPN_VALUE_LSB = 38; +const NRPN_INDEX_MSB = 99; +const NRPN_INDEX_LSB = 98; + +let nrpnIndexMSB = null; +let nrpnIndexLSB = null; +let nrpnValueMSB = null; +let nrpnValueLSB = null; + +let nrpnIndex_ = null; +let nrpnValue_ = null; + +/* NRPN implementations differ, we need to check whether the cycle starts with LSB or MSB */ +const MSB_START = 9; +const LSB_START = 10; +let FIRST_CC = null; +let ROUTINE_TYPE = null; +/* the state of the current NRPN construction cycle */ + + +const LSBRoutine = (ccIndex, ccValue) => +{ + // NOTE: this is still the MSBRoutine + if (ccIndex === NRPN_INDEX_MSB) nrpnIndexMSB = ccValue << 7; + else if (ccIndex === NRPN_INDEX_LSB) nrpnIndexLSB = ccValue; + + nrpnIndex_ = nrpnIndexMSB | nrpnIndexLSB; + + if (typeof nrpnIndex_ === "number") + { + if (ccIndex === NRPN_VALUE_MSB) + { + nrpnValueMSB = ccValue << 7; + + + if (typeof nrpnValueLSB === "number") + { + nrpnValue_ = nrpnValueMSB | nrpnValueLSB; + return [nrpnIndex_, nrpnValue_]; + } + } + else if (ccIndex === NRPN_VALUE_LSB) + { + nrpnValueLSB = ccValue; + + nrpnValue_ = nrpnValueMSB | nrpnValueLSB; + return [nrpnIndex_, nrpnValue_]; + } + } + + return null; +}; + +const MSBRoutine = (ccIndex, ccValue) => +{ + if (ccIndex === NRPN_INDEX_MSB) nrpnIndexMSB = ccValue << 7; + else if (ccIndex === NRPN_INDEX_LSB) nrpnIndexLSB = ccValue; + + nrpnIndex_ = nrpnIndexMSB | nrpnIndexLSB; + if (typeof nrpnIndex_ === "number") + { + if (ccIndex === NRPN_VALUE_MSB) + { + nrpnValueMSB = ccValue << 7; + + if (typeof nrpnValueLSB === "number") + { + nrpnValue_ = nrpnValueMSB | nrpnValueLSB; + return [nrpnIndex_, nrpnValue_]; + } + } + else if (ccIndex === NRPN_VALUE_LSB) + { + nrpnValueLSB = ccValue; + nrpnValue_ = nrpnValueMSB | nrpnValueLSB; + return [nrpnIndex_, nrpnValue_]; + } + } + + return null; +}; + +const NRPNRoutine = (ccIndex, ccValue) => +{ + if (FIRST_CC === null) + { + FIRST_CC = ccIndex; + ROUTINE_TYPE = FIRST_CC === NRPN_INDEX_MSB ? MSB_START : LSB_START; + } + if (ROUTINE_TYPE === MSB_START) + { + return MSBRoutine(ccIndex, ccValue); + } + if (ROUTINE_TYPE === LSB_START) + { + return LSBRoutine(ccIndex, ccValue); + } + return null; +}; +let midi = null; + +/* INIT FUNCTIONS */ +let outputDevice = null; + +function onMIDIMessage(_event) +{ + if (!_event) return; + + if (op.patch.isEditorMode()) gui.emitEvent("userActivity"); + + const { data } = _event; + const [statusByte, LSB, MSB] = data; + + if (CLOCK_SIGNALS.includes(statusByte)) + { + OUTPUTS.Clock.set(_event); + return; + } + + if (statusByte > 248) + { + // we don't use statusbytes above 248 for now + return; + } + + const deviceName = deviceSelect.get(); + const channel = getMIDIChannel(statusByte); + + let messageType = getMessageType(statusByte); + const outputIndex = LSB; + const outputValue = MSB; + + const isNRPNByte = messageType === "CC" && NRPN_CCS.some((cc) => { return cc === LSB; }); + let nrpnIndex; + let nrpnValue; + + if (isNRPNByte) + { + const nrpnValueRes = NRPNRoutine(LSB, MSB); + if (nrpnValueRes) + { + const [index, value] = nrpnValueRes; + messageType = "NRPN"; + nrpnIndex = index; + nrpnValue = value; + } + } + + const newEvent = { + /* OLD EVENT v */ + deviceName, + "inputId": 0, // what is this for? + messageType, + // ..., + "index": outputIndex, + "value": outputValue, + + "cmd": data[0] >> 4, + "channel": data[0] & 0xf, + "type": data[0] & 0xf0, + "note": data[1], + "velocity": data[2], + data, + ...messageType === "Note" && { + "newNote": [LSB, getMIDINote(LSB)], + "velocity": outputValue, + }, + ...messageType === "NRPN" && { nrpnIndex, nrpnValue }, + }; + + if (learning) + { + if (["Note", "CC", "NRPN"].includes(messageType)) + { + const newOp = op.patch.addOp(OPS[messageType].NAMESPACE, { + "translate": { + "x": op.uiAttribs.translate.x, + "y": op.uiAttribs.translate.y + 100, + }, + }); + + op.patch.link(op, messageType, newOp, "MIDI Event In"); + newOp.getPortByName("MIDI Channel").set(channel + 1); + + if (messageType === "Note") + { + const { + "newNote": [, noteName], + } = newEvent; + newOp.getPortByName("Note").set(noteName); + } + + if (messageType === "CC") + { + const { index } = newEvent; + newOp.getPortByName("CC Index").set(index); + } + + if (messageType === "NRPN") + { + newOp.getPortByName("NRPN Index").set(nrpnIndex); + } + } + learning = false; + } + // if (normalize.get()) event.velocity /= 127; + + // with pressure and tilt off + // note off: 128, cmd: 8 + // note on: 144, cmd: 9 + // pressure / tilt on + // pressure: 176, cmd 11: + // bend: 224, cmd: 14 + OUTPUTS.Event.set(null); + OUTPUTS.Event.set(newEvent); + + if (messageType !== "UNKNOWN" && !NOT_YET_USED.includes(messageType)) + { + OUTPUTS[messageType].set(null); + OUTPUTS[messageType].set(newEvent); + } +} + +function setDevice() +{ + if (!midi || !midi.inputs) return; + const name = deviceSelect.get(); + + op.setTitle(`Midi ${name}`); + + const inputs = midi.inputs.values(); + // const outputs = midi.outputs.values(); + + for (let input = inputs.next(); input && !input.done; input = inputs.next()) + { + if (input.value.name === name) + { + input.value.onmidimessage = onMIDIMessage; + outputDevice = midi.inputs.get(input.value.id); + } + else if (input.value.onmidimessage === onMIDIMessage) input.value.onmidimessage = null; + } + + /* for (let output = outputs.next(); output && !output.done; output = outputs.next()) { + if (output.value.name === name) { + outputDevice = midi.outputs.get(output.value.id); + } + } */ +} + +function onMIDIFailure() +{ + op.uiAttr({ "warning": "No MIDI support in your browser." }); +} + +function onMIDISuccess(midiAccess) +{ + midi = midiAccess; + const inputs = midi.inputs.values(); + op.uiAttr({ "info": "no midi devices found" }); + + const deviceNames = []; + + for (let input = inputs.next(); input && !input.done; input = inputs.next()) + { + deviceNames.push(input.value.name); + } + + deviceSelect.uiAttribs.values = deviceNames; + + op.refreshParams(); + setDevice(); +} + +deviceSelect.onChange = setDevice; + +if (navigator.requestMIDIAccess) +{ + navigator.requestMIDIAccess({ "sysex": false }).then(onMIDISuccess, onMIDIFailure); +} +else onMIDIFailure(); + +resetIn.onTriggered = () => +{ + + // TODO: senmd note off to every note + /* + if (!outputDevice) return; + for (let i = 0; i < 12; i += 1) { + outputDevice.send([0x90, i, 0]); + outputDevice.send([0xb0, i, 0]); + } */ +}; + +learn.onTriggered = () => +{ + if (!outputDevice) return; + learning = true; +}; + + +}; + +Ops.Devices.Midi.MidiInputDevice_v2.prototype = new CABLES.Op(); +CABLES.OPS["484b3a00-41b7-4e3f-8a99-a1b32a764eff"]={f:Ops.Devices.Midi.MidiInputDevice_v2,objName:"Ops.Devices.Midi.MidiInputDevice_v2"}; + + + + +// ************************************************************** +// +// Ops.Devices.Midi.MidiMonitor +// +// ************************************************************** + +Ops.Devices.Midi.MidiMonitor = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inData = op.inObject("Event"); + +op.setPortGroup("MIDI", [inData]); + +/* OUTPUTS */ +const OUTPUT_KEYS = [ + "Device", + "MIDI Channel", + "Message Type", + "Note", + "Note Velocity", + "CC Number", + "CC Value", + "Pitch Bend Value", + "NRPN Number", + "NRPN Value", + "Program Change", +]; + +const eventOut = op.outObject("MIDI Event Out"); +const triggerOut = op.outTrigger("Trigger Out"); + +// create outputs from keys specified above +const OUTPUTS = { + "Device": op.outNumber("Device", -1), + "MIDI Channel": op.outNumber("MIDI Channel", -1), + "Message Type": op.outNumber("Message Type", -1), + "Note": op.outNumber("Note", -1), + "Note Velocity": op.outNumber("Note Velocity", -1), + "CC Number": op.outNumber("CC Number", -1), + "CC Value": op.outNumber("CC Value", -1), + "Pitch Bend Value": op.outNumber("Pitch Bend Value", -1), + "NRPN Number": op.outNumber("NRPN Number", -1), + "NRPN Value": op.outNumber("NRPN Value", -1), + "Program Change Value": op.outNumber("Program Change Value", -1), + +}; + +op.setPortGroup("MIDI/Trigger Out", [eventOut, triggerOut]); +op.setPortGroup("General Info", ["Device", "MIDI Channel", "Message Type"].map((key) => OUTPUTS[key])); +op.setPortGroup("Note", ["Note", "Note Velocity"].map((key) => OUTPUTS[key])); +op.setPortGroup("CC", ["CC Number", "CC Value"].map((key) => OUTPUTS[key])); +op.setPortGroup("Pitch Bend", [OUTPUTS["Pitch Bend Value"]]); +op.setPortGroup("NRPN", ["NRPN Number", "NRPN Value"].map((key) => OUTPUTS[key])); +op.setPortGroup("Program Change", ["Program Change Value"].map((key) => OUTPUTS[key])); + +/* http://midiio.sapp.org/src/MidiOutput.cpp for NRPN */ +/* http://www.indiana.edu/~emusic/etext/MIDI/chapter3_MIDI3.shtml */ + +/* +The two things we can assume is that we will receive the NRPN index messages BEFORE the data +and that the LSB of the data will change every time we get an NRPN change. +*/ + +function getMIDIChannel(statusByte) +{ + return (statusByte & 0x0f) + 1; +} + +function getPitchBendValue(dataByte1LSB, dataByte2MSB) +{ + const pitchBendValue = (dataByte2MSB << 7) + dataByte1LSB - 8192; // scale to -1 to 1 = /8192; + return pitchBendValue; +} + +/* http://tetradev.blogspot.com/2010/03/nrpns-part-2-nrpns-in-ableton-with-max.html */ +/* https://sites.uci.edu/camp2014/2014/04/30/managing-midi-pitchbend-messages/ */ + +inData.onChange = function () +{ + const event = inData.get(); + + if (!event || !event.data) return; + const [statusByte, dataByte1LSB, dataByte2MSB] = event.data; + /* We skip MIDI signals that at the moment are not relevant for CABLES, + i.e. Ableton: if SYNC is on, every 2nd 3-Byte-Tuple sent + is a Timing clock message + we don't wanna show that for now, hence we skip everything above 248 */ + if (statusByte >= 248) + { + eventOut.set(event); + triggerOut.trigger(); + return; + } + + const { messageType, deviceName } = event; + + OUTPUTS.Device.set(deviceName); + OUTPUTS["MIDI Channel"].set(getMIDIChannel(statusByte)); + OUTPUTS["Message Type"].set(messageType); + + switch (messageType) + { + case "NRPN": + OUTPUTS["NRPN Number"].set(event.nrpnIndex); + OUTPUTS["NRPN Value"].set(event.nrpnValue); + Object.keys(OUTPUTS) + .filter( + (key) => !key.startsWith(messageType) + && key !== "Message Type" && key !== "MIDI Channel" && key !== "Device", + ) + .forEach((filteredKey) => OUTPUTS[filteredKey].set("-")); + break; + case "CC": + const [, ccIndex, ccValue] = event.data; + OUTPUTS["CC Number"].set(ccIndex); + OUTPUTS["CC Value"].set(ccValue); + Object.keys(OUTPUTS) + .filter( + (key) => !key.startsWith(messageType) + && key !== "Message Type" && key !== "MIDI Channel" && key !== "Device", + ) + .forEach((filteredKey) => OUTPUTS[filteredKey].set("-")); + break; + case "Note": + const { + "newNote": [noteIndex], + velocity, + } = event; + OUTPUTS.Note.set(noteIndex); + OUTPUTS["Note Velocity"].set(velocity); + Object.keys(OUTPUTS) + .filter( + (key) => !key.startsWith(messageType) + && key !== "Message Type" && key !== "MIDI Channel" && key !== "Device" + ) + .forEach((filteredKey) => OUTPUTS[filteredKey].set("-")); + break; + case "Pitch Bend": + OUTPUTS["Pitch Bend Value"].set(getPitchBendValue(dataByte1LSB, dataByte2MSB)); + Object.keys(OUTPUTS) + .filter( + (key) => !key.startsWith(messageType) + && key !== "Message Type" && key !== "MIDI Channel" && key !== "Device" + ) + .forEach((filteredKey) => OUTPUTS[filteredKey].set("-")); + break; + case "Program Change": + const [, pcValue] = event.data; + OUTPUTS["Program Change Value"].set(pcValue); + Object.keys(OUTPUTS) + .filter( + (key) => !key.startsWith(messageType) + && key !== "Message Type" && key !== "MIDI Channel" && key !== "Device" + ) + .forEach((filteredKey) => OUTPUTS[filteredKey].set("-")); + break; + default: + Object.keys(OUTPUTS) + .filter((key) => key !== "Message Type" && key !== "MIDI Channel" && key !== "Device") + .forEach((filteredKey) => OUTPUTS[filteredKey].set("-")); + } + + triggerOut.trigger(); + eventOut.set(event); + // } +}; + + +}; + +Ops.Devices.Midi.MidiMonitor.prototype = new CABLES.Op(); +CABLES.OPS["3f585ff5-afd6-45d5-b082-80c62f6cdf2b"]={f:Ops.Devices.Midi.MidiMonitor,objName:"Ops.Devices.Midi.MidiMonitor"}; + + + + +// ************************************************************** +// +// Ops.Devices.Midi.MidiNRPN +// +// ************************************************************** + +Ops.Devices.Midi.MidiNRPN = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +/* UTIL */ +const MIDIChannels = Array.from(Array(16).keys()).map((i) => { return i + 1; }); + +/* IN */ +const inEvent = op.inObject("MIDI Event In"); +const midiChannelDropdown = op.inValueSelect("MIDI Channel", MIDIChannels, 1); + +const nrpnIndexDropdown = op.inValueInt("NRPN Index", 0); +const normalizeDropdown = op.inValueSelect("Normalize", ["none", "0 to 1", "-1 to 1"], "none"); +const learn = op.inTriggerButton("learn"); +const clear = op.inTriggerButton("clear"); + +op.setPortGroup("MIDI", [inEvent, midiChannelDropdown]); +op.setPortGroup("NRPN", [nrpnIndexDropdown, normalizeDropdown]); +op.setPortGroup("", [learn, clear]); +/* OUT */ +const eventOut = op.outObject("MIDI Event Out"); +const triggerOut = op.outTrigger("Trigger Out"); +const nrpnIndexOut = op.outValue("NRPN Index"); +const nrpnValueOut = op.outValue("NRPN Value"); + +op.setPortGroup("MIDI/Trigger Out", [eventOut, triggerOut]); +op.setPortGroup("NRPN Out", [nrpnIndexOut, nrpnValueOut]); + +nrpnIndexDropdown.set(0); +midiChannelDropdown.set(1); +normalizeDropdown.set(normalizeDropdown.get("none")); + +let learning = false; +learn.onTriggered = () => +{ + learning = true; +}; + +clear.onTriggered = () => +{ + nrpnIndexDropdown.set(0); + midiChannelDropdown.set(1); + normalizeDropdown.set(normalizeDropdown.get("none")); + op.refreshParams(); +}; +let outValue; +inEvent.onChange = () => +{ + const event = inEvent.get(); + if (!event) return; + if (event.messageType !== "NRPN") return; + + const { channel, nrpnIndex, nrpnValue } = event; + + if (learning) + { + nrpnIndexDropdown.set(nrpnIndex); + midiChannelDropdown.set(channel + 1); + + learning = false; + + if (CABLES.UI) + { + op.uiAttr({ "info": `bound to NRPN: ${nrpnIndexDropdown.get()}` }); + op.refreshParams(); + } + } + + if (channel === midiChannelDropdown.get() - 1) + { + if (nrpnIndex === nrpnIndexDropdown.get()) + { + nrpnIndexOut.set(nrpnIndex); + + outValue = nrpnValue; + + if (normalizeDropdown.get() === "0 to 1") + { + nrpnValueOut.set(outValue / 16383); + triggerOut.trigger(); + } + else if (normalizeDropdown.get() === "-1 to 1") + { + nrpnValueOut.set(outValue / (16383 / 2) - 1); + triggerOut.trigger(); + } + else if (normalizeDropdown.get() === "none") + { + nrpnValueOut.set(outValue); + triggerOut.trigger(); + } + else nrpnValueOut.set(0); + } + } + eventOut.set(null); + eventOut.set(event); +}; + + +}; + +Ops.Devices.Midi.MidiNRPN.prototype = new CABLES.Op(); +CABLES.OPS["2b13bc7b-c1bd-4319-9c85-86a81a6e2354"]={f:Ops.Devices.Midi.MidiNRPN,objName:"Ops.Devices.Midi.MidiNRPN"}; + + + + +// ************************************************************** +// +// Ops.Devices.Midi.MidiNRPNOut +// +// ************************************************************** + +Ops.Devices.Midi.MidiNRPNOut = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// your new op +// have a look at the documentation at: +// https://docs.cables.gl/dev_hello_op/dev_hello_op.html +const MIDIChannels = Array.from(Array(16).keys(), i => i + 1); +const clamp = (val, min, max) => Math.min(Math.max(val, min), max); +const CC_STATUS_BYTE = 0xb; +const CC_STATUS_BYTE_START = 176; + +const inChannel = op.inDropDown("MIDI Channel", MIDIChannels, "1"); +const inNrpnIndex = op.inInt("NRPN Index", 0); +const inNrpnValue = op.inInt("NRPN Value", 0); +const inMin = op.inFloat("Min In Value", 0); +const inMax = op.inFloat("Max In Value", 1); +op.setPortGroup("General",[inChannel]); +op.setPortGroup("NRPN",[inNrpnValue, inNrpnIndex]); +op.setPortGroup("Value Range",[inMin, inMax]); +const outEvent = op.outObject("MIDI Event Out"); + +inNrpnValue.onChange = function() { + const val = inNrpnValue.get(); + + const nrpnValue = Math.floor(CABLES.map(val,inMin.get(), inMax.get(), 0, 16383)); + const nrpnIndex = clamp(inNrpnIndex.get(), 0, 16383); + // const ccValue = clamp(inNrpnValue.get(), 0, 127); + /* + const newEvent = Object.assign( + { + // OLD EVENT v + deviceName, + output: outputDevice, + inputId: 0, // what is this for? + messageType, + // ..., + index: outputIndex, + value: outputValue, + + cmd: data[0] >> 4, + channel: data[0] & 0xf, + type: data[0] & 0xf0, + note: data[1], + velocity: data[2], + data, + }, + messageType === 'Note' && { + newNote: [LSB, getMIDINote(LSB)], + velocity: outputValue, + }, + messageType === 'NRPN' && { nrpnIndex, nrpnValue }, + ); + */ + + const event = { + deviceName: null, + output: null, + inputId: 0, + messageType: "NRPN", + data: [], + channel: inChannel.get() - 1, + nrpnIndex, + nrpnValue, + } + + outEvent.set(null); + outEvent.set(event); +} + +}; + +Ops.Devices.Midi.MidiNRPNOut.prototype = new CABLES.Op(); +CABLES.OPS["469abc8f-598a-4a42-a5df-881bf80ee363"]={f:Ops.Devices.Midi.MidiNRPNOut,objName:"Ops.Devices.Midi.MidiNRPNOut"}; + + + + +// ************************************************************** +// +// Ops.Devices.Midi.MidiNote +// +// ************************************************************** + +Ops.Devices.Midi.MidiNote = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +/* UTIL */ +const NOTE_OFF = 0x8; +const NOTE_ON = 0x9; +const NOTE_VALUES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]; + +const MIDIChannels = Array.from(Array(16).keys()).map((i) => { return i + 1; }); + +function getMIDINote(dataByte1LSB) +{ + return dataByte1LSB <= 126 + ? `${NOTE_VALUES[dataByte1LSB % 12]}${Math.floor(dataByte1LSB / 12) - 2} - ${dataByte1LSB}` + : "NO NOTE"; +} + +const noteValues = Array.from(Array(128).keys(), (key) => { return getMIDINote(key); }); +const velocityArray = Array.from(Array(128).keys(), (key) => { return 0; }); +/* IN */ +const inEvent = op.inObject("MIDI Event In"); +const midiChannelDropdown = op.inValueSelect("MIDI Channel", MIDIChannels, 1); +const noteDropdown = op.inValueSelect("Note", noteValues, "none"); +const normalizeDropdown = op.inSwitch( + "Normalize Velocity", + ["none", "0 to 1", "-1 to 1"], + "none", +); +const gateType = op.inBool("Toggle Gate", false); +const learn = op.inTriggerButton("learn"); +const clear = op.inTriggerButton("clear"); + +op.setPortGroup("MIDI", [inEvent, midiChannelDropdown]); +op.setPortGroup("", [learn, clear]); +op.setPortGroup("Note", [noteDropdown, normalizeDropdown, gateType]); + +/* OUT */ +const eventOut = op.outObject("MIDI Event Out"); +const triggerOut = op.outTrigger("Trigger Out"); +const currentNoteOut = op.outNumber("Current Note"); +const velocityOut = op.outNumber("Velocity"); +const gateOut = op.outValueBool("Gate"); +const arrayOut = op.outArray("Velocity Array"); +arrayOut.set(velocityArray); + +op.setPortGroup("MIDI/Trigger Out", [eventOut, triggerOut]); +op.setPortGroup("Note Out", [currentNoteOut, velocityOut, gateOut]); +noteDropdown.set(0); +midiChannelDropdown.set(1); + +let learning = false; +learn.onTriggered = () => +{ + learning = true; +}; + +clear.onTriggered = () => +{ + noteDropdown.set(0); + midiChannelDropdown.set(1); + normalizeDropdown.set(normalizeDropdown.get("none")); + gateType.set(false); + op.refreshParams(); +}; + +gateType.onChange = () => +{ + if (!gateType.get()) gateOut.set(false); +}; + +inEvent.onChange = () => +{ + const event = inEvent.get(); + if (!event) return; + if (event.messageType !== "Note") return; + if (!event.newNote) return; + + const [statusByte] = event.data; + + const { newNote, velocity } = event; + const [noteIndex, noteName] = newNote; + + if (learning || noteDropdown.onChange) + { + noteDropdown.set(noteName); + midiChannelDropdown.set(event.channel + 1); + + learning = false; + + if (CABLES.UI) + { + gui.emitEvent("portValueEdited", op, noteDropdown, noteDropdown.get()); + gui.emitEvent("portValueEdited", op, midiChannelDropdown, midiChannelDropdown.get()); + + op.uiAttr({ "info": `bound to Note: ${noteDropdown.get()}` }); + op.refreshParams(); + } + } + + if (event.channel === midiChannelDropdown.get() - 1) + { + if (getMIDINote(noteIndex) === noteDropdown.get()) + { + if ((statusByte >> 4 === NOTE_OFF || velocity === 0) && !gateType.get()) + { + gateOut.set(false); + velocityOut.set(0); + velocityArray[noteIndex] = 0; + arrayOut.set(null); + arrayOut.set(velocityArray); + } + else if (statusByte >> 4 === NOTE_ON) + { + if (gateType.get()) + { + gateOut.set(!gateOut.get()); + } + else + { + gateOut.set(true); + } + currentNoteOut.set(noteIndex); + velocityArray[noteIndex] = velocity; + arrayOut.set(null); + arrayOut.set(velocityArray); + if (normalizeDropdown.get() === "0 to 1") + { + // (max'-min')/(max-min)*(value-min)+min' + velocityOut.set((1 / 126) * (velocity - 1)); + velocityArray[noteIndex] = (1 / 126) * (velocity - 1); + triggerOut.trigger(); + } + else if (normalizeDropdown.get() === "-1 to 1") + { + // (max'-min')/(max-min)*(value-min)+min' + const normalizedValue = (2 / 126) * (velocity - 1) - 1; + velocityArray[noteIndex] = normalizedValue; + velocityOut.set(normalizedValue); + triggerOut.trigger(); + } + else if (normalizeDropdown.get() === "none") + { + velocityOut.set(velocity); + triggerOut.trigger(); + } + } + } + else if (noteDropdown.get() === 0) + { + // no note selected + if ((statusByte >> 4 === NOTE_OFF || velocity === 0) && !gateType.get()) + { + gateOut.set(false); + velocityOut.set(0); + velocityArray[noteIndex] = 0; + arrayOut.set(null); + arrayOut.set(velocityArray); + } + else if (statusByte >> 4 === NOTE_ON) + { + if (gateType.get()) + { + gateOut.set(!gateOut.get()); + } + else + { + gateOut.set(true); + } + currentNoteOut.set(noteIndex); + + if (normalizeDropdown.get() === "0 to 1") + { + // (max'-min')/(max-min)*(value-min)+min' + const newVelocity = (1 / 126) * (velocity - 1); + velocityOut.set(newVelocity); + velocityArray[noteIndex] = newVelocity; + arrayOut.set(null); + arrayOut.set(velocityArray); + triggerOut.trigger(); + } + else if (normalizeDropdown.get() === "-1 to 1") + { + // (max'-min')/(max-min)*(value-min)+min' + const normalizedValue = (2 / 126) * (velocity - 1) - 1; + velocityOut.set(normalizedValue); + velocityArray[noteIndex] = normalizedValue; + arrayOut.set(null); + arrayOut.set(velocityArray); + triggerOut.trigger(); + } + else if (normalizeDropdown.get() === "none") + { + velocityOut.set(velocity); + velocityArray[noteIndex] = velocity; + arrayOut.set(null); + arrayOut.set(velocityArray); + triggerOut.trigger(); + } + } + } + } + eventOut.set(null); + eventOut.set(event); +}; + + +}; + +Ops.Devices.Midi.MidiNote.prototype = new CABLES.Op(); +CABLES.OPS["517ed1fc-6110-4611-9cc7-8dd459191c65"]={f:Ops.Devices.Midi.MidiNote,objName:"Ops.Devices.Midi.MidiNote"}; + + + + +// ************************************************************** +// +// Ops.Devices.Midi.MidiNoteFilter +// +// ************************************************************** + +Ops.Devices.Midi.MidiNoteFilter = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +/* UTIL */ +const NOTE_OFF = 0x8; +const NOTE_ON = 0x9; +const NOTE_VALUES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]; + +const MIDIChannels = Array.from(Array(16).keys()).map((i) => { return i + 1; }); + +function getMIDINote(dataByte1LSB) +{ + return dataByte1LSB <= 126 + ? `${NOTE_VALUES[dataByte1LSB % 12]}${Math.floor(dataByte1LSB / 12) - 2} - ${dataByte1LSB}` + : "NO NOTE"; +} + +function getNoteIndexFromMIDINote(midiNote) +{ + if (!midiNote || midiNote === "NO NOTE") return null; + const string = midiNote.split("- ")[1]; + return Number(string); +} + +const noteValues = Array.from(Array(128).keys()).map((key) => { return getMIDINote(key); }); + +/* IN */ +// persistent array for learned notes +const learnedNotesIn = op.inArray("Note Values", []); +learnedNotesIn.setUiAttribs({ "hidePort": true }); + +const inEvent = op.inObject("MIDI Event"); +const midiChannelDropdown = op.inValueSelect("MIDI Channel", MIDIChannels, 1); +const noteStartDropdown = op.inValueSelect("Note Start", noteValues, 0); +const noteEndDropdown = op.inValueSelect("Note End", noteValues, 0); +const normalizeDropdown = op.inValueSelect( + "Normalize Velocity", + ["none", "0 to 1", "-1 to 1"], + "none", +); +const learn = op.inTriggerButton("learn"); +const reset = op.inTriggerButton("reset"); + +op.setPortGroup("MIDI", [inEvent, midiChannelDropdown]); +op.setPortGroup("Notes", [noteStartDropdown, noteEndDropdown, normalizeDropdown]); + +/* OUT */ +const eventOut = op.outObject("Event"); +const triggerOut = op.outTrigger("Trigger Out"); +const noteIndexOut = op.outNumber("Current Note"); +const velocityOut = op.outNumber("Velocity"); +const gateOut = op.outValueBool("Gate"); + +op.setPortGroup("MIDI/Trigger Out", [eventOut, triggerOut]); +op.setPortGroup("Notes Out", [noteIndexOut, velocityOut, gateOut]); + +noteStartDropdown.set(0); +noteEndDropdown.set(0); +midiChannelDropdown.set(1); + +let learning = false; + +learn.onTriggered = () => +{ + if (learnedNotesIn.get().length > 0) + { + learnedNotesIn.set([]); + } + learning = true; +}; +reset.onTriggered = () => +{ + learning = false; + learnedNotesIn.set([]); + noteStartDropdown.set(0); + noteEndDropdown.set(0); + midiChannelDropdown.set(1); + op.refreshParams(); +}; + +let selfRef = false; +noteStartDropdown.onChange = () => +{ + const learnedNotes = learnedNotesIn.get(); + learnedNotes[0] = getNoteIndexFromMIDINote(noteStartDropdown.get()); + op.refreshParams(); + + if (selfRef) return; + if (learnedNotes.length === 2) + { + selfRef = true; + learnedNotes.sort((a, b) => { return a - b; }); + const [start, end] = learnedNotes; + noteStartDropdown.set(getMIDINote(start)); + noteEndDropdown.set(getMIDINote(end)); + selfRef = false; + } + learnedNotesIn.set(learnedNotes); +}; + +noteEndDropdown.onChange = () => +{ + const learnedNotes = learnedNotesIn.get(); + learnedNotes[1] = getNoteIndexFromMIDINote(noteEndDropdown.get()); + op.refreshParams(); + + if (selfRef) return; + if (learnedNotes.length === 2) + { + selfRef = true; + learnedNotes.sort((a, b) => { return a - b; }); + const [start, end] = learnedNotes; + noteStartDropdown.set(getMIDINote(start)); + noteEndDropdown.set(getMIDINote(end)); + selfRef = false; + } + learnedNotesIn.set(learnedNotes); +}; + +inEvent.onChange = () => +{ + const event = inEvent.get(); + if (!event) return; + if (event.messageType !== "Note") return; + if (!event.newNote) return; + + const [statusByte] = event.data; + + const { newNote, velocity } = event; + const [noteIndex, noteName] = newNote; + const midiNote = getMIDINote(noteIndex); + const learnedNotes = learnedNotesIn.get(); + + if (learning) + { + if (statusByte >> 4 === NOTE_OFF) + { + eventOut.set(event); + return; + } + if (!learnedNotes.includes(midiNote) && learnedNotes.length < 2) + { + learnedNotes.push(noteIndex); + learnedNotesIn.set(learnedNotes); + } + if (learnedNotes.length === 2) + { + learnedNotes.sort((a, b) => { return a - b; }); + learnedNotesIn.set(learnedNotes); + const [start, end] = learnedNotes; + + noteStartDropdown.set(getMIDINote(start)); + noteEndDropdown.set(getMIDINote(end)); + learning = false; + } + + midiChannelDropdown.set(event.channel + 1); + + if (CABLES.UI) + { + gui.emitEvent("portValueEdited", op, midiChannelDropdown, midiChannelDropdown.get()); + gui.emitEvent("portValueEdited", op, learnedNotes, learnedNotes.get()); + gui.emitEvent("portValueEdited", op, learnedNotesIn, learnedNotesIn.get()); + gui.emitEvent("portValueEdited", op, noteEndDropdown, noteEndDropdown.get()); + gui.emitEvent("portValueEdited", op, noteStartDropdown, noteStartDropdown.get()); + + op.uiAttr({ "info": `Start bound to Note: ${noteStartDropdown.get()}` }); + op.uiAttr({ "info": `End bound to Note: ${noteEndDropdown.get()}` }); + op.refreshParams(); + } + eventOut.set(event); + return; + } + + if (event.channel === midiChannelDropdown.get() - 1 && learnedNotes.length === 2) + { + const [start, end] = learnedNotes; + if (start <= noteIndex && noteIndex <= end) + { + if (statusByte >> 4 === NOTE_OFF || velocity === 0) + { + gateOut.set(false); + if (velocity === 0) velocityOut.set(0); + } + if (statusByte >> 4 === NOTE_ON) + { + gateOut.set(true); + + noteIndexOut.set(noteIndex); + triggerOut.trigger(); + + if (normalizeDropdown.get() === "0 to 1") + { + // (max'-min')/(max-min)*(value-min)+min' + velocityOut.set((1 / 126) * (velocity - 1)); + } + else if (normalizeDropdown.get() === "-1 to 1") + { + // (max'-min')/(max-min)*(value-min)+min' + const normalizedValue = (2 / 126) * (velocity - 1) - 1; + velocityOut.set(normalizedValue); + } + else if (normalizeDropdown.get() === "none") velocityOut.set(velocity); + } + } + } + + eventOut.set(event); +}; + + +}; + +Ops.Devices.Midi.MidiNoteFilter.prototype = new CABLES.Op(); +CABLES.OPS["b248a588-81cc-47af-a65b-36509abd2888"]={f:Ops.Devices.Midi.MidiNoteFilter,objName:"Ops.Devices.Midi.MidiNoteFilter"}; + + + + +// ************************************************************** +// +// Ops.Devices.Midi.MidiNoteOut +// +// ************************************************************** + +Ops.Devices.Midi.MidiNoteOut = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const MIDIChannels = Array.from(Array(16).keys(), (i) => { return i + 1; }); +const NOTE_VALUES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]; + +const clamp = (val, min, max) => { return Math.min(Math.max(val, min), max); }; +const NOTE_OFF = 0x8; +const NOTE_ON = 0x9; + +function getMIDINote(dataByte1LSB) +{ + return dataByte1LSB <= 126 + ? `${NOTE_VALUES[dataByte1LSB % 12]}${Math.floor(dataByte1LSB / 12) - 2} - ${dataByte1LSB}` + : "NO NOTE"; +} + +const noteValues = Array.from(Array(128).keys(), (key) => { return getMIDINote(key); }); +const velocityArray = Array.from(Array(128).keys(), (key) => { return 0; }); + +const inChannel = op.inDropDown("MIDI Channel", MIDIChannels, "1"); +const inNoteDropdown = op.inDropDown("Note", noteValues); +const inNoteNumber = op.inInt("Note Number", 0); +const inVelocity = op.inInt("Velocity", 0); +const inMin = op.inFloat("Min In Velocity", 0); +const inMax = op.inFloat("Max In Velocity", 1); +const inNoteArray = op.inArray("Velocity Array In"); +op.setPortGroup("General", [inChannel, inNoteDropdown]); +op.setPortGroup("Note", [inNoteNumber, inVelocity]); +op.setPortGroup("Velocity Range", [inMin, inMax]); + +const outEvent = op.outObject("MIDI Event Out"); + +// this is a safety mechanism for when changing a note while another one is playing, kill old one +let currentNote = null; +const killAllNotes = () => +{ + for (let i = 0; i < 128; i += 1) + { + outEvent.set(null); + outEvent.set({ "data": [(NOTE_OFF << 4 | (inChannel.get() - 1)), i, 0] }); + } +}; + +const killLastNote = () => +{ + outEvent.set(null); + outEvent.set({ "data": [(NOTE_OFF << 4 | (inChannel.get() - 1)), currentNote, 0] }); +}; + +inNoteNumber.onLinkChanged = function () +{ + if (!inNoteNumber.isLinked()) killLastNote(); +}; + +inVelocity.onLinkChanged = function () +{ + if (!inVelocity.isLinked()) killAllNotes(); +}; + +inNoteArray.onLinkChanged = function () +{ + if (!inNoteArray.isLinked()) killAllNotes(); +}; + +inNoteDropdown.onChange = inChannel.onChange = killLastNote; + +inNoteNumber.onChange = inVelocity.onChange = function () +{ + /* if (!inNoteDropdown.get()) { + // if (!op.uiAttribs.error) op.uiAttr({ error: "Please choose a MIDI Note!" }); + return; + } + */ + // if (op.uiAttribs.error) op.uiAttr({ error: null }); + + const val = inVelocity.get(); + const noteNumber = inNoteNumber.get(); + const velocity = Math.floor(CABLES.map(val, inMin.get(), inMax.get(), 0, 127)); + + let noteIndex = Math.floor(clamp(noteNumber, 0, 127)); + + if (inNoteDropdown.get() !== 0) noteIndex = clamp(Number(inNoteDropdown.get().split("-").pop()), 0, 127); + + else + { + if (currentNote) + { + if (noteIndex !== currentNote) + { + const killEvent = { + "deviceName": null, + "output": null, + "inputId": 0, + "messageType": "Note", + "data": [(NOTE_OFF << 4 | (inChannel.get() - 1)), currentNote, 0], + "index": currentNote, + "value": 0, + "newNote": [currentNote, getMIDINote(currentNote)], + "velocity": 0, + "channel": inChannel.get() - 1, + }; + outEvent.set(null); + outEvent.set(killEvent); + } + } + } + + const data = velocity > 0 ? + [(NOTE_ON << 4 | (inChannel.get() - 1)), noteIndex, velocity] + : [(NOTE_OFF << 4 | (inChannel.get() - 1)), noteIndex, velocity]; + + const event = { + "deviceName": null, + "output": null, + "inputId": 0, + "messageType": "Note", + "data": data, + "index": noteIndex, + "value": velocity, + "newNote": [noteIndex, getMIDINote(noteIndex)], + velocity, + "channel": inChannel.get() - 1, + }; + + outEvent.set(null); + outEvent.set(event); + currentNote = noteIndex; +}; +let oldArr = []; + +inNoteArray.onChange = function () +{ + if (!inNoteArray.get()) return; + const arr = inNoteArray.get(); + const length = arr.length > 127 ? 128 : arr.length; + + for (let i = 0; i < length; i += 1) + { + const velocity = Math.floor(CABLES.map(arr[i], inMin.get(), inMax.get(), 0, 127)); + const event = { + "deviceName": null, + "output": null, + "inputId": 0, + "messageType": "Note", + "data": velocity > 0 ? + [(NOTE_ON << 4 | (inChannel.get() - 1)), i, velocity] + : [(NOTE_OFF << 4 | (inChannel.get() - 1)), i, velocity], + "index": i, + "value": velocity, + "newNote": [i, getMIDINote(i)], + velocity, + "channel": inChannel.get() - 1, + }; + + oldArr = arr; + outEvent.set(null); + outEvent.set(event); + } +}; + + +}; + +Ops.Devices.Midi.MidiNoteOut.prototype = new CABLES.Op(); +CABLES.OPS["172dcd08-cd5b-4272-bc7d-2b1a61ecfd4a"]={f:Ops.Devices.Midi.MidiNoteOut,objName:"Ops.Devices.Midi.MidiNoteOut"}; + + + + +// ************************************************************** +// +// Ops.Devices.Midi.MidiOutputDevice +// +// ************************************************************** + +Ops.Devices.Midi.MidiOutputDevice = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// your new op +// have a look at the documentation at: +// https://docs.cables.gl/dev_hello_op/dev_hello_op.html +const CC_STATUS_BYTE = 0xb; +const NOTE_OFF = 0x8; + +let midi = null; +let outputDevice = null; + +const inDeviceSelect = op.inValueSelect("Device", ["none"]); +const inNote = op.inObject("Note"); +const inCC = op.inObject("CC"); +const inNRPN = op.inObject("NRPN"); + +op.setPortGroup("Device", [inDeviceSelect]); +op.setPortGroup("Midi Events", [inNote, inCC, inNRPN]); + + +inNRPN.onChange = function (_event) +{ + if (!outputDevice) return; + if (!_event) return; + + const event = _event.get(); + + if (!event) return; + if (!event.data) return; + if (event.messageType !== "NRPN") return; + + const indexLSB = (event.nrpnIndex & 0b1111111); + const indexMSB = (event.nrpnIndex >> 7); + + const valueLSB = (event.nrpnValue & 0b1111111); + const valueMSB = (event.nrpnValue >> 7); + + const dataIndexLSB = [CC_STATUS_BYTE << 4 | event.channel, 98, indexLSB]; + const dataIndexMSB = [CC_STATUS_BYTE << 4 | event.channel, 99, indexMSB]; + + const dataValueLSB = [CC_STATUS_BYTE << 4 | event.channel, 38, valueLSB]; + const dataValueMSB = [CC_STATUS_BYTE << 4 | event.channel, 6, valueMSB]; + + outputDevice.send(dataIndexLSB); + outputDevice.send(dataIndexMSB); + outputDevice.send(dataValueLSB); + outputDevice.send(dataValueMSB); +}; + +inCC.onChange = function (_event) +{ + if (!outputDevice) return; + if (!_event) return; + + const event = _event.get(); + + if (!event) return; + if (!event.data) return; + if (event.messageType !== "CC") return; + // TODO: Check for invalid status bytes + outputDevice.send(event.data); +}; + +let currentNote = null; +let currentChannel = null; + +const killLastNote = () => +{ + if (!outputDevice || !currentNote || !currentChannel) return; + outputDevice.send([(NOTE_OFF << 4 | (currentChannel)), currentNote, 0]); +}; + +const killAllNotes = () => +{ + if (!outputDevice) return; + for (let i = 0; i < 128; i += 1) + { + for (let channel = 0; channel < 16; channel += 1) outputDevice.send([(NOTE_OFF << 4 | channel), i, 0]); + } +}; + +inNote.onLinkChanged = function () +{ + if (!inNote.isLinked()) killAllNotes(); +}; + +inNote.onChange = function (_event) +{ + if (!outputDevice) return; + if (!_event) return; + + const event = _event.get(); + + if (!event) return; + if (!event.data) return; + // TODO: let CC all notes off message pass through + // if (event.messageType !== "Note") return; + // TODO: Check for invalid status bytes + + setTimeout(function () + { + outputDevice.send(event.data); + currentNote = event.index; + currentChannel = event.channel; + }, 20); +}; + +function setDevice() +{ + if (!midi || !midi.inputs) return; + const name = inDeviceSelect.get(); + + op.setTitle(`Midi ${name}`); + + const inputs = midi.inputs.values(); + const outputs = midi.outputs.values(); + + for (let output = outputs.next(); output && !output.done; output = outputs.next()) + { + if (output.value.name === name) + { + outputDevice = midi.outputs.get(output.value.id); + } + } +} + + +function onMIDIFailure() +{ + op.uiAttr({ "warning": "No MIDI support in your browser." }); +} + +function onMIDISuccess(midiAccess) +{ + midi = midiAccess; + const inputs = midi.inputs.values(); + const outputs = midi.outputs.values(); + op.uiAttr({ "info": "no midi devices found" }); + + const deviceNames = []; + + for (let output = outputs.next(); output && !output.done; output = outputs.next()) + { + deviceNames.push(output.value.name); + } + + inDeviceSelect.uiAttribs.values = deviceNames; + + op.refreshParams(); + setDevice(); +} + +inDeviceSelect.onChange = setDevice; + +if (navigator.requestMIDIAccess) +{ + navigator.requestMIDIAccess({ "sysex": false }).then(onMIDISuccess, onMIDIFailure); +} +else onMIDIFailure(); + + +}; + +Ops.Devices.Midi.MidiOutputDevice.prototype = new CABLES.Op(); +CABLES.OPS["a874a81a-4416-4ed5-bea9-66531ed83376"]={f:Ops.Devices.Midi.MidiOutputDevice,objName:"Ops.Devices.Midi.MidiOutputDevice"}; + + + + +// ************************************************************** +// +// Ops.Devices.Midi.MidiTranspose +// +// ************************************************************** + +Ops.Devices.Midi.MidiTranspose = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const NOTE_VALUES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]; + +const MIDIChannels = Array.from(Array(16).keys()).map((i) => { return i + 1; }); +const NOTE_OFF = 0x8; +const NOTE_ON = 0x9; +const CC_MSG = 0xb; +function getMIDINote(dataByte1LSB) +{ + return dataByte1LSB <= 126 + ? `${NOTE_VALUES[dataByte1LSB % 12]}${Math.floor(dataByte1LSB / 12) - 2} - ${dataByte1LSB}` + : "NO NOTE"; +} + +/* IN */ +const inEvent = op.inObject("MIDI Event In"); +const midiChannelDropdown = op.inValueSelect("MIDI Channel", MIDIChannels, 1); +const inTranspose = op.inInt("Transpose Amount", 0); +const learn = op.inTriggerButton("learn"); + +op.setPortGroup("MIDI", [inEvent, midiChannelDropdown, learn]); +op.setPortGroup("Transpose", [inTranspose]); + +/* OUT */ +/* OUT */ +const eventOut = op.outObject("MIDI Event Out"); +const triggerOut = op.outTrigger("Trigger Out"); + +const killAllNotes = () => +{ + for (let i = 0; i < 128; i += 1) + { + for (let channel = 0; channel < 16; channel += 1) + { + eventOut.set(null); + eventOut.set({ "data": [(NOTE_OFF << 4 | channel), i, 0] }); + } + op.log("killAllNotes transpose"); + } +}; + +const killAllNotesAgain = () => +{ + for (let channel = 0; channel < 16; channel += 1) + { + eventOut.set(null); + eventOut.set({ "data": [(CC_MSG << 4 | channel), 123, 0] }); + } +}; +inTranspose.onChange = function () +{ + killAllNotesAgain(); + if (lastTransposedNote) + { + // eventOut.set(null); + // eventOut.set({ data: [(NOTE_OFF << 4 | lastTransposedNote.channel), lastTransposedNote.index, 0] }); + } +}; +let lastTransposedNote = null; + +let learning = false; +learn.onTriggered = () => +{ + learning = true; +}; + +inEvent.onChange = () => +{ + const event = inEvent.get(); + + if (!event) return; + if (event.messageType !== "Note") return; + if (!event.newNote) return; + + if (learning) + { + midiChannelDropdown.set(event.channel + 1); + learning = false; + if (CABLES.UI) + { + op.uiAttr({ "info": `bound to MIDI Channel: ${midiChannelDropdown.get()}` }); + op.refreshParams(); + } + } + + if (event.channel === midiChannelDropdown.get() - 1) + { + const newEvent = { ...event }; + + const note = event.index; + const transposeAmount = inTranspose.get(); + const newNoteIndex = Math.min(Math.max(note + transposeAmount, 0), 127); + + if (event.data[0] === (NOTE_ON << 4 | (event.channel))) + { + eventOut.set(null); + eventOut.set({ ...newEvent, + "data": [(NOTE_OFF << 4 | (event.channel)), note, 0], + "note": note, + "index": note, + "velocity": 0, + "newNote": [note, getMIDINote(note)], }); + } + + newEvent.note = newNoteIndex; + newEvent.index = newNoteIndex; + newEvent.data[1] = newNoteIndex; + newEvent.newNote = [newNoteIndex, getMIDINote(newNoteIndex)]; + + lastTransposedNote = newEvent; + + eventOut.set(newEvent); + } + else + { + eventOut.set(event); + } + triggerOut.trigger(); +}; + + +}; + +Ops.Devices.Midi.MidiTranspose.prototype = new CABLES.Op(); +CABLES.OPS["c3b01c76-a300-44d3-8e1a-c8ae7a776463"]={f:Ops.Devices.Midi.MidiTranspose,objName:"Ops.Devices.Midi.MidiTranspose"}; + + + + +// ************************************************************** +// +// Ops.Devices.Midi.MidiValueToNote_v2 +// +// ************************************************************** + +Ops.Devices.Midi.MidiValueToNote_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let midiValuePort = op.inValue("Midi Value"); +let notePort = op.outString("Note"); + +let FLATS = "C Db D Eb E F Gb G Ab A Bb B".split(" "); +let SHARPS = "C C# D D# E F F# G G# A A# B".split(" "); + +function note(num, sharps) +{ + if (num === true || num === false) return function (m) { return note(m, num); }; + num = Math.round(num); + let pcs = sharps === true ? SHARPS : FLATS; + let pc = pcs[num % 12]; + let o = Math.floor(num / 12) - 1; + return pc + o; +} + +midiValuePort.onChange = function () +{ + let val = midiValuePort.get(); + if (val) + { + let n = note(val, true); + notePort.set(n); + } +}; + + +}; + +Ops.Devices.Midi.MidiValueToNote_v2.prototype = new CABLES.Op(); +CABLES.OPS["6f9cc2b3-8dba-44de-a677-a0706952a64c"]={f:Ops.Devices.Midi.MidiValueToNote_v2,objName:"Ops.Devices.Midi.MidiValueToNote_v2"}; + + + + +// ************************************************************** +// +// Ops.Devices.Mobile.DeviceVibrate +// +// ************************************************************** + +Ops.Devices.Mobile.DeviceVibrate = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let inVibrate = op.inTriggerButton("Vibrate"); +let outSupported = op.outBoolNum("Supported"); + +navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || +navigator.mozVibrate || navigator.msVibrate; + +if (navigator.vibrate) outSupported.set(true); +else outSupported.set(false); + +inVibrate.onTriggered = function () +{ + if (navigator.vibrate) + { + navigator.vibrate(1500); + } +}; + +if (window.self !== window.top) +{ + op.setUiError("iframe", "DeviceVibrate does not work in an iframe, open the patch without an iframe to get it to work", 1); + op.warn("DeviceVibrate does not work in an iframe, open the patch without an iframe to get it to work"); +} + + +}; + +Ops.Devices.Mobile.DeviceVibrate.prototype = new CABLES.Op(); +CABLES.OPS["e947fc63-e44e-4bdd-98e0-89e79373f073"]={f:Ops.Devices.Mobile.DeviceVibrate,objName:"Ops.Devices.Mobile.DeviceVibrate"}; + + + + +// ************************************************************** +// +// Ops.Devices.Mobile.GeoLocation +// +// ************************************************************** + +Ops.Devices.Mobile.GeoLocation = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + outSupported = op.outBoolNum("Browser Support", navigator.geolocation != false), + outLat = op.outNumber("Latitude"), + outLon = op.outNumber("Longitude"), + outData = op.outObject("Data"); + +if (navigator.geolocation && navigator.geolocation.watchPosition) + navigator.geolocation.watchPosition(updatePos); + +function updatePos(position) +{ + outLat.set(position.coords.latitude); + outLon.set(position.coords.longitude); + outData.set(position); +} + + +}; + +Ops.Devices.Mobile.GeoLocation.prototype = new CABLES.Op(); +CABLES.OPS["7d9ae643-d011-417e-afe3-b3acb78a6d63"]={f:Ops.Devices.Mobile.GeoLocation,objName:"Ops.Devices.Mobile.GeoLocation"}; + + + + +// ************************************************************** +// +// Ops.Devices.Mobile.LockOrientation +// +// ************************************************************** + +Ops.Devices.Mobile.LockOrientation = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inPortrait = op.inValueBool("Portrait"); +const inLandscape = op.inValueBool("Landscape"); + +screen.lockOrientationUniversal = screen.lockOrientation || screen.mozLockOrientation || screen.msLockOrientation; + +const support = op.outBoolNum("Supported", screen.lockOrientationUniversal !== undefined); +const locked = op.outBoolNum("Locked"); + +inPortrait.onChange = setup; +inLandscape.onChange = setup; + +function setup() +{ + if (screen.lockOrientationUniversal) + { + let orientations = []; + if (inPortrait.get())orientations.push("portrait"); + if (inLandscape.get())orientations.push("landscape"); + + if (screen.lockOrientationUniversal(orientations)) locked.set(true); + else locked.set(false); + } + locked.set(false); +} + + +}; + +Ops.Devices.Mobile.LockOrientation.prototype = new CABLES.Op(); +CABLES.OPS["486d5713-5292-47af-bbd3-df81fb7cd3ca"]={f:Ops.Devices.Mobile.LockOrientation,objName:"Ops.Devices.Mobile.LockOrientation"}; + + + + +// ************************************************************** +// +// Ops.Devices.Mobile.MotionSensor_v2 +// +// ************************************************************** + +Ops.Devices.Mobile.MotionSensor_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + mulAxis = op.inValue("Mul Orientation", 1), + req = op.inTrigger("Request Permissions"), + axis1 = op.outNumber("Orientation Alpha"), + axis2 = op.outNumber("Orientation Beta"), + axis3 = op.outNumber("Orientation Gamma"), + accX = op.outNumber("Acceleration X"), + accY = op.outNumber("Acceleration Y"), + accZ = op.outNumber("Acceleration Z"), + accNoGravX = op.outNumber("Acceleration X no gravity"), + accNoGravY = op.outNumber("Acceleration Y no gravity"), + accNoGravZ = op.outNumber("Acceleration Z no gravity"), + + rotRate1 = op.outNumber("Rotation Rate Alpha"), + rotRate2 = op.outNumber("Rotation Rate Beta"), + rotRate3 = op.outNumber("Rotation Rate Gamma"), + + outObj = op.outObject("Object"); + +let lastTime = 0; +let lastTimeAcc = 0; +let obj = {}; + +function handleDeviceMotion(event) +{ + if (CABLES.now() - lastTimeAcc > 15) + { + lastTimeAcc = CABLES.now(); + + accX.set(event.accelerationIncludingGravity.x || 0); + accY.set(event.accelerationIncludingGravity.y || 0); + accZ.set(event.accelerationIncludingGravity.z || 0); + + accNoGravX.set(event.acceleration.x || 0); + accNoGravY.set(event.acceleration.y || 0); + accNoGravZ.set(event.acceleration.z || 0); + + obj.AccelerationX = accX.get(); + obj.AccelerationY = accY.get(); + obj.AccelerationZ = accZ.get(); + + rotRate1.set(event.rotationRate.alpha || 0); + rotRate2.set(event.rotationRate.beta || 0); + rotRate3.set(event.rotationRate.gamma || 0); + + outObj.set(null); + outObj.set(obj); + } +} + +function handleDeviceOrientation(event) +{ + if (CABLES.now() - lastTime > 15) + { + lastTime = CABLES.now(); + axis1.set((event.alpha || 0) * mulAxis.get()); + axis2.set((event.beta || 0) * mulAxis.get()); + axis3.set((event.gamma || 0) * mulAxis.get()); + + obj.OrientationAlpha = axis1.get(); + obj.OrientationBeta = axis2.get(); + obj.OrientationGamma = axis3.get(); + + outObj.set(null); + outObj.set(obj); + } +} + +req.onTriggered = function () +{ + if (window.DeviceMotionEvent && window.DeviceMotionEvent.requestPermission) + { + window.DeviceMotionEvent.requestPermission() + .then((response) => + { + if (response == "granted") + { + window.addEventListener("devicemotion", handleDeviceMotion, true); + } + else + console.log(response); + }) + .catch((e) => + { + console.log(e); + }); + + window.DeviceOrientationEvent.requestPermission() + .then((response) => + { + if (response == "granted") + { + window.addEventListener("deviceorientation", handleDeviceOrientation, true); + } + else + console.log(response); + }) + .catch((e) => + { + console.log(e); + }); + } + else + { + window.addEventListener("devicemotion", handleDeviceMotion, true); + window.addEventListener("deviceorientation", handleDeviceOrientation, true); + } +}; + +if (window.self !== window.top) +{ + op.setUiError("iframe", "MotionSensor does not work in an iframe, open the patch without an iframe to get it to work", 1); + op.warn("MotionSensor does not work in an iframe, open the patch without an iframe to get it to work"); +} + + +}; + +Ops.Devices.Mobile.MotionSensor_v2.prototype = new CABLES.Op(); +CABLES.OPS["f4102f07-e5ff-4c1e-ac5b-6a4758b81727"]={f:Ops.Devices.Mobile.MotionSensor_v2,objName:"Ops.Devices.Mobile.MotionSensor_v2"}; + + + + +// ************************************************************** +// +// Ops.Devices.Mobile.Pinch +// +// ************************************************************** + +Ops.Devices.Mobile.Pinch = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// constants +const elId = "glcanvas"; +const initialScale = 1.0; + +// inputs +const enabledPort = op.inValueBool("Enabled", true); +const minScalePort = op.inValue("Min Scale", 0.0); +const maxScalePort = op.inValue("Max Scale", 4.0); +const resetScalePort = op.inTriggerButton("Reset Scale"); +const inLimit = op.inBool("Limit", true); + +// variables +let scale = initialScale; +let tmpScale = initialScale; +let pinchInProgress = false; + +// setup +const el = document.getElementById(elId); +const hammertime = new Hammer(el); +hammertime.get("pinch").set({ "enable": true }); + +// outputs +const scalePort = op.outNumber("Scale", 1); +const eventPort = op.outObject("Event Details"); +const outDelta = op.outNumber("Delta"); + +// change listeners +window.addEventListener("gesturestart", (e) => { return e.preventDefault(); }); +window.addEventListener("gesturechange", (e) => { return e.preventDefault(); }); +window.addEventListener("gestureend", (e) => { return e.preventDefault(); }); + +hammertime.on("pinch", function (ev) +{ + op.log(ev.additionalEvent); + ev.preventDefault(); // this is ignored in some browsers + if (!enabledPort.get()) { return; } + + // if(ev.isFinal || ev.isFirst) { op.log(ev); } + + tmpScale = ev.scale; + pinchInProgress = true; + + // if(ev.isFinal || !ev.isFinal && pinchInProgress) { + const oldScale = scale; + outDelta.set(0); + + if (ev.isFinal) + { + scale *= tmpScale; + scale = checkAndCorrectBoundaries(scale); + + scalePort.set(scale); + pinchInProgress = false; + op.log("Final Pinch detected, resetting"); + tmpScale = initialScale; + } + else + { + scalePort.set(checkAndCorrectBoundaries(scale * tmpScale)); + } + + let d = oldScale - scalePort.get(); + if (d < 0) d = -1; + else if (d > 0) d = 1; + + outDelta.set(d); + + // if(ev.additionalEvent) { + /* + if(ev.additionalEvent === 'pinchin') { + scale -= Math.abs(ev.velocity); + } else if (ev.additionalEvent === 'pinchout') { + scale += Math.abs(ev.velocity); + } + */ + // } + // scale += ev.velocity; + /* + op.log('ev.scale: ', ev.scale); + tmpScale = ev.scale; + + var scaleToSet; + if(ev.isFinal) { + scale *= tmpScale; + scaleToSet = scale; + tmpScale = initialScale; + } else { + scaleToSet = scale * tmpScale; + } + + op.log('scaleToSet', scaleToSet); + + scale = checkAndCorrectBoundaries(scale); + scaleToSet = checkAndCorrectBoundaries(scaleToSet); + + scalePort.set(scaleToSet); + */ +}); + +el.addEventListener("touchend", function (ev) +{ + op.log("touchend"); + if (pinchInProgress) + { + op.log("touchend, setting manually"); + ev.preventDefault(); // this is ignored in some browsers + ev.stopPropagation(); + pinchInProgress = false; + scale *= tmpScale; + scale = checkAndCorrectBoundaries(scale); + tmpScale = initialScale; + scalePort.set(scale); + } +}); + +function checkAndCorrectBoundaries(s) +{ + let correctedS = s; + + if (inLimit.get()) + { + if (s < minScalePort.get()) + { + correctedS = minScalePort.get(); + } + else if (s > maxScalePort.get()) + { + correctedS = maxScalePort.get(); + } + } + return correctedS; +} + +resetScalePort.onTriggered = reset; + +// functions + +function reset() +{ + scale = initialScale; + scalePort.set(scale); +} + + +}; + +Ops.Devices.Mobile.Pinch.prototype = new CABLES.Op(); +CABLES.OPS["98e19e37-88ca-4c07-bed7-a050dac31e3a"]={f:Ops.Devices.Mobile.Pinch,objName:"Ops.Devices.Mobile.Pinch"}; + + + + +// ************************************************************** +// +// Ops.Devices.Mobile.ScreenOrientation +// +// ************************************************************** + +Ops.Devices.Mobile.ScreenOrientation = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + angle = op.outNumber("Angle"), + str = op.outString("Description"); + +let count = 0; +window.addEventListener("resize", onOrientationChange, false); +window.addEventListener("orientationchange", onOrientationChange, false); + +onOrientationChange(); + +if (screen && screen.orientation) +{ + screen.orientation.addEventListener("change", onOrientationChange); +} + +function onOrientationChange() +{ + count++; + if (!screen.orientation) return; + if (screen.orientation.hasOwnProperty("angle"))angle.set(screen.orientation.angle); + let s = screen.orientation.type + " #" + count + " WINORIENT:" + window.orientation; + str.set(s); +} + +op.onDelete = function () +{ + window.removeEventListener("resize", onOrientationChange); + window.removeEventListener("orientationchange", onOrientationChange); +}; + + +}; + +Ops.Devices.Mobile.ScreenOrientation.prototype = new CABLES.Op(); +CABLES.OPS["ef8f5f5a-4652-4fad-983b-aca96d9cc13b"]={f:Ops.Devices.Mobile.ScreenOrientation,objName:"Ops.Devices.Mobile.ScreenOrientation"}; + + + + +// ************************************************************** +// +// Ops.Devices.Mouse.MouseButtons +// +// ************************************************************** + +Ops.Devices.Mouse.MouseButtons = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + mouseClickLeft = op.outTrigger("Click Left"), + mouseClickRight = op.outTrigger("Click Right"), + mouseDoubleClick = op.outTrigger("Double Click"), + mouseDownLeft = op.outBoolNum("Button pressed Left", false), + mouseDownMiddle = op.outBoolNum("Button pressed Middle", false), + mouseDownRight = op.outBoolNum("Button pressed Right", false), + triggerMouseDownLeft = op.outTrigger("Mouse Down Left"), + triggerMouseDownMiddle = op.outTrigger("Mouse Down Middle"), + triggerMouseDownRight = op.outTrigger("Mouse Down Right"), + triggerMouseUpLeft = op.outTrigger("Mouse Up Left"), + triggerMouseUpMiddle = op.outTrigger("Mouse Up Middle"), + triggerMouseUpRight = op.outTrigger("Mouse Up Right"), + area = op.inValueSelect("Area", ["Canvas", "Document"], "Canvas"), + active = op.inValueBool("Active", true); + +const cgl = op.patch.cgl; +let listenerElement = null; +area.onChange = updateListeners; +op.onDelete = removeListeners; +updateListeners(); + +function onMouseDown(e) +{ + if (e.which == 1) + { + mouseDownLeft.set(true); + triggerMouseDownLeft.trigger(); + } + else if (e.which == 2) + { + mouseDownMiddle.set(true); + triggerMouseDownMiddle.trigger(); + } + else if (e.which == 3) + { + mouseDownRight.set(true); + triggerMouseDownRight.trigger(); + } +} + +function onMouseUp(e) +{ + if (e.which == 1) + { + mouseDownLeft.set(false); + triggerMouseUpLeft.trigger(); + } + else if (e.which == 2) + { + mouseDownMiddle.set(false); + triggerMouseUpMiddle.trigger(); + } + else if (e.which == 3) + { + mouseDownRight.set(false); + triggerMouseUpRight.trigger(); + } +} + +function onClickRight(e) +{ + mouseClickRight.trigger(); + e.preventDefault(); +} + +function onDoubleClick(e) +{ + mouseDoubleClick.trigger(); +} + +function onmouseclick(e) +{ + mouseClickLeft.trigger(); +} + +function ontouchstart(event) +{ + if (event.touches && event.touches.length > 0) + { + event.touches[0].which = 1; + onMouseDown(event.touches[0]); + } +} + +function ontouchend(event) +{ + onMouseUp({ "which": 1 }); +} + +function removeListeners() +{ + if (!listenerElement) return; + listenerElement.removeEventListener("touchend", ontouchend); + listenerElement.removeEventListener("touchcancel", ontouchend); + listenerElement.removeEventListener("touchstart", ontouchstart); + listenerElement.removeEventListener("dblclick", onDoubleClick); + listenerElement.removeEventListener("click", onmouseclick); + listenerElement.removeEventListener("mousedown", onMouseDown); + listenerElement.removeEventListener("mouseup", onMouseUp); + listenerElement.removeEventListener("contextmenu", onClickRight); + listenerElement.removeEventListener("mouseleave", onMouseUp); + listenerElement = null; +} + +function addListeners() +{ + if (listenerElement)removeListeners(); + + listenerElement = cgl.canvas; + if (area.get() == "Document") listenerElement = document.body; + + listenerElement.addEventListener("touchend", ontouchend); + listenerElement.addEventListener("touchcancel", ontouchend); + listenerElement.addEventListener("touchstart", ontouchstart); + listenerElement.addEventListener("dblclick", onDoubleClick); + listenerElement.addEventListener("click", onmouseclick); + listenerElement.addEventListener("mousedown", onMouseDown); + listenerElement.addEventListener("mouseup", onMouseUp); + listenerElement.addEventListener("contextmenu", onClickRight); + listenerElement.addEventListener("mouseleave", onMouseUp); +} + +op.onLoaded = updateListeners; + +active.onChange = updateListeners; + +function updateListeners() +{ + removeListeners(); + if (active.get()) addListeners(); +} + + +}; + +Ops.Devices.Mouse.MouseButtons.prototype = new CABLES.Op(); +CABLES.OPS["c7e5e545-c8a1-4fef-85c2-45422b947f0d"]={f:Ops.Devices.Mouse.MouseButtons,objName:"Ops.Devices.Mouse.MouseButtons"}; + + + + +// ************************************************************** +// +// Ops.Devices.Mouse.MouseDrag +// +// ************************************************************** + +Ops.Devices.Mouse.MouseDrag = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + active = op.inValueBool("Active", true), + speed = op.inValue("Speed", 0.01), + inputType = op.inSwitch("Input Type", ["All", "Mouse", "Touch"], "All"), + area = op.inSwitch("Area", ["Canvas", "Document"], "Canvas"), + outDeltaX = op.outNumber("Delta X"), + outDeltaY = op.outNumber("Delta Y"), + outDragging = op.outNumber("Is Dragging"); + +let listenerElement = null; +const absoluteX = 0; +const absoluteY = 0; +let pressed = false; +let lastX = 0; +let lastY = 0; +let firstMove = true; + +area.onChange = updateArea; + +updateArea(); + +function onMouseMove(e) +{ + if (e.touches) e = e.touches[0]; + + if (pressed && e) + { + if (!firstMove) + { + outDragging.set(true); + const deltaX = (e.clientX - lastX) * speed.get(); + const deltaY = (e.clientY - lastY) * speed.get(); + + outDeltaX.set(0); + outDeltaY.set(0); + outDeltaX.set(deltaX); + outDeltaY.set(deltaY); + } + + firstMove = false; + + lastX = e.clientX; + lastY = e.clientY; + } +} + +function onMouseDown(e) +{ + try { listenerElement.setPointerCapture(e.pointerId); } + catch (_e) {} + + pressed = true; +} + +function onMouseUp(e) +{ + try { listenerElement.releasePointerCapture(e.pointerId); } + catch (e) {} + + pressed = false; + outDragging.set(false); + lastX = 0; + lastY = 0; + firstMove = true; +} + +function updateArea() +{ + removeListener(); + + if (area.get() == "Document") listenerElement = document; + else listenerElement = op.patch.cgl.canvas; + + if (active.get())addListener(); +} + +function addListener() +{ + if (!listenerElement)updateArea(); + + if (inputType.get() == "All" || inputType.get() == "Mouse") + { + listenerElement.addEventListener("mousemove", onMouseMove); + listenerElement.addEventListener("mousedown", onMouseDown); + listenerElement.addEventListener("mouseup", onMouseUp); + listenerElement.addEventListener("mouseenter", onMouseUp); + listenerElement.addEventListener("mouseleave", onMouseUp); + } + + if (inputType.get() == "All" || inputType.get() == "Touch") + { + listenerElement.addEventListener("touchmove", onMouseMove); + listenerElement.addEventListener("touchend", onMouseUp); + listenerElement.addEventListener("touchstart", onMouseDown); + } +} + +function removeListener() +{ + if (!listenerElement) return; + listenerElement.removeEventListener("mousemove", onMouseMove); + listenerElement.removeEventListener("mousedown", onMouseDown); + listenerElement.removeEventListener("mouseup", onMouseUp); + listenerElement.removeEventListener("mouseenter", onMouseUp); + listenerElement.removeEventListener("mouseleave", onMouseUp); + + listenerElement.removeEventListener("touchmove", onMouseMove); + listenerElement.removeEventListener("touchend", onMouseUp); + listenerElement.removeEventListener("touchstart", onMouseDown); +} + +active.onChange = function () +{ + if (active.get())addListener(); + else removeListener(); +}; + +op.onDelete = function () +{ + removeListener(); +}; + + +}; + +Ops.Devices.Mouse.MouseDrag.prototype = new CABLES.Op(); +CABLES.OPS["5103d14e-2f21-4f43-ae91-c1b55a944226"]={f:Ops.Devices.Mouse.MouseDrag,objName:"Ops.Devices.Mouse.MouseDrag"}; + + + + +// ************************************************************** +// +// Ops.Devices.Mouse.MouseWheel_v2 +// +// ************************************************************** + +Ops.Devices.Mouse.MouseWheel_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + speed = op.inValue("Speed", 1), + preventScroll = op.inValueBool("prevent scroll", true), + flip = op.inValueBool("Flip Direction"), + inSimpleIncrement = op.inBool("Simple Delta", true), + area = op.inSwitch("Area", ["Canvas", "Document", "Parent"], "Document"), + active = op.inValueBool("active", true), + delta = op.outNumber("delta", 0), + deltaX = op.outNumber("delta X", 0), + deltaOrig = op.outNumber("browser event delta", 0), + trigger = op.outTrigger("Wheel Action"); + +const cgl = op.patch.cgl; +const value = 0; + +const startTime = CABLES.now() / 1000.0; +const v = 0; + +let dir = 1; + +let listenerElement = null; + +area.onChange = updateArea; +const vOut = 0; + +addListener(); + +const isChromium = window.chrome, + winNav = window.navigator, + vendorName = winNav.vendor, + isOpera = winNav.userAgent.indexOf("OPR") > -1, + isIEedge = winNav.userAgent.indexOf("Edge") > -1, + isIOSChrome = winNav.userAgent.match("CriOS"); + +const isWindows = window.navigator.userAgent.indexOf("Windows") != -1; +const isLinux = window.navigator.userAgent.indexOf("Linux") != -1; +const isMac = window.navigator.userAgent.indexOf("Mac") != -1; + +const isChrome = (isChromium !== null && isChromium !== undefined && vendorName === "Google Inc." && isOpera === false && isIEedge === false); +const isFirefox = navigator.userAgent.search("Firefox") > 1; + +flip.onChange = function () +{ + if (flip.get())dir = -1; + else dir = 1; +}; + +function normalizeWheel(event) +{ + let sY = 0; + + if ("detail" in event) { sY = event.detail; } + + if ("deltaY" in event) + { + sY = event.deltaY; + if (event.deltaY > 20)sY = 20; + else if (event.deltaY < -20)sY = -20; + } + return sY * dir; +} + +function normalizeWheelX(event) +{ + let sX = 0; + + if ("deltaX" in event) + { + sX = event.deltaX; + if (event.deltaX > 20)sX = 20; + else if (event.deltaX < -20)sX = -20; + } + return sX; +} + +let lastEvent = 0; + +function onMouseWheel(e) +{ + if (Date.now() - lastEvent < 10) return; + lastEvent = Date.now(); + + deltaOrig.set(e.wheelDelta || e.deltaY); + + if (e.deltaY) + { + let d = normalizeWheel(e); + if (inSimpleIncrement.get()) + { + if (d > 0)d = speed.get(); + else d = -speed.get(); + } + else d *= 0.01 * speed.get(); + + delta.set(0); + delta.set(d); + } + + if (e.deltaX) + { + let dX = normalizeWheelX(e); + dX *= 0.01 * speed.get(); + + deltaX.set(0); + deltaX.set(dX); + } + + if (preventScroll.get()) e.preventDefault(); + trigger.trigger(); +} + +function updateArea() +{ + removeListener(); + + if (area.get() == "Document") listenerElement = document; + if (area.get() == "Parent") listenerElement = cgl.canvas.parentElement; + else listenerElement = cgl.canvas; + + if (active.get())addListener(); +} + +function addListener() +{ + if (!listenerElement)updateArea(); + listenerElement.addEventListener("wheel", onMouseWheel, { "passive": false }); +} + +function removeListener() +{ + if (listenerElement) listenerElement.removeEventListener("wheel", onMouseWheel); +} + +active.onChange = function () +{ + updateArea(); +}; + + +}; + +Ops.Devices.Mouse.MouseWheel_v2.prototype = new CABLES.Op(); +CABLES.OPS["7b9626db-536b-4bb4-85c3-95401bc60d1b"]={f:Ops.Devices.Mouse.MouseWheel_v2,objName:"Ops.Devices.Mouse.MouseWheel_v2"}; + + + + +// ************************************************************** +// +// Ops.Devices.Mouse.Mouse_v3 +// +// ************************************************************** + +Ops.Devices.Mouse.Mouse_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inCoords = op.inSwitch("Coordinates", ["Pixel", "Pixel Display", "-1 to 1", "0 to 1"], "-1 to 1"), + area = op.inValueSelect("Area", ["Canvas", "Document", "Parent Element"], "Canvas"), + flipY = op.inValueBool("flip y", true), + rightClickPrevDef = op.inBool("right click prevent default", true), + touchscreen = op.inValueBool("Touch support", true), + active = op.inValueBool("Active", true), + outMouseX = op.outNumber("x", 0), + outMouseY = op.outNumber("y", 0), + mouseClick = op.outTrigger("click"), + mouseClickRight = op.outTrigger("click right"), + mouseDown = op.outBoolNum("Button is down"), + mouseOver = op.outBoolNum("Mouse is hovering"); + +const cgl = op.patch.cgl; +let normalize = 1; +let listenerElement = null; +let mouseX = cgl.canvas.width / 2; +let mouseY = cgl.canvas.height / 2; +area.onChange = addListeners; + +outMouseX.set(mouseX); +outMouseY.set(mouseY); + +inCoords.onChange = updateCoordNormalizing; +op.onDelete = removeListeners; + +addListeners(); + +function setValue(x, y) +{ + x = x || 0; + y = y || 0; + + if (normalize == 0) + { + outMouseX.set(x); + outMouseY.set(y); + } + else + if (normalize == 3) + { + outMouseX.set(x * cgl.pixelDensity); + outMouseY.set(y * cgl.pixelDensity); + } + else + { + let w = cgl.canvas.width / cgl.pixelDensity; + let h = cgl.canvas.height / cgl.pixelDensity; + if (listenerElement == document.body) + { + w = listenerElement.clientWidth / cgl.pixelDensity; + h = listenerElement.clientHeight / cgl.pixelDensity; + } + + if (normalize == 1) + { + outMouseX.set(x / w * 2.0 - 1.0); + outMouseY.set(y / h * 2.0 - 1.0); + } + if (normalize == 2) + { + outMouseX.set(x / w); + outMouseY.set(y / h); + } + } +} + +touchscreen.onChange = function () +{ + removeListeners(); + addListeners(); +}; + +active.onChange = function () +{ + if (listenerElement)removeListeners(); + if (active.get())addListeners(); +}; + +function updateCoordNormalizing() +{ + mouseX = 0; + mouseY = 0; + setValue(mouseX, mouseY); + + if (inCoords.get() == "Pixel")normalize = 0; + else if (inCoords.get() == "-1 to 1")normalize = 1; + else if (inCoords.get() == "0 to 1")normalize = 2; + else if (inCoords.get() == "Pixel CSS")normalize = 3; +} + +function onMouseEnter(e) +{ + mouseDown.set(false); + mouseOver.set(true); +} + +function onMouseDown(e) +{ + mouseDown.set(true); +} + +function onMouseUp(e) +{ + mouseDown.set(false); +} + +function onClickRight(e) +{ + mouseClickRight.trigger(); + if (rightClickPrevDef.get()) e.preventDefault(); +} + +function onmouseclick(e) +{ + mouseClick.trigger(); +} + +function onMouseLeave(e) +{ + mouseOver.set(false); + mouseDown.set(false); +} + +function setCoords(e) +{ + let x = e.clientX; + let y = e.clientY; + + if (area.get() != "Document") + { + x = e.offsetX; + y = e.offsetY; + } + + if (flipY.get()) setValue(x, listenerElement.clientHeight - y); + else setValue(x, y); +} + +function onmousemove(e) +{ + mouseOver.set(true); + setCoords(e); +} + +function ontouchmove(e) +{ + if (event.touches && event.touches.length > 0) setCoords(e.touches[0]); +} + +function ontouchstart(event) +{ + mouseDown.set(true); + + if (event.touches && event.touches.length > 0) onMouseDown(event.touches[0]); +} + +function ontouchend(event) +{ + mouseDown.set(false); + onMouseUp(); +} + +function removeListeners() +{ + if (!listenerElement) return; + listenerElement.removeEventListener("touchend", ontouchend); + listenerElement.removeEventListener("touchstart", ontouchstart); + listenerElement.removeEventListener("touchmove", ontouchmove); + + listenerElement.removeEventListener("click", onmouseclick); + listenerElement.removeEventListener("mousemove", onmousemove); + listenerElement.removeEventListener("mouseleave", onMouseLeave); + listenerElement.removeEventListener("mousedown", onMouseDown); + listenerElement.removeEventListener("mouseup", onMouseUp); + listenerElement.removeEventListener("mouseenter", onMouseEnter); + listenerElement.removeEventListener("contextmenu", onClickRight); + listenerElement = null; +} + +function addListeners() +{ + if (listenerElement || !active.get())removeListeners(); + if (!active.get()) return; + + listenerElement = cgl.canvas; + if (area.get() == "Document") listenerElement = document.body; + if (area.get() == "Parent Element") listenerElement = cgl.canvas.parentElement; + + if (touchscreen.get()) + { + listenerElement.addEventListener("touchend", ontouchend); + listenerElement.addEventListener("touchstart", ontouchstart); + listenerElement.addEventListener("touchmove", ontouchmove); + } + + listenerElement.addEventListener("mousemove", onmousemove); + listenerElement.addEventListener("mouseleave", onMouseLeave); + listenerElement.addEventListener("mousedown", onMouseDown); + listenerElement.addEventListener("mouseup", onMouseUp); + listenerElement.addEventListener("mouseenter", onMouseEnter); + listenerElement.addEventListener("contextmenu", onClickRight); + listenerElement.addEventListener("click", onmouseclick); +} + + +}; + +Ops.Devices.Mouse.Mouse_v3.prototype = new CABLES.Op(); +CABLES.OPS["6d1edbc0-088a-43d7-9156-918fb3d7f24b"]={f:Ops.Devices.Mouse.Mouse_v3,objName:"Ops.Devices.Mouse.Mouse_v3"}; + + + + +// ************************************************************** +// +// Ops.Devices.TouchGesture +// +// ************************************************************** + +Ops.Devices.TouchGesture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// inputs +const inEnabled = op.inBool("Active", true); +let enableVerticalSwipePort = op.inValueBool("Vertical Swipe", true); +let enableVerticalPanPort = op.inValueBool("Vertical Pan", true); + +// outputs +let pressPort = op.outTrigger("Press"); +let pressUpPort = op.outTrigger("Press Up"); +let panLeftPort = op.outTrigger("Pan Left"); +let panRightPort = op.outTrigger("Pan Right"); +let swipeLeftPort = op.outTrigger("Swipe Left"); +let swipeRightPort = op.outTrigger("Swipe Right"); +let swipeUpPort = op.outTrigger("Swipe Up"); +let swipeDownPort = op.outTrigger("Swipe Down"); +let eventPort = op.outObject("Event"); + +let canvas = op.patch.cgl.canvas; + +// create a simple instance +// by default, it only adds horizontal recognizers +let mc = new Hammer(canvas); + +// change listeners +enableVerticalSwipePort.onChange = onEnableVerticalSwipePortChange; +enableVerticalPanPort.onChange = onEnableVerticalPanPortChange; + +// init +onEnableVerticalSwipePortChange(); +onEnableVerticalPanPortChange(); + +function onEnableVerticalSwipePortChange() +{ + let direction = Hammer.DIRECTION_HORIZONTAL; + if (enableVerticalSwipePort.get()) + { + direction = Hammer.DIRECTION_ALL; + } + mc.get("swipe").set({ "direction": direction }); +} + +function onEnableVerticalPanPortChange() +{ + let direction = Hammer.DIRECTION_HORIZONTAL; + if (enableVerticalPanPort.get()) + { + direction = Hammer.DIRECTION_ALL; + } + mc.get("pan").set({ "direction": direction }); +} + +/* +mc.on("panleft panright tap press", function(ev) { + myElement.textContent = ev.type +" gesture detected."; +}); +*/ + +mc.on("panleft", onPanLeft); +mc.on("panright", onPanRight); +mc.on("swipeleft", onSwipeLeft); +mc.on("swiperight", onSwipeRight); +mc.on("swipeup", onSwipeUp); +mc.on("swipedown", onSwipeDown); +mc.on("press", onPress); +mc.on("pressup", onPressUp); + +function onPress(ev) +{ + if (!inEnabled.get()) return; + eventPort.set(ev); + pressPort.trigger(); +} + +function onPressUp(ev) +{ + if (!inEnabled.get()) return; + eventPort.set(ev); + pressUpPort.trigger(); +} + +function onPanLeft(ev) +{ + if (!inEnabled.get()) return; + eventPort.set(ev); + panLeftPort.trigger(); +} + +function onPanRight(ev) +{ + if (!inEnabled.get()) return; + eventPort.set(ev); + panRightPort.trigger(); +} + +function onSwipeLeft(ev) +{ + if (!inEnabled.get()) return; + eventPort.set(ev); + swipeLeftPort.trigger(); +} + +function onSwipeRight(ev) +{ + if (!inEnabled.get()) return; + eventPort.set(ev); + swipeRightPort.trigger(); +} + +function onSwipeUp(ev) +{ + if (!inEnabled.get()) return; + eventPort.set(ev); + swipeUpPort.trigger(); +} + +function onSwipeDown(ev) +{ + if (!inEnabled.get()) return; + eventPort.set(ev); + swipeDownPort.trigger(); +} + +/* +// By default it adds a set of tap, doubletap, press, +// horizontal pan and swipe, and the multi-touch pinch +// and rotate recognizers. The pinch and rotate recognizers +// are disabled by default because they would make the +// element blocking, but you can enable them by calling: +hammertime.get('pinch').set({ enable: true }); +hammertime.get('rotate').set({ enable: true }); + +// Enabling vertical or all directions for the pan and swipe recognizers: +hammertime.get('pan').set({ direction: Hammer.DIRECTION_ALL }); +hammertime.get('swipe').set({ direction: Hammer.DIRECTION_VERTICAL }); +*/ + + +}; + +Ops.Devices.TouchGesture.prototype = new CABLES.Op(); +CABLES.OPS["08c5d91e-32d2-4852-ac18-d4cae543dd37"]={f:Ops.Devices.TouchGesture,objName:"Ops.Devices.TouchGesture"}; + + + + +// ************************************************************** +// +// Ops.Devices.TouchScreen +// +// ************************************************************** + +Ops.Devices.TouchScreen = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + disableScaleWeb = op.inValueBool("Disable Scaling", true), + disableDefault = op.inValueBool("Disable Scroll", true), + hdpi = op.inValueBool("HDPI Coordinates", false), + active = op.inValueBool("Active", true), + + outTouched = op.outNumber("Touched", false), + numFingers = op.outNumber("Fingers", 0), + + f1x = op.outNumber("Finger 1 X", 0), + f1y = op.outNumber("Finger 1 Y", 0), + f1f = op.outNumber("Finger 1 Force", 0), + + f2x = op.outNumber("Finger 2 X", 0), + f2y = op.outNumber("Finger 2 Y", 0), + area = op.inSwitch("Area", ["Canvas", "Document"], "Canvas"), + + outEvents = op.outArray("Events"), + normalize = op.inValueBool("Normalize Coordinates"), + flipY = op.inValueBool("Flip Y"), + outTouchStart = op.outTrigger("Touch Start"), + outTouchEnd = op.outTrigger("Touch End"); + +area.onChange = updateArea; + +function setPos(event) +{ + if (event.touches && event.touches.length > 0) + { + var rect = event.target.getBoundingClientRect(); + var x = event.touches[0].clientX - event.touches[0].target.offsetLeft; + var y = event.touches[0].clientY - event.touches[0].target.offsetTop; + + if (flipY.get()) y = rect.height - y; + + if (hdpi.get()) + { + x *= (op.patch.cgl.pixelDensity || 1); + y *= (op.patch.cgl.pixelDensity || 1); + } + + if (normalize.get()) + { + x = (x / rect.width * 2.0 - 1.0); + y = (y / rect.height * 2.0 - 1.0); + } + + f1x.set(x); + f1y.set(y); + + if (event.touches[0].force)f1f.set(event.touches[0].force); + } + + if (event.touches && event.touches.length > 1) + { + var rect = event.target.getBoundingClientRect(); + var x = event.touches[1].clientX - event.touches[1].target.offsetLeft; + var y = event.touches[1].clientY - event.touches[1].target.offsetTop; + + if (hdpi.get()) + { + x *= (op.patch.cgl.pixelDensity || 1); + y *= (op.patch.cgl.pixelDensity || 1); + } + + f2x.set(x); + f2y.set(y); + } + outEvents.set(event.touches); +} + +const ontouchstart = function (event) +{ + outTouched.set(true); + setPos(event); + numFingers.set(event.touches.length); + outTouchStart.trigger(); +}; + +const ontouchend = function (event) +{ + outTouched.set(false); + f1f.set(0); + setPos(event); + + numFingers.set(event.touches.length); + outTouchEnd.trigger(); +}; + +const ontouchmove = function (event) +{ + setPos(event); + numFingers.set(event.touches.length); + if (disableDefault.get() || (disableScaleWeb.get() && event.scale !== 1)) + { + event.preventDefault(); + document.body.style["touch-action"] = "none"; + } + else + { + document.body.style["touch-action"] = "initial"; + } +}; + +const cgl = op.patch.cgl; +let listenerElement = null; +function addListeners() +{ + listenerElement.addEventListener("touchmove", ontouchmove, { "passive": true }); + listenerElement.addEventListener("touchstart", ontouchstart, { "passive": true }); + listenerElement.addEventListener("touchend", ontouchend, { "passive": true }); +} + +function updateArea() +{ + removeListeners(); + + if (area.get() == "Document") listenerElement = document; + else listenerElement = cgl.canvas; + + if (active.get()) addListeners(); +} + +function removeListeners() +{ + if (listenerElement) + { + listenerElement.removeEventListener("touchmove", ontouchmove); + listenerElement.removeEventListener("touchstart", ontouchstart); + listenerElement.removeEventListener("touchend", ontouchend); + } + listenerElement = null; +} + +active.onChange = function () +{ + updateArea(); +}; + +updateArea(); + + +}; + +Ops.Devices.TouchScreen.prototype = new CABLES.Op(); +CABLES.OPS["cedffacf-0f09-4342-bd21-540bd9c8037d"]={f:Ops.Devices.TouchScreen,objName:"Ops.Devices.TouchScreen"}; + + + + +// ************************************************************** +// +// Ops.Game.PersonController +// +// ************************************************************** + +Ops.Game.PersonController = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("Exe"), + speed = op.inValue("Speed", 1), + outX = op.outNumber("X"), + outY = op.outNumber("Y"), + outDir = op.outNumber("Dir"), + goNorth = op.inBool("North"), + goEast = op.inBool("East"), + goSouth = op.inBool("South"), + goWest = op.inBool("West"); + +let lastTime = performance.now(); +let dir = 0; + +exe.onTriggered = function () +{ + let ago = (performance.now() - lastTime) / 1000; + let x = 0; + let y = 0; + if (goEast.get())x += ago * speed.get(); + if (goWest.get())x -= ago * speed.get(); + if (goNorth.get())y += ago * speed.get(); + if (goSouth.get())y -= ago * speed.get(); + + if (goEast.get())dir = 90; + if (goWest.get())dir = 270; + if (goNorth.get())dir = 0; + if (goSouth.get())dir = 180; + + outDir.set(dir); + outX.set(outX.get() + x); + outY.set(outY.get() + y); + lastTime = performance.now(); +}; + + +}; + +Ops.Game.PersonController.prototype = new CABLES.Op(); +CABLES.OPS["7b08dea1-a05b-422e-a1de-7832058bee51"]={f:Ops.Game.PersonController,objName:"Ops.Game.PersonController"}; + + + + +// ************************************************************** +// +// Ops.Geometry.BoundingBox +// +// ************************************************************** + +Ops.Geometry.BoundingBox = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inW = op.inFloat("Width", 1), + inH = op.inFloat("Height", 1), + inD = op.inFloat("Depth", 1), + result = op.outObject("Result"); + +inW.onChange = +inH.onChange = +inD.onChange = update; +update(); + +function update() +{ + result.set( + { + "_max": [inW.get() / 2, inH.get() / 2, inD.get() / 2], + "_min": [-inW.get() / 2, -inH.get() / 2, -inD.get() / 2], + "_center": [0, 0, 0] + }); +} + + +}; + +Ops.Geometry.BoundingBox.prototype = new CABLES.Op(); +CABLES.OPS["73dc3511-7c1d-4e42-9e00-f86bc952058a"]={f:Ops.Geometry.BoundingBox,objName:"Ops.Geometry.BoundingBox"}; + + + + +// ************************************************************** +// +// Ops.Geometry.CalculateNormals +// +// ************************************************************** + +Ops.Geometry.CalculateNormals = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + geometry = op.inObject("Geometry"), + smoothNormals = op.inValueBool("Smooth"), + forceZUp = op.inValueBool("Force Z Up"), + geomOut = op.outObject("Geometry Out"); + +geomOut.ignoreValueSerialize = true; +geometry.ignoreValueSerialize = true; + +geometry.onChange = calc; +smoothNormals.onChange = calc; +forceZUp.onChange = calc; + +let geom = null; + +function calc() +{ + if (!geometry.get()) return; + + let geom = geometry.get().copy(); + + if (!smoothNormals.get())geom.unIndex(); + + geom.calculateNormals({ + "forceZUp": forceZUp.get() + }); + + geomOut.set(geom); +} + + +}; + +Ops.Geometry.CalculateNormals.prototype = new CABLES.Op(); +CABLES.OPS["c90c70e5-59eb-4b19-9c15-962e3e2f236b"]={f:Ops.Geometry.CalculateNormals,objName:"Ops.Geometry.CalculateNormals"}; + + + + +// ************************************************************** +// +// Ops.Geometry.GeometryToWireframeArray3 +// +// ************************************************************** + +Ops.Geometry.GeometryToWireframeArray3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inGeom = op.inObject("Geometry"), + outArr = op.outArray("Array"); + + +inGeom.onChange = function () +{ + const g = inGeom.get(); + + outArr.set(null); + + if (!g) return; + + const arr = []; + + for (let i = 0; i < g.verticesIndices.length; i += 3) + { + arr.push( + g.vertices[g.verticesIndices[i + 0] * 3 + 0], + g.vertices[g.verticesIndices[i + 0] * 3 + 1], + g.vertices[g.verticesIndices[i + 0] * 3 + 2], + + g.vertices[g.verticesIndices[i + 1] * 3 + 0], + g.vertices[g.verticesIndices[i + 1] * 3 + 1], + g.vertices[g.verticesIndices[i + 1] * 3 + 2], + + + g.vertices[g.verticesIndices[i + 1] * 3 + 0], + g.vertices[g.verticesIndices[i + 1] * 3 + 1], + g.vertices[g.verticesIndices[i + 1] * 3 + 2], + + g.vertices[g.verticesIndices[i + 2] * 3 + 0], + g.vertices[g.verticesIndices[i + 2] * 3 + 1], + g.vertices[g.verticesIndices[i + 2] * 3 + 2], + + + g.vertices[g.verticesIndices[i + 2] * 3 + 0], + g.vertices[g.verticesIndices[i + 2] * 3 + 1], + g.vertices[g.verticesIndices[i + 2] * 3 + 2], + + g.vertices[g.verticesIndices[i + 0] * 3 + 0], + g.vertices[g.verticesIndices[i + 0] * 3 + 1], + g.vertices[g.verticesIndices[i + 0] * 3 + 2]); + } + + outArr.set(arr); +}; + + +}; + +Ops.Geometry.GeometryToWireframeArray3.prototype = new CABLES.Op(); +CABLES.OPS["d6d0f3ce-5670-49bb-893a-7c9b0262b991"]={f:Ops.Geometry.GeometryToWireframeArray3,objName:"Ops.Geometry.GeometryToWireframeArray3"}; + + + + +// ************************************************************** +// +// Ops.Geometry.Triangulate2dPath +// +// ************************************************************** + +Ops.Geometry.Triangulate2dPath = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTriggerButton("Update"), + inWinding = op.inDropDown("Combine", ["Positive", "Odd", "Intersect", "Negative"], "Positive"), + inPath = op.inArray("2d Point Path"), + inPath2 = op.inArray("Path 2"), + inPath3 = op.inArray("Path 3"), + next = op.outTrigger("Next"), + outGeom = op.outObject("Geometry"); + +inExec.onTriggered = tess; +let geom = null; +function tess() +{ + // var Tess2 = require('tess2'); + + // Define input + // var ca = [0,0, 10,0, 5,10]; + // var cb = [0,2, 10,2, 10,6, 0,6]; + // var contours = [ca,cb]; + + let points = inPath.get(); + + if (!points || points.length === 0) + { + outGeom.set(null); + return; + } + + let contours = [points]; + + let points2 = inPath2.get(); + if (points2 && points2.length > 0) contours.push(points2); + + let points3 = inPath3.get(); + if (points3 && points3.length > 0) contours.push(points3); + + let winding = Tess2.WINDING_ODD; + if (inWinding.get() == "Positive") + { + winding = Tess2.WINDING_POSITIVE; + } + if (inWinding.get() == "Negative") + { + winding = Tess2.WINDING_NEGATIVE; + } + if (inWinding.get() == "Intersect") + { + winding = Tess2.WINDING_ABS_GEQ_TWO; + } + + let res = null; + try + { + // Tesselate + res = Tess2.tesselate({ + "contours": contours, + "windingRule": winding, + "elementType": Tess2.POLYGONS, + "polySize": 3, + "vertexSize": 2 + }); + } + catch (e) {} + + if (res) + { + let changed = true; + + if (geom) changed = geom.vertices.length / 3 != res.vertices.length / 2; + + if (changed) + { + geom = new CGL.Geometry("tess2geom"); + } + + let verts3 = []; + for (let i = 0; i < res.vertices.length; i += 2) + { + verts3.push(res.vertices[i + 0], res.vertices[i + 1], 0); + } + + geom.vertices = verts3; + geom.verticesIndices = res.elements; + geom.calculateNormals(); + geom.mapTexCoords2d(); + geom.flipVertDir(); + + outGeom.set(null); + outGeom.set(geom); + } + + next.trigger(); +} + + +}; + +Ops.Geometry.Triangulate2dPath.prototype = new CABLES.Op(); +CABLES.OPS["6165a15f-abf3-4398-87f7-541bedc109e5"]={f:Ops.Geometry.Triangulate2dPath,objName:"Ops.Geometry.Triangulate2dPath"}; + + + + +// ************************************************************** +// +// Ops.Gl.AspectRatio +// +// ************************************************************** + +Ops.Gl.AspectRatio = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let aspects = [ + { "title": "1:2", "v": 1 / 2 }, + { "title": "1", "v": 1 }, + { "title": "5:4", "v": 5 / 4 }, + { "title": "4:3", "v": 4 / 3 }, + { "title": "3:2", "v": 3 / 2 }, + { "title": "11:8", "v": 11 / 8 }, + { "title": "16:9", "v": 16 / 9 }, + { "title": "2:1", "v": 2 }, + { "title": "21:9", "v": 21 / 9 }, + { "title": "custom", "v": 0 }, +]; +let aspectTitles = []; +for (let i = 0; i < aspects.length; i++) aspectTitles.push(aspects[i].title); + +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + outWidth = op.outNumber("Width"), + outHeight = op.outNumber("Height"), + inAspect = op.inValueSelect("Aspect Ratio", aspectTitles, aspects[0].title), + inCustom = op.inValueFloat("Custom", 1.777777); + +const + useVPSize = op.inValueBool("use viewport size", true), + width = op.inValueInt("texture width", 512), + height = op.inValueInt("texture height", 512); + +op.setPortGroup("Size", [useVPSize, width, height]); +useVPSize.onChange = updateVpSize; +function updateVpSize() +{ + width.setUiAttribs({ "greyout": useVPSize.get() }); + height.setUiAttribs({ "greyout": useVPSize.get() }); +} + +const prevViewPort = []; +const cgl = op.patch.cgl; +let w = 1000, h = 1000, x, y; +let ratio = 1; + +inAspect.onChange = changedRatio; +inCustom.onChange = changedRatio; + +changedRatio(); + +function changedRatio() +{ + let selected = inAspect.get(); + if (selected == "custom") + { + if (inCustom.uiAttribs.greyout) inCustom.setUiAttribs({ "greyout": false }); + ratio = Math.abs(inCustom.get()); + } + else + { + if (!inCustom.uiAttribs.greyout) inCustom.setUiAttribs({ "greyout": true }); + + for (let i = 0; i < aspects.length; i++) + { + if (aspects[i].title == selected) + { + ratio = aspects[i].v; + break; + } + } + } +} + +function resize() +{ + let theWidth = cgl.canvasWidth; + let theHeight = cgl.canvasHeight; + + if (!useVPSize.get()) + { + theWidth = width.get(); + theHeight = height.get(); + } + + let _w = theHeight * ratio; + let _h = theHeight; + let _x = 0; + let _y = 0; + if (_w > theWidth) + { + _w = theWidth; + _h = theWidth / ratio; + } + + if (_w < theWidth) _x = (theWidth - _w) / 2; + if (_h < theHeight) _y = (theHeight - _h) / 2; + + _w = Math.ceil(_w); + _h = Math.ceil(_h); + _x = Math.ceil(_x); + _y = Math.ceil(_y); + + if (_w != w || _h != h || _x != x || _y != y) + { + w = _w; + h = _h; + x = _x; + y = _y; + + cgl.setViewPort(x, y, w, h); + + for (let i = 0; i < op.patch.ops.length; i++) + if (op.patch.ops[i].onResize)op.patch.ops[i].onResize(); + } + + outWidth.set(w); + outHeight.set(h); +} + +op.onDelete = function () +{ + cgl.resetViewPort(); +}; + +render.onTriggered = function () +{ + let vp = cgl.getViewPort(); + prevViewPort[0] = vp[0]; + prevViewPort[1] = vp[1]; + prevViewPort[2] = vp[2]; + prevViewPort[3] = vp[3]; + + resize(); + x = Math.ceil(x); + y = Math.ceil(y); + w = Math.ceil(w); + h = Math.ceil(h); + + cgl.setViewPort(x, y, w, h); + + mat4.perspective(cgl.pMatrix, 45, ratio, 0.1, 1100.0); + + trigger.trigger(); + + cgl.setViewPort(prevViewPort[0], prevViewPort[1], prevViewPort[2], prevViewPort[3]); +}; + + +}; + +Ops.Gl.AspectRatio.prototype = new CABLES.Op(); +CABLES.OPS["b4f17994-3028-4203-9a8d-d5e5377a58fc"]={f:Ops.Gl.AspectRatio,objName:"Ops.Gl.AspectRatio"}; + + + + +// ************************************************************** +// +// Ops.Gl.BlendMode +// +// ************************************************************** + +Ops.Gl.BlendMode = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Render"), + inBlend = op.inValueSelect("Blendmode", ["None", "Normal", "Add", "Subtract", "Multiply"], "Normal"), + inPremul = op.inValueBool("Premultiplied"), + next = op.outTrigger("Next"); + +const cgl = op.patch.cgl; +let blendMode = 0; +inBlend.onChange = update; +update(); + +function update() +{ + if (inBlend.get() == "Normal")blendMode = CGL.BLEND_NORMAL; + else if (inBlend.get() == "Add")blendMode = CGL.BLEND_ADD; + else if (inBlend.get() == "Subtract")blendMode = CGL.BLEND_SUB; + else if (inBlend.get() == "Multiply")blendMode = CGL.BLEND_MUL; + else blendMode = CGL.BLEND_NONE; + + if (CABLES.UI) + { + let blstr = ""; + if (inBlend.get() == "Normal")blstr = ""; + else if (inBlend.get() == "Add")blstr = "Add"; + else if (inBlend.get() == "Subtract")blstr = "Sub"; + else if (inBlend.get() == "Multiply")blstr = "Mul"; + else blstr = "None"; + + op.setUiAttrib({ "extendTitle": blstr }); + } +} + +exec.onTriggered = function () +{ + cgl.pushBlendMode(blendMode, inPremul.get()); + cgl.pushBlend(blendMode != CGL.BLEND_NONE); + next.trigger(); + cgl.popBlend(); + cgl.popBlendMode(); + cgl.gl.blendEquationSeparate(cgl.gl.FUNC_ADD, cgl.gl.FUNC_ADD); + cgl.gl.blendFuncSeparate(cgl.gl.SRC_ALPHA, cgl.gl.ONE_MINUS_SRC_ALPHA, cgl.gl.ONE, cgl.gl.ONE_MINUS_SRC_ALPHA); +}; + + +}; + +Ops.Gl.BlendMode.prototype = new CABLES.Op(); +CABLES.OPS["ce0fff72-1438-4373-924f-e1d0f78b053f"]={f:Ops.Gl.BlendMode,objName:"Ops.Gl.BlendMode"}; + + + + +// ************************************************************** +// +// Ops.Gl.Canvas2Texture +// +// ************************************************************** + +Ops.Gl.Canvas2Texture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + cgl = op.patch.cgl, + inCanvas = op.inObject("canvas"), + inTextureFilter = op.inValueSelect("filter", ["nearest", "linear", "mipmap"]), + inTextureWrap = op.inValueSelect("wrap", ["repeat", "mirrored repeat", "clamp to edge"], "clamp to edge"), + inTextureFlip = op.inValueBool("flip"), + inUnpackAlpha = op.inValueBool("unpackPreMultipliedAlpha"), + outTexture = op.outTexture("texture"), + outWidth = op.outNumber("width"), + outHeight = op.outNumber("height"), + canvasTexture = new CGL.Texture(cgl); + +let cgl_filter = null; +let cgl_wrap = null; + +inTextureFlip.set(false); +inUnpackAlpha.set(false); + +inTextureFlip.setUiAttribs({ "hidePort": true }); +inUnpackAlpha.setUiAttribs({ "hidePort": true }); + +inTextureFilter.onChange = onFilterChange; +inTextureWrap.onChange = onWrapChange; + +inTextureFlip.onChange = +inCanvas.onChange = +inUnpackAlpha.onChange = reload; + +function reload() +{ + let canvas = inCanvas.get(); + if (!canvas) return; + + canvasTexture.unpackAlpha = inUnpackAlpha.get(); + canvasTexture.flip = inTextureFlip.get(); + canvasTexture.wrap = cgl_wrap; + canvasTexture.image = canvas; + canvasTexture.initTexture(canvas, cgl_filter); + outWidth.set(canvasTexture.width); + outHeight.set(canvasTexture.height); + + outTexture.set(CGL.Texture.getEmptyTexture(cgl)); + outTexture.set(canvasTexture); +} + +function onFilterChange() +{ + switch (inTextureFilter.get()) + { + case "nearest": cgl_filter = CGL.Texture.FILTER_NEAREST; break; + case "mipmap": cgl_filter = CGL.Texture.FILTER_MIPMAP; break; + case "linear": + default: cgl_filter = CGL.Texture.FILTER_LINEAR; + } + reload(); +} + +function onWrapChange() +{ + switch (inTextureWrap.get()) + { + case "repeat": cgl_wrap = CGL.Texture.WRAP_REPEAT; break; + case "mirrored repeat": cgl_wrap = CGL.Texture.WRAP_MIRRORED_REPEAT; break; + case "clamp to edge": + default: cgl_wrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + } + reload(); +} + +inTextureFilter.set("linear"); +inTextureWrap.set("repeat"); + +outTexture.set(CGL.Texture.getEmptyTexture(cgl)); + + +}; + +Ops.Gl.Canvas2Texture.prototype = new CABLES.Op(); +CABLES.OPS["2fbada6b-70fa-4b43-87db-8b0d9293990b"]={f:Ops.Gl.Canvas2Texture,objName:"Ops.Gl.Canvas2Texture"}; + + + + +// ************************************************************** +// +// Ops.Gl.CanvasFocus +// +// ************************************************************** + +Ops.Gl.CanvasFocus = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inFocus = op.inTriggerButton("Focus"), + hasFocus = op.outBool("has focus"); + +op.onDelete = removeListeners; +addListeners(); + +inFocus.onTriggered = () => +{ + op.patch.cgl.canvas.focus(); +}; + +function onFocus() +{ + hasFocus.set(true); +} + +function onBlur() +{ + hasFocus.set(false); +} + +function addListeners() +{ + op.patch.cgl.canvas.addEventListener("focus", onFocus); + op.patch.cgl.canvas.addEventListener("blur", onBlur); +} + +function removeListeners() +{ + op.patch.cgl.canvas.removeEventListener("focus", onFocus); + op.patch.cgl.canvas.removeEventListener("blur", onBlur); +} + + +}; + +Ops.Gl.CanvasFocus.prototype = new CABLES.Op(); +CABLES.OPS["e235ea77-f697-475a-8799-d5e4deed7204"]={f:Ops.Gl.CanvasFocus,objName:"Ops.Gl.CanvasFocus"}; + + + + +// ************************************************************** +// +// Ops.Gl.CanvasInBrowserViewport +// +// ************************************************************** + +Ops.Gl.CanvasInBrowserViewport = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inUpdate = op.inTriggerButton("Update"), + outResult = op.outBoolNum("Fully Visible"), + outResultPartly = op.outBoolNum("Partly Visible"); + +inUpdate.onTriggered = update; + +window.addEventListener("DOMContentLoaded load", update); +window.addEventListener("resize", update); +window.addEventListener("scroll", update); + +// from: https://stackoverflow.com/questions/19669786/check-if-element-is-visible-in-dom + +function pointInViewport(x, y) +{ + return ( + y >= 0 && + x >= 0 && + y <= (window.innerHeight || document.documentElement.clientHeight) && + x <= (window.innerWidth || document.documentElement.clientWidth) + ); +} + +function elementInViewport(el) +{ + let rect = el.getBoundingClientRect(); + + return ( + rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && + rect.right <= (window.innerWidth || document.documentElement.clientWidth) + ); +} + +function elementInViewportPartly(el) +{ + let rect = el.getBoundingClientRect(); + + return ( + pointInViewport(rect.left, rect.top) || + pointInViewport(rect.left, rect.bottom) || + pointInViewport(rect.right, rect.top) || + pointInViewport(rect.right, rect.bottom) + ); +} + +function update() +{ + let visible = elementInViewport(op.patch.cgl.canvas); + let visiblePartly = elementInViewportPartly(op.patch.cgl.canvas); + + outResultPartly.set(visiblePartly); + outResult.set(visible); +} + +update(); + + +}; + +Ops.Gl.CanvasInBrowserViewport.prototype = new CABLES.Op(); +CABLES.OPS["2721f83b-246c-46fa-9ad9-d8c829adb94d"]={f:Ops.Gl.CanvasInBrowserViewport,objName:"Ops.Gl.CanvasInBrowserViewport"}; + + + + +// ************************************************************** +// +// Ops.Gl.CanvasInfo +// +// ************************************************************** + +Ops.Gl.CanvasInfo = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + width = op.outNumber("width"), + height = op.outNumber("height"), + inUnit = op.inSwitch("Pixel Unit", ["Display", "CSS"], "Display"), + pixelRatio = op.outNumber("Pixel Ratio"), + aspect = op.outNumber("Aspect Ratio"), + landscape = op.outBool("Landscape"); + +let cgl = op.patch.cgl; + +cgl.on("resize", update); + +inUnit.onChange = update; +update(); + +function update() +{ + let div = 1; + if (inUnit.get() == "CSS")div = op.patch.cgl.pixelDensity; + height.set(cgl.canvasHeight / div); + width.set(cgl.canvasWidth / div); + + pixelRatio.set(op.patch.cgl.pixelDensity); // window.devicePixelRatio + + aspect.set(cgl.canvasWidth / cgl.canvasHeight); + landscape.set(cgl.canvasWidth > cgl.canvasHeight ? 1 : 0); +} + + +}; + +Ops.Gl.CanvasInfo.prototype = new CABLES.Op(); +CABLES.OPS["94e499e5-b4ee-4861-ab48-6ab5098b2cc3"]={f:Ops.Gl.CanvasInfo,objName:"Ops.Gl.CanvasInfo"}; + + + + +// ************************************************************** +// +// Ops.Gl.ClearColor +// +// ************************************************************** + +Ops.Gl.ClearColor = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + r = op.inFloatSlider("r", 0.1), + g = op.inFloatSlider("g", 0.1), + b = op.inFloatSlider("b", 0.1), + a = op.inFloatSlider("a", 1); + +r.setUiAttribs({ "colorPick": true }); + +const cgl = op.patch.cgl; + +render.onTriggered = function () +{ + cgl.gl.clearColor(r.get(), g.get(), b.get(), a.get()); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); + trigger.trigger(); +}; + + +}; + +Ops.Gl.ClearColor.prototype = new CABLES.Op(); +CABLES.OPS["19b441eb-9f63-4f35-ba08-b87841517c4d"]={f:Ops.Gl.ClearColor,objName:"Ops.Gl.ClearColor"}; + + + + +// ************************************************************** +// +// Ops.Gl.ClearDepth +// +// ************************************************************** + +Ops.Gl.ClearDepth = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; + +const + render=op.inTrigger('render'), + trigger=op.outTrigger('trigger'), + cgl=op.patch.cgl; + +render.onTriggered=function() +{ + cgl.gl.clear(cgl.gl.DEPTH_BUFFER_BIT); + trigger.trigger(); +}; + + + + +}; + +Ops.Gl.ClearDepth.prototype = new CABLES.Op(); +CABLES.OPS["9e8a4b73-4ba7-4c4f-b266-81c5f9db9b7a"]={f:Ops.Gl.ClearDepth,objName:"Ops.Gl.ClearDepth"}; + + + + +// ************************************************************** +// +// Ops.Gl.ColorMask +// +// ************************************************************** + +Ops.Gl.ColorMask = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Execute"), + inR = op.inValueBool("Red", true), + inG = op.inValueBool("Green", true), + inB = op.inValueBool("Blue", true), + inA = op.inValueBool("Alpha", true), + next = op.outTrigger("Next"); + +const cgl = op.patch.cgl; + +// var old=cgl.gl.getParameter(cgl.gl.COLOR_WRITEMASK); + +exec.onTriggered = function () +{ + cgl.gl.colorMask(inR.get(), inG.get(), inB.get(), inA.get()); + next.trigger(); + op.patch.cgl.gl.colorMask(true, true, true, true); +}; + + +}; + +Ops.Gl.ColorMask.prototype = new CABLES.Op(); +CABLES.OPS["44433419-dcf4-46e6-8f40-d331598029ac"]={f:Ops.Gl.ColorMask,objName:"Ops.Gl.ColorMask"}; + + + + +// ************************************************************** +// +// Ops.Gl.ColorPick +// +// ************************************************************** + +Ops.Gl.ColorPick = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + x = op.inValueFloat("x"), + y = op.inValueFloat("y"), + r = op.outNumber("r"), + g = op.outNumber("g"), + b = op.outNumber("b"), + a = op.outNumber("a"); + +const cgl = op.patch.cgl; +let pixelValues = new Uint8Array(4); +render.onTriggered = doRender; + +function doRender() +{ + cgl.gl.readPixels(x.get(), cgl.canvas.height - y.get(), 1, 1, cgl.gl.RGBA, cgl.gl.UNSIGNED_BYTE, pixelValues); + r.set(pixelValues[0] / 255); + g.set(pixelValues[1] / 255); + b.set(pixelValues[2] / 255); + a.set(pixelValues[3] / 255); +} + + +}; + +Ops.Gl.ColorPick.prototype = new CABLES.Op(); +CABLES.OPS["12de35ad-3f76-496c-9585-b77a87530de3"]={f:Ops.Gl.ColorPick,objName:"Ops.Gl.ColorPick"}; + + + + +// ************************************************************** +// +// Ops.Gl.CubeMap.CubeMapFromTextures_v2 +// +// ************************************************************** + +Ops.Gl.CubeMap.CubeMapFromTextures_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let loadingId = 0; +let skyboxCubemap = null; +const gl = op.patch.cgl.gl; +const cgl = op.patch.cgl; + + +const inFilenames = []; + +const titles = [ + "posx", "negx", + "posy", "negy", + "posz", "negz" +]; + +titles.forEach(function (title) +{ // create inlet ports + const inFilename = op.inUrl(title, "image"); + inFilename.onChange = loadImagesLater; // assign on change handlers + inFilenames.push(inFilename); +}); + +const inFlipY = op.inBool("Flip Y", false); +let outTex = op.outObject("cubemap"); +inFlipY.onChange = loadImagesLater; + +let timeoutLater = null; + +function loadImagesLater() +{ + clearTimeout(timeoutLater); + timeoutLater = setTimeout(loadImages, 100); +} + +function loadImage(src) +{ + return new Promise((resolve, reject) => + { + const image = new Image(); + image.crossOrigin = ""; + image.addEventListener("load", () => { return resolve(image); }); + image.addEventListener("error", (err) => { return reject(err); }); + image.src = src; + }); +} + +function loadImages() +{ + op.setUiError("loadingerror", null); + op.setUiError("loading", "Loading images...", 0); + + skyboxCubemap = null; + loadingId = cgl.patch.loading.start("cubemap texture", ""); + + const images = Promise.all( + inFilenames.map((inFile) => { return inFile.get(); }) // get file address + .filter(Boolean) // remove all 0's (empty file adresses) so we only resolve + .map((filename) => { return loadImage(filename); })) // map to resolver function + .then((images) => + { // wait for all images to be loaded and only then continue + if (images.length === 6) + { + cgl.gl.pixelStorei( + cgl.gl.UNPACK_FLIP_Y_WEBGL, + inFlipY.get() + ); + skyboxCubemap = cgl.gl.createTexture(cgl.gl.TEXTURE_CUBE_MAP); + cgl.gl.bindTexture(cgl.gl.TEXTURE_CUBE_MAP, skyboxCubemap); + + cgl.gl.texParameteri(cgl.gl.TEXTURE_CUBE_MAP, cgl.gl.TEXTURE_WRAP_S, cgl.gl.CLAMP_TO_EDGE); + cgl.gl.texParameteri(cgl.gl.TEXTURE_CUBE_MAP, cgl.gl.TEXTURE_WRAP_T, cgl.gl.CLAMP_TO_EDGE); + cgl.gl.texParameteri(cgl.gl.TEXTURE_CUBE_MAP, cgl.gl.TEXTURE_MIN_FILTER, cgl.gl.LINEAR_MIPMAP_LINEAR); + cgl.gl.texParameteri(cgl.gl.TEXTURE_CUBE_MAP, cgl.gl.TEXTURE_MAG_FILTER, cgl.gl.LINEAR); + + if (inFlipY.get()) + { + const temp = images[2]; + images[2] = images[3]; + images[3] = temp; + } + + images.forEach((img, index) => + { + cgl.gl.bindTexture( + cgl.gl.TEXTURE_CUBE_MAP, + skyboxCubemap + ); + + cgl.gl.texImage2D( + cgl.gl.TEXTURE_CUBE_MAP_POSITIVE_X + index, + 0, + cgl.gl.RGBA, + cgl.gl.RGBA, + cgl.gl.UNSIGNED_BYTE, + img + ); + }); + + cgl.gl.generateMipmap(cgl.gl.TEXTURE_CUBE_MAP); + + outTex.set({ "cubemap": skyboxCubemap }); + + cgl.gl.bindTexture(cgl.gl.TEXTURE_CUBE_MAP, null); + cgl.patch.loading.finished(loadingId); + + op.setUiError("loading", null); + } + }) + .catch((err) => + { + op.error("error", err); + op.setUiError("loadingerror", "Could not load textures!", 2); + }); +} + + +}; + +Ops.Gl.CubeMap.CubeMapFromTextures_v2.prototype = new CABLES.Op(); +CABLES.OPS["44e837c5-ecd8-42cf-9be6-4db2283b9cbf"]={f:Ops.Gl.CubeMap.CubeMapFromTextures_v2,objName:"Ops.Gl.CubeMap.CubeMapFromTextures_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.CubeMap.CubeMapMaterial_v2 +// +// ************************************************************** + +Ops.Gl.CubeMap.CubeMapMaterial_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"cubemap_frag":"{{MODULES_HEAD}}\n\n#define PI 3.14159265358\n#define PI_TWO 2.*PI\n#define RECIPROCAL_PI 1./PI\n#define RECIPROCAL_PI2 RECIPROCAL_PI/2.\n\nIN vec3 vCoords;\nIN vec3 v_normal;\nIN vec3 v_eyeCoords;\nIN vec3 v_pos;\nIN mat3 normalMatrix;\nIN vec3 texCoords;\nIN vec3 reflectionTexCoords;\nIN vec3 normInterpolated;\nIN vec3 fragPos;\n\nUNI vec3 camPos;\nUNI float inRotation;\nUNI vec3 inColor;\n\n\n#ifdef TEX_FORMAT_CUBEMAP\n UNI samplerCube skybox;\n #ifndef WEBGL1\n #define SAMPLETEX textureLod\n #endif\n #ifdef WEBGL1\n #define SAMPLETEX textureCubeLodEXT\n #endif\n#endif\n\n#ifndef TEX_FORMAT_CUBEMAP\n #define TEX_FORMAT_EQUIRECT\n UNI sampler2D skybox;\n #ifdef WEBGL1\n // #extension GL_EXT_shader_texture_lod : enable\n #ifdef GL_EXT_shader_texture_lod\n #define textureLod texture2DLodEXT\n #endif\n // #define textureLod texture2D\n #endif\n #define SAMPLETEX sampleEquirect\n\n#endif\n\n\n\nUNI mat4 modelMatrix;\nUNI mat4 inverseViewMatrix;\nUNI float miplevel;\n\n#ifdef TEX_FORMAT_EQUIRECT\n const vec2 invAtan = vec2(0.1591, 0.3183);\n vec4 sampleEquirect(sampler2D tex,vec3 direction,float lod)\n {\n #ifndef WEBGL1\n vec3 newDirection = normalize(direction);\n \t\tvec2 sampleUV;\n \t\tsampleUV.x = -1. * (atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.75);\n \t\tsampleUV.y = asin( clamp(direction.y, -1., 1.) ) * RECIPROCAL_PI + 0.5;\n #endif\n\n #ifdef WEBGL1\n vec3 newDirection = normalize(direction);\n \t\tvec2 sampleUV = vec2(atan(newDirection.z, newDirection.x), asin(newDirection.y+1e-6));\n sampleUV *= vec2(0.1591, 0.3183);\n sampleUV += 0.5;\n #endif\n return textureLod(tex, sampleUV, lod);\n }\n#endif\n\nvoid main()\n{\n float rot = inRotation * PI_TWO;\n float sa = sin(rot);\n float ca = cos(rot);\n mat2 matRotation = mat2(ca,sa,-sa,ca);\n\n {{MODULE_BEGIN_FRAG}}\n\n vec3 normal = normalize(normInterpolated);\n\n vec4 col = vec4(1.0,1.0,1.0,1.0);\n vec3 viewDirection = normalize((camPos - fragPos));\n\n #ifdef DO_REFLECTION\n vec3 envMapNormal = normal;\n vec3 reflectDirection = reflect(-viewDirection, normal);\n\n if (!gl_FrontFacing) {\n reflectDirection.yz *= -1.;\n } else {\n // reflectDirection.x *= -1.;\n }\n\n #ifdef FLIP_X\n reflectDirection.x *= -1.;\n #endif\n #ifdef FLIP_Y\n reflectDirection.y *= -1.;\n #endif\n #ifdef FLIP_Z\n reflectDirection.z *= -1.;\n #endif\n\n reflectDirection.xz *= matRotation;\n col = SAMPLETEX(skybox, reflectDirection,1. + miplevel*10.0);\n #endif\n\n #ifndef DO_REFLECTION\n if (!gl_FrontFacing) normal.x *= -1.;\n\n #ifdef FLIP_X\n normal.x *= -1.;\n #endif\n #ifdef FLIP_Y\n normal.y *= -1.;\n #endif\n #ifdef FLIP_Z\n normal.z *= -1.;\n #endif\n\n normal.xz *= matRotation;\n\n col = SAMPLETEX(skybox, normal, miplevel * 10.0);\n #endif\n\n #ifdef COLORIZE\n col.rgb *= inColor;\n #endif\n {{MODULE_COLOR}}\n\n outColor=col;\n}\n","cubemap_vert":"\n{{MODULES_HEAD}}\n\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\n\nOUT vec3 v_eyeCoords;\nOUT vec3 v_normal;\nOUT vec3 v_pos;\nOUT mat3 normalMatrix;\nOUT vec3 normInterpolated;\nOUT vec3 norm;\nOUT vec3 texCoords;\nOUT vec3 reflectionTexCoords;\nOUT vec3 fragPos;\nOUT vec4 modelPos;\nIN vec3 vPosition;\nIN vec3 attrVertNormal;\nIN vec3 attrTangent;\nIN vec3 attrBiTangent;\nIN vec2 attrTexCoord;\n\nOUT mat4 mvMatrix;\nOUT vec2 texCoord;\nmat3 transposeMat3(mat3 m)\n{\n return mat3(m[0][0], m[1][0], m[2][0],\n m[0][1], m[1][1], m[2][1],\n m[0][2], m[1][2], m[2][2]);\n}\n\nmat3 inverseMat3(mat3 m)\n{\n float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];\n float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];\n float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];\n\n float b01 = a22 * a11 - a12 * a21;\n float b11 = -a22 * a10 + a12 * a20;\n float b21 = a21 * a10 - a11 * a20;\n\n float det = a00 * b01 + a01 * b11 + a02 * b21;\n\n return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),\n b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),\n b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;\n}\n\nvoid main()\n{\n vec4 pos = vec4( vPosition, 1. );\n mat4 mMatrix=modelMatrix;\n\n\n norm=attrVertNormal;\n texCoord=attrTexCoord;\n vec3 tangent = attrTangent;\n vec3 bitangent = attrBiTangent;\n\n {{MODULE_VERTEX_POSITION}}\n\n mat3 mMatrixMat3 = mat3(mMatrix);\n normalMatrix = transposeMat3(inverseMat3(mMatrixMat3));\n normInterpolated = vec3(normalMatrix*norm);\n\n\n\n mvMatrix=viewMatrix*mMatrix;\n modelPos=mMatrix*pos;\n\n fragPos = vec3((mMatrix) * pos);\n gl_Position = projMatrix * mvMatrix * pos;\n\n}",}; +// https://jmonkeyengine.github.io/wiki/jme3/advanced/pbr_part3.html +// https://learnopengl.com/PBR/IBL/Diffuse-irradiance + +const render = op.inTrigger("render"); +const inCubemap = op.inObject("Cubemap"); +const inUseReflection = op.inValueBool("Use Reflection", false); +const inMiplevel = op.inValueSlider("Blur", 0.0); +op.setPortGroup("Appearance", [inMiplevel, inUseReflection]); +const inRotation = op.inFloat("Rotation", 0); +const inFlipX = op.inBool("Flip X", false); +const inFlipY = op.inBool("Flip Y", false); +const inFlipZ = op.inBool("Flip Z", false); + +op.setPortGroup("Transforms", [inRotation, inFlipX, inFlipY, inFlipZ]); +const inColorize = op.inBool("Colorize", false); +const inR = op.inFloatSlider("R", Math.random()); +const inG = op.inFloatSlider("G", Math.random()); +const inB = op.inFloatSlider("B", Math.random()); +inR.setUiAttribs({ "colorPick": true }); + +op.setPortGroup("Color", [inColorize, inR, inG, inB]); + +inUseReflection.onChange = inCubemap.onChange = +inFlipX.onChange = inFlipY.onChange = inFlipZ.onChange = updateMapping; +inColorize.onChange = function () +{ + shader.toggleDefine("COLORIZE", inColorize.get()); + inR.setUiAttribs({ "greyout": !inColorize.get() }); + inG.setUiAttribs({ "greyout": !inColorize.get() }); + inB.setUiAttribs({ "greyout": !inColorize.get() }); +}; +const trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const srcVert = attachments.cubemap_vert; +const srcFrag = attachments.cubemap_frag; + +const shader = new CGL.Shader(cgl, "cubemap material"); +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); + +if (cgl.glVersion == 1) +{ + if (!cgl.gl.getExtension("EXT_shader_texture_lod")) + { + op.log("no EXT_shader_texture_lod texture extension"); + throw "no EXT_shader_texture_lod texture extension"; + } + else + { + shader.enableExtension("GL_EXT_shader_texture_lod"); + cgl.gl.getExtension("OES_texture_float"); + cgl.gl.getExtension("OES_texture_float_linear"); + cgl.gl.getExtension("OES_texture_half_float"); + cgl.gl.getExtension("OES_texture_half_float_linear"); + + shader.enableExtension("GL_OES_standard_derivatives"); + shader.enableExtension("GL_OES_texture_float"); + shader.enableExtension("GL_OES_texture_float_linear"); + shader.enableExtension("GL_OES_texture_half_float"); + shader.enableExtension("GL_OES_texture_half_float_linear"); + } +} + +shader.setSource(srcVert, srcFrag); +const inMiplevelUniform = new CGL.Uniform(shader, "f", "miplevel", inMiplevel); +const inRotationUniform = new CGL.Uniform(shader, "f", "inRotation", inRotation); +const inColorUniform = new CGL.Uniform(shader, "3f", "inColor", inR, inG, inB); +const inSkyboxUniform = new CGL.Uniform(shader, "t", "skybox", 0); +render.onTriggered = doRender; +updateMapping(); + +function doRender() +{ + cgl.pushShader(shader); + shader.popTextures(); + if (inCubemap.get()) + { + if (inCubemap.get().cubemap) shader.pushTexture(inSkyboxUniform, inCubemap.get().cubemap, cgl.gl.TEXTURE_CUBE_MAP); + else shader.pushTexture(inSkyboxUniform, inCubemap.get().tex); + + if (inMiplevel.get() && inCubemap.get().filter != CGL.Texture.FILTER_MIPMAP) op.setUiError("texnomip", "blur needs to be mipmaped texture", 1); + else op.setUiError("texnomip", null); + } + else shader.pushTexture(inSkyboxUniform, CGL.Texture.getTempTexture(cgl).tex); + + trigger.trigger(); + cgl.popShader(); +} + +function updateMapping() +{ + shader.toggleDefine("FLIP_X", inFlipX.get()); + shader.toggleDefine("FLIP_Y", inFlipY.get()); + shader.toggleDefine("FLIP_Z", inFlipZ.get()); + shader.toggleDefine("DO_REFLECTION", inUseReflection.get()); + + if (inCubemap.get() && inCubemap.get().cubemap) + { + shader.define("TEX_FORMAT_CUBEMAP"); + shader.removeDefine("TEX_FORMAT_EQUIRECT"); + } + else + { + shader.removeDefine("TEX_FORMAT_CUBEMAP"); + shader.define("TEX_FORMAT_EQUIRECT"); + } +} + + +}; + +Ops.Gl.CubeMap.CubeMapMaterial_v2.prototype = new CABLES.Op(); +CABLES.OPS["d1fce807-a626-433f-ba61-3f59149fe46e"]={f:Ops.Gl.CubeMap.CubeMapMaterial_v2,objName:"Ops.Gl.CubeMap.CubeMapMaterial_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.CubeMap.CubemapToEquirectangularTexture_v2 +// +// ************************************************************** + +Ops.Gl.CubeMap.CubemapToEquirectangularTexture_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"projection_frag":"IN vec2 texCoord;\nUNI samplerCube cubemap;\n\n#ifdef WEBGL2\n #define textureCube texture\n#endif\n\nvec4 encodeRGBE8( vec3 rgb )\n{\n vec4 vEncoded;\n float maxComponent = max(max(rgb.r, rgb.g), rgb.b );\n float fExp = ceil( log2(maxComponent) );\n vEncoded.rgb = rgb / exp2(fExp);\n vEncoded.a = (fExp + 128.0) / 255.0;\n return vEncoded;\n}\n\nvoid main() {\n #ifdef EQUIRECTANGULAR\n\n float phi=texCoord.s*3.1415*2.;\n float theta=(-texCoord.t - 0.5)*3.1415;\n vec3 dir = vec3(cos(phi)*cos(theta),sin(theta),sin(phi)*cos(theta));\n\n //In this example i use a depthmap with only 1 channel, but the projection should work with a colored cubemap to\n vec4 col = textureCube(cubemap, dir ).rgba;\n\n #ifdef RGBE\n col=encodeRGBE8(col.rgb);\n #endif\n\n outColor = col;\n\n #endif\n #ifndef EQUIRECTANGULAR\n vec4 col=vec4(0.);\n vec2 localST=texCoord;\n localST.y = 1. - localST.y;\n\n //Scale Tex coordinates such that each quad has local coordinates from 0,0 to 1,1\n localST.t = mod(localST.t*3.,1.);\n localST.s = mod(localST.s*4.,1.);\n\n //Due to the way my depth-cubemap is rendered, objects to the -x,y,z side is projected to the positive x,y,z side\n //Inside where tob/bottom is to be drawn?\n if (texCoord.s*4.> 1. && texCoord.s*4.<2.)\n {\n //Bottom (-y) quad\n if (texCoord.t*3. < 1.)\n {\n vec3 dir=vec3(localST.s*2.-1.,-1.,-localST.t*2.+1.);//Due to the (arbitrary) way I choose as up in my depth-viewmatrix, i her emultiply the latter coordinate with -1\n\n #ifdef WEBGL2\n col = textureCube( cubemap, dir );\n #endif\n\n #ifdef WEBGL1\n col = textureCube(cubemap, dir);\n #endif\n }\n //top (+y) quad\n else if (texCoord.t*3. > 2.)\n {\n vec3 dir=vec3(localST.s*2.-1.,1.,localST.t*2.-1.);//Get lower y texture, which is projected to the +y part of my cubemap\n #ifdef WEBGL2\n col = textureCube( cubemap, dir );\n #endif\n\n #ifdef WEBGL1\n col = textureCube(cubemap, dir);\n #endif\n }\n else//Front (-z) quad\n {\n vec3 dir=vec3(localST.s*2.-1.,-localST.t*2.+1.,1.);\n col = textureCube( cubemap, dir );\n }\n }\n //If not, only these ranges should be drawn\n else if (texCoord.t*3. > 1. && texCoord.t*3. < 2.)\n {\n if (texCoord.x*4. < 1.)//left (-x) quad\n {\n vec3 dir=vec3(-1.,-localST.t*2.+1.,localST.s*2.-1.);\n col = textureCube( cubemap, dir );\n }\n else if (texCoord.x*4. < 3.)//right (+x) quad (front was done above)\n {\n vec3 dir=vec3(1,-localST.t*2.+1.,-localST.s*2.+1.);\n col = textureCube(cubemap, dir);\n }\n else //back (+z) quad\n {\n vec3 dir=vec3(-localST.s*2.+1.,-localST.t*2.+1.,-1.);\n col = textureCube(cubemap, dir);\n }\n }\n else//Tob/bottom, but outside where we need to put something\n {\n discard;//No need to add fancy semi transparant borders for quads, this is just for debugging purpose after all\n }\n\n col.a=1.0;\n #ifdef RGBE\n col=encodeRGBE8(col.rgb);\n #endif\n outColor = col;\n\n\n #endif\n}","projection_vert":"{{MODULES_HEAD}}\nIN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\nIN float attrVertIndex;\n\nOUT vec2 texCoord;\nOUT vec3 norm;\nOUT vec3 worldPos;\nUNI mat4 projMatrix;\nUNI mat4 viewMatrix;\nUNI mat4 modelMatrix;\n\nconst vec2 scale = vec2(0.5, 0.5);\n\nvoid main()\n{\n texCoord=attrTexCoord;\n norm=attrVertNormal;\n vec4 pos=vec4(vPosition, 1.0);\n\n {{MODULE_VERTEX_POSITION}}\n\n gl_Position = pos;\n}",}; +const + inTrigger = op.inTrigger("In Trigger"), + inCubemap = op.inObject("Cubemap"), + inProj = op.inSwitch("Projection", ["Equirectangular", "Cube unwrap"], "Equirectangular"), + inFormat = op.inSwitch("Format", ["8bit", "32bit", "RGBE"], "8bit"), + tfilter = op.inSwitch("Filter", ["nearest", "linear", "mipmap"], "linear"), + inWidth = op.inInt("Width", 1024), + inHeight = op.inInt("Height", 512), + outTrigger = op.outTrigger("Out Trigger"), + outProjection = op.outTexture("Result"); + +op.setPortGroup("Options", [inWidth, inHeight, inProj, inFormat, tfilter]); +inProj.onChange = updateDefines; + +const cgl = op.patch.cgl; +const mesh = CGL.MESHES.getSimpleRect(cgl, "fullscreenRectangle"); +const IS_WEBGL_1 = cgl.glVersion == 1; +let sizeChanged = false; +let needsUpdate = true; +let fb = null; +let cgl_filter = CGL.Texture.FILTER_LINEAR; +const projectionShader = new CGL.Shader(cgl, "cubemapProjection"); +projectionShader.offScreenPass = true; +const uniformCubemap = new CGL.Uniform(projectionShader, "t", "cubemap", 0); + +projectionShader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); +projectionShader.setSource(attachments.projection_vert, attachments.projection_frag); + +tfilter.onChange = createFb; +inFormat.onChange = createFb; +updateDefines(); +createFb(); + +function createFb() +{ + if (fb)fb.dispose(); + + cgl_filter = CGL.Texture.FILTER_LINEAR; + if (tfilter.get() == "nearest") cgl_filter = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "mipmap") cgl_filter = CGL.Texture.FILTER_MIPMAP; + + if (IS_WEBGL_1) + { + fb = new CGL.Framebuffer(cgl, inWidth.get(), inHeight.get(), { + "isFloatingPointTexture": inFormat.get() == "32bit", + "filter": cgl_filter, + "wrap": CGL.Texture.WRAP_REPEAT + }); + } + else + { + fb = new CGL.Framebuffer2(cgl, inWidth.get(), inHeight.get(), { + "isFloatingPointTexture": inFormat.get() == "32bit", + "filter": cgl_filter, + "wrap": CGL.Texture.WRAP_REPEAT, + }); + } + updateDefines(); + needsUpdate = true; +} + +inWidth.onChange = inHeight.onChange = () => +{ + sizeChanged = true; +}; + +inCubemap.onChange = () => +{ + needsUpdate = true; +}; + +function updateDefines() +{ + projectionShader.toggleDefine("EQUIRECTANGULAR", inProj.get() == "Equirectangular"); + projectionShader.toggleDefine("RGBE", inFormat.get() == "RGBE"); + needsUpdate = true; +} + +inTrigger.onTriggered = function () +{ + if (!inCubemap.get()) + { + outTrigger.trigger(); + return; + } + + if (sizeChanged) + { + if (fb) fb.setSize(inWidth.get(), inHeight.get()); + sizeChanged = false; + needsUpdate = true; + } + + if (needsUpdate) + { + projectionShader.popTextures(); + + fb.renderStart(cgl); + projectionShader.pushTexture(uniformCubemap, inCubemap.get().cubemap, cgl.gl.TEXTURE_CUBE_MAP); + mesh.render(projectionShader); + fb.renderEnd(); + + outProjection.set(CGL.Texture.getEmptyTexture(cgl)); + outProjection.set(fb.getTextureColor()); + needsUpdate = false; + } + outTrigger.trigger(); +}; + + +}; + +Ops.Gl.CubeMap.CubemapToEquirectangularTexture_v2.prototype = new CABLES.Op(); +CABLES.OPS["5e5fa774-ecb1-44dd-8c47-ce4a592f68f1"]={f:Ops.Gl.CubeMap.CubemapToEquirectangularTexture_v2,objName:"Ops.Gl.CubeMap.CubemapToEquirectangularTexture_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.CubeMap.EquirectangularTextureToCubemap +// +// ************************************************************** + +Ops.Gl.CubeMap.EquirectangularTextureToCubemap = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"equirect_to_cube_frag":"#define PI 3.14159265358 //97932384626433832795\n#define PI_TWO 2. * PI\n#define RECIPROCAL_PI 1./PI\n#define RECIPROCAL_PI2 RECIPROCAL_PI/2.\n\nUNI sampler2D equirectangularMap;\nIN vec3 worldPos;\n\nvec4 sampleEquirect(sampler2D tex, vec3 direction) {\nvec2 sampleUV;\nvec3 newDirection = normalize(direction);\n\nsampleUV.x = -1. * (atan( newDirection.z, newDirection.x ) * RECIPROCAL_PI2 + 0.75);\n sampleUV.y = asin( clamp(newDirection.y, -1., 1.) ) * RECIPROCAL_PI + 0.5;\n\n return texture(tex, sampleUV);\n}\n\nvoid main() {\n {{MODULE_BEGIN_FRAG}}\n vec4 col = vec4(1.);\n\n {{MODULE_COLOR}}\n\n outColor = vec4(1., 0., 0., 1.);\n vec3 newPos = worldPos;\n outColor = vec4(sampleEquirect(equirectangularMap, newPos));\n}\n\n","equirect_to_cube_vert":"{{MODULES_HEAD}}\nIN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\nIN float attrVertIndex;\n\nOUT vec2 texCoord;\nOUT vec3 norm;\nOUT vec3 worldPos;\nUNI mat4 projMatrix;\nUNI mat4 viewMatrix;\nUNI mat4 modelMatrix;\n\nvoid main()\n{\n texCoord=attrTexCoord;\n norm=attrVertNormal;\n vec4 pos=vec4(vPosition, 1.0);\n\n {{MODULE_VERTEX_POSITION}}\n\n mat4 mMatrix=modelMatrix;\n worldPos = vec3(mMatrix * pos);\n mat4 rotView = mat4(mat3(viewMatrix)); // remove translation from the view matrix\n vec4 clipPos = projMatrix * rotView * pos;\n\n gl_Position = clipPos.xyww;\n}",}; +const cgl = op.patch.cgl; +const geometry = new CGL.Geometry("unit cube"); + +const inTrigger = op.inTrigger("Trigger In"); +const inTexture = op.inTexture("Equirectangular Map"); + +const inSize = op.inDropDown("Cubemap Size", [32, 64, 128, 256, 512, 1024, 2048], 512); +const inAdvanced = op.inBool("Advanced", false); +const inTextureFilter = op.inSwitch("Filter", ["Nearest", "Linear"], "Linear"); +op.setPortGroup("Cubemap Options", [inSize, inAdvanced, inTextureFilter]); +const outTrigger = op.outTrigger("Trigger Out"); +const outCubemap = op.outTexture("Cubemap Projection"); + +inTextureFilter.setUiAttribs({ "greyout": !inAdvanced.get() }); + +inAdvanced.onChange = () => { return inTextureFilter.setUiAttribs({ "greyout": !inAdvanced.get() }); }; +geometry.vertices = new Float32Array([ + // * NOTE: tex coords not needed for cubemapping + -1.0, 1.0, -1.0, + -1.0, -1.0, -1.0, + 1.0, -1.0, -1.0, + 1.0, -1.0, -1.0, + 1.0, 1.0, -1.0, + -1.0, 1.0, -1.0, + + -1.0, -1.0, 1.0, + -1.0, -1.0, -1.0, + -1.0, 1.0, -1.0, + -1.0, 1.0, -1.0, + -1.0, 1.0, 1.0, + -1.0, -1.0, 1.0, + + 1.0, -1.0, -1.0, + 1.0, -1.0, 1.0, + 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + 1.0, 1.0, -1.0, + 1.0, -1.0, -1.0, + + -1.0, -1.0, 1.0, + -1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + 1.0, -1.0, 1.0, + -1.0, -1.0, 1.0, + + -1.0, 1.0, -1.0, + 1.0, 1.0, -1.0, + 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + -1.0, 1.0, 1.0, + -1.0, 1.0, -1.0, + + -1.0, -1.0, -1.0, + -1.0, -1.0, 1.0, + 1.0, -1.0, -1.0, + 1.0, -1.0, -1.0, + -1.0, -1.0, 1.0, + 1.0, -1.0, 1.0 +]); +const mesh = new CGL.Mesh(cgl, geometry); + +// * FRAMEBUFFER * +let fb = null; +const IS_WEBGL_1 = cgl.glVersion == 1; + +let cubemap = null; + +const equirectToCubeEffect = new CGL.TextureEffect(cgl, { "isFloatingPointTexture": true }); +const equiToCubeShader = new CGL.Shader(cgl, "equirectToCube"); +const uniformEquirectangularMap = new CGL.Uniform(equiToCubeShader, "t", "equirectangularMap", 0); +equiToCubeShader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); +equiToCubeShader.setSource(attachments.equirect_to_cube_vert, attachments.equirect_to_cube_frag); +equiToCubeShader.offScreenPass = true; + +inTexture.onChange = inSize.onChange = inTextureFilter.onChange = resetCubemap; + +let reinitCubemap = true; +function resetCubemap() +{ + reinitCubemap = true; +} + +function createCubemap() +{ + if (!inTexture.get()) + { + return; + } + + if (cubemap) cubemap.dispose(); + cubemap = null; + + if (fb) fb.delete(); + + const textureOptions = { + "isFloatingPointTexture": true, + "filter": CGL.Texture.FILTER_LINEAR, + "wrap": CGL.Texture.WRAP_CLAMP_TO_EDGE, + }; + + if (inAdvanced.get()) + { + textureOptions.filter = CGL.Texture["FILTER_" + inTextureFilter.get().toUpperCase()]; + } + if (IS_WEBGL_1) + { + fb = new CGL.Framebuffer(cgl, Number(inSize.get()), Number(inSize.get()), textureOptions); + } + else + { + fb = new CGL.Framebuffer2(cgl, Number(inSize.get()), Number(inSize.get()), textureOptions); + } + + cubemap = new CGL.CubemapFramebuffer(cgl, Number(inSize.get()), Number(inSize.get()), {}); + reinitCubemap = false; +} + +inTrigger.onTriggered = function () +{ + if (!inTexture.get()) + { + // outCubemap.set(null); + outTrigger.trigger(); + return; + } + + if (reinitCubemap) + { + createCubemap(); + } + + equiToCubeShader.popTextures(); + + cgl.frameStore.renderOffscreen = true; + + if (inTexture.get() && inTexture.get().tex) + { + // fb.renderStart(cgl); + + equiToCubeShader.pushTexture(uniformEquirectangularMap, inTexture.get().tex); + + cgl.pushShader(equiToCubeShader); + + cubemap.renderStart(); + + for (let i = 0; i < 6; i += 1) + { + cubemap.renderStartCubemapFace(i); + mesh.render(equiToCubeShader); + cubemap.renderEndCubemapFace(); + } + + cubemap.renderEnd(); + + cgl.popShader(); + + // fb.renderEnd(); + cgl.frameStore.renderOffscreen = false; + + outCubemap.set(null); + outCubemap.set(cubemap.getTextureColor()); + } + + outTrigger.trigger(); +}; + + +}; + +Ops.Gl.CubeMap.EquirectangularTextureToCubemap.prototype = new CABLES.Op(); +CABLES.OPS["e4cbae17-10bf-44cd-a4e8-4b16dd849d0c"]={f:Ops.Gl.CubeMap.EquirectangularTextureToCubemap,objName:"Ops.Gl.CubeMap.EquirectangularTextureToCubemap"}; + + + + +// ************************************************************** +// +// Ops.Gl.CubeMap.RenderToCubemap_v2 +// +// ************************************************************** + +Ops.Gl.CubeMap.RenderToCubemap_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTrigger = op.inTrigger("Render"), + inFp = op.inBool("32bit float tex", false), + outTrigger = op.outTrigger("Next"), + outTex = op.outTexture("cubemap"); + +const cgl = op.patch.cgl; + +const inSize = op.inDropDown("Size", [32, 64, 128, 256, 512, 1024, 2048], 512); +let sizeChanged = true; +inSize.onChange = () => { return sizeChanged = true; }; + +let fb = null; + +inFp.onChange = createFb; + +let emptyCubemap = null; + +createFb(); + +function createFb() +{ + if (fb)fb.delete(); + fb = new CGL.CubemapFramebuffer( + cgl, + Number(inSize.get()), + Number(inSize.get()), + { + "isFloatingPointTexture": inFp.get() + }); +} + +inTrigger.onTriggered = function () +{ + if (sizeChanged) + { + if (fb) fb.setSize(Number(inSize.get()), Number(inSize.get())); + sizeChanged = false; + } + + if (fb) + { + fb.renderStart(); + for (let i = 0; i < 6; i += 1) + { + fb.renderStartCubemapFace(i); + outTrigger.trigger(); + fb.renderEndCubemapFace(); + } + fb.renderEnd(); + if (!emptyCubemap)emptyCubemap = CGL.Texture.getEmptyCubemapTexture(cgl); + outTex.set(emptyCubemap); + outTex.set(fb.getTextureColor()); + } + else outTrigger.trigger(); +}; + + +}; + +Ops.Gl.CubeMap.RenderToCubemap_v2.prototype = new CABLES.Op(); +CABLES.OPS["2db05f08-ea89-4e56-bba9-8668d963a461"]={f:Ops.Gl.CubeMap.RenderToCubemap_v2,objName:"Ops.Gl.CubeMap.RenderToCubemap_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.CubeMap.Skybox +// +// ************************************************************** + +Ops.Gl.CubeMap.Skybox = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"skybox_frag":"#define PI 3.14159265358 //97932384626433832795\n#define PI_TWO 2. * PI\n#define RECIPROCAL_PI 1./PI\n#define RECIPROCAL_PI2 RECIPROCAL_PI/2.\n\nUNI vec2 expGamma;\n\n\n#ifdef TEX_FORMAT_CUBEMAP\n UNI samplerCube skybox;\n #ifndef WEBGL1\n #define SAMPLETEX texture\n #endif\n #ifdef WEBGL1\n #define SAMPLETEX textureCubeLodEXT\n #endif\n#endif\n\n#ifndef TEX_FORMAT_CUBEMAP\n #define TEX_FORMAT_EQUIRECT\n UNI sampler2D skybox;\n #ifdef WEBGL1\n #ifdef GL_EXT_shader_texture_lod\n #define textureLod texture2DLodEXT\n #endif\n #endif\n #define SAMPLETEX sampleEquirect\n\n#endif\n\nIN vec3 worldPos;\n\nvec4 sampleEquirect(sampler2D tex, vec3 direction) {\n vec2 sampleUV;\n vec3 newDirection = normalize(direction);\n\n sampleUV.x = atan( newDirection.z, newDirection.x ) * RECIPROCAL_PI2 + 0.75;\n sampleUV.y = asin( clamp(newDirection.y, -1., 1.) ) * RECIPROCAL_PI + 0.5;\n\n return texture(tex, sampleUV);\n}\n\nhighp vec3 DecodeRGBE8(highp vec4 rgbe)\n{\n highp vec3 vDecoded = rgbe.rgb * pow(2.0, rgbe.a * 255.0-128.0);\n return vDecoded;\n}\n\nvoid main() {\n {{MODULE_BEGIN_FRAG}}\n vec4 col = vec4(1.);\n\n {{MODULE_COLOR}}\n\n vec3 newPos = worldPos;\n\n vec4 finalColor;\n #ifndef RGBE\n finalColor = vec4(SAMPLETEX(skybox, newPos));\n #endif\n\n #ifdef RGBE\n finalColor.rgb=DecodeRGBE8(SAMPLETEX(skybox, newPos));\n #endif\n\n float gamma=expGamma.x;\n float exposure=expGamma.y;\n finalColor.rgb = vec3(1.0) - exp(-finalColor.rgb * exposure);\n\n finalColor.rgb = pow(finalColor.rgb, vec3(1.0 / gamma));\n outColor=vec4(finalColor.rgb,1.0);\n\n}\n","skybox_vert":"{{MODULES_HEAD}}\nIN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\nIN float attrVertIndex;\n\nOUT vec2 texCoord;\nOUT vec3 norm;\nOUT vec3 worldPos;\nUNI mat4 projMatrix;\nUNI mat4 viewMatrix;\nUNI mat4 modelMatrix;\n\nvoid main()\n{\n texCoord=attrTexCoord;\n norm=attrVertNormal;\n vec4 pos=vec4(vPosition, 1.0);\n\n {{MODULE_VERTEX_POSITION}}\n\n mat4 mMatrix=modelMatrix;\n worldPos = vec3(mMatrix * pos);\n mat4 rotView = mat4(mat3(viewMatrix)); // remove translation from the view matrix\n vec4 clipPos = projMatrix * rotView * pos;\n\n gl_Position = clipPos.xyww;\n}",}; +const + cgl = op.patch.cgl, + inTrigger = op.inTrigger("Trigger In"), + inRender = op.inBool("Render", true), + inTexture = op.inTexture("Skybox"), + inRot = op.inFloat("Rotate", 0), + + inRGBE = op.inBool("RGBE Format", false), + inExposure = op.inFloat("Exposure", 1), + inGamma = op.inFloat("Gamma", 2.2), + + outTrigger = op.outTrigger("Trigger Out"); + +const geometry = new CGL.Geometry("unit cube"); + +geometry.vertices = new Float32Array([ + // * NOTE: tex coords not needed for cubemapping + -1.0, 1.0, -1.0, + -1.0, -1.0, -1.0, + 1.0, -1.0, -1.0, + 1.0, -1.0, -1.0, + 1.0, 1.0, -1.0, + -1.0, 1.0, -1.0, + + -1.0, -1.0, 1.0, + -1.0, -1.0, -1.0, + -1.0, 1.0, -1.0, + -1.0, 1.0, -1.0, + -1.0, 1.0, 1.0, + -1.0, -1.0, 1.0, + + 1.0, -1.0, -1.0, + 1.0, -1.0, 1.0, + 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + 1.0, 1.0, -1.0, + 1.0, -1.0, -1.0, + + -1.0, -1.0, 1.0, + -1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + 1.0, -1.0, 1.0, + -1.0, -1.0, 1.0, + + -1.0, 1.0, -1.0, + 1.0, 1.0, -1.0, + 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + -1.0, 1.0, 1.0, + -1.0, 1.0, -1.0, + + -1.0, -1.0, -1.0, + -1.0, -1.0, 1.0, + 1.0, -1.0, -1.0, + 1.0, -1.0, -1.0, + -1.0, -1.0, 1.0, + 1.0, -1.0, 1.0 +]); + +const mesh = new CGL.Mesh(cgl, geometry); +const skyboxShader = new CGL.Shader(cgl, "skybox"); +const uniformSkybox = new CGL.Uniform(skyboxShader, "t", "skybox", 0); +const uniExposure = new CGL.Uniform(skyboxShader, "2f", "expGamma", inExposure, inGamma); + +skyboxShader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); +skyboxShader.setSource(attachments.skybox_vert, attachments.skybox_frag); +skyboxShader.offScreenPass = true; + +inRGBE.onChange = () => +{ + skyboxShader.toggleDefine("RGBE", inRGBE.get()); +}; + +inTexture.onChange = () => +{ + const b = inTexture.get() && inTexture.get().cubemap; + + skyboxShader.toggleDefine("TEX_FORMAT_CUBEMAP", b); + skyboxShader.toggleDefine("TEX_FORMAT_EQUIRECT", !b); +}; + +inTrigger.onTriggered = () => +{ + if (!inTexture.get() || !inRender.get()) + { + outTrigger.trigger(); + return; + } + + skyboxShader.popTextures(); + + cgl.pushModelMatrix(); + + if (!inTexture.get().cubemap && inTexture.get().filter !== CGL.Texture.FILTER_LINEAR) + op.setUiError("linearFilter", "If there is a seam in the skybox, try changing the texture filter to linear!", 0); + else + op.setUiError("linearFilter", null); + + mat4.rotateY(cgl.mMatrix, cgl.mMatrix, inRot.get() * CGL.DEG2RAD); + + if (inTexture.get().tex) + skyboxShader.pushTexture(uniformSkybox, inTexture.get().tex); + else if (inTexture.get().cubemap) + skyboxShader.pushTexture(uniformSkybox, inTexture.get().cubemap, cgl.gl.TEXTURE_CUBE_MAP); + + mesh.render(skyboxShader); + + cgl.popModelMatrix(); + cgl.popDepthFunc(); + + outTrigger.trigger(); +}; + + +}; + +Ops.Gl.CubeMap.Skybox.prototype = new CABLES.Op(); +CABLES.OPS["97ce1d35-bd7a-43cb-a2bf-5b7e37fb8925"]={f:Ops.Gl.CubeMap.Skybox,objName:"Ops.Gl.CubeMap.Skybox"}; + + + + +// ************************************************************** +// +// Ops.Gl.DepthTest +// +// ************************************************************** + +Ops.Gl.DepthTest = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// todo:rename to depthtest + +const render = op.inTrigger("Render"); +const enable = op.inValueBool("Enable depth testing", true); +const meth = op.inValueSelect("Depth Test Method", ["never", "always", "less", "less or equal", "greater", "greater or equal", "equal", "not equal"], "less or equal"); +const write = op.inValueBool("Write to depth buffer", true); +const trigger = op.outTrigger("Next"); + +const cgl = op.patch.cgl; +let compareMethod = cgl.gl.LEQUAL; + +meth.onChange = updateFunc; + +function updateFunc() +{ + if (meth.get() == "never") compareMethod = cgl.gl.NEVER; + else if (meth.get() == "always") compareMethod = cgl.gl.ALWAYS; + else if (meth.get() == "less") compareMethod = cgl.gl.LESS; + else if (meth.get() == "less or equal") compareMethod = cgl.gl.LEQUAL; + else if (meth.get() == "greater") compareMethod = cgl.gl.GREATER; + else if (meth.get() == "greater or equal") compareMethod = cgl.gl.GEQUAL; + else if (meth.get() == "equal") compareMethod = cgl.gl.EQUAL; + else if (meth.get() == "not equal") compareMethod = cgl.gl.NOTEQUAL; +} + +render.onTriggered = function () +{ + cgl.pushDepthTest(enable.get()); + cgl.pushDepthWrite(write.get()); + cgl.pushDepthFunc(compareMethod); + + trigger.trigger(); + + cgl.popDepthTest(); + cgl.popDepthWrite(); + cgl.popDepthFunc(); +}; + + +}; + +Ops.Gl.DepthTest.prototype = new CABLES.Op(); +CABLES.OPS["3996ed5d-8143-4bec-9cfd-c1b193a295af"]={f:Ops.Gl.DepthTest,objName:"Ops.Gl.DepthTest"}; + + + + +// ************************************************************** +// +// Ops.Gl.DirectionalTranslate +// +// ************************************************************** + +Ops.Gl.DirectionalTranslate = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Exec"), + inMatrix = op.inArray("Center Model Matrix"), + inAmount = op.inValue("Amount"), + next = op.outTrigger("Next"); + +const cgl = op.patch.cgl; + +let va = vec3.create(); +let vb = vec3.create(); +let diff = vec3.create(); +let mm = mat3.create(); + +exec.onTriggered = function () +{ + let matbefore = inMatrix.get(); + if (!matbefore) return; + + mat4.getTranslation(va, matbefore); + mat4.getTranslation(vb, cgl.modelMatrix()); + + mat3.fromMat4(mm, cgl.modelMatrix()); + mat3.invert(mm, mm); + + vec3.sub(diff, vb, va); + vec3.normalize(diff, diff); + vec3.transformMat3(diff, diff, mm); + vec3.normalize(diff, diff); + + diff[0] *= inAmount.get(); + diff[1] *= inAmount.get(); + diff[2] *= inAmount.get(); + + cgl.pushModelMatrix(); + mat4.translate(cgl.mMatrix, cgl.mMatrix, diff); + next.trigger(); + cgl.popModelMatrix(); +}; + + +}; + +Ops.Gl.DirectionalTranslate.prototype = new CABLES.Op(); +CABLES.OPS["d0f3dbca-7457-44b5-987a-9d49e5310d98"]={f:Ops.Gl.DirectionalTranslate,objName:"Ops.Gl.DirectionalTranslate"}; + + + + +// ************************************************************** +// +// Ops.Gl.DownloadTexture_v2 +// +// ************************************************************** + +Ops.Gl.DownloadTexture_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTex = op.inTexture("Texture"), + start = op.inTriggerButton("Download"), + fileName = op.inString("Filename", "screenshot"), + outFinished = op.outBoolNum("Finished"); + +const gl = op.patch.cgl.gl; +let fb = null; + +start.onTriggered = function () +{ + if (!inTex.get() || !inTex.get().tex) return; + outFinished.set(false); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); + + const width = inTex.get().width; + const height = inTex.get().height; + + if (inTex.get().textureType == CGL.Texture.TYPE_FLOAT) op.setUiError("fptex", "Texture is more than 8 bit, not possible to create files with high precision"); + else op.setUiError("fptex", null); + + if (!fb)fb = gl.createFramebuffer(); + + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, inTex.get().tex, 0); + + const canRead = (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + if (!canRead) + { + outFinished.set(true); + op.logError("cannot read texture!"); + return; + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + const data = new Uint8Array(width * height * 4); + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + // Create a 2D canvas to store the result + const canvas = document.createElement("canvas"); + canvas.width = width; + canvas.height = height; + const context = canvas.getContext("2d"); + + // Copy the pixels to a 2D canvas + const imageData = context.createImageData(width, height); + imageData.data.set(data); + + const data2 = imageData.data; + + // flip image + Array.from({ "length": height }, (val, i) => { return data2.slice(i * width * 4, (i + 1) * width * 4); }) + .forEach((val, i) => { return data2.set(val, (height - i - 1) * width * 4); }); + + context.putImageData(imageData, 0, 0); + + dataURIToBlob(canvas.toDataURL(), + function (blob) + { + const userAgent = navigator.userAgent || navigator.vendor || window.opera; + + if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) + { + const reader = new FileReader(); + // var out = new Blob([byte], {type: "application/pdf"}); + reader.onload = function (e) + { + window.location.href = reader.result; + // window.open(reader.result); + }; + reader.readAsDataURL(blob); + } + else + { + const anchor = document.createElement("a"); + anchor.download = fileName.get() + ".png"; + // anchor.target='_blank'; + anchor.href = URL.createObjectURL(blob); + document.body.appendChild(anchor); + anchor.click(); + } + outFinished.set(true); + }); +}; + +function dataURIToBlob(dataURI, callback) +{ + const binStr = atob(dataURI.split(",")[1]), + len = binStr.length, + arr = new Uint8Array(len); + for (let i = 0; i < len; i++) arr[i] = binStr.charCodeAt(i); + callback(new Blob([arr], { "type": "image/png" })); +} + + +}; + +Ops.Gl.DownloadTexture_v2.prototype = new CABLES.Op(); +CABLES.OPS["00d2a6ea-5843-43d0-9428-dbc47c112e6e"]={f:Ops.Gl.DownloadTexture_v2,objName:"Ops.Gl.DownloadTexture_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.DrawTextureMapping +// +// ************************************************************** + +Ops.Gl.DrawTextureMapping = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Render"), + inGeom = op.inObject("Geometry", null, "geometry"), + numPoints = op.inValue("Num Points"), + next = op.outTrigger("Next"); + +let cgl = op.patch.cgl; + +let mesh = null; +let attr = null; +let points = []; + +inGeom.onChange = function () +{ + let geom = inGeom.get(); + + if (!geom || !geom.verticesIndices) return; + + points.length = 0; + let newgeom = new CGL.Geometry("texturemapping"); + + for (let i = 0; i < geom.verticesIndices.length; i += 3) + { + var index; + + index = geom.verticesIndices[i + 0]; + points.push(geom.texCoords[index * 2 + 0]); + points.push(geom.texCoords[index * 2 + 1]); + points.push(0); + + index = geom.verticesIndices[i + 1]; + points.push(geom.texCoords[index * 2 + 0]); + points.push(geom.texCoords[index * 2 + 1]); + points.push(0); + + index = geom.verticesIndices[i + 1]; + points.push(geom.texCoords[index * 2 + 0]); + points.push(geom.texCoords[index * 2 + 1]); + points.push(0); + + index = geom.verticesIndices[i + 2]; + points.push(geom.texCoords[index * 2 + 0]); + points.push(geom.texCoords[index * 2 + 1]); + points.push(0); + + index = geom.verticesIndices[i + 2]; + points.push(geom.texCoords[index * 2 + 0]); + points.push(geom.texCoords[index * 2 + 1]); + points.push(0); + + index = geom.verticesIndices[i + 0]; + points.push(geom.texCoords[index * 2 + 0]); + points.push(geom.texCoords[index * 2 + 1]); + points.push(0); + } + + newgeom.vertices = points; + + // if(!mesh) + mesh = new CGL.Mesh(cgl, newgeom); + + // else mesh.setGeom(geom ); + // if(!(points instanceof Float32Array)) + // { + // if(points.length!=buff.length) + // { + // buff=new Float32Array(points.length); + // buff.set(points); + // } + // else + // { + // buff.set(points); + // } + // } + // else + // { + // buff=points; + // } + // attr=mesh.setAttribute(CGL.SHADERVAR_VERTEX_POSITION,buff,3); +}; + +render.onTriggered = function () +{ + if (points.length === 0) return; + if (!mesh) return; + if (op.instanced(render)) return; + + let shader = cgl.getShader(); + if (!shader) return; + + let oldPrim = shader.glPrimitive; + + shader.glPrimitive = cgl.gl.LINES; + + // if(numPoints.get()<=0)attr.numItems=buff.length/3; + // else attr.numItems=Math.min(numPoints.get(),buff.length/3); + + mesh.render(shader); + + shader.glPrimitive = oldPrim; + + next.trigger(); +}; + + +}; + +Ops.Gl.DrawTextureMapping.prototype = new CABLES.Op(); +CABLES.OPS["f61e47de-9156-4243-9a83-79002aeaf7be"]={f:Ops.Gl.DrawTextureMapping,objName:"Ops.Gl.DrawTextureMapping"}; + + + + +// ************************************************************** +// +// Ops.Gl.FaceCulling_v2 +// +// ************************************************************** + +Ops.Gl.FaceCulling_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + STR_FRONT = "Front Sides", + STR_BACK = "Back Sides", + STR_BOTH = "All", + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + facing = op.inSwitch("Discard", [STR_BACK, STR_FRONT, STR_BOTH], STR_BACK), + enable = op.inValueBool("Active", true), + cgl = op.patch.cgl; + +op.setPortGroup("Face Fulling", [enable, facing]); +let whichFace = cgl.gl.BACK; + +render.onTriggered = function () +{ + cgl.pushCullFace(enable.get()); + cgl.pushCullFaceFacing(whichFace); + + trigger.trigger(); + + cgl.popCullFace(); + cgl.popCullFaceFacing(); +}; + +facing.onChange = function () +{ + whichFace = cgl.gl.BACK; + if (facing.get() == STR_FRONT) whichFace = cgl.gl.FRONT; + else if (facing.get() == STR_BOTH) whichFace = cgl.gl.FRONT_AND_BACK; +}; + + +}; + +Ops.Gl.FaceCulling_v2.prototype = new CABLES.Op(); +CABLES.OPS["9dfd0ee4-81e1-438c-8a99-4894c64f41cb"]={f:Ops.Gl.FaceCulling_v2,objName:"Ops.Gl.FaceCulling_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.FontMSDF_v2 +// +// ************************************************************** + +Ops.Gl.FontMSDF_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inUUID = op.inString("Font Name", CABLES.uuid()), + urlData = op.inUrl("Font Data"), + urlTex = op.inUrl("Font Image"), + urlTex1 = op.inUrl("Font Image 1"), + urlTex2 = op.inUrl("Font Image 2"), + urlTex3 = op.inUrl("Font Image 3"), + outLoaded = op.outBool("Loaded"), + outNumChars = op.outNumber("Total Chars"), + outChars = op.outString("Chars"), + cgl = op.patch.cgl; + +let + loadedData = false, + loadedTex = false, + loadingId = 0; + +inUUID.onChange = +urlData.onChange = + urlTex.onChange = + urlTex1.onChange = + urlTex2.onChange = + urlTex3.onChange = load; + +const textures = []; + +function updateLoaded() +{ + const l = loadedData && loadedTex; + if (!outLoaded.get() && l) op.patch.emitEvent("FontLoadedMSDF"); + outLoaded.set(l); +} + +op.onFileChanged = function (fn) +{ + if ( + (urlTex.get() && urlTex.get().indexOf(fn) > -1) || + (urlTex1.get() && urlTex1.get().indexOf(fn) > -1) || + (urlTex2.get() && urlTex2.get().indexOf(fn) > -1) || + (urlTex3.get() && urlTex3.get().indexOf(fn) > -1)) + { + load(); + } +}; + +let oldUUID = ""; + +function load() +{ + if (!urlData.get() || !urlTex.get()) return; + + textures.length = 0; + op.patch.deleteVar("font_data_" + oldUUID); + op.patch.deleteVar("font_tex_" + oldUUID); + oldUUID = inUUID.get(); + + const varNameData = "font_data_" + inUUID.get(); + const varNameTex = "font_tex_" + inUUID.get(); + + op.patch.setVarValue(varNameData, {}); + op.patch.setVarValue(varNameTex, textures); + + op.patch.getVar(varNameData).type = "fontData"; + op.patch.getVar(varNameTex).type = "fontTexture"; + + loadedData = loadedTex = false; + updateLoaded(); + + op.patch.loading.finished(loadingId); + loadingId = op.patch.loading.start("jsonFile", "" + urlData.get()); + + op.setUiError("invaliddata", null); + op.setUiError("jsonerr", null); + op.setUiError("texurlerror", null); + + const urlDatastr = op.patch.getFilePath(String(urlData.get())); + + // load font data json + cgl.patch.loading.addAssetLoadingTask(() => + { + CABLES.ajax(urlDatastr, (err, _data, xhr) => + { + if (err) + { + op.logError(err); + return; + } + try + { + let data = _data; + if (typeof data === "string") data = JSON.parse(_data); + if (!data.chars || !data.info || !data.info.face) + { + op.setUiError("invaliddata", "data file is invalid"); + return; + } + + outNumChars.set(data.chars.length); + let allChars = ""; + for (let i = 0; i < data.chars.length; i++)allChars += data.chars[i].char; + outChars.set(allChars); + + op.setUiAttrib({ "extendTitle": data.info.face }); + op.patch.setVarValue(varNameData, null); + op.patch.setVarValue(varNameData, + { + "name": CABLES.basename(urlData.get()), + "basename": inUUID.get(), + "data": data + }); + + op.patch.loading.finished(loadingId); + loadedData = true; + updateLoaded(); + } + catch (e) + { + op.patch.setVarValue(varNameData, null); + op.patch.setVarValue(varNameTex, null); + + op.logError(e); + op.setUiError("jsonerr", "Problem while loading json:
" + e); + op.patch.loading.finished(loadingId); + updateLoaded(); + outLoaded.set(false); + } + }); + }); + + // load font texture + + for (let i = 0; i < 4; i++) + { + const num = i; + + let texPort = urlTex; + if (i == 1)texPort = urlTex1; + if (i == 2)texPort = urlTex2; + if (i == 3)texPort = urlTex3; + + if (!texPort.get()) continue; + + const loadingIdTex = cgl.patch.loading.start("textureOp", texPort.get()); + const urlTexstr = op.patch.getFilePath(String(texPort.get())); + + CGL.Texture.load(cgl, urlTexstr, + function (err, tex) + { + if (err) + { + op.setUiError("texurlerror", "could not load texture"); + cgl.patch.loading.finished(loadingIdTex); + loadedTex = false; + return; + } + textures[num] = tex; + op.patch.setVarValue(varNameTex, null); + op.patch.setVarValue(varNameTex, textures); + + loadedTex = true; + cgl.patch.loading.finished(loadingIdTex); + updateLoaded(); + }, { + "filter": CGL.Texture.FILTER_LINEAR, + "flip": false + }); + } +} + + +}; + +Ops.Gl.FontMSDF_v2.prototype = new CABLES.Op(); +CABLES.OPS["6cbd5d67-25d5-4936-a2ad-3ee8ed478570"]={f:Ops.Gl.FontMSDF_v2,objName:"Ops.Gl.FontMSDF_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.ForceCanvasSize +// +// ************************************************************** + +Ops.Gl.ForceCanvasSize = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTrigger = op.inTrigger("Trigger"), + inActive = op.inBool("Active", true), + inWhat = op.inSwitch("Force", ["Resolution", "Aspect Ratio"], "Resolution"), + inCenter = op.inBool("Center In Parent", true), + inScaleFit = op.inBool("Scale to fit Parent", false), + inWidth = op.inInt("Set Width", 300), + inHeight = op.inInt("Set Height", 200), + inPresets = op.inDropDown("Aspect Ratio", ["Custom", "21:9", "2:1", "16:9", "16:10", "4:3", "1:1", "9:16", "1:2", "iPhoneXr Vert"], "16:9"), + inRatio = op.inFloat("Ratio", 0), + inStretch = op.inDropDown("Fill Parent", ["Auto", "Width", "Height", "Both"], "Auto"), + next = op.outTrigger("Next"), + outWidth = op.outNumber("Width"), + outHeight = op.outNumber("Height"), + outMarginLeft = op.outNumber("Margin Left"), + outMarginTop = op.outNumber("Margin Top"); + +op.setPortGroup("Size", [inWidth, inHeight]); +op.setPortGroup("Proportions", [inRatio, inStretch, inPresets]); + +let align = 0; +const ALIGN_NONE = 0; +const ALIGN_WIDTH = 1; +const ALIGN_HEIGHT = 2; +const ALIGN_BOTH = 3; +const ALIGN_AUTO = 4; + +inStretch.onChange = updateUi; +inWhat.onChange = updateMethod; +inCenter.onChange = + inTrigger.onLinkChanged = removeStyles; + +inPresets.onChange = updateRatioPreset; + +const cgl = op.patch.cgl; + +if (window.getComputedStyle(cgl.canvas).position === "absolute") +{ + cgl.canvas.style.position = "initial"; + op.warn("[cables forceCanvasSize] - canvas was positioned absolute, not compatible with Ops.Gl.ForceCanvasSize"); +} + +updateUi(); + +function updateMethod() +{ + if (inWhat.get() == "Aspect Ratio") + { + inRatio.set(100); + updateRatioPreset(); + } + updateUi(); +} + +function updateRatioPreset() +{ + const pr = inPresets.get(); + if (pr == "Custom") return; + else if (pr == "16:9")inRatio.set(16 / 9); + else if (pr == "4:3")inRatio.set(4 / 3); + else if (pr == "16:10")inRatio.set(16 / 10); + else if (pr == "21:9")inRatio.set(21 / 9); + else if (pr == "2:1")inRatio.set(2); + else if (pr == "1:1")inRatio.set(1); + else if (pr == "9:16")inRatio.set(9 / 16); + else if (pr == "1:2")inRatio.set(0.5); + else if (pr == "iPhoneXr Vert")inRatio.set(9 / 19.5); +} + +inRatio.onChange = () => +{ + removeStyles(); +}; + +inActive.onChange = function () +{ + if (!inActive.get())removeStyles(); +}; + +function updateUi() +{ + const forceRes = inWhat.get() == "Resolution"; + inWidth.setUiAttribs({ "greyout": !forceRes }); + inHeight.setUiAttribs({ "greyout": !forceRes }); + + inPresets.setUiAttribs({ "greyout": forceRes }); + inStretch.setUiAttribs({ "greyout": forceRes }); + inRatio.setUiAttribs({ "greyout": forceRes }); + + align = 0; + + if (!forceRes) + { + const strAlign = inStretch.get(); + if (strAlign == "Width")align = ALIGN_WIDTH; + else if (strAlign == "Height")align = ALIGN_HEIGHT; + else if (strAlign == "Both")align = ALIGN_BOTH; + else if (strAlign == "Auto")align = ALIGN_AUTO; + } +} + +function removeStyles() +{ + cgl.canvas.style["margin-top"] = ""; + cgl.canvas.style["margin-left"] = ""; + + outMarginLeft.set(0); + outMarginTop.set(0); + + const rect = cgl.canvas.parentNode.getBoundingClientRect(); + cgl.setSize(rect.width, rect.height); +} + +inTrigger.onTriggered = function () +{ + if (!inActive.get()) return next.trigger(); + + let w = inWidth.get(); + let h = inHeight.get(); + + let clientRect = cgl.canvas.parentNode.getBoundingClientRect(); + if (clientRect.height == 0) + { + cgl.canvas.parentNode.style.height = "100%"; + clientRect = cgl.canvas.parentNode.getBoundingClientRect(); + } + if (clientRect.width == 0) + { + cgl.canvas.parentNode.style.width = "100%"; + clientRect = cgl.canvas.parentNode.getBoundingClientRect(); + } + + if (align == ALIGN_WIDTH) + { + w = clientRect.width; + h = w * 1 / inRatio.get(); + } + else if (align == ALIGN_HEIGHT) + { + h = clientRect.height; + w = h * inRatio.get(); + } + else if (align == ALIGN_AUTO) + { + const rect = clientRect; + + h = rect.height; + w = h * inRatio.get(); + + if (w > rect.width) + { + w = rect.width; + h = w * 1 / inRatio.get(); + } + } + else if (align == ALIGN_BOTH) + { + const rect = clientRect; + h = rect.height; + w = h * inRatio.get(); + + if (w < rect.width) + { + w = rect.width; + h = w * 1 / inRatio.get(); + } + } + + w = Math.ceil(w); + h = Math.ceil(h); + + if (inCenter.get()) + { + const rect = clientRect; + + const t = (rect.height - h) / 2; + const l = (rect.width - w) / 2; + + outMarginLeft.set(l); + outMarginTop.set(t); + + cgl.canvas.style["margin-top"] = t + "px"; + cgl.canvas.style["margin-left"] = l + "px"; + } + else + { + cgl.canvas.style["margin-top"] = "0"; + cgl.canvas.style["margin-left"] = "0"; + + outMarginLeft.set(0); + outMarginTop.set(0); + } + + if (inScaleFit.get()) + { + const rect = clientRect; + const scX = rect.width / inWidth.get(); + const scY = rect.height / inHeight.get(); + cgl.canvas.style.transform = "scale(" + Math.min(scX, scY) + ")"; + } + else + { + cgl.canvas.style.transform = "scale(1)"; + } + + if (cgl.canvas.width / cgl.pixelDensity != w || cgl.canvas.height / cgl.pixelDensity != h) + { + outWidth.set(w); + outHeight.set(h); + cgl.setSize(w, h); + } + // else + next.trigger(); +}; + + +}; + +Ops.Gl.ForceCanvasSize.prototype = new CABLES.Op(); +CABLES.OPS["a8b3380e-cd4a-4000-9ee9-1c65a11027dd"]={f:Ops.Gl.ForceCanvasSize,objName:"Ops.Gl.ForceCanvasSize"}; + + + + +// ************************************************************** +// +// Ops.Gl.GLTF.GltfAnimationArray +// +// ************************************************************** + +Ops.Gl.GLTF.GltfAnimationArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Render"), + inNodeName = op.inString("Node Name"), + inNum = op.inInt("Steps", 100), + inFullAnim = op.inBool("Full Animation", true), + inAnimStart = op.inFloat("Start", 0), + inAnimLen = op.inFloat("Length", 10), + next = op.outTrigger("Next"), + outFound = op.outBool("Found"), + outArr = op.outArray("Positions"); + +const cgl = op.patch.cgl; + +op.setPortGroup("Timing", [inFullAnim, inAnimStart, inAnimLen]); +let node = null; + +inFullAnim.onChange = function () +{ + inAnimStart.setUiAttribs({ "greyout": inFullAnim.get() }); + inAnimLen.setUiAttribs({ "greyout": inFullAnim.get() }); +}; + +inNodeName.onChange = function () +{ + outArr.set(null); + node = null; + outFound.set(false); +}; + +inExec.onTriggered = function () +{ + if (!cgl.frameStore.currentScene) return; + + if (!node) + { + const name = inNodeName.get(); + + if (!cgl.frameStore || !cgl.frameStore.currentScene || !cgl.frameStore.currentScene.nodes) + { + return; + } + + for (var i = 0; i < cgl.frameStore.currentScene.nodes.length; i++) + { + if (cgl.frameStore.currentScene.nodes[i].name == name) + { + node = cgl.frameStore.currentScene.nodes[i]; + outFound.set(true); + } + } + } + + // var idx=inNode.get(); + // idx=Math.max(0,idx); + // idx=Math.min(cgl.frameStore.currentScene.nodes.length-1,idx); + + const n = node; + const arr = []; + + if (n && n._animTrans && n._animTrans.length) + { + outArr.set(null); + + const num = inNum.get(); + let len = n._animTrans[0].getLength(); + let add = 0; + + if (!inFullAnim.get()) + { + len = inAnimLen.get(); + add = inAnimStart.get(); + } + + for (var i = 0; i < num; i++) + { + const t = len * i / num + add; + + arr[i * 3 + 0] = n._animTrans[0].getValue(t); + arr[i * 3 + 1] = n._animTrans[1].getValue(t); + arr[i * 3 + 2] = n._animTrans[2].getValue(t); + } + + outArr.set(arr); + } + + next.trigger(); +}; + + +}; + +Ops.Gl.GLTF.GltfAnimationArray.prototype = new CABLES.Op(); +CABLES.OPS["568ce7cd-a938-4498-9109-482564757a0e"]={f:Ops.Gl.GLTF.GltfAnimationArray,objName:"Ops.Gl.GLTF.GltfAnimationArray"}; + + + + +// ************************************************************** +// +// Ops.Gl.GLTF.GltfCameraViewMatrix +// +// ************************************************************** + +Ops.Gl.GLTF.GltfCameraViewMatrix = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Update"), + inName = op.inString("Node Name", "default"), + outArr = op.outArray("Matrix"), + outFound = op.outBool("Found"); + +let camNode = null; + +inExec.onTriggered = () => +{ + if (!camNode) findCam(); + + if (camNode) + { + camNode.start(0); + camNode.end(); + outArr.set(camNode.vMat); + } +}; + +inName.onChange = () => { camNode = null; }; + +function findCam() +{ + const gltf = op.patch.cgl.frameStore.currentScene; + + if (gltf) + { + gltf.cameras = gltf.cameras || []; + for (let i = 0; i < gltf.cameras.length; i++) + { + if (gltf.cameras[i].name == inName.get()) + { + camNode = gltf.cameras[i]; + outFound.set(true); + return; + } + } + } + + outFound.set(false); +} + + +}; + +Ops.Gl.GLTF.GltfCameraViewMatrix.prototype = new CABLES.Op(); +CABLES.OPS["ab3c43f7-3d73-4f46-8034-454e9c4d51c5"]={f:Ops.Gl.GLTF.GltfCameraViewMatrix,objName:"Ops.Gl.GLTF.GltfCameraViewMatrix"}; + + + + +// ************************************************************** +// +// Ops.Gl.GLTF.GltfDracoCompression +// +// ************************************************************** + +Ops.Gl.GLTF.GltfDracoCompression = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +class DracoDecoderClass +{ + constructor() + { + this.workerLimit = 4; + this.workerPool = []; + this.workerNextTaskID = 1; + this.workerSourceURL = ""; + + this.config = { + "wasm": Uint8Array.from(atob(DracoDecoderWASM), (c) => { return c.charCodeAt(0); }), + "wrapper": DracoWASMWrapperCode, + "decoderSettings": {}, + }; + + const dracoWorker = this._DracoWorker.toString(); + const workerCode = dracoWorker.substring(dracoWorker.indexOf("{") + 1, dracoWorker.lastIndexOf("}")); + + const jsContent = this.config.wrapper; + const body = [ + "/* draco decoder */", + jsContent, + "", + "/* worker */", + workerCode + ].join("\n"); + + this.workerSourceURL = URL.createObjectURL(new Blob([body])); + } + + _getWorker(taskID, taskCost) + { + if (this.workerPool.length < this.workerLimit) + { + const worker = new Worker(this.workerSourceURL); + worker._callbacks = {}; + worker._taskCosts = {}; + worker._taskLoad = 0; + worker.postMessage({ "type": "init", "decoderConfig": this.config }); + worker.onmessage = (e) => + { + const message = e.data; + + switch (message.type) + { + case "done": + worker._callbacks[message.taskID].finishedCallback(message.geometry); + break; + + case "error": + worker._callbacks[message.taskID].errorCallback(message); + break; + + default: + op.error("THREE.DRACOLoader: Unexpected message, \"" + message.type + "\""); + } + this._releaseTask(worker, message.taskID); + }; + this.workerPool.push(worker); + } + else + { + this.workerPool.sort(function (a, b) + { + return a._taskLoad > b._taskLoad ? -1 : 1; + }); + } + + const worker = this.workerPool[this.workerPool.length - 1]; + worker._taskCosts[taskID] = taskCost; + worker._taskLoad += taskCost; + return worker; + } + + decodeGeometry(buffer, finishedCallback, errorCallback = null) + { + const taskID = this.workerNextTaskID++; + const taskCost = buffer.byteLength; + + const worker = this._getWorker(taskID, taskCost); + worker._callbacks[taskID] = { finishedCallback, errorCallback }; + worker.postMessage({ "type": "decode", "taskID": taskID, buffer }, [buffer]); + } + + _releaseTask(worker, taskID) + { + worker._taskLoad -= worker._taskCosts[taskID]; + delete worker._callbacks[taskID]; + delete worker._taskCosts[taskID]; + } + + _DracoWorker() + { + let pendingDecoder; + + onmessage = function (e) + { + const message = e.data; + switch (message.type) + { + case "init": + const decoderConfig = message.decoderConfig; + const moduleConfig = decoderConfig.decoderSettings; + pendingDecoder = new Promise(function (resolve) + { + moduleConfig.onModuleLoaded = function (draco) + { + // Module is Promise-like. Wrap before resolving to avoid loop. + resolve({ "draco": draco }); + }; + moduleConfig.wasmBinary = decoderConfig.wasm; + DracoDecoderModule(moduleConfig); // eslint-disable-line no-undef + }); + break; + case "decode": + pendingDecoder.then((module) => + { + const draco = module.draco; + + const f = new draco.Decoder(); + const dataBuff = new Int8Array(message.buffer); + + const geometryType = f.GetEncodedGeometryType(dataBuff); + const buffer = new draco.DecoderBuffer(); + buffer.Init(dataBuff, dataBuff.byteLength); + + let outputGeometry = new draco.Mesh(); + const status = f.DecodeBufferToMesh(buffer, outputGeometry); + const attribute = f.GetAttributeByUniqueId(outputGeometry, 1); + const geometry = dracoAttributes(draco, f, outputGeometry, geometryType, name); + + this.postMessage({ "type": "done", "taskID": message.taskID, "geometry": geometry }); + + draco.destroy(f); + draco.destroy(buffer); + }); + break; + } + }; + + let dracoAttributes = function (draco, decoder, dracoGeometry, geometryType, name) + { + const attributeIDs = { + "position": draco.POSITION, + "normal": draco.NORMAL, + "color": draco.COLOR, + "uv": draco.TEX_COORD, + "joints": draco.GENERIC, + "weights": draco.GENERIC, + }; + const attributeTypes = { + "position": "Float32Array", + "normal": "Float32Array", + "color": "Float32Array", + "weights": "Float32Array", + "joints": "Uint8Array", + "uv": "Float32Array" + }; + + const geometry = { + "index": null, + "attributes": [] + }; + + let count = 0; + for (const attributeName in attributeIDs) + { + const attributeType = attributeTypes[attributeName]; + let attributeID = decoder.GetAttributeId(dracoGeometry, attributeIDs[attributeName]); + + count++; + if (attributeID != -1) + { + let attribute = decoder.GetAttribute(dracoGeometry, attributeID); + geometry.attributes.push(decodeAttribute(draco, decoder, dracoGeometry, attributeName, attributeType, attribute)); + } + } + + if (geometryType === draco.TRIANGULAR_MESH) geometry.index = decodeIndex(draco, decoder, dracoGeometry); + else op.warn("unknown draco geometryType", geometryType); + + draco.destroy(dracoGeometry); + return geometry; + }; + + let decodeIndex = function (draco, decoder, dracoGeometry) + { + const numFaces = dracoGeometry.num_faces(); + const numIndices = numFaces * 3; + const byteLength = numIndices * 4; + const ptr = draco._malloc(byteLength); + + decoder.GetTrianglesUInt32Array(dracoGeometry, byteLength, ptr); + const index = new Uint32Array(draco.HEAPF32.buffer, ptr, numIndices).slice(); + + draco._free(ptr); + + return { + "array": index, + "itemSize": 1 + }; + }; + + let decodeAttribute = function (draco, decoder, dracoGeometry, attributeName, attributeType, attribute) + { + let bytesPerElement = 4; + if (attributeType === "Float32Array") bytesPerElement = 4; + else if (attributeType === "Uint8Array") bytesPerElement = 1; + else op.warn("unknown attrtype bytesPerElement", attributeType); + + const numComponents = attribute.num_components(); + const numPoints = dracoGeometry.num_points(); + const numValues = numPoints * numComponents; + const byteLength = numValues * bytesPerElement; + const dataType = getDracoDataType(draco, attributeType); + const ptr = draco._malloc(byteLength); + let array = null; + + decoder.GetAttributeDataArrayForAllPoints(dracoGeometry, attribute, dataType, byteLength, ptr); + + if (attributeType === "Float32Array") array = new Float32Array(draco.HEAPF32.buffer, ptr, numValues).slice(); + else if (attributeType === "Uint8Array") array = new Uint8Array(draco.HEAPF32.buffer, ptr, numValues).slice(); + else op.warn("unknown attrtype", attributeType); + + draco._free(ptr); + + return { + "name": attributeName, + "array": array, + "itemSize": numComponents + }; + }; + + let getDracoDataType = function (draco, attributeType) + { + switch (attributeType) + { + case "Float32Array": return draco.DT_FLOAT32; + case "Int8Array": return draco.DT_INT8; + case "Int16Array": return draco.DT_INT16; + case "Int32Array": return draco.DT_INT32; + case "Uint8Array": return draco.DT_UINT8; + case "Uint16Array": return draco.DT_UINT16; + case "Uint32Array": return draco.DT_UINT32; + } + }; + } +} + +window.DracoDecoder = new DracoDecoderClass(); + + +}; + +Ops.Gl.GLTF.GltfDracoCompression.prototype = new CABLES.Op(); +CABLES.OPS["4ecdc2ef-a242-4548-ad74-13f617119a64"]={f:Ops.Gl.GLTF.GltfDracoCompression,objName:"Ops.Gl.GLTF.GltfDracoCompression"}; + + + + +// ************************************************************** +// +// Ops.Gl.GLTF.GltfGeometry +// +// ************************************************************** + +Ops.Gl.GLTF.GltfGeometry = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Update"), + inNodeName = op.inString("Name", "default"), + inSubmesh = op.inInt("Submesh", 0), + next = op.outTrigger("Next"), + outGeom = op.outObject("Geometry", null, "geometry"), + outFound = op.outBoolNum("Found"); + +const cgl = op.patch.cgl; +let mesh = null; +let currentSceneLoaded = null; + +inSubmesh.onChange = +inNodeName.onChange = function () +{ + outGeom.set(null); + mesh = null; + outFound.set(false); + op.setUiAttrib({ "extendTitle": inNodeName.get() + "." + inSubmesh.get() }); +}; + +exec.onTriggered = () => +{ + if (!cgl.frameStore.currentScene) return; + if (currentSceneLoaded != cgl.frameStore.currentScene.loaded) mesh = null; + + if (!mesh) + { + if (!cgl.frameStore || !cgl.frameStore.currentScene || !cgl.frameStore.currentScene.nodes || !cgl.frameStore.currentScene.loaded) + { + return; + } + outFound.set(false); + outGeom.set(null); + const name = inNodeName.get(); + + currentSceneLoaded = cgl.frameStore.currentScene.loaded; + + for (let i = 0; i < cgl.frameStore.currentScene.meshes.length; i++) + { + if (cgl.frameStore.currentScene.meshes[i].name == name) + { + mesh = cgl.frameStore.currentScene.meshes[i]; + + const idx = Math.abs(inSubmesh.get()); + if (mesh.meshes[idx] && mesh.meshes[idx].geom) + { + outFound.set(true); + outGeom.set(mesh.meshes[idx].geom); + } + } + } + } + + next.trigger(); +}; + + +}; + +Ops.Gl.GLTF.GltfGeometry.prototype = new CABLES.Op(); +CABLES.OPS["2e59da07-455a-457c-99d8-1c23a1ddeea2"]={f:Ops.Gl.GLTF.GltfGeometry,objName:"Ops.Gl.GLTF.GltfGeometry"}; + + + + +// ************************************************************** +// +// Ops.Gl.GLTF.GltfHierarchy +// +// ************************************************************** + +Ops.Gl.GLTF.GltfHierarchy = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec=op.inTrigger("Trigger"), + inNodeName=op.inString("Node name","default"), + next=op.outTrigger("Next"), + outArr=op.outArray("Bones Lines"); + +exec.onTriggered=update; + +const cgl=op.patch.cgl; + + +let node=null; +const tr = vec3.create(); + + + +inNodeName.onChange=()=> +{ + node=null; + update(); +}; + +function addChild(gltf,arr,parent,child) +{ + + if(parent) + { + + mat4.getTranslation(tr, parent.modelMatAbs()); + arr.push(tr[0], tr[1], tr[2]); + + mat4.getTranslation(tr, child.modelMatAbs()); + arr.push(tr[0], tr[1], tr[2]); + + } + + if(child && child.children) + { + for(let i=0;i= 0) + { + scene.nodes[i].addTranslate = null; + } + } +} + +inExec.onTriggered = function () +{ + if (!cgl.frameStore.currentScene) return; + + scene = cgl.frameStore.currentScene; + + let node = null; + + const ampl = inAmplitude.get(); + const offs = inOffset.get(); + const time = inTime.get(); + const ax = axisX.get(); + const ay = axisY.get(); + const az = axisZ.get(); + + Math.randomSeed = 5711; + let found = 0; + + for (let i = 0; i < cgl.frameStore.currentScene.nodes.length; i++) + { + if (cgl.frameStore.currentScene.nodes[i].name.indexOf(inFilter.get()) >= 0) + { + node = cgl.frameStore.currentScene.nodes[i]; + + found++; + + const v = Math.sin(time + (Math.seededRandom() * offs)) * ampl; + node.addTranslate = [v * ax, v * ay, v * az]; + } + } + + outNum.set(found); + + next.trigger(); +}; + + +}; + +Ops.Gl.GLTF.GltfNodeSineAnim.prototype = new CABLES.Op(); +CABLES.OPS["b4608e38-cc48-4748-a640-d653f53fc950"]={f:Ops.Gl.GLTF.GltfNodeSineAnim,objName:"Ops.Gl.GLTF.GltfNodeSineAnim"}; + + + + +// ************************************************************** +// +// Ops.Gl.GLTF.GltfNodeTransform_v2 +// +// ************************************************************** + +Ops.Gl.GLTF.GltfNodeTransform_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Render"), + inNodeName = op.inString("Node Name"), + next = op.outTrigger("Next"), + inApply = op.inBool("Set Matrix", true), + outFound = op.outBool("Found"), + outMat = op.outArray("Matrix"); + +const cgl = op.patch.cgl; +const translate = vec3.create(); +let node = null; +let currentSceneLoaded = null; +const m = mat4.create(); + +inNodeName.onChange = function () +{ + node = null; + outFound.set(false); + op.setUiAttrib({ "extendTitle": inNodeName.get() }); +}; + +inExec.onTriggered = function () +{ + if (!cgl.frameStore.currentScene) return; + if (currentSceneLoaded != cgl.frameStore.currentScene.loaded) node = null; + let found = false; + + if (!node) + { + const name = inNodeName.get(); + + if (!cgl.frameStore || !cgl.frameStore.currentScene || !cgl.frameStore.currentScene.nodes) return; + + currentSceneLoaded = cgl.frameStore.currentScene.loaded; + + for (let i = 0; i < cgl.frameStore.currentScene.nodes.length; i++) + { + if (cgl.frameStore.currentScene.nodes[i].name == name) + { + node = cgl.frameStore.currentScene.nodes[i]; + found = true; + break; + } + } + } + else + { + found = true; + } + + outFound.set(found); + cgl.pushModelMatrix(); + + if (node) + { + mat4.copy(m, node.modelMatAbs()); + + mat4.multiply(cgl.mMatrix, cgl.mMatrix, m); + + outMat.set(null); + outMat.set(m); + } + + next.trigger(); + cgl.popModelMatrix(); +}; + + +}; + +Ops.Gl.GLTF.GltfNodeTransform_v2.prototype = new CABLES.Op(); +CABLES.OPS["5a36a0f2-a4cb-4ac4-a7af-95924f2a9558"]={f:Ops.Gl.GLTF.GltfNodeTransform_v2,objName:"Ops.Gl.GLTF.GltfNodeTransform_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.GLTF.GltfNodeTransforms_v2 +// +// ************************************************************** + +Ops.Gl.GLTF.GltfNodeTransforms_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Render"), + inStr = op.inString("Search", ""), + inSort = op.inSwitch("Order", ["None", "AlphaNumerical"], "None"), + inSpace = op.inSwitch("Space", ["GLTF", "World"], "GLTF"), + outPos = op.outArray("Positions"), + next = op.outTrigger("Next"), + outScale = op.outArray("Scale"), + outNames = op.outArray("Names"), + outRot = op.outArray("Rotation"); + +const cgl = op.patch.cgl; +let needsupdate = true; +outPos.onChange = function () { needsupdate = true; }; +inExec.onTriggered = exec; + +inStr.onChange = function () +{ + needsupdate = true; +}; +function exec() +{ + // if (needsupdate) + update(); + next.trigger(); +} + +function update() +{ + outPos.set(null); + outScale.set(null); + outNames.set(null); + // outRot.set(null); + + if (!cgl.frameStore.currentScene) return; + + const arrPos = []; + const arrRot = []; + const arrScale = []; + const arrNames = []; + + const worldspace = inSpace.get() == "World"; + + for (let i = 0; i < cgl.frameStore.currentScene.nodes.length; i++) + { + if (cgl.frameStore.currentScene.nodes[i].name.indexOf(inStr.get()) == 0) + { + const n = cgl.frameStore.currentScene.nodes[i]._node; + const node = cgl.frameStore.currentScene.nodes[i]; + arrNames.push(n.name); + + const tr = vec3.create(); + + let m = node.modelMatAbs(); + // const m=node.modelMatLocal(); + + if (!worldspace) + { + m = node.modelMatLocal(); + } + + mat4.getTranslation(tr, m); + + // const empty=vec3.create(); + // vec3.transformMat4(tr, empty, m); + + arrPos.push(tr[0], tr[1], tr[2]); + + const q = quat.create(); + mat4.getRotation(q, m); + arrRot.push(q[0], q[1], q[2], q[3]); + + if (node._tempAnimScale) arrScale.push(node._tempAnimScale[0], node._tempAnimScale[1], node._tempAnimScale[2]); + else if (n.scale) arrScale.push(n.scale[0], n.scale[1], n.scale[2]); + else arrScale.push(1, 1, 1); + } + } + + if (inSort.get()) + { + let list = []; + for (let j = 0; j < arrNames.length; j++) + list.push({ + "name": arrNames[j], + "pos": [arrPos[j * 3 + 0], arrPos[j * 3 + 1], arrPos[j * 3 + 2]], + "scale": [arrScale[j * 3 + 0], arrScale[j * 3 + 1], arrScale[j * 3 + 2]] + }); + + list.sort(function (a, b) + { + return ((a.name < b.name) ? -1 : ((a.name == b.name) ? 0 : 1)); + // Sort could be modified to, for example, sort on the age + // if the name is the same. + }); + + // 3) separate them back out: + for (let k = 0; k < list.length; k++) + { + arrNames[k] = list[k].name; + arrPos[k * 3 + 0] = list[k].pos[0]; + arrPos[k * 3 + 1] = list[k].pos[1]; + arrPos[k * 3 + 2] = list[k].pos[2]; + arrScale[k * 3 + 0] = list[k].scale[0]; + arrScale[k * 3 + 1] = list[k].scale[1]; + arrScale[k * 3 + 2] = list[k].scale[2]; + } + } + + outPos.set(arrPos); + outScale.set(arrScale); + outNames.set(arrNames); + outRot.set(arrRot); + + needsupdate = false; +} + + +}; + +Ops.Gl.GLTF.GltfNodeTransforms_v2.prototype = new CABLES.Op(); +CABLES.OPS["02247569-4a2d-4a1b-952d-3585b1c677a8"]={f:Ops.Gl.GLTF.GltfNodeTransforms_v2,objName:"Ops.Gl.GLTF.GltfNodeTransforms_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.GLTF.GltfNode_v2 +// +// ************************************************************** + +Ops.Gl.GLTF.GltfNode_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Render"), + inNodeName = op.inString("Node Name"), + inTrans = op.inBool("Transformation", true), + inDraw = op.inBool("Draw Mesh", true), + inChilds = op.inBool("Draw Childs", true), + inIgnMaterial = op.inBool("Ignore Material", true), + + inSceneTime = op.inBool("Use Scene Time", true), + inTime = op.inFloat("Time", 0), + + next = op.outTrigger("Next"), + outGeom = op.outObject("Geometry", null, "geometry"), + outFound = op.outBool("Found"); +const cgl = op.patch.cgl; + +let node = null; +let currentSceneLoaded = null; + +inNodeName.onChange = function () +{ + outGeom.set(null); + node = null; + outFound.set(false); + if (!inNodeName.isLinked())op.setUiAttrib({ "extendTitle": inNodeName.get() }); +}; + +inSceneTime.onChange = updateTimeInputs; + +updateTimeInputs(); + +function updateTimeInputs() +{ + inTime.setUiAttribs({ "greyout": inSceneTime.get() }); +} + +inExec.onTriggered = function () +{ + if (!cgl.frameStore.currentScene) return; + if (currentSceneLoaded != cgl.frameStore.currentScene.loaded) node = null; + + if (!node) + { + const name = inNodeName.get(); + + if (!cgl.frameStore || !cgl.frameStore.currentScene || !cgl.frameStore.currentScene.nodes) + { + return; + } + currentSceneLoaded = cgl.frameStore.currentScene.loaded; + + for (let i = 0; i < cgl.frameStore.currentScene.nodes.length; i++) + { + if (cgl.frameStore.currentScene.nodes[i].name == name) + { + node = cgl.frameStore.currentScene.nodes[i]; + outFound.set(true); + + if (node && node.mesh && node.mesh.meshes && node.mesh.meshes[0].geom) outGeom.set(node.mesh.meshes[0].geom); + else outGeom.set(null); + } + } + } + + cgl.pushModelMatrix(); + + if (node) + { + if (inTrans.get()) + { + cgl.pushModelMatrix(); + node.transform(cgl); + } + + // node.updateMatrix(); + + // render(cgl, dontTransform, dontDrawMesh, ignoreMaterial, ignoreChilds, drawHidden, _time) + + let time; + if (!inSceneTime.get()) time = inTime.get(); + + node.render(cgl, !inTrans.get(), !inDraw.get(), inIgnMaterial.get(), !inChilds.get(), true, time); + } + + next.trigger(); + + if (node) + { + if (inTrans.get()) cgl.popModelMatrix(); + } + + cgl.popModelMatrix(); +}; + + +}; + +Ops.Gl.GLTF.GltfNode_v2.prototype = new CABLES.Op(); +CABLES.OPS["10d09387-0085-4162-ab5b-b89eebbf3cf4"]={f:Ops.Gl.GLTF.GltfNode_v2,objName:"Ops.Gl.GLTF.GltfNode_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.GLTF.GltfScene_v3 +// +// ************************************************************** + +Ops.Gl.GLTF.GltfScene_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"inc_camera_js":"const gltfCamera = class\n{\n constructor(gltf, node)\n {\n this.node=node;\n this.name=node.name;\n // console.log(gltf);\n this.config=gltf.json.cameras[node.camera];\n\n this.pos = vec3.create();\n this.quat = quat.create();\n this.quatOr = quat.create();\n this.vCenter = vec3.create();\n this.vUp = vec3.create();\n this.vMat = mat4.create();\n\n }\n\n updateAnim(time)\n {\n if (this.node && this.node._animTrans)\n {\n\n vec3.set(this.pos,\n this.node._animTrans[0].getValue(time),\n this.node._animTrans[1].getValue(time),\n this.node._animTrans[2].getValue(time));\n\n quat.set(this.quat,\n this.node._animRot[0].getValue(time),\n this.node._animRot[1].getValue(time),\n this.node._animRot[2].getValue(time),\n this.node._animRot[3].getValue(time));\n }\n }\n\n start(time)\n {\n if (cgl.frameStore.shadowPass) return;\n\n this.updateAnim(time);\n const asp = cgl.getViewPort()[2] / cgl.getViewPort()[3];\n\n cgl.pushPMatrix();\n // mat4.perspective(\n // cgl.pMatrix,\n // this.config.perspective.yfov*0.5,\n // asp,\n // this.config.perspective.znear,\n // this.config.perspective.zfar);\n\n cgl.pushViewMatrix();\n // mat4.identity(cgl.vMatrix);\n\n // if(this.node && this.node.parent)\n // {\n // console.log(this.node.parent)\n // vec3.add(this.pos,this.pos,this.node.parent._node.translation);\n // vec3.sub(this.vCenter,this.vCenter,this.node.parent._node.translation);\n // mat4.translate(cgl.vMatrix,cgl.vMatrix,\n // [\n // -this.node.parent._node.translation[0],\n // -this.node.parent._node.translation[1],\n // -this.node.parent._node.translation[2]\n // ])\n // }\n\n\n\n // vec3.set(this.vUp, 0, 1, 0);\n // vec3.set(this.vCenter, 0, -1, 0);\n // // vec3.set(this.vCenter, 0, 1, 0);\n // vec3.transformQuat(this.vCenter, this.vCenter, this.quat);\n // vec3.normalize(this.vCenter, this.vCenter);\n // vec3.add(this.vCenter, this.vCenter, this.pos);\n\n\n // mat4.lookAt(cgl.vMatrix, this.pos, this.vCenter, this.vUp);\n\n\n let mv=mat4.create();\n mat4.invert(mv,this.node.modelMatAbs());\n\n // console.log(this.node.modelMatAbs());\n\n this.vMat=mv;\n\n mat4.identity(cgl.vMatrix);\n // console.log(mv);\n mat4.mul(cgl.vMatrix,cgl.vMatrix,mv);\n\n\n }\n\n end()\n {\n if (cgl.frameStore.shadowPass) return;\n cgl.popPMatrix();\n cgl.popViewMatrix();\n }\n};\n\n","inc_gltf_js":"const CHUNK_HEADER_SIZE = 8;\n\nconst Gltf = class\n{\n constructor()\n {\n this.json = {};\n this.accBuffers = [];\n this.meshes = [];\n this.nodes = [];\n this.shaders = [];\n this.timing = [];\n this.cams = [];\n this.startTime = performance.now();\n this.bounds = new CABLES.CG.BoundingBox();\n this.loaded = Date.now();\n this.accBuffersDelete = [];\n }\n\n getNode(n)\n {\n for (let i = 0; i < this.nodes.length; i++)\n {\n if (this.nodes[i].name == n) return this.nodes[i];\n }\n }\n\n unHideAll()\n {\n for (let i = 0; i < this.nodes.length; i++)\n {\n this.nodes[i].unHide();\n }\n }\n};\n\nfunction Utf8ArrayToStr(array)\n{\n if (window.TextDecoder) return new TextDecoder(\"utf-8\").decode(array);\n\n let out, i, len, c;\n let char2, char3;\n\n out = \"\";\n len = array.length;\n i = 0;\n while (i < len)\n {\n c = array[i++];\n switch (c >> 4)\n {\n case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:\n // 0xxxxxxx\n out += String.fromCharCode(c);\n break;\n case 12: case 13:\n // 110x xxxx 10xx xxxx\n char2 = array[i++];\n out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));\n break;\n case 14:\n // 1110 xxxx 10xx xxxx 10xx xxxx\n char2 = array[i++];\n char3 = array[i++];\n out += String.fromCharCode(((c & 0x0F) << 12) |\n ((char2 & 0x3F) << 6) |\n ((char3 & 0x3F) << 0));\n break;\n }\n }\n\n return out;\n}\n\nfunction readChunk(dv, bArr, arrayBuffer, offset)\n{\n const chunk = {};\n\n if (offset >= dv.byteLength)\n {\n op.log(\"could not read chunk...\");\n return;\n }\n chunk.size = dv.getUint32(offset + 0, le);\n\n // chunk.type = new TextDecoder(\"utf-8\").decode(bArr.subarray(offset+4, offset+4+4));\n chunk.type = Utf8ArrayToStr(bArr.subarray(offset + 4, offset + 4 + 4));\n\n if (chunk.type == \"BIN\\0\")\n {\n // console.log(chunk.size,arrayBuffer.length,offset);\n // try\n // {\n chunk.dataView = new DataView(arrayBuffer, offset + 8, chunk.size);\n // }\n // catch(e)\n // {\n // chunk.dataView = null;\n // console.log(e);\n // }\n }\n else\n if (chunk.type == \"JSON\")\n {\n const json = Utf8ArrayToStr(bArr.subarray(offset + 8, offset + 8 + chunk.size));\n\n try\n {\n const obj = JSON.parse(json);\n chunk.data = obj;\n outGenerator.set(obj.asset.generator);\n }\n catch (e)\n {\n }\n }\n else\n {\n op.warn(\"unknown type\", chunk.type);\n }\n\n return chunk;\n}\n\nfunction loadAnims(gltf)\n{\n const uniqueAnimNames = {};\n\n for (let i = 0; i < gltf.json.animations.length; i++)\n {\n const an = gltf.json.animations[i];\n\n for (let ia = 0; ia < an.channels.length; ia++)\n {\n const chan = an.channels[ia];\n\n const node = gltf.nodes[chan.target.node];\n const sampler = an.samplers[chan.sampler];\n\n const acc = gltf.json.accessors[sampler.input];\n const bufferIn = gltf.accBuffers[sampler.input];\n\n const accOut = gltf.json.accessors[sampler.output];\n const bufferOut = gltf.accBuffers[sampler.output];\n\n gltf.accBuffersDelete.push(sampler.output, sampler.input);\n\n if (bufferIn && bufferOut)\n {\n let numComps = 1;\n if (accOut.type == \"VEC2\")numComps = 2;\n else if (accOut.type == \"VEC3\")numComps = 3;\n else if (accOut.type == \"VEC4\")numComps = 4;\n else op.warn(\"unknown accOut.type\", accOut.type);\n\n const anims = [];\n\n uniqueAnimNames[an.name] = true;\n\n for (let k = 0; k < numComps; k++)\n {\n const newAnim = new CABLES.TL.Anim();\n // newAnim.name=an.name;\n anims.push(newAnim);\n }\n\n if (sampler.interpolation == \"LINEAR\") {}\n else if (sampler.interpolation == \"STEP\") for (let k = 0; k < numComps; k++) anims[k].defaultEasing = CABLES.EASING_ABSOLUTE;\n else if (sampler.interpolation == \"CUBICSPLINE\") for (let k = 0; k < numComps; k++) anims[k].defaultEasing = CABLES.EASING_CUBICSPLINE;\n else op.warn(\"unknown interpolation\", sampler.interpolation);\n\n // console.log(bufferOut)\n\n // if there is no keyframe for time 0 copy value of first keyframe at time 0\n if (bufferIn[0] !== 0.0)\n for (let k = 0; k < numComps; k++)\n anims[k].setValue(0, bufferOut[0 * numComps + k]);\n\n // console.log(sampler.interpolation,bufferOut.length/numComps)\n\n for (let j = 0; j < bufferIn.length; j++)\n {\n maxTime = Math.max(bufferIn[j], maxTime);\n\n for (let k = 0; k < numComps; k++)\n {\n if (anims[k].defaultEasing === CABLES.EASING_CUBICSPLINE)\n {\n const idx = ((j * numComps) * 3 + k);\n\n const key = anims[k].setValue(bufferIn[j], bufferOut[idx + numComps]);\n key.bezTangIn = bufferOut[idx];\n key.bezTangOut = bufferOut[idx + (numComps * 2)];\n\n // console.log(an.name,k,bufferOut[idx+1]);\n }\n else\n {\n // console.log(an.name,k,bufferOut[j * numComps + k]);\n anims[k].setValue(bufferIn[j], bufferOut[j * numComps + k]);\n }\n }\n }\n\n node.setAnim(chan.target.path, an.name, anims);\n }\n else\n {\n op.warn(\"loadAmins bufferIn undefined \", bufferIn === undefined);\n op.warn(\"loadAmins bufferOut undefined \", bufferOut === undefined);\n op.warn(\"loadAmins \", sampler, accOut);\n op.warn(\"loadAmins num accBuffers\", gltf.accBuffers.length);\n op.warn(\"loadAmins num accessors\", gltf.json.accessors.length);\n }\n }\n }\n\n gltf.uniqueAnimNames = uniqueAnimNames;\n\n outAnims.set(null);\n outAnims.set(Object.keys(uniqueAnimNames));\n}\n\nfunction loadCams(gltf)\n{\n if (!gltf || !gltf.json.cameras) return;\n\n gltf.cameras = gltf.cameras || [];\n\n for (let i = 0; i < gltf.nodes.length; i++)\n {\n if (gltf.nodes[i].hasOwnProperty(\"camera\"))\n {\n const cam = new gltfCamera(gltf, gltf.nodes[i]);\n gltf.cameras.push(cam);\n }\n }\n}\n\nfunction loadAfterDraco()\n{\n if (!window.DracoDecoder)\n {\n setTimeout(() =>\n {\n loadAfterDraco();\n }, 100);\n }\n\n reloadSoon();\n}\n\nfunction parseGltf(arrayBuffer)\n{\n let j = 0, i = 0;\n\n const gltf = new Gltf();\n gltf.timing.push(\"Start parsing\", Math.round((performance.now() - gltf.startTime)));\n\n if (!arrayBuffer) return;\n const byteArray = new Uint8Array(arrayBuffer);\n let pos = 0;\n\n // var string = new TextDecoder(\"utf-8\").decode(byteArray.subarray(pos, 4));\n const string = Utf8ArrayToStr(byteArray.subarray(pos, 4));\n pos += 4;\n if (string != \"glTF\") return;\n\n gltf.timing.push(\"dataview\", Math.round((performance.now() - gltf.startTime)));\n\n const dv = new DataView(arrayBuffer);\n const version = dv.getUint32(pos, le);\n pos += 4;\n const size = dv.getUint32(pos, le);\n pos += 4;\n\n outVersion.set(version);\n\n const chunks = [];\n gltf.chunks = chunks;\n\n chunks.push(readChunk(dv, byteArray, arrayBuffer, pos));\n pos += chunks[0].size + CHUNK_HEADER_SIZE;\n gltf.json = chunks[0].data;\n outJson.set(gltf.json);\n outExtensions.set(gltf.json.extensionsUsed || []);\n\n let ch = readChunk(dv, byteArray, arrayBuffer, pos);\n while (ch)\n {\n chunks.push(ch);\n pos += ch.size + CHUNK_HEADER_SIZE;\n ch = readChunk(dv, byteArray, arrayBuffer, pos);\n }\n\n gltf.chunks = chunks;\n\n const views = chunks[0].data.bufferViews;\n const accessors = chunks[0].data.accessors;\n\n gltf.timing.push(\"Parse buffers\", Math.round((performance.now() - gltf.startTime)));\n\n if (gltf.json.extensionsUsed && gltf.json.extensionsUsed.indexOf(\"KHR_draco_mesh_compression\") > -1)\n {\n if (!window.DracoDecoder)\n {\n op.setUiError(\"gltfdraco\", \"GLTF draco compression lib not found / add draco op to your patch!\");\n\n loadAfterDraco();\n return gltf;\n }\n else\n {\n gltf.useDraco = true;\n }\n }\n\n op.setUiError(\"gltfdraco\", null);\n // let accPos = (view.byteOffset || 0) + (acc.byteOffset || 0);\n\n if (views)\n {\n for (i = 0; i < accessors.length; i++)\n {\n const acc = accessors[i];\n const view = views[acc.bufferView];\n\n let numComps = 0;\n if (acc.type == \"SCALAR\")numComps = 1;\n else if (acc.type == \"VEC2\")numComps = 2;\n else if (acc.type == \"VEC3\")numComps = 3;\n else if (acc.type == \"VEC4\")numComps = 4;\n else if (acc.type == \"MAT4\")numComps = 16;\n else console.error(\"unknown accessor type\", acc.type);\n\n // const decoder = new decoderModule.Decoder();\n // const decodedGeometry = decodeDracoData(data, decoder);\n // // Encode mesh\n // encodeMeshToFile(decodedGeometry, decoder);\n\n // decoderModule.destroy(decoder);\n // decoderModule.destroy(decodedGeometry);\n\n // 5120 (BYTE)\t1\n // 5121 (UNSIGNED_BYTE)\t1\n // 5122 (SHORT)\t2\n\n if (chunks[1].dataView)\n {\n if (view)\n {\n const num = acc.count * numComps;\n let accPos = (view.byteOffset || 0) + (acc.byteOffset || 0);\n let stride = view.byteStride || 0;\n let dataBuff = null;\n\n if (acc.componentType == 5126 || acc.componentType == 5125) // 4byte FLOAT or INT\n {\n stride = stride || 4;\n\n const isInt = acc.componentType == 5125;\n if (isInt)dataBuff = new Uint32Array(num);\n else dataBuff = new Float32Array(num);\n\n for (j = 0; j < num; j++)\n {\n if (isInt) dataBuff[j] = chunks[1].dataView.getUint32(accPos, le);\n else dataBuff[j] = chunks[1].dataView.getFloat32(accPos, le);\n\n if (stride != 4 && (j + 1) % numComps === 0)accPos += stride - (numComps * 4);\n accPos += 4;\n }\n }\n else if (acc.componentType == 5123) // UNSIGNED_SHORT\n {\n stride = stride || 2;\n\n dataBuff = new Uint16Array(num);\n\n for (j = 0; j < num; j++)\n {\n dataBuff[j] = chunks[1].dataView.getUint16(accPos, le);\n\n if (stride != 2 && (j + 1) % numComps === 0) accPos += stride - (numComps * 2);\n\n accPos += 2;\n }\n }\n else if (acc.componentType == 5121) // UNSIGNED_BYTE\n {\n stride = stride || 1;\n\n dataBuff = new Uint8Array(num);\n\n for (j = 0; j < num; j++)\n {\n dataBuff[j] = chunks[1].dataView.getUint8(accPos, le);\n\n if (stride != 1 && (j + 1) % numComps === 0) accPos += stride - (numComps * 1);\n\n accPos += 1;\n }\n }\n\n else\n {\n console.error(\"unknown component type\", acc.componentType);\n }\n\n gltf.accBuffers.push(dataBuff);\n }\n else\n {\n // console.log(\"has no dataview\");\n }\n }\n }\n }\n\n gltf.timing.push(\"Parse mesh groups\", Math.round((performance.now() - gltf.startTime)));\n\n gltf.json.meshes = gltf.json.meshes || [];\n\n if (gltf.json.meshes)\n {\n for (i = 0; i < gltf.json.meshes.length; i++)\n {\n const mesh = new gltfMeshGroup(gltf, gltf.json.meshes[i]);\n gltf.meshes.push(mesh);\n }\n }\n\n gltf.timing.push(\"Parse nodes\", Math.round((performance.now() - gltf.startTime)));\n\n for (i = 0; i < gltf.json.nodes.length; i++)\n {\n if (gltf.json.nodes[i].children)\n for (j = 0; j < gltf.json.nodes[i].children.length; j++)\n {\n gltf.json.nodes[gltf.json.nodes[i].children[j]].isChild = true;\n }\n }\n\n for (i = 0; i < gltf.json.nodes.length; i++)\n {\n const node = new gltfNode(gltf.json.nodes[i], gltf);\n gltf.nodes.push(node);\n }\n\n for (i = 0; i < gltf.nodes.length; i++)\n {\n const node = gltf.nodes[i];\n\n if (!node.children) continue;\n for (let j = 0; j < node.children.length; j++)\n {\n gltf.nodes[node.children[j]].parent = node;\n }\n }\n\n for (i = 0; i < gltf.nodes.length; i++)\n {\n gltf.nodes[i].initSkin();\n }\n\n needsMatUpdate = true;\n\n gltf.timing.push(\"load anims\", Math.round((performance.now() - gltf.startTime)));\n\n if (gltf.json.animations) loadAnims(gltf);\n\n gltf.timing.push(\"load cameras\", Math.round((performance.now() - gltf.startTime)));\n\n if (gltf.json.cameras) loadCams(gltf);\n\n gltf.timing.push(\"finished\", Math.round((performance.now() - gltf.startTime)));\n\n return gltf;\n}\n","inc_mesh_js":"let gltfMesh = class\n{\n constructor(name, prim, gltf, finished)\n {\n this.POINTS = 0;\n this.LINES = 1;\n this.LINE_LOOP = 2;\n this.LINE_STRIP = 3;\n this.TRIANGLES = 4;\n this.TRIANGLE_STRIP = 5;\n this.TRIANGLE_FAN = 6;\n\n this.test = 0;\n this.name = name;\n this.submeshIndex = 0;\n this.material = prim.material;\n this.mesh = null;\n this.geom = new CGL.Geometry(\"gltf_\" + this.name);\n this.geom.verticesIndices = [];\n this.bounds = null;\n this.primitive = 4;\n if (prim.hasOwnProperty(\"mode\")) this.primitive = prim.mode;\n\n if (prim.hasOwnProperty(\"indices\")) this.geom.verticesIndices = gltf.accBuffers[prim.indices];\n\n gltf.loadingMeshes = gltf.loadingMeshes || 0;\n gltf.loadingMeshes++;\n\n this.materialJson =\n this._matPbrMetalness =\n this._matPbrRoughness =\n this._matDiffuseColor = null;\n\n if (gltf.json.materials)\n {\n if (this.material != -1) this.materialJson = gltf.json.materials[this.material];\n\n if (this.materialJson && this.materialJson.pbrMetallicRoughness)\n {\n if (!this.materialJson.pbrMetallicRoughness.hasOwnProperty(\"baseColorFactor\"))\n {\n this._matDiffuseColor = [1, 1, 1, 1];\n }\n else\n {\n this._matDiffuseColor = this.materialJson.pbrMetallicRoughness.baseColorFactor;\n }\n\n this._matDiffuseColor = this.materialJson.pbrMetallicRoughness.baseColorFactor;\n\n if (!this.materialJson.pbrMetallicRoughness.hasOwnProperty(\"metallicFactor\"))\n {\n this._matPbrMetalness = 1.0;\n }\n else\n {\n this._matPbrMetalness = this.materialJson.pbrMetallicRoughness.metallicFactor || null;\n }\n\n if (!this.materialJson.pbrMetallicRoughness.hasOwnProperty(\"roughnessFactor\"))\n {\n this._matPbrRoughness = 1.0;\n }\n else\n {\n this._matPbrRoughness = this.materialJson.pbrMetallicRoughness.roughnessFactor || null;\n }\n }\n }\n\n if (gltf.useDraco && prim.extensions.KHR_draco_mesh_compression)\n {\n const view = gltf.chunks[0].data.bufferViews[prim.extensions.KHR_draco_mesh_compression.bufferView];\n const num = view.byteLength;\n const dataBuff = new Int8Array(num);\n let accPos = (view.byteOffset || 0);// + (acc.byteOffset || 0);\n for (let j = 0; j < num; j++)\n {\n dataBuff[j] = gltf.chunks[1].dataView.getInt8(accPos, le);\n accPos++;\n }\n\n const dracoDecoder = window.DracoDecoder;\n dracoDecoder.decodeGeometry(dataBuff.buffer, (geometry) =>\n {\n const geom = new CGL.Geometry(\"draco mesh \" + name);\n\n for (let i = 0; i < geometry.attributes.length; i++)\n {\n const attr = geometry.attributes[i];\n\n if (attr.name === \"position\") geom.vertices = attr.array;\n else if (attr.name === \"normal\") geom.vertexNormals = attr.array;\n else if (attr.name === \"uv\") geom.texCoords = attr.array;\n else if (attr.name === \"color\") geom.vertexColors = this.calcVertexColors(attr.array);\n else if (attr.name === \"joints\") geom.setAttribute(\"attrJoints\", Array.from(attr.array), 4);\n else if (attr.name === \"weights\")\n {\n const arr4 = new Float32Array(attr.array.length / attr.itemSize * 4);\n\n for (let k = 0; k < attr.array.length / attr.itemSize; k++)\n {\n arr4[k * 4] = arr4[k * 4 + 1] = arr4[k * 4 + 2] = arr4[k * 4 + 3] = 0;\n for (let j = 0; j < attr.itemSize; j++)\n arr4[k * 4 + j] = attr.array[k * attr.itemSize + j];\n }\n geom.setAttribute(\"attrWeights\", arr4, 4);\n }\n else op.logWarn(\"unknown draco attrib\", attr);\n }\n\n geometry.attributes = null;\n geom.verticesIndices = geometry.index.array;\n\n this.setGeom(geom);\n\n this.mesh = null;\n gltf.loadingMeshes--;\n if (finished)finished(this);\n }, (error) => { op.logError(error); });\n }\n else\n {\n gltf.loadingMeshes--;\n this.fillGeomAttribs(gltf, this.geom, prim.attributes);\n\n if (prim.targets)\n {\n console.log(\"prim.targets\", prim.targets.length);\n for (let j = 0; j < prim.targets.length; j++)\n {\n // var tgeom=new CGL.Geometry(\"gltf_\"+this.name);\n let tgeom = this.geom.copy();\n\n if (prim.hasOwnProperty(\"indices\")) tgeom.verticesIndices = gltf.accBuffers[prim.indices];\n\n this.fillGeomAttribs(gltf, tgeom, prim.targets[j], false);\n\n { // calculate normals for final position of morphtarget for later...\n for (let i = 0; i < tgeom.vertices.length; i++) tgeom.vertices[i] += this.geom.vertices[i];\n tgeom.calculateNormals();\n for (let i = 0; i < tgeom.vertices.length; i++) tgeom.vertices[i] -= this.geom.vertices[i];\n }\n\n this.geom.morphTargets.push(tgeom);\n }\n }\n if (finished)finished(this);\n }\n }\n\n _linearToSrgb(x)\n {\n if (x <= 0)\n return 0;\n else if (x >= 1)\n return 1;\n else if (x < 0.0031308)\n return x * 12.92;\n else\n return Math.pow(x, 1 / 2.2) * 1.055 - 0.055;\n }\n\n calcVertexColors(arr)\n {\n let vertexColors = null;\n if (arr instanceof Float32Array)\n {\n let div = false;\n for (let i = 0; i < arr.length; i++)\n {\n if (arr[i] > 1)\n {\n div = true;\n continue;\n }\n }\n\n if (div)\n for (let i = 0; i < arr.length; i++) arr[i] /= 65535;\n\n vertexColors = arr;\n }\n\n else if (arr instanceof Uint16Array)\n {\n const fb = new Float32Array(arr.length);\n for (let i = 0; i < arr.length; i++) fb[i] = arr[i] / 65535;\n\n vertexColors = fb;\n }\n else vertexColors = arr;\n\n for (let i = 0; i < vertexColors.length; i++)\n {\n vertexColors[i] = this._linearToSrgb(vertexColors[i]);\n }\n\n return vertexColors;\n }\n\n fillGeomAttribs(gltf, tgeom, attribs, setGeom)\n {\n if (attribs.hasOwnProperty(\"POSITION\")) tgeom.vertices = gltf.accBuffers[attribs.POSITION];\n if (attribs.hasOwnProperty(\"NORMAL\")) tgeom.vertexNormals = gltf.accBuffers[attribs.NORMAL];\n if (attribs.hasOwnProperty(\"TANGENT\")) tgeom.tangents = gltf.accBuffers[attribs.TANGENT];\n\n if (attribs.hasOwnProperty(\"COLOR_0\")) tgeom.vertexColors = this.calcVertexColors(gltf.accBuffers[attribs.COLOR_0]);\n if (attribs.hasOwnProperty(\"COLOR_1\")) tgeom.setAttribute(\"attrVertColor1\", this.calcVertexColors(gltf.accBuffers[attribs.COLOR_1]), 4);\n if (attribs.hasOwnProperty(\"COLOR_2\")) tgeom.setAttribute(\"attrVertColor2\", this.calcVertexColors(gltf.accBuffers[attribs.COLOR_2]), 4);\n if (attribs.hasOwnProperty(\"COLOR_3\")) tgeom.setAttribute(\"attrVertColor3\", this.calcVertexColors(gltf.accBuffers[attribs.COLOR_3]), 4);\n if (attribs.hasOwnProperty(\"COLOR_4\")) tgeom.setAttribute(\"attrVertColor4\", this.calcVertexColors(gltf.accBuffers[attribs.COLOR_4]), 4);\n\n if (attribs.hasOwnProperty(\"TEXCOORD_0\"))tgeom.texCoords = gltf.accBuffers[attribs.TEXCOORD_0];\n if (attribs.hasOwnProperty(\"TEXCOORD_1\"))tgeom.setAttribute(\"attrTexCoord1\", gltf.accBuffers[attribs.TEXCOORD_1], 2);\n if (attribs.hasOwnProperty(\"TEXCOORD_2\"))tgeom.setAttribute(\"attrTexCoord2\", gltf.accBuffers[attribs.TEXCOORD_2], 2);\n if (attribs.hasOwnProperty(\"TEXCOORD_3\"))tgeom.setAttribute(\"attrTexCoord3\", gltf.accBuffers[attribs.TEXCOORD_3], 2);\n if (attribs.hasOwnProperty(\"TEXCOORD_4\"))tgeom.setAttribute(\"attrTexCoord4\", gltf.accBuffers[attribs.TEXCOORD_4], 2);\n\n if (attribs.hasOwnProperty(\"WEIGHTS_0\"))\n {\n tgeom.setAttribute(\"attrWeights\", gltf.accBuffers[attribs.WEIGHTS_0], 4);\n }\n if (attribs.hasOwnProperty(\"JOINTS_0\"))\n {\n if (!gltf.accBuffers[attribs.JOINTS_0])console.log(\"no !gltf.accBuffers[attribs.JOINTS_0]\");\n tgeom.setAttribute(\"attrJoints\", gltf.accBuffers[attribs.JOINTS_0], 4);\n }\n\n if (attribs.hasOwnProperty(\"POSITION\")) gltf.accBuffersDelete.push(attribs.POSITION);\n if (attribs.hasOwnProperty(\"NORMAL\")) gltf.accBuffersDelete.push(attribs.NORMAL);\n if (attribs.hasOwnProperty(\"TEXCOORD_0\")) gltf.accBuffersDelete.push(attribs.TEXCOORD_0);\n if (attribs.hasOwnProperty(\"TANGENT\")) gltf.accBuffersDelete.push(attribs.TANGENT);\n if (attribs.hasOwnProperty(\"COLOR_0\"))gltf.accBuffersDelete.push(attribs.COLOR_0);\n if (attribs.hasOwnProperty(\"COLOR_0\"))gltf.accBuffersDelete.push(attribs.COLOR_0);\n if (attribs.hasOwnProperty(\"COLOR_1\"))gltf.accBuffersDelete.push(attribs.COLOR_1);\n if (attribs.hasOwnProperty(\"COLOR_2\"))gltf.accBuffersDelete.push(attribs.COLOR_2);\n if (attribs.hasOwnProperty(\"COLOR_3\"))gltf.accBuffersDelete.push(attribs.COLOR_3);\n\n if (attribs.hasOwnProperty(\"TEXCOORD_1\")) gltf.accBuffersDelete.push(attribs.TEXCOORD_1);\n if (attribs.hasOwnProperty(\"TEXCOORD_2\")) gltf.accBuffersDelete.push(attribs.TEXCOORD_2);\n if (attribs.hasOwnProperty(\"TEXCOORD_3\")) gltf.accBuffersDelete.push(attribs.TEXCOORD_3);\n if (attribs.hasOwnProperty(\"TEXCOORD_4\")) gltf.accBuffersDelete.push(attribs.TEXCOORD_4);\n\n if (setGeom !== false) if (tgeom && tgeom.verticesIndices) this.setGeom(tgeom);\n }\n\n setGeom(geom)\n {\n if (inNormFormat.get() == \"X-ZY\")\n {\n for (let i = 0; i < geom.vertexNormals.length; i += 3)\n {\n let t = geom.vertexNormals[i + 2];\n geom.vertexNormals[i + 2] = geom.vertexNormals[i + 1];\n geom.vertexNormals[i + 1] = -t;\n }\n }\n\n if (inVertFormat.get() == \"XZ-Y\")\n {\n for (let i = 0; i < geom.vertices.length; i += 3)\n {\n let t = geom.vertices[i + 2];\n geom.vertices[i + 2] = -geom.vertices[i + 1];\n geom.vertices[i + 1] = t;\n }\n }\n\n if (this.primitive == this.TRIANGLES)\n {\n if (!geom.vertexNormals.length || inCalcNormals.get()) geom.calculateNormals();\n\n if ((!geom.biTangents || geom.biTangents.length == 0) && geom.tangents)\n {\n const bitan = vec3.create();\n const tan = vec3.create();\n\n const tangents = geom.tangents;\n geom.tangents = new Float32Array(tangents.length / 4 * 3);\n geom.biTangents = new Float32Array(tangents.length / 4 * 3);\n\n for (let i = 0; i < tangents.length; i += 4)\n {\n const idx = i / 4 * 3;\n\n vec3.cross(\n bitan,\n [geom.vertexNormals[idx], geom.vertexNormals[idx + 1], geom.vertexNormals[idx + 2]],\n [tangents[i], tangents[i + 1], tangents[i + 2]]\n );\n\n vec3.div(bitan, bitan, [tangents[i + 3], tangents[i + 3], tangents[i + 3]]);\n vec3.normalize(bitan, bitan);\n\n geom.biTangents[idx + 0] = bitan[0];\n geom.biTangents[idx + 1] = bitan[1];\n geom.biTangents[idx + 2] = bitan[2];\n\n geom.tangents[idx + 0] = tangents[i + 0];\n geom.tangents[idx + 1] = tangents[i + 1];\n geom.tangents[idx + 2] = tangents[i + 2];\n }\n }\n\n if (geom.tangents.length === 0 || inCalcNormals.get()) geom.calcTangentsBitangents();\n }\n\n this.geom = geom;\n\n this.bounds = geom.getBounds();\n }\n\n render(cgl, ignoreMaterial, skinRenderer)\n {\n if (!this.mesh && this.geom && this.geom.verticesIndices)\n {\n let g = this.geom;\n if (this.geom.vertices.length / 3 > 64000)\n {\n g = this.geom.copy();\n g.unIndex(false, true);\n }\n\n let glprim;\n if (this.primitive == this.TRIANGLES)glprim = cgl.gl.TRIANGLES;\n else if (this.primitive == this.LINES)glprim = cgl.gl.LINES;\n else if (this.primitive == this.LINE_STRIP)glprim = cgl.gl.LINE_STRIP;\n else if (this.primitive == this.POINTS)glprim = cgl.gl.POINTS;\n else\n {\n op.logWarn(\"unknown primitive type\", this);\n }\n\n this.mesh = new CGL.Mesh(cgl, g, glprim);\n // this.mesh._geom = null;\n }\n else\n {\n // update morphTargets\n if (this.geom && this.geom.morphTargets.length)\n {\n this.morphGeom = this.geom.copy();\n\n this.test = time * 11.7;\n\n if (this.test >= this.geom.morphTargets.length - 1) this.test = 0;\n\n const mt = this.geom.morphTargets[Math.floor(this.test)];\n const mt2 = this.geom.morphTargets[Math.floor(this.test + 1)];\n\n if (mt && mt.vertices && mt2)\n {\n if (this.morphGeom.vertexNormals.length != mt.vertexNormals.length)\n this.morphGeom.vertexNormals = new Float32Array(mt.vertexNormals.length);\n\n const fract = this.test % 1;\n for (let i = 0; i < this.morphGeom.vertices.length; i++)\n {\n this.morphGeom.vertices[i] =\n this.geom.vertices[i] +\n (1.0 - fract) * mt.vertices[i] +\n fract * mt2.vertices[i];\n\n this.morphGeom.vertexNormals[i] =\n (1.0 - fract) * mt.vertexNormals[i] +\n fract * mt2.vertexNormals[i];\n }\n\n this.mesh.updateNormals(this.morphGeom);\n this.mesh.updateVertices(this.morphGeom);\n }\n }\n\n let useMat = !ignoreMaterial && this.material != -1 && gltf.shaders[this.material];\n if (skinRenderer)useMat = false;\n\n if (useMat) cgl.pushShader(gltf.shaders[this.material]);\n\n const currentShader = cgl.getShader() || {};\n const uniDiff = currentShader.uniformColorDiffuse;\n\n const uniPbrMetalness = currentShader.uniformPbrMetalness;\n const uniPbrRoughness = currentShader.uniformPbrRoughness;\n\n if (!gltf.shaders[this.material] && inUseMatProps.get())\n {\n if (uniDiff && this._matDiffuseColor)\n {\n this._matDiffuseColorOrig = [uniDiff.getValue()[0], uniDiff.getValue()[1], uniDiff.getValue()[2], uniDiff.getValue()[3]];\n uniDiff.setValue(this._matDiffuseColor);\n }\n\n if (uniPbrMetalness)\n if (this._matPbrMetalness != null)\n {\n this._matPbrMetalnessOrig = uniPbrMetalness.getValue();\n uniPbrMetalness.setValue(this._matPbrMetalness);\n }\n else\n uniPbrMetalness.setValue(0);\n\n if (uniPbrRoughness)\n if (this._matPbrRoughness != null)\n {\n this._matPbrRoughnessOrig = uniPbrRoughness.getValue();\n uniPbrRoughness.setValue(this._matPbrRoughness);\n }\n else\n {\n uniPbrRoughness.setValue(0);\n }\n }\n\n if (this.mesh) this.mesh.render(cgl.getShader(), ignoreMaterial);\n\n if (inUseMatProps.get())\n {\n if (uniDiff && this._matDiffuseColor) uniDiff.setValue(this._matDiffuseColorOrig);\n if (uniPbrMetalness && this._matPbrMetalnessOrig != undefined) uniPbrMetalness.setValue(this._matPbrMetalnessOrig);\n if (uniPbrRoughness && this._matPbrRoughnessOrig != undefined) uniPbrRoughness.setValue(this._matPbrRoughnessOrig);\n }\n\n if (useMat) cgl.popShader();\n }\n }\n};\n","inc_meshGroup_js":"const gltfMeshGroup = class\n{\n constructor(gltf, m)\n {\n this.bounds = new CABLES.CG.BoundingBox();\n this.meshes = [];\n this.name = m.name;\n const prims = m.primitives;\n\n for (let i = 0; i < prims.length; i++)\n {\n const mesh = new gltfMesh(this.name, prims[i], gltf,\n (mesh) =>\n {\n this.bounds.apply(mesh.bounds);\n });\n\n mesh.submeshIndex = i;\n this.meshes.push(mesh);\n }\n }\n\n render(cgl, ignoreMat, skinRenderer, _time)\n {\n for (let i = 0; i < this.meshes.length; i++)\n {\n const useMat = gltf.shaders[this.meshes[i].material];\n\n if (!ignoreMat && useMat) cgl.pushShader(gltf.shaders[this.meshes[i].material]);\n // console.log(gltf.shaders[this.meshes[i].material],this.meshes[i].material)\n if (skinRenderer)skinRenderer.renderStart(cgl, _time);\n\n this.meshes[i].render(cgl, ignoreMat, skinRenderer, _time);\n if (skinRenderer)skinRenderer.renderFinish(cgl);\n if (!ignoreMat && useMat) cgl.popShader();\n }\n }\n};\n","inc_node_js":"const gltfNode = class\n{\n constructor(node, gltf)\n {\n this.isChild = node.isChild || false;\n this.name = node.name;\n if (node.hasOwnProperty(\"camera\")) this.camera = node.camera;\n this.hidden = false;\n this.mat = mat4.create();\n this._animMat = mat4.create();\n this._tempMat = mat4.create();\n this._tempQuat = quat.create();\n this._tempRotmat = mat4.create();\n this.mesh = null;\n this.children = [];\n this._node = node;\n this._gltf = gltf;\n this.absMat = mat4.create();\n this.addTranslate = null;\n this._tempAnimScale = null;\n this.addMulMat = null;\n this.updateMatrix();\n this._animActions = {};\n this.skinRenderer = null;\n this.copies = [];\n }\n\n get skin()\n {\n if (this._node.hasOwnProperty(\"skin\")) return this._node.skin;\n else return -1;\n }\n\n copy()\n {\n this.isCopy = true;\n const n = new gltfNode(this._node, this._gltf);\n n.copyOf = this;\n\n n._animActions = this._animActions;\n n.children = this.children;\n n.skinRenderer = new GltfSkin(n);\n\n this.updateMatrix();\n return n;\n }\n\n hasSkin()\n {\n if (this._node.hasOwnProperty(\"skin\")) return this._gltf.json.skins[this._node.skin].name || \"unknown\";\n return false;\n }\n\n initSkin()\n {\n if (this.skin > -1)\n {\n this.skinRenderer = new GltfSkin(this);\n }\n }\n\n updateMatrix()\n {\n mat4.identity(this.mat);\n if (this._node.translation) mat4.translate(this.mat, this.mat, this._node.translation);\n\n if (this._node.rotation)\n {\n const rotmat = mat4.create();\n this._rot = this._node.rotation;\n\n mat4.fromQuat(rotmat, this._node.rotation);\n mat4.mul(this.mat, this.mat, rotmat);\n }\n\n if (this._node.scale)\n {\n this._scale = this._node.scale;\n mat4.scale(this.mat, this.mat, this._scale);\n }\n\n if (this._node.hasOwnProperty(\"mesh\"))\n {\n this.mesh = this._gltf.meshes[this._node.mesh];\n if (this.isCopy)\n {\n console.log(this.mesh);\n }\n }\n\n if (this._node.children)\n {\n for (let i = 0; i < this._node.children.length; i++)\n {\n this._gltf.json.nodes[i].isChild = true;\n if (this._gltf.nodes[this._node.children[i]]) this._gltf.nodes[this._node.children[i]].isChild = true;\n this.children.push(this._node.children[i]);\n }\n }\n }\n\n unHide()\n {\n this.hidden = false;\n for (let i = 0; i < this.children.length; i++)\n if (this.children[i].unHide) this.children[i].unHide();\n }\n\n calcBounds(gltf, mat, bounds)\n {\n const localMat = mat4.create();\n\n if (mat) mat4.copy(localMat, mat);\n if (this.mat) mat4.mul(localMat, localMat, this.mat);\n\n if (this.mesh)\n {\n const bb = this.mesh.bounds.copy();\n bb.mulMat4(localMat);\n bounds.apply(bb);\n\n if (bounds.changed)\n {\n boundingPoints.push(\n bb._min[0] || 0, bb._min[1] || 0, bb._min[2] || 0,\n bb._max[0] || 0, bb._max[1] || 0, bb._max[2] || 0);\n }\n }\n\n for (let i = 0; i < this.children.length; i++)\n {\n if (gltf.nodes[this.children[i]] && gltf.nodes[this.children[i]].calcBounds)\n {\n const b = gltf.nodes[this.children[i]].calcBounds(gltf, localMat, bounds);\n\n bounds.apply(b);\n }\n }\n\n if (bounds.changed) return bounds;\n else return null;\n }\n\n setAnimAction(name)\n {\n // console.log(\"setAnimAction:\", name);\n if (!name) return;\n\n this._currentAnimaction = name;\n\n if (name && !this._animActions[name])\n {\n // console.log(\"no action found:\", name,this._animActions);\n return null;\n }\n\n // else console.log(\"YES action found:\", name);\n // console.log(this._animActions);\n\n for (let path in this._animActions[name])\n {\n if (path == \"translation\") this._animTrans = this._animActions[name][path];\n else if (path == \"rotation\") this._animRot = this._animActions[name][path];\n else if (path == \"scale\") this._animScale = this._animActions[name][path];\n else console.warn(\"unknown anim path\", path, this._animActions[name][path]);\n }\n }\n\n setAnim(path, name, anims)\n {\n if (!path || !name || !anims) return;\n\n // console.log(\"setanim\", this._node.name, path, name, anims);\n\n this._animActions[name] = this._animActions[name] || {};\n\n // console.log(this._animActions);\n // debugger;\n\n // for (let i = 0; i < this.copies.length; i++) this.copies[i]._animActions = this._animActions;\n\n if (this._animActions[name][path]) op.warn(\"animation action path already exists\", name, path, this._animActions[name][path]);\n\n this._animActions[name][path] = anims;\n\n if (path == \"translation\") this._animTrans = anims;\n else if (path == \"rotation\") this._animRot = anims;\n else if (path == \"scale\") this._animScale = anims;\n else console.warn(\"unknown anim path\", path, anims);\n }\n\n modelMatLocal()\n {\n return this._animMat || this.mat;\n }\n\n modelMatAbs()\n {\n return this.absMat;\n }\n\n transform(cgl, _time)\n {\n if (!_time && _time != 0)_time = time;\n\n this._lastTimeTrans = _time;\n\n // console.log(this._rot)\n\n gltfTransforms++;\n\n if (!this._animTrans && !this._animRot && !this._animScale)\n {\n mat4.mul(cgl.mMatrix, cgl.mMatrix, this.mat);\n this._animMat = null;\n }\n else\n {\n this._animMat = this._animMat || mat4.create();\n mat4.identity(this._animMat);\n\n const playAnims = true;\n\n if (playAnims && this._animTrans)\n {\n mat4.translate(this._animMat, this._animMat, [\n this._animTrans[0].getValue(_time),\n this._animTrans[1].getValue(_time),\n this._animTrans[2].getValue(_time)]);\n }\n else\n if (this._node.translation) mat4.translate(this._animMat, this._animMat, this._node.translation);\n\n if (playAnims && this._animRot)\n {\n if (this._animRot[0].defaultEasing == CABLES.EASING_LINEAR) CABLES.TL.Anim.slerpQuaternion(_time, this._tempQuat, this._animRot[0], this._animRot[1], this._animRot[2], this._animRot[3]);\n else if (this._animRot[0].defaultEasing == CABLES.EASING_ABSOLUTE)\n {\n this._tempQuat[0] = this._animRot[0].getValue(_time);\n this._tempQuat[1] = this._animRot[1].getValue(_time);\n this._tempQuat[2] = this._animRot[2].getValue(_time);\n this._tempQuat[3] = this._animRot[3].getValue(_time);\n }\n else if (this._animRot[0].defaultEasing == CABLES.EASING_CUBICSPLINE)\n {\n CABLES.TL.Anim.slerpQuaternion(_time, this._tempQuat, this._animRot[0], this._animRot[1], this._animRot[2], this._animRot[3]);\n }\n\n mat4.fromQuat(this._tempMat, this._tempQuat);\n mat4.mul(this._animMat, this._animMat, this._tempMat);\n }\n else if (this._rot)\n {\n mat4.fromQuat(this._tempRotmat, this._rot);\n mat4.mul(this._animMat, this._animMat, this._tempRotmat);\n }\n\n if (playAnims && this._animScale)\n {\n if (!this._tempAnimScale) this._tempAnimScale = [1, 1, 1];\n this._tempAnimScale[0] = this._animScale[0].getValue(_time);\n this._tempAnimScale[1] = this._animScale[1].getValue(_time);\n this._tempAnimScale[2] = this._animScale[2].getValue(_time);\n mat4.scale(this._animMat, this._animMat, this._tempAnimScale);\n }\n else if (this._scale) mat4.scale(this._animMat, this._animMat, this._scale);\n\n mat4.mul(cgl.mMatrix, cgl.mMatrix, this._animMat);\n }\n\n if (this.addTranslate) mat4.translate(cgl.mMatrix, cgl.mMatrix, this.addTranslate);\n\n if (this.addMulMat) mat4.mul(cgl.mMatrix, cgl.mMatrix, this.addMulMat);\n\n mat4.copy(this.absMat, cgl.mMatrix);\n }\n\n render(cgl, dontTransform, dontDrawMesh, ignoreMaterial, ignoreChilds, drawHidden, _time)\n {\n if (!dontTransform) cgl.pushModelMatrix();\n\n if (_time === undefined) _time = gltf.time;\n\n if (!dontTransform || this.skinRenderer) this.transform(cgl, _time);\n\n if (this.hidden && !drawHidden)\n {\n }\n else\n {\n if (this.skinRenderer)\n {\n this.skinRenderer.time = _time;\n if (!dontDrawMesh)\n this.mesh.render(cgl, ignoreMaterial, this.skinRenderer, _time);\n }\n else\n {\n if (this.mesh && !dontDrawMesh)\n this.mesh.render(cgl, ignoreMaterial, null, _time);\n }\n }\n\n if (!ignoreChilds && !this.hidden)\n for (let i = 0; i < this.children.length; i++)\n if (gltf.nodes[this.children[i]])\n gltf.nodes[this.children[i]].render(cgl, dontTransform, dontDrawMesh, ignoreMaterial, ignoreChilds, drawHidden, _time);\n\n if (!dontTransform)cgl.popModelMatrix();\n }\n};\n","inc_print_js":"let tab = null;\n\nfunction closeTab()\n{\n if (tab)gui.mainTabs.closeTab(tab.id);\n tab = null;\n}\n\nfunction formatVec(arr)\n{\n const nums = [];\n for (let i = 0; i < arr.length; i++)\n {\n nums.push(Math.round(arr[i] * 1000) / 1000);\n }\n\n return nums.join(\",\");\n}\n\nfunction printNode(html, node, level)\n{\n if (!gltf) return;\n\n html += \"\";\n\n let ident = \"\";\n let identSpace = \"\";\n\n for (let i = 1; i < level; i++)\n {\n identSpace += \"   \";\n let identClass = \"identBg\";\n if (i == 1)identClass = \"identBgLevel0\";\n ident += \"
\";\n }\n let id = CABLES.uuid();\n html += ident;\n html += \"\";\n // html+='
';\n\n if (node.mesh && node.mesh.meshes.length)html += \" \";\n else html += \"  \";\n\n html += node.name + \"\";\n\n if (node.mesh)\n {\n html += \"\";\n for (let i = 0; i < node.mesh.meshes.length; i++)\n {\n if (i > 0)html += \", \";\n html += node.mesh.meshes[i].name;\n }\n\n html += \"\";\n\n html += \"\";\n html += node.hasSkin() || \"-\";\n html += \"\";\n\n html += \"\";\n let countMats = 0;\n for (let i = 0; i < node.mesh.meshes.length; i++)\n {\n if (countMats > 0)html += \", \";\n if (gltf.json.materials && node.mesh.meshes[i].hasOwnProperty(\"material\"))\n {\n if (gltf.json.materials[node.mesh.meshes[i].material])\n {\n html += gltf.json.materials[node.mesh.meshes[i].material].name;\n countMats++;\n }\n }\n }\n if (countMats == 0)html += \"none\";\n html += \"\";\n }\n else\n {\n html += \"---\";\n }\n\n html += \"\";\n\n if (node._node.translation || node._node.rotation || node._node.scale)\n {\n let info = \"\";\n\n if (node._node.translation)info += \"Translate: `\" + formatVec(node._node.translation) + \"` || \";\n if (node._node.rotation)info += \"Rotation: `\" + formatVec(node._node.rotation) + \"` || \";\n if (node._node.scale)info += \"Scale: `\" + formatVec(node._node.scale) + \"` || \";\n\n html += \"  \";\n }\n\n if (node._animRot || node._animScale || node._animTrans)\n {\n let info = \"Animated: \";\n if (node._animRot) info += \"Rot \";\n if (node._animScale) info += \"Scale \";\n if (node._animTrans) info += \"Trans \";\n\n html += \" \";\n }\n\n if (!node._node.translation && !node._node.rotation && !node._node.scale && !node._animRot && !node._animScale && !node._animTrans) html += \"-\";\n\n html += \"\";\n\n html += \"\";\n let hideclass = \"\";\n if (node.hidden)hideclass = \"node-hidden\";\n\n // html+='';\n html += \"Transform\";\n html += \" Hierarchy\";\n html += \" Node\";\n\n if (node.hasSkin())\n html += \" Skin\";\n\n html += \"\";\n html += \" \";\n html += \"\";\n\n html += \"\";\n\n if (node.children)\n {\n for (let i = 0; i < node.children.length; i++)\n html = printNode(html, gltf.nodes[node.children[i]], level + 1);\n }\n\n return html;\n}\n\nfunction printMaterial(mat, idx)\n{\n let html = \"\";\n html += \" \" + idx + \"\";\n html += \" \" + mat.name + \"\";\n // html+=' Assign';\n\n html += \" \";\n\n const info = JSON.stringify(mat, null, 4).replaceAll(\"\\\"\", \"\").replaceAll(\"\\n\", \"
\");\n\n html += \"\" + info + \"', 'title': '\" + mat.name + \"' });\\\"> \";\n\n if (mat.pbrMetallicRoughness && mat.pbrMetallicRoughness.baseColorFactor)\n {\n let rgb = \"\";\n rgb += \"\" + Math.round(mat.pbrMetallicRoughness.baseColorFactor[0] * 255);\n rgb += \",\" + Math.round(mat.pbrMetallicRoughness.baseColorFactor[1] * 255);\n rgb += \",\" + Math.round(mat.pbrMetallicRoughness.baseColorFactor[2] * 255);\n\n html += \"
 \";\n }\n html += \" \" + (gltf.shaders[idx] ? \"-\" : \"Assign\") + \"\";\n html += \"\";\n\n html += \"\";\n return html;\n}\n\nfunction printInfo()\n{\n if (!gltf) return;\n\n const startTime = performance.now();\n const sizes = {};\n let html = \"
\";\n\n html += \"generator:\" + gltf.json.asset.generator;\n\n let numNodes = 0;\n if (gltf.json.nodes)numNodes = gltf.json.nodes.length;\n html += \"
Nodes (\" + numNodes + \")
\";\n\n html += \"\";\n\n html += \"\";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \"\";\n\n for (let i = 0; i < gltf.nodes.length; i++)\n {\n if (!gltf.nodes[i].isChild)\n html = printNode(html, gltf.nodes[i], 1);\n }\n html += \"
NameMeshSkinMaterialTransformExpose
\";\n\n // / //////////////////\n\n let numMaterials = 0;\n if (gltf.json.materials)numMaterials = gltf.json.materials.length;\n html += \"
Materials (\" + numMaterials + \")
\";\n\n if (!gltf.json.materials || gltf.json.materials.length == 0)\n {\n }\n else\n {\n html += \"\";\n html += \"\";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \"\";\n for (let i = 0; i < gltf.json.materials.length; i++)\n {\n html += printMaterial(gltf.json.materials[i], i);\n }\n html += \"
IndexNameColorFunction
\";\n }\n\n // / ///////////////////////\n\n html += \"
Meshes (\" + gltf.json.meshes.length + \")
\";\n\n html += \"\";\n html += \"\";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \"\";\n\n let sizeBufferViews = [];\n sizes.meshes = 0;\n\n for (let i = 0; i < gltf.json.meshes.length; i++)\n {\n html += \"\";\n html += \"\";\n\n html += \"\";\n\n // -------\n\n html += \"\";\n\n html += \"\";\n\n html += \"\";\n html += \"\";\n\n for (let j = 0; j < gltf.json.meshes[i].primitives.length; j++)\n {\n const accessor = gltf.json.accessors[gltf.json.meshes[i].primitives[j].indices];\n if (accessor)\n {\n let bufView = accessor.bufferView;\n\n if (sizeBufferViews.indexOf(bufView) == -1)\n {\n sizeBufferViews.push(bufView);\n if (gltf.json.bufferViews[bufView])sizes.meshes += gltf.json.bufferViews[bufView].byteLength;\n }\n }\n\n for (let k in gltf.json.meshes[i].primitives[j].attributes)\n {\n const attr = gltf.json.meshes[i].primitives[j].attributes[k];\n const bufView2 = gltf.json.accessors[attr].bufferView;\n\n if (sizeBufferViews.indexOf(bufView2) == -1)\n {\n sizeBufferViews.push(bufView2);\n if (gltf.json.bufferViews[bufView2])sizes.meshes += gltf.json.bufferViews[bufView2].byteLength;\n }\n }\n }\n }\n html += \"
NameNodeMaterialVerticesAttributes
\" + gltf.json.meshes[i].name + \"\";\n let count = 0;\n let nodename = \"\";\n for (var j = 0; j < gltf.json.nodes.length; j++)\n {\n if (gltf.json.nodes[j].mesh == i)\n {\n count++;\n if (count == 1)\n {\n nodename = gltf.json.nodes[j].name;\n }\n }\n }\n if (count > 1) html += (count) + \" nodes (\" + nodename + \" ...)\";\n else html += nodename;\n html += \"\";\n for (var j = 0; j < gltf.json.meshes[i].primitives.length; j++)\n {\n if (gltf.json.meshes[i].primitives[j].hasOwnProperty(\"material\"))\n {\n if (gltf.json.materials[gltf.json.meshes[i]])\n {\n html += gltf.json.materials[gltf.json.meshes[i].primitives[j].material].name + \" \";\n }\n }\n else html += \"None\";\n }\n html += \"\";\n let numVerts = 0;\n for (var j = 0; j < gltf.json.meshes[i].primitives.length; j++)\n {\n if (gltf.json.meshes[i].primitives[j].attributes.POSITION != undefined)\n {\n let v = parseInt(gltf.json.accessors[gltf.json.meshes[i].primitives[j].attributes.POSITION].count);\n numVerts += v;\n html += \"\" + v + \"
\";\n }\n else html += \"-
\";\n }\n\n if (gltf.json.meshes[i].primitives.length > 0)\n html += \"=\" + numVerts;\n html += \"
\";\n for (let j = 0; j < gltf.json.meshes[i].primitives.length; j++)\n {\n html += Object.keys(gltf.json.meshes[i].primitives[j].attributes);\n html += \" Geometry\";\n html += \"
\";\n }\n html += \"
\";\n\n // / //////////////////////////////////\n\n let numAnims = 0;\n if (gltf.json.animations)numAnims = gltf.json.animations.length;\n html += \"
Animations (\" + numAnims + \")
\";\n\n if (gltf.json.animations)\n {\n html += \"\";\n html += \"\";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \"\";\n\n sizes.animations = 0;\n\n for (let i = 0; i < gltf.json.animations.length; i++)\n {\n for (let j = 0; j < gltf.json.animations[i].samplers.length; j++)\n {\n let bufView = gltf.json.accessors[gltf.json.animations[i].samplers[j].input].bufferView;\n if (sizeBufferViews.indexOf(bufView) == -1)\n {\n sizeBufferViews.push(bufView);\n sizes.animations += gltf.json.bufferViews[bufView].byteLength;\n }\n\n bufView = gltf.json.accessors[gltf.json.animations[i].samplers[j].output].bufferView;\n if (sizeBufferViews.indexOf(bufView) == -1)\n {\n sizeBufferViews.push(bufView);\n sizes.animations += gltf.json.bufferViews[bufView].byteLength;\n }\n }\n\n for (let j = 0; j < gltf.json.animations[i].channels.length; j++)\n {\n html += \"\";\n html += \" \";\n\n html += \" \";\n html += \" \";\n\n const smplidx = gltf.json.animations[i].channels[j].sampler;\n const smplr = gltf.json.animations[i].samplers[smplidx];\n\n html += \" \";\n\n html += \" \";\n\n html += \"\";\n }\n }\n html += \"
NameTarget nodePathInterpolationKeys
Anim \" + i + \": \" + gltf.json.animations[i].name + \"\" + gltf.nodes[gltf.json.animations[i].channels[j].target.node].name + \"\";\n html += gltf.json.animations[i].channels[j].target.path + \" \";\n html += \" \" + smplr.interpolation + \"\" + gltf.json.accessors[smplr.output].count;\n\n html += \"  \";\n\n html += \"
\";\n }\n else\n {\n\n }\n\n // / ///////////////////\n\n let numImages = 0;\n if (gltf.json.images)numImages = gltf.json.images.length;\n html += \"
Images (\" + numImages + \")
\";\n\n if (gltf.json.images)\n {\n html += \"\";\n\n html += \"\";\n html += \" \";\n html += \" \";\n html += \" \";\n\n html += \"\";\n\n sizes.images = 0;\n\n for (let i = 0; i < gltf.json.images.length; i++)\n {\n if (gltf.json.images[i].bufferView)\n sizes.images += gltf.json.bufferViews[gltf.json.images[i].bufferView].byteLength;\n\n html += \"\";\n html += \"\";\n html += \"\";\n html += \"\";\n\n html += \"\";\n }\n html += \"
nametypefunc
\" + gltf.json.images[i].name + \"\" + gltf.json.images[i].mimeType + \"\";\n\n let name = gltf.json.images[i].name;\n if (name === undefined)name = gltf.json.images[i].bufferView;\n\n html += \"Expose\";\n html += \"
\";\n }\n\n // / ///////////////////////\n\n let numCameras = 0;\n if (gltf.json.cameras)numCameras = gltf.json.cameras.length;\n html += \"
Cameras (\" + numCameras + \")
\";\n\n if (gltf.json.cameras)\n {\n html += \"\";\n\n html += \"\";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \"\";\n\n for (let i = 0; i < gltf.json.cameras.length; i++)\n {\n html += \"\";\n html += \"\";\n html += \"\";\n html += \"\";\n\n html += \"\";\n }\n html += \"
nametypeinfo
\" + gltf.json.cameras[i].name + \"\" + gltf.json.cameras[i].type + \"\";\n\n if (gltf.json.cameras[i].perspective)\n {\n html += \"yfov: \" + Math.round(gltf.json.cameras[i].perspective.yfov * 100) / 100;\n html += \", \";\n html += \"zfar: \" + Math.round(gltf.json.cameras[i].perspective.zfar * 100) / 100;\n html += \", \";\n html += \"znear: \" + Math.round(gltf.json.cameras[i].perspective.znear * 100) / 100;\n }\n html += \"
\";\n }\n\n // / ////////////////////////////////////\n\n let numSkins = 0;\n if (gltf.json.skins)numSkins = gltf.json.skins.length;\n html += \"
Skins (\" + numSkins + \")
\";\n\n if (gltf.json.skins)\n {\n // html += \"

Skins (\" + gltf.json.skins.length + \")

\";\n html += \"\";\n\n html += \"\";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \"\";\n\n for (let i = 0; i < gltf.json.skins.length; i++)\n {\n html += \"\";\n html += \"\";\n html += \"\";\n html += \"\";\n html += \"\";\n html += \"\";\n }\n html += \"
nametotal joints
\" + gltf.json.skins[i].name + \"\" + \"\" + gltf.json.skins[i].joints.length + \"\";\n html += \"
\";\n }\n\n // / //////////////////////////\n\n let sizeBin = 0;\n if (gltf.json.buffers)\n sizeBin = gltf.json.buffers[0].byteLength;\n\n html += \"
File Size Allocation (\" + Math.round(sizeBin / 1024) + \"k )
\";\n\n html += \"\";\n html += \"\";\n html += \" \";\n html += \" \";\n html += \" \";\n html += \"\";\n let sizeUnknown = sizeBin;\n for (let i in sizes)\n {\n // html+=i+':'+Math.round(sizes[i]/1024);\n html += \"\";\n html += \"\";\n html += \"\";\n html += \"\";\n html += \"\";\n sizeUnknown -= sizes[i];\n }\n\n if (sizeUnknown != 0)\n {\n html += \"\";\n html += \"\";\n html += \"\";\n html += \"\";\n html += \"\";\n }\n\n html += \"
namesize%
\" + i + \"\" + readableSize(sizes[i]) + \" \" + Math.round(sizes[i] / sizeBin * 100) + \"%
unknown\" + readableSize(sizeUnknown) + \" \" + Math.round(sizeUnknown / sizeBin * 100) + \"%
\";\n html += \"
\";\n\n tab = new CABLES.UI.Tab(\"GLTF\", { \"icon\": \"cube\", \"infotext\": \"tab_gltf\", \"padding\": true, \"singleton\": true });\n gui.mainTabs.addTab(tab, true);\n\n tab.addEventListener(\"onClose\", closeTab);\n tab.html(html);\n\n CABLES.UI.Collapsable.setup(ele.byId(\"groupNodes\"), ele.byId(\"sectionNodes\"), false);\n CABLES.UI.Collapsable.setup(ele.byId(\"groupMaterials\"), ele.byId(\"materialtable\"), true);\n CABLES.UI.Collapsable.setup(ele.byId(\"groupAnims\"), ele.byId(\"sectionAnim\"), true);\n CABLES.UI.Collapsable.setup(ele.byId(\"groupMeshes\"), ele.byId(\"meshestable\"), true);\n CABLES.UI.Collapsable.setup(ele.byId(\"groupCameras\"), ele.byId(\"sectionCameras\"), true);\n CABLES.UI.Collapsable.setup(ele.byId(\"groupImages\"), ele.byId(\"sectionImages\"), true);\n CABLES.UI.Collapsable.setup(ele.byId(\"groupSkins\"), ele.byId(\"sectionSkins\"), true);\n CABLES.UI.Collapsable.setup(ele.byId(\"groupBinary\"), ele.byId(\"sectionBinary\"), true);\n\n gui.maintabPanel.show(true);\n}\n\nfunction readableSize(n)\n{\n if (n > 1024) return Math.round(n / 1024) + \" kb\";\n if (n > 1024 * 500) return Math.round(n / 1024) + \" mb\";\n else return n + \" bytes\";\n}\n","inc_skin_js":"const GltfSkin = class\n{\n constructor(node)\n {\n this._mod = null;\n this._node = node;\n this._lastTime = 0;\n this._matArr = [];\n this._m = mat4.create();\n this._invBindMatrix = mat4.create();\n this.identity = true;\n }\n\n renderFinish(cgl)\n {\n cgl.popModelMatrix();\n this._mod.unbind();\n }\n\n renderStart(cgl, time)\n {\n if (!this._mod)\n {\n this._mod = new CGL.ShaderModifier(cgl, op.name + this._node.name);\n\n this._mod.addModule({\n \"priority\": -2,\n \"name\": \"MODULE_VERTEX_POSITION\",\n \"srcHeadVert\": attachments.skin_head_vert || \"\",\n \"srcBodyVert\": attachments.skin_vert || \"\"\n });\n\n this._mod.addUniformVert(\"m4[]\", \"MOD_boneMats\", []);// bohnenmatze\n const tr = vec3.create();\n }\n\n const skinIdx = this._node.skin;\n const arrLength = gltf.json.skins[skinIdx].joints.length * 16;\n\n // if (this._lastTime != time || !time)\n {\n // this._lastTime=inTime.get();\n if (this._matArr.length != arrLength) this._matArr.length = arrLength;\n\n for (let i = 0; i < gltf.json.skins[skinIdx].joints.length; i++)\n {\n const i16 = i * 16;\n const jointIdx = gltf.json.skins[skinIdx].joints[i];\n const nodeJoint = gltf.nodes[jointIdx];\n\n for (let j = 0; j < 16; j++)\n this._invBindMatrix[j] = gltf.accBuffers[gltf.json.skins[skinIdx].inverseBindMatrices][i16 + j];\n\n mat4.mul(this._m, nodeJoint.modelMatAbs(), this._invBindMatrix);\n\n for (let j = 0; j < this._m.length; j++) this._matArr[i16 + j] = this._m[j];\n }\n\n this._mod.setUniformValue(\"MOD_boneMats\", this._matArr);\n this._lastTime = time;\n }\n\n this._mod.define(\"SKIN_NUM_BONES\", gltf.json.skins[skinIdx].joints.length);\n this._mod.bind();\n\n // draw mesh...\n cgl.pushModelMatrix();\n if (this.identity)mat4.identity(cgl.mMatrix);\n }\n};\n","skin_vert":"int index=int(attrJoints.x);\nvec4 newPos = (MOD_boneMats[index] * pos) * attrWeights.x;\nvec3 newNorm = (vec4((MOD_boneMats[index] * vec4(norm.xyz, 0.0)) * attrWeights.x).xyz);\n\nindex=int(attrJoints.y);\nnewPos += (MOD_boneMats[index] * pos) * attrWeights.y;\nnewNorm = (vec4((MOD_boneMats[index] * vec4(norm.xyz, 0.0)) * attrWeights.y).xyz)+newNorm;\n\nindex=int(attrJoints.z);\nnewPos += (MOD_boneMats[index] * pos) * attrWeights.z;\nnewNorm = (vec4((MOD_boneMats[index] * vec4(norm.xyz, 0.0)) * attrWeights.z).xyz)+newNorm;\n\nindex=int(attrJoints.w);\nnewPos += (MOD_boneMats[index] * pos) * attrWeights.w ;\nnewNorm = (vec4((MOD_boneMats[index] * vec4(norm.xyz, 0.0)) * attrWeights.w).xyz)+newNorm;\n\npos=newPos;\n\nnorm=normalize(newNorm.xyz);\n\n\n","skin_head_vert":"\nIN vec4 attrWeights;\nIN vec4 attrJoints;\nUNI mat4 MOD_boneMats[SKIN_NUM_BONES];\n",}; +const gltfCamera = class +{ + constructor(gltf, node) + { + this.node=node; + this.name=node.name; + // console.log(gltf); + this.config=gltf.json.cameras[node.camera]; + + this.pos = vec3.create(); + this.quat = quat.create(); + this.quatOr = quat.create(); + this.vCenter = vec3.create(); + this.vUp = vec3.create(); + this.vMat = mat4.create(); + + } + + updateAnim(time) + { + if (this.node && this.node._animTrans) + { + + vec3.set(this.pos, + this.node._animTrans[0].getValue(time), + this.node._animTrans[1].getValue(time), + this.node._animTrans[2].getValue(time)); + + quat.set(this.quat, + this.node._animRot[0].getValue(time), + this.node._animRot[1].getValue(time), + this.node._animRot[2].getValue(time), + this.node._animRot[3].getValue(time)); + } + } + + start(time) + { + if (cgl.frameStore.shadowPass) return; + + this.updateAnim(time); + const asp = cgl.getViewPort()[2] / cgl.getViewPort()[3]; + + cgl.pushPMatrix(); + // mat4.perspective( + // cgl.pMatrix, + // this.config.perspective.yfov*0.5, + // asp, + // this.config.perspective.znear, + // this.config.perspective.zfar); + + cgl.pushViewMatrix(); + // mat4.identity(cgl.vMatrix); + + // if(this.node && this.node.parent) + // { + // console.log(this.node.parent) + // vec3.add(this.pos,this.pos,this.node.parent._node.translation); + // vec3.sub(this.vCenter,this.vCenter,this.node.parent._node.translation); + // mat4.translate(cgl.vMatrix,cgl.vMatrix, + // [ + // -this.node.parent._node.translation[0], + // -this.node.parent._node.translation[1], + // -this.node.parent._node.translation[2] + // ]) + // } + + + + // vec3.set(this.vUp, 0, 1, 0); + // vec3.set(this.vCenter, 0, -1, 0); + // // vec3.set(this.vCenter, 0, 1, 0); + // vec3.transformQuat(this.vCenter, this.vCenter, this.quat); + // vec3.normalize(this.vCenter, this.vCenter); + // vec3.add(this.vCenter, this.vCenter, this.pos); + + + // mat4.lookAt(cgl.vMatrix, this.pos, this.vCenter, this.vUp); + + + let mv=mat4.create(); + mat4.invert(mv,this.node.modelMatAbs()); + + // console.log(this.node.modelMatAbs()); + + this.vMat=mv; + + mat4.identity(cgl.vMatrix); + // console.log(mv); + mat4.mul(cgl.vMatrix,cgl.vMatrix,mv); + + + } + + end() + { + if (cgl.frameStore.shadowPass) return; + cgl.popPMatrix(); + cgl.popViewMatrix(); + } +}; + +const CHUNK_HEADER_SIZE = 8; + +const Gltf = class +{ + constructor() + { + this.json = {}; + this.accBuffers = []; + this.meshes = []; + this.nodes = []; + this.shaders = []; + this.timing = []; + this.cams = []; + this.startTime = performance.now(); + this.bounds = new CABLES.CG.BoundingBox(); + this.loaded = Date.now(); + this.accBuffersDelete = []; + } + + getNode(n) + { + for (let i = 0; i < this.nodes.length; i++) + { + if (this.nodes[i].name == n) return this.nodes[i]; + } + } + + unHideAll() + { + for (let i = 0; i < this.nodes.length; i++) + { + this.nodes[i].unHide(); + } + } +}; + +function Utf8ArrayToStr(array) +{ + if (window.TextDecoder) return new TextDecoder("utf-8").decode(array); + + let out, i, len, c; + let char2, char3; + + out = ""; + len = array.length; + i = 0; + while (i < len) + { + c = array[i++]; + switch (c >> 4) + { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + // 0xxxxxxx + out += String.fromCharCode(c); + break; + case 12: case 13: + // 110x xxxx 10xx xxxx + char2 = array[i++]; + out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); + break; + case 14: + // 1110 xxxx 10xx xxxx 10xx xxxx + char2 = array[i++]; + char3 = array[i++]; + out += String.fromCharCode(((c & 0x0F) << 12) | + ((char2 & 0x3F) << 6) | + ((char3 & 0x3F) << 0)); + break; + } + } + + return out; +} + +function readChunk(dv, bArr, arrayBuffer, offset) +{ + const chunk = {}; + + if (offset >= dv.byteLength) + { + op.log("could not read chunk..."); + return; + } + chunk.size = dv.getUint32(offset + 0, le); + + // chunk.type = new TextDecoder("utf-8").decode(bArr.subarray(offset+4, offset+4+4)); + chunk.type = Utf8ArrayToStr(bArr.subarray(offset + 4, offset + 4 + 4)); + + if (chunk.type == "BIN\0") + { + // console.log(chunk.size,arrayBuffer.length,offset); + // try + // { + chunk.dataView = new DataView(arrayBuffer, offset + 8, chunk.size); + // } + // catch(e) + // { + // chunk.dataView = null; + // console.log(e); + // } + } + else + if (chunk.type == "JSON") + { + const json = Utf8ArrayToStr(bArr.subarray(offset + 8, offset + 8 + chunk.size)); + + try + { + const obj = JSON.parse(json); + chunk.data = obj; + outGenerator.set(obj.asset.generator); + } + catch (e) + { + } + } + else + { + op.warn("unknown type", chunk.type); + } + + return chunk; +} + +function loadAnims(gltf) +{ + const uniqueAnimNames = {}; + + for (let i = 0; i < gltf.json.animations.length; i++) + { + const an = gltf.json.animations[i]; + + for (let ia = 0; ia < an.channels.length; ia++) + { + const chan = an.channels[ia]; + + const node = gltf.nodes[chan.target.node]; + const sampler = an.samplers[chan.sampler]; + + const acc = gltf.json.accessors[sampler.input]; + const bufferIn = gltf.accBuffers[sampler.input]; + + const accOut = gltf.json.accessors[sampler.output]; + const bufferOut = gltf.accBuffers[sampler.output]; + + gltf.accBuffersDelete.push(sampler.output, sampler.input); + + if (bufferIn && bufferOut) + { + let numComps = 1; + if (accOut.type == "VEC2")numComps = 2; + else if (accOut.type == "VEC3")numComps = 3; + else if (accOut.type == "VEC4")numComps = 4; + else op.warn("unknown accOut.type", accOut.type); + + const anims = []; + + uniqueAnimNames[an.name] = true; + + for (let k = 0; k < numComps; k++) + { + const newAnim = new CABLES.TL.Anim(); + // newAnim.name=an.name; + anims.push(newAnim); + } + + if (sampler.interpolation == "LINEAR") {} + else if (sampler.interpolation == "STEP") for (let k = 0; k < numComps; k++) anims[k].defaultEasing = CABLES.EASING_ABSOLUTE; + else if (sampler.interpolation == "CUBICSPLINE") for (let k = 0; k < numComps; k++) anims[k].defaultEasing = CABLES.EASING_CUBICSPLINE; + else op.warn("unknown interpolation", sampler.interpolation); + + // console.log(bufferOut) + + // if there is no keyframe for time 0 copy value of first keyframe at time 0 + if (bufferIn[0] !== 0.0) + for (let k = 0; k < numComps; k++) + anims[k].setValue(0, bufferOut[0 * numComps + k]); + + // console.log(sampler.interpolation,bufferOut.length/numComps) + + for (let j = 0; j < bufferIn.length; j++) + { + maxTime = Math.max(bufferIn[j], maxTime); + + for (let k = 0; k < numComps; k++) + { + if (anims[k].defaultEasing === CABLES.EASING_CUBICSPLINE) + { + const idx = ((j * numComps) * 3 + k); + + const key = anims[k].setValue(bufferIn[j], bufferOut[idx + numComps]); + key.bezTangIn = bufferOut[idx]; + key.bezTangOut = bufferOut[idx + (numComps * 2)]; + + // console.log(an.name,k,bufferOut[idx+1]); + } + else + { + // console.log(an.name,k,bufferOut[j * numComps + k]); + anims[k].setValue(bufferIn[j], bufferOut[j * numComps + k]); + } + } + } + + node.setAnim(chan.target.path, an.name, anims); + } + else + { + op.warn("loadAmins bufferIn undefined ", bufferIn === undefined); + op.warn("loadAmins bufferOut undefined ", bufferOut === undefined); + op.warn("loadAmins ", sampler, accOut); + op.warn("loadAmins num accBuffers", gltf.accBuffers.length); + op.warn("loadAmins num accessors", gltf.json.accessors.length); + } + } + } + + gltf.uniqueAnimNames = uniqueAnimNames; + + outAnims.set(null); + outAnims.set(Object.keys(uniqueAnimNames)); +} + +function loadCams(gltf) +{ + if (!gltf || !gltf.json.cameras) return; + + gltf.cameras = gltf.cameras || []; + + for (let i = 0; i < gltf.nodes.length; i++) + { + if (gltf.nodes[i].hasOwnProperty("camera")) + { + const cam = new gltfCamera(gltf, gltf.nodes[i]); + gltf.cameras.push(cam); + } + } +} + +function loadAfterDraco() +{ + if (!window.DracoDecoder) + { + setTimeout(() => + { + loadAfterDraco(); + }, 100); + } + + reloadSoon(); +} + +function parseGltf(arrayBuffer) +{ + let j = 0, i = 0; + + const gltf = new Gltf(); + gltf.timing.push("Start parsing", Math.round((performance.now() - gltf.startTime))); + + if (!arrayBuffer) return; + const byteArray = new Uint8Array(arrayBuffer); + let pos = 0; + + // var string = new TextDecoder("utf-8").decode(byteArray.subarray(pos, 4)); + const string = Utf8ArrayToStr(byteArray.subarray(pos, 4)); + pos += 4; + if (string != "glTF") return; + + gltf.timing.push("dataview", Math.round((performance.now() - gltf.startTime))); + + const dv = new DataView(arrayBuffer); + const version = dv.getUint32(pos, le); + pos += 4; + const size = dv.getUint32(pos, le); + pos += 4; + + outVersion.set(version); + + const chunks = []; + gltf.chunks = chunks; + + chunks.push(readChunk(dv, byteArray, arrayBuffer, pos)); + pos += chunks[0].size + CHUNK_HEADER_SIZE; + gltf.json = chunks[0].data; + outJson.set(gltf.json); + outExtensions.set(gltf.json.extensionsUsed || []); + + let ch = readChunk(dv, byteArray, arrayBuffer, pos); + while (ch) + { + chunks.push(ch); + pos += ch.size + CHUNK_HEADER_SIZE; + ch = readChunk(dv, byteArray, arrayBuffer, pos); + } + + gltf.chunks = chunks; + + const views = chunks[0].data.bufferViews; + const accessors = chunks[0].data.accessors; + + gltf.timing.push("Parse buffers", Math.round((performance.now() - gltf.startTime))); + + if (gltf.json.extensionsUsed && gltf.json.extensionsUsed.indexOf("KHR_draco_mesh_compression") > -1) + { + if (!window.DracoDecoder) + { + op.setUiError("gltfdraco", "GLTF draco compression lib not found / add draco op to your patch!"); + + loadAfterDraco(); + return gltf; + } + else + { + gltf.useDraco = true; + } + } + + op.setUiError("gltfdraco", null); + // let accPos = (view.byteOffset || 0) + (acc.byteOffset || 0); + + if (views) + { + for (i = 0; i < accessors.length; i++) + { + const acc = accessors[i]; + const view = views[acc.bufferView]; + + let numComps = 0; + if (acc.type == "SCALAR")numComps = 1; + else if (acc.type == "VEC2")numComps = 2; + else if (acc.type == "VEC3")numComps = 3; + else if (acc.type == "VEC4")numComps = 4; + else if (acc.type == "MAT4")numComps = 16; + else console.error("unknown accessor type", acc.type); + + // const decoder = new decoderModule.Decoder(); + // const decodedGeometry = decodeDracoData(data, decoder); + // // Encode mesh + // encodeMeshToFile(decodedGeometry, decoder); + + // decoderModule.destroy(decoder); + // decoderModule.destroy(decodedGeometry); + + // 5120 (BYTE) 1 + // 5121 (UNSIGNED_BYTE) 1 + // 5122 (SHORT) 2 + + if (chunks[1].dataView) + { + if (view) + { + const num = acc.count * numComps; + let accPos = (view.byteOffset || 0) + (acc.byteOffset || 0); + let stride = view.byteStride || 0; + let dataBuff = null; + + if (acc.componentType == 5126 || acc.componentType == 5125) // 4byte FLOAT or INT + { + stride = stride || 4; + + const isInt = acc.componentType == 5125; + if (isInt)dataBuff = new Uint32Array(num); + else dataBuff = new Float32Array(num); + + for (j = 0; j < num; j++) + { + if (isInt) dataBuff[j] = chunks[1].dataView.getUint32(accPos, le); + else dataBuff[j] = chunks[1].dataView.getFloat32(accPos, le); + + if (stride != 4 && (j + 1) % numComps === 0)accPos += stride - (numComps * 4); + accPos += 4; + } + } + else if (acc.componentType == 5123) // UNSIGNED_SHORT + { + stride = stride || 2; + + dataBuff = new Uint16Array(num); + + for (j = 0; j < num; j++) + { + dataBuff[j] = chunks[1].dataView.getUint16(accPos, le); + + if (stride != 2 && (j + 1) % numComps === 0) accPos += stride - (numComps * 2); + + accPos += 2; + } + } + else if (acc.componentType == 5121) // UNSIGNED_BYTE + { + stride = stride || 1; + + dataBuff = new Uint8Array(num); + + for (j = 0; j < num; j++) + { + dataBuff[j] = chunks[1].dataView.getUint8(accPos, le); + + if (stride != 1 && (j + 1) % numComps === 0) accPos += stride - (numComps * 1); + + accPos += 1; + } + } + + else + { + console.error("unknown component type", acc.componentType); + } + + gltf.accBuffers.push(dataBuff); + } + else + { + // console.log("has no dataview"); + } + } + } + } + + gltf.timing.push("Parse mesh groups", Math.round((performance.now() - gltf.startTime))); + + gltf.json.meshes = gltf.json.meshes || []; + + if (gltf.json.meshes) + { + for (i = 0; i < gltf.json.meshes.length; i++) + { + const mesh = new gltfMeshGroup(gltf, gltf.json.meshes[i]); + gltf.meshes.push(mesh); + } + } + + gltf.timing.push("Parse nodes", Math.round((performance.now() - gltf.startTime))); + + for (i = 0; i < gltf.json.nodes.length; i++) + { + if (gltf.json.nodes[i].children) + for (j = 0; j < gltf.json.nodes[i].children.length; j++) + { + gltf.json.nodes[gltf.json.nodes[i].children[j]].isChild = true; + } + } + + for (i = 0; i < gltf.json.nodes.length; i++) + { + const node = new gltfNode(gltf.json.nodes[i], gltf); + gltf.nodes.push(node); + } + + for (i = 0; i < gltf.nodes.length; i++) + { + const node = gltf.nodes[i]; + + if (!node.children) continue; + for (let j = 0; j < node.children.length; j++) + { + gltf.nodes[node.children[j]].parent = node; + } + } + + for (i = 0; i < gltf.nodes.length; i++) + { + gltf.nodes[i].initSkin(); + } + + needsMatUpdate = true; + + gltf.timing.push("load anims", Math.round((performance.now() - gltf.startTime))); + + if (gltf.json.animations) loadAnims(gltf); + + gltf.timing.push("load cameras", Math.round((performance.now() - gltf.startTime))); + + if (gltf.json.cameras) loadCams(gltf); + + gltf.timing.push("finished", Math.round((performance.now() - gltf.startTime))); + + return gltf; +} +let gltfMesh = class +{ + constructor(name, prim, gltf, finished) + { + this.POINTS = 0; + this.LINES = 1; + this.LINE_LOOP = 2; + this.LINE_STRIP = 3; + this.TRIANGLES = 4; + this.TRIANGLE_STRIP = 5; + this.TRIANGLE_FAN = 6; + + this.test = 0; + this.name = name; + this.submeshIndex = 0; + this.material = prim.material; + this.mesh = null; + this.geom = new CGL.Geometry("gltf_" + this.name); + this.geom.verticesIndices = []; + this.bounds = null; + this.primitive = 4; + if (prim.hasOwnProperty("mode")) this.primitive = prim.mode; + + if (prim.hasOwnProperty("indices")) this.geom.verticesIndices = gltf.accBuffers[prim.indices]; + + gltf.loadingMeshes = gltf.loadingMeshes || 0; + gltf.loadingMeshes++; + + this.materialJson = + this._matPbrMetalness = + this._matPbrRoughness = + this._matDiffuseColor = null; + + if (gltf.json.materials) + { + if (this.material != -1) this.materialJson = gltf.json.materials[this.material]; + + if (this.materialJson && this.materialJson.pbrMetallicRoughness) + { + if (!this.materialJson.pbrMetallicRoughness.hasOwnProperty("baseColorFactor")) + { + this._matDiffuseColor = [1, 1, 1, 1]; + } + else + { + this._matDiffuseColor = this.materialJson.pbrMetallicRoughness.baseColorFactor; + } + + this._matDiffuseColor = this.materialJson.pbrMetallicRoughness.baseColorFactor; + + if (!this.materialJson.pbrMetallicRoughness.hasOwnProperty("metallicFactor")) + { + this._matPbrMetalness = 1.0; + } + else + { + this._matPbrMetalness = this.materialJson.pbrMetallicRoughness.metallicFactor || null; + } + + if (!this.materialJson.pbrMetallicRoughness.hasOwnProperty("roughnessFactor")) + { + this._matPbrRoughness = 1.0; + } + else + { + this._matPbrRoughness = this.materialJson.pbrMetallicRoughness.roughnessFactor || null; + } + } + } + + if (gltf.useDraco && prim.extensions.KHR_draco_mesh_compression) + { + const view = gltf.chunks[0].data.bufferViews[prim.extensions.KHR_draco_mesh_compression.bufferView]; + const num = view.byteLength; + const dataBuff = new Int8Array(num); + let accPos = (view.byteOffset || 0);// + (acc.byteOffset || 0); + for (let j = 0; j < num; j++) + { + dataBuff[j] = gltf.chunks[1].dataView.getInt8(accPos, le); + accPos++; + } + + const dracoDecoder = window.DracoDecoder; + dracoDecoder.decodeGeometry(dataBuff.buffer, (geometry) => + { + const geom = new CGL.Geometry("draco mesh " + name); + + for (let i = 0; i < geometry.attributes.length; i++) + { + const attr = geometry.attributes[i]; + + if (attr.name === "position") geom.vertices = attr.array; + else if (attr.name === "normal") geom.vertexNormals = attr.array; + else if (attr.name === "uv") geom.texCoords = attr.array; + else if (attr.name === "color") geom.vertexColors = this.calcVertexColors(attr.array); + else if (attr.name === "joints") geom.setAttribute("attrJoints", Array.from(attr.array), 4); + else if (attr.name === "weights") + { + const arr4 = new Float32Array(attr.array.length / attr.itemSize * 4); + + for (let k = 0; k < attr.array.length / attr.itemSize; k++) + { + arr4[k * 4] = arr4[k * 4 + 1] = arr4[k * 4 + 2] = arr4[k * 4 + 3] = 0; + for (let j = 0; j < attr.itemSize; j++) + arr4[k * 4 + j] = attr.array[k * attr.itemSize + j]; + } + geom.setAttribute("attrWeights", arr4, 4); + } + else op.logWarn("unknown draco attrib", attr); + } + + geometry.attributes = null; + geom.verticesIndices = geometry.index.array; + + this.setGeom(geom); + + this.mesh = null; + gltf.loadingMeshes--; + if (finished)finished(this); + }, (error) => { op.logError(error); }); + } + else + { + gltf.loadingMeshes--; + this.fillGeomAttribs(gltf, this.geom, prim.attributes); + + if (prim.targets) + { + console.log("prim.targets", prim.targets.length); + for (let j = 0; j < prim.targets.length; j++) + { + // var tgeom=new CGL.Geometry("gltf_"+this.name); + let tgeom = this.geom.copy(); + + if (prim.hasOwnProperty("indices")) tgeom.verticesIndices = gltf.accBuffers[prim.indices]; + + this.fillGeomAttribs(gltf, tgeom, prim.targets[j], false); + + { // calculate normals for final position of morphtarget for later... + for (let i = 0; i < tgeom.vertices.length; i++) tgeom.vertices[i] += this.geom.vertices[i]; + tgeom.calculateNormals(); + for (let i = 0; i < tgeom.vertices.length; i++) tgeom.vertices[i] -= this.geom.vertices[i]; + } + + this.geom.morphTargets.push(tgeom); + } + } + if (finished)finished(this); + } + } + + _linearToSrgb(x) + { + if (x <= 0) + return 0; + else if (x >= 1) + return 1; + else if (x < 0.0031308) + return x * 12.92; + else + return Math.pow(x, 1 / 2.2) * 1.055 - 0.055; + } + + calcVertexColors(arr) + { + let vertexColors = null; + if (arr instanceof Float32Array) + { + let div = false; + for (let i = 0; i < arr.length; i++) + { + if (arr[i] > 1) + { + div = true; + continue; + } + } + + if (div) + for (let i = 0; i < arr.length; i++) arr[i] /= 65535; + + vertexColors = arr; + } + + else if (arr instanceof Uint16Array) + { + const fb = new Float32Array(arr.length); + for (let i = 0; i < arr.length; i++) fb[i] = arr[i] / 65535; + + vertexColors = fb; + } + else vertexColors = arr; + + for (let i = 0; i < vertexColors.length; i++) + { + vertexColors[i] = this._linearToSrgb(vertexColors[i]); + } + + return vertexColors; + } + + fillGeomAttribs(gltf, tgeom, attribs, setGeom) + { + if (attribs.hasOwnProperty("POSITION")) tgeom.vertices = gltf.accBuffers[attribs.POSITION]; + if (attribs.hasOwnProperty("NORMAL")) tgeom.vertexNormals = gltf.accBuffers[attribs.NORMAL]; + if (attribs.hasOwnProperty("TANGENT")) tgeom.tangents = gltf.accBuffers[attribs.TANGENT]; + + if (attribs.hasOwnProperty("COLOR_0")) tgeom.vertexColors = this.calcVertexColors(gltf.accBuffers[attribs.COLOR_0]); + if (attribs.hasOwnProperty("COLOR_1")) tgeom.setAttribute("attrVertColor1", this.calcVertexColors(gltf.accBuffers[attribs.COLOR_1]), 4); + if (attribs.hasOwnProperty("COLOR_2")) tgeom.setAttribute("attrVertColor2", this.calcVertexColors(gltf.accBuffers[attribs.COLOR_2]), 4); + if (attribs.hasOwnProperty("COLOR_3")) tgeom.setAttribute("attrVertColor3", this.calcVertexColors(gltf.accBuffers[attribs.COLOR_3]), 4); + if (attribs.hasOwnProperty("COLOR_4")) tgeom.setAttribute("attrVertColor4", this.calcVertexColors(gltf.accBuffers[attribs.COLOR_4]), 4); + + if (attribs.hasOwnProperty("TEXCOORD_0"))tgeom.texCoords = gltf.accBuffers[attribs.TEXCOORD_0]; + if (attribs.hasOwnProperty("TEXCOORD_1"))tgeom.setAttribute("attrTexCoord1", gltf.accBuffers[attribs.TEXCOORD_1], 2); + if (attribs.hasOwnProperty("TEXCOORD_2"))tgeom.setAttribute("attrTexCoord2", gltf.accBuffers[attribs.TEXCOORD_2], 2); + if (attribs.hasOwnProperty("TEXCOORD_3"))tgeom.setAttribute("attrTexCoord3", gltf.accBuffers[attribs.TEXCOORD_3], 2); + if (attribs.hasOwnProperty("TEXCOORD_4"))tgeom.setAttribute("attrTexCoord4", gltf.accBuffers[attribs.TEXCOORD_4], 2); + + if (attribs.hasOwnProperty("WEIGHTS_0")) + { + tgeom.setAttribute("attrWeights", gltf.accBuffers[attribs.WEIGHTS_0], 4); + } + if (attribs.hasOwnProperty("JOINTS_0")) + { + if (!gltf.accBuffers[attribs.JOINTS_0])console.log("no !gltf.accBuffers[attribs.JOINTS_0]"); + tgeom.setAttribute("attrJoints", gltf.accBuffers[attribs.JOINTS_0], 4); + } + + if (attribs.hasOwnProperty("POSITION")) gltf.accBuffersDelete.push(attribs.POSITION); + if (attribs.hasOwnProperty("NORMAL")) gltf.accBuffersDelete.push(attribs.NORMAL); + if (attribs.hasOwnProperty("TEXCOORD_0")) gltf.accBuffersDelete.push(attribs.TEXCOORD_0); + if (attribs.hasOwnProperty("TANGENT")) gltf.accBuffersDelete.push(attribs.TANGENT); + if (attribs.hasOwnProperty("COLOR_0"))gltf.accBuffersDelete.push(attribs.COLOR_0); + if (attribs.hasOwnProperty("COLOR_0"))gltf.accBuffersDelete.push(attribs.COLOR_0); + if (attribs.hasOwnProperty("COLOR_1"))gltf.accBuffersDelete.push(attribs.COLOR_1); + if (attribs.hasOwnProperty("COLOR_2"))gltf.accBuffersDelete.push(attribs.COLOR_2); + if (attribs.hasOwnProperty("COLOR_3"))gltf.accBuffersDelete.push(attribs.COLOR_3); + + if (attribs.hasOwnProperty("TEXCOORD_1")) gltf.accBuffersDelete.push(attribs.TEXCOORD_1); + if (attribs.hasOwnProperty("TEXCOORD_2")) gltf.accBuffersDelete.push(attribs.TEXCOORD_2); + if (attribs.hasOwnProperty("TEXCOORD_3")) gltf.accBuffersDelete.push(attribs.TEXCOORD_3); + if (attribs.hasOwnProperty("TEXCOORD_4")) gltf.accBuffersDelete.push(attribs.TEXCOORD_4); + + if (setGeom !== false) if (tgeom && tgeom.verticesIndices) this.setGeom(tgeom); + } + + setGeom(geom) + { + if (inNormFormat.get() == "X-ZY") + { + for (let i = 0; i < geom.vertexNormals.length; i += 3) + { + let t = geom.vertexNormals[i + 2]; + geom.vertexNormals[i + 2] = geom.vertexNormals[i + 1]; + geom.vertexNormals[i + 1] = -t; + } + } + + if (inVertFormat.get() == "XZ-Y") + { + for (let i = 0; i < geom.vertices.length; i += 3) + { + let t = geom.vertices[i + 2]; + geom.vertices[i + 2] = -geom.vertices[i + 1]; + geom.vertices[i + 1] = t; + } + } + + if (this.primitive == this.TRIANGLES) + { + if (!geom.vertexNormals.length || inCalcNormals.get()) geom.calculateNormals(); + + if ((!geom.biTangents || geom.biTangents.length == 0) && geom.tangents) + { + const bitan = vec3.create(); + const tan = vec3.create(); + + const tangents = geom.tangents; + geom.tangents = new Float32Array(tangents.length / 4 * 3); + geom.biTangents = new Float32Array(tangents.length / 4 * 3); + + for (let i = 0; i < tangents.length; i += 4) + { + const idx = i / 4 * 3; + + vec3.cross( + bitan, + [geom.vertexNormals[idx], geom.vertexNormals[idx + 1], geom.vertexNormals[idx + 2]], + [tangents[i], tangents[i + 1], tangents[i + 2]] + ); + + vec3.div(bitan, bitan, [tangents[i + 3], tangents[i + 3], tangents[i + 3]]); + vec3.normalize(bitan, bitan); + + geom.biTangents[idx + 0] = bitan[0]; + geom.biTangents[idx + 1] = bitan[1]; + geom.biTangents[idx + 2] = bitan[2]; + + geom.tangents[idx + 0] = tangents[i + 0]; + geom.tangents[idx + 1] = tangents[i + 1]; + geom.tangents[idx + 2] = tangents[i + 2]; + } + } + + if (geom.tangents.length === 0 || inCalcNormals.get()) geom.calcTangentsBitangents(); + } + + this.geom = geom; + + this.bounds = geom.getBounds(); + } + + render(cgl, ignoreMaterial, skinRenderer) + { + if (!this.mesh && this.geom && this.geom.verticesIndices) + { + let g = this.geom; + if (this.geom.vertices.length / 3 > 64000) + { + g = this.geom.copy(); + g.unIndex(false, true); + } + + let glprim; + if (this.primitive == this.TRIANGLES)glprim = cgl.gl.TRIANGLES; + else if (this.primitive == this.LINES)glprim = cgl.gl.LINES; + else if (this.primitive == this.LINE_STRIP)glprim = cgl.gl.LINE_STRIP; + else if (this.primitive == this.POINTS)glprim = cgl.gl.POINTS; + else + { + op.logWarn("unknown primitive type", this); + } + + this.mesh = new CGL.Mesh(cgl, g, glprim); + // this.mesh._geom = null; + } + else + { + // update morphTargets + if (this.geom && this.geom.morphTargets.length) + { + this.morphGeom = this.geom.copy(); + + this.test = time * 11.7; + + if (this.test >= this.geom.morphTargets.length - 1) this.test = 0; + + const mt = this.geom.morphTargets[Math.floor(this.test)]; + const mt2 = this.geom.morphTargets[Math.floor(this.test + 1)]; + + if (mt && mt.vertices && mt2) + { + if (this.morphGeom.vertexNormals.length != mt.vertexNormals.length) + this.morphGeom.vertexNormals = new Float32Array(mt.vertexNormals.length); + + const fract = this.test % 1; + for (let i = 0; i < this.morphGeom.vertices.length; i++) + { + this.morphGeom.vertices[i] = + this.geom.vertices[i] + + (1.0 - fract) * mt.vertices[i] + + fract * mt2.vertices[i]; + + this.morphGeom.vertexNormals[i] = + (1.0 - fract) * mt.vertexNormals[i] + + fract * mt2.vertexNormals[i]; + } + + this.mesh.updateNormals(this.morphGeom); + this.mesh.updateVertices(this.morphGeom); + } + } + + let useMat = !ignoreMaterial && this.material != -1 && gltf.shaders[this.material]; + if (skinRenderer)useMat = false; + + if (useMat) cgl.pushShader(gltf.shaders[this.material]); + + const currentShader = cgl.getShader() || {}; + const uniDiff = currentShader.uniformColorDiffuse; + + const uniPbrMetalness = currentShader.uniformPbrMetalness; + const uniPbrRoughness = currentShader.uniformPbrRoughness; + + if (!gltf.shaders[this.material] && inUseMatProps.get()) + { + if (uniDiff && this._matDiffuseColor) + { + this._matDiffuseColorOrig = [uniDiff.getValue()[0], uniDiff.getValue()[1], uniDiff.getValue()[2], uniDiff.getValue()[3]]; + uniDiff.setValue(this._matDiffuseColor); + } + + if (uniPbrMetalness) + if (this._matPbrMetalness != null) + { + this._matPbrMetalnessOrig = uniPbrMetalness.getValue(); + uniPbrMetalness.setValue(this._matPbrMetalness); + } + else + uniPbrMetalness.setValue(0); + + if (uniPbrRoughness) + if (this._matPbrRoughness != null) + { + this._matPbrRoughnessOrig = uniPbrRoughness.getValue(); + uniPbrRoughness.setValue(this._matPbrRoughness); + } + else + { + uniPbrRoughness.setValue(0); + } + } + + if (this.mesh) this.mesh.render(cgl.getShader(), ignoreMaterial); + + if (inUseMatProps.get()) + { + if (uniDiff && this._matDiffuseColor) uniDiff.setValue(this._matDiffuseColorOrig); + if (uniPbrMetalness && this._matPbrMetalnessOrig != undefined) uniPbrMetalness.setValue(this._matPbrMetalnessOrig); + if (uniPbrRoughness && this._matPbrRoughnessOrig != undefined) uniPbrRoughness.setValue(this._matPbrRoughnessOrig); + } + + if (useMat) cgl.popShader(); + } + } +}; +const gltfMeshGroup = class +{ + constructor(gltf, m) + { + this.bounds = new CABLES.CG.BoundingBox(); + this.meshes = []; + this.name = m.name; + const prims = m.primitives; + + for (let i = 0; i < prims.length; i++) + { + const mesh = new gltfMesh(this.name, prims[i], gltf, + (mesh) => + { + this.bounds.apply(mesh.bounds); + }); + + mesh.submeshIndex = i; + this.meshes.push(mesh); + } + } + + render(cgl, ignoreMat, skinRenderer, _time) + { + for (let i = 0; i < this.meshes.length; i++) + { + const useMat = gltf.shaders[this.meshes[i].material]; + + if (!ignoreMat && useMat) cgl.pushShader(gltf.shaders[this.meshes[i].material]); + // console.log(gltf.shaders[this.meshes[i].material],this.meshes[i].material) + if (skinRenderer)skinRenderer.renderStart(cgl, _time); + + this.meshes[i].render(cgl, ignoreMat, skinRenderer, _time); + if (skinRenderer)skinRenderer.renderFinish(cgl); + if (!ignoreMat && useMat) cgl.popShader(); + } + } +}; +const gltfNode = class +{ + constructor(node, gltf) + { + this.isChild = node.isChild || false; + this.name = node.name; + if (node.hasOwnProperty("camera")) this.camera = node.camera; + this.hidden = false; + this.mat = mat4.create(); + this._animMat = mat4.create(); + this._tempMat = mat4.create(); + this._tempQuat = quat.create(); + this._tempRotmat = mat4.create(); + this.mesh = null; + this.children = []; + this._node = node; + this._gltf = gltf; + this.absMat = mat4.create(); + this.addTranslate = null; + this._tempAnimScale = null; + this.addMulMat = null; + this.updateMatrix(); + this._animActions = {}; + this.skinRenderer = null; + this.copies = []; + } + + get skin() + { + if (this._node.hasOwnProperty("skin")) return this._node.skin; + else return -1; + } + + copy() + { + this.isCopy = true; + const n = new gltfNode(this._node, this._gltf); + n.copyOf = this; + + n._animActions = this._animActions; + n.children = this.children; + n.skinRenderer = new GltfSkin(n); + + this.updateMatrix(); + return n; + } + + hasSkin() + { + if (this._node.hasOwnProperty("skin")) return this._gltf.json.skins[this._node.skin].name || "unknown"; + return false; + } + + initSkin() + { + if (this.skin > -1) + { + this.skinRenderer = new GltfSkin(this); + } + } + + updateMatrix() + { + mat4.identity(this.mat); + if (this._node.translation) mat4.translate(this.mat, this.mat, this._node.translation); + + if (this._node.rotation) + { + const rotmat = mat4.create(); + this._rot = this._node.rotation; + + mat4.fromQuat(rotmat, this._node.rotation); + mat4.mul(this.mat, this.mat, rotmat); + } + + if (this._node.scale) + { + this._scale = this._node.scale; + mat4.scale(this.mat, this.mat, this._scale); + } + + if (this._node.hasOwnProperty("mesh")) + { + this.mesh = this._gltf.meshes[this._node.mesh]; + if (this.isCopy) + { + console.log(this.mesh); + } + } + + if (this._node.children) + { + for (let i = 0; i < this._node.children.length; i++) + { + this._gltf.json.nodes[i].isChild = true; + if (this._gltf.nodes[this._node.children[i]]) this._gltf.nodes[this._node.children[i]].isChild = true; + this.children.push(this._node.children[i]); + } + } + } + + unHide() + { + this.hidden = false; + for (let i = 0; i < this.children.length; i++) + if (this.children[i].unHide) this.children[i].unHide(); + } + + calcBounds(gltf, mat, bounds) + { + const localMat = mat4.create(); + + if (mat) mat4.copy(localMat, mat); + if (this.mat) mat4.mul(localMat, localMat, this.mat); + + if (this.mesh) + { + const bb = this.mesh.bounds.copy(); + bb.mulMat4(localMat); + bounds.apply(bb); + + if (bounds.changed) + { + boundingPoints.push( + bb._min[0] || 0, bb._min[1] || 0, bb._min[2] || 0, + bb._max[0] || 0, bb._max[1] || 0, bb._max[2] || 0); + } + } + + for (let i = 0; i < this.children.length; i++) + { + if (gltf.nodes[this.children[i]] && gltf.nodes[this.children[i]].calcBounds) + { + const b = gltf.nodes[this.children[i]].calcBounds(gltf, localMat, bounds); + + bounds.apply(b); + } + } + + if (bounds.changed) return bounds; + else return null; + } + + setAnimAction(name) + { + // console.log("setAnimAction:", name); + if (!name) return; + + this._currentAnimaction = name; + + if (name && !this._animActions[name]) + { + // console.log("no action found:", name,this._animActions); + return null; + } + + // else console.log("YES action found:", name); + // console.log(this._animActions); + + for (let path in this._animActions[name]) + { + if (path == "translation") this._animTrans = this._animActions[name][path]; + else if (path == "rotation") this._animRot = this._animActions[name][path]; + else if (path == "scale") this._animScale = this._animActions[name][path]; + else console.warn("unknown anim path", path, this._animActions[name][path]); + } + } + + setAnim(path, name, anims) + { + if (!path || !name || !anims) return; + + // console.log("setanim", this._node.name, path, name, anims); + + this._animActions[name] = this._animActions[name] || {}; + + // console.log(this._animActions); + // debugger; + + // for (let i = 0; i < this.copies.length; i++) this.copies[i]._animActions = this._animActions; + + if (this._animActions[name][path]) op.warn("animation action path already exists", name, path, this._animActions[name][path]); + + this._animActions[name][path] = anims; + + if (path == "translation") this._animTrans = anims; + else if (path == "rotation") this._animRot = anims; + else if (path == "scale") this._animScale = anims; + else console.warn("unknown anim path", path, anims); + } + + modelMatLocal() + { + return this._animMat || this.mat; + } + + modelMatAbs() + { + return this.absMat; + } + + transform(cgl, _time) + { + if (!_time && _time != 0)_time = time; + + this._lastTimeTrans = _time; + + // console.log(this._rot) + + gltfTransforms++; + + if (!this._animTrans && !this._animRot && !this._animScale) + { + mat4.mul(cgl.mMatrix, cgl.mMatrix, this.mat); + this._animMat = null; + } + else + { + this._animMat = this._animMat || mat4.create(); + mat4.identity(this._animMat); + + const playAnims = true; + + if (playAnims && this._animTrans) + { + mat4.translate(this._animMat, this._animMat, [ + this._animTrans[0].getValue(_time), + this._animTrans[1].getValue(_time), + this._animTrans[2].getValue(_time)]); + } + else + if (this._node.translation) mat4.translate(this._animMat, this._animMat, this._node.translation); + + if (playAnims && this._animRot) + { + if (this._animRot[0].defaultEasing == CABLES.EASING_LINEAR) CABLES.TL.Anim.slerpQuaternion(_time, this._tempQuat, this._animRot[0], this._animRot[1], this._animRot[2], this._animRot[3]); + else if (this._animRot[0].defaultEasing == CABLES.EASING_ABSOLUTE) + { + this._tempQuat[0] = this._animRot[0].getValue(_time); + this._tempQuat[1] = this._animRot[1].getValue(_time); + this._tempQuat[2] = this._animRot[2].getValue(_time); + this._tempQuat[3] = this._animRot[3].getValue(_time); + } + else if (this._animRot[0].defaultEasing == CABLES.EASING_CUBICSPLINE) + { + CABLES.TL.Anim.slerpQuaternion(_time, this._tempQuat, this._animRot[0], this._animRot[1], this._animRot[2], this._animRot[3]); + } + + mat4.fromQuat(this._tempMat, this._tempQuat); + mat4.mul(this._animMat, this._animMat, this._tempMat); + } + else if (this._rot) + { + mat4.fromQuat(this._tempRotmat, this._rot); + mat4.mul(this._animMat, this._animMat, this._tempRotmat); + } + + if (playAnims && this._animScale) + { + if (!this._tempAnimScale) this._tempAnimScale = [1, 1, 1]; + this._tempAnimScale[0] = this._animScale[0].getValue(_time); + this._tempAnimScale[1] = this._animScale[1].getValue(_time); + this._tempAnimScale[2] = this._animScale[2].getValue(_time); + mat4.scale(this._animMat, this._animMat, this._tempAnimScale); + } + else if (this._scale) mat4.scale(this._animMat, this._animMat, this._scale); + + mat4.mul(cgl.mMatrix, cgl.mMatrix, this._animMat); + } + + if (this.addTranslate) mat4.translate(cgl.mMatrix, cgl.mMatrix, this.addTranslate); + + if (this.addMulMat) mat4.mul(cgl.mMatrix, cgl.mMatrix, this.addMulMat); + + mat4.copy(this.absMat, cgl.mMatrix); + } + + render(cgl, dontTransform, dontDrawMesh, ignoreMaterial, ignoreChilds, drawHidden, _time) + { + if (!dontTransform) cgl.pushModelMatrix(); + + if (_time === undefined) _time = gltf.time; + + if (!dontTransform || this.skinRenderer) this.transform(cgl, _time); + + if (this.hidden && !drawHidden) + { + } + else + { + if (this.skinRenderer) + { + this.skinRenderer.time = _time; + if (!dontDrawMesh) + this.mesh.render(cgl, ignoreMaterial, this.skinRenderer, _time); + } + else + { + if (this.mesh && !dontDrawMesh) + this.mesh.render(cgl, ignoreMaterial, null, _time); + } + } + + if (!ignoreChilds && !this.hidden) + for (let i = 0; i < this.children.length; i++) + if (gltf.nodes[this.children[i]]) + gltf.nodes[this.children[i]].render(cgl, dontTransform, dontDrawMesh, ignoreMaterial, ignoreChilds, drawHidden, _time); + + if (!dontTransform)cgl.popModelMatrix(); + } +}; +let tab = null; + +function closeTab() +{ + if (tab)gui.mainTabs.closeTab(tab.id); + tab = null; +} + +function formatVec(arr) +{ + const nums = []; + for (let i = 0; i < arr.length; i++) + { + nums.push(Math.round(arr[i] * 1000) / 1000); + } + + return nums.join(","); +} + +function printNode(html, node, level) +{ + if (!gltf) return; + + html += ""; + + let ident = ""; + let identSpace = ""; + + for (let i = 1; i < level; i++) + { + identSpace += "   "; + let identClass = "identBg"; + if (i == 1)identClass = "identBgLevel0"; + ident += "
"; + } + let id = CABLES.uuid(); + html += ident; + html += ""; + // html+='
'; + + if (node.mesh && node.mesh.meshes.length)html += " "; + else html += "  "; + + html += node.name + ""; + + if (node.mesh) + { + html += ""; + for (let i = 0; i < node.mesh.meshes.length; i++) + { + if (i > 0)html += ", "; + html += node.mesh.meshes[i].name; + } + + html += ""; + + html += ""; + html += node.hasSkin() || "-"; + html += ""; + + html += ""; + let countMats = 0; + for (let i = 0; i < node.mesh.meshes.length; i++) + { + if (countMats > 0)html += ", "; + if (gltf.json.materials && node.mesh.meshes[i].hasOwnProperty("material")) + { + if (gltf.json.materials[node.mesh.meshes[i].material]) + { + html += gltf.json.materials[node.mesh.meshes[i].material].name; + countMats++; + } + } + } + if (countMats == 0)html += "none"; + html += ""; + } + else + { + html += "---"; + } + + html += ""; + + if (node._node.translation || node._node.rotation || node._node.scale) + { + let info = ""; + + if (node._node.translation)info += "Translate: `" + formatVec(node._node.translation) + "` || "; + if (node._node.rotation)info += "Rotation: `" + formatVec(node._node.rotation) + "` || "; + if (node._node.scale)info += "Scale: `" + formatVec(node._node.scale) + "` || "; + + html += "  "; + } + + if (node._animRot || node._animScale || node._animTrans) + { + let info = "Animated: "; + if (node._animRot) info += "Rot "; + if (node._animScale) info += "Scale "; + if (node._animTrans) info += "Trans "; + + html += " "; + } + + if (!node._node.translation && !node._node.rotation && !node._node.scale && !node._animRot && !node._animScale && !node._animTrans) html += "-"; + + html += ""; + + html += ""; + let hideclass = ""; + if (node.hidden)hideclass = "node-hidden"; + + // html+=''; + html += "Transform"; + html += " Hierarchy"; + html += " Node"; + + if (node.hasSkin()) + html += " Skin"; + + html += ""; + html += " "; + html += ""; + + html += ""; + + if (node.children) + { + for (let i = 0; i < node.children.length; i++) + html = printNode(html, gltf.nodes[node.children[i]], level + 1); + } + + return html; +} + +function printMaterial(mat, idx) +{ + let html = ""; + html += " " + idx + ""; + html += " " + mat.name + ""; + // html+=' Assign'; + + html += " "; + + const info = JSON.stringify(mat, null, 4).replaceAll("\"", "").replaceAll("\n", "
"); + + html += "" + info + "', 'title': '" + mat.name + "' });\"> "; + + if (mat.pbrMetallicRoughness && mat.pbrMetallicRoughness.baseColorFactor) + { + let rgb = ""; + rgb += "" + Math.round(mat.pbrMetallicRoughness.baseColorFactor[0] * 255); + rgb += "," + Math.round(mat.pbrMetallicRoughness.baseColorFactor[1] * 255); + rgb += "," + Math.round(mat.pbrMetallicRoughness.baseColorFactor[2] * 255); + + html += "
 "; + } + html += " " + (gltf.shaders[idx] ? "-" : "Assign") + ""; + html += ""; + + html += ""; + return html; +} + +function printInfo() +{ + if (!gltf) return; + + const startTime = performance.now(); + const sizes = {}; + let html = "
"; + + html += "generator:" + gltf.json.asset.generator; + + let numNodes = 0; + if (gltf.json.nodes)numNodes = gltf.json.nodes.length; + html += "
Nodes (" + numNodes + ")
"; + + html += ""; + + html += ""; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += ""; + + for (let i = 0; i < gltf.nodes.length; i++) + { + if (!gltf.nodes[i].isChild) + html = printNode(html, gltf.nodes[i], 1); + } + html += "
NameMeshSkinMaterialTransformExpose
"; + + // / ////////////////// + + let numMaterials = 0; + if (gltf.json.materials)numMaterials = gltf.json.materials.length; + html += "
Materials (" + numMaterials + ")
"; + + if (!gltf.json.materials || gltf.json.materials.length == 0) + { + } + else + { + html += ""; + html += ""; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += ""; + for (let i = 0; i < gltf.json.materials.length; i++) + { + html += printMaterial(gltf.json.materials[i], i); + } + html += "
IndexNameColorFunction
"; + } + + // / /////////////////////// + + html += "
Meshes (" + gltf.json.meshes.length + ")
"; + + html += ""; + html += ""; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += ""; + + let sizeBufferViews = []; + sizes.meshes = 0; + + for (let i = 0; i < gltf.json.meshes.length; i++) + { + html += ""; + html += ""; + + html += ""; + + // ------- + + html += ""; + + html += ""; + + html += ""; + html += ""; + + for (let j = 0; j < gltf.json.meshes[i].primitives.length; j++) + { + const accessor = gltf.json.accessors[gltf.json.meshes[i].primitives[j].indices]; + if (accessor) + { + let bufView = accessor.bufferView; + + if (sizeBufferViews.indexOf(bufView) == -1) + { + sizeBufferViews.push(bufView); + if (gltf.json.bufferViews[bufView])sizes.meshes += gltf.json.bufferViews[bufView].byteLength; + } + } + + for (let k in gltf.json.meshes[i].primitives[j].attributes) + { + const attr = gltf.json.meshes[i].primitives[j].attributes[k]; + const bufView2 = gltf.json.accessors[attr].bufferView; + + if (sizeBufferViews.indexOf(bufView2) == -1) + { + sizeBufferViews.push(bufView2); + if (gltf.json.bufferViews[bufView2])sizes.meshes += gltf.json.bufferViews[bufView2].byteLength; + } + } + } + } + html += "
NameNodeMaterialVerticesAttributes
" + gltf.json.meshes[i].name + ""; + let count = 0; + let nodename = ""; + for (var j = 0; j < gltf.json.nodes.length; j++) + { + if (gltf.json.nodes[j].mesh == i) + { + count++; + if (count == 1) + { + nodename = gltf.json.nodes[j].name; + } + } + } + if (count > 1) html += (count) + " nodes (" + nodename + " ...)"; + else html += nodename; + html += ""; + for (var j = 0; j < gltf.json.meshes[i].primitives.length; j++) + { + if (gltf.json.meshes[i].primitives[j].hasOwnProperty("material")) + { + if (gltf.json.materials[gltf.json.meshes[i]]) + { + html += gltf.json.materials[gltf.json.meshes[i].primitives[j].material].name + " "; + } + } + else html += "None"; + } + html += ""; + let numVerts = 0; + for (var j = 0; j < gltf.json.meshes[i].primitives.length; j++) + { + if (gltf.json.meshes[i].primitives[j].attributes.POSITION != undefined) + { + let v = parseInt(gltf.json.accessors[gltf.json.meshes[i].primitives[j].attributes.POSITION].count); + numVerts += v; + html += "" + v + "
"; + } + else html += "-
"; + } + + if (gltf.json.meshes[i].primitives.length > 0) + html += "=" + numVerts; + html += "
"; + for (let j = 0; j < gltf.json.meshes[i].primitives.length; j++) + { + html += Object.keys(gltf.json.meshes[i].primitives[j].attributes); + html += " Geometry"; + html += "
"; + } + html += "
"; + + // / ////////////////////////////////// + + let numAnims = 0; + if (gltf.json.animations)numAnims = gltf.json.animations.length; + html += "
Animations (" + numAnims + ")
"; + + if (gltf.json.animations) + { + html += ""; + html += ""; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += ""; + + sizes.animations = 0; + + for (let i = 0; i < gltf.json.animations.length; i++) + { + for (let j = 0; j < gltf.json.animations[i].samplers.length; j++) + { + let bufView = gltf.json.accessors[gltf.json.animations[i].samplers[j].input].bufferView; + if (sizeBufferViews.indexOf(bufView) == -1) + { + sizeBufferViews.push(bufView); + sizes.animations += gltf.json.bufferViews[bufView].byteLength; + } + + bufView = gltf.json.accessors[gltf.json.animations[i].samplers[j].output].bufferView; + if (sizeBufferViews.indexOf(bufView) == -1) + { + sizeBufferViews.push(bufView); + sizes.animations += gltf.json.bufferViews[bufView].byteLength; + } + } + + for (let j = 0; j < gltf.json.animations[i].channels.length; j++) + { + html += ""; + html += " "; + + html += " "; + html += " "; + + const smplidx = gltf.json.animations[i].channels[j].sampler; + const smplr = gltf.json.animations[i].samplers[smplidx]; + + html += " "; + + html += " "; + + html += ""; + } + } + html += "
NameTarget nodePathInterpolationKeys
Anim " + i + ": " + gltf.json.animations[i].name + "" + gltf.nodes[gltf.json.animations[i].channels[j].target.node].name + ""; + html += gltf.json.animations[i].channels[j].target.path + " "; + html += " " + smplr.interpolation + "" + gltf.json.accessors[smplr.output].count; + + html += "  "; + + html += "
"; + } + else + { + + } + + // / /////////////////// + + let numImages = 0; + if (gltf.json.images)numImages = gltf.json.images.length; + html += "
Images (" + numImages + ")
"; + + if (gltf.json.images) + { + html += ""; + + html += ""; + html += " "; + html += " "; + html += " "; + + html += ""; + + sizes.images = 0; + + for (let i = 0; i < gltf.json.images.length; i++) + { + if (gltf.json.images[i].bufferView) + sizes.images += gltf.json.bufferViews[gltf.json.images[i].bufferView].byteLength; + + html += ""; + html += ""; + html += ""; + html += ""; + + html += ""; + } + html += "
nametypefunc
" + gltf.json.images[i].name + "" + gltf.json.images[i].mimeType + ""; + + let name = gltf.json.images[i].name; + if (name === undefined)name = gltf.json.images[i].bufferView; + + html += "Expose"; + html += "
"; + } + + // / /////////////////////// + + let numCameras = 0; + if (gltf.json.cameras)numCameras = gltf.json.cameras.length; + html += "
Cameras (" + numCameras + ")
"; + + if (gltf.json.cameras) + { + html += ""; + + html += ""; + html += " "; + html += " "; + html += " "; + html += ""; + + for (let i = 0; i < gltf.json.cameras.length; i++) + { + html += ""; + html += ""; + html += ""; + html += ""; + + html += ""; + } + html += "
nametypeinfo
" + gltf.json.cameras[i].name + "" + gltf.json.cameras[i].type + ""; + + if (gltf.json.cameras[i].perspective) + { + html += "yfov: " + Math.round(gltf.json.cameras[i].perspective.yfov * 100) / 100; + html += ", "; + html += "zfar: " + Math.round(gltf.json.cameras[i].perspective.zfar * 100) / 100; + html += ", "; + html += "znear: " + Math.round(gltf.json.cameras[i].perspective.znear * 100) / 100; + } + html += "
"; + } + + // / //////////////////////////////////// + + let numSkins = 0; + if (gltf.json.skins)numSkins = gltf.json.skins.length; + html += "
Skins (" + numSkins + ")
"; + + if (gltf.json.skins) + { + // html += "

Skins (" + gltf.json.skins.length + ")

"; + html += ""; + + html += ""; + html += " "; + html += " "; + html += " "; + html += ""; + + for (let i = 0; i < gltf.json.skins.length; i++) + { + html += ""; + html += ""; + html += ""; + html += ""; + html += ""; + html += ""; + } + html += "
nametotal joints
" + gltf.json.skins[i].name + "" + "" + gltf.json.skins[i].joints.length + ""; + html += "
"; + } + + // / ////////////////////////// + + let sizeBin = 0; + if (gltf.json.buffers) + sizeBin = gltf.json.buffers[0].byteLength; + + html += "
File Size Allocation (" + Math.round(sizeBin / 1024) + "k )
"; + + html += ""; + html += ""; + html += " "; + html += " "; + html += " "; + html += ""; + let sizeUnknown = sizeBin; + for (let i in sizes) + { + // html+=i+':'+Math.round(sizes[i]/1024); + html += ""; + html += ""; + html += ""; + html += ""; + html += ""; + sizeUnknown -= sizes[i]; + } + + if (sizeUnknown != 0) + { + html += ""; + html += ""; + html += ""; + html += ""; + html += ""; + } + + html += "
namesize%
" + i + "" + readableSize(sizes[i]) + " " + Math.round(sizes[i] / sizeBin * 100) + "%
unknown" + readableSize(sizeUnknown) + " " + Math.round(sizeUnknown / sizeBin * 100) + "%
"; + html += "
"; + + tab = new CABLES.UI.Tab("GLTF", { "icon": "cube", "infotext": "tab_gltf", "padding": true, "singleton": true }); + gui.mainTabs.addTab(tab, true); + + tab.addEventListener("onClose", closeTab); + tab.html(html); + + CABLES.UI.Collapsable.setup(ele.byId("groupNodes"), ele.byId("sectionNodes"), false); + CABLES.UI.Collapsable.setup(ele.byId("groupMaterials"), ele.byId("materialtable"), true); + CABLES.UI.Collapsable.setup(ele.byId("groupAnims"), ele.byId("sectionAnim"), true); + CABLES.UI.Collapsable.setup(ele.byId("groupMeshes"), ele.byId("meshestable"), true); + CABLES.UI.Collapsable.setup(ele.byId("groupCameras"), ele.byId("sectionCameras"), true); + CABLES.UI.Collapsable.setup(ele.byId("groupImages"), ele.byId("sectionImages"), true); + CABLES.UI.Collapsable.setup(ele.byId("groupSkins"), ele.byId("sectionSkins"), true); + CABLES.UI.Collapsable.setup(ele.byId("groupBinary"), ele.byId("sectionBinary"), true); + + gui.maintabPanel.show(true); +} + +function readableSize(n) +{ + if (n > 1024) return Math.round(n / 1024) + " kb"; + if (n > 1024 * 500) return Math.round(n / 1024) + " mb"; + else return n + " bytes"; +} +const GltfSkin = class +{ + constructor(node) + { + this._mod = null; + this._node = node; + this._lastTime = 0; + this._matArr = []; + this._m = mat4.create(); + this._invBindMatrix = mat4.create(); + this.identity = true; + } + + renderFinish(cgl) + { + cgl.popModelMatrix(); + this._mod.unbind(); + } + + renderStart(cgl, time) + { + if (!this._mod) + { + this._mod = new CGL.ShaderModifier(cgl, op.name + this._node.name); + + this._mod.addModule({ + "priority": -2, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": attachments.skin_head_vert || "", + "srcBodyVert": attachments.skin_vert || "" + }); + + this._mod.addUniformVert("m4[]", "MOD_boneMats", []);// bohnenmatze + const tr = vec3.create(); + } + + const skinIdx = this._node.skin; + const arrLength = gltf.json.skins[skinIdx].joints.length * 16; + + // if (this._lastTime != time || !time) + { + // this._lastTime=inTime.get(); + if (this._matArr.length != arrLength) this._matArr.length = arrLength; + + for (let i = 0; i < gltf.json.skins[skinIdx].joints.length; i++) + { + const i16 = i * 16; + const jointIdx = gltf.json.skins[skinIdx].joints[i]; + const nodeJoint = gltf.nodes[jointIdx]; + + for (let j = 0; j < 16; j++) + this._invBindMatrix[j] = gltf.accBuffers[gltf.json.skins[skinIdx].inverseBindMatrices][i16 + j]; + + mat4.mul(this._m, nodeJoint.modelMatAbs(), this._invBindMatrix); + + for (let j = 0; j < this._m.length; j++) this._matArr[i16 + j] = this._m[j]; + } + + this._mod.setUniformValue("MOD_boneMats", this._matArr); + this._lastTime = time; + } + + this._mod.define("SKIN_NUM_BONES", gltf.json.skins[skinIdx].joints.length); + this._mod.bind(); + + // draw mesh... + cgl.pushModelMatrix(); + if (this.identity)mat4.identity(cgl.mMatrix); + } +}; +// https://raw.githubusercontent.com/KhronosGroup/glTF/master/specification/2.0/figures/gltfOverview-2.0.0b.png + +const + inExec = op.inTrigger("Render"), + dataPort = op.inString("data"), + inFile = op.inUrl("glb File", [".glb"]), + inRender = op.inBool("Draw", true), + inCamera = op.inDropDown("Camera", ["None"], "None"), + inAnimation = op.inString("Animation", ""), + inShow = op.inTriggerButton("Show Structure"), + inCenter = op.inSwitch("Center", ["None", "XYZ", "XZ"], "XYZ"), + inRescale = op.inBool("Rescale", true), + inRescaleSize = op.inFloat("Rescale Size", 2.5), + + inTime = op.inFloat("Time"), + inTimeLine = op.inBool("Sync to timeline", false), + inLoop = op.inBool("Loop", true), + + inNormFormat = op.inSwitch("Normals Format", ["XYZ", "X-ZY"], "XYZ"), + inVertFormat = op.inSwitch("Vertices Format", ["XYZ", "XZ-Y"], "XYZ"), + inCalcNormals = op.inBool("Calc Normals", false), + + inMaterials = op.inObject("Materials"), + inHideNodes = op.inArray("Hide Nodes"), + inUseMatProps = op.inBool("Use Material Properties", false), + inActive = op.inBool("Active", true), + + nextBefore = op.outTrigger("Render Before"), + next = op.outTrigger("Next"), + outGenerator = op.outString("Generator"), + outVersion = op.outNumber("GLTF Version"), + outExtensions = op.outArray("GLTF Extensions Used"), + outAnimLength = op.outNumber("Anim Length", 0), + outAnimTime = op.outNumber("Anim Time", 0), + outJson = op.outObject("Json"), + outAnims = op.outArray("Anims"), + outPoints = op.outArray("BoundingPoints"), + outBounds = op.outObject("Bounds"), + outAnimFinished = op.outTrigger("Finished"), + outLoading = op.outBool("Loading"); + +op.setPortGroup("Timing", [inTime, inTimeLine, inLoop]); + +const le = true; // little endian +const cgl = op.patch.cgl; +inFile.onChange = + inVertFormat.onChange = + inCalcNormals.onChange = + inNormFormat.onChange = reloadSoon; + +let gltfTransforms = 0; +let finishedLoading = false; +let cam = null; +let boundingPoints = []; +let gltf = null; +let maxTime = 0; +let time = 0; +let needsMatUpdate = true; +let timedLoader = null; +let loadingId = null; +let data = null; +const scale = vec3.create(); +let lastTime = 0; +let doCenter = false; + +const boundsCenter = vec3.create(); + +inShow.onTriggered = printInfo; +dataPort.setUiAttribs({ "hideParam": true, "hidePort": true }); +dataPort.onChange = loadData; +inHideNodes.onChange = hideNodesFromData; +inAnimation.onChange = updateAnimation; + +op.setPortGroup("Transform", [inRescale, inRescaleSize, inCenter]); + +inCenter.onChange = updateCenter; + +function updateCamera() +{ + const arr = ["None"]; + if (gltf) + { + for (let i = 0; i < gltf.nodes.length; i++) + { + if (gltf.nodes[i].camera >= 0) + { + arr.push(gltf.nodes[i].name); + } + } + } + inCamera.uiAttribs.values = arr; +} + +function updateCenter() +{ + doCenter = inCenter.get() != "None"; + + if (gltf && gltf.bounds) + { + boundsCenter.set(gltf.bounds.center); + boundsCenter[0] = -boundsCenter[0]; + boundsCenter[1] = -boundsCenter[1]; + boundsCenter[2] = -boundsCenter[2]; + if (inCenter.get() == "XZ") boundsCenter[1] = -gltf.bounds.minY; + } +} + +inRescale.onChange = function () +{ + inRescaleSize.setUiAttribs({ "greyout": !inRescale.get() }); +}; + +inMaterials.onChange = function () +{ + needsMatUpdate = true; +}; + +op.onDelete = function () +{ + closeTab(); +}; + +inTimeLine.onChange = function () +{ + inTime.setUiAttribs({ "greyout": inTimeLine.get() }); +}; + +inCamera.onChange = setCam; + +function setCam() +{ + cam = null; + if (!gltf) return; + + for (let i = 0; i < gltf.nodes.length; i++) + { + if (gltf.nodes[i].name == inCamera.get())cam = new gltfCamera(gltf, gltf.nodes[i]); + } +} + +inExec.onTriggered = function () +{ + if (!finishedLoading) return; + if (!inActive.get()) return; + + gltfTransforms = 0; + if (inTimeLine.get()) time = op.patch.timer.getTime(); + else time = Math.max(0, inTime.get()); + + if (inLoop.get()) + { + time %= maxTime; + if (time < lastTime)outAnimFinished.trigger(); + } + else + { + if (maxTime > 0 && time >= maxTime)outAnimFinished.trigger(); + } + lastTime = time; + + cgl.pushModelMatrix(); + + outAnimTime.set(time || 0); + + if (finishedLoading && gltf && gltf.bounds) + { + if (inRescale.get()) + { + let sc = inRescaleSize.get() / gltf.bounds.maxAxis; + gltf.scale = sc; + vec3.set(scale, sc, sc, sc); + mat4.scale(cgl.mMatrix, cgl.mMatrix, scale); + } + if (doCenter) + { + mat4.translate(cgl.mMatrix, cgl.mMatrix, boundsCenter); + } + } + + let oldScene = cgl.frameStore.currentScene || null; + cgl.frameStore.currentScene = gltf; + + nextBefore.trigger(); + + if (finishedLoading) + { + if (needsMatUpdate) updateMaterials(); + + if (cam) cam.start(time); + + if (gltf) + { + gltf.time = time; + + { + if (gltf.bounds && cgl.shouldDrawHelpers(op)) + { + if (CABLES.UI.renderHelper)cgl.pushShader(CABLES.GL_MARKER.getDefaultShader(cgl)); + else cgl.pushShader(CABLES.GL_MARKER.getSelectedShader(cgl)); + gltf.bounds.render(cgl); + cgl.popShader(); + } + + // if (!gltf.renderMMatrix)gltf.renderMMatrix = mat4.create(); + // cgl.pushModelMatrix(); + // mat4.copy(gltf.renderMMatrix, cgl.mMatrix); + // mat4.identity(cgl.mMatrix); + + if (inRender.get()) + { + for (let i = 0; i < gltf.nodes.length; i++) + if (!gltf.nodes[i].isChild) + gltf.nodes[i].render(cgl); + } + else + { + for (let i = 0; i < gltf.nodes.length; i++) + if (!gltf.nodes[i].isChild) + gltf.nodes[i].render(cgl, false, true); + // render(cgl, dontTransform, dontDrawMesh, ignoreMaterial, ignoreChilds, drawHidden, _time) + } + + // cgl.popModelMatrix(); + } + } + } + + next.trigger(); + cgl.frameStore.currentScene = oldScene; + + cgl.popModelMatrix(); + + if (cam)cam.end(); +}; + +function finishLoading() +{ + if (!gltf) + { + op.setUiError("nogltf", "gltf not found"); + return; + } + op.setUiError("nogltf", null); + if (gltf.loadingMeshes > 0) + { + // op.log("waiting for async meshes..."); + setTimeout(finishLoading, 100); + return; + } + + gltf.timing.push("finishLoading()", Math.round((performance.now() - gltf.startTime))); + + needsMatUpdate = true; + // op.refreshParams(); + outAnimLength.set(maxTime); + + gltf.bounds = new CABLES.CG.BoundingBox(); + // gltf.bounds.applyPos(0, 0, 0); + + if (!gltf)op.setUiError("urlerror", "could not load gltf:
\"" + inFile.get() + "\"", 2); + else op.setUiError("urlerror", null); + + gltf.timing.push("start calc bounds", Math.round((performance.now() - gltf.startTime))); + + for (let i = 0; i < gltf.nodes.length; i++) + { + const node = gltf.nodes[i]; + node.updateMatrix(); + if (!node.isChild) node.calcBounds(gltf, null, gltf.bounds); + } + + if (gltf.bounds)outBounds.set(gltf.bounds); + + gltf.timing.push("calced bounds", Math.round((performance.now() - gltf.startTime))); + + hideNodesFromData(); + + gltf.timing.push("hideNodesFromData", Math.round((performance.now() - gltf.startTime))); + + if (tab)printInfo(); + + gltf.timing.push("printinfo", Math.round((performance.now() - gltf.startTime))); + + updateCamera(); + setCam(); + outPoints.set(boundingPoints); + + if (gltf) + { + if (inFile.get() && !inFile.get().startsWith("data:")) + { + op.setUiAttrib({ "extendTitle": CABLES.basename(inFile.get()) }); + } + + gltf.loaded = Date.now(); + // if (gltf.bounds)outBounds.set(gltf.bounds); + } + + if (gltf) + { + for (let i = 0; i < gltf.nodes.length; i++) + { + if (!gltf.nodes[i].isChild) + { + gltf.nodes[i].render(cgl, false, true, true, false, true, 0); + } + } + + for (let i = 0; i < gltf.nodes.length; i++) + { + const node = gltf.nodes[i]; + node.children = uniqueArray(node.children); // stupid fix why are there too many children ?! + } + } + + updateCenter(); + updateAnimation(); + + outLoading.set(false); + + cgl.patch.loading.finished(loadingId); + loadingId = null; + + // if (gltf.chunks.length > 1) gltf.chunks[1] = null; + // if (gltf.chunks.length > 2) gltf.chunks[2] = null; + + op.setUiAttrib({ "accBuffersDelete": CABLES.basename(inFile.get()) }); + + if (gltf.accBuffersDelete) + { + for (let i = 0; i < gltf.accBuffersDelete.length; i++) + { + gltf.accBuffers[gltf.accBuffersDelete[i]] = null; + } + } + + finishedLoading = true; +} + +function loadBin(addCacheBuster) +{ + if (!inActive.get()) return; + + if (!loadingId)loadingId = cgl.patch.loading.start("gltfScene", inFile.get()); + + let fileToLoad = inFile.get(); + let url = op.patch.getFilePath(String(inFile.get())); + if (inFile.get() && !inFile.get().startsWith("data:")) + { + if (addCacheBuster === true)url += "?rnd=" + CABLES.generateUUID(); + } + finishedLoading = false; + outLoading.set(true); + fetch(url) + .then((res) => { return res.arrayBuffer(); }) + .then((arrayBuffer) => + { + if (inFile.get() != fileToLoad) + { + cgl.patch.loading.finished(loadingId); + loadingId = null; + return; + } + + boundingPoints = []; + + maxTime = 0; + gltf = parseGltf(arrayBuffer); + + finishLoading(); + }); + closeTab(); + + const oReq = new XMLHttpRequest(); + oReq.open("GET", url, true); + oReq.responseType = "arraybuffer"; + + cgl.patch.loading.addAssetLoadingTask(() => + { + + }); +} + +// op.onFileChanged = function (fn) +// { +// gltf.accBuffersDelete[i]; +// if (fn && fn.length > 3 && inFile.get() && inFile.get().indexOf(fn) > -1) reloadSoon(true); +// }; + +op.onFileChanged = function (fn) +{ + if (inFile.get() && inFile.get().indexOf(fn) > -1) + { + reloadSoon(true); + } +}; + +inActive.onChange = () => +{ + if (inActive.get()) reloadSoon(); + + if (!inActive.get()) + { + gltf = null; + } +}; + +function reloadSoon(nocache) +{ + clearTimeout(timedLoader); + timedLoader = setTimeout(function () { loadBin(nocache); }, 30); +} + +function updateMaterials() +{ + if (!gltf) return; + + gltf.shaders = {}; + + if (inMaterials.links.length == 1 && inMaterials.get()) + { + // just accept a associative object with shader in it + const op = inMaterials.links[0].portOut.parent; + + const portShader = op.getPort("Shader"); + const portName = op.getPort("Material Name"); + + if (!portShader && !portName) + { + const inMats = inMaterials.get(); + for (let matname in inMats) + { + if (inMats[matname] && gltf.json.materials) + for (let i = 0; i < gltf.json.materials.length; i++) + { + if (gltf.json.materials[i].name == matname) + { + if (gltf.shaders[i]) + { + op.warn("double material assignment:", name); + } + gltf.shaders[i] = inMats[matname]; + } + } + } + } + } + + if (inMaterials.get()) + { + for (let j = 0; j < inMaterials.links.length; j++) + { + const op = inMaterials.links[j].portOut.parent; + const portShader = op.getPort("Shader"); + const portName = op.getPort("Material Name"); + + if (portShader && portName && portShader.get()) + { + const name = portName.get(); + if (gltf.json.materials) + for (let i = 0; i < gltf.json.materials.length; i++) + if (gltf.json.materials[i].name == name) + { + if (gltf.shaders[i]) + { + op.warn("double material assignment:", name); + } + gltf.shaders[i] = portShader.get(); + } + } + } + } + needsMatUpdate = false; + if (tab)printInfo(); +} + +function hideNodesFromArray() +{ + const hideArr = inHideNodes.get(); + + if (!gltf || !data || !data.hiddenNodes) return; + if (!hideArr) + { + return; + } + + for (let i = 0; i < hideArr.length; i++) + { + const n = gltf.getNode(hideArr[i]); + if (n)n.hidden = true; + } +} + +function hideNodesFromData() +{ + if (!data)loadData(); + if (!gltf) return; + + gltf.unHideAll(); + + if (data && data.hiddenNodes) + { + for (const i in data.hiddenNodes) + { + const n = gltf.getNode(i); + if (n) n.hidden = true; + else op.verbose("node to be hidden not found", i, n); + } + } + hideNodesFromArray(); +} + +function loadData() +{ + data = dataPort.get(); + + if (!data || data === "")data = {}; + else data = JSON.parse(data); + + if (gltf)hideNodesFromData(); + + return data; +} + +function saveData() +{ + dataPort.set(JSON.stringify(data)); +} + +function updateAnimation() +{ + if (gltf && gltf.nodes) + { + for (let i = 0; i < gltf.nodes.length; i++) + { + gltf.nodes[i].setAnimAction(inAnimation.get()); + } + } +} + +function findParents(nodes, childNodeIndex) +{ + for (let i = 0; i < gltf.nodes.length; i++) + { + if (gltf.nodes[i].children.indexOf(childNodeIndex) >= 0) + { + nodes.push(gltf.nodes[i]); + if (gltf.nodes[i].isChild) findParents(nodes, i); + } + } +} + +op.exposeTexture = function (name) +{ + const newop = gui.corePatch().addOp("Ops.Gl.GLTF.GltfTexture"); + newop.getPort("Name").set(name); + setNewOpPosition(newop, 1); + op.patch.link(op, next.name, newop, "Render"); + gui.patchView.centerSelectOp(newop.id, true); + gui.patchView.testCollision(newop); +}; + +op.exposeGeom = function (name, idx) +{ + const newop = gui.corePatch().addOp("Ops.Gl.GLTF.GltfGeometry"); + newop.getPort("Name").set(name); + newop.getPort("Submesh").set(idx); + setNewOpPosition(newop, 1); + op.patch.link(op, next.name, newop, "Update"); + gui.patchView.centerSelectOp(newop.id, true); + gui.patchView.testCollision(newop); +}; + +function setNewOpPosition(newOp, num) +{ + num = num || 1; + + newOp.setUiAttrib({ "translate": { "x": op.uiAttribs.translate.x, "y": op.uiAttribs.translate.y + num * CABLES.GLUI.glUiConfig.newOpDistanceY } }); +} + +op.exposeNode = function (name, type, options) +{ + let tree = type == "hierarchy"; + if (tree) + { + let ops = []; + + for (let i = 0; i < gltf.nodes.length; i++) + { + if (gltf.nodes[i].name == name) + { + let arrHierarchy = []; + const node = gltf.nodes[i]; + findParents(arrHierarchy, i); + + arrHierarchy = arrHierarchy.reverse(); + arrHierarchy.push(node, node); + + let prevPort = next.name; + let prevOp = op; + for (let j = 0; j < arrHierarchy.length; j++) + { + const newop = gui.corePatch().addOp("Ops.Gl.GLTF.GltfNode_v2"); + newop.getPort("Node Name").set(arrHierarchy[j].name); + op.patch.link(prevOp, prevPort, newop, "Render"); + setNewOpPosition(newop, j); + + if (j == arrHierarchy.length - 1) + { + newop.getPort("Transformation").set(false); + } + else + { + newop.getPort("Draw Mesh").set(false); + newop.getPort("Draw Childs").set(false); + } + + prevPort = "Next"; + prevOp = newop; + ops.push(newop); + gui.patchView.testCollision(newop); + } + } + } + + for (let i = 0; i < ops.length; i++) + { + ops[i].selectChilds(); + } + } + else + { + let newopname = "Ops.Gl.GLTF.GltfNode_v2"; + if (options && options.skin)newopname = "Ops.Gl.GLTF.GltfSkin"; + if (type == "transform")newopname = "Ops.Gl.GLTF.GltfNodeTransform_v2"; + + gui.serverOps.loadOpLibs(newopname, () => + { + let newop = gui.corePatch().addOp(newopname); + + newop.getPort("Node Name").set(name); + setNewOpPosition(newop); + op.patch.link(op, next.name, newop, "Render"); + gui.patchView.centerSelectOp(newop.id, true); + gui.patchView.testCollision(newop); + }); + } + gui.closeModal(); +}; + +op.assignMaterial = function (name) +{ + const newop = gui.corePatch().addOp("Ops.Gl.GLTF.GltfSetMaterial"); + newop.getPort("Material Name").set(name); + op.patch.link(op, inMaterials.name, newop, "Material"); + gui.patchView.centerSelectOp(newop.id, true); + setNewOpPosition(newop); + gui.patchView.testCollision(newop); + + gui.closeModal(); +}; + +op.toggleNodeVisibility = function (name) +{ + const n = gltf.getNode(name); + n.hidden = !n.hidden; + data.hiddenNodes = data.hiddenNodes || {}; + + if (n) + if (n.hidden)data.hiddenNodes[name] = true; + else delete data.hiddenNodes[name]; + + saveData(); +}; + +op.showAnim = function (anim, channel) +{ + const an = gltf.json.animations[anim]; + const chan = gltf.json.animations[anim].channels[channel]; + + const node = gltf.nodes[chan.target.node]; + const sampler = an.samplers[chan.sampler]; + + const acc = gltf.json.accessors[sampler.input]; + const bufferIn = gltf.accBuffers[sampler.input]; + + const accOut = gltf.json.accessors[sampler.output]; + const bufferOut = gltf.accBuffers[sampler.output]; +}; + +function uniqueArray(arr) +{ + const u = {}, a = []; + for (let i = 0, l = arr.length; i < l; ++i) + { + if (!u.hasOwnProperty(arr[i])) + { + a.push(arr[i]); + u[arr[i]] = 1; + } + } + return a; +} + + +}; + +Ops.Gl.GLTF.GltfScene_v3.prototype = new CABLES.Op(); +CABLES.OPS["a9c59d94-8aea-4c20-ab5d-63ce46ecfa16"]={f:Ops.Gl.GLTF.GltfScene_v3,objName:"Ops.Gl.GLTF.GltfScene_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.GLTF.GltfSetMaterial +// +// ************************************************************** + +Ops.Gl.GLTF.GltfSetMaterial = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inShader = op.inObject("Shader", null, "shader"), + inName = op.inString("Material Name", "none"), + outMat = op.outObject("Material"); + +inName.onChange = +inShader.onChange = function () +{ + op.setTitle("Material " + inName.get()); + outMat.set(null); + outMat.set(inShader.get()); +}; + + +}; + +Ops.Gl.GLTF.GltfSetMaterial.prototype = new CABLES.Op(); +CABLES.OPS["baf968ea-e4df-4fca-9cda-e6ddd38a4200"]={f:Ops.Gl.GLTF.GltfSetMaterial,objName:"Ops.Gl.GLTF.GltfSetMaterial"}; + + + + +// ************************************************************** +// +// Ops.Gl.GLTF.GltfSkin +// +// ************************************************************** + +Ops.Gl.GLTF.GltfSkin = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"joints_vert":"\n\n\n\n\n // if(attrJoints.x!=-1.0)\n {\n int index=int(attrJoints.x);\n vec4 newPos = (MOD_boneMats[index] * pos) * attrWeights.x;\n vec3 newNorm = (vec4((MOD_boneMats[index] * vec4(norm.xyz, 0.0)) * attrWeights.x).xyz);\n\n // if(attrJoints.y!=-1.0)\n {\n index=int(attrJoints.y);\n newPos += (MOD_boneMats[index] * pos) * attrWeights.y;\n newNorm = (vec4((MOD_boneMats[index] * vec4(norm.xyz, 0.0)) * attrWeights.y).xyz)+newNorm;\n }\n\n // if(attrJoints.z!=-1.0)\n {\n index=int(attrJoints.z);\n newPos += (MOD_boneMats[index] * pos) * attrWeights.z;\n newNorm = (vec4((MOD_boneMats[index] * vec4(norm.xyz, 0.0)) * attrWeights.z).xyz)+newNorm;\n }\n\n // if(attrJoints.w!=-1.0)\n {\n index=int(attrJoints.w);\n newPos += (MOD_boneMats[index] * pos) * attrWeights.w ;\n newNorm = (vec4((MOD_boneMats[index] * vec4(norm.xyz, 0.0)) * attrWeights.w).xyz)+newNorm;\n }\n\n pos=newPos;\n norm=normalize(newNorm.xyz);\n }\n\n\n\n// mat4 skinMatrix =\n// attrWeights.x * MOD_boneMats[int(attrJoints.x)] +\n// attrWeights.y * MOD_boneMats[int(attrJoints.y)] +\n// attrWeights.z * MOD_boneMats[int(attrJoints.z)] +\n// attrWeights.w * MOD_boneMats[int(attrJoints.w)];\n\n// mMatrix*=skinMatrix;\n\n\n\n\n\n\n\n\n\n","joints_head_vert":"IN vec4 attrWeights;\nIN vec4 attrJoints;\n\n\nUNI mat4 MOD_boneMats[SKIN_NUM_BONES];",}; +const + exec = op.inTrigger("Render"), + inNodeName = op.inString("Node Name", "default"), + inSceneTime = op.inBool("Scene Time", true), + inTime = op.inFloat("Time", 0), + inBlendAnims = op.inArray("Blend Anims"), + outFound = op.outBool("Found Node"), + outFoundSkin = op.outBool("Found Skin"), + next = op.outTrigger("Next"); + +exec.onTriggered = update; +const cgl = op.patch.cgl; +const mod = new CGL.ShaderModifier(cgl, op.name); +let arr = []; +let node = null; +const tr = vec3.create(); + +inSceneTime.onChange = updateTimeInputs; + +updateTimeInputs(); + +function updateTimeInputs() +{ + inTime.setUiAttribs({ "greyout": inSceneTime.get() }); +} + +inNodeName.onChange = () => +{ + op.setUiAttrib({ "extendTitle": inNodeName.get() }); + node = null; + update(); +}; + +function update() +{ + if (!cgl.frameStore || !cgl.frameStore.currentScene) return; + + const gltf = cgl.frameStore.currentScene; + const name = inNodeName.get(); + + for (let i = 0; i < cgl.frameStore.currentScene.nodes.length; i++) + { + if (cgl.frameStore.currentScene.nodes[i].name == name) + { + node = cgl.frameStore.currentScene.nodes[i]; + outFound.set(true); + } + } + + if (!node) + { + outFound.set(false); + return; + } + outFoundSkin.set(node.skin > -1); + + if (node.skin == -1) + { + return; + } + + if (!gltf.json.skins) + { + op.warn.log("no skins found..."); + return; + } + + let time = gltf.time; + if (!inSceneTime.get()) + { + time = inTime.get(); + } + + if (!inSceneTime.get()) + for (let i = 0; i < gltf.nodes.length; i++) + if (!gltf.nodes[i].isChild) + gltf.nodes[i].render(cgl, false, true, true, false, false, time); + + transformBlend(node, cgl, time); + + node.render(cgl, true, false, true, false, true, time); + + next.trigger(); +} + +function transformBlend(node, cgl, time) +{ + // let hasTrans = node._anims.trans.length > 0; + // let hasRot = node._anims.rot.length > 0; + // hasRot = false; + // let hasScale = node._anims.scale.length > 0; + // hasScale = false; + + const animnames = Object.keys(cgl.frameStore.currentScene.uniqueAnimNames); + + const weights = inBlendAnims.get(); + + // if ((!hasTrans && !hasRot && !hasScale) || _w === 0) + // { + // mat4.mul(cgl.mMatrix, cgl.mMatrix, node.mat); + // node._animMat = null; + // } + // else + { + // node._animActions[n][path] + // animnames + + node._animMat = node._animMat || mat4.create(); + mat4.identity(node._animMat); + + const playAnims = true; + + if (playAnims) + { + let _x = 0, _y = 0, _z = 0, _w = 0; + + for (let i = 0; i < animnames.length; i++) + { + const animName = animnames[i]; + if (!node._animActions[animName] || !node._animActions[animName].translation) continue; + + let _time = time;// times[animnames[i]]; + // let _anim = node._anims.trans[i]; + + let _anim = node._animActions[animName].translation; + let weight = weights[i]; + + if (_anim) + { + _x += _anim[0].getValue(_time) * weight + (_anim[0].getValue(0) * (1 - weight)); + _y += _anim[1].getValue(_time) * weight + (_anim[1].getValue(0) * (1 - weight)); + _z += _anim[2].getValue(_time) * weight + (_anim[2].getValue(0) * (1 - weight)); + _w += 1; + } + } + + if (_w > 0) + { + _x /= _w; + _y /= _w; + _z /= _w; + + mat4.translate(node._animMat, node._animMat, [_x, _y, _z]); + } + } + else + if (node._node.translation) mat4.translate(node._animMat, node._animMat, node._node.translation); + + if (playAnims) + { + node._tempQuats = node._tempQuats || []; + + for (let i = 0; i < animnames.length; i++) + { + const animName = animnames[i]; + if (!node._animActions[animName] || !node._animActions[animName].translation) continue; + + let _time = time;// times[animnames[i]]; + + let _tempQuat2 = node._tempQuats[i] || quat.create(); + + // let shouldAnim = node._anims.rot[i] && node._anims.trans[i]; + // let _anim = node._anims.rot[i]; + let _anim = node._animActions[animName].rotation; + let weight = weights[i]; + + if (_anim) + { + CABLES.TL.Anim.slerpQuaternion(_time, _tempQuat2, _anim[0], _anim[1], _anim[2], _anim[3]); + } + node._tempQuats[i] = (_tempQuat2); + } + + let _finalQuat = node._tempQuat; + + for (let i = 0; i < node._tempQuats.length; i++) + { + // if (weights[i] === 0) continue; + quat.slerp(_finalQuat, _finalQuat, node._tempQuats[i], node._anims.trans[i] ? weights[i] : 0); + } + + mat4.fromQuat(node._tempMat, _finalQuat); + mat4.mul(node._animMat, node._animMat, node._tempMat); + + node._tempQuat = _finalQuat; + } + else if (node._rot) + { + mat4.fromQuat(node._tempRotmat, node._rot); + mat4.mul(node._animMat, node._animMat, node._tempRotmat); + } + + if (playAnims) + { + let _x = 0, _y = 0, _z = 0, _w = 0; + + for (let i = 0; i < animnames.length; i++) + { + const animName = animnames[i]; + if (!node._animActions[animName] || !node._animActions[animName].translation) continue; + + let _time = time;// times[animnames[i]]; + + // let _anim = node._anims.scale[i]; + let _anim = node._animActions[animName].scaling; + let weight = weights[i]; + + if (_anim) + { + _x += _anim[0].getValue(_time) * weight; + _y += _anim[1].getValue(_time) * weight; + _z += _anim[2].getValue(_time) * weight; + _w += weight; + } + } + + if (_w > 0) + { + _x /= _w; + _y /= _w; + _z /= _w; + + mat4.scale(node._animMat, node._animMat, [_x, _y, _z]); + } + } + else if (node._scale) mat4.scale(node._animMat, node._animMat, node._scale); + + mat4.mul(cgl.mMatrix, cgl.mMatrix, node._animMat); + } + + if (node.addTranslate)mat4.translate(cgl.mMatrix, cgl.mMatrix, node.addTranslate); + + if (node.addMulMat) mat4.mul(cgl.mMatrix, cgl.mMatrix, node.addMulMat); + + mat4.copy(node.absMat, cgl.mMatrix); +} + + +}; + +Ops.Gl.GLTF.GltfSkin.prototype = new CABLES.Op(); +CABLES.OPS["0ce62e9b-d990-4ae2-b40f-a036a021aa9c"]={f:Ops.Gl.GLTF.GltfSkin,objName:"Ops.Gl.GLTF.GltfSkin"}; + + + + +// ************************************************************** +// +// Ops.Gl.GLTF.GltfTexture +// +// ************************************************************** + +Ops.Gl.GLTF.GltfTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Render"), + imgName = op.inString("Name", ""), + tfilter = op.inSwitch("Filter", ["nearest", "linear", "mipmap"], "mipmap"), + wrap = op.inValueSelect("Wrap", ["repeat", "mirrored repeat", "clamp to edge"], "clamp to edge"), + aniso = op.inSwitch("Anisotropic", [0, 1, 2, 4, 8, 16], 0), + flip = op.inValueBool("Flip", false), + unpackAlpha = op.inValueBool("Pre Multiplied Alpha", false), + outTex = op.outTexture("Texture"), + width = op.outNumber("Width"), + height = op.outNumber("Height"), + type = op.outString("Type"), + outFound = op.outBool("Found"); + +const cgl = op.patch.cgl; +let tex = null; +let cgl_filter = 0; +let cgl_wrap = 0; +let cgl_aniso = 0; + +aniso.onChange = tfilter.onChange = onFilterChange; +wrap.onChange = onWrapChange; +imgName.onChange = flip.onChange = unpackAlpha.onChange = function () { reloadSoon(); }; + +function reloadSoon() +{ + tex = null; +} + +inExec.onTriggered = function () +{ + if (tex) return; + + if (!cgl.frameStore.currentScene || !cgl.frameStore.currentScene.json) return; + + if (cgl.frameStore.currentScene.chunks.length < 2) + { + return; + } + + if (!cgl.frameStore.currentScene.json.images) return; + + let img = null; + + for (let i = 0; i < cgl.frameStore.currentScene.json.images.length; i++) + { + if (cgl.frameStore.currentScene.json.images[i].name == imgName.get() || cgl.frameStore.currentScene.json.images[i].bufferView == parseFloat(imgName.get())) + { + img = cgl.frameStore.currentScene.json.images[i]; + } + } + if (!img) + { + tex = CGL.Texture.getEmptyTexture(cgl); + outFound.set(false); + outTex.set(tex); + width.set(tex.width); + height.set(tex.height); + return; + } + + const buffView = cgl.frameStore.currentScene.json.bufferViews[img.bufferView]; + let dv = cgl.frameStore.currentScene.chunks[1].dataView; + + if (!buffView) return; + const data = new Uint8Array(buffView.byteLength); + + for (let i = 0; i < buffView.byteLength; i++) + data[i] = dv.getUint8(buffView.byteOffset + i); + + const blob = new Blob([data.buffer], { "type": img.mimeType }); + const sourceURI = URL.createObjectURL(blob); + + if (tfilter.get() == "nearest") cgl_filter = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "linear") cgl_filter = CGL.Texture.FILTER_LINEAR; + else if (tfilter.get() == "mipmap") cgl_filter = CGL.Texture.FILTER_MIPMAP; + else if (tfilter.get() == "Anisotropic") cgl_filter = CGL.Texture.FILTER_ANISOTROPIC; + + cgl_aniso = parseFloat(aniso.get()); + + tex = CGL.Texture.load(cgl, sourceURI, + function (err) + { + if (err) + { + outFound.set(false); + } + + outTex.set(tex); + + width.set(tex.width); + height.set(tex.height); + type.set(img.mimeType); + outTex.set(null); + outTex.set(tex); + outFound.set(true); + }, { + "anisotropic": cgl_aniso, + "wrap": cgl_wrap, + "flip": flip.get(), + "unpackAlpha": unpackAlpha.get(), + "filter": cgl_filter + }); + + outTex.set(null); + outTex.set(tex); +}; + +function onFilterChange() +{ + reloadSoon(); +} + +function onWrapChange() +{ + if (wrap.get() == "repeat") cgl_wrap = CGL.Texture.WRAP_REPEAT; + if (wrap.get() == "mirrored repeat") cgl_wrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + if (wrap.get() == "clamp to edge") cgl_wrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + reloadSoon(); +} + + +}; + +Ops.Gl.GLTF.GltfTexture.prototype = new CABLES.Op(); +CABLES.OPS["6479a948-7a48-42a3-b40a-794f4364715f"]={f:Ops.Gl.GLTF.GltfTexture,objName:"Ops.Gl.GLTF.GltfTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.GLTF.GltfTransformNode +// +// ************************************************************** + +Ops.Gl.GLTF.GltfTransformNode = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Render"), + inNodeName = op.inString("Node Name"), + inPosX = op.inFloat("Translate X", 0), + inPosY = op.inFloat("Translate Y", 0), + inPosZ = op.inFloat("Translate Z", 0), + inRotX = op.inFloat("Rotation X", 0), + inRotY = op.inFloat("Rotation Y", 0), + inRotZ = op.inFloat("Rotation Z", 0), + next = op.outTrigger("Next"), + outFound = op.outBool("Found"); + +const cgl = op.patch.cgl; + +let q = quat.create(); +let mat = mat4.create(); +let qmat = mat4.create(); + +let node = null; +let currentSceneLoaded = null; + +inNodeName.onChange = function () +{ + node = null; + outFound.set(false); + op.setUiAttrib({ "extendTitle": inNodeName.get() }); +}; + +op.onDelete = function () +{ + // todo restore orig values! +}; + +inExec.onTriggered = function () +{ + if (!cgl.frameStore.currentScene) return; + if (currentSceneLoaded != cgl.frameStore.currentScene.loaded) node = null; + + if (!node) + { + const name = inNodeName.get(); + + if (!cgl.frameStore || !cgl.frameStore.currentScene || !cgl.frameStore.currentScene.nodes) return; + + currentSceneLoaded = cgl.frameStore.currentScene.loaded; + + for (let i = 0; i < cgl.frameStore.currentScene.nodes.length; i++) + { + if (cgl.frameStore.currentScene.nodes[i].name == name) + { + node = cgl.frameStore.currentScene.nodes[i]; + outFound.set(true); + } + } + } + + if (node) + { + mat4.identity(mat); + mat4.translate(mat, mat, [inPosX.get(), inPosY.get(), inPosZ.get()]); + + mat4.rotateX(mat, mat, inRotX.get()); + mat4.rotateY(mat, mat, inRotY.get()); + mat4.rotateZ(mat, mat, inRotZ.get()); + + node.addMulMat = mat; + } + + next.trigger(); +}; + + +}; + +Ops.Gl.GLTF.GltfTransformNode.prototype = new CABLES.Op(); +CABLES.OPS["bccdb19d-6786-4656-90d7-e798346ea644"]={f:Ops.Gl.GLTF.GltfTransformNode,objName:"Ops.Gl.GLTF.GltfTransformNode"}; + + + + +// ************************************************************** +// +// Ops.Gl.GLTF.GltfVertexAnim +// +// ************************************************************** + +Ops.Gl.GLTF.GltfVertexAnim = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Render"), + inNodeName = op.inString("Node Name", "default"), + inSceneTime = op.inBool("Scene Time", true), + inTime = op.inFloat("Time", 0), + outFound = op.outBoolNum("Found Node"), + next = op.outTrigger("Next"); + +exec.onTriggered = render; +const cgl = op.patch.cgl; +let node = null; +let needsUpdate = true; +let origGMesh = null; +let mesh = null; +let geom = null; +let morphGeom = null; +let origGeom = null; + +inSceneTime.onChange = updateTimeInputs; +updateTimeInputs(); + +let lastMorph1 = -1; +let lastMorph2 = -1; +let lastFract = -1; + +inNodeName.onChange = () => +{ + op.setUiAttrib({ "extendTitle": inNodeName.get() }); + node = null; + needsUpdate = true; + lastMorph1 = -1; + lastMorph2 = -1; + lastFract = -1; +}; + +function updateTimeInputs() +{ + inTime.setUiAttribs({ "greyout": inSceneTime.get() }); +} + +function morph(finalGeom, mt, mt2, fract) +{ + if (mt && mt.vertices && mt2) + { + if (finalGeom.vertexNormals.length != mt.vertexNormals.length) + finalGeom.vertexNormals = new Float32Array(mt.vertexNormals.length); + + for (let i = 0; i < finalGeom.vertices.length; i++) + { + finalGeom.vertices[i] = + origGeom.vertices[i] + + (1.0 - fract) * mt.vertices[i] + + fract * mt2.vertices[i]; + + finalGeom.vertexNormals[i] = + (1.0 - fract) * mt.vertexNormals[i] + + fract * mt2.vertexNormals[i]; + } + } +} + + +function update() +{ + if (!cgl.frameStore.currentScene) return; + + needsUpdate = false; + mesh = null; + + const gltf = cgl.frameStore.currentScene; + const name = inNodeName.get(); + for (let i = 0; i < cgl.frameStore.currentScene.nodes.length; i++) + { + op.log(cgl.frameStore.currentScene.nodes[i].name); + if (cgl.frameStore.currentScene.nodes[i].name == name) + { + node = cgl.frameStore.currentScene.nodes[i]; + outFound.set(true); + op.log(node); + + if (node.mesh && node.mesh.meshes) + { + // mesh=node.mesh.meshes[0].copy(); + origGMesh = node.mesh.meshes[0]; + origGeom = node.mesh.meshes[0].geom; + geom = node.mesh.meshes[0].geom.copy(); + morphGeom = geom.copy(); + mesh = new CGL.Mesh(cgl, geom); + // mesh.setGeom(); + } + else op.warn("[gltfvertexanim] node found but no meshes"); + + op.log("orig mesh", node.mesh.meshes[0]); + op.log("mesh", mesh); + } + } + + if (!node) + { + outFound.set(false); + } +} + +function render() +{ + if (!cgl.frameStore.currentScene) return; + + if (needsUpdate) update(); + + if (!geom) return; + if (!mesh) return; + + let time = cgl.frameStore.currentScene.time; + if (!inSceneTime.get())time = inTime.get(); + + if (time >= geom.morphTargets.length - 1) time = geom.morphTargets.length - 1; + + let morph1 = Math.floor(time); + let morph2 = Math.floor(time + 1); + const fract = time % 1; + + if (lastMorph1 != morph1 || lastMorph2 != morph2 || fract != lastFract) + { + const mt = geom.morphTargets[morph1]; + const mt2 = geom.morphTargets[morph2]; + + morph(morphGeom, mt, mt2, fract); + + mesh.updateNormals(morphGeom); + mesh.updateVertices(morphGeom); + + lastMorph1 = morph1; + lastMorph2 = morph2; + lastFract = fract; + } + + mesh.render(cgl.getShader()); + + next.trigger(); +} + + +}; + +Ops.Gl.GLTF.GltfVertexAnim.prototype = new CABLES.Op(); +CABLES.OPS["e64b035c-133e-43b0-9ff8-fcd03ee5f26e"]={f:Ops.Gl.GLTF.GltfVertexAnim,objName:"Ops.Gl.GLTF.GltfVertexAnim"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.AlignGeometry +// +// ************************************************************** + +Ops.Gl.Geometry.AlignGeometry = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + geometry = op.inObject("Geometry"), + x = op.inValueSelect("X", ["Ignore", "Center", "Max", "Min"], "Ignore"), + y = op.inValueSelect("Y", ["Ignore", "Center", "Max", "Min"], "Ignore"), + z = op.inValueSelect("Z", ["Ignore", "Center", "Max", "Min"], "Ignore"), + outGeom = op.outObject("Result"); + +x.onChange = y.onChange = z.onChange = geometry.onChange = update; + +const + axis = [0, 0, 0], + ALIGN_NONE = 0, + ALIGN_CENTER = 1, + ALIGN_MAX = 2, + ALIGN_MIN = 3; + +let oldGeom = null, + geom = null; + +function getAxisId(port) +{ + if (port.get() == "Ignore") return ALIGN_NONE; + if (port.get() == "Center") return ALIGN_CENTER; + if (port.get() == "Max") return ALIGN_MAX; + if (port.get() == "Min") return ALIGN_MIN; +} + +function update() +{ + if (oldGeom != geometry.get()) + { + geom = null; + oldGeom = geometry.get(); + } + + if (!oldGeom) + { + outGeom.set(null); + return; + } + + axis[0] = getAxisId(x); + axis[1] = getAxisId(y); + axis[2] = getAxisId(z); + + const bounds = oldGeom.getBounds(); + if (!geom) geom = oldGeom.copy(); + + for (let axi = 0; axi < 3; axi++) + { + let min = 0, max = 0; + if (axi === 0) + { + min = bounds.minX; + max = bounds.maxX; + } + else if (axi == 1) + { + min = bounds.minY; + max = bounds.maxY; + } + else if (axi == 2) + { + min = bounds.minZ; + max = bounds.maxZ; + } + + if (axis[axi] == ALIGN_NONE) + { + for (let i = 0; i < geom.vertices.length; i += 3) + geom.vertices[i + axi] = oldGeom.vertices[i + axi]; + } + else if (axis[axi] == ALIGN_CENTER) + { + const off = min + (max - min) / 2; + for (let i = 0; i < geom.vertices.length; i += 3) + geom.vertices[i + axi] = oldGeom.vertices[i + axi] - off; + } + else if (axis[axi] == ALIGN_MAX) + { + for (let i = 0; i < geom.vertices.length; i += 3) + geom.vertices[i + axi] = oldGeom.vertices[i + axi] - max; + } + else if (axis[axi] == ALIGN_MIN) + { + for (let i = 0; i < geom.vertices.length; i += 3) + geom.vertices[i + axi] = oldGeom.vertices[i + axi] - min; + } + } + + outGeom.set(null); + outGeom.set(geom); +} + + +}; + +Ops.Gl.Geometry.AlignGeometry.prototype = new CABLES.Op(); +CABLES.OPS["955c1a40-17ca-4944-8cf6-07e14212be2d"]={f:Ops.Gl.Geometry.AlignGeometry,objName:"Ops.Gl.Geometry.AlignGeometry"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.BoundingBoxVisible +// +// ************************************************************** + +Ops.Gl.Geometry.BoundingBoxVisible = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Exec"), + inBB = op.inObject("Boundings"), + inActive = op.inBool("Active", true), + inDraw = op.inBool("Draw", true), + + inWidth = op.inFloat("Width", 1), + inHeight = op.inFloat("Height", 1), + inLength = op.inFloat("Length", 1), + + next = op.outTrigger("Next"), + result = op.outBool("Visible"), + + cgl = op.patch.cgl, + trans = vec3.create(), + m = mat4.create(), + pos = vec3.create(), + identVec = vec3.create(); + +let + vp = null, + geom = null, + bb = null, + mesh = null; + +inBB.onLinkChanged = updateUi; +updateUi(); + +function isVisible(posi) +{ + // vec3.add(pos,pos,posi); + vec3.transformMat4(pos, posi, m); + + vec3.transformMat4(trans, pos, cgl.pMatrix); + + const xp = (trans[0] * vp[2] / 2) + vp[2] / 2; + const yp = (trans[1] * vp[3] / 2) + vp[3] / 2; + + return pos[2] < 0.0 && xp > 0 && xp < vp[2] && yp > 0 && yp < vp[3]; +} + +function updateUi() +{ + inWidth.setUiAttribs({ "greyout": inBB.isLinked() }); + inHeight.setUiAttribs({ "greyout": inBB.isLinked() }); + inLength.setUiAttribs({ "greyout": inBB.isLinked() }); +} + +inHeight.onChange = +inLength.onChange = +inWidth.onChange = +inBB.onChange = function () +{ + mesh = null; +}; +buildMesh(); + +function buildMesh() +{ + if (inBB.isLinked()) + { + bb = inBB.get(); + if (!bb || !bb._max || !bb._min) return; + } + else + { + bb = new CABLES.CG.BoundingBox(); + + bb.applyPos(inWidth.get() / 2, inHeight.get() / 2, inLength.get() / 2); + bb.applyPos(-inWidth.get() / 2, -inHeight.get() / 2, -inLength.get() / 2); + } + + geom = new CGL.Geometry(op.name); + geom.vertices = + [ + bb._max[0], bb._max[1], bb._max[2], + bb._min[0], bb._max[1], bb._max[2], + + bb._min[0], bb._max[1], bb._max[2], + bb._min[0], bb._min[1], bb._max[2], + + bb._min[0], bb._min[1], bb._max[2], + bb._max[0], bb._min[1], bb._max[2], + + bb._max[0], bb._min[1], bb._max[2], + bb._max[0], bb._max[1], bb._max[2], + + // + + bb._max[0], bb._max[1], bb._min[2], + bb._min[0], bb._max[1], bb._min[2], + + bb._min[0], bb._max[1], bb._min[2], + bb._min[0], bb._min[1], bb._min[2], + + bb._min[0], bb._min[1], bb._min[2], + bb._max[0], bb._min[1], bb._min[2], + + bb._max[0], bb._min[1], bb._min[2], + bb._max[0], bb._max[1], bb._min[2], + + // + + bb._max[0], bb._max[1], bb._min[2], + bb._max[0], bb._max[1], bb._max[2], + + bb._min[0], bb._max[1], bb._min[2], + bb._min[0], bb._max[1], bb._max[2], + + bb._max[0], bb._min[1], bb._min[2], + bb._max[0], bb._min[1], bb._max[2], + + bb._min[0], bb._min[1], bb._min[2], + bb._min[0], bb._min[1], bb._max[2], + + // + + bb._min[0], bb._min[1], bb._min[2], + bb._max[0], bb._max[1], bb._max[2], + + bb._max[0], bb._min[1], bb._min[2], + bb._min[0], bb._max[1], bb._max[2], + + ]; + + mesh = new CGL.Mesh(cgl, geom, cgl.gl.LINES); +} + +// LINE/LINE +function lineToScreen(posA, posB) +{ + vec3.transformMat4(pos, posA, m); + vec3.transformMat4(trans, pos, cgl.pMatrix); + + if (pos[2] > 0.0) return false; + + const x1 = (trans[0] * vp[2] / 2) + vp[2] / 2; + const y1 = (trans[1] * vp[3] / 2) + vp[3] / 2; + + vec3.transformMat4(pos, posB, m); + vec3.transformMat4(trans, pos, cgl.pMatrix); + + if (pos[2] > 0.0) return false; + + const x2 = (trans[0] * vp[2] / 2) + vp[2] / 2; + const y2 = (trans[1] * vp[3] / 2) + vp[3] / 2; + + const w = vp[2]; + const h = vp[3]; + + return lineline(x1, y1, x2, y2, 0, 0, w, h) || + + lineline(x1, y1, x2, y2, 0, 0, w, 0) || + lineline(x1, y1, x2, y2, 0, h, w, h) || + + lineline(x1, y1, x2, y2, 0, 0, 0, h) || + lineline(x1, y1, x2, y2, w, 0, w, h); +} + +function lineline(x1, y1, x2, y2, x3, y3, x4, y4) +{ + // calculate the direction of the lines + const uA = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)); + const uB = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)); + + // if uA and uB are between 0-1, lines are colliding + if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) + { + // const intersectionX =d x1 + (uA * (x2 - x1)); + // const intersectionY = y1 + (uA * (y2 - y1)); + + return true; + } + return false; +} + +exec.onTriggered = () => +{ + if (!inActive.get()) return; + + if (inBB.isLinked()) + { + bb = inBB.get(); + } + + if (inBB.isLinked() && (!bb || !bb._center || !bb._max)) + { + result.set(false); + return; + } + + if (inDraw.get()) + { + if (!geom || !mesh) buildMesh(); + if (mesh)mesh.render(cgl.getShader()); + } + + vp = cgl.getViewPort(); + + mat4.multiply(m, cgl.vMatrix, cgl.mMatrix); + + if (bb) + { + const isVis = + + isVisible(bb._center) || + + isVisible(bb._max) || + isVisible(bb._min) || + + lineToScreen(bb._max, bb._min) || + + lineToScreen([bb._max[0], bb._max[1], bb._max[2]], [bb._min[0], bb._max[1], bb._max[2]]) || + lineToScreen([bb._min[0], bb._max[1], bb._max[2]], [bb._min[0], bb._min[1], bb._max[2]]) || + lineToScreen([bb._min[0], bb._min[1], bb._max[2]], [bb._max[0], bb._min[1], bb._max[2]]) || + lineToScreen([bb._max[0], bb._min[1], bb._max[2]], [bb._max[0], bb._max[1], bb._max[2]]) || + + // + + lineToScreen([bb._max[0], bb._max[1], bb._min[2]], [bb._min[0], bb._max[1], bb._min[2]]) || + lineToScreen([bb._min[0], bb._max[1], bb._min[2]], [bb._min[0], bb._min[1], bb._min[2]]) || + lineToScreen([bb._min[0], bb._min[1], bb._min[2]], [bb._max[0], bb._min[1], bb._min[2]]) || + lineToScreen([bb._max[0], bb._min[1], bb._min[2]], [bb._max[0], bb._max[1], bb._min[2]]) || + + // + + lineToScreen([bb._max[0], bb._max[1], bb._min[2]], [bb._max[0], bb._max[1], bb._max[2]]) || + lineToScreen([bb._min[0], bb._max[1], bb._min[2]], [bb._min[0], bb._max[1], bb._max[2]]) || + lineToScreen([bb._max[0], bb._min[1], bb._min[2]], [bb._max[0], bb._min[1], bb._max[2]]) || + lineToScreen([bb._min[0], bb._min[1], bb._min[2]], [bb._min[0], bb._min[1], bb._max[2]]); + + result.set(isVis); + } + + next.trigger(); +}; + + +}; + +Ops.Gl.Geometry.BoundingBoxVisible.prototype = new CABLES.Op(); +CABLES.OPS["a4a8d0ca-296e-4bf5-a7be-4585f875bc06"]={f:Ops.Gl.Geometry.BoundingBoxVisible,objName:"Ops.Gl.Geometry.BoundingBoxVisible"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.DivideGeometry +// +// ************************************************************** + +Ops.Gl.Geometry.DivideGeometry = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; + +let geometry = op.inObject("Geometry"); +let outGeom = op.outObject("Result"); + +geometry.onChange = update; + + +function update() +{ + outGeom.set(null); + if (geometry.get()) + { + let geom = geometry.get(); + let newGeom = new CGL.Geometry(op.name); + + let newVerts = []; + let newFaces = []; + let newNormals = []; + let newTexCoords = []; + + for (let i = 0; i < geom.verticesIndices.length; i += 3) + { + newFaces.push(newVerts.length / 3); + newVerts.push(geom.vertices[geom.verticesIndices[i + 0] * 3 + 0]); + newVerts.push(geom.vertices[geom.verticesIndices[i + 0] * 3 + 1]); + newVerts.push(geom.vertices[geom.verticesIndices[i + 0] * 3 + 2]); + newNormals.push(geom.vertexNormals[geom.verticesIndices[i + 0] * 3 + 0]); + newNormals.push(geom.vertexNormals[geom.verticesIndices[i + 0] * 3 + 1]); + newNormals.push(geom.vertexNormals[geom.verticesIndices[i + 0] * 3 + 2]); + newTexCoords.push(geom.texCoords[geom.verticesIndices[i + 0] * 2 + 0]); + newTexCoords.push(geom.texCoords[geom.verticesIndices[i + 0] * 2 + 1]); + + newFaces.push(newVerts.length / 3); + newVerts.push(geom.vertices[geom.verticesIndices[i + 1] * 3 + 0]); + newVerts.push(geom.vertices[geom.verticesIndices[i + 1] * 3 + 1]); + newVerts.push(geom.vertices[geom.verticesIndices[i + 1] * 3 + 2]); + newNormals.push(geom.vertexNormals[geom.verticesIndices[i + 1] * 3 + 0]); + newNormals.push(geom.vertexNormals[geom.verticesIndices[i + 1] * 3 + 1]); + newNormals.push(geom.vertexNormals[geom.verticesIndices[i + 1] * 3 + 2]); + newTexCoords.push(geom.texCoords[geom.verticesIndices[i + 1] * 2 + 0]); + newTexCoords.push(geom.texCoords[geom.verticesIndices[i + 1] * 2 + 1]); + + newFaces.push(newVerts.length / 3); + newVerts.push(geom.vertices[geom.verticesIndices[i + 2] * 3 + 0]); + newVerts.push(geom.vertices[geom.verticesIndices[i + 2] * 3 + 1]); + newVerts.push(geom.vertices[geom.verticesIndices[i + 2] * 3 + 2]); + newNormals.push(geom.vertexNormals[geom.verticesIndices[i + 2] * 3 + 0]); + newNormals.push(geom.vertexNormals[geom.verticesIndices[i + 2] * 3 + 1]); + newNormals.push(geom.vertexNormals[geom.verticesIndices[i + 2] * 3 + 2]); + newTexCoords.push(geom.texCoords[geom.verticesIndices[i + 2] * 2 + 0]); + newTexCoords.push(geom.texCoords[geom.verticesIndices[i + 2] * 2 + 1]); + } + + newGeom.vertices = newVerts; + newGeom.vertexNormals = newNormals; + newGeom.verticesIndices = newFaces; + newGeom.setTexCoords(newTexCoords); + + outGeom.set(newGeom); + } +} + + +}; + +Ops.Gl.Geometry.DivideGeometry.prototype = new CABLES.Op(); +CABLES.OPS["ab0c768e-e684-47ba-b11f-f95d86532df2"]={f:Ops.Gl.Geometry.DivideGeometry,objName:"Ops.Gl.Geometry.DivideGeometry"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.FlipNormals +// +// ************************************************************** + +Ops.Gl.Geometry.FlipNormals = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + geometry = op.inObject("Geometry"), + outGeom = op.outObject("Result"), + doFlip = op.inValueBool("Flip", true), + doNormalize = op.inValueBool("Normalize", true); + +doFlip.onChange = + doNormalize.onChange = + geometry.onChange = flip; + +function flip() +{ + let oldGeom = geometry.get(); + + if (!oldGeom) + { + outGeom.set(null); + return; + } + + let geom = oldGeom.copy(); + + if (doFlip.get()) + { + for (let i = 0; i < geom.vertexNormals.length; i++) + geom.vertexNormals[i] *= -1; + + if (doNormalize.get()) + { + let vec = vec3.create(); + + for (let i = 0; i < geom.vertexNormals.length; i += 3) + { + vec3.set(vec, + geom.vertexNormals[i + 0], + geom.vertexNormals[i + 1], + geom.vertexNormals[i + 2]); + vec3.normalize(vec, vec); + + geom.vertexNormals[i + 0] = vec[0]; + geom.vertexNormals[i + 1] = vec[1]; + geom.vertexNormals[i + 2] = vec[2]; + } + } + } + + outGeom.set(geom); +} + + +}; + +Ops.Gl.Geometry.FlipNormals.prototype = new CABLES.Op(); +CABLES.OPS["0055f588-dde6-4232-958b-4c19cdc67abd"]={f:Ops.Gl.Geometry.FlipNormals,objName:"Ops.Gl.Geometry.FlipNormals"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.FreezeMeshes +// +// ************************************************************** + +Ops.Gl.Geometry.FreezeMeshes = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inCapture = op.inTriggerButton("Capture"), + outGeom = op.outObject("Geometry", null, "geometry"), + next = op.outTrigger("Next"); + +const cgl = op.patch.cgl; +let shouldCapture = false; +let geom = null; + +inCapture.onTriggered = () => +{ + shouldCapture = true; + if (shouldCapture) + { + geom = new CGL.Geometry(); + + const old = CGL.Mesh.prototype.render; + CGL.Mesh.prototype.render = meshCapture; + + next.trigger(); + + CGL.Mesh.prototype.render = old; + shouldCapture = false; + + // geom.unIndex(false, true); + + outGeom.set(null); + outGeom.set(geom); + } +}; + +function meshCapture() +{ + if (!this._geom || !this._geom.copy) + { + return; + } + + const g = this._geom.copy(); + const normalMat = mat4.create(); + mat4.invert(normalMat, cgl.mMatrix); + mat4.transpose(normalMat, normalMat); + + for (let i = 0; i < g.vertices.length; i += 3) + { + const v = [g.vertices[i + 0], g.vertices[i + 1], g.vertices[i + 2]]; + + vec3.transformMat4(v, v, cgl.mMatrix); + + g.vertices[i + 0] = v[0]; + g.vertices[i + 1] = v[1]; + g.vertices[i + 2] = v[2]; + + // ---------- + + const vn = [g.vertexNormals[i + 0], g.vertexNormals[i + 1], g.vertexNormals[i + 2], 1]; + vec4.transformMat4(vn, vn, normalMat); + + g.vertexNormals[i + 0] = vn[0]; + g.vertexNormals[i + 1] = vn[1]; + g.vertexNormals[i + 2] = vn[2]; + } + + // g.unIndex(); + geom.merge(g); +} + + +}; + +Ops.Gl.Geometry.FreezeMeshes.prototype = new CABLES.Op(); +CABLES.OPS["6bcd033d-3a20-477f-93f1-33d0c701528a"]={f:Ops.Gl.Geometry.FreezeMeshes,objName:"Ops.Gl.Geometry.FreezeMeshes"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.GeometryBoundingBox +// +// ************************************************************** + +Ops.Gl.Geometry.GeometryBoundingBox = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inGeom = op.inObject("Geometry"), + outBB = op.outObject("Boundings"), + outMinX = op.outNumber("Min X"), + outMinY = op.outNumber("Min Y"), + outMinZ = op.outNumber("Min Z"), + outMaxX = op.outNumber("Max X"), + outMaxY = op.outNumber("Max Y"), + outMaxZ = op.outNumber("Max Z"), + outPoints = op.outArray("MaxMin Points"); + +const points = []; + +inGeom.onChange = () => +{ + const bb = new CGL.BoundingBox(inGeom.get()); + outBB.set(bb); + + outMinX.set(bb._min[0]); + outMinY.set(bb._min[1]); + outMinZ.set(bb._min[2]); + + outMaxX.set(bb._max[0]); + outMaxY.set(bb._max[1]); + outMaxZ.set(bb._max[2]); + + + points.length = 0; + points.push( + // bb._max[0],bb._max[1],bb._max[2], + // bb._min[0],bb._min[1],bb._min[2], + + bb._max[0], bb._max[1], bb._max[2], + bb._max[0], bb._min[1], bb._max[2], + bb._min[0], bb._min[1], bb._max[2], + bb._min[0], bb._max[1], bb._max[2], + + bb._max[0], bb._max[1], bb._min[2], + bb._max[0], bb._min[1], bb._min[2], + bb._min[0], bb._min[1], bb._min[2], + bb._min[0], bb._max[1], bb._min[2], + + bb._center[0], bb._center[1], bb._center[2] + ); + outPoints.set(null); + outPoints.set(points); +}; + + +}; + +Ops.Gl.Geometry.GeometryBoundingBox.prototype = new CABLES.Op(); +CABLES.OPS["7c13487b-87b2-40c9-b363-c5f699968579"]={f:Ops.Gl.Geometry.GeometryBoundingBox,objName:"Ops.Gl.Geometry.GeometryBoundingBox"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.GeometryExtrude +// +// ************************************************************** + +Ops.Gl.Geometry.GeometryExtrude = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inGeom = op.inObject("Geometry", null, "geometry"), + inHeight = op.inFloat("Height", 0.5), + inSmooth = op.inBool("Smooth", true), + inExtrudeWalls = op.inBool("Walls", true), + inCapTop = op.inBool("Top", true), + inCapBottom = op.inBool("Bottom", true), + outGeom = op.outObject("Result Geometry", null, "geometry"); + +function isClockwise(verts) +{ + let sum = 0.0; + for (let i = 0; i < verts.length - 3; i += 3) + { + // Vector v1 = verts[i]; + // Vector v2 = verts[(i + 1) % verts.length]; + sum += (verts[i + 3] - verts[i]) * (verts[i + 3 + 1] + verts[i]); + } + return sum > 0.0; +} + +inSmooth.onChange = +inExtrudeWalls.onChange = +inCapTop.onChange = +inCapBottom.onChange = +inHeight.onChange = +inGeom.onChange = () => +{ + const geom = inGeom.get(); + + if (!geom) + { + outGeom.set(null); + return; + } + + function edgesUsedMulti(idx1, idx2) + { + let count = 0; + for (let i = 0; i < geom.verticesIndices.length; i += 3) + { + if ( + ( + geom.verticesIndices[i] == idx1 || + geom.verticesIndices[i + 1] == idx1 || + geom.verticesIndices[i + 2] == idx1 + ) && + ( + geom.verticesIndices[i] == idx2 || + geom.verticesIndices[i + 1] == idx2 || + geom.verticesIndices[i + 2] == idx2 + )) + { + count++; + if (count == 2) return true; + } + } + + return false; + } + + let verts = []; + const indices = []; + const h = inHeight.get(); + + if (inExtrudeWalls.get()) + for (let i = 0; i < geom.verticesIndices.length; i += 3) + { + const vert1 = geom.verticesIndices[i]; + const vert2 = geom.verticesIndices[i + 1]; + const vert3 = geom.verticesIndices[i + 2]; + + // 1 + if (!edgesUsedMulti(vert1, vert2)) + { + const a = []; + a.push([geom.vertices[vert1 * 3 + 0], geom.vertices[vert1 * 3 + 1], geom.vertices[vert1 * 3 + 2]]); + a.push([geom.vertices[vert1 * 3 + 0], geom.vertices[vert1 * 3 + 1], geom.vertices[vert1 * 3 + 2] + h]); + a.push([geom.vertices[vert2 * 3 + 0], geom.vertices[vert2 * 3 + 1], geom.vertices[vert2 * 3 + 2]]); + + if (!isClockwise(a)) verts = verts.concat(a); + else verts = verts.concat(a.reverse()); + + a.length = 0; + a.push([geom.vertices[vert2 * 3 + 0], geom.vertices[vert2 * 3 + 1], geom.vertices[vert2 * 3 + 2] + h]); + a.push([geom.vertices[vert2 * 3 + 0], geom.vertices[vert2 * 3 + 1], geom.vertices[vert2 * 3 + 2]]); + a.push([geom.vertices[vert1 * 3 + 0], geom.vertices[vert1 * 3 + 1], geom.vertices[vert1 * 3 + 2] + h]); + + if (!isClockwise(a)) verts = verts.concat(a); + else verts = verts.concat(a.reverse()); + } + + // 2 + if (!edgesUsedMulti(vert3, vert2)) + { + const a = []; + a.push([geom.vertices[vert3 * 3 + 0], geom.vertices[vert3 * 3 + 1], geom.vertices[vert3 * 3 + 2]]); + a.push([geom.vertices[vert3 * 3 + 0], geom.vertices[vert3 * 3 + 1], geom.vertices[vert3 * 3 + 2] + h]); + a.push([geom.vertices[vert2 * 3 + 0], geom.vertices[vert2 * 3 + 1], geom.vertices[vert2 * 3 + 2]]); + + if (isClockwise(a)) verts = verts.concat(a); + else verts = verts.concat(a.reverse()); + + a.length = 0; + + a.push([geom.vertices[vert2 * 3 + 0], geom.vertices[vert2 * 3 + 1], geom.vertices[vert2 * 3 + 2] + h]); + a.push([geom.vertices[vert2 * 3 + 0], geom.vertices[vert2 * 3 + 1], geom.vertices[vert2 * 3 + 2]]); + a.push([geom.vertices[vert3 * 3 + 0], geom.vertices[vert3 * 3 + 1], geom.vertices[vert3 * 3 + 2] + h]); + + if (isClockwise(a)) verts = verts.concat(a); + else verts = verts.concat(a.reverse()); + } + // 3 + + if (!edgesUsedMulti(vert3, vert1)) + { + const a = []; + a.push([geom.vertices[vert3 * 3 + 0], geom.vertices[vert3 * 3 + 1], geom.vertices[vert3 * 3 + 2]]); + a.push([geom.vertices[vert3 * 3 + 0], geom.vertices[vert3 * 3 + 1], geom.vertices[vert3 * 3 + 2] + h]); + a.push([geom.vertices[vert1 * 3 + 0], geom.vertices[vert1 * 3 + 1], geom.vertices[vert1 * 3 + 2]]); + + if (!isClockwise(a)) verts = verts.concat(a); + else verts = verts.concat(a.reverse()); + + a.length = 0; + + a.push([geom.vertices[vert1 * 3 + 0], geom.vertices[vert1 * 3 + 1], geom.vertices[vert1 * 3 + 2] + h]); + a.push([geom.vertices[vert1 * 3 + 0], geom.vertices[vert1 * 3 + 1], geom.vertices[vert1 * 3 + 2]]); + a.push([geom.vertices[vert3 * 3 + 0], geom.vertices[vert3 * 3 + 1], geom.vertices[vert3 * 3 + 2] + h]); + + if (!isClockwise(a)) verts = verts.concat(a); + else verts = verts.concat(a.reverse()); + } + } + + const newGeom = CGL.Geometry.buildFromFaces(verts, "extrude", true); + + newGeom.calculateNormals(); + newGeom.calcTangentsBitangents(); + + if (inCapBottom.get()) + { + newGeom.merge(geom); + } + + if (inCapTop.get()) + { + const flippedgeo = geom.copy(); + + for (let i = 0; i < flippedgeo.vertices.length; i += 3) + flippedgeo.vertices[i + 2] += h; + + flippedgeo.flipVertDir(); + flippedgeo.flipNormals(); + newGeom.merge(flippedgeo); + } + + newGeom.flipVertDir(); + + if (!inSmooth.get()) + { + newGeom.unIndex(); + newGeom.calculateNormals({ "forceZUp": true }); + newGeom.flipNormals(); + } + + outGeom.set(null); + outGeom.set(newGeom); +}; + + +}; + +Ops.Gl.Geometry.GeometryExtrude.prototype = new CABLES.Op(); +CABLES.OPS["64a34a29-000d-4350-875f-5b72b97a314f"]={f:Ops.Gl.Geometry.GeometryExtrude,objName:"Ops.Gl.Geometry.GeometryExtrude"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.GeometryInfo +// +// ************************************************************** + +Ops.Gl.Geometry.GeometryInfo = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + geometry = op.inObject("Geometry", null, "geometry"), + outIndexed = op.outBoolNum("Indexed", false), + outFaces = op.outNumber("Faces"), + outIndices = op.outNumber("Indices"), + outVertices = op.outNumber("Vertices"), + outNormals = op.outNumber("Normals"), + outTexCoords = op.outNumber("TexCoords"), + outTangents = op.outNumber("Tangents"), + outBiTangents = op.outNumber("BiTangents"), + outVertexColors = op.outNumber("VertexColors"), + outAttribs = op.outNumber("Other Attributes"); + +geometry.onLinkChanged = () => +{ +}; + +geometry.onChange = function () +{ + let geom = geometry.get(); + if (geom) + { + const info = geom.getInfo(); + outFaces.set(info.numFaces); + outIndices.set(info.indices || info.indices); + outVertices.set(info.numVerts); + outNormals.set(info.numNormals); + outTexCoords.set(info.numTexCoords); + outTangents.set(info.numTangents); + outBiTangents.set(info.numBiTangents); + outVertexColors.set(info.numVertexColors); + outAttribs.set(info.numAttribs); + outIndexed.set(info.isIndexed); + } + else + { + outIndexed.set(null); + outFaces.set(null); + outVertices.set(null); + outNormals.set(null); + outTexCoords.set(null); + outTangents.set(null); + outBiTangents.set(null); + outVertexColors.set(null); + outAttribs.set(null); + } +}; + + +}; + +Ops.Gl.Geometry.GeometryInfo.prototype = new CABLES.Op(); +CABLES.OPS["a9208e84-e957-43ac-9a79-9c719eff95eb"]={f:Ops.Gl.Geometry.GeometryInfo,objName:"Ops.Gl.Geometry.GeometryInfo"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.GeometryMerge +// +// ************************************************************** + +Ops.Gl.Geometry.GeometryMerge = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inGeom = op.inObject("Geometry"), + inGeom2 = op.inObject("Geometry 2"), + inMerge = op.inTriggerButton("Merge"), + inReset = op.inTriggerButton("Reset"), + outGeom = op.outObject("Geometry Result"); + +const geom = new CGL.Geometry(op.name); + +outGeom.set(geom); + +inReset.onTriggered = function () +{ + geom.clear(); + outGeom.set(null); + outGeom.set(geom); +}; + +inMerge.onTriggered = function () +{ + if (inGeom.get() || inGeom2.get()) + { + if (inGeom.get())geom.merge(inGeom.get()); + if (inGeom2.get())geom.merge(inGeom2.get()); + outGeom.set(null); + outGeom.set(geom); + } +}; + + +}; + +Ops.Gl.Geometry.GeometryMerge.prototype = new CABLES.Op(); +CABLES.OPS["f915eaab-92df-495e-84ed-500ec301b6f7"]={f:Ops.Gl.Geometry.GeometryMerge,objName:"Ops.Gl.Geometry.GeometryMerge"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.GeometryMergeSimple +// +// ************************************************************** + +Ops.Gl.Geometry.GeometryMergeSimple = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inGeom = op.inObject("Geometry"), + inGeom2 = op.inObject("Geometry 2"), + outGeom = op.outObject("Geometry Result"); + +let geom = new CGL.Geometry(op.name); +outGeom.set(geom); + +inGeom.onChange = +inGeom2.onChange = +function () +{ + if (inGeom.get() || inGeom2.get()) + { + geom = new CGL.Geometry(op.name); + if (inGeom.get()) + { + geom = inGeom.get().copy(); + } + if (inGeom2.get())geom.merge(inGeom2.get()); + outGeom.set(null); + outGeom.set(geom); + } +}; + + +}; + +Ops.Gl.Geometry.GeometryMergeSimple.prototype = new CABLES.Op(); +CABLES.OPS["e9a6c398-b6f2-4c53-a7ea-47aa835c6938"]={f:Ops.Gl.Geometry.GeometryMergeSimple,objName:"Ops.Gl.Geometry.GeometryMergeSimple"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.GeometryPoints +// +// ************************************************************** + +Ops.Gl.Geometry.GeometryPoints = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + geometry = op.inObject("Geometry"), + outFaces = op.outArray("Faces", 3), + outVertices = op.outArray("Vertices", 3), + outNormals = op.outArray("Normals", 3), + outTextcoords = op.outArray("TexCoords", 2), + outVertexColors = op.outArray("Vertex Colors", 4), + outTangents = op.outArray("Tangents", 3), + outBiTangents = op.outArray("BiTangents", 3); + +geometry.onChange = function () +{ + let geom = geometry.get(); + if (!geom) return; + + // convert float32array to array + let verts = Array.prototype.slice.call(geom.vertices); + + outVertices.set(verts); + outFaces.set(geom.verticesIndices); + outTextcoords.set(geom.texCoords); + outNormals.set(geom.vertexNormals); + outTangents.set(geom.tangents); + outBiTangents.set(geom.biTangents); + outVertexColors.set(geom.vertexColors); +}; + + +}; + +Ops.Gl.Geometry.GeometryPoints.prototype = new CABLES.Op(); +CABLES.OPS["b215118b-de1f-4be9-8890-d07a2ecff010"]={f:Ops.Gl.Geometry.GeometryPoints,objName:"Ops.Gl.Geometry.GeometryPoints"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.GeometryToObj +// +// ************************************************************** + +Ops.Gl.Geometry.GeometryToObj = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inGeo = op.inObject("Geometry", null, "geometry"), + outStr = op.outString("Obj"); + +function decimal(n) +{ + return Math.round(n * 10000000) / 10000000; +} + +inGeo.onChange = () => +{ + const geom = inGeo.get(); + + if (!geom) + { + outStr.set(null); + return; + } + + let str = "# made with cables.gl".endl().endl(); + + str += "# " + JSON.stringify(geom.getInfo()); + str += "".endl(); + str += "".endl(); + + // vertices + for (let i = 0; i < geom.vertices.length; i += 3) + { + str += "v " + decimal(geom.vertices[i + 0]) + " " + decimal(geom.vertices[i + 1]) + " " + decimal(geom.vertices[i + 2]) + "".endl(); + } + + str += "".endl(); + + // normals + for (let i = 0; i < geom.vertexNormals.length; i += 3) + { + str += "vn " + decimal(geom.vertexNormals[i + 0]) + " " + decimal(geom.vertexNormals[i + 1]) + " " + decimal(geom.vertexNormals[i + 2]) + "".endl(); + } + + str += "".endl(); + + // texcoords + for (let i = 0; i < geom.texCoords.length; i += 2) + { + str += "vt " + decimal(geom.texCoords[i + 0]) + " " + decimal(geom.texCoords[i + 1]) + " 0".endl(); + } + + str += "".endl(); + + // faces + if (geom.verticesIndices.length) + { + for (let i = 0; i < geom.verticesIndices.length; i += 3) + { + str += "f "; + for (let j = 0; j < 3; j++) + { + str += (geom.verticesIndices[i + j] + 1) + "/" + (geom.verticesIndices[i + j] + 1) + "/" + (geom.verticesIndices[i + j] + 1) + " "; + } + str += "".endl(); + } + } + else + { + for (let i = 0; i < geom.vertices.length / 3 - 1; i += 3) + { + str += "f " + i + " " + (i + 1) + " " + (i + 2) + " ".endl(); + } + } + + // str += "".endl(); + + outStr.set(str); +}; + + +}; + +Ops.Gl.Geometry.GeometryToObj.prototype = new CABLES.Op(); +CABLES.OPS["3890b676-9ba6-42c1-9a57-659b74958e20"]={f:Ops.Gl.Geometry.GeometryToObj,objName:"Ops.Gl.Geometry.GeometryToObj"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.GeometryUnIndex +// +// ************************************************************** + +Ops.Gl.Geometry.GeometryUnIndex = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + geometry = op.inObject("Geometry"), + result = op.outObject("Result"); + +geometry.onChange = function () +{ + let geom = geometry.get(); + + if (geom) + { + if (!geom.isIndexed()) + { + result.set(geom); + return; + } + + const newGeom = geom.copy(); + newGeom.unIndex(false, true); + result.set(newGeom); + } + else result.set(null); +}; + + +}; + +Ops.Gl.Geometry.GeometryUnIndex.prototype = new CABLES.Op(); +CABLES.OPS["b0b2430c-5206-4d1f-a0a6-bc5d79a29027"]={f:Ops.Gl.Geometry.GeometryUnIndex,objName:"Ops.Gl.Geometry.GeometryUnIndex"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.ReverseVertices +// +// ************************************************************** + +Ops.Gl.Geometry.ReverseVertices = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + geometry = op.inObject("Geometry"), + outGeom = op.outObject("Result"), + doFlip = op.inValueBool("Flip", true); + +doFlip.onChange = + geometry.onChange = flip; + +function flip() +{ + let oldGeom = geometry.get(); + + if (!oldGeom) + { + outGeom.set(null); + return; + } + + let geom = oldGeom.copy(); + + if(doFlip.get())geom.flipVertDir(); + + outGeom.set(null); + outGeom.set(geom); +} + + +}; + +Ops.Gl.Geometry.ReverseVertices.prototype = new CABLES.Op(); +CABLES.OPS["548079e7-616d-4f7a-98a0-509c9c7bc36d"]={f:Ops.Gl.Geometry.ReverseVertices,objName:"Ops.Gl.Geometry.ReverseVertices"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.ScaleGeometry +// +// ************************************************************** + +Ops.Gl.Geometry.ScaleGeometry = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let geometry = op.inObject("Geometry"); +let scale = op.inValue("Scale", 1); +let outGeom = op.outObject("Result"); + +scale.onChange = geometry.onChange = update; + +function update() +{ + let oldGeom = geometry.get(); + + if (oldGeom) + { + let geom = oldGeom.copy(); + let rotVec = vec3.create(); + let emptyVec = vec3.create(); + let transVec = vec3.create(); + let centerVec = vec3.create(); + let s = scale.get(); + + for (let i = 0; i < geom.vertices.length; i += 3) + { + geom.vertices[i + 0] *= s; + geom.vertices[i + 1] *= s; + geom.vertices[i + 2] *= s; + } + + outGeom.set(geom); + } + else outGeom.set(null); +} + + +}; + +Ops.Gl.Geometry.ScaleGeometry.prototype = new CABLES.Op(); +CABLES.OPS["7730e67b-5916-4481-bcd1-54fa6e3a1d02"]={f:Ops.Gl.Geometry.ScaleGeometry,objName:"Ops.Gl.Geometry.ScaleGeometry"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.SortGeometryAxis +// +// ************************************************************** + +Ops.Gl.Geometry.SortGeometryAxis = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + SORT_RANDOM = "Random", + SORT_X = "X Axis", + SORT_Y = "Y Axis", + SORT_Z = "Z Axis", + SORT_NONE = "None", + + geometry = op.inObject("Geometry"), + sorting = op.inValueSelect("Sort", [SORT_RANDOM, SORT_X, SORT_Y, SORT_Z, SORT_NONE], SORT_X), + reverse = op.inValueBool("Reverse", false), + outGeom = op.outObject("Result"); + +reverse.onChange = + geometry.onChange = + sorting.onChange = update; + +function update() +{ + if (geometry.get()) + { + const geom = geometry.get(); + let faces = []; + faces.length = geom.verticesIndices.length / 3; + + for (let i = 0; i < geom.verticesIndices.length; i += 3) + { + const face = [0, 0, 0]; + face[0] = geom.verticesIndices[i + 0]; + face[1] = geom.verticesIndices[i + 1]; + face[2] = geom.verticesIndices[i + 2]; + faces[i / 3] = face; + } + + if (sorting.get() == SORT_RANDOM) + { + faces = CABLES.shuffleArray(faces); + } + else + if (sorting.get() == SORT_Y) + { + faces.sort(function (a, b) + { + let avgA = 0; + avgA += geom.vertices[a[0] * 3 + 1]; + avgA += geom.vertices[a[1] * 3 + 1]; + avgA += geom.vertices[a[2] * 3 + 1]; + avgA /= 3; + + let avgB = 0; + avgB += geom.vertices[b[0] * 3 + 1]; + avgB += geom.vertices[b[1] * 3 + 1]; + avgB += geom.vertices[b[2] * 3 + 1]; + avgB /= 3; + + return avgA - avgB; + }); + } + else + if (sorting.get() == SORT_X) + { + faces.sort(function (a, b) + { + let avgA = 0; + avgA += geom.vertices[a[0] * 3 + 0]; + avgA += geom.vertices[a[1] * 3 + 0]; + avgA += geom.vertices[a[2] * 3 + 0]; + avgA /= 3; + + let avgB = 0; + avgB += geom.vertices[b[0] * 3 + 0]; + avgB += geom.vertices[b[1] * 3 + 0]; + avgB += geom.vertices[b[2] * 3 + 0]; + avgB /= 3; + + return avgA - avgB; + }); + } + else + if (sorting.get() == SORT_Z) + { + faces.sort(function (a, b) + { + let avgA = 0; + avgA += geom.vertices[a[0] * 3 + 2]; + avgA += geom.vertices[a[1] * 3 + 2]; + avgA += geom.vertices[a[2] * 3 + 2]; + avgA /= 3; + + let avgB = 0; + avgB += geom.vertices[b[0] * 3 + 2]; + avgB += geom.vertices[b[1] * 3 + 2]; + avgB += geom.vertices[b[2] * 3 + 2]; + avgB /= 3; + + return avgA - avgB; + }); + } + else + { + if (sorting.get() != SORT_NONE) op.error("No sorting found", sorting.get()); + } + + const newGeom = new CGL.Geometry(op.name); + const newVerts = []; + const newFaces = []; + const newNormals = []; + const newTexCoords = []; + const newTangents = []; + const newBiTangents = []; + + if (reverse.get()) + { + faces = faces.reverse(); + } + + faces = [].concat.apply([], faces); + + for (let i = 0; i < faces.length; i += 3) + { + newFaces.push( + newVerts.length / 3); + newVerts.push( + geom.vertices[faces[i + 0] * 3 + 0], + geom.vertices[faces[i + 0] * 3 + 1], + geom.vertices[faces[i + 0] * 3 + 2]); + newNormals.push( + geom.vertexNormals[faces[i + 0] * 3 + 0], + geom.vertexNormals[faces[i + 0] * 3 + 1], + geom.vertexNormals[faces[i + 0] * 3 + 2]); + newTexCoords.push( + geom.texCoords[faces[i + 0] * 2 + 0], + geom.texCoords[faces[i + 0] * 2 + 1]); + + if (geom.tangents) + newTangents.push( + geom.tangents[faces[i + 0] * 3 + 0], + geom.tangents[faces[i + 0] * 3 + 1], + geom.tangents[faces[i + 0] * 3 + 2]); + if (geom.biTangents) + newBiTangents.push( + geom.biTangents[faces[i + 0] * 3 + 0], + geom.biTangents[faces[i + 0] * 3 + 1], + geom.biTangents[faces[i + 0] * 3 + 2]); + + newFaces.push( + newVerts.length / 3); + newVerts.push( + geom.vertices[faces[i + 1] * 3 + 0], + geom.vertices[faces[i + 1] * 3 + 1], + geom.vertices[faces[i + 1] * 3 + 2]); + newNormals.push( + geom.vertexNormals[faces[i + 1] * 3 + 0], + geom.vertexNormals[faces[i + 1] * 3 + 1], + geom.vertexNormals[faces[i + 1] * 3 + 2]); + newTexCoords.push( + geom.texCoords[faces[i + 1] * 2 + 0], + geom.texCoords[faces[i + 1] * 2 + 1]); + if (geom.tangents) + newTangents.push( + geom.tangents[faces[i + 1] * 3 + 0], + geom.tangents[faces[i + 1] * 3 + 1], + geom.tangents[faces[i + 1] * 3 + 2]); + if (geom.biTangents) + newBiTangents.push( + geom.biTangents[faces[i + 1] * 3 + 0], + geom.biTangents[faces[i + 1] * 3 + 1], + geom.biTangents[faces[i + 1] * 3 + 2]); + + newFaces.push( + newVerts.length / 3); + newVerts.push( + geom.vertices[faces[i + 2] * 3 + 0], + geom.vertices[faces[i + 2] * 3 + 1], + geom.vertices[faces[i + 2] * 3 + 2]); + newNormals.push( + geom.vertexNormals[faces[i + 2] * 3 + 0], + geom.vertexNormals[faces[i + 2] * 3 + 1], + geom.vertexNormals[faces[i + 2] * 3 + 2]); + newTexCoords.push( + geom.texCoords[faces[i + 2] * 2 + 0], + geom.texCoords[faces[i + 2] * 2 + 1]); + if (geom.tangents) + newTangents.push( + geom.tangents[faces[i + 2] * 3 + 0], + geom.tangents[faces[i + 2] * 3 + 1], + geom.tangents[faces[i + 2] * 3 + 2]); + if (geom.biTangents) + newBiTangents.push( + geom.biTangents[faces[i + 2] * 3 + 0], + geom.biTangents[faces[i + 2] * 3 + 1], + geom.biTangents[faces[i + 2] * 3 + 2]); + } + + newGeom.vertices = newVerts; + newGeom.vertexNormals = newNormals; + newGeom.verticesIndices = newFaces; + newGeom.texCoords = newTexCoords; + newGeom.tangents = newTangents; + newGeom.biTangents = newBiTangents; + + outGeom.set(null); + outGeom.set(newGeom); + } +} + + +}; + +Ops.Gl.Geometry.SortGeometryAxis.prototype = new CABLES.Op(); +CABLES.OPS["8b0a635c-83f0-4d95-9b9c-1b5ca55c6724"]={f:Ops.Gl.Geometry.SortGeometryAxis,objName:"Ops.Gl.Geometry.SortGeometryAxis"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.SvgPathToGeometry_v2 +// +// ************************************************************** + +Ops.Gl.Geometry.SvgPathToGeometry_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr = op.inString("SVG Path"), + inStepSize = op.inFloat("Bezier Stepsize", 3), + inRescale = op.inFloat("Rescale", 1), + outGeom = op.outObject("Geometry", null, "geometry"); + +inStepSize.onChange = +inRescale.onChange = +inStr.onChange = () => +{ + let str = inStr.get(); + + if (!str || str.length < 2) + { + outGeom.set(null); + return; + } + + str = str.replace(/([A-Z,a-z])/g, " $1 "); + + const cmds = fromPathToArray(str); + + // create a list of closed contours + const polys = []; + cmds.forEach(({ type, x, y, x1, y1, x2, y2 }) => + { + switch (type) + { + case "M": + polys.push(new Polygon()); + polys[polys.length - 1].moveTo({ x, y }); + break; + case "L": + polys[polys.length - 1].moveTo({ x, y }); + break; + case "C": + polys[polys.length - 1].cubicTo({ x, y }, { "x": x1, "y": y1 }, { "x": x2, "y": y2 }); + break; + case "Q": + polys[polys.length - 1].conicTo({ x, y }, { "x": x1, "y": y1 }); + break; + case "Z": + polys[polys.length - 1].close(); + break; + } + }); + + // sort contours by descending area + polys.sort((a, b) => { return Math.abs(b.area) - Math.abs(a.area); }); + // classify contours to find holes and their 'parents' + const root = []; + for (let i = 0; i < polys.length; ++i) + { + let parent = null; + for (let j = i - 1; j >= 0; --j) + { + // a contour is a hole if it is inside its parent and has different winding + if (polys[j].inside(polys[i].points[0]) && polys[i].area * polys[j].area < 0) + { + parent = polys[j]; + break; + } + } + if (parent) + { + parent.children.push(polys[i]); + } + else + { + root.push(polys[i]); + } + } + + const totalPoints = polys.reduce((sum, p) => { return sum + p.points.length; }, 0); + const vertexData = new Float32Array(totalPoints * 2); + let vertexCount = 0; + const indices = []; + + function process(poly) + { + // construct input for earcut + const coords = []; + const holes = []; + + poly.points.forEach(({ x, y }) => { return coords.push(x, y); }); + + poly.children.forEach((child) => + { + // children's children are new, separate shapes + child.children.forEach(process); + + holes.push(coords.length / 2); + child.points.forEach(({ x, y }) => { return coords.push(x, y); }); + }); + + // add vertex data + vertexData.set(coords, vertexCount * 2); + // add index data + earcut(coords, holes).forEach((i) => { return indices.push(i + vertexCount); }); + vertexCount += coords.length / 2; + } + + root.forEach(process); + + const finalVertexData = new Float32Array(totalPoints * 3); + + let max = -99999; + + for (let i = 0; i < finalVertexData.length / 3; i++) + { + finalVertexData[i * 3 + 0] = vertexData[i * 2 + 0]; + finalVertexData[i * 3 + 1] = vertexData[i * 2 + 1] * -1; + max = Math.max(finalVertexData[i * 3 + 1], max); + + finalVertexData[i * 3 + 2] = 0; + } + + let resc = inRescale.get(); + + let geom = new CGL.Geometry("circle"); + geom.setVertices(finalVertexData); + geom.verticesIndices = indices; + + if (resc != 0) + { + const bounds = geom.getBounds(); + for (let i = 0; i < finalVertexData.length / 3; i++) + { + finalVertexData[i * 3 + 0] = (finalVertexData[i * 3 + 0] / (bounds.size[0] / 2)) * resc; + finalVertexData[i * 3 + 1] = (finalVertexData[i * 3 + 1] / (bounds.size[0] / 2)) * resc; + } + geom.setVertices(finalVertexData); + } + + geom.mapTexCoords2d(); + geom.flipVertDir(); + geom.calculateNormals(); + geom.calcTangentsBitangents(); + + outGeom.set(geom); +}; + +const PATH_COMMANDS = { + "M": ["x", "y"], + "m": ["dx", "dy"], + "H": ["x"], + "h": ["dx"], + "V": ["y"], + "v": ["dy"], + "L": ["x", "y"], + "l": ["dx", "dy"], + "Z": [], + "C": ["x1", "y1", "x2", "y2", "x", "y"], + "c": ["dx1", "dy1", "dx2", "dy2", "dx", "dy"], + "S": ["x2", "y2", "x", "y"], + "s": ["dx2", "dy2", "dx", "dy"], + "Q": ["x1", "y1", "x", "y"], + "q": ["dx1", "dy1", "dx", "dy"], + "T": ["x", "y"], + "t": ["dx", "dy"], + "A": ["rx", "ry", "rotation", "large-arc", "sweep", "x", "y"], + "a": ["rx", "ry", "rotation", "large-arc", "sweep", "dx", "dy"] +}; + +function fromPathToArray(path) +{ + const items = path.replace(/[\n\r]/g, "") + .replace(/-/g, " -") + .replace(/(\d*\.)(\d+)(?=\.)/g, "$1$2 ") + .trim() + .split(/\s*,|\s+/); + + const segments = []; + let currentCommand = ""; + let currentElement = {}; + while (items.length > 0) + { + let it = items.shift(); + if (PATH_COMMANDS.hasOwnProperty(it)) + { + currentCommand = it; + } + else + { + items.unshift(it); + } + + currentElement = { "type": currentCommand }; + PATH_COMMANDS[currentCommand].forEach((prop) => + { + it = items.shift(); // TODO sanity check + currentElement[prop] = parseFloat(it); + }); + if (currentCommand === "M") + { + currentCommand = "L"; + } + else if (currentCommand === "m") + { + currentCommand = "l"; + } + segments.push(currentElement); + } + return segments; +} + +// https://stackoverflow.com/questions/50554803/triangulate-path-data-from-opentype-js-using-earcut + +const MAX_BEZIER_STEPS = 15; +// this is for inside checks - doesn't have to be particularly +// small because glyphs have finite resolution +const EPSILON = 1e-6; + +class Polygon +{ + constructor() + { + this.points = []; + this.children = []; + this.area = 0.0; + + this.BEZIER_STEP_SIZE = inStepSize.get(); + } + + moveTo(p) + { + this.points.push(p); + } + + lineTo(p) + { + this.points.push(p); + } + + close() + { + let cur = this.points[this.points.length - 1]; + this.points.forEach((next) => + { + this.area += 0.5 * cross(cur, next); + cur = next; + }); + } + + conicTo(p, p1) + { + const p0 = this.points[this.points.length - 1]; + const dist = distance(p0, p1) + distance(p1, p); + const steps = Math.max(2, Math.min(MAX_BEZIER_STEPS, dist / this.BEZIER_STEP_SIZE)); + for (let i = 1; i <= steps; ++i) + { + const t = i / steps; + this.points.push(lerp(lerp(p0, p1, t), lerp(p1, p, t), t)); + } + } + + cubicTo(p, p1, p2) + { + const p0 = this.points[this.points.length - 1]; + const dist = distance(p0, p1) + distance(p1, p2) + distance(p2, p); + const steps = Math.max(2, Math.min(MAX_BEZIER_STEPS, dist / this.BEZIER_STEP_SIZE)); + for (let i = 1; i <= steps; ++i) + { + const t = i / steps; + const a = lerp(lerp(p0, p1, t), lerp(p1, p2, t), t); + const b = lerp(lerp(p1, p2, t), lerp(p2, p, t), t); + this.points.push(lerp(a, b, t)); + } + } + + inside(p) + { + let count = 0, cur = this.points[this.points.length - 1]; + this.points.forEach((next) => + { + const p0 = (cur.y < next.y ? cur : next); + const p1 = (cur.y < next.y ? next : cur); + if (p0.y < p.y + EPSILON && p1.y > p.y + EPSILON) + { + if ((p1.x - p0.x) * (p.y - p0.y) > (p.x - p0.x) * (p1.y - p0.y)) + { + count += 1; + } + } + cur = next; + }); + return (count % 2) !== 0; + } +} + +function distance(p1, p2) +{ + const dx = p1.x - p2.x, dy = p1.y - p2.y; + return Math.sqrt(dx * dx + dy * dy); +} + +function lerp(p1, p2, t) +{ + return { "x": (1 - t) * p1.x + t * p2.x, "y": (1 - t) * p1.y + t * p2.y }; +} + +function cross(p1, p2) +{ + return p1.x * p2.y - p1.y * p2.x; +} + + +}; + +Ops.Gl.Geometry.SvgPathToGeometry_v2.prototype = new CABLES.Op(); +CABLES.OPS["4267b3e7-1285-4a3e-acc8-ea92a72a6bc0"]={f:Ops.Gl.Geometry.SvgPathToGeometry_v2,objName:"Ops.Gl.Geometry.SvgPathToGeometry_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Geometry.TransformGeometry +// +// ************************************************************** + +Ops.Gl.Geometry.TransformGeometry = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + geometry = op.inObject("Geometry"), + transX = op.inValue("Translate X"), + transY = op.inValue("Translate Y"), + transZ = op.inValue("Translate Z"), + scaleX = op.inValueSlider("Scale X", 1), + scaleY = op.inValueSlider("Scale Y", 1), + scaleZ = op.inValueSlider("Scale Z", 1), + rotX = op.inValue("Rotation X"), + rotY = op.inValue("Rotation Y"), + rotZ = op.inValue("Rotation Z"), + outGeom = op.outObject("Result", null, "geometry"); + +transX.onChange = + transY.onChange = + transZ.onChange = + scaleX.onChange = + scaleY.onChange = + scaleZ.onChange = + rotX.onChange = + rotY.onChange = + rotZ.onChange = + geometry.onChange = update; + +const rotVec = vec3.create(); +const emptyVec = vec3.create(); +const transVec = vec3.create(); +const centerVec = vec3.create(); + +function update() +{ + const oldGeom = geometry.get(); + const i = 0; + + if (oldGeom) + { + const geom = oldGeom.copy(); + + for (let i = 0; i < geom.vertices.length; i += 3) + { + geom.vertices[i + 0] *= scaleX.get(); + geom.vertices[i + 1] *= scaleY.get(); + geom.vertices[i + 2] *= scaleZ.get(); + + geom.vertices[i + 0] += transX.get(); + geom.vertices[i + 1] += transY.get(); + geom.vertices[i + 2] += transZ.get(); + } + + for (let i = 0; i < geom.vertices.length; i += 3) + { + vec3.set(rotVec, + geom.vertices[i + 0], + geom.vertices[i + 1], + geom.vertices[i + 2]); + + vec3.rotateX(rotVec, rotVec, transVec, rotX.get() * CGL.DEG2RAD); + vec3.rotateY(rotVec, rotVec, transVec, rotY.get() * CGL.DEG2RAD); + vec3.rotateZ(rotVec, rotVec, transVec, rotZ.get() * CGL.DEG2RAD); + + geom.vertices[i + 0] = rotVec[0]; + geom.vertices[i + 1] = rotVec[1]; + geom.vertices[i + 2] = rotVec[2]; + } + + outGeom.set(null); + outGeom.set(geom); + } + else + { + outGeom.set(null); + } +} + + +}; + +Ops.Gl.Geometry.TransformGeometry.prototype = new CABLES.Op(); +CABLES.OPS["9678fee2-5436-499c-b94d-2603cdbeb380"]={f:Ops.Gl.Geometry.TransformGeometry,objName:"Ops.Gl.Geometry.TransformGeometry"}; + + + + +// ************************************************************** +// +// Ops.Gl.GlInfo +// +// ************************************************************** + +Ops.Gl.GlInfo = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const gl = op.patch.cgl.gl; + +let mxsmpl = 0; +if (gl.MAX_SAMPLES !== undefined)mxsmpl = gl.getParameter(gl.MAX_SAMPLES); + +const + outGlVersion = op.outNumber("WebGl Version", gl.getParameter(gl.VERSION)), + outGlslVersion = op.outNumber("GLSL Version", gl.getParameter(gl.SHADING_LANGUAGE_VERSION)), + outFragUnis = op.outNumber("Max Frag uniforms", gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS)), + outVertUnis = op.outNumber("Max Vert uniforms", gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS)), + outTexSize = op.outNumber("Max Texture Size", gl.getParameter(gl.MAX_TEXTURE_SIZE)), + outTexUnits = op.outNumber("Max Texture Units", gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS)), + outVarVec = op.outNumber("Max Varying Vectors", gl.getParameter(gl.MAX_VARYING_VECTORS)), + outMSAA = op.outNumber("Max MSAA Samples", mxsmpl), + outExts = op.outArray("Extensions", gl.getSupportedExtensions()), + outVendor = op.outString("Vendor"), + outRenderer = op.outString("Renderer"), + debugInfo = gl.getExtension("WEBGL_debug_renderer_info"); + +if (debugInfo) +{ + outVendor.set(gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL)); + outRenderer.set(gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL)); +} + + +}; + +Ops.Gl.GlInfo.prototype = new CABLES.Op(); +CABLES.OPS["2a90bd0e-e743-475e-8e19-00793950b531"]={f:Ops.Gl.GlInfo,objName:"Ops.Gl.GlInfo"}; + + + + +// ************************************************************** +// +// Ops.Gl.GlPrimitive +// +// ************************************************************** + +Ops.Gl.GlPrimitive = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Execute"), + next = op.outTrigger("Next"), + + prim = op.inValueSelect("Primitive", ["LINES", "LINE_STRIP", "LINE_LOOP", "POINTS", "TRIANGLES", "TRIANGLE_FAN", "TRIANGLE_STRIP"], "LINES"); +const cgl = op.patch.cgl; + +let glPrim = cgl.gl.LINES; + +prim.onChange = function () +{ + if (prim.get() == "LINES")glPrim = cgl.gl.LINES; + if (prim.get() == "LINE_STRIP")glPrim = cgl.gl.LINE_STRIP; + if (prim.get() == "LINE_LOOP")glPrim = cgl.gl.LINE_LOOP; + if (prim.get() == "POINTS")glPrim = cgl.gl.POINTS; + if (prim.get() == "TRIANGLES")glPrim = cgl.gl.TRIANGLES; + if (prim.get() == "TRIANGLE_FAN")glPrim = cgl.gl.TRIANGLE_FAN; + if (prim.get() == "TRIANGLE_STRIP")glPrim = cgl.gl.TRIANGLE_STRIP; +}; + +exec.onTriggered = function () +{ + let shader = cgl.getShader(); + if (!shader) return; + let oldPrim = shader.glPrimitive; + shader.glPrimitive = glPrim; + + next.trigger(); + + shader.glPrimitive = oldPrim; +}; + + +}; + +Ops.Gl.GlPrimitive.prototype = new CABLES.Op(); +CABLES.OPS["ef0bae7e-32c9-4815-9ac3-9439fc1194ee"]={f:Ops.Gl.GlPrimitive,objName:"Ops.Gl.GlPrimitive"}; + + + + +// ************************************************************** +// +// Ops.Gl.GradientTexture +// +// ************************************************************** + +Ops.Gl.GradientTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inGrad = op.inGradient("Gradient"), + inDir = op.inValueSelect("Direction", ["X", "Y", "Radial"], "X"), + inSmoothstep = op.inValueBool("Smoothstep", false), + inStep = op.inBool("Step", false), + inFlip = op.inBool("Flip", false), + inSRGB = op.inBool("sRGB", false), + inOklab = op.inBool("Oklab", false), + inSize = op.inValueInt("Size", 256), + tfilter = op.inSwitch("filter", ["nearest", "linear", "mipmap"], "linear"), + twrap = op.inValueSelect("wrap", ["clamp to edge", "repeat", "mirrored repeat"], "clamp to edge"), + inGradArray = op.inArray("Gradient Array"), + inRandom = op.inTriggerButton("Randomize Colors"), + outTex = op.outTexture("Texture"), + outColors = op.outArray("Colors", null, 3), + outColorPos = op.outArray("Colors Pos", null, 1); + +const cgl = op.patch.cgl; + +twrap.onChange = + tfilter.onChange = + inStep.onChange = + inFlip.onChange = + inSRGB.onChange = + inOklab.onChange = + inSize.onChange = inGrad.onChange = inSmoothstep.onChange = inDir.onChange = inGradArray.onChange = update; + +inGrad.set("{\"keys\" : [{\"pos\":0,\"r\":0,\"g\":0,\"b\":0},{\"pos\":0.25,\"r\":0,\"g\":0,\"b\":0},{\"pos\":0.75,\"r\":1,\"g\":1,\"b\":1},{\"pos\":1,\"r\":1,\"g\":1,\"b\":1}]}"); + +op.onLoaded = update; + +inRandom.onTriggered = () => +{ + const keys = parseKeys(); + if (keys) + { + keys.forEach((key) => + { + key.r = Math.random(); + key.g = Math.random(); + key.b = Math.random(); + }); + const newKeys = JSON.stringify({ "keys": keys }); + inGrad.set(newKeys); + } +}; + +function rgbToOklab(r, g, b) +{ + let l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b; + let m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b; + let s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b; + l = Math.cbrt(l); m = Math.cbrt(m); s = Math.cbrt(s); + return [ + l * +0.2104542553 + m * +0.7936177850 + s * -0.0040720468, + l * +1.9779984951 + m * -2.4285922050 + s * +0.4505937099, + l * +0.0259040371 + m * +0.7827717662 + s * -0.8086757660 + ]; +} + +function clamp(value, min, max) +{ + return Math.max(Math.min(value, max), min); +} + +function oklabToRGB(L, a, b) +{ + let l = L + a * +0.3963377774 + b * +0.2158037573; + let m = L + a * -0.1055613458 + b * -0.0638541728; + let s = L + a * -0.0894841775 + b * -1.2914855480; + l **= 3; m **= 3; s **= 3; + let r = l * +4.0767416621 + m * -3.3077115913 + s * +0.2309699292; + let g = l * -1.2684380046 + m * +2.6097574011 + s * -0.3413193965; + var b = l * -0.0041960863 + m * -0.7034186147 + s * +1.7076147010; + r = clamp(r, 0, 1); g = clamp(g, 0, 1); b = clamp(b, 0, 1); + return [r, g, b]; +} + +function lin2srgb(r, g, b) +{ + r /= 255; + + const thr = 0.0031308; + + let c_loR = 12.92 * r; + + let c_hiR = 1.055 * Math.pow(r, 0.41666) - 0.055; + return ((r < thr) ? c_loR : c_hiR) * 255; +} + +function update() +{ + const keys = parseKeys(); + if (keys) updateGradient(keys); +} + +function parseKeys() +{ + let keys = null; + op.setUiError("nodata", null); + op.setUiError("parse", null); + + if (Array.isArray(inGradArray.get())) + { + keys = inGradArray.get(); + } + else + { + let grad = null; + if (!inGrad.get() || inGrad.get() === "") + { + op.setUiError("nodata", "gradient no data"); + return null; + } + + try + { + grad = JSON.parse(inGrad.get()); + } + catch (e) + { + op.setUiError("parse", "could not parse gradient data"); + } + + if (!grad || !grad.keys) + { + op.setUiError("nodata", "gradient no data"); + return null; + } + keys = grad.keys; + } + return keys; +} + +function updateGradient(keys) +{ + let width = Math.round(inSize.get()); + if (width < 4) width = 4; + + let selectedWrap = 0; + let selectedFilter = 0; + if (twrap.get() == "repeat") selectedWrap = CGL.Texture.WRAP_REPEAT; + else if (twrap.get() == "mirrored repeat") selectedWrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + else if (twrap.get() == "clamp to edge") selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + if (tfilter.get() == "nearest") selectedFilter = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "linear") selectedFilter = CGL.Texture.FILTER_LINEAR; + else if (tfilter.get() == "mipmap") selectedFilter = CGL.Texture.FILTER_MIPMAP; + + const tex = new CGL.Texture(cgl); + + if (inDir.get() == "X" || inDir.get() == "Y") + { + const pixels = new Uint8Array(width * 4); + + for (let i = 0; i < keys.length - 1; i++) + { + const keyA = keys[i]; + const keyB = keys[i + 1]; + + for (let x = keyA.pos * width; x < keyB.pos * width; x++) + { + let p = CABLES.map(x, keyA.pos * width, keyB.pos * width, 0, 1); + if (inStep.get())p = Math.round(p); + if (inSmoothstep.get()) p = CABLES.smoothStep(p); + x = Math.round(x); + + let xx = x; + if (inFlip.get())xx = width - x - 1; + + if (inOklab.get()) + { + const klabA = rgbToOklab(keyA.r, keyA.g, keyA.b); + const labA_r = klabA[0]; + const labA_g = klabA[1]; + const labA_b = klabA[2]; + + const klabB = rgbToOklab(keyB.r, keyB.g, keyB.b); + const labB_r = klabB[0]; + const labB_g = klabB[1]; + const labB_b = klabB[2]; + + const l = ((p * labB_r + (1.0 - p) * labA_r)); + const a = ((p * labB_g + (1.0 - p) * labA_g)); + const b = ((p * labB_b + (1.0 - p) * labA_b)); + + const pixCol = oklabToRGB(l, a, b); + pixels[xx * 4 + 0] = Math.round(pixCol[0] * 255); + pixels[xx * 4 + 1] = Math.round(pixCol[1] * 255); + pixels[xx * 4 + 2] = Math.round(pixCol[2] * 255); + } + else + { + pixels[xx * 4 + 0] = Math.round((p * keyB.r + (1.0 - p) * keyA.r) * 255); + pixels[xx * 4 + 1] = Math.round((p * keyB.g + (1.0 - p) * keyA.g) * 255); + pixels[xx * 4 + 2] = Math.round((p * keyB.b + (1.0 - p) * keyA.b) * 255); + } + + if (typeof keyA.a !== "undefined" && typeof keyB.a !== "undefined") + { + const alpha = Math.round((p * keyB.a + (1.0 - p) * keyA.a) * 255); + pixels[xx * 4 + 3] = alpha; + } + else + { + pixels[xx * 4 + 3] = Math.round(255); + } + } + } + + if (inSRGB.get()) + for (let i = 0; i < pixels.length; i += 4) + { + pixels[i + 0] = lin2srgb(pixels[i + 0]); + pixels[i + 1] = lin2srgb(pixels[i + 1]); + pixels[i + 2] = lin2srgb(pixels[i + 2]); + } + + if (inDir.get() == "X") tex.initFromData(pixels, width, 1, selectedFilter, selectedWrap); + if (inDir.get() == "Y") tex.initFromData(pixels, 1, width, selectedFilter, selectedWrap); + } + + if (inDir.get() == "Radial") + { + const pixels = new Uint8Array(width * width * 4); + + const animR = new CABLES.Anim(); + const animG = new CABLES.Anim(); + const animB = new CABLES.Anim(); + + for (let i = 0; i < keys.length - 1; i++) + { + animR.setValue(keys[i].pos, keys[i].r); + animG.setValue(keys[i].pos, keys[i].g); + animB.setValue(keys[i].pos, keys[i].b); + } + + for (let x = 0; x < width; x++) + { + for (let y = 0; y < width; y++) + { + const dx = x - (width - 1) / 2; + const dy = y - (width - 1) / 2; + let pos = Math.sqrt(dx * dx + dy * dy) / (width) * 2; + + if (inSmoothstep.get()) pos = CABLES.smoothStep(pos); + + pixels[(x * 4) + (y * 4 * width) + 0] = animR.getValue(pos) * 255; + pixels[(x * 4) + (y * 4 * width) + 1] = animG.getValue(pos) * 255; + pixels[(x * 4) + (y * 4 * width) + 2] = animB.getValue(pos) * 255; + pixels[(x * 4) + (y * 4 * width) + 3] = Math.round(255); + } + } + + if (inSRGB.get()) + for (let i = 0; i < pixels.length; i += 4) + { + pixels[i + 0] = lin2srgb(pixels[i + 0]); + pixels[i + 1] = lin2srgb(pixels[i + 1]); + pixels[i + 2] = lin2srgb(pixels[i + 2]); + } + + tex.initFromData(pixels, width, width, selectedFilter, selectedWrap); + } + + const colorArr = []; + for (let i = 0; i < keys.length - 1; i++) + { + colorArr.push(keys[i].r, keys[i].g, keys[i].b); + } + + const colorPosArr = []; + for (let i = 0; i < keys.length - 1; i++) + { + colorPosArr.push(keys[i].pos); + } + + outColors.set(colorArr); + outColorPos.set(colorPosArr); + + outTex.set(null); + outTex.set(tex); +} + + +}; + +Ops.Gl.GradientTexture.prototype = new CABLES.Op(); +CABLES.OPS["01380a50-2dbb-4465-ae80-86349b0b717a"]={f:Ops.Gl.GradientTexture,objName:"Ops.Gl.GradientTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.GridTransform +// +// ************************************************************** + +Ops.Gl.GridTransform = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Render"), + numX = op.inValueInt("Num X", 5), + numY = op.inValueInt("Num Y", 5), + spaceX = op.inValue("Space X", 1), + spaceY = op.inValue("Space Y", 1), + next = op.outTrigger("Next"), + outIndex = op.outNumber("Index"), + outX = op.outNumber("x index"), + outY = op.outNumber("y index"); + +let matOrig = mat4.create(); +let vec = vec3.create(); + +let cgl = op.patch.cgl; + +render.onTriggered = function () +{ + cgl.pushModelMatrix(); + + mat4.copy(matOrig, cgl.modelMatrix()); + + let mx = spaceX.get(); + let my = spaceY.get(); + + let maxX = Math.floor(numX.get()); + let maxY = Math.floor(numY.get()); + + let alX = ((maxX - 1) * mx) / 2; + let alY = ((maxY - 1) * my) / 2; + + let i = 0; + for (let y = 0; y < maxY; y++) + { + outY.set(y); + + for (let x = 0; x < maxX; x++) + { + vec3.set(vec, + x * mx - alX, + y * my - alY, + 0); + outX.set(x); + mat4.translate(cgl.mMatrix, matOrig, vec); + outIndex.set(i); + i++; + next.trigger(); + } + } + + cgl.popModelMatrix(); +}; + + +}; + +Ops.Gl.GridTransform.prototype = new CABLES.Op(); +CABLES.OPS["242e9cfa-3f83-4ff7-b9e8-1c136938a270"]={f:Ops.Gl.GridTransform,objName:"Ops.Gl.GridTransform"}; + + + + +// ************************************************************** +// +// Ops.Gl.Identity +// +// ************************************************************** + +Ops.Gl.Identity = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe=op.inTrigger("exe"); +const trigger=op.outTrigger('trigger'); +const cgl=op.patch.cgl; + +exe.onTriggered=function() +{ + cgl.pushModelMatrix(); + + mat4.identity(cgl.mMatrix); + trigger.trigger(); + + cgl.popModelMatrix(); +}; + +}; + +Ops.Gl.Identity.prototype = new CABLES.Op(); +CABLES.OPS["59a5a21f-4498-4960-8527-86f75ab5ec11"]={f:Ops.Gl.Identity,objName:"Ops.Gl.Identity"}; + + + + +// ************************************************************** +// +// Ops.Gl.IdentityViewMatrix +// +// ************************************************************** + +Ops.Gl.IdentityViewMatrix = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe=op.inTrigger("exe"); +const trigger=op.outTrigger('trigger'); +const cgl=op.patch.cgl; + +exe.onTriggered=function() +{ + cgl.pushViewMatrix(); + mat4.identity(cgl.vMatrix); + trigger.trigger(); + cgl.popViewMatrix(); +}; + +}; + +Ops.Gl.IdentityViewMatrix.prototype = new CABLES.Op(); +CABLES.OPS["265c70e7-4d20-4ce0-9aa4-2c12ed867e8f"]={f:Ops.Gl.IdentityViewMatrix,objName:"Ops.Gl.IdentityViewMatrix"}; + + + + +// ************************************************************** +// +// Ops.Gl.ImageSequenceAnim_v2 +// +// ************************************************************** + +Ops.Gl.ImageSequenceAnim_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTime = op.inValue("Time"), + inType = op.inSwitch("Unit", ["Seconds", "Frames"], "Seconds"), + fps = op.inValueFloat("FPS", 10), + numX = op.inValueFloat("Num X", 4), + numY = op.inValueFloat("Num Y", 4), + maxFrames = op.inInt("Max Frames", 0), + + texRepeatX = op.outNumber("Repeat X"), + texRepeatY = op.outNumber("Repeat Y"), + texU = op.outNumber("Offset X"), + texV = op.outNumber("Offset Y"), + + outFrame = op.outNumber("Frame"), + outProgress = op.outNumber("Progress"); + +numX.onChange = numY.onChange = setRepeat; + +texU.set(0); +texV.set(0); + +const posX = 0; +const posY = 0; +const lastSwitch = 0; +const frame = 0; +setRepeat(); + +function setRepeat() +{ + texRepeatY.set(1 / numY.get()); + texRepeatX.set(1 / numX.get()); + update(); +} + +inTime.onChange = update; + +function update() +{ + let frame = Math.ceil(Math.abs(inTime.get()) * (fps.get())); + if (inType.get() == "Frames") frame = inTime.get(); + let numFrames = numX.get() * numY.get(); + if (maxFrames.get() !== 0) numFrames = maxFrames.get(); + + frame %= numFrames; + + const row = Math.floor(frame / (numX.get())); + const col = frame - (row * (numX.get())); + + outFrame.set(frame); + outProgress.set((frame) / (numFrames - 1)); + + texU.set(texRepeatX.get() * col); + texV.set(texRepeatY.get() * row); +} + + +}; + +Ops.Gl.ImageSequenceAnim_v2.prototype = new CABLES.Op(); +CABLES.OPS["282203ae-8e8c-4ff7-a0a6-f0cb0ec1ca25"]={f:Ops.Gl.ImageSequenceAnim_v2,objName:"Ops.Gl.ImageSequenceAnim_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.InteractiveRectangle_v2 +// +// ************************************************************** + +Ops.Gl.InteractiveRectangle_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Trigger in"), + trigger = op.outTrigger("Trigger out"), + width = op.inValue("Width", 1), + height = op.inValue("Height", 1), + inId = op.inString("ID"), + classPort = op.inString("Class"), + pivotX = op.inValueSelect("Pivot x", ["center", "left", "right"]), + pivotY = op.inValueSelect("Pivot y", ["center", "top", "bottom"]), + axis = op.inValueSelect("Axis", ["xy", "xz"]), + isInteractive = op.inValueBool("Is Interactive", true), + renderRect = op.inValueBool("Render Rectangle", true), + divVisible = op.inValueBool("Show Boundings", true), + cursorPort = op.inValueSelect("Cursor", ["auto", "crosshair", "pointer", "Hand", "move", "n-resize", "ne-resize", "e-resize", "se-resize", "s-resize", "sw-resize", "w-resize", "nw-resize", "text", "wait", "help", "none"], "pointer"), + active = op.inValueBool("Render", true); + +const geomOut = op.outObject("geometry"); +geomOut.ignoreValueSerialize = true; + +const + mouseOver = op.outBoolNum("Pointer Hover", false), + mouseDown = op.outBoolNum("Pointer Down", false), + outX = op.outNumber("Pointer X"), + outY = op.outNumber("Pointer Y"), + outTop = op.outNumber("Top"), + outLeft = op.outNumber("Left"), + outRight = op.outNumber("Right"), + outBottom = op.outNumber("Bottom"), + mouseClick = op.outTrigger("Left Click"); + +const elementPort = op.outObject("Dom Element"); + +active.setUiAttribs({ "title": "Active" }); + +const cgl = op.patch.cgl; +axis.set("xy"); +pivotX.set("center"); +pivotY.set("center"); + +const geom = new CGL.Geometry(op.name); +let mesh = null; +let div = null; +const m = mat4.create(); +const trans = mat4.create(); +const pos = vec3.create(); +const divAlign = vec3.create(); +const divAlignSize = vec3.create(); + +axis.onChange = rebuild; +pivotX.onChange = rebuild; +pivotY.onChange = rebuild; +width.onChange = rebuild; +height.onChange = rebuild; +cursorPort.onChange = updateCursor; +rebuild(); + +const modelMatrix = mat4.create(); +const identViewMatrix = mat4.create(); +const zeroVec3 = vec3.create(); + +render.onTriggered = function () +{ + if (!div) + { + setUpDiv(); + addListeners(); + updateDivVisibility(); + updateIsInteractive(); + } + updateDivSize(); + + if (active.get() && renderRect.get() && mesh) mesh.render(cgl.getShader()); + + trigger.trigger(); +}; + +function rebuild() +{ + let w = width.get(); + let h = height.get(); + let x = 0; + let y = 0; + + if (typeof w == "string")w = parseFloat(w); + if (typeof h == "string")h = parseFloat(h); + + if (pivotX.get() == "center") + { + x = 0; + divAlign[0] = -w / 2; + } + if (pivotX.get() == "right") + { + x = -w / 2; + } + if (pivotX.get() == "left") + { + x = w / 2; + } + + if (pivotY.get() == "center") + { + y = 0; + divAlign[1] = -h / 2; + } + if (pivotY.get() == "top") y = -h / 2; + if (pivotY.get() == "bottom") y = +h / 2; + + const verts = []; + const tc = []; + const norms = []; + const indices = []; + + const numRows = 1; + const numColumns = 1; + + const stepColumn = w / numColumns; + const stepRow = h / numRows; + + let c, r; + + for (r = 0; r <= numRows; r++) + { + for (c = 0; c <= numColumns; c++) + { + verts.push(c * stepColumn - width.get() / 2 + x); + if (axis.get() == "xz") verts.push(0.0); + verts.push(r * stepRow - height.get() / 2 + y); + if (axis.get() == "xy") verts.push(0.0); + + tc.push(c / numColumns); + tc.push(1.0 - r / numRows); + + if (axis.get() == "xz") + { + norms.push(0); + norms.push(1); + norms.push(0); + } + + if (axis.get() == "xy") + { + norms.push(0); + norms.push(0); + norms.push(-1); + } + } + } + + for (c = 0; c < numColumns; c++) + { + for (r = 0; r < numRows; r++) + { + const ind = c + (numColumns + 1) * r; + const v1 = ind; + const v2 = ind + 1; + const v3 = ind + numColumns + 1; + const v4 = ind + 1 + numColumns + 1; + + indices.push(v1); + indices.push(v3); + indices.push(v2); + + indices.push(v2); + indices.push(v3); + indices.push(v4); + } + } + + geom.clear(); + geom.vertices = verts; + geom.texCoords = tc; + geom.verticesIndices = indices; + geom.vertexNormals = norms; + + if (!mesh) mesh = new CGL.Mesh(cgl, geom); + else mesh.setGeom(geom); + + geomOut.set(null); + geomOut.set(geom); +} + +let divX = 0; +let divY = 0; +let divWidth = 0; +let divHeight = 0; + +const mMatrix = mat4.create(); +divVisible.onChange = updateDivVisibility; +inId.onChange = updateId; +classPort.onChange = updateClassNames; + +function updateDivVisibility() +{ + if (div) + { + if (divVisible.get()) div.style.border = "1px solid red"; + else div.style.border = "none"; + } +} + +function updateCursor() +{ + if (div) + { + div.style.cursor = cursorPort.get(); + } +} + +function updateId() +{ + if (div) + { + div.setAttribute("id", inId.get()); + } +} + +function updateDivSize() +{ + // var vp=cgl.getViewPort(); + + mat4.multiply(mMatrix, cgl.vMatrix, cgl.mMatrix); + vec3.transformMat4(pos, divAlign, mMatrix); + vec3.transformMat4(trans, pos, cgl.pMatrix); + + const x1 = (trans[0] * cgl.canvasWidth / 2) + cgl.canvasWidth / 2; + const y1 = (trans[1] * cgl.canvasHeight / 2) + cgl.canvasHeight / 2; + + divAlignSize[0] = divAlign[0] + width.get(); + divAlignSize[1] = divAlign[1]; + + vec3.transformMat4(pos, divAlignSize, mMatrix); + vec3.transformMat4(trans, pos, cgl.pMatrix); + + const x2 = ((trans[0] * cgl.canvasWidth / 2) + cgl.canvasWidth / 2); + const y2 = ((trans[1] * cgl.canvasHeight / 2) + cgl.canvasHeight / 2); + + divAlignSize[0] = divAlign[0]; + divAlignSize[1] = divAlign[1] + height.get(); + + vec3.transformMat4(pos, divAlignSize, mMatrix); + vec3.transformMat4(trans, pos, cgl.pMatrix); + + const x3 = ((trans[0] * cgl.canvasWidth / 2) + cgl.canvasWidth / 2); + const y3 = ((trans[1] * cgl.canvasHeight / 2) + cgl.canvasHeight / 2); + + divAlignSize[0] = divAlign[0] + width.get(); + divAlignSize[1] = divAlign[1] + height.get(); + + vec3.transformMat4(pos, divAlignSize, mMatrix); + vec3.transformMat4(trans, pos, cgl.pMatrix); + + const x4 = ((trans[0] * cgl.canvasWidth / 2) + cgl.canvasWidth / 2); + const y4 = ((trans[1] * cgl.canvasHeight / 2) + cgl.canvasHeight / 2); + + divX = Math.min(x1, x2, x3, x4); + divY = Math.min(cgl.canvasHeight - y1, cgl.canvasHeight - y2, cgl.canvasHeight - y3, cgl.canvasHeight - y4); + + const xb = Math.max(x1, x2, x3, x4); + const yb = Math.max(cgl.canvasHeight - y1, cgl.canvasHeight - y2, cgl.canvasHeight - y3, cgl.canvasHeight - y4); + + outTop.set(divY); + outLeft.set(divX); + outRight.set(xb); + outBottom.set(yb); + + divWidth = Math.abs(xb - divX); + divHeight = Math.abs(yb - divY); + + divX /= op.patch.cgl.pixelDensity; + divY /= op.patch.cgl.pixelDensity; + divWidth /= op.patch.cgl.pixelDensity; + divHeight /= op.patch.cgl.pixelDensity; + + // div.style.left=divX+'px'; + // div.style.top=divY+'px'; + // div.style.width=divWidth+'px'; + // div.style.height=divHeight+'px'; + + const divXpx = divX + "px"; + const divYpx = divY + "px"; + const divWidthPx = divWidth + "px"; + const divHeightPx = divHeight + "px"; + if (divXpx != div.style.left) div.style.left = divXpx; + if (divYpx != div.style.top) div.style.top = divYpx; + if (div.style.width != divWidthPx) div.style.width = divWidthPx; + if (div.style.height != divHeightPx) div.style.height = divHeightPx; +} + +function updateClassNames() +{ + if (div) + { + div.className = classPort.get(); + } +} + +op.onDelete = function () +{ + if (div)div.remove(); +}; + +function setUpDiv() +{ + if (!div) + { + div = document.createElement("div"); + div.dataset.op = op.id; + div.oncontextmenu = function (e) + { + e.preventDefault(); + }; + + div.style.padding = "0px"; + div.style.position = "absolute"; + div.style["box-sizing"] = "border-box"; + div.style.border = "1px solid red"; + // div.style['border-left']="1px solid blue"; + // div.style['border-top']="1px solid green"; + div.style["z-index"] = "500"; + + div.style["-webkit-user-select"] = "none"; + div.style["user-select"] = "none"; + div.style["-webkit-tap-highlight-color"] = "rgba(0,0,0,0)"; + div.style["-webkit-touch-callout"] = "none"; + + const canvas = op.patch.cgl.canvas.parentElement; + canvas.appendChild(div); + updateCursor(); + updateIsInteractive(); + updateId(); + updateClassNames(); + } + updateDivSize(); + elementPort.set(div); +} + +let listenerElement = null; + +function onMouseMove(e) +{ + const offsetX = -width.get() / 2; + const offsetY = -height.get() / 2; + + outX.set(Math.max(0.0, Math.min(1.0, e.offsetX / divWidth))); + outY.set(Math.max(0.0, Math.min(1.0, 1.0 - e.offsetY / divHeight))); +} + +function onMouseLeave(e) +{ + mouseDown.set(false); + mouseOver.set(false); +} + +function onMouseEnter(e) +{ + mouseOver.set(true); +} + +function onMouseDown(e) +{ + mouseDown.set(true); +} + +function onMouseUp(e) +{ + mouseDown.set(false); +} + +function onmouseclick(e) +{ + mouseClick.trigger(); +} + +function onTouchMove(e) +{ + const targetEle = document.elementFromPoint(e.targetTouches[0].pageX, e.targetTouches[0].pageY); + + if (targetEle == div) + { + mouseOver.set(true); + if (e.touches && e.touches.length > 0) + { + const rect = div.getBoundingClientRect(); // e.target + const x = e.targetTouches[0].pageX - rect.left; + const y = e.targetTouches[0].pageY - rect.top; + + const touch = e.touches[0]; + + outX.set(Math.max(0.0, Math.min(1.0, x / divWidth))); + outY.set(Math.max(0.0, Math.min(1.0, 1.0 - y / divHeight))); + + onMouseMove(touch); + } + } + else + { + mouseOver.set(false); + } +} + +active.onChange = updateActiveRender; +function updateActiveRender() +{ + if (active.get()) + { + addListeners(); + if (div) div.style.display = "block"; + } + else + { + removeListeners(); + if (div) div.style.display = "none"; + } +} + +isInteractive.onChange = updateIsInteractive; +function updateIsInteractive() +{ + if (isInteractive.get()) + { + addListeners(); + if (div)div.style["pointer-events"] = "initial"; + } + else + { + removeListeners(); + mouseDown.set(false); + mouseOver.set(false); + if (div)div.style["pointer-events"] = "none"; + } +} + +function removeListeners() +{ + if (listenerElement) + { + document.removeEventListener("touchmove", onTouchMove); + listenerElement.removeEventListener("touchend", onMouseUp); + listenerElement.removeEventListener("touchstart", onMouseDown); + + listenerElement.removeEventListener("click", onmouseclick); + listenerElement.removeEventListener("mousemove", onMouseMove); + listenerElement.removeEventListener("mouseleave", onMouseLeave); + listenerElement.removeEventListener("mousedown", onMouseDown); + listenerElement.removeEventListener("mouseup", onMouseUp); + listenerElement.removeEventListener("mouseenter", onMouseEnter); + // listenerElement.removeEventListener('contextmenu', onClickRight); + listenerElement = null; + } +} + +function addListeners() +{ + if (listenerElement)removeListeners(); + + listenerElement = div; + + if (listenerElement) + { + document.addEventListener("touchmove", onTouchMove); + listenerElement.addEventListener("touchend", onMouseUp); + listenerElement.addEventListener("touchstart", onMouseDown); + + listenerElement.addEventListener("click", onmouseclick); + listenerElement.addEventListener("mousemove", onMouseMove); + listenerElement.addEventListener("mouseleave", onMouseLeave); + listenerElement.addEventListener("mousedown", onMouseDown); + listenerElement.addEventListener("mouseup", onMouseUp); + listenerElement.addEventListener("mouseenter", onMouseEnter); + // listenerElement.addEventListener('contextmenu', onClickRight); + } +} + + +}; + +Ops.Gl.InteractiveRectangle_v2.prototype = new CABLES.Op(); +CABLES.OPS["334728ca-60a2-4a42-a059-d9b5f3fe4d32"]={f:Ops.Gl.InteractiveRectangle_v2,objName:"Ops.Gl.InteractiveRectangle_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.LayerSequence +// +// ************************************************************** + +Ops.Gl.LayerSequence = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + cleanup = op.inTriggerButton("Clean up connections"); + +const + cgl = op.patch.cgl, + triggers = [], + num = 16; + +let updateTimeout = null; + +exe.onTriggered = triggerAll; +cleanup.onTriggered = clean; +cleanup.setUiAttribs({ "hidePort": true }); +cleanup.setUiAttribs({ "hideParam": true }); + +for (let i = 0; i < num; i++) +{ + const p = op.outTrigger("trigger " + i); + triggers.push(p); + p.onLinkChanged = updateButton; +} + +function updateButton() +{ + clearTimeout(updateTimeout); + updateTimeout = setTimeout(() => + { + let show = false; + for (let i = 0; i < triggers.length; i++) + if (triggers[i].links.length > 1) show = true; + + cleanup.setUiAttribs({ "hideParam": !show }); + + if (op.isCurrentUiOp()) op.refreshParams(); + }, 60); +} + +function triggerAll() +{ + for (let i = 0; i < triggers.length; i++) + { + if (triggers[i].isLinked()) + { + cgl.gl.clear(cgl.gl.DEPTH_BUFFER_BIT); + + triggers[i].trigger(); + } + } +} + +function clean() +{ + let count = 0; + for (let i = 0; i < triggers.length; i++) + { + let removeLinks = []; + + if (triggers[i].links.length > 1) + for (let j = 1; j < triggers[i].links.length; j++) + { + while (triggers[count].links.length > 0) count++; + + removeLinks.push(triggers[i].links[j]); + const otherPort = triggers[i].links[j].getOtherPort(triggers[i]); + op.patch.link(op, "trigger " + count, otherPort.parent, otherPort.name); + count++; + } + + for (let j = 0; j < removeLinks.length; j++) removeLinks[j].remove(); + } + updateButton(); +} + + +}; + +Ops.Gl.LayerSequence.prototype = new CABLES.Op(); +CABLES.OPS["09c33c7e-e282-468d-93e1-b8a7a0a4c4d2"]={f:Ops.Gl.LayerSequence,objName:"Ops.Gl.LayerSequence"}; + + + + +// ************************************************************** +// +// Ops.Gl.LetterBox +// +// ************************************************************** + +Ops.Gl.LetterBox = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const render = op.inTrigger("render"); +const trigger = op.outTrigger("trigger"); + +const outWidth = op.outNumber("Width"); +const outHeight = op.outNumber("Height"); + +let ratio = op.inValueSelect("ratio", [1, 1.25, 1.3333333333, 1.777777777778, 1.88, 2.33333333333333, 2.4151, 3, 4]); + +ratio.set(1.777777777778); + +const cgl = op.patch.cgl; + +let blackBars = op.inValueBool("black bars"); +blackBars.set(true); + +let x = 0, y = 0, w = 1000, h = 1000; + +function resize() +{ + let _w = cgl.canvasHeight * ratio.get(); + let _h = cgl.canvasHeight; + let _x = 0; + let _y = 0; + if (_w > cgl.canvasWidth) + { + _w = cgl.canvasWidth; + _h = cgl.canvasWidth / ratio.get(); + } + + if (_w < cgl.canvasWidth) _x = (cgl.canvasWidth - _w) / 2; + if (_h < cgl.canvasHeight) _y = (cgl.canvasHeight - _h) / 2; + + _w = Math.ceil(_w); + _h = Math.ceil(_h); + _x = Math.ceil(_x); + _y = Math.ceil(_y); + + if (_w != w || _h != h || _x != x || _y != y) + { + w = _w; + h = _h; + x = _x; + y = _y; + + cgl.setViewPort(x, y, w, h); + + for (let i = 0; i < op.patch.ops.length; i++) + if (op.patch.ops[i].onResize)op.patch.ops[i].onResize(); + } + + outWidth.set(w); + outHeight.set(h); +} + +op.onDelete = function () +{ + // cgl.gl.disable(cgl.gl.SCISSOR_TEST); + cgl.resetViewPort(); +}; + +render.onTriggered = function () +{ + if (blackBars.get()) + { + cgl.gl.clearColor(0, 0, 0, 1); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); + } + + resize(); + + x = Math.round(x); + y = Math.round(y); + w = Math.round(w + 0.5); + h = Math.round(h + 0.5); + + cgl.gl.scissor(x, y, w, h); + cgl.setViewPort(x, y, w, h); + + mat4.perspective(cgl.pMatrix, 45, ratio.get(), 0.1, 1100.0); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.LetterBox.prototype = new CABLES.Op(); +CABLES.OPS["6a62d24e-d0a6-4110-a042-15e3cda59db4"]={f:Ops.Gl.LetterBox,objName:"Ops.Gl.LetterBox"}; + + + + +// ************************************************************** +// +// Ops.Gl.LineFont_v2 +// +// ************************************************************** + +Ops.Gl.LineFont_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + string = op.inString("Text", "cables"), + letterSpacing = op.inValue("Letter Spacing", 1), + align = op.inSwitch("align", ["left", "center", "right"], "left"), + inDraw = op.inBool("Render", true), + outArr = op.outArray("Lines", null, 3); + +let lineArray = []; +let stringWidth = 0; +const meshes = []; +const vec = vec3.create(); +const cgl = op.patch.cgl; +const characters = + [ + { + // a + "l": [ + [182.667, 349.057, 164.167, 349.057], + [160.333, 360.557, 171.333, 326.89, 175.333, 326.89, 186, 360.557], + ] + }, + { + // b + "l": + [ + [174.333, 343.057, 160.255, 343.057], + [160.333, 326.89, 175.5, 326.89, 178.333, 330.724, 178.333, 340.724, 174.333, 343.057, 180.5, 346.807, 180.5, 357.474, 176, 360.557, 160.167, 360.557, 160.333, 326.89] + ] + }, + { + // c + "l": + [ + [180.583, 331.307, 175.917, 326.807, 166, 326.807, 160.083, 332.557, 160.083, 354.557, 165.833, 360.474, 175.917, 360.474, 180.5, 355.807], + ] + }, + { + // d + "l": + [ + [160.083, 327.057, 160.083, 360.557, 175.417, 360.557, 180.708, 355.265, 180.708, 332.974, 175.104, 327.057, 160.083, 327.057], + ] + }, + { + // e + "l": + [ + [175.167, 343.932, 160.436, 343.932], + [177.917, 326.807, 164.5, 326.807, 160.436, 330.872, 160.436, 356.845, 164.014, 360.422, 177.917, 360.422] + ] + }, + { + // f + "l": + [ + [176.792, 326.932, 164.125, 326.932, 160.167, 330.891, 160.167, 360.683], + [173.458, 345.599, 160.167, 345.599], + ] + }, + { + // g + "l": + [ + [180.455, 332.395, 175.391, 328.33, 166.194, 328.33, 160.167, 334.357, 160.167, 355.933, 165.792, 360.557, 176.038, 360.557, 181.62, 354.976, 181.62, 344.811, 173.122, 344.811], + ] + }, + { + // h + "l": + [ + [160.167, 326.89, 160.167, 360.557], + [160.5, 343.723, 182.333, 343.723], + [182.333, 326.89, 182.333, 360.974] + ] + }, + { + // i + "l": + [ + [160.167, 326.807, 160.167, 360.641] + ] + }, + { + // j + "l": + [ + [159.833, 326.89, 166.833, 326.89, 166.833, 362.057, 163.962, 364.928, 159.833, 364.928], + ] + }, + { + // k + "l": + [ + [160.167, 326.807, 160.167, 360.974], + [178.917, 326.807, 160.167, 348.474], + [164.905, 342.998, 180.333, 360.64] + ] + }, + { + // l + "l": + [ + [160.167, 326.974, 160.167, 360.558, 176.083, 360.558], + ] + }, + { + "l": + [ + [160.167, 360.557, 160.247, 326.89, 164.997, 326.89, 175.5, 360.557, 178, 360.557, 188.58, 326.89, 193.33, 326.89, 193.25, 360.557], + ] + }, + { + // n + "l": + [ + [160.167, 360.599, 160.167, 326.933, 164.629, 326.933, 178.333, 360.599, 182.083, 360.599, 182.083, 326.933], + ] + }, + { + "l": + [ + [160.283, 332.448, 165.764, 326.967, 178.405, 326.967, 183.668, 332.23, 183.668, 354.365, 177.434, 360.599, 166.367, 360.599, 160.167, 354.399, 160.283, 332.448], + ] + }, + + { + // p + "l": + [ + [160.167, 360.432, 160.167, 327.015, 175.955, 327.015, 179.667, 330.728, 179.667, 341.015, 175.602, 345.08, 160.167, 345.08], + ] + }, + + { + // q + "l": + [ + [184.504, 361.693, 180.517, 357.706], + [160.283, 332.413, 165.764, 326.932, 178.405, 326.932, 183.668, 332.195, 183.668, 354.33, 177.434, 360.564, 166.367, 360.564, 160.167, 354.364, 160.283, 332.413], + ] + }, + { + // r + "l": + [ + [179.667, 360.307, 173.5, 344.955], + [160.167, 360.307, 160.167, 326.89, 175.955, 326.89, 179.667, 330.603, 179.667, 340.89, 175.602, 344.955, 160.167, 344.955], + ] + }, + { + // s + "l": + [ + [179.979, 326.87, 165.895, 326.87, 160.167, 332.598, 160.167, 338.307, 179.292, 349.057, 179.292, 355.223, 173.917, 360.598, 160.167, 360.598], + ] + }, + { + // t + "l": + [ + [170.417, 326.89, 170.417, 360.974], + [180.5, 326.89, 160.167, 326.89] + ] + }, + { + // u + "l": + [ + [160.167, 327.14, 160.167, 356.845, 164.108, 360.786, 178.125, 360.786, 182.012, 356.899, 181.958, 327.14], + ] + }, + { + // v + "l": + [ + [160.167, 326.901, 170.167, 360.797, 174.417, 360.797, 184.667, 326.734], + ] + }, + { + // w + "l": + [ + [203.5, 326.89, 195.208, 360.557, 191.458, 360.557, 184, 326.89, 179.758, 326.89, 172.208, 360.557, 168.458, 360.557, 160.167, 326.89], + ] + }, + { + // x + "l": + [ + [181.333, 360.64, 159.667, 326.807], + [159.667, 360.557, 181.75, 326.807] + ] + }, + { + // y + "l": + [ + [160.167, 326.891, 168.508, 347.224, 173.992, 347.224, 182.917, 326.891], + [171.333, 347.224, 171.333, 360.641] + ] + }, + { + // z + "l": + [ + [161.167, 326.807, 180.5, 326.807, 180.5, 332.473, 161.167, 355.223, 161.167, 360.557, 180.5, 360.557], + ] + }, + + { + // 0 + "l": + [ + [167.591, 326.89, 173.076, 326.89, 180.5, 334.315, 180.5, 353.132, 173.076, 360.557, 167.591, 360.557, 160.167, 353.132, 160.167, 334.315, 167.591, 326.89], + ] + }, + { + // 1 + "l": + [ + [160.167, 334.315, 167.549, 326.932, 170.333, 326.89, 170.417, 360.557], + ] + }, + { + // 2 + "l": + [ + [164.066, 330.415, 167.591, 326.89, 180.5, 326.89, 180.5, 330.603, 160.167, 351.224, 160.167, 360.557, 180.5, 360.599], + ] + }, + { + // 3 + "l": + [ + [169.583, 342.932, 180.5, 342.932], + [163.129, 331.353, 167.591, 326.89, 180.5, 326.89, 180.5, 360.557, 167.591, 360.557, 162.837, 355.803], + ] + }, + { + // 4 + "l": + [ + [178.076, 326.89, 178.076, 360.599], + [160.167, 326.89, 160.167, 338.474, 165.104, 343.412, 178.5, 343.412], + ] + }, + { + // 5 + "l": + [ + [180.5, 326.89, 160.098, 326.958, 160.167, 342.932, 180.5, 342.932, 180.5, 353.132, 173.076, 360.557, 160.167, 360.557], + ] + }, + { + // 6 + "l": + [ + [173.076, 326.89, 167.591, 326.89, 160.167, 333.89, 160.167, 353.132, 167.591, 360.557, 173.417, 360.557, 180.671, 353.303, 180.671, 342.932, 160.167, 342.932], + ] + }, + { + // 7 + "l": + [ + [163.591, 326.89, 180.5, 326.89, 170.417, 360.557], + ] + }, + { + // 8 + "l": + [ + [180.5, 334.315, 173.076, 326.89, 167.591, 326.89, 160.167, 334.315, 180.5, 353.132, 173.076, 360.557, 167.591, 360.557, 160.167, 353.132, 180.5, 334.315], + ] + }, + { + // 9 + "l": + [ + [167.591, 360.557, 173.076, 360.557, 180.5, 353.132, 180.5, 334.315, 173.076, 326.89, 167.591, 326.89, 160.167, 334.315, 160.167, 342.932, 180.5, 342.932] + ] + }, + + { + // & + "l": + [ + [182.496, 351.137, 173.076, 360.557, 167.591, 360.557, 160.167, 353.132, 160.167, 348.087, 173.922, 339.533, 172.229, 326.89, 165.167, 326.89, 165.052, 339.515, 184.292, 359.432], + ] + }, + { + // ' + "l": + [ + [160.167, 326.932, 160.167, 333.557], + [162.879, 326.932, 162.879, 333.557] + + ] + }, + { + // ; + "l": + [ + [160.167, 342.932, 160.167, 346.224], + [160.167, 354.224, 160.167, 360.557] + ] + }, + { + // : + "l": + [ + [160.167, 342.932, 160.167, 346.224], + [160.167, 354.224, 160.167, 357.974] + ] + }, + { + // _ + "l": + [ + [160.167, 360.557, 170.417, 360.557] + ] + }, + { + // + + "l": + [ + [160.167, 342.932, 170, 342.932], + [164.833, 347.849, 164.833, 338.015] + ] + }, + { + // - + "l": + [ + [160.167, 342.932, 170, 342.932], + ] + }, + { + // / + "l": + [ + [180.5, 326.89, 160.167, 360.557], + ] + }, + { + // . + "l": + [ + [160.167, 360.599, 163.417, 360.599], + ] + }, + { + // , + "l": + [ + [165.163, 360.557, 160.167, 365.553], + ] + }, + { + // ) + "l": + [ + [160.167, 360.557, 167.591, 353.132, 167.591, 334.315, 160.167, 326.89], + ] + }, + { + // ( + "l": + [ + [167.591, 326.89, 160.167, 334.315, 160.167, 353.132, 167.591, 360.557], + ] + }, + { + // ? + "l": + [ + [170.333, 363.481, 170.333, 368.966], + [160.167, 334.315, 167.591, 326.89, 173.076, 326.89, 180.5, 334.315, 180.5, 342.932, 170.333, 353.132, 170.333, 360.557] + ] + }, + { + // ! + "l": + [ + [160.167, 353.557, 160.167, 326.89], + [160.167, 357.64, 160.167, 360.557] + ] + }, + + ]; + +function translateX(w) +{ + transX += w; + + vec3.set(vec, w, 0, 0); + mat4.translate(cgl.mMatrix, cgl.mMatrix, vec); +} + +let alignMode = 0; +align.onChange = function () +{ + if (align.get() == "left")alignMode = 0; + if (align.get() == "center")alignMode = 1; + if (align.get() == "right")alignMode = 2; +}; + +let oldPrim = 0; +let shader = null; + +let transX = 0; + +function renderChar(charIndex, simulate) +{ + shader = cgl.getShader(); + if (!shader) return; + oldPrim = shader.glPrimitive; + + shader.glPrimitive = cgl.gl.LINE_STRIP; + + if (charIndex >= characters.length)charIndex = 0; + + if (!simulate) + { + for (let m = 0; m < characters[charIndex].linesArr.length; m += 3) + { + lineArray.push( + characters[charIndex].linesArr[m + 0] + transX, + characters[charIndex].linesArr[m + 1], + characters[charIndex].linesArr[m + 2] + ); + + // characters[charIndex].m[m].render(op.patch.cgl.getShader()); + } + + for (let m = 0; m < characters[charIndex].m.length; m++) + { + if (inDraw.get()) + characters[charIndex].m[m].render(op.patch.cgl.getShader()); + } + translateX(characters[charIndex].w * letterSpacing.get()); + } + else + { + stringWidth += characters[charIndex].w * letterSpacing.get(); + } + shader.glPrimitive = oldPrim; +} + +render.onTriggered = function () +{ + stringWidth = 0; + if (!string.get()) return; + let spaceWidth = 0.15; + vec3.set(vec, 0.3, 0, 0); + cgl.pushModelMatrix(); + + let startCharacters = 97; + let startNumbers = 48; + + let str = string.get() + ""; + + // cgl.gl.lineWidth(lineWidth.get()); + + for (let sim = 0; sim < 2; sim++) + { + transX = 0; + lineArray.length = 0; + let simulate = sim === 0; + + if (!simulate) + { + if (alignMode == 1) translateX(-stringWidth / 2 + 0.04 * letterSpacing.get()); + if (alignMode == 2) translateX(-stringWidth + 0.08 * letterSpacing.get()); + } + + for (let i = 0; i < str.length; i++) + { + let w = 0; + let charIndex = str.toLowerCase().charCodeAt(i); + + if (charIndex == 38) renderChar(36, simulate); // & + else if (charIndex == 39) renderChar(37, simulate); // ' + else if (charIndex == 34) renderChar(37, simulate); // ' + else if (charIndex == 59) renderChar(38, simulate); // ; + else if (charIndex == 58) renderChar(39, simulate); // : + else if (charIndex == 95) renderChar(40, simulate); // _ + else if (charIndex == 43) renderChar(41, simulate); // + + else if (charIndex == 45) renderChar(42, simulate); // - + else if (charIndex == 47) renderChar(43, simulate); // / + else if (charIndex == 46) renderChar(44, simulate); // . + else if (charIndex == 44) renderChar(45, simulate); // , + else if (charIndex == 41) renderChar(46, simulate); // ) + else if (charIndex == 40) renderChar(47, simulate); // () + else if (charIndex == 63) renderChar(48, simulate); // ? + else if (charIndex == 33) renderChar(49, simulate); // ! + else + if (charIndex >= startNumbers && charIndex <= startNumbers + 10) + { + renderChar(charIndex - startNumbers + 26, simulate); + } + else + if (charIndex >= startCharacters && charIndex - startCharacters < characters.length) + { + renderChar(charIndex - startCharacters, simulate); + } + else + if (charIndex == 32) + { + if (simulate)stringWidth += spaceWidth; + else translateX(spaceWidth); + } + else + { + renderChar(48, simulate); + } + } + } + + outArr.set(null); + outArr.set(lineArray); + + cgl.popModelMatrix(); +}; + +function avg(which) +{ + let avgX = 0, avgY = 0; + let count = 0; + for (let l = 0; l < characters[which].l.length; l++) + { + for (let j = 0; j < characters[which].l[l].length; j += 2) + { + avgX += characters[which].l[l][j]; + avgY += characters[which].l[l][j + 1]; + count++; + } + } + avgX /= count; + avgY /= count; + return [avgX, avgY]; +} + +function min(which) +{ + let min = 9999999; + + for (let l = 0; l < characters[which].l.length; l++) + { + for (let j = 0; j < characters[which].l[l].length; j += 2) + { + min = Math.min(min, characters[which].l[l][j]); + } + } + return min; +} + +function width(which) +{ + let min = 9999999; + let max = -9999999; + + for (let l = 0; l < characters[which].l.length; l++) + { + for (let j = 0; j < characters[which].l[l].length; j += 2) + { + min = Math.min(min, characters[which].l[l][j]); + max = Math.max(max, characters[which].l[l][j]); + } + } + return ((max - min)); +} + +meshes.length = 0; + +let avgXY = []; +let avg1 = avg(0); +let avg2 = avg(1); + +avgXY = [(avg1[0] + avg2[0]) / 2, (avg1[1] + avg2[1]) / 2]; + +for (let i = 0; i < characters.length; i++) +{ + characters[i].w = width(i) * (0.002); + characters[i].m = []; + let lines = []; + + for (let l = 0; l < characters[i].l.length; l++) + { + let count = 0; + let indices = []; + let vertices = []; + + for (let j = 0; j < characters[i].l[l].length - 2; j += 2) + { + lines.push( + (characters[i].l[l][j] - min(i)) * 0.005, + (characters[i].l[l][j + 1] - avgXY[1]) * -0.005, + 0); + + lines.push( + (characters[i].l[l][j + 2] - min(i)) * 0.005, + (characters[i].l[l][j + 3] - avgXY[1]) * -0.005, + 0); + } + + for (let j = 0; j < characters[i].l[l].length; j += 2) + { + vertices.push((characters[i].l[l][j] - min(i)) * 0.005); + vertices.push((characters[i].l[l][j + 1] - avgXY[1]) * -0.005); + vertices.push(0); + + indices.push(count); + count++; + } + + characters[i].linesArr = lines; + let geom = new CGL.Geometry(op.name); + geom.vertices = vertices; + geom.verticesIndices = indices; + let mesh = new CGL.Mesh(op.patch.cgl, geom); + characters[i].m.push(mesh); + } + + outArr.set([]); + + characters[i].w += 0.1; +} + + +}; + +Ops.Gl.LineFont_v2.prototype = new CABLES.Op(); +CABLES.OPS["a3615010-05af-45bc-bf98-6972c2de21bc"]={f:Ops.Gl.LineFont_v2,objName:"Ops.Gl.LineFont_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.MainLoop +// +// ************************************************************** + +Ops.Gl.MainLoop = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + fpsLimit = op.inValue("FPS Limit", 0), + trigger = op.outTrigger("trigger"), + width = op.outNumber("width"), + height = op.outNumber("height"), + reduceFocusFPS = op.inValueBool("Reduce FPS not focussed", true), + reduceLoadingFPS = op.inValueBool("Reduce FPS loading"), + clear = op.inValueBool("Clear", true), + clearAlpha = op.inValueBool("ClearAlpha", true), + fullscreen = op.inValueBool("Fullscreen Button", false), + active = op.inValueBool("Active", true), + hdpi = op.inValueBool("Hires Displays", false), + inUnit = op.inSwitch("Pixel Unit", ["Display", "CSS"], "Display"); + +op.onAnimFrame = render; +hdpi.onChange = function () +{ + if (hdpi.get()) op.patch.cgl.pixelDensity = window.devicePixelRatio; + else op.patch.cgl.pixelDensity = 1; + + op.patch.cgl.updateSize(); + if (CABLES.UI) gui.setLayout(); + + // inUnit.setUiAttribs({ "greyout": !hdpi.get() }); + + // if (!hdpi.get())inUnit.set("CSS"); + // else inUnit.set("Display"); +}; + +active.onChange = function () +{ + op.patch.removeOnAnimFrame(op); + + if (active.get()) + { + op.setUiAttrib({ "extendTitle": "" }); + op.onAnimFrame = render; + op.patch.addOnAnimFrame(op); + op.log("adding again!"); + } + else + { + op.setUiAttrib({ "extendTitle": "Inactive" }); + } +}; + +const cgl = op.patch.cgl; +let rframes = 0; +let rframeStart = 0; + +if (!op.patch.cgl) op.uiAttr({ "error": "No webgl cgl context" }); + +const identTranslate = vec3.create(); +vec3.set(identTranslate, 0, 0, 0); +const identTranslateView = vec3.create(); +vec3.set(identTranslateView, 0, 0, -2); + +fullscreen.onChange = updateFullscreenButton; +setTimeout(updateFullscreenButton, 100); +let fsElement = null; + +let winhasFocus = true; +let winVisible = true; + +window.addEventListener("blur", () => { winhasFocus = false; }); +window.addEventListener("focus", () => { winhasFocus = true; }); +document.addEventListener("visibilitychange", () => { winVisible = !document.hidden; }); +testMultiMainloop(); + +inUnit.onChange = () => +{ + width.set(0); + height.set(0); +}; + +function getFpsLimit() +{ + if (reduceLoadingFPS.get() && op.patch.loading.getProgress() < 1.0) return 5; + + if (reduceFocusFPS.get()) + { + if (!winVisible) return 10; + if (!winhasFocus) return 30; + } + + return fpsLimit.get(); +} + +function updateFullscreenButton() +{ + function onMouseEnter() + { + if (fsElement)fsElement.style.display = "block"; + } + + function onMouseLeave() + { + if (fsElement)fsElement.style.display = "none"; + } + + op.patch.cgl.canvas.addEventListener("mouseleave", onMouseLeave); + op.patch.cgl.canvas.addEventListener("mouseenter", onMouseEnter); + + if (fullscreen.get()) + { + if (!fsElement) + { + fsElement = document.createElement("div"); + + const container = op.patch.cgl.canvas.parentElement; + if (container)container.appendChild(fsElement); + + fsElement.addEventListener("mouseenter", onMouseEnter); + fsElement.addEventListener("click", function (e) + { + if (CABLES.UI && !e.shiftKey) gui.cycleFullscreen(); + else cgl.fullScreen(); + }); + } + + fsElement.style.padding = "10px"; + fsElement.style.position = "absolute"; + fsElement.style.right = "5px"; + fsElement.style.top = "5px"; + fsElement.style.width = "20px"; + fsElement.style.height = "20px"; + fsElement.style.cursor = "pointer"; + fsElement.style["border-radius"] = "40px"; + fsElement.style.background = "#444"; + fsElement.style["z-index"] = "9999"; + fsElement.style.display = "none"; + fsElement.innerHTML = ""; + } + else + { + if (fsElement) + { + fsElement.style.display = "none"; + fsElement.remove(); + fsElement = null; + } + } +} + +op.onDelete = function () +{ + cgl.gl.clearColor(0, 0, 0, 0); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); +}; + +function render(time) +{ + if (!active.get()) return; + if (cgl.aborted || cgl.canvas.clientWidth === 0 || cgl.canvas.clientHeight === 0) return; + + op.patch.cg = cgl; + + const startTime = performance.now(); + + op.patch.config.fpsLimit = getFpsLimit(); + + if (cgl.canvasWidth == -1) + { + cgl.setCanvas(op.patch.config.glCanvasId); + return; + } + + if (cgl.canvasWidth != width.get() || cgl.canvasHeight != height.get()) + { + let div = 1; + if (inUnit.get() == "CSS")div = op.patch.cgl.pixelDensity; + + width.set(cgl.canvasWidth / div); + height.set(cgl.canvasHeight / div); + } + + if (CABLES.now() - rframeStart > 1000) + { + CGL.fpsReport = CGL.fpsReport || []; + if (op.patch.loading.getProgress() >= 1.0 && rframeStart !== 0)CGL.fpsReport.push(rframes); + rframes = 0; + rframeStart = CABLES.now(); + } + CGL.MESH.lastShader = null; + CGL.MESH.lastMesh = null; + + cgl.renderStart(cgl, identTranslate, identTranslateView); + + if (clear.get()) + { + cgl.gl.clearColor(0, 0, 0, 1); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); + } + + trigger.trigger(); + + if (CGL.MESH.lastMesh)CGL.MESH.lastMesh.unBind(); + + if (CGL.Texture.previewTexture) + { + if (!CGL.Texture.texturePreviewer) CGL.Texture.texturePreviewer = new CGL.Texture.texturePreview(cgl); + CGL.Texture.texturePreviewer.render(CGL.Texture.previewTexture); + } + cgl.renderEnd(cgl); + + op.patch.cg = null; + + if (clearAlpha.get()) + { + cgl.gl.clearColor(1, 1, 1, 1); + cgl.gl.colorMask(false, false, false, true); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT); + cgl.gl.colorMask(true, true, true, true); + } + + if (!cgl.frameStore.phong)cgl.frameStore.phong = {}; + rframes++; + + op.patch.cgl.profileData.profileMainloopMs = performance.now() - startTime; +} + +function testMultiMainloop() +{ + setTimeout( + () => + { + if (op.patch.getOpsByObjName(op.name).length > 1) + { + op.setUiError("multimainloop", "there should only be one mainloop op!"); + op.patch.addEventListener("onOpDelete", testMultiMainloop); + } + else op.setUiError("multimainloop", null, 1); + }, 500); +} + + +}; + +Ops.Gl.MainLoop.prototype = new CABLES.Op(); +CABLES.OPS["b0472a1d-db16-4ba6-8787-f300fbdc77bb"]={f:Ops.Gl.MainLoop,objName:"Ops.Gl.MainLoop"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.AnimMatrix +// +// ************************************************************** + +Ops.Gl.Matrix.AnimMatrix = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTrigger = op.inTrigger("Update"), + inMat = op.inArray("Next Matrix"), + // inStart=op.inTriggerButton("Start Anim"), + inDur = op.inFloat("Duration", 1), + next = op.outTrigger("Next"), + outArr = op.outArray("Matrix"); + +let lastTime = 0; +let startTime = 0; +let firsttime = true; +let cycle = 1; + +const anim = new CABLES.Anim(); +anim.createPort(op, "easing", init); +anim.loop = false; + +let lastMat = null; + +inDur.onChange = inMat.onChange = init; + +const a = vec3.create(); +const b = vec3.create(); + +let arr1, arr2; +let result = mat4.create(); + +inTrigger.onTriggered = () => +{ + let t = CABLES.now() / 1000; + + const perc = anim.getValue(t); + + if (arr1 && arr2) ipMat(perc); +}; + +function matEquals(a, b) +{ + return ( + a[0] == b[0] && + a[1] == b[1] && + a[2] == b[2] && + a[3] == b[3] && + a[4] == b[4] && + a[5] == b[5] && + a[6] == b[6] && + a[7] == b[7] && + a[8] == b[8] && + a[9] == b[9] && + a[10] == b[10] && + a[11] == b[11] && + a[12] == b[12] && + a[13] == b[13] && + a[14] == b[14] && + a[15] == b[15]); +} + +function init() +{ + if (!inMat.get()) return; + if (inMat.get() == lastMat) + { + // mat4.copy(result,inMat.get()); + return; + } + + if (lastMat) + if (inMat.get() == lastMat && matEquals(inMat.get(), lastMat)) + { + return; + } + + lastMat = inMat.get(); + startTime = performance.now(); + anim.clear(CABLES.now() / 1000.0); + + anim.setValue(CABLES.now() / 1000.0, cycle); + + if (cycle == 1) cycle = 0; + else cycle = 1; + + if (cycle == 0) + { + arr1 = inMat.get(); + arr2 = mat4.create(); + mat4.copy(arr2, result); + } + else + { + arr1 = mat4.create(); + arr2 = inMat.get(); + mat4.copy(arr1, result); + } + + anim.setValue(inDur.get() + CABLES.now() / 1000.0, cycle, () => + { + // result=outArr.get(); + }); + + firsttime = false; +} + +function ip(val1, val2, perc) +{ + return ((val2 - val1) * perc + val1); +} + +function ipMat(perc) +{ + if (!arr1 || !arr2 || arr1.length != arr2.length) + { + outArr.set(null); + op.logError("arrays wrong", arr1.length, arr2.length); + } + else + { + getYPR(a, arr1); + getYPR(b, arr2); + + mat4.identity(result); + result[12] = ip(arr1[12], arr2[12], perc); + result[13] = ip(arr1[13], arr2[13], perc); + result[14] = ip(arr1[14], arr2[14], perc); + + vec3.lerp(a, a, b, perc); + + mat4.rotateZ(result, result, a[2]); + mat4.rotateY(result, result, a[1]); + mat4.rotateX(result, result, a[0]); + + outArr.set(null); + outArr.set(result); + } + next.trigger(); +} + +// 0 1 2 3 +// 4 5 6 7 +// 8 9 10 11 +// 12 13 14 15 + +function getYPR(v, m) +{ + const r1 = Math.atan2(m[6], m[10]); + const c2 = Math.sqrt(m[0] * m[0] + m[1] * m[1]); + const r2 = Math.atan2(-m[2], c2); + const s1 = Math.sin(r1); + const c1 = Math.cos(r1); + const r3 = Math.atan2(s1 * m[8] - c1 * m[4], c1 * m[5] - s1 * m[9]); + + v[0] = r1; + v[1] = r2; + v[2] = r3; + return v; +} + + +}; + +Ops.Gl.Matrix.AnimMatrix.prototype = new CABLES.Op(); +CABLES.OPS["7800dde0-0ce4-4acd-9605-d412931bb90e"]={f:Ops.Gl.Matrix.AnimMatrix,objName:"Ops.Gl.Matrix.AnimMatrix"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.ArrayPathFollow +// +// ************************************************************** + +Ops.Gl.Matrix.ArrayPathFollow = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe = op.inTrigger("exe"); +const arrayIn = op.inArray("array"); +const time = op.inValueFloat("time"); + +const duration = op.inValueFloat("duration"); +duration.set(0.1); + +const offset = op.inValueFloat("offset"); +offset.set(0.0); + +const lookAhead = op.inValueFloat("look ahead"); +lookAhead.set(3.0); + +const trigger = op.outTrigger("trigger"); +const triggerLookat = op.outTrigger("transform lookat"); +const idx = op.addOutPort(new CABLES.Port(op, "index")); + +const vec = vec3.create(); +const vecn = vec3.create(); +const cgl = op.patch.cgl; + +const startTime = CABLES.now(); + +let animX = new CABLES.Anim(); +let animY = new CABLES.Anim(); +let animZ = new CABLES.Anim(); + +let animQX = new CABLES.Anim(); +let animQY = new CABLES.Anim(); +let animQZ = new CABLES.Anim(); +let animQW = new CABLES.Anim(); + +let animLength = 0; +let timeStep = 0.1; +function setup() +{ + animX = new CABLES.Anim(); + animY = new CABLES.Anim(); + animZ = new CABLES.Anim(); + + animQX = new CABLES.Anim(); + animQY = new CABLES.Anim(); + animQZ = new CABLES.Anim(); + animQW = new CABLES.Anim(); + + let i = 0; + const arr = arrayIn.get(); + if (!arr) return; + timeStep = parseFloat(duration.get()); + + for (i = 0; i < arr.length; i += 3) + { + animX.setValue(i / 3 * timeStep, arr[i + 0]); + animY.setValue(i / 3 * timeStep, arr[i + 1]); + animZ.setValue(i / 3 * timeStep, arr[i + 2]); + animLength = i / 3 * timeStep; + } + + for (i = 0; i < arr.length / 3; i++) + { + const t = i * timeStep; + const nt = (i * timeStep + timeStep) % animLength; + + vec3.set(vec, + animX.getValue(t), + animY.getValue(t), + animZ.getValue(t) + ); + vec3.set(vecn, + animX.getValue(nt), + animY.getValue(nt), + animZ.getValue(nt) + ); + + vec3.set(vec, vecn[0] - vec[0], vecn[1] - vec[1], vecn[2] - vec[2]); + vec3.normalize(vec, vec); + vec3.set(vecn, 0, 0, 1); + + quat.rotationTo(q, vecn, vec); + + animQX.setValue(i * timeStep, q[0]); + animQY.setValue(i * timeStep, q[1]); + animQZ.setValue(i * timeStep, q[2]); + animQW.setValue(i * timeStep, q[3]); + } +} + +arrayIn.onChange = duration.onChange = setup; + +let q = quat.create(); +const qMat = mat4.create(); + +function render() +{ + if (!arrayIn.get()) return; + + const t = (time.get() + parseFloat(offset.get())) % animLength; + const nt = (time.get() + timeStep * lookAhead.get() + parseFloat(offset.get())) % animLength; + + vec3.set(vec, + animX.getValue(t), + animY.getValue(t), + animZ.getValue(t) + ); + + idx.set(nt); + + if (triggerLookat.isLinked()) + { + vec3.set(vecn, + animX.getValue(nt), + animY.getValue(nt), + animZ.getValue(nt) + ); + + cgl.pushModelMatrix(); + mat4.translate(cgl.mMatrix, cgl.mMatrix, vecn); + triggerLookat.trigger(); + cgl.popModelMatrix(); + } + + cgl.pushModelMatrix(); + mat4.translate(cgl.mMatrix, cgl.mMatrix, vec); + + CABLES.TL.Anim.slerpQuaternion(t, q, animQX, animQY, animQZ, animQW); + mat4.fromQuat(qMat, q); + mat4.multiply(cgl.mMatrix, cgl.mMatrix, qMat); + + trigger.trigger(); + cgl.popModelMatrix(); +} + +exe.onTriggered = render; + + +}; + +Ops.Gl.Matrix.ArrayPathFollow.prototype = new CABLES.Op(); +CABLES.OPS["395bff14-d092-4e7e-a723-b6a69564add2"]={f:Ops.Gl.Matrix.ArrayPathFollow,objName:"Ops.Gl.Matrix.ArrayPathFollow"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.ArrayPathFollowParticles_v2 +// +// ************************************************************** + +Ops.Gl.Matrix.ArrayPathFollowParticles_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"pathfollow_vert":"\nfloat off=MOD_offset;\n\n#ifdef RANDOMSPEED\n off*=MOD_rand(pos.xy);\n#endif\n\nfloat fr=fract(abs(mod(off+rndOffset,float(PATHFOLLOW_POINTS))));\nint index=int(abs(mod(off+rndOffset,max(0.0,float(PATHFOLLOW_POINTS)))));\nint index2=int(abs(mod(off+1.0+rndOffset,max(0.0,float(PATHFOLLOW_POINTS)))));\n\nif(index2!=0)\n{\n pos.xyz = mix( MOD_pathPoints[index] ,MOD_pathPoints[index2] ,fr);\n\n #ifdef CHECK_DISTANCE\n if( distance(MOD_pathPoints[index] ,MOD_pathPoints[index2]) > MOD_maxDistance ) pos.xyz=vec3(9999999.0,9999999.0,9999999.0);\n #endif\n}\nelse\n{\n pos.xyz=MOD_pathPoints[0];\n}\n\npos.xyz+=rndPos;","pathfollow_head_vert":"UNI vec3 MOD_pathPoints[PATHFOLLOW_POINTS];\n\nIN vec3 rndPos;\nIN float rndOffset;\n\n\nfloat MOD_rand(vec2 co){\n return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);\n}\n",}; +const + exec = op.inTrigger("Exec"), + inPoints = op.inArray("Points"), + inParticles = op.inValue("Num Particles", 500), + inLength = op.inValue("Length", 20), + inSpread = op.inValue("Spread", 0.2), + inOffset = op.inValue("Offset"), + inMaxDistance = op.inValue("Max Distance", 0), + inRandomSpeed = op.inValueBool("RandomSpeed"), + next = op.outTrigger("Next"); + +const cgl = op.patch.cgl; +let shaderModule = null; +let shader = null; +let mesh = null; +let needsRebuild = true; +let geom = null; +let updateUniformPoints = false; + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "title": op.objName, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": attachments.pathfollow_head_vert, + "srcBodyVert": attachments.pathfollow_vert +}); + +mod.addUniform("f", "MOD_maxDistance", inMaxDistance); +mod.addUniform("f", "MOD_offset", inOffset); +mod.addUniform("3f[]", "MOD_pathPoints", inPoints); + +inParticles.onChange = + inLength.onChange = + inSpread.onChange = resetLater; + +inMaxDistance.onChange = updateDefines; + +function resetLater() +{ + needsRebuild = true; +} + +function getRandomVec(size) +{ + return [ + (Math.random() - 0.5) * 2 * size, + (Math.random() - 0.5) * 2 * size, + (Math.random() - 0.5) * 2 * size + ]; +} + +function rebuild() +{ + op.log("rebuild"); + + mesh = null; + needsRebuild = false; + let i = 0; + let verts = null; + const num = Math.abs(Math.floor(inParticles.get()) * 3); + if (!verts || verts.length != num) verts = new Float32Array(num); + + for (i = 0; i < verts.length; i += 3) + { + verts[i + 0] = (Math.random() - 0.5); + verts[i + 1] = (Math.random() - 0.5); + verts[i + 2] = (Math.random() - 0.5); + } + + if (!geom)geom = new CGL.Geometry(op.name); + geom.setPointVertices(verts); + + if (!mesh) + { + mesh = new CGL.Mesh(cgl, geom, cgl.gl.POINTS); + + mesh.addVertexNumbers = true; + mesh._verticesNumbers = null; + + op.log("NEW MESH"); + } + else + { + mesh.unBind(); + } + mesh.setGeom(geom); + + const rndArray = new Float32Array(num); + + let spread = inSpread.get(); + if (spread < 0)spread = 0; + + for (i = 0; i < num / 3; i++) + { + let v = getRandomVec(spread); + while (vec3.len(v) > spread / 2) v = getRandomVec(spread); + + rndArray[i * 3 + 0] = v[0]; + rndArray[i * 3 + 1] = v[1]; + rndArray[i * 3 + 2] = v[2]; + } + rndArray[i] = (Math.random() - 0.5) * spread; + + mesh.setAttribute("rndPos", rndArray, 3); + + // offset random + + var rndOffset = new Float32Array(num / 3); + for (i = 0; i < num / 3; i++) + rndOffset[i] = (Math.random()) * inLength.get(); + + mesh.setAttribute("rndOffset", rndOffset, 1); + + // speed random + + var rndOffset = new Float32Array(num / 3); + for (i = 0; i < num / 3; i++) + rndOffset[i] = (Math.random()) * inLength.get(); + + mesh.setAttribute("rndOffset", rndOffset, 1); + updateDefines(); +} + +mod.define("PATHFOLLOW_POINTS", 1); + +function updateDefines() +{ + mod.toggleDefine("CHECK_DISTANCE", inMaxDistance.get() != 0); + mod.toggleDefine("RANDOMSPEED", inRandomSpeed); +} + +exec.onTriggered = function () +{ + if (op.patch.isEditorMode()) + { + if (cgl.getShader().glPrimitive != cgl.gl.POINTS) op.setUiError("nopointmat", "Using a Material not made for point rendering. Try to use PointMaterial."); + else op.setUiError("nopointmat", null); + } + + if (!inPoints.get() || inPoints.get().length === 0) return; + if (needsRebuild)rebuild(); + + mod.bind(); + + if (inPoints.get()) + mod.define("PATHFOLLOW_POINTS", Math.floor(inPoints.get().length / 3)); + else mod.define("PATHFOLLOW_POINTS", 0); + + if (mesh) mesh.render(cgl.getShader()); + + next.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.Matrix.ArrayPathFollowParticles_v2.prototype = new CABLES.Op(); +CABLES.OPS["12a48cb2-a528-4498-8cda-18535af08f4a"]={f:Ops.Gl.Matrix.ArrayPathFollowParticles_v2,objName:"Ops.Gl.Matrix.ArrayPathFollowParticles_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.ArrayTranslate +// +// ************************************************************** + +Ops.Gl.Matrix.ArrayTranslate = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + arrayIn = op.inArray("array"), + trigger = op.outTrigger("trigger"), + idx = op.addOutPort(new CABLES.Port(op, "index")); + +const cgl = op.patch.cgl; +let vec = vec3.create(); +exe.onTriggered = render; + +function render() +{ + if (!arrayIn.get()) return; + let arr = arrayIn.get(); + + for (let i = 0; i < arr.length; i += 3) + { + vec3.set(vec, arr[i], arr[i + 1], arr[i + 2]); + cgl.pushModelMatrix(); + mat4.translate(cgl.mMatrix, cgl.mMatrix, vec); + trigger.trigger(); + cgl.popModelMatrix(); + } +} + + +}; + +Ops.Gl.Matrix.ArrayTranslate.prototype = new CABLES.Op(); +CABLES.OPS["1371bc89-b4ac-4032-86e1-70ff2506665b"]={f:Ops.Gl.Matrix.ArrayTranslate,objName:"Ops.Gl.Matrix.ArrayTranslate"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.Billboard +// +// ************************************************************** + +Ops.Gl.Matrix.Billboard = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exec = op.inTrigger("Exec"); +const next = op.outTrigger("Next"); + +const cgl = op.patch.cgl; + +let mm = mat4.create(); +let mv = mat4.create(); +let m = mat4.create(); +let mempty = mat4.create(); + +exec.onTriggered = function () +{ + mat4.invert(mm, cgl.mMatrix); + mat4.invert(mv, cgl.vMatrix); + + mat4.mul(mm, mm, mv); + + mm[12] = 0; + mm[13] = 0; + mm[14] = 0; + + cgl.pushModelMatrix(); + cgl.pushViewMatrix(); + mat4.mul(cgl.mMatrix, cgl.mMatrix, mm); + next.trigger(); + cgl.popViewMatrix(); + cgl.popModelMatrix(); +}; + + +}; + +Ops.Gl.Matrix.Billboard.prototype = new CABLES.Op(); +CABLES.OPS["d41e676e-d8a7-4a1e-8abf-f1bddfc982d5"]={f:Ops.Gl.Matrix.Billboard,objName:"Ops.Gl.Matrix.Billboard"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.Camera +// +// ************************************************************** + +Ops.Gl.Matrix.Camera = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const render = op.inTrigger("render"); +const trigger = op.outTrigger("trigger"); + +/* Inputs */ +// projection | prespective & ortogonal +const projectionMode = op.inValueSelect("projection mode", ["prespective", "ortogonal"], "prespective"); +const zNear = op.inValue("frustum near", 0.01); +const zFar = op.inValue("frustum far", 5000.0); + +const fov = op.inValue("fov", 45); +const autoAspect = op.inValueBool("Auto Aspect Ratio", true); +const aspect = op.inValue("Aspect Ratio", 1); + +// look at camera +const eyeX = op.inValue("eye X", 0); +const eyeY = op.inValue("eye Y", 0); +const eyeZ = op.inValue("eye Z", 5); + +const centerX = op.inValue("center X", 0); +const centerY = op.inValue("center Y", 0); +const centerZ = op.inValue("center Z", 0); + +// camera transform and movements +const posX = op.inValue("truck", 0); +const posY = op.inValue("boom", 0); +const posZ = op.inValue("dolly", 0); + +const rotX = op.inValue("tilt", 0); +const rotY = op.inValue("pan", 0); +const rotZ = op.inValue("roll", 0); + +/* Outputs */ +const outAsp = op.outNumber("Aspect"); +const outArr = op.outArray("Look At Array"); + +/* logic */ +const cgl = op.patch.cgl; + +let asp = 0; + +const vUp = vec3.create(); +const vEye = vec3.create(); +const vCenter = vec3.create(); +const transMatrix = mat4.create(); +mat4.identity(transMatrix); + +const arr = []; + +// Transform and move +const vPos = vec3.create(); +const transMatrixMove = mat4.create(); +mat4.identity(transMatrixMove); + +let updateCameraMovementMatrix = true; + +render.onTriggered = function () +{ + if (cgl.frameStore.shadowPass) return trigger.trigger(); + + // Aspect ration + if (!autoAspect.get()) asp = aspect.get(); + else asp = cgl.getViewPort()[2] / cgl.getViewPort()[3]; + outAsp.set(asp); + + // translation (truck, boom, dolly) + cgl.pushViewMatrix(); + + if (updateCameraMovementMatrix) + { + mat4.identity(transMatrixMove); + + vec3.set(vPos, posX.get(), posY.get(), posZ.get()); + if (posX.get() !== 0.0 || posY.get() !== 0.0 || posZ.get() !== 0.0) + mat4.translate(transMatrixMove, transMatrixMove, vPos); + + if (rotX.get() !== 0) + mat4.rotateX(transMatrixMove, transMatrixMove, rotX.get() * CGL.DEG2RAD); + if (rotY.get() !== 0) + mat4.rotateY(transMatrixMove, transMatrixMove, rotY.get() * CGL.DEG2RAD); + if (rotZ.get() !== 0) + mat4.rotateZ(transMatrixMove, transMatrixMove, rotZ.get() * CGL.DEG2RAD); + + updateCameraMovementMatrix = false; + } + + mat4.multiply(cgl.vMatrix, cgl.vMatrix, transMatrixMove); + + // projection (prespective / ortogonal) + cgl.pushPMatrix(); + + // look at + cgl.pushViewMatrix(); + + if (projectionMode.get() == "prespective") + { + mat4.perspective( + cgl.pMatrix, + fov.get() * 0.0174533, + asp, + zNear.get(), + zFar.get() + ); + } + else if (projectionMode.get() == "ortogonal") + { + mat4.ortho( + cgl.pMatrix, + -1 * (fov.get() / 14), + 1 * (fov.get() / 14), + -1 * (fov.get() / 14) / asp, + 1 * (fov.get() / 14) / asp, + zNear.get(), + zFar.get() + ); + } + + arr[0] = eyeX.get(); + arr[1] = eyeY.get(); + arr[2] = eyeZ.get(); + + arr[3] = centerX.get(); + arr[4] = centerY.get(); + arr[5] = centerZ.get(); + + arr[6] = 0; + arr[7] = 1; + arr[8] = 0; + + outArr.set(null); + outArr.set(arr); + + vec3.set(vUp, 0, 1, 0); + vec3.set(vEye, eyeX.get(), eyeY.get(), eyeZ.get()); + vec3.set(vCenter, centerX.get(), centerY.get(), centerZ.get()); + + mat4.lookAt(transMatrix, vEye, vCenter, vUp); + + mat4.multiply(cgl.vMatrix, cgl.vMatrix, transMatrix); + + trigger.trigger(); + + cgl.popViewMatrix(); + cgl.popPMatrix(); + + cgl.popViewMatrix(); + + // GUI for dolly, boom and truck + if (op.isCurrentUiOp()) + gui.setTransformGizmo({ + "posX": posX, + "posY": posY, + "posZ": posZ + }); +}; + +const updateUI = function () +{ + if (!autoAspect.get()) + { + aspect.setUiAttribs({ "greyout": false }); + } + else + { + aspect.setUiAttribs({ "greyout": true }); + } +}; + +const cameraMovementChanged = function () +{ + updateCameraMovementMatrix = true; +}; + +// listeners +posX.onChange = cameraMovementChanged; +posY.onChange = cameraMovementChanged; +posZ.onChange = cameraMovementChanged; + +rotX.onChange = cameraMovementChanged; +rotY.onChange = cameraMovementChanged; +rotZ.onChange = cameraMovementChanged; + +autoAspect.onChange = updateUI; +updateUI(); + + +}; + +Ops.Gl.Matrix.Camera.prototype = new CABLES.Op(); +CABLES.OPS["b24dbfdc-485c-49d2-92a1-7258efd9239a"]={f:Ops.Gl.Matrix.Camera,objName:"Ops.Gl.Matrix.Camera"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.CameraInfo +// +// ************************************************************** + +Ops.Gl.Matrix.CameraInfo = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + cameraType = op.inSwitch("Camera Type", ["Perspective", "Orthographic"], "Perspective"), + trigger = op.outTrigger("trigger"), + outX = op.outNumber("X"), + outY = op.outNumber("Y"), + outZ = op.outNumber("Z"), + outRightX = op.outNumber("Right X"), + outRightY = op.outNumber("Right Y"), + outRightZ = op.outNumber("Right Z"), + outUpX = op.outNumber("Up X"), + outUpY = op.outNumber("Up Y"), + outUpZ = op.outNumber("Up Z"), + outForwardX = op.outNumber("Forward X"), + outForwardY = op.outNumber("Forward Y"), + outForwardZ = op.outNumber("Forward Z"), + outNear = op.outNumber("Near Frustum"), + outFar = op.outNumber("Far Frustum"), + outTop = op.outNumber("Bottom Frustum"), + outBottom = op.outNumber("Top Frustum"), + outLeft = op.outNumber("Left Frustum"), + outRight = op.outNumber("Right Frustum"), + outFov = op.outNumber("FOV"), + outAspect = op.outNumber("Aspect Ratio"); +const + cgl = op.patch.cgl, + pos = vec3.create(), + identVec = vec3.create(), + iViewMatrix = mat4.create(); +render.onTriggered = update; + +function update() +{ + mat4.invert(iViewMatrix, cgl.vMatrix); + + outRightX.set(iViewMatrix[0]); + outRightY.set(iViewMatrix[1]); + outRightZ.set(iViewMatrix[2]); + + outUpX.set(iViewMatrix[4]); + outUpY.set(iViewMatrix[5]); + outUpZ.set(iViewMatrix[6]); + + outForwardX.set(iViewMatrix[8]); + outForwardY.set(iViewMatrix[9]); + outForwardZ.set(iViewMatrix[10]); + + outX.set(iViewMatrix[12]); + outY.set(iViewMatrix[13]); + outZ.set(iViewMatrix[14]); + + // https://stackoverflow.com/questions/10830293/decompose-projection-matrix44-to-left-right-bottom-top-near-and-far-boundary/10836497#10836497 + const m11 = cgl.pMatrix[4 * 0 + 0]; + const m13 = cgl.pMatrix[4 * 2 + 0]; + const m14 = cgl.pMatrix[4 * 3 + 0]; + const m22 = cgl.pMatrix[4 * 1 + 1]; + const m23 = cgl.pMatrix[4 * 2 + 1]; + const m24 = cgl.pMatrix[4 * 3 + 1]; + const m33 = cgl.pMatrix[4 * 2 + 2]; + const m34 = cgl.pMatrix[4 * 3 + 2]; + + // https://stackoverflow.com/questions/46182845/field-of-view-aspect-ratio-view-matrix-from-projection-matrix-hmd-ost-calib + const FOV = 2 * Math.atan(1 / m22) * 180 / Math.PI; + const aspectRatio = m22 / m11; + + outFov.set(FOV); + outAspect.set(aspectRatio); + if (cameraType.get() === "Perspective") + { + const near = m34 / (m33 - 1); + const far = m34 / (m33 + 1); + const top = near * (m23 + 1) / m22; + const bottom = near * (m23 - 1) / m22; + const left = near * (m13 - 1) / m11; + const right = near * (m13 + 1) / m11; + + outNear.set(near); + outFar.set(far); + outTop.set(top); + outBottom.set(bottom); + outLeft.set(left); + outRight.set(right); + } + else if (cameraType.get() === "Orthographic") + { + const near = (1 + m34) / m33; + const far = -(1 - m34) / m33; + const bottom = near * (m23 - 1) / m22; + const top = near * (m23 + 1) / m22; + const left = near * (m13 - 1) / m11; + const right = near * (m13 + 1) / m11; + + outNear.set(near); + outFar.set(far); + outTop.set(top); + outBottom.set(bottom); + outLeft.set(left); + outRight.set(right); + } + + trigger.trigger(); +} + + +}; + +Ops.Gl.Matrix.CameraInfo.prototype = new CABLES.Op(); +CABLES.OPS["92a0c536-f2bf-4972-9f02-a9accf26c1df"]={f:Ops.Gl.Matrix.CameraInfo,objName:"Ops.Gl.Matrix.CameraInfo"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.CameraPosition +// +// ************************************************************** + +Ops.Gl.Matrix.CameraPosition = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + outX = op.outNumber("X"), + outY = op.outNumber("Y"), + outZ = op.outNumber("Z"); + +const + cgl = op.patch.cgl, + pos = vec3.create(), + identVec = vec3.create(), + iViewMatrix = mat4.create(); + +render.onTriggered = update; + +function update() +{ + mat4.invert(iViewMatrix, cgl.vMatrix); + vec3.transformMat4(pos, identVec, iViewMatrix); + + outX.set(pos[0]); + outY.set(pos[1]); + outZ.set(pos[2]); + + trigger.trigger(); +} + + +}; + +Ops.Gl.Matrix.CameraPosition.prototype = new CABLES.Op(); +CABLES.OPS["eff9a971-d9dd-4999-94b1-9a5cbba13581"]={f:Ops.Gl.Matrix.CameraPosition,objName:"Ops.Gl.Matrix.CameraPosition"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.Coordinates +// +// ************************************************************** + +Ops.Gl.Matrix.Coordinates = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + outX = op.outNumber("X"), + outY = op.outNumber("Y"), + outZ = op.outNumber("Z"), + pos = vec3.create(), + empty = vec3.create(); + +render.onTriggered = function () +{ + const cg = op.patch.cg; + + vec3.transformMat4(pos, empty, cg.mMatrix); + + outX.set(pos[0]); + outY.set(pos[1]); + outZ.set(pos[2]); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.Matrix.Coordinates.prototype = new CABLES.Op(); +CABLES.OPS["390d0214-92a9-48e9-85b4-f3092ee9e043"]={f:Ops.Gl.Matrix.Coordinates,objName:"Ops.Gl.Matrix.Coordinates"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.DeviceOrientationCamera +// +// ************************************************************** + +Ops.Gl.Matrix.DeviceOrientationCamera = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Render"), + next = op.outTrigger("Next"), + winOrient = op.outNumber("Window Orientation"), + cgl = op.patch.cgl, + vCenter = vec3.create(), + transMatrix = mat4.create(), + displayOrientQuat = quat.create(), + displayOrientMatrix = mat4.create(); + +window.addEventListener("deviceorientation", onOrientationChange, true); +let tempQuat = quat.create(); +mat4.identity(transMatrix); + +const viewDirQuat = quat.create(); + +render.onTriggered = function () +{ + // check for new permission request on IOS or android + if (DeviceMotionEvent && DeviceMotionEvent.requestPermission) + { + DeviceOrientationEvent.requestPermission() + .then((response) => + { + if (response == "granted") + { + window.addEventListener("deviceorientation", onOrientationChange, true); + } + }) + .catch(op.error); + } + else + { + window.addEventListener("deviceorientation", onOrientationChange, true); + } + + if (window.orientation === undefined) + { + next.trigger(); + return; + } + + cgl.pushViewMatrix(); + + tempQuat = quat.clone(viewDirQuat); + quat.invert(tempQuat, tempQuat); + + if (window.orientation == 90 || window.orientation == -90) + { + quat.setAxisAngle(displayOrientQuat, [0, 0, 1], window.orientation * CGL.DEG2RAD); + quat.multiply(tempQuat, displayOrientQuat, tempQuat); + } + + mat4.fromQuat(transMatrix, tempQuat); + // added rotateX by 90 as orientation was incorrect + mat4.rotateX(transMatrix, transMatrix, 90.0 * CGL.DEG2RAD); + mat4.rotateY(transMatrix, transMatrix, 90.0 * CGL.DEG2RAD); + mat4.multiply(cgl.vMatrix, cgl.vMatrix, transMatrix); + + // mat4.translate(cgl.vMatrix,cgl.vMatrix,[1,0,0]);//original code + + next.trigger(); + cgl.popViewMatrix(); +}; + +// frp, http://asterixcreative.com/blog/mobile-gyroscope-with-javascript-and-quaternions-programming-tutorial-part-1/ +function quatFromEuler(quat, alpha, beta, gamma) +{ + const x = CGL.DEG2RAD * beta; + const y = CGL.DEG2RAD * gamma; + const z = CGL.DEG2RAD * alpha; + + const cX = Math.cos(x / 2); + const cY = Math.cos(y / 2); + const cZ = Math.cos(z / 2); + const sX = Math.sin(x / 2); + const sY = Math.sin(y / 2); + const sZ = Math.sin(z / 2); + + quat[0] = sX * cY * cZ - cX * sY * sZ; + quat[1] = cX * sY * cZ + sX * cY * sZ; + quat[2] = cX * cY * sZ + sX * sY * cZ; + quat[3] = cX * cY * cZ - sX * sY * sZ; + + return quat; +} + +function onOrientationChange(event) +{ + const alpha = (event.alpha || 0); + const beta = (event.beta || 0); + const gamma = (event.gamma || 0); + + winOrient.set(window.orientation || 0); + quatFromEuler(viewDirQuat, alpha, beta, gamma); +} + + +}; + +Ops.Gl.Matrix.DeviceOrientationCamera.prototype = new CABLES.Op(); +CABLES.OPS["c213a5b4-6a47-425a-9457-ae0b14c88e9a"]={f:Ops.Gl.Matrix.DeviceOrientationCamera,objName:"Ops.Gl.Matrix.DeviceOrientationCamera"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.GetMatrixScaling +// +// ************************************************************** + +Ops.Gl.Matrix.GetMatrixScaling = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + inArr = op.inArray("Matrix"), + trigger = op.outTrigger("trigger"), + outX = op.outNumber("Scaling"); + +const cgl = op.patch.cgl; +const pos = vec3.create(); +const identVec = vec3.create(); +const iViewMatrix = mat4.create(); + +function getScaling(mat) +{ + let m31 = mat[8]; + let m32 = mat[9]; + let m33 = mat[10]; + + return Math.hypot(m31, m32, m33); +} + +render.onTriggered = function () +{ + if (!inArr.get()) return; + + outX.set(getScaling(cgl.mMatrix)); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.Matrix.GetMatrixScaling.prototype = new CABLES.Op(); +CABLES.OPS["3bcc8ae2-0837-4560-90dc-ae7836ee9db0"]={f:Ops.Gl.Matrix.GetMatrixScaling,objName:"Ops.Gl.Matrix.GetMatrixScaling"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.GetModelMatrix +// +// ************************************************************** + +Ops.Gl.Matrix.GetModelMatrix = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + matrix = op.outArray("matrix"); + +const m = mat4.create(); + +render.onTriggered = function () +{ + mat4.copy(m, op.patch.cg.mMatrix); + matrix.set(null); + matrix.set(m); + trigger.trigger(); +}; + +matrix.set([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); + + +}; + +Ops.Gl.Matrix.GetModelMatrix.prototype = new CABLES.Op(); +CABLES.OPS["2d96f0a3-979a-4dc3-8c49-848f08efe0e0"]={f:Ops.Gl.Matrix.GetModelMatrix,objName:"Ops.Gl.Matrix.GetModelMatrix"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.GetProjectonMatrix +// +// ************************************************************** + +Ops.Gl.Matrix.GetProjectonMatrix = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + cgl = op.patch.cgl, + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + matrix = op.outArray("matrix", null, 16); + +let m = mat4.create(); +mat4.identity(m); +matrix.set(m); + +render.onTriggered = function () +{ + mat4.copy(m, cgl.pMatrix); + matrix.set(null); + matrix.set(m); + trigger.trigger(); +}; + + +}; + +Ops.Gl.Matrix.GetProjectonMatrix.prototype = new CABLES.Op(); +CABLES.OPS["3f048006-89e9-4e3f-a7d3-42aaa77ed630"]={f:Ops.Gl.Matrix.GetProjectonMatrix,objName:"Ops.Gl.Matrix.GetProjectonMatrix"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.GetViewMatrix +// +// ************************************************************** + +Ops.Gl.Matrix.GetViewMatrix = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let render = op.inTrigger("render"); +let trigger = op.outTrigger("trigger"); +let matrix = op.addOutPort(new CABLES.Port(op, "matrix", CABLES.OP_PORT_TYPE_ARRAY)); + +let m = mat4.create(); + +render.onTriggered = function () +{ + mat4.copy(m, op.patch.cg.vMatrix); + matrix.set(null); + matrix.set(m); + trigger.trigger(); +}; + +matrix.set([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); + + +}; + +Ops.Gl.Matrix.GetViewMatrix.prototype = new CABLES.Op(); +CABLES.OPS["a58406ae-79b5-4dab-99fa-0a66c2325aab"]={f:Ops.Gl.Matrix.GetViewMatrix,objName:"Ops.Gl.Matrix.GetViewMatrix"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.InterpolateMatrix +// +// ************************************************************** + +Ops.Gl.Matrix.InterpolateMatrix = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe = op.inTrigger("Exe"); +const inArr1 = op.inArray("Array 1"); +const inArr2 = op.inArray("Array 2"); +const inPerc = op.inValueSlider("perc"); +const next = op.outTrigger("Next"); +const outArr = op.outArray("Result"); + +const result = mat4.create(); + +function ip(val1, val2, perc) +{ + return ((val2 - val1) * perc + val1); +} + +const a = vec3.create(); +const b = vec3.create(); + +exe.onTriggered = function () +{ + const arr1 = inArr1.get(); + const arr2 = inArr2.get(); + + if (!arr1 || !arr2 || arr1.length != arr2.length) + { + outArr.set(null); + op.logError("arrays wrong"); + } + else + { + getYPR(a, arr1); + getYPR(b, arr2); + + const perc = inPerc.get(); + + mat4.identity(result); + result[12] = ip(arr1[12], arr2[12], perc); + result[13] = ip(arr1[13], arr2[13], perc); + result[14] = ip(arr1[14], arr2[14], perc); + + vec3.lerp(a, a, b, perc); + + mat4.rotateZ(result, result, a[2]); + mat4.rotateY(result, result, a[1]); + mat4.rotateX(result, result, a[0]); + + outArr.set(null); + outArr.set(result); + } + next.trigger(); +}; + +// 0 1 2 3 +// 4 5 6 7 +// 8 9 10 11 +// 12 13 14 15 + +function getYPR(v, m) +{ + const r1 = Math.atan2(m[6], m[10]); + const c2 = Math.sqrt(m[0] * m[0] + m[1] * m[1]); + const r2 = Math.atan2(-m[2], c2); + const s1 = Math.sin(r1); + const c1 = Math.cos(r1); + const r3 = Math.atan2(s1 * m[8] - c1 * m[4], c1 * m[5] - s1 * m[9]); + + v[0] = r1; + v[1] = r2; + v[2] = r3; + return v; +} + + +}; + +Ops.Gl.Matrix.InterpolateMatrix.prototype = new CABLES.Op(); +CABLES.OPS["84e1908b-fc17-47db-9ba1-bc38d7809076"]={f:Ops.Gl.Matrix.InterpolateMatrix,objName:"Ops.Gl.Matrix.InterpolateMatrix"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.InvertMatrix +// +// ************************************************************** + +Ops.Gl.Matrix.InvertMatrix = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inMat = op.inArray("Matrix"), + outMat = op.outArray("Result"); + +const m = mat4.create(); + +inMat.onChange = () => +{ + if (!inMat.get()) return; + mat4.invert(m, inMat.get()); + outMat.set(null); + outMat.set(m); +}; + + +}; + +Ops.Gl.Matrix.InvertMatrix.prototype = new CABLES.Op(); +CABLES.OPS["2ebd0d87-f67a-4101-bdf0-283c610b095a"]={f:Ops.Gl.Matrix.InvertMatrix,objName:"Ops.Gl.Matrix.InvertMatrix"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.LookatCamera +// +// ************************************************************** + +Ops.Gl.Matrix.LookatCamera = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const render = op.inTrigger("render"); +const trigger = op.outTrigger("trigger"); + +const eyeX = op.inValueFloat("eyeX"); +const eyeY = op.inValueFloat("eyeY"); +const eyeZ = op.inValueFloat("eyeZ"); + +const centerX = op.inValueFloat("centerX"); +const centerY = op.inValueFloat("centerY"); +const centerZ = op.inValueFloat("centerZ"); + +const vecUpX = op.inValueFloat("upX"); +const vecUpY = op.inValueFloat("upY"); +const vecUpZ = op.inValueFloat("upZ"); + +const outArr = op.outArray("Array"); + +centerX.set(0); +centerY.set(0); +centerZ.set(0); + +eyeX.set(5); +eyeY.set(5); +eyeZ.set(5); + +vecUpX.set(0); +vecUpY.set(1); +vecUpZ.set(0); + +const cgl = op.patch.cgl; +const vUp = vec3.create(); +const vEye = vec3.create(); +const vCenter = vec3.create(); +const transMatrix = mat4.create(); +mat4.identity(transMatrix); + +const arr = []; + + +render.onTriggered = function () +{ + if (cgl.frameStore.shadowPass) return trigger.trigger(); + + + if (op.isCurrentUiOp()) + gui.setTransformGizmo( + { + "posX": eyeX, + "posY": eyeY, + "posZ": eyeZ + }); + + + cgl.pushViewMatrix(); + + arr[0] = eyeX.get(); + arr[1] = eyeY.get(); + arr[2] = eyeZ.get(); + + arr[3] = centerX.get(); + arr[4] = centerY.get(); + arr[5] = centerZ.get(); + + arr[6] = vecUpX.get(); + arr[7] = vecUpY.get(); + arr[8] = vecUpZ.get(); + outArr.set(null); + outArr.set(arr); + + vec3.set(vUp, vecUpX.get(), vecUpY.get(), vecUpZ.get()); + vec3.set(vEye, eyeX.get(), eyeY.get(), eyeZ.get()); + vec3.set(vCenter, centerX.get(), centerY.get(), centerZ.get()); + + mat4.lookAt(transMatrix, vEye, vCenter, vUp); + + mat4.multiply(cgl.vMatrix, cgl.vMatrix, transMatrix); + + trigger.trigger(); + cgl.popViewMatrix(); +}; + + +}; + +Ops.Gl.Matrix.LookatCamera.prototype = new CABLES.Op(); +CABLES.OPS["e0f1bad6-7dfb-4665-b458-ca50a1bfe7fa"]={f:Ops.Gl.Matrix.LookatCamera,objName:"Ops.Gl.Matrix.LookatCamera"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.MatrixTranslation +// +// ************************************************************** + +Ops.Gl.Matrix.MatrixTranslation = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + inArr = op.inArray("Matrix"), + trigger = op.outTrigger("trigger"), + outX = op.outNumber("X"), + outY = op.outNumber("Y"), + outZ = op.outNumber("Z"); + +const cgl = op.patch.cgl; +const pos = vec3.create(); +const identVec = vec3.create(); +const iViewMatrix = mat4.create(); + +render.onTriggered = function () +{ + if (!inArr.get()) return; + + mat4.invert(iViewMatrix, inArr.get()); + vec3.transformMat4(pos, identVec, iViewMatrix); + + outX.set(pos[0]); + outY.set(pos[1]); + outZ.set(pos[2]); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.Matrix.MatrixTranslation.prototype = new CABLES.Op(); +CABLES.OPS["d5ba91a4-d419-4805-b37f-595c261615b3"]={f:Ops.Gl.Matrix.MatrixTranslation,objName:"Ops.Gl.Matrix.MatrixTranslation"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.MulViewMatrix +// +// ************************************************************** + +Ops.Gl.Matrix.MulViewMatrix = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + matrix = op.inArray("matrix"), + inIdentity = op.inValueBool("Identity", false), + trigger = op.outTrigger("trigger"); + +const m = mat4.create(); +const cgl = this.patch.cgl; + +matrix.set([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); + +render.onTriggered = function () +{ + cgl.pushViewMatrix(); + + if (matrix.get()) + { + if (inIdentity.get()) mat4.identity(cgl.vMatrix); + + mat4.multiply(cgl.vMatrix, cgl.vMatrix, matrix.get()); + } + + trigger.trigger(); + cgl.popViewMatrix(); +}; + + +}; + +Ops.Gl.Matrix.MulViewMatrix.prototype = new CABLES.Op(); +CABLES.OPS["c2833486-717e-4f3c-9dd8-c62cc92ea46e"]={f:Ops.Gl.Matrix.MulViewMatrix,objName:"Ops.Gl.Matrix.MulViewMatrix"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.MultiplyModelMatrix +// +// ************************************************************** + +Ops.Gl.Matrix.MultiplyModelMatrix = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let cgl = op.patch.cgl; +let render = op.inTrigger("render"); +let inIdentity = op.inValueBool("Identity", false); +let next = op.outTrigger("trigger"); + +let m = mat4.create(); +let matrix = op.inArray("matrix"); + +render.onTriggered = function () +{ + cgl.pushModelMatrix(); + + if (inIdentity.get()) mat4.identity(cgl.mMatrix); + + const m = matrix.get(); + + if (m) mat4.multiply(cgl.mMatrix, cgl.mMatrix, m); + + next.trigger(); + cgl.popModelMatrix(); +}; + +matrix.set([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); + + +}; + +Ops.Gl.Matrix.MultiplyModelMatrix.prototype = new CABLES.Op(); +CABLES.OPS["ec2784ab-9174-4052-894b-744a18e0d348"]={f:Ops.Gl.Matrix.MultiplyModelMatrix,objName:"Ops.Gl.Matrix.MultiplyModelMatrix"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.OrbitControls +// +// ************************************************************** + +Ops.Gl.Matrix.OrbitControls = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + minDist = op.inValueFloat("min distance"), + maxDist = op.inValueFloat("max distance"), + + minRotY = op.inValue("min rot y", 0), + maxRotY = op.inValue("max rot y", 0), + + initialRadius = op.inValue("initial radius", 0), + initialAxis = op.inValueSlider("initial axis y"), + initialX = op.inValueSlider("initial axis x"), + + mul = op.inValueFloat("mul"), + smoothness = op.inValueSlider("Smoothness", 1.0), + speedX = op.inValue("Speed X", 1), + speedY = op.inValue("Speed Y", 1), + + active = op.inValueBool("Active", true), + + allowPanning = op.inValueBool("Allow Panning", true), + allowZooming = op.inValueBool("Allow Zooming", true), + allowRotation = op.inValueBool("Allow Rotation", true), + restricted = op.inValueBool("restricted", true), + + trigger = op.outTrigger("trigger"), + outRadius = op.outNumber("radius"), + outXDeg = op.outNumber("Rot X"), + outYDeg = op.outNumber("Rot Y"), + + inReset = op.inTriggerButton("Reset"); + +op.setPortGroup("Initial Values", [initialAxis, initialX, initialRadius]); +op.setPortGroup("Interaction", [mul, smoothness, speedX, speedY]); +op.setPortGroup("Boundaries", [minRotY, maxRotY, minDist, maxDist]); + +mul.set(1); +minDist.set(0.05); +maxDist.set(99999); + +inReset.onTriggered = reset; + +let eye = vec3.create(); +const vUp = vec3.create(); +const vCenter = vec3.create(); +const viewMatrix = mat4.create(); +const tempViewMatrix = mat4.create(); +const vOffset = vec3.create(); +const finalEyeAbs = vec3.create(); + +initialAxis.set(0.5); + +let mouseDown = false; +let radius = 5; +outRadius.set(radius); + +let lastMouseX = 0, lastMouseY = 0; +let percX = 0, percY = 0; + +vec3.set(vCenter, 0, 0, 0); +vec3.set(vUp, 0, 1, 0); + +const tempEye = vec3.create(); +const finalEye = vec3.create(); +const tempCenter = vec3.create(); +const finalCenter = vec3.create(); + +let px = 0; +let py = 0; + +let divisor = 1; +let element = null; +updateSmoothness(); + +op.onDelete = unbind; + +const halfCircle = Math.PI; +const fullCircle = Math.PI * 2; + +function reset() +{ + let off = 0; + + if (px % fullCircle < -halfCircle) + { + off = -fullCircle; + px %= -fullCircle; + } + else + if (px % fullCircle > halfCircle) + { + off = fullCircle; + px %= fullCircle; + } + else px %= fullCircle; + + py %= (Math.PI); + + vec3.set(vOffset, 0, 0, 0); + vec3.set(vCenter, 0, 0, 0); + vec3.set(vUp, 0, 1, 0); + + percX = (initialX.get() * Math.PI * 2 + off); + percY = (initialAxis.get() - 0.5); + + radius = initialRadius.get(); + eye = circlePos(percY); +} + +function updateSmoothness() +{ + divisor = smoothness.get() * 10 + 1.0; +} + +smoothness.onChange = updateSmoothness; + +let initializing = true; + +function ip(val, goal) +{ + if (initializing) return goal; + return val + (goal - val) / divisor; +} + +let lastPy = 0; +const lastPx = 0; + +render.onTriggered = function () +{ + const cgl = op.patch.cg; + + if (!element) + { + setElement(cgl.canvas); + bind(); + } + + cgl.pushViewMatrix(); + + px = ip(px, percX); + py = ip(py, percY); + + let degY = (py + 0.5) * 180; + + if (minRotY.get() !== 0 && degY < minRotY.get()) + { + degY = minRotY.get(); + py = lastPy; + } + else if (maxRotY.get() !== 0 && degY > maxRotY.get()) + { + degY = maxRotY.get(); + py = lastPy; + } + else + { + lastPy = py; + } + + const degX = (px) * CGL.RAD2DEG; + + outYDeg.set(degY); + outXDeg.set(degX); + + circlePosi(eye, py); + + vec3.add(tempEye, eye, vOffset); + vec3.add(tempCenter, vCenter, vOffset); + + finalEye[0] = ip(finalEye[0], tempEye[0]); + finalEye[1] = ip(finalEye[1], tempEye[1]); + finalEye[2] = ip(finalEye[2], tempEye[2]); + + finalCenter[0] = ip(finalCenter[0], tempCenter[0]); + finalCenter[1] = ip(finalCenter[1], tempCenter[1]); + finalCenter[2] = ip(finalCenter[2], tempCenter[2]); + + const empty = vec3.create(); + + mat4.lookAt(viewMatrix, finalEye, finalCenter, vUp); + mat4.rotate(viewMatrix, viewMatrix, px, vUp); + + // finaly multiply current scene viewmatrix + mat4.multiply(cgl.vMatrix, cgl.vMatrix, viewMatrix); + + trigger.trigger(); + cgl.popViewMatrix(); + initializing = false; +}; + +function circlePosi(vec, perc) +{ + const mmul = mul.get(); + if (radius < minDist.get() * mmul) radius = minDist.get() * mmul; + if (radius > maxDist.get() * mmul) radius = maxDist.get() * mmul; + + outRadius.set(radius * mmul); + + let i = 0, degInRad = 0; + + degInRad = 360 * perc / 2 * CGL.DEG2RAD; + vec3.set(vec, + Math.cos(degInRad) * radius * mmul, + Math.sin(degInRad) * radius * mmul, + 0); + return vec; +} + +function circlePos(perc) +{ + const mmul = mul.get(); + if (radius < minDist.get() * mmul)radius = minDist.get() * mmul; + if (radius > maxDist.get() * mmul)radius = maxDist.get() * mmul; + + outRadius.set(radius * mmul); + + let i = 0, degInRad = 0; + const vec = vec3.create(); + degInRad = 360 * perc / 2 * CGL.DEG2RAD; + vec3.set(vec, + Math.cos(degInRad) * radius * mmul, + Math.sin(degInRad) * radius * mmul, + 0); + return vec; +} + +function onmousemove(event) +{ + if (!mouseDown) return; + + const x = event.clientX; + const y = event.clientY; + + let movementX = (x - lastMouseX); + let movementY = (y - lastMouseY); + + movementX *= speedX.get(); + movementY *= speedY.get(); + + if (event.buttons == 2 && allowPanning.get()) + { + vOffset[2] += movementX * 0.01 * mul.get(); + vOffset[1] += movementY * 0.01 * mul.get(); + } + else + if (event.buttons == 4 && allowZooming.get()) + { + radius += movementY * 0.05; + eye = circlePos(percY); + } + else + { + if (allowRotation.get()) + { + percX += movementX * 0.003; + percY += movementY * 0.002; + + if (restricted.get()) + { + if (percY > 0.5)percY = 0.5; + if (percY < -0.5)percY = -0.5; + } + } + } + + lastMouseX = x; + lastMouseY = y; +} + +function onMouseDown(event) +{ + lastMouseX = event.clientX; + lastMouseY = event.clientY; + mouseDown = true; + + try { element.setPointerCapture(event.pointerId); } + catch (e) {} +} + +function onMouseUp(e) +{ + mouseDown = false; + // cgl.canvas.style.cursor='url(/ui/img/rotate.png),pointer'; + + try { element.releasePointerCapture(e.pointerId); } + catch (e) {} +} + +function lockChange() +{ + const el = op.patch.cg.canvas; + + if (document.pointerLockElement === el || document.mozPointerLockElement === el || document.webkitPointerLockElement === el) + { + document.addEventListener("mousemove", onmousemove, false); + } +} + +function onMouseEnter(e) +{ + // cgl.canvas.style.cursor='url(/ui/img/rotate.png),pointer'; +} + +initialRadius.onChange = function () +{ + radius = initialRadius.get(); + reset(); +}; + +initialX.onChange = function () +{ + px = percX = (initialX.get() * Math.PI * 2); +}; + +initialAxis.onChange = function () +{ + py = percY = (initialAxis.get() - 0.5); + eye = circlePos(percY); +}; + +const onMouseWheel = function (event) +{ + if (allowZooming.get()) + { + const delta = CGL.getWheelSpeed(event) * 0.06; + radius += (parseFloat(delta)) * 1.2; + + eye = circlePos(percY); + } +}; + +const ontouchstart = function (event) +{ + if (event.touches && event.touches.length > 0) onMouseDown(event.touches[0]); +}; + +const ontouchend = function (event) +{ + onMouseUp(); +}; + +const ontouchmove = function (event) +{ + if (event.touches && event.touches.length > 0) onmousemove(event.touches[0]); +}; + +active.onChange = function () +{ + if (active.get())bind(); + else unbind(); +}; + +function setElement(ele) +{ + unbind(); + element = ele; + bind(); +} + +function bind() +{ + if (!element) return; + + element.addEventListener("pointermove", onmousemove); + element.addEventListener("pointerdown", onMouseDown); + element.addEventListener("pointerup", onMouseUp); + element.addEventListener("pointerleave", onMouseUp); + element.addEventListener("pointerenter", onMouseEnter); + element.addEventListener("contextmenu", function (e) { e.preventDefault(); }); + element.addEventListener("wheel", onMouseWheel, { "passive": true }); +} + +function unbind() +{ + if (!element) return; + + element.removeEventListener("pointermove", onmousemove); + element.removeEventListener("pointerdown", onMouseDown); + element.removeEventListener("pointerup", onMouseUp); + element.removeEventListener("pointerleave", onMouseUp); + element.removeEventListener("pointerenter", onMouseUp); + element.removeEventListener("wheel", onMouseWheel); +} + +eye = circlePos(0); + +initialX.set(0.25); +initialRadius.set(0.05); + + +}; + +Ops.Gl.Matrix.OrbitControls.prototype = new CABLES.Op(); +CABLES.OPS["eaf4f7ce-08a3-4d1b-b9f4-ebc0b7b1cde1"]={f:Ops.Gl.Matrix.OrbitControls,objName:"Ops.Gl.Matrix.OrbitControls"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.Quaternion +// +// ************************************************************** + +Ops.Gl.Matrix.Quaternion = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + x = op.inValueFloat("x"), + y = op.inValueFloat("y"), + z = op.inValueFloat("z"), + w = op.inValueFloat("w"); + +let q = quat.create(); +let qMat = mat4.create(); +let cgl = op.patch.cgl; +render.onTriggered = function () +{ + if (x.isAnimated()) + { + let time = op.patch.timer.getTime(); + CABLES.TL.Anim.slerpQuaternion(time, q, x.anim, y.anim, z.anim, w.anim); + } + else + { + quat.set(q, x.get(), y.get(), z.get(), w.get()); + } + cgl.pushModelMatrix(); + + mat4.fromQuat(qMat, q); + mat4.multiply(cgl.mMatrix, cgl.mMatrix, qMat); + + trigger.trigger(); + cgl.popModelMatrix(); +}; + + +}; + +Ops.Gl.Matrix.Quaternion.prototype = new CABLES.Op(); +CABLES.OPS["e256892f-7f68-4113-9eb8-cd981026ea8b"]={f:Ops.Gl.Matrix.Quaternion,objName:"Ops.Gl.Matrix.Quaternion"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.QuaternionCamera +// +// ************************************************************** + +Ops.Gl.Matrix.QuaternionCamera = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + + eyeX = op.inValueFloat("eyeX", 5), + eyeY = op.inValueFloat("eyeY", 5), + eyeZ = op.inValueFloat("eyeZ", 5), + + quatX = op.inValueFloat("quatX", 0), + quatY = op.inValueFloat("quatY", 0), + quatZ = op.inValueFloat("quatZ", 0), + quatW = op.inValueFloat("quatW", 0), + + vecUpX = op.inValueFloat("upX", 0), + vecUpY = op.inValueFloat("upY", 1), + vecUpZ = op.inValueFloat("upZ", 0); + +const cgl = op.patch.cgl; +const vUp = vec3.create(); +const vEye = vec3.create(); +const vCenter = vec3.create(); +const vQuat = quat.create(); +const transMatrix = mat4.create(); +mat4.identity(transMatrix); + + +// arr[i*3+0]=n._animTrans[0].getValue(t); + +// arrRot[i*4+3]=n._animRot[3].getValue(t); + + +const arr = []; + +render.onTriggered = function () +{ + if (cgl.frameStore.shadowPass) return trigger.trigger(); + + if (op.isCurrentUiOp()) + gui.setTransformGizmo( + { + "posX": eyeX, + "posY": eyeY, + "posZ": eyeZ + }); + + cgl.pushViewMatrix(); + + quat.set(vQuat, quatX.get(), quatY.get(), quatZ.get(), quatW.get()); + + vec3.set(vUp, vecUpX.get(), vecUpY.get(), vecUpZ.get()); + vec3.set(vEye, eyeX.get(), eyeY.get(), eyeZ.get()); + + vec3.set(vCenter, 0, -1, 0); + vec3.transformQuat(vCenter, vCenter, vQuat); + vec3.normalize(vCenter, vCenter); + vec3.add(vCenter, vCenter, vEye); + + mat4.lookAt(transMatrix, vEye, vCenter, vUp); + + mat4.multiply(cgl.vMatrix, cgl.vMatrix, transMatrix); + + trigger.trigger(); + cgl.popViewMatrix(); +}; + + +}; + +Ops.Gl.Matrix.QuaternionCamera.prototype = new CABLES.Op(); +CABLES.OPS["7141c048-615e-47b5-9d8b-d0ceaad9bd79"]={f:Ops.Gl.Matrix.QuaternionCamera,objName:"Ops.Gl.Matrix.QuaternionCamera"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.RandomGridPlacement +// +// ************************************************************** + +Ops.Gl.Matrix.RandomGridPlacement = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("Exe"), + maxDepth = op.inValue("max Depth", 4), + deeper = op.inValueSlider("Possibility"), + seed = op.inValue("Seed", 1), + inScale = op.inValueSlider("Scale", 1), + width = op.inValue("Width", 4), + height = op.inValue("Height", 3), + next = op.outTrigger("Next"), + outIndex = op.outNumber("Index"), + outDepth = op.outNumber("depth"); + +const cgl = op.patch.cgl; +let globalScale = 1; +let vPos = vec3.create(); +let vScale = vec3.create(); +let hhalf = 0; +let whalf = 0; +let index = 0; + +function drawSquare(x, y, depth, scale) +{ + let godeeper = Math.seededRandom() > deeper.get() * 0.9; + + if (depth > maxDepth.get())godeeper = false; + + if (godeeper) + { + depth++; + let st = 1 / (depth * depth); + + for (let _x = 0; _x < 2; _x++) + { + for (let _y = 0; _y < 2; _y++) + { + let xx = _x * scale / 2; + let yy = _y * scale / 2; + + drawSquare( + x + xx - scale / 4, + y + yy - scale / 4, + depth, + scale / 2 * globalScale); + } + } + } + else + { + cgl.pushModelMatrix(); + vec3.set(vScale, scale, scale, scale); + vec3.set(vPos, x - whalf + 0.5, y - hhalf + 0.5, 0); + index++; + outIndex.set(index); + outDepth.set(depth); + + mat4.translate(cgl.mMatrix, cgl.mMatrix, vPos); + mat4.scale(cgl.mMatrix, cgl.mMatrix, vScale); + next.trigger(); + + cgl.popModelMatrix(); + } +} + +exe.onTriggered = function () +{ + index = 0; + Math.randomSeed = seed.get(); + + whalf = width.get() / 2; + hhalf = height.get() / 2; + + globalScale = inScale.get(); + + for (let x = 0; x < width.get(); x++) + { + for (let y = 0; y < height.get(); y++) + { + drawSquare(x, y, 0, globalScale); + let sc = 1; + } + } +}; + + +}; + +Ops.Gl.Matrix.RandomGridPlacement.prototype = new CABLES.Op(); +CABLES.OPS["3353effa-851f-4c0f-bace-ba5e2e82ae49"]={f:Ops.Gl.Matrix.RandomGridPlacement,objName:"Ops.Gl.Matrix.RandomGridPlacement"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.RandomGridPlacementArrays +// +// ************************************************************** + +Ops.Gl.Matrix.RandomGridPlacementArrays = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("Exe"), + maxDepth = op.inValue("max Depth", 4), + deeper = op.inValueSlider("Possibility", 0.5), + seed = op.inValue("Seed", 1), + inScale = op.inValueSlider("Scale", 1), + width = op.inValue("Width", 4), + height = op.inValue("Height", 3), + outPosArr = op.outArray("Positions"), + outScaleArr = op.outArray("Scalings"), + outArrayLength = op.outNumber("Array Length"), + outArrayPoints = op.outNumber("Total Points"); + +const cgl = op.patch.cgl; +let needsChange = true; +let globalScale = 1; +let vPos = vec3.create(); +let vScale = vec3.create(); +let hhalf = 0; +let whalf = 0; +let index = 0; +let arrPos = []; +let arrScale = []; + +let count = 0; + +maxDepth.onChange = + deeper.onChange = + seed.onChange = + inScale.onChange = + width.onChange = + height.onChange = + function () + { + needsChange = true; + }; + +function drawSquare(x, y, depth, scale) +{ + let godeeper = Math.seededRandom() > deeper.get() * 0.9; + + if (depth > maxDepth.get())godeeper = false; + + if (godeeper) + { + depth++; + let st = 1 / (depth * depth); + + for (let _x = 0; _x < 2; _x++) + { + for (let _y = 0; _y < 2; _y++) + { + let xx = _x * scale / 2; + let yy = _y * scale / 2; + + drawSquare( + x + xx - scale / 4, + y + yy - scale / 4, + depth, + scale / 2 * globalScale); + } + } + } + else + { + vec3.set(vScale, scale, scale, scale); + vec3.set(vPos, x - whalf + 0.5, y - hhalf + 0.5, 0); + index++; + + arrPos[count * 3 + 0] = vPos[0]; + arrPos[count * 3 + 1] = vPos[1]; + arrPos[count * 3 + 2] = vPos[2]; + + arrScale[count * 3 + 0] = vScale[0]; + arrScale[count * 3 + 1] = vScale[1]; + arrScale[count * 3 + 2] = vScale[2]; + + count++; + } +} + +exe.onTriggered = function () +{ + if (!needsChange) return; + + needsChange = false; + index = 0; + Math.randomSeed = seed.get(); + + whalf = width.get() / 2; + hhalf = height.get() / 2; + + globalScale = inScale.get(); + + arrPos.length = 0; + arrScale.length = 0; + count = 0; + + for (let x = 0; x < width.get(); x++) + { + for (let y = 0; y < height.get(); y++) + { + drawSquare(x, y, 0, globalScale); + let sc = 1; + } + } + + outArrayLength.set(arrPos.length); + outArrayPoints.set(arrPos.length / 3); + + outPosArr.set(null); + outPosArr.set(arrPos); + outScaleArr.set(null); + outScaleArr.set(arrScale); +}; + + +}; + +Ops.Gl.Matrix.RandomGridPlacementArrays.prototype = new CABLES.Op(); +CABLES.OPS["81f910ec-a11c-4bee-bd63-8ae036632d7d"]={f:Ops.Gl.Matrix.RandomGridPlacementArrays,objName:"Ops.Gl.Matrix.RandomGridPlacementArrays"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.Scale +// +// ************************************************************** + +Ops.Gl.Matrix.Scale = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + scale = op.inValueFloat("scale", 1.0), + trigger = op.outTrigger("trigger"); + +const vScale = vec3.create(); + +scale.onChange = scaleChanged; +scaleChanged(); + +render.onTriggered = function () +{ + const cgl = op.patch.cg; + cgl.pushModelMatrix(); + mat4.scale(cgl.mMatrix, cgl.mMatrix, vScale); + trigger.trigger(); + cgl.popModelMatrix(); +}; + +function scaleChanged() +{ + const s = scale.get(); + vec3.set(vScale, s, s, s); +} + + +}; + +Ops.Gl.Matrix.Scale.prototype = new CABLES.Op(); +CABLES.OPS["50e7f565-0cdb-47ca-912b-87c04e2f00e3"]={f:Ops.Gl.Matrix.Scale,objName:"Ops.Gl.Matrix.Scale"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.ScaleXYZ +// +// ************************************************************** + +Ops.Gl.Matrix.ScaleXYZ = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + scaleX = op.inValueFloat("x", 1), + scaleY = op.inValueFloat("y", 1), + scaleZ = op.inValueFloat("z", 1), + trigger = op.outTrigger("trigger"); + +const vScale = vec3.create(); + +let hasChanged = true; + +scaleX.onChange = scaleY.onChange = scaleZ.onChange = scaleChanged; + +scaleChanged(); + +render.onTriggered = execrender; + +function execrender() +{ + const cgl = op.patch.cg || op.patch.cgl; + + if (hasChanged) + { + vec3.set(vScale, scaleX.get(), scaleY.get(), scaleZ.get()); + hasChanged = false; + } + + cgl.pushModelMatrix(); + mat4.scale(cgl.mMatrix, cgl.mMatrix, vScale); + trigger.trigger(); + cgl.popModelMatrix(); +} + +function scaleChanged() +{ + hasChanged = true; +} + + +}; + +Ops.Gl.Matrix.ScaleXYZ.prototype = new CABLES.Op(); +CABLES.OPS["9ba52457-5f0d-4b20-a97c-4ec4856b8e29"]={f:Ops.Gl.Matrix.ScaleXYZ,objName:"Ops.Gl.Matrix.ScaleXYZ"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.ScaleXYZViewMatrix +// +// ************************************************************** + +Ops.Gl.Matrix.ScaleXYZViewMatrix = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + scaleX = op.inValueFloat("x", 1), + scaleY = op.inValueFloat("y", 1), + scaleZ = op.inValueFloat("z", 1), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +let vScale = vec3.create(); +let transMatrix = mat4.create(); +mat4.identity(transMatrix); + +scaleX.onChange = scaleY.onChange = scaleZ.onChange = scaleChanged; +scaleChanged(); + +render.onTriggered = exec; + +function exec() +{ + cgl.pushViewMatrix(); + mat4.multiply(cgl.vMatrix, cgl.vMatrix, transMatrix); + trigger.trigger(); + cgl.popViewMatrix(); +} + +function scaleChanged() +{ + vec3.set(vScale, scaleX.get(), scaleY.get(), scaleZ.get()); + mat4.identity(transMatrix); + mat4.scale(transMatrix, transMatrix, vScale); +} + + +}; + +Ops.Gl.Matrix.ScaleXYZViewMatrix.prototype = new CABLES.Op(); +CABLES.OPS["8b1fa9c9-0c4d-41b6-9c4f-8f4b633a9d7f"]={f:Ops.Gl.Matrix.ScaleXYZViewMatrix,objName:"Ops.Gl.Matrix.ScaleXYZViewMatrix"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.ScreenCoordinates +// +// ************************************************************** + +Ops.Gl.Matrix.ScreenCoordinates = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Execute"), + inUnit = op.inSwitch("Pixel Unit", ["Display", "CSS"], "Display"), + trigger = op.outTrigger("Trigger"), + x = op.outNumber("X"), + y = op.outNumber("Y"), + visi = op.outNumber("Visible"); + +const cgl = op.patch.cgl; +const trans = vec3.create(); +const m = mat4.create(); +const pos = vec3.create(); +const identVec = vec3.create(); + +let div = Math.randomSeed = 1; +inUnit.onChange = () => +{ + if (inUnit.get() == "CSS")div = cgl.pixelDensity; + else div = 1; +}; + +exec.onTriggered = function () +{ + mat4.multiply(m, cgl.vMatrix, cgl.mMatrix); + vec3.transformMat4(pos, identVec, m); + + vec3.transformMat4(trans, pos, cgl.pMatrix); + + const vp = cgl.getViewPort(); + const xp = (trans[0] * vp[2] / 2) + vp[2] / 2; + const yp = (trans[1] * vp[3] / 2) + vp[3] / 2; + + visi.set(pos[2] < 0.0 && xp > 0 && xp < vp[2] && yp > 0 && yp < vp[3]); + + x.set(xp / div); + y.set(yp / div); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.Matrix.ScreenCoordinates.prototype = new CABLES.Op(); +CABLES.OPS["75cadc63-62bb-4ddd-b519-aa99568a1e6b"]={f:Ops.Gl.Matrix.ScreenCoordinates,objName:"Ops.Gl.Matrix.ScreenCoordinates"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.ScreenPosTo3d_v3 +// +// ************************************************************** + +Ops.Gl.Matrix.ScreenPosTo3d_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Exec"), + inX = op.inValue("X"), + inY = op.inValue("Y"), + inputType = op.inSwitch("Input Type", ["Pixel", "-1 to 1"], "Pixel"), + outTrigger = op.outTrigger("Trigger out"), + outX = op.outNumber("Result X"), + outY = op.outNumber("Result Y"); + +const mat = mat4.create(); +const cgl = op.patch.cgl; + +exec.onTriggered = calc; + +let inp = 0; +inputType.onChange = () => +{ + if (inputType.get() == "Pixel")inp = 0; + else if (inputType.get() == "-1 to 1")inp = 1; +}; + +function calc() +{ + let x = 0; + let y = 0; + + let aspect = cgl.canvas.clientWidth / cgl.canvas.clientHeight; + + if (inp === 0) // pixel + { + x = 2.0 * inX.get() / cgl.canvas.clientWidth - 1; + y = -2.0 * inY.get() / cgl.canvas.clientHeight + 1; + } + else if (inp === 1) // -1 to 1 + { + x = inX.get(); + y = inY.get(); + } + + let point3d = vec3.fromValues(x, y, 0); + + mat4.mul(mat, cgl.pMatrix, cgl.vMatrix); + + mat4.invert(mat, mat); + + vec3.transformMat4(point3d, point3d, mat); + + outX.set(point3d[0] * 10); + outY.set(point3d[1] * 10); + outTrigger.trigger(); +} + + +}; + +Ops.Gl.Matrix.ScreenPosTo3d_v3.prototype = new CABLES.Op(); +CABLES.OPS["48d72532-afa6-40c9-a895-00a43635a94b"]={f:Ops.Gl.Matrix.ScreenPosTo3d_v3,objName:"Ops.Gl.Matrix.ScreenPosTo3d_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.SetProjectionMatrix +// +// ************************************************************** + +Ops.Gl.Matrix.SetProjectionMatrix = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inExe=op.inTrigger("exe"); +const inMatrix=op.inArray('Matrix'); +const next=op.outTrigger("next"); +const cgl=op.patch.cgl; + +inExe.onTriggered=function() +{ + if(inMatrix.get()) + { + cgl.pushPMatrix(); + + mat4.copy(cgl.pMatrix,inMatrix.get() ); + + next.trigger(); + cgl.popPMatrix(); + + } + +}; + +}; + +Ops.Gl.Matrix.SetProjectionMatrix.prototype = new CABLES.Op(); +CABLES.OPS["2c614eb3-ab11-4793-a085-3ef8f517e30b"]={f:Ops.Gl.Matrix.SetProjectionMatrix,objName:"Ops.Gl.Matrix.SetProjectionMatrix"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.Shear +// +// ************************************************************** + +Ops.Gl.Matrix.Shear = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render=op.inTrigger('render'), + shearX=op.inValueFloat("shearX",0.5), + shearY=op.inValueFloat("shearY"), + trigger=op.outTrigger('trigger'); + +const cgl=op.patch.cgl; +const shearMatrix = mat4.create(); + +shearY.onChange=shearX.onChange=update; + +function update() +{ + mat4.identity(shearMatrix); + shearMatrix[1]=Math.tan(shearX.get()); + shearMatrix[4]=Math.tan(shearY.get()); +} + +render.onTriggered=function() +{ + cgl.pushModelMatrix(); + + mat4.multiply(cgl.mMatrix,cgl.mMatrix,shearMatrix); + trigger.trigger(); + + cgl.popModelMatrix(); +}; + + + +}; + +Ops.Gl.Matrix.Shear.prototype = new CABLES.Op(); +CABLES.OPS["02d76d99-67f2-4146-b906-8bce2c3ad6bb"]={f:Ops.Gl.Matrix.Shear,objName:"Ops.Gl.Matrix.Shear"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.Transform +// +// ************************************************************** + +Ops.Gl.Matrix.Transform = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + posX = op.inValue("posX", 0), + posY = op.inValue("posY", 0), + posZ = op.inValue("posZ", 0), + scale = op.inValue("scale", 1), + rotX = op.inValue("rotX", 0), + rotY = op.inValue("rotY", 0), + rotZ = op.inValue("rotZ", 0), + trigger = op.outTrigger("trigger"); + +op.setPortGroup("Rotation", [rotX, rotY, rotZ]); +op.setPortGroup("Position", [posX, posY, posZ]); +op.setPortGroup("Scale", [scale]); +op.setUiAxisPorts(posX, posY, posZ); + +const vPos = vec3.create(); +const vScale = vec3.create(); +const transMatrix = mat4.create(); +mat4.identity(transMatrix); + +let + doScale = false, + doTranslate = false, + translationChanged = true, + scaleChanged = true, + rotChanged = true; + +rotX.onChange = rotY.onChange = rotZ.onChange = setRotChanged; +posX.onChange = posY.onChange = posZ.onChange = setTranslateChanged; +scale.onChange = setScaleChanged; + +render.onTriggered = function () +{ + // if(!CGL.TextureEffect.checkOpNotInTextureEffect(op)) return; + + let updateMatrix = false; + if (translationChanged) + { + updateTranslation(); + updateMatrix = true; + } + if (scaleChanged) + { + updateScale(); + updateMatrix = true; + } + if (rotChanged) updateMatrix = true; + + if (updateMatrix) doUpdateMatrix(); + + const cg = op.patch.cgl; + cg.pushModelMatrix(); + mat4.multiply(cg.mMatrix, cg.mMatrix, transMatrix); + + trigger.trigger(); + cg.popModelMatrix(); + + if (CABLES.UI && CABLES.UI.showCanvasTransforms) gui.setTransform(op.id, posX.get(), posY.get(), posZ.get()); + + if (op.isCurrentUiOp()) + gui.setTransformGizmo( + { + "posX": posX, + "posY": posY, + "posZ": posZ, + }); +}; + +op.transform3d = function () +{ + return { "pos": [posX, posY, posZ] }; +}; + +function doUpdateMatrix() +{ + mat4.identity(transMatrix); + if (doTranslate)mat4.translate(transMatrix, transMatrix, vPos); + + if (rotX.get() !== 0)mat4.rotateX(transMatrix, transMatrix, rotX.get() * CGL.DEG2RAD); + if (rotY.get() !== 0)mat4.rotateY(transMatrix, transMatrix, rotY.get() * CGL.DEG2RAD); + if (rotZ.get() !== 0)mat4.rotateZ(transMatrix, transMatrix, rotZ.get() * CGL.DEG2RAD); + + if (doScale)mat4.scale(transMatrix, transMatrix, vScale); + rotChanged = false; +} + +function updateTranslation() +{ + doTranslate = false; + if (posX.get() !== 0.0 || posY.get() !== 0.0 || posZ.get() !== 0.0) doTranslate = true; + vec3.set(vPos, posX.get(), posY.get(), posZ.get()); + translationChanged = false; +} + +function updateScale() +{ + // doScale=false; + // if(scale.get()!==0.0) + doScale = true; + vec3.set(vScale, scale.get(), scale.get(), scale.get()); + scaleChanged = false; +} + +function setTranslateChanged() +{ + translationChanged = true; +} + +function setScaleChanged() +{ + scaleChanged = true; +} + +function setRotChanged() +{ + rotChanged = true; +} + +doUpdateMatrix(); + + +}; + +Ops.Gl.Matrix.Transform.prototype = new CABLES.Op(); +CABLES.OPS["650baeb1-db2d-4781-9af6-ab4e9d4277be"]={f:Ops.Gl.Matrix.Transform,objName:"Ops.Gl.Matrix.Transform"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.TransformMul +// +// ************************************************************** + +Ops.Gl.Matrix.TransformMul = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const render=op.inTrigger("render"); +const mul=op.inValueFloat("mul"); +const trigger=op.outTrigger("trigger"); + +const cgl=op.patch.cgl; + +render.onTriggered=function() +{ + var pos=[0,0,0]; + vec3.transformMat4(pos, [0,0,0], cgl.mMatrix); + + cgl.pushModelMatrix(); + vec3.mul(pos,pos,[mul.get(),mul.get(),mul.get()] ); + + mat4.translate(cgl.mMatrix,cgl.mMatrix, pos ); + trigger.trigger(); + + cgl.popModelMatrix(); +}; + +}; + +Ops.Gl.Matrix.TransformMul.prototype = new CABLES.Op(); +CABLES.OPS["2a83f565-7c5c-4cce-862f-d38481eb3726"]={f:Ops.Gl.Matrix.TransformMul,objName:"Ops.Gl.Matrix.TransformMul"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.TransformView +// +// ************************************************************** + +Ops.Gl.Matrix.TransformView = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + posX = op.inValueFloat("posX"), + posY = op.inValueFloat("posY"), + posZ = op.inValueFloat("posZ"), + scale = op.inValueFloat("scale"), + rotX = op.inValueFloat("rotX"), + rotY = op.inValueFloat("rotY"), + rotZ = op.inValueFloat("rotZ"), + trigger = op.outTrigger("trigger"); + +op.setPortGroup("Position", [posX, posY, posZ]); +op.setPortGroup("Scale", [scale]); +op.setPortGroup("Rotation", [rotX, rotZ, rotY]); + +const vPos = vec3.create(); +const vScale = vec3.create(); +const transMatrix = mat4.create(); +mat4.identity(transMatrix); + +let doScale = false; +let doTranslate = false; + +let translationChanged = true; +let didScaleChanged = true; +let didRotChanged = true; + +render.onTriggered = function () +{ + const cg = op.patch.cg; + + let updateMatrix = false; + if (translationChanged) + { + updateTranslation(); + updateMatrix = true; + } + if (didScaleChanged) + { + updateScale(); + updateMatrix = true; + } + if (didRotChanged) + { + updateMatrix = true; + } + if (updateMatrix)doUpdateMatrix(); + + cg.pushViewMatrix(); + mat4.multiply(cg.vMatrix, cg.vMatrix, transMatrix); + + trigger.trigger(); + cg.popViewMatrix(); + + if (op.isCurrentUiOp()) + gui.setTransformGizmo( + { + "posX": posX, + "posY": posY, + "posZ": posZ, + }); +}; + +op.transform3d = function () +{ + return { + "pos": [posX, posY, posZ] + }; +}; + +function doUpdateMatrix() +{ + mat4.identity(transMatrix); + if (doTranslate)mat4.translate(transMatrix, transMatrix, vPos); + + if (rotX.get() !== 0)mat4.rotateX(transMatrix, transMatrix, rotX.get() * CGL.DEG2RAD); + if (rotY.get() !== 0)mat4.rotateY(transMatrix, transMatrix, rotY.get() * CGL.DEG2RAD); + if (rotZ.get() !== 0)mat4.rotateZ(transMatrix, transMatrix, rotZ.get() * CGL.DEG2RAD); + + if (doScale)mat4.scale(transMatrix, transMatrix, vScale); + rotChanged = false; +} + +function updateTranslation() +{ + doTranslate = false; + if (posX.get() !== 0.0 || posY.get() !== 0.0 || posZ.get() !== 0.0) doTranslate = true; + vec3.set(vPos, posX.get(), posY.get(), posZ.get()); + translationChanged = false; +} + +function updateScale() +{ + doScale = false; + if (scale.get() !== 0.0)doScale = true; + vec3.set(vScale, scale.get(), scale.get(), scale.get()); + scaleChanged = false; +} + +function translateChanged() +{ + translationChanged = true; +} + +function scaleChanged() +{ + didScaleChanged = true; +} + +function rotChanged() +{ + didRotChanged = true; +} + +rotX.onChange = +rotY.onChange = +rotZ.onChange = rotChanged; + +scale.onChange = scaleChanged; + +posX.onChange = +posY.onChange = +posZ.onChange = translateChanged; + +rotX.set(0.0); +rotY.set(0.0); +rotZ.set(0.0); + +scale.set(1.0); + +posX.set(0.0); +posY.set(0.0); +posZ.set(0.0); + +doUpdateMatrix(); + + +}; + +Ops.Gl.Matrix.TransformView.prototype = new CABLES.Op(); +CABLES.OPS["0b3e04f7-323e-4ac8-8a22-a21e2f36e0e9"]={f:Ops.Gl.Matrix.TransformView,objName:"Ops.Gl.Matrix.TransformView"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.Translate +// +// ************************************************************** + +Ops.Gl.Matrix.Translate = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const render = op.inTrigger("render"); +const trigger = op.outTrigger("trigger"); +const x = op.inValue("x"); +const y = op.inValue("y"); +const z = op.inValue("z"); + +let vec = vec3.create(); + +render.onTriggered = function () +{ + const cgl = op.patch.cg; + + vec3.set(vec, x.get(), y.get(), z.get()); + cgl.pushModelMatrix(); + mat4.translate(cgl.mMatrix, cgl.mMatrix, vec); + trigger.trigger(); + cgl.popModelMatrix(); +}; + + +}; + +Ops.Gl.Matrix.Translate.prototype = new CABLES.Op(); +CABLES.OPS["1f89ba0e-e7eb-46d7-8c66-7814b7c528b9"]={f:Ops.Gl.Matrix.Translate,objName:"Ops.Gl.Matrix.Translate"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.TranslateView +// +// ************************************************************** + +Ops.Gl.Matrix.TranslateView = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render=op.inTrigger('render'), + x=op.inValueFloat("x"), + y=op.inValueFloat("y"), + z=op.inValueFloat("z"), + trigger=op.outTrigger('trigger'); + +const cgl=op.patch.cgl; +const vec=vec3.create(); + +render.onTriggered=function() +{ + vec3.set(vec, x.get(),y.get(),z.get()); + cgl.pushViewMatrix(); + mat4.translate(cgl.vMatrix,cgl.vMatrix, vec); + trigger.trigger(); + cgl.popViewMatrix(); +}; + + +}; + +Ops.Gl.Matrix.TranslateView.prototype = new CABLES.Op(); +CABLES.OPS["b15472e2-b895-4dde-95c3-239fa5e08afc"]={f:Ops.Gl.Matrix.TranslateView,objName:"Ops.Gl.Matrix.TranslateView"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.VectorTranslate +// +// ************************************************************** + +Ops.Gl.Matrix.VectorTranslate = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exec = op.inTrigger("Exec"); +const speed = op.inValue("Speed"); +const vecX = op.inValue("Vector X"); +const vecY = op.inValue("Vector Y"); +const vecZ = op.inValue("Vector Z"); +const resetVecX = op.inFloat("Reset Position X"); +const resetVecY = op.inFloat("Reset Position Y"); +const resetVecZ = op.inFloat("Reset Position Z"); +const next = op.outTrigger("Next"); + +const reset = op.inTriggerButton("reset"); + +const max = op.inValue("max"); + +const cgl = op.patch.cgl; + +const vec = vec3.create(); +const pos = vec3.create(); +const mat = mat4.create(); + +let lastTime = 0; +let timeDiff = 0; + +reset.onTriggered = function () +{ + vec3.set(pos, + (resetVecX.get()), + (resetVecY.get()), + (resetVecZ.get()) + ); +}; + +let dir = false; +function changeDir(d) +{ + dir = !dir; + + move(); +} + +function isOutside() +{ + if ( + pos[0] > max.get() || pos[0] < -max.get() + || pos[1] > max.get() || pos[1] < -max.get() + || pos[2] > max.get() || pos[2] < -max.get()) + return true; + return false; +} + +function move() +{ +} + +exec.onTriggered = function () +{ + timeDiff = op.patch.freeTimer.get() - lastTime; + const m = speed.get() * timeDiff * 0.1; + + vec3.set(vec, + (vecX.get()), + (vecY.get()), + (vecZ.get()) + ); + + vec3.normalize(vec, vec); + + vec[0] *= m; + vec[1] *= m; + vec[2] *= m; + + lastTime = op.patch.freeTimer.get(); + + move(); + + // if(isOutside()) + // { + // op.log("OUTSIDE"); + // changeDir(); + // var count=0; + // while(isOutside() && count<10) + // { + // randomize(); + // count++; + // move(); + // } + // } + + // if(pos[0]>max.get() || pos[0]<-max.get()) changeDir(); + // else if(pos[1]>max.get() || pos[1]<-max.get()) changeDir(); + // else if(pos[2]>max.get() || pos[2]<-max.get()) changeDir(); + + vec3.add(pos, pos, vec); + + cgl.pushModelMatrix(); + + mat4.translate(cgl.mMatrix, cgl.mMatrix, pos); + + next.trigger(); + + cgl.popModelMatrix(); +}; + + +}; + +Ops.Gl.Matrix.VectorTranslate.prototype = new CABLES.Op(); +CABLES.OPS["ca65a1bc-3efa-4b73-96c4-087003b9470a"]={f:Ops.Gl.Matrix.VectorTranslate,objName:"Ops.Gl.Matrix.VectorTranslate"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.WASDCamera_v2 +// +// ************************************************************** + +Ops.Gl.Matrix.WASDCamera_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + enablePointerLock = op.inBool("Enable pointer lock", true), + trigger = op.outTrigger("trigger"), + isLocked = op.outBoolNum("isLocked", false), + + moveSpeed = op.inFloat("Speed", 1), + mouseSpeed = op.inFloat("Mouse Speed", 1), + fly = op.inValueBool("Allow Flying", true), + inActive = op.inBool("Active", true), + + inMoveXPos = op.inBool("Move X+"), + inMoveXNeg = op.inBool("Move X-"), + inMoveYPos = op.inBool("Move Y+"), + inMoveYNeg = op.inBool("Move Y-"), + + inReset = op.inTriggerButton("Reset"), + + outPosX = op.outNumber("posX"), + outPosY = op.outNumber("posY"), + outPosZ = op.outNumber("posZ"), + + outMouseDown = op.outTrigger("Mouse Left"), + outMouseDownRight = op.outTrigger("Mouse Right"), + + outDirX = op.outNumber("Dir X"), + outDirY = op.outNumber("Dir Y"), + outDirZ = op.outNumber("Dir Z"); + +const vPos = vec3.create(); +let speedx = 0, speedy = 0, speedz = 0; +const movementSpeedFactor = 0.5; + +op.setPortGroup("Move", [inMoveYNeg, inMoveYPos, inMoveXNeg, inMoveXPos]); + +let mouseNoPL = { "firstMove": true, + "deltaX": 0, + "deltaY": 0, +}; + +const DEG2RAD = 3.14159 / 180.0; + +let rotX = 0; +let rotY = 0; + +let posX = 0; +let posY = 0; +let posZ = 0; + +let pressedW = false; +let pressedA = false; +let pressedS = false; +let pressedD = false; + +const cgl = op.patch.cgl; + +const viewMatrix = mat4.create(); + +op.toWorkPortsNeedToBeLinked(render); +let lastMove = 0; + +initListener(); + +enablePointerLock.onChange = initListener; + +inReset.onTriggered = () => +{ + rotX = 0; + rotY = 0; + posX = 0; + posY = 0; + posZ = 0; +}; + +inActive.onChange = () => +{ + document.exitPointerLock(); + removeListener(); + + lockChangeCallback(); + + if (inActive.get()) + { + initListener(); + } +}; + +render.onTriggered = function () +{ + if (cgl.frameStore.shadowPass) return trigger.trigger(); + + calcCameraMovement(); + move(); + + if (!fly.get())posY = 0.0; + + if (speedx !== 0.0 || speedy !== 0.0 || speedz !== 0) + { + outPosX.set(posX); + outPosY.set(posY); + outPosZ.set(posZ); + } + + cgl.pushViewMatrix(); + + vec3.set(vPos, -posX, -posY, -posZ); + + mat4.identity(cgl.vMatrix); + + mat4.rotateX(cgl.vMatrix, cgl.vMatrix, DEG2RAD * rotX); + mat4.rotateY(cgl.vMatrix, cgl.vMatrix, DEG2RAD * rotY); + + mat4.translate(cgl.vMatrix, cgl.vMatrix, vPos); + + trigger.trigger(); + cgl.popViewMatrix(); + + // for dir vec + mat4.identity(viewMatrix); + mat4.rotateX(viewMatrix, viewMatrix, DEG2RAD * rotX); + mat4.rotateY(viewMatrix, viewMatrix, DEG2RAD * rotY); + mat4.transpose(viewMatrix, viewMatrix); + + const dir = vec4.create(); + vec4.transformMat4(dir, [0, 0, 1, 1], viewMatrix); + + vec4.normalize(dir, dir); + outDirX.set(-dir[0]); + outDirY.set(-dir[1]); + outDirZ.set(-dir[2]); +}; + +//-------------- + +function calcCameraMovement() +{ + let camMovementXComponent = 0.0, + camMovementYComponent = 0.0, + camMovementZComponent = 0.0, + pitchFactor = 0, + yawFactor = 0; + + if (pressedW) + { + // Control X-Axis movement + pitchFactor = Math.cos(DEG2RAD * rotX); + + camMovementXComponent += (movementSpeedFactor * (Math.sin(DEG2RAD * rotY))) * pitchFactor; + + // Control Y-Axis movement + camMovementYComponent += movementSpeedFactor * (Math.sin(DEG2RAD * rotX)) * -1.0; + + // Control Z-Axis movement + yawFactor = (Math.cos(DEG2RAD * rotX)); + camMovementZComponent += (movementSpeedFactor * (Math.cos(DEG2RAD * rotY)) * -1.0) * yawFactor; + } + + if (pressedS) + { + // Control X-Axis movement + pitchFactor = Math.cos(DEG2RAD * rotX); + camMovementXComponent += (movementSpeedFactor * (Math.sin(DEG2RAD * rotY)) * -1.0) * pitchFactor; + + // Control Y-Axis movement + camMovementYComponent += movementSpeedFactor * (Math.sin(DEG2RAD * rotX)); + + // Control Z-Axis movement + yawFactor = (Math.cos(DEG2RAD * rotX)); + camMovementZComponent += (movementSpeedFactor * (Math.cos(DEG2RAD * rotY))) * yawFactor; + } + + let yRotRad = DEG2RAD * rotY; + + if (pressedA) + { + // Calculate our Y-Axis rotation in radians once here because we use it twice + + camMovementXComponent += -movementSpeedFactor * (Math.cos(yRotRad)); + camMovementZComponent += -movementSpeedFactor * (Math.sin(yRotRad)); + } + + if (pressedD) + { + // Calculate our Y-Axis rotation in radians once here because we use it twice + + camMovementXComponent += movementSpeedFactor * (Math.cos(yRotRad)); + camMovementZComponent += movementSpeedFactor * (Math.sin(yRotRad)); + } + + const mulSpeed = 0.016; + + speedx = camMovementXComponent * mulSpeed; + speedy = camMovementYComponent * mulSpeed; + speedz = camMovementZComponent * mulSpeed; + + if (speedx > movementSpeedFactor) speedx = movementSpeedFactor; + if (speedx < -movementSpeedFactor) speedx = -movementSpeedFactor; + + if (speedy > movementSpeedFactor) speedy = movementSpeedFactor; + if (speedy < -movementSpeedFactor) speedy = -movementSpeedFactor; + + if (speedz > movementSpeedFactor) speedz = movementSpeedFactor; + if (speedz < -movementSpeedFactor) speedz = -movementSpeedFactor; +} + +function moveCallback(e) +{ + const mouseSensitivity = 0.1; + rotX += e.movementY * mouseSensitivity * mouseSpeed.get(); + rotY += e.movementX * mouseSensitivity * mouseSpeed.get(); + + if (rotX < -90.0) rotX = -90.0; + if (rotX > 90.0) rotX = 90.0; + if (rotY < -180.0) rotY += 360.0; + if (rotY > 180.0) rotY -= 360.0; +} + +const canvas = document.getElementById("glcanvas"); + +function mouseDown(e) +{ + if (e.which == 3) outMouseDownRight.trigger(); + else outMouseDown.trigger(); +} + +function lockChangeCallback(e) +{ + if (document.pointerLockElement === canvas || + document.mozPointerLockElement === canvas || + document.webkitPointerLockElement === canvas) + { + document.addEventListener("pointerdown", mouseDown, false); + document.addEventListener("pointermove", moveCallback, false); + document.addEventListener("keydown", keyDown, false); + document.addEventListener("keyup", keyUp, false); + isLocked.set(true); + } + else + { + document.removeEventListener("pointerdown", mouseDown, false); + document.removeEventListener("pointermove", moveCallback, false); + document.removeEventListener("keydown", keyDown, false); + document.removeEventListener("keyup", keyUp, false); + isLocked.set(false); + pressedW = false; + pressedA = false; + pressedS = false; + pressedD = false; + } +} + +function startPointerLock() +{ + const test = false; + if (render.isLinked() && enablePointerLock.get()) + { + document.addEventListener("pointermove", moveCallback, false); + canvas.requestPointerLock = canvas.requestPointerLock || + canvas.mozRequestPointerLock || + canvas.webkitRequestPointerLock; + canvas.requestPointerLock(); + } +} + +function removeListener() +{ + cgl.canvas.removeEventListener("pointermove", moveCallbackNoPL, false); + cgl.canvas.removeEventListener("pointerup", upCallbackNoPL, false); + cgl.canvas.removeEventListener("keydown", keyDown, false); + cgl.canvas.removeEventListener("keyup", keyUp, false); + + document.removeEventListener("pointerlockchange", lockChangeCallback, false); + document.removeEventListener("mozpointerlockchange", lockChangeCallback, false); + document.removeEventListener("webkitpointerlockchange", lockChangeCallback, false); + document.getElementById("glcanvas").removeEventListener("mousedown", startPointerLock); +} + +function initListener() +{ + if (enablePointerLock.get()) + { + document.addEventListener("pointerlockchange", lockChangeCallback, false); + document.addEventListener("mozpointerlockchange", lockChangeCallback, false); + document.addEventListener("webkitpointerlockchange", lockChangeCallback, false); + document.getElementById("glcanvas").addEventListener("mousedown", startPointerLock); + + cgl.canvas.removeEventListener("pointermove", moveCallbackNoPL, false); + cgl.canvas.removeEventListener("pointerup", upCallbackNoPL, false); + cgl.canvas.removeEventListener("keydown", keyDown, false); + cgl.canvas.removeEventListener("keyup", keyUp, false); + } + else + { + cgl.canvas.addEventListener("pointermove", moveCallbackNoPL, false); + cgl.canvas.addEventListener("pointerup", upCallbackNoPL, false); + cgl.canvas.addEventListener("keydown", keyDown, false); + cgl.canvas.addEventListener("keyup", keyUp, false); + } +} + +function upCallbackNoPL(e) +{ + try { cgl.canvas.releasePointerCapture(e.pointerId); } + catch (e) {} + mouseNoPL.firstMove = true; +} + +function moveCallbackNoPL(e) +{ + if (e && e.buttons == 1) + { + try { cgl.canvas.setPointerCapture(e.pointerId); } + catch (_e) {} + + if (!mouseNoPL.firstMove) + { + // outDragging.set(true); + const deltaX = (e.clientX - mouseNoPL.lastX) * mouseSpeed.get() * 0.5; + const deltaY = (e.clientY - mouseNoPL.lastY) * mouseSpeed.get() * 0.5; + + rotX += deltaY; + rotY += deltaX; + // outDeltaX.set(deltaX); + // outDeltaY.set(deltaY); + } + + mouseNoPL.firstMove = false; + + mouseNoPL.lastX = e.clientX; + mouseNoPL.lastY = e.clientY; + } +} + +function move() +{ + let timeOffset = window.performance.now() - lastMove; + timeOffset *= moveSpeed.get(); + posX += speedx * timeOffset; + posY += speedy * timeOffset; + posZ += speedz * timeOffset; + + lastMove = window.performance.now(); +} + +function keyDown(e) +{ + switch (e.which) + { + case 87: + pressedW = true; + break; + case 65: + pressedA = true; + break; + case 83: + pressedS = true; + break; + case 68: + pressedD = true; + break; + + default: + break; + } +} + +function keyUp(e) +{ + switch (e.which) + { + case 87: + pressedW = false; + break; + case 65: + pressedA = false; + break; + case 83: + pressedS = false; + break; + case 68: + pressedD = false; + break; + } +} + +inMoveXPos.onChange = () => { pressedD = inMoveXPos.get(); }; +inMoveXNeg.onChange = () => { pressedA = inMoveXNeg.get(); }; +inMoveYPos.onChange = () => { pressedW = inMoveYPos.get(); }; +inMoveYNeg.onChange = () => { pressedS = inMoveYNeg.get(); }; + + +}; + +Ops.Gl.Matrix.WASDCamera_v2.prototype = new CABLES.Op(); +CABLES.OPS["af6c3fe2-58a9-4f81-be41-4c21aabffde9"]={f:Ops.Gl.Matrix.WASDCamera_v2,objName:"Ops.Gl.Matrix.WASDCamera_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.MediaRecorder +// +// ************************************************************** + +Ops.Gl.MediaRecorder = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const videoTypes = ["webm", "mp4", "x-matroska"]; +const audioTypes = ["webm", "mp3", "x-matroska"]; +const videoCodecs = ["vp9", "vp8", "avc1", "av1", "h265", "h264", "mpeg", "mp4a"]; +const audioCodecs = ["opus", "pcm", "aac", "mp3", "ogg"]; + +const supportedVideos = getSupportedMimeTypes("video", videoTypes, videoCodecs, audioCodecs); + +function getSupportedMimeTypes(media, types, codecs, codecsB) +{ + const isSupported = MediaRecorder.isTypeSupported; + const supported = []; + + types.forEach((type) => + { + const mimeType = `${media}/${type}`; + if (isSupported(mimeType)) + supported.push(mimeType); + }); + + types.forEach((type) => + { + const mimeType = `${media}/${type}`; + codecs.forEach((codec) => + { + return [`${mimeType}; codecs=${codec}`].forEach((variation) => + { + if (isSupported(variation)) supported.push(variation); + + codecsB.forEach((codecB) => + { + return [`${mimeType}; codecs=${codec},${codecB}`].forEach((eachVariation) => + { + if (isSupported(eachVariation)) supported.push(eachVariation); + }); + }); + }); + }); + }); + return supported; +} + +// / //////////////// + +const + recordingToggle = op.inBool("Recording", false), + + inFilename = op.inString("Filename", "cables"), + inCodecs = op.inDropDown("Mimetype", supportedVideos), + inMbit = op.inFloat("MBit", 5), + inFPS = op.inFloat("FPS", 30), + + inMedia = op.inSwitch("Media", ["Video", "Audio", "Audio+Video"], "Video"), + inAudio = op.inObject("Audio In", null, "audioNode"), + inCanvasId = op.inString("Video Canvas Id", "glcanvas"), + + outState = op.outString("State"), + outError = op.outString("Error"), + outCodec = op.outString("Final Mimetype"), + outCodecs = op.outArray("Valid Mimetypes", supportedVideos); + +op.setPortGroup("Inputs", [inMedia, inAudio, inCanvasId]); +op.setPortGroup("Encoding", [inMbit, inCodecs, inFPS]); + +const gl = op.patch.cgl.gl; +let fb = null; +const cgl = op.patch.cgl; + +let cgl_filter = 0; +let cgl_wrap = 0; +let tex = null; +let timeout = null; +let firstTime = true; +let mediaRecorder; +let recordedBlobs; +let sourceBuffer; + +recordingToggle.onChange = toggleRecording; + +inFPS.onChange = + inMbit.onChange = + inMedia.onChange = + inAudio.onChange = + inCanvasId.onChange = + inCodecs.onChange = setupMediaRecorder; + +op.patch.cgl.on("resize", () => +{ + if (mediaRecorder && mediaRecorder.state === "active")mediaRecorder.stop(); + mediaRecorder = null; +}); + +setupMediaRecorder(); + +function handleDataAvailable(event) +{ + if (event.data && event.data.size > 0) + { + recordedBlobs.push(event.data); + } +} + +function toggleRecording() +{ + if (recordingToggle.get()) startRecording(); + else stopRecording(); +} + +function setupMediaRecorder() +{ + outCodec.set("unknown"); + + outState.set(""); + outCodec.set(""); + outError.set(""); + op.setUiError("constr", null); + op.setUiError("audionoaudio", null); + op.setUiError("nocanvas", null); + mediaRecorder = null; + + if (inCodecs.get() === "" || inCodecs.get() === 0) + { + return; + } + + let options = { "mimeType": inCodecs.get(), "videoBitsPerSecond": inMbit.get() * 1024 * 1024 }; + recordedBlobs = []; + try + { + const canvas = document.getElementById(inCanvasId.get()); + if (!canvas) + { + op.setUiError("nocanvas", "canvas not found "); + return; + } + canvas.getContext("2d"); + const streamVid = canvas.captureStream(inFPS.get()); + + let stream = streamVid; + if (inMedia.get() !== "Video") + { + const audioCtx = CABLES.WEBAUDIO.createAudioContext(op); + const streamAudio = audioCtx.createMediaStreamDestination(); + + if (!inAudio.get()) + { + op.setUiError("audionoaudio", "no audio connected "); + return; + } + inAudio.get().connect(streamAudio); + + if (inMedia.get() === "Audio+Video")stream = new MediaStream([...streamVid.getTracks(), ...streamAudio.stream.getTracks()]); + else stream = streamAudio; + } + + mediaRecorder = new MediaRecorder(stream, options); + } + catch (err) + { + op.error(err); + op.error("error mr constructor: ", err); + outError.set(err.message); + op.setUiError("contr", "MediaRecorder error: " + err.message); + } + if (mediaRecorder) + { + outState.set(mediaRecorder.state); + outCodec.set(mediaRecorder.mimeType); + } + else + { + op.warn("no mediarecorder created..."); + } +} + +// The nested try blocks will be simplified when Chrome 47 moves to Stable +function startRecording() +{ + if (!mediaRecorder)setupMediaRecorder(); + if (!mediaRecorder) + { + op.setUiError("noobj", "could not create mediarecorder, try setting all parameters"); + return; + } + + recordedBlobs = []; + + op.setUiError("noobj", null); + + op.verbose("start recording: ", inCodecs.get()); + + mediaRecorder.ondataavailable = handleDataAvailable; + mediaRecorder.start(1000); + + outState.set(mediaRecorder.state); + op.log("MediaRecorder started", mediaRecorder); +} + +function stopRecording() +{ + if (!mediaRecorder) + { + // op.warn("cant stop no mediarecorder"); + return; + } + op.verbose("mediaRecorder.state", mediaRecorder.state); + if (mediaRecorder.state === "inactive") return; + + op.verbose("mediaRecorder.videoBitsPerSecond ", mediaRecorder.videoBitsPerSecond / 1024 / 1024); + op.verbose("mediaRecorder.mimeType ", mediaRecorder.mimeType); + + mediaRecorder.onstop = download; + + mediaRecorder.stop(); + outState.set(mediaRecorder.state); + + op.verbose("Recorded Blobs: ", recordedBlobs); + // download(); +} + +function download() +{ + if (recordedBlobs.length === 0) + { + op.warn("download canceled, no recordedBlobs"); + } + + if (!mediaRecorder) return; + + const blob = new Blob(recordedBlobs, { "type": "application/octet-stream" }); + const url = window.URL.createObjectURL(blob); + const a = document.createElement("a"); + a.style.display = "none"; + a.href = url; + const codec = mediaRecorder.mimeType; + let ext = "webm"; + if (codec.indexOf("video/x-matroska") >= 0)ext = "mkv"; + if (codec.indexOf("video/mp4") >= 0)ext = "mp4"; + a.download = (inFilename.get() || "cables") + "." + ext; + document.body.appendChild(a); + a.click(); + setTimeout(() => + { + document.body.removeChild(a); + window.URL.revokeObjectURL(url); + }, 100); +} + + +}; + +Ops.Gl.MediaRecorder.prototype = new CABLES.Op(); +CABLES.OPS["ff12e50f-e2bd-4554-9aec-dab9de4cba8b"]={f:Ops.Gl.MediaRecorder,objName:"Ops.Gl.MediaRecorder"}; + + + + +// ************************************************************** +// +// Ops.Gl.MeshInstancer_v4 +// +// ************************************************************** + +Ops.Gl.MeshInstancer_v4 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"instancer_body_frag":"#ifdef COLORIZE_INSTANCES\n #ifdef BLEND_MODE_MULTIPLY\n col.rgb *= frag_instColor.rgb;\n col.a *= frag_instColor.a;\n #endif\n\n #ifdef BLEND_MODE_ADD\n col.rgb += frag_instColor.rgb;\n col.a += frag_instColor.a;\n #endif\n\n #ifdef BLEND_MODE_NONE\n col.rgb = frag_instColor.rgb;\n col.a = frag_instColor.a;\n #endif\n#endif\n","instancer_body_vert":"\n\n#ifdef HAS_TEXCOORDS\ntexCoord=(texCoord*instTexCoords.zw)+instTexCoords.xy;\n#endif\n\nmMatrix*=instMat;\npos.xyz*=MOD_scale;\n\n#ifdef HAS_COLORS\nfrag_instColor=instColor;\n#endif\n#ifndef HAS_COLORS\nfrag_instColor=vec4(1.0);\n#endif\n\n","instancer_head_frag":"IN vec4 frag_instColor;\n","instancer_head_vert":"\nIN vec4 instColor;\nIN mat4 instMat;\nIN vec4 instTexCoords;\nOUT mat4 instModelMat;\nOUT vec4 frag_instColor;\n\n#define INSTANCING\n\n",}; +const + exe = op.inTrigger("exe"), + geom = op.inObject("geom", null, "geometry"), + inScale = op.inValue("Scale", 1), + doLimit = op.inValueBool("Limit Instances", false), + inLimit = op.inValueInt("Limit", 100), + inTranslates = op.inArray("positions", 3), + inScales = op.inArray("Scale Array", 3), + inRot = op.inArray("Rotations", 3), + inRotMeth = op.inSwitch("Rotation Type", ["Euler", "Quaternions"], "Euler"), + inBlendMode = op.inSwitch("Material blend mode", ["Multiply", "Add", "Normal"], "Multiply"), + inColor = op.inArray("Colors", 4), + inTexCoords = op.inArray("TexCoords", 4), + outTrigger = op.outTrigger("Trigger Out"), + outNum = op.outNumber("Num"); + +op.setPortGroup("Limit Number of Instances", [inLimit, doLimit]); +op.setPortGroup("Parameters", [inScales, inRot, inTranslates, inRotMeth]); +op.toWorkPortsNeedToBeLinked(geom); +op.toWorkPortsNeedToBeLinked(exe); + +geom.ignoreValueSerialize = true; + +const cgl = op.patch.cgl; +const m = mat4.create(); +let + matrixArray = new Float32Array(1), + instColorArray = new Float32Array(1), + instTexcoordArray = new Float32Array(1), + mesh = null, + recalc = true, + num = 0, + arrayChangedColor = true, + arrayChangedTexcoords = true, + arrayChangedTrans = true; + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "name": "MODULE_VERTEX_POSITION", + "title": op.name, + "priority": -2, + "srcHeadVert": attachments.instancer_head_vert, + "srcBodyVert": attachments.instancer_body_vert +}); + +mod.addModule({ + "name": "MODULE_COLOR", + "priority": -2, + "title": op.name, + "srcHeadFrag": attachments.instancer_head_frag, + "srcBodyFrag": attachments.instancer_body_frag, +}); + +mod.addUniformVert("f", "MOD_scale", inScale); + +let needsUpdateDefines = true; +inBlendMode.onChange = () => { needsUpdateDefines = true; }; +doLimit.onChange = updateLimit; +exe.onTriggered = doRender; +exe.onLinkChanged = function () +{ + if (!exe.isLinked()) removeModule(); +}; + +updateLimit(); + +inRot.onChange = +inScales.onChange = +inTranslates.onChange = +inRotMeth.onChange = + function () + { + arrayChangedTrans = true; + recalc = true; + }; + +inTexCoords.onChange = function () +{ + arrayChangedTexcoords = true; + recalc = true; + needsUpdateDefines = true; +}; + +inColor.onChange = function () +{ + arrayChangedColor = true; + recalc = true; + needsUpdateDefines = true; +}; + +function reset() +{ + arrayChangedColor = true, + arrayChangedTrans = true; + recalc = true; +} + +function updateDefines() +{ + mod.toggleDefine("COLORIZE_INSTANCES", inColor.get()); + mod.toggleDefine("TEXCOORDS_INSTANCES", inTexCoords.get()); + mod.toggleDefine("BLEND_MODE_MULTIPLY", inBlendMode.get() === "Multiply"); + mod.toggleDefine("BLEND_MODE_ADD", inBlendMode.get() === "Add"); + mod.toggleDefine("BLEND_MODE_NONE", inBlendMode.get() === "Normal"); + needsUpdateDefines = false; +} + +geom.onChange = function () +{ + if (mesh)mesh.dispose(); + if (!geom.get()) + { + mesh = null; + return; + } + + mesh = new CGL.Mesh(cgl, geom.get()); + reset(); +}; + +function removeModule() +{ + +} + +function setupArray() +{ + if (!mesh) return; + + let transforms = inTranslates.get(); + if (!transforms) transforms = [0, 0, 0]; + + num = Math.floor(transforms.length / 3); + + if (needsUpdateDefines)updateDefines(); + + const colArr = inColor.get(); + const tcArr = inTexCoords.get(); + const scales = inScales.get(); + const useQuats = inRotMeth.get() == "Quaternions"; + const useNormals = inRotMeth.get() == "Normals"; + + let stride = 3; + if (useQuats)stride = 4; + inRot.setUiAttribs({ "stride": stride }); + + if (matrixArray.length != num * 16) matrixArray = new Float32Array(num * 16); + if (instColorArray.length != num * 4) + { + arrayChangedColor = true; + instColorArray = new Float32Array(num * 4); + } + if (instTexcoordArray.length != num * 4) + { + arrayChangedTexcoords = true; + instTexcoordArray = new Float32Array(num * 4); + } + + const rotArr = inRot.get(); + + for (let i = 0; i < num; i++) + { + mat4.identity(m); + + mat4.translate(m, m, + [ + transforms[i * 3], + transforms[i * 3 + 1], + transforms[i * 3 + 2] + ]); + + if (rotArr) + { + if (useQuats) + { + const mq = mat4.create(); + const q = [rotArr[i * 4 + 0], rotArr[i * 4 + 1], rotArr[i * 4 + 2], rotArr[i * 4 + 3]]; + quat.normalize(q, q); + mat4.fromQuat(mq, q); + mat4.mul(m, m, mq); + } + if (useNormals) + { + // let q = quat.create(); + // if (rotArr[i + 1] > 0.99999) + // { + // q.set(0, 0, 0, 1); + // } + // else if (rotArr[i + 1] < -0.99999) + // { + // q.set(1, 0, 0, 0); + // } + // else + // { + // let axis = vec3.create(); + // vec3.set(axis, rotArr[i + 2], 0, -rotArr[i + 0]); + // vec3.normalize(axis, axis); + // let radians = Math.acos(rotArr[i + 1]); + // quat.setAxisAngle(q, axis, radians); + // } + + // const mq = mat4.create(); + + // quat.normalize(q, q); + // mat4.fromQuat(mq, q); + // mat4.mul(m, m, mq); + } + else + { + mat4.rotateX(m, m, rotArr[i * 3 + 0] * CGL.DEG2RAD); + mat4.rotateY(m, m, rotArr[i * 3 + 1] * CGL.DEG2RAD); + mat4.rotateZ(m, m, rotArr[i * 3 + 2] * CGL.DEG2RAD); + } + } + + if (arrayChangedColor && colArr) + { + instColorArray[i * 4 + 0] = colArr[i * 4 + 0]; + instColorArray[i * 4 + 1] = colArr[i * 4 + 1]; + instColorArray[i * 4 + 2] = colArr[i * 4 + 2]; + instColorArray[i * 4 + 3] = colArr[i * 4 + 3]; + } + + if (arrayChangedTexcoords && tcArr) + { + instTexcoordArray[i * 4 + 0] = tcArr[i * 4 + 0]; + instTexcoordArray[i * 4 + 1] = tcArr[i * 4 + 1]; + instTexcoordArray[i * 4 + 2] = tcArr[i * 4 + 2]; + instTexcoordArray[i * 4 + 3] = tcArr[i * 4 + 3]; + } + + if (scales && scales.length > i) mat4.scale(m, m, [scales[i * 3], scales[i * 3 + 1], scales[i * 3 + 2]]); + else mat4.scale(m, m, [1, 1, 1]); + + for (let a = 0; a < 16; a++) matrixArray[i * 16 + a] = m[a]; + } + + mesh.numInstances = num; + + if (arrayChangedTrans) mesh.addAttribute("instMat", matrixArray, 16); + if (arrayChangedColor) mesh.addAttribute("instColor", instColorArray, 4, { "instanced": true }); + if (arrayChangedTexcoords) mesh.addAttribute("instTexCoords", instTexcoordArray, 4, { "instanced": true }); + + mod.toggleDefine("HAS_TEXCOORDS", tcArr); + mod.toggleDefine("HAS_COLORS", colArr); + + arrayChangedColor = false; + recalc = false; +} + +function updateLimit() +{ + inLimit.setUiAttribs({ "greyout": !doLimit.get() }); +} + +function doRender() +{ + if (!mesh) return; + if (recalc) setupArray(); + + mod.bind(); + + if (doLimit.get()) mesh.numInstances = Math.min(num, inLimit.get()); + else mesh.numInstances = num; + + outNum.set(this.name, mesh.numInstances); + + if (mesh.numInstances > 0) mesh.render(cgl.getShader()); + + outTrigger.trigger(); + + mod.unbind(); +} + + +}; + +Ops.Gl.MeshInstancer_v4.prototype = new CABLES.Op(); +CABLES.OPS["322d8c8d-851b-481d-9bee-ec1cf7d57a35"]={f:Ops.Gl.MeshInstancer_v4,objName:"Ops.Gl.MeshInstancer_v4"}; + + + + +// ************************************************************** +// +// Ops.Gl.MeshMorph +// +// ************************************************************** + +Ops.Gl.MeshMorph = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + NUMGEOMS = 16, + render = op.inTrigger("render"), + inMethod = op.inSwitch("Method", ["Auto Anim", "Interpolate Index", "Interpolate Indices"], "Auto Anim"), + nextGeom = op.inValueInt("Geometry"), + duration = op.inValue("Duration", 1.0), + inIndex = op.inFloat("Index", 0), + inIndex2 = op.inFloat("Index 2", 0), + inFade = op.inFloatSlider("Fade", 0), + finished = op.outBoolNum("Finished"), + next = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const inGeoms = []; +let mesh = null; +let method_autoAnim = true; +let method_manualFade = false; +let method_interpolate = false; +let method_interpolate2 = false; +let oldGeom = 0; + +const anim = new CABLES.Anim(); +anim.clear(); +const inEase = anim.createPort(op, "Easing", updateGeom); + +window.meshsequencecounter = window.meshsequencecounter || 1; +window.meshsequencecounter++; +const prfx = String.fromCharCode(97 + window.meshsequencecounter); + +const srcHeadVert = "" + .endl() + "IN vec3 " + prfx + "attrMorphTargetA;" + .endl() + "IN vec3 " + prfx + "attrMorphTargetB;" + .endl(); + +const srcBodyVert = "" + .endl() + " pos = vec4(" + prfx + "attrMorphTargetA * MOD_fade + " + prfx + "attrMorphTargetB * (1.0 - MOD_fade), 1. );" + + .endl(); + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addUniform("f", "MOD_fade", 1); +mod.addUniform("f", "MOD_doMorph", 1); +mod.addModule({ + "title": op.objName, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": srcHeadVert, + "srcBodyVert": srcBodyVert +}); + +inIndex2.onChange = + inIndex.onChange = + nextGeom.onChange = updateGeom; +render.onTriggered = doRender; +inMethod.onChange = updateUi; +updateUi(); + +for (let i = 0; i < NUMGEOMS; i++) +{ + const inGeom = op.inObject("Geometry " + (i)); + inGeom.onChange = updateMeshes; + inGeoms.push(inGeom); +} + +function updateUi() +{ + method_interpolate = inMethod.get() == "Interpolate Index"; + method_autoAnim = inMethod.get() == "Auto Anim"; + method_interpolate2 = inMethod.get() == "Interpolate Indices"; + + duration.setUiAttribs({ "greyout": !method_autoAnim }); + nextGeom.setUiAttribs({ "greyout": !(method_autoAnim || method_manualFade) }); + inIndex.setUiAttribs({ "greyout": !(method_interpolate || method_interpolate2) }); + inIndex2.setUiAttribs({ "greyout": !method_interpolate2 }); + inIndex2.setUiAttribs({ "greyout": !method_interpolate2 }); + inEase.setUiAttribs({ "greyout": !method_autoAnim }); + + inFade.setUiAttribs({ "greyout": !(method_manualFade || method_interpolate2) }); +} + +function checkLength() +{ + op.setUiError("nosamelength", null); + let oldGeomLength = 0; + + for (let i = 0; i < inGeoms.length; i++) + { + const geom = inGeoms[i].get(); + if (geom && geom._vertices) + { + if (oldGeomLength != 0 && oldGeomLength != geom._vertices.length) op.setUiError("nosamelength", "Geometries must have the same number of vertices!", 1); + oldGeomLength = geom._vertices.length; + } + } +} + +function updateMeshes() +{ + checkLength(); + if (mesh) return; + + for (let i = 0; i < inGeoms.length; i++) + { + const geom = inGeoms[i].get(); + if (geom && geom._vertices) + { + if (i === 0) + { + mesh = new CGL.Mesh(cgl, geom); + + mesh.addAttribute(prfx + "attrMorphTargetA", geom._vertices, 3); + mesh.addAttribute(prfx + "attrMorphTargetB", geom._vertices, 3); + updateGeom(); + } + } + } +} + +function updateGeom() +{ + let geom1; + let geom2; + + if (method_autoAnim || method_manualFade) + { + let getGeom = nextGeom.get(); + if (getGeom < 0) getGeom = 0; + else if (getGeom >= NUMGEOMS) getGeom = NUMGEOMS; + let temp = 0; + + if (oldGeom === getGeom) return; + + anim.clear(); + anim.setValue(op.patch.freeTimer.get(), 0); + anim.setValue(op.patch.freeTimer.get() + duration.get(), 1, + function () + { + oldGeom = getGeom; + finished.set(true); + }); + finished.set(false); + + geom1 = inGeoms[oldGeom].get(); + geom2 = inGeoms[getGeom].get(); + + if (method_manualFade) + { + if (inFade.get() != 0) geom2 = inGeoms[oldGeom].get(); + if (inFade.get() == 1) geom1 = inGeoms[getGeom].get(); + + oldGeom = getGeom; + } + } + + if (method_interpolate2) + { + const b = Math.max(Math.floor(inIndex.get()), 0); + const a = Math.min(Math.ceil(inIndex2.get()), NUMGEOMS); + + if (inGeoms[a]) geom1 = inGeoms[a].get(); + else geom1 = null; + + if (inGeoms[b]) geom2 = inGeoms[b].get(); + else geom2 = null; + } + + if (method_interpolate) + { + const a = Math.max(Math.floor(inIndex.get()), 0); + const b = Math.min(Math.ceil(inIndex.get()), NUMGEOMS); + + if (inGeoms[a]) geom1 = inGeoms[a].get(); + else geom1 = null; + + if (inGeoms[b]) geom2 = inGeoms[b].get(); + else geom2 = null; + } + + if (mesh && geom1 && geom2 && geom1._vertices && geom2._vertices) + { + mesh.updateAttribute(prfx + "attrMorphTargetB", geom1._vertices); + mesh.updateAttribute(prfx + "attrMorphTargetA", geom2._vertices); + } +} + +function doRender() +{ + if (method_autoAnim) mod.setUniformValue("MOD_fade", anim.getValue(op.patch.freeTimer.get())); + else if (method_interpolate) + { + let f = inIndex.get() % 1; + mod.setUniformValue("MOD_fade", f); + } + else if (method_manualFade) mod.setUniformValue("MOD_fade", inFade.get()); + else if (method_interpolate2) mod.setUniformValue("MOD_fade", inFade.get()); + + if (mesh) + { + mod.bind(); + mesh.render(cgl.getShader()); + next.trigger(); + mod.unbind(); + } +} + + +}; + +Ops.Gl.MeshMorph.prototype = new CABLES.Op(); +CABLES.OPS["41bc544e-a0c9-450b-b657-405d80b1298c"]={f:Ops.Gl.MeshMorph,objName:"Ops.Gl.MeshMorph"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.CablesLogo +// +// ************************************************************** + +Ops.Gl.Meshes.CablesLogo = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + scale = op.inValue("Scale", 1), + draw = op.inBool("Draw", true), + trigger = op.outTrigger("trigger"), + geomOut = op.outObject("Geometry"); + +const verts = [14.4166, 163.754, 0, 18.4809, 210.763, 0, 54.9491, 204.346, 0, 42.7849, 158.762, 0, 22.5453, 257.772, 0, 67.1133, 249.93, 0, 109.532, 234.597, 0, 89.7001, 191.777, 0, 69.8685, 148.956, 0, 121.577, 173.384, 0, 94.8187, 134.563, 0, 148.336, 212.204, 0, 185.332, 186.28, 0, 150.011, 149.481, 0, 116.915, 116.086, 0, 174.431, 120.383, 0, 135.438, 94.0268, 0, 213.424, 146.739, 0, 241.515, 107.197, 0, 193.515, 87.7918, 0, 149.882, 69.1061, 0, 205.939, 53.4095, 0, 159.743, 42.0425, 0, 252.134, 64.7765, 0, 259.112, 21.5601, 0, 211.953, 17.6223, 0, 164.793, 13.6845, 0, 211.807, -19.1835, 0, 164.803, -15.1197, 0, 258.81, -23.2474, 0, 251.027, -67.8259, 0, 205.438, -55.6602, 0, 159.849, -43.4946, 0, 192.786, -90.46, 0, 150.007, -70.5651, 0, 235.565, -110.355, 0, 213.005, -149.583, 0, 174.326, -122.559, 0, 135.648, -95.5346, 0, 150.535, -150.933, 0, 117.14, -117.606, 0, 183.929, -184.259, 0, 149.313, -213.406, 0, 122.21, -174.782, 0, 95.1064, -136.159, 0, 90.1486, -193.307, 0, 70.1663, -150.569, 0, 110.131, -236.046, 0, 67.6335, -251.595, 0, 55.3747, -206.031, 0, 43.116, -160.467, 0, 18.9111, -212.474, 0, 14.7512, -165.479, 0, 23.071, -259.469, 0, -22.1816, -259.545, 0, -18.1173, -212.536, 0, -14.0529, -165.527, 0, -54.5854, -206.119, 0, -42.4212, -160.536, 0, -66.7496, -251.703, 0, -108.973, -236.672, 0, -89.239, -193.701, 0, -69.5049, -150.73, 0, -120.824, -175.76, 0, -94.4551, -136.336, 0, -147.193, -215.185, 0, -183.41, -190.469, 0, -148.964, -152.339, 0, -116.552, -117.859, 0, -173.286, -123.476, 0, -135.074, -95.8, 0, -211.498, -151.152, 0, -239.586, -111.835, 0, -192.467, -90.79, 0, -149.518, -70.8793, 0, -205.184, -55.8988, 0, -159.38, -43.8157, 0, -250.988, -67.9818, 0, -258.553, -23.6913, 0, -211.491, -19.5745, 0, -164.429, -15.4577, 0, -211.443, 17.4104, 0, -164.439, 13.3465, 0, -258.446, 21.4742, 0, -250.664, 66.0527, 0, -205.075, 53.8871, 0, -159.486, 41.7214, 0, -192.423, 88.6869, 0, -149.644, 68.7919, 0, -235.201, 108.582, 0, -212.641, 147.81, 0, -173.962, 120.786, 0, -135.284, 93.7614, 0, -150.171, 149.16, 0, -116.777, 115.833, 0, -183.566, 182.486, 0, -148.949, 211.632, 0, -121.846, 173.009, 0, -94.7427, 134.385, 0, -89.7849, 191.534, 0, -69.8026, 148.796, 0, -109.767, 234.272, 0, -67.2698, 249.822, 0, -55.011, 204.258, 0, -42.7523, 158.694, 0, -18.5474, 210.7, 0, -14.3875, 163.705, 0, -22.7074, 257.695, 0, 22.5453, 257.772, 0, 18.4809, 210.763, 0, 14.4166, 163.754, 0, 256.822, 264.163, 0, 296.476, 236.296, 0, 276.952, 212.586, 0, 276.952, 212.586, 0, 240.805, 244.919, 0, 256.822, 264.163, 0, 336.13, 208.429, 0, 313.099, 180.253, 0, 276.952, 212.586, 0, 276.952, 212.586, 0, 296.476, 236.296, 0, 336.13, 208.429, 0, 288.309, 152.686, 0, 255.898, 189.327, 0, 313.099, 180.253, 0, 223.486, 225.968, 0, 240.805, 244.919, 0, 285.635, 306.513, 0, 328.243, 283.496, 0, 313.087, 259.335, 0, 313.087, 259.335, 0, 271.643, 284.706, 0, 285.635, 306.513, 0, 370.852, 260.478, 0, 354.53, 233.964, 0, 313.087, 259.335, 0, 313.087, 259.335, 0, 328.243, 283.496, 0, 370.852, 260.478, 0, 336.13, 208.429, 0, 296.476, 236.296, 0, 354.53, 233.964, 0, 336.13, 208.429, 0, 256.822, 264.163, 0, 271.643, 284.706, 0, 296.476, 236.296, 0, 256.822, 264.163, 0, 311.134, 352.806, 0, 357.268, 338.992, 0, 343.405, 310.57, 0, 343.405, 310.57, 0, 299.162, 329.55, 0, 311.134, 352.806, 0, 403.403, 325.177, 0, 387.649, 291.589, 0, 343.405, 310.57, 0, 343.405, 310.57, 0, 357.268, 338.992, 0, 403.403, 325.177, 0, 370.852, 260.478, 0, 328.243, 283.496, 0, 387.649, 291.589, 0, 370.852, 260.478, 0, 285.635, 306.513, 0, 299.162, 329.55, 0, 328.243, 283.496, 0, 285.635, 306.513, 0, 328.173, 398.813, 0, 377.479, 395.259, 0, 368.527, 367.195, 0, 368.527, 367.195, 0, 320.46, 375.27, 0, 328.173, 398.813, 0, 426.784, 391.705, 0, 416.594, 359.12, 0, 368.527, 367.195, 0, 368.527, 367.195, 0, 377.479, 395.259, 0, 426.784, 391.705, 0, 403.403, 325.177, 0, 357.268, 338.992, 0, 416.594, 359.12, 0, 403.403, 325.177, 0, 311.134, 352.806, 0, 320.46, 375.27, 0, 357.268, 338.992, 0, 311.134, 352.806, 0, 341.169, 453.101, 0, 389.523, 451.215, 0, 384.421, 423.263, 0, 384.421, 423.263, 0, 335.304, 425.309, 0, 341.169, 453.101, 0, 437.877, 449.328, 0, 433.538, 421.218, 0, 384.421, 423.263, 0, 384.421, 423.263, 0, 389.523, 451.215, 0, 437.877, 449.328, 0, 426.784, 391.705, 0, 377.479, 395.259, 0, 433.538, 421.218, 0, 426.784, 391.705, 0, 328.173, 398.813, 0, 335.304, 425.309, 0, 377.479, 395.259, 0, 328.173, 398.813, 0, 347.768, 502.233, 0, 394.824, 501.411, 0, 392.954, 479.119, 0, 392.954, 479.119, 0, 345.086, 480.533, 0, 347.768, 502.233, 0, 441.88, 500.589, 0, 440.822, 477.705, 0, 392.954, 479.119, 0, 392.954, 479.119, 0, 394.824, 501.411, 0, 441.88, 500.589, 0, 437.877, 449.328, 0, 389.523, 451.215, 0, 440.822, 477.705, 0, 437.877, 449.328, 0, 341.169, 453.101, 0, 345.086, 480.533, 0, 389.523, 451.215, 0, 341.169, 453.101, 0, 352.384, 517.252, 0, 394.985, 517.267, 0, 395.241, 512.525, 0, 395.241, 512.525, 0, 349.927, 512.83, 0, 352.384, 517.252, 0, 437.585, 517.282, 0, 440.555, 512.22, 0, 395.241, 512.525, 0, 395.241, 512.525, 0, 394.985, 517.267, 0, 437.585, 517.282, 0, 441.88, 500.589, 0, 394.824, 501.411, 0, 440.555, 512.22, 0, 441.88, 500.589, 0, 347.768, 502.233, 0, 349.927, 512.83, 0, 394.824, 501.411, 0, 347.768, 502.233, 0, 360.098, 522.975, 0, 394.737, 522.834, 0, 394.834, 520.442, 0, 394.834, 520.442, 0, 355.961, 520.425, 0, 360.098, 522.975, 0, 429.375, 522.693, 0, 433.707, 520.459, 0, 394.834, 520.442, 0, 394.834, 520.442, 0, 394.737, 522.834, 0, 429.375, 522.693, 0, 437.585, 517.282, 0, 394.985, 517.267, 0, 433.707, 520.459, 0, 437.585, 517.282, 0, 355.961, 520.425, 0, 394.834, 520.442, 0, 394.985, 517.267, 0, 352.384, 517.252, 0, 185.332, 186.28, 0, 204.761, 206.303, 0, 234.697, 167.64, 0, 213.424, 146.739, 0, 264.633, 128.977, 0, 241.515, 107.197, 0, -255.099, -268.612, 0, -294.753, -240.745, 0, -275.229, -217.035, 0, -275.229, -217.035, 0, -239.082, -249.368, 0, -255.099, -268.612, 0, -334.408, -212.878, 0, -311.376, -184.702, 0, -275.229, -217.035, 0, -275.229, -217.035, 0, -294.753, -240.745, 0, -334.408, -212.878, 0, -286.56, -157.158, 0, -254.149, -193.771, 0, -311.376, -184.702, 0, -221.739, -230.385, 0, -239.082, -249.368, 0, -283.912, -310.962, 0, -326.521, -287.944, 0, -311.364, -263.784, 0, -311.364, -263.784, 0, -269.92, -289.154, 0, -283.912, -310.962, 0, -369.129, -264.927, 0, -352.807, -238.413, 0, -311.364, -263.784, 0, -311.364, -263.784, 0, -326.521, -287.944, 0, -369.129, -264.927, 0, -334.408, -212.878, 0, -294.753, -240.745, 0, -352.807, -238.413, 0, -334.408, -212.878, 0, -255.099, -268.612, 0, -269.92, -289.154, 0, -294.753, -240.745, 0, -255.099, -268.612, 0, -309.411, -357.255, 0, -355.546, -343.44, 0, -341.683, -315.018, 0, -341.683, -315.018, 0, -297.439, -333.999, 0, -309.411, -357.255, 0, -401.681, -329.626, 0, -385.927, -296.038, 0, -341.683, -315.018, 0, -341.683, -315.018, 0, -355.546, -343.44, 0, -401.681, -329.626, 0, -369.129, -264.927, 0, -326.521, -287.944, 0, -385.927, -296.038, 0, -369.129, -264.927, 0, -283.912, -310.962, 0, -297.439, -333.999, 0, -326.521, -287.944, 0, -283.912, -310.962, 0, -326.45, -403.262, 0, -375.756, -399.708, 0, -366.804, -371.644, 0, -366.804, -371.644, 0, -318.737, -379.718, 0, -326.45, -403.262, 0, -425.061, -396.154, 0, -414.871, -363.569, 0, -366.804, -371.644, 0, -366.804, -371.644, 0, -375.756, -399.708, 0, -425.061, -396.154, 0, -401.681, -329.626, 0, -355.546, -343.44, 0, -414.871, -363.569, 0, -401.681, -329.626, 0, -309.411, -357.255, 0, -318.737, -379.718, 0, -355.546, -343.44, 0, -309.411, -357.255, 0, -339.446, -457.55, 0, -387.8, -455.663, 0, -382.698, -427.712, 0, -382.698, -427.712, 0, -333.581, -429.758, 0, -339.446, -457.55, 0, -436.154, -453.776, 0, -431.815, -425.666, 0, -382.698, -427.712, 0, -382.698, -427.712, 0, -387.8, -455.663, 0, -436.154, -453.776, 0, -425.061, -396.154, 0, -375.756, -399.708, 0, -431.815, -425.666, 0, -425.061, -396.154, 0, -326.45, -403.262, 0, -333.581, -429.758, 0, -375.756, -399.708, 0, -326.45, -403.262, 0, -346.045, -506.682, 0, -393.101, -505.86, 0, -391.232, -483.568, 0, -391.232, -483.568, 0, -343.363, -484.982, 0, -346.045, -506.682, 0, -440.157, -505.037, 0, -439.1, -482.153, 0, -391.232, -483.568, 0, -391.232, -483.568, 0, -393.101, -505.86, 0, -440.157, -505.037, 0, -436.154, -453.776, 0, -387.8, -455.663, 0, -439.1, -482.153, 0, -436.154, -453.776, 0, -339.446, -457.55, 0, -343.363, -484.982, 0, -387.8, -455.663, 0, -339.446, -457.55, 0, -350.661, -521.701, 0, -393.262, -521.716, 0, -393.518, -516.974, 0, -393.518, -516.974, 0, -348.204, -517.279, 0, -350.661, -521.701, 0, -435.862, -521.731, 0, -438.832, -516.669, 0, -393.518, -516.974, 0, -393.518, -516.974, 0, -393.262, -521.716, 0, -435.862, -521.731, 0, -440.157, -505.037, 0, -393.101, -505.86, 0, -438.832, -516.669, 0, -440.157, -505.037, 0, -346.045, -506.682, 0, -348.204, -517.279, 0, -393.101, -505.86, 0, -346.045, -506.682, 0, -358.375, -527.424, 0, -393.014, -527.283, 0, -393.111, -524.891, 0, -393.111, -524.891, 0, -354.238, -524.874, 0, -358.375, -527.424, 0, -427.653, -527.142, 0, -431.985, -524.908, 0, -393.111, -524.891, 0, -393.111, -524.891, 0, -393.014, -527.283, 0, -427.653, -527.142, 0, -435.862, -521.731, 0, -393.262, -521.716, 0, -431.985, -524.908, 0, -435.862, -521.731, 0, -354.238, -524.874, 0, -393.111, -524.891, 0, -393.262, -521.716, 0, -350.661, -521.701, 0, -183.41, -190.469, 0, -202.939, -210.621, 0, -232.873, -172.071, 0, -211.498, -151.152, 0, -262.807, -133.52, 0, -239.586, -111.835, 0]; +const indices = [0, 1, 2, 2, 3, 0, 2, 1, 4, 4, 5, 2, 6, 7, 2, 2, 5, 6, 8, 3, 2, 2, 7, 8, 6, 11, 9, 9, 7, 6, 8, 7, 9, 9, 10, 8, 12, 13, 9, 9, 11, 12, 14, 10, 9, 9, 13, 14, 12, 17, 15, 15, 13, 12, 14, 13, 15, 15, 16, 14, 18, 19, 15, 15, 17, 18, 20, 16, 15, 15, 19, 20, 18, 23, 21, 21, 19, 18, 20, 19, 21, 21, 22, 20, 24, 25, 21, 21, 23, 24, 26, 22, 21, 21, 25, 26, 24, 29, 27, 27, 25, 24, 26, 25, 27, 27, 28, 26, 30, 31, 27, 27, 29, 30, 32, 28, 27, 27, 31, 32, 30, 35, 33, 33, 31, 30, 32, 31, 33, 33, 34, 32, 36, 37, 33, 33, 35, 36, 38, 34, 33, 33, 37, 38, 36, 41, 39, 39, 37, 36, 38, 37, 39, 39, 40, 38, 42, 43, 39, 39, 41, 42, 44, 40, 39, 39, 43, 44, 42, 47, 45, 45, 43, 42, 44, 43, 45, 45, 46, 44, 48, 49, 45, 45, 47, 48, 50, 46, 45, 45, 49, 50, 48, 53, 51, 51, 49, 48, 50, 49, 51, 51, 52, 50, 54, 55, 51, 51, 53, 54, 56, 52, 51, 51, 55, 56, 54, 59, 57, 57, 55, 54, 56, 55, 57, 57, 58, 56, 60, 61, 57, 57, 59, 60, 62, 58, 57, 57, 61, 62, 60, 65, 63, 63, 61, 60, 62, 61, 63, 63, 64, 62, 66, 67, 63, 63, 65, 66, 68, 64, 63, 63, 67, 68, 66, 71, 69, 69, 67, 66, 68, 67, 69, 69, 70, 68, 72, 73, 69, 69, 71, 72, 74, 70, 69, 69, 73, 74, 72, 77, 75, 75, 73, 72, 74, 73, 75, 75, 76, 74, 78, 79, 75, 75, 77, 78, 80, 76, 75, 75, 79, 80, 78, 83, 81, 81, 79, 78, 80, 79, 81, 81, 82, 80, 84, 85, 81, 81, 83, 84, 86, 82, 81, 81, 85, 86, 84, 89, 87, 87, 85, 84, 86, 85, 87, 87, 88, 86, 90, 91, 87, 87, 89, 90, 92, 88, 87, 87, 91, 92, 90, 95, 93, 93, 91, 90, 92, 91, 93, 93, 94, 92, 96, 97, 93, 93, 95, 96, 98, 94, 93, 93, 97, 98, 96, 101, 99, 99, 97, 96, 98, 97, 99, 99, 100, 98, 102, 103, 99, 99, 101, 102, 104, 100, 99, 99, 103, 104, 102, 107, 105, 105, 103, 102, 104, 103, 105, 105, 106, 104, 108, 109, 105, 105, 107, 108, 110, 106, 105, 105, 109, 110, 111, 112, 113, 123, 124, 113, 113, 125, 123, 126, 127, 113, 113, 124, 126, 123, 272, 270, 270, 124, 123, 126, 124, 270, 270, 269, 126, 268, 269, 270, 270, 271, 268, 273, 271, 270, 270, 272, 273, 114, 115, 116, 117, 118, 119, 120, 121, 122, 128, 129, 130, 130, 142, 143, 131, 132, 133, 140, 141, 131, 134, 135, 136, 136, 146, 147, 137, 138, 139, 144, 145, 137, 148, 149, 150, 150, 162, 163, 151, 152, 153, 160, 161, 151, 154, 155, 156, 156, 166, 167, 157, 158, 159, 164, 165, 157, 168, 169, 170, 170, 182, 183, 171, 172, 173, 180, 181, 171, 174, 175, 176, 176, 186, 187, 177, 178, 179, 184, 185, 177, 188, 189, 190, 190, 202, 203, 191, 192, 193, 200, 201, 191, 194, 195, 196, 196, 206, 207, 197, 198, 199, 204, 205, 197, 208, 209, 210, 210, 222, 223, 211, 212, 213, 220, 221, 211, 214, 215, 216, 216, 226, 227, 217, 218, 219, 224, 225, 217, 228, 229, 230, 228, 264, 250, 230, 242, 243, 248, 249, 250, 250, 262, 263, 231, 232, 233, 240, 241, 231, 234, 235, 236, 236, 246, 247, 237, 238, 239, 244, 245, 237, 251, 252, 253, 260, 261, 251, 254, 255, 256, 257, 258, 259, 265, 266, 267, 274, 275, 276, 286, 287, 276, 276, 288, 286, 289, 290, 276, 276, 287, 289, 286, 435, 433, 433, 287, 286, 289, 287, 433, 433, 432, 289, 431, 432, 433, 433, 434, 431, 436, 434, 433, 433, 435, 436, 277, 278, 279, 280, 281, 282, 283, 284, 285, 291, 292, 293, 293, 305, 306, 294, 295, 296, 303, 304, 294, 297, 298, 299, 299, 309, 310, 300, 301, 302, 307, 308, 300, 311, 312, 313, 313, 325, 326, 314, 315, 316, 323, 324, 314, 317, 318, 319, 319, 329, 330, 320, 321, 322, 327, 328, 320, 331, 332, 333, 333, 345, 346, 334, 335, 336, 343, 344, 334, 337, 338, 339, 339, 349, 350, 340, 341, 342, 347, 348, 340, 351, 352, 353, 353, 365, 366, 354, 355, 356, 363, 364, 354, 357, 358, 359, 359, 369, 370, 360, 361, 362, 367, 368, 360, 371, 372, 373, 373, 385, 386, 374, 375, 376, 383, 384, 374, 377, 378, 379, 379, 389, 390, 380, 381, 382, 387, 388, 380, 391, 392, 393, 391, 427, 413, 393, 405, 406, 411, 412, 413, 413, 425, 426, 394, 395, 396, 403, 404, 394, 397, 398, 399, 399, 409, 410, 400, 401, 402, 407, 408, 400, 414, 415, 416, 423, 424, 414, 417, 418, 419, 420, 421, 422, 428, 429, 430]; + +let geom = new CGL.Geometry(op.name); +let mesh = null; +scale.onChange = build; +build(); + +function build() +{ + let sc = scale.get(); + let vertices = verts.slice(0); + + for (let i = 0; i < vertices.length; i++) vertices[i] = vertices[i] / 1000 * sc; + + geom.vertices = vertices; + geom.mapTexCoords2d(); + geom.verticesIndices = indices; + geom.tangents = vertices.map(function (v, i) { return i % 3 == 0 ? 1 : 0; }); + geom.biTangents = vertices.map(function (v, i) { return i % 3 == 1 ? 1 : 0; }); + geom.vertexNormals = vertices.map(function (v, i) { return i % 3 == 2 ? 1 : 0; }); + geomOut.set(null); + geomOut.set(geom); + + if (!mesh)mesh = new CGL.Mesh(op.patch.cgl, geom); + else mesh.setGeom(geom); +} + +render.onTriggered = function () +{ + if (draw.get()) + mesh.render(op.patch.cgl.getShader()); + trigger.trigger(); +}; + + +}; + +Ops.Gl.Meshes.CablesLogo.prototype = new CABLES.Op(); +CABLES.OPS["d53b5d7b-99b5-420e-b5a1-2d7c2c1f1ebb"]={f:Ops.Gl.Meshes.CablesLogo,objName:"Ops.Gl.Meshes.CablesLogo"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Circle +// +// ************************************************************** + +Ops.Gl.Meshes.Circle = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + radius = op.inValue("radius", 0.5), + innerRadius = op.inValueSlider("innerRadius", 0), + segments = op.inValueInt("segments", 40), + percent = op.inValueSlider("percent", 1), + steps = op.inValue("steps", 0), + invertSteps = op.inValueBool("invertSteps", false), + mapping = op.inSwitch("mapping", ["flat", "round"]), + drawSpline = op.inValueBool("Spline", false), + inDraw = op.inValueBool("Draw", true), + trigger = op.outTrigger("trigger"), + geomOut = op.outObject("geometry", null, "geometry"); + +op.setPortGroup("Size", [radius, innerRadius]); +op.setPortGroup("Display", [percent, steps, invertSteps]); + +mapping.set("flat"); + +mapping.onChange = + segments.onChange = + radius.onChange = + innerRadius.onChange = + percent.onChange = + steps.onChange = + invertSteps.onChange = + drawSpline.onChange = calcLater; + +geomOut.ignoreValueSerialize = true; +const cgl = op.patch.cgl; + +let geom = new CGL.Geometry("circle"); +let mesh = null; +const lastSegs = -1; + +let oldPrim = 0; +let shader = null; +let needsCalc = true; + +render.onTriggered = renderMesh; + +op.preRender = () => +{ + renderMesh(); +}; + +function renderMesh() +{ + if (!CGL.TextureEffect.checkOpNotInTextureEffect(op)) return; + + if (needsCalc)calc(); + shader = cgl.getShader(); + if (!shader) return; + oldPrim = shader.glPrimitive; + + if (drawSpline.get()) shader.glPrimitive = cgl.gl.LINE_STRIP; + + if (inDraw.get())mesh.render(shader); + trigger.trigger(); + + shader.glPrimitive = oldPrim; +} + +function calc() +{ + const segs = Math.max(3, Math.floor(segments.get())); + + geom.clear(); + + const faces = []; + const texCoords = []; + const vertexNormals = []; + const tangents = []; + const biTangents = []; + + let i = 0, degInRad = 0; + let oldPosX = 0, oldPosY = 0; + let oldPosXTexCoord = 0, oldPosYTexCoord = 0; + + let oldPosXIn = 0, oldPosYIn = 0; + let oldPosXTexCoordIn = 0, oldPosYTexCoordIn = 0; + + let posxTexCoordIn = 0, posyTexCoordIn = 0; + let posxTexCoord = 0, posyTexCoord = 0; + let posx = 0, posy = 0; + + const perc = Math.max(0.0, percent.get()); + const verts = []; + + if (drawSpline.get()) + { + let lastX = 0; + let lastY = 0; + const tc = []; + for (i = 0; i <= segs * perc; i++) + { + degInRad = (360 / segs) * i * CGL.DEG2RAD; + posx = Math.cos(degInRad) * radius.get(); + posy = Math.sin(degInRad) * radius.get(); + + posyTexCoord = 0.5; + + if (i > 0) + { + verts.push(lastX); + verts.push(lastY); + verts.push(0); + posxTexCoord = 1.0 - (i - 1) / segs; + + tc.push(posxTexCoord, posyTexCoord); + } + verts.push(posx); + verts.push(posy); + verts.push(0); + + lastX = posx; + lastY = posy; + } + geom.setPointVertices(verts); + } + else + if (innerRadius.get() <= 0) + { + for (i = 0; i <= segs * perc; i++) + { + degInRad = (360 / segs) * i * CGL.DEG2RAD; + posx = Math.cos(degInRad) * radius.get(); + posy = Math.sin(degInRad) * radius.get(); + + if (mapping.get() == "flat") + { + posxTexCoord = (Math.cos(degInRad) + 1.0) / 2; + posyTexCoord = 1.0 - (Math.sin(degInRad) + 1.0) / 2; + posxTexCoordIn = 0.5; + posyTexCoordIn = 0.5; + } + else if (mapping.get() == "round") + { + posxTexCoord = 1.0 - i / segs; + posyTexCoord = 0; + posxTexCoordIn = posxTexCoord; + posyTexCoordIn = 1; + } + + faces.push( + [posx, posy, 0], + [oldPosX, oldPosY, 0], + [0, 0, 0] + ); + + texCoords.push(posxTexCoord, posyTexCoord, oldPosXTexCoord, oldPosYTexCoord, posxTexCoordIn, posyTexCoordIn); + vertexNormals.push(0, 0, 1, 0, 0, 1, 0, 0, 1); + tangents.push(1, 0, 0, 1, 0, 0, 1, 0, 0); + biTangents.push(0, 1, 0, 0, 1, 0, 0, 1, 0); + + oldPosXTexCoord = posxTexCoord; + oldPosYTexCoord = posyTexCoord; + + oldPosX = posx; + oldPosY = posy; + } + + geom = CGL.Geometry.buildFromFaces(faces, "circle"); + geom.vertexNormals = vertexNormals; + geom.tangents = tangents; + geom.biTangents = biTangents; + geom.texCoords = texCoords; + } + else + { + let count = 0; + const numSteps = segs * perc; + const pos = 0; + + for (i = 0; i <= numSteps; i++) + { + count++; + + degInRad = (360 / segs) * i * CGL.DEG2RAD; + posx = Math.cos(degInRad) * radius.get(); + posy = Math.sin(degInRad) * radius.get(); + + const posxIn = Math.cos(degInRad) * innerRadius.get() * radius.get(); + const posyIn = Math.sin(degInRad) * innerRadius.get() * radius.get(); + + if (mapping.get() == "round") + { + posxTexCoord = 1.0 - i / segs; + posyTexCoord = 0; + posxTexCoordIn = posxTexCoord; + posyTexCoordIn = 1; + } + + if (steps.get() === 0.0 || + (count % parseInt(steps.get(), 10) === 0 && !invertSteps.get()) || + (count % parseInt(steps.get(), 10) !== 0 && invertSteps.get())) + { + faces.push( + [posx, posy, 0], + [oldPosX, oldPosY, 0], + [posxIn, posyIn, 0] + ); + + faces.push( + [posxIn, posyIn, 0], + [oldPosX, oldPosY, 0], + [oldPosXIn, oldPosYIn, 0] + ); + + texCoords.push( + posxTexCoord, 0, + oldPosXTexCoord, 0, + posxTexCoordIn, 1, + + posxTexCoord, 1, + oldPosXTexCoord, 0, + oldPosXTexCoordIn, 1); + + vertexNormals.push( + 0, 0, 1, 0, 0, 1, 0, 0, 1, + 0, 0, 1, 0, 0, 1, 0, 0, 1 + ); + tangents.push( + 1, 0, 0, 1, 0, 0, 1, 0, 0, + 1, 0, 0, 1, 0, 0, 1, 0, 0 + ); + biTangents.push( + 0, 1, 0, 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, 0, 1, 0 + ); + } + + oldPosXTexCoordIn = posxTexCoordIn; + oldPosYTexCoordIn = posyTexCoordIn; + + oldPosXTexCoord = posxTexCoord; + oldPosYTexCoord = posyTexCoord; + + oldPosX = posx; + oldPosY = posy; + + oldPosXIn = posxIn; + oldPosYIn = posyIn; + } + + geom = CGL.Geometry.buildFromFaces(faces, "circle"); + geom.vertexNormals = vertexNormals; + geom.tangents = tangents; + geom.biTangents = biTangents; + + if (mapping.get() == "flat") geom.mapTexCoords2d(); + else geom.texCoords = texCoords; + } + + geomOut.set(null); + geomOut.set(geom); + + if (geom.vertices.length == 0) return; + if (mesh) mesh.dispose(); + mesh = null; + mesh = new CGL.Mesh(cgl, geom); + needsCalc = false; +} + +function calcLater() +{ + needsCalc = true; +} + +op.onDelete = function () +{ + if (mesh)mesh.dispose(); +}; + + +}; + +Ops.Gl.Meshes.Circle.prototype = new CABLES.Op(); +CABLES.OPS["4db917cc-2cef-43f4-83d5-38c4572fe943"]={f:Ops.Gl.Meshes.Circle,objName:"Ops.Gl.Meshes.Circle"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Cone +// +// ************************************************************** + +Ops.Gl.Meshes.Cone = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// adapted from the FreeGLUT project +const + render = op.inTrigger("render"), + slices = op.inValue("slices", 32), + stacks = op.inValue("stacks", 5), + radius = op.inValue("radius", 1), + height = op.inValue("height", 2), + active = op.inValueBool("Active", true), + trigger = op.outTrigger("trigger"), + geomOut = op.outObject("geometry"); + +geomOut.ignoreValueSerialize = true; + +const cgl = op.patch.cgl; +let mesh = null; +const geom = null; +let i = 0, j = 0, idx = 0, offset = 0; + +let needsRebuild = true; + +stacks.onChange = slices.onChange = radius.onChange = height.onChange = updateMeshLater; + +function updateMeshLater() +{ + needsRebuild = true; +} + +render.onTriggered = function () +{ + if (needsRebuild) updateMesh(); + if (active.get() && mesh) + { + mesh.render(cgl.getShader()); + } + else + { + trigger.trigger(); + return; + } + // mesh.render(cgl.getShader()); + trigger.trigger(); +}; + +function updateMesh() +{ + let nstacks = Math.round(stacks.get()); + let nslices = Math.round(slices.get()); + if (nstacks < 1)nstacks = 1; + if (nslices < 3)nslices = 3; + const r = radius.get(); + generateCone(r, Math.max(0.01, height.get()), nstacks, nslices); + needsRebuild = false; +} + +function circleTable(n, halfCircle) +{ + let i; + /* Table size, the sign of n flips the circle direction */ + const size = Math.abs(n); + + /* Determine the angle between samples */ + const angle = (halfCircle ? 1 : 2) * Math.PI / n;// ( n === 0 ) ? 1 : n ; + + /* Allocate memory for n samples, plus duplicate of first entry at the end */ + const sint = []; + const cost = []; + + /* Compute cos and sin around the circle */ + sint[0] = 0.0; + cost[0] = 1.0; + + for (i = 1; i < size; i++) + { + sint[i] = Math.sin(angle * i); + cost[i] = Math.cos(angle * i); + } + + if (halfCircle) + { + sint[size] = 0.0; /* sin PI */ + cost[size] = -1.0; /* cos PI */ + } + else + { + /* Last sample is duplicate of the first (sin or cos of 2 PI) */ + sint[size] = sint[0]; + cost[size] = cost[0]; + } + return { "cost": cost, "sint": sint }; +} + +function generateCone(base, height, stacks, slices) +{ + let r = base; + let z = 0; + const geom = new CGL.Geometry(op.name); + geom.glPrimitive = cgl.gl.TRIANGLE_STRIP; + geom.tangents = []; + geom.biTangents = []; + + const table = circleTable(-slices + 1, false); + + const zStep = height / ((stacks > 0) ? stacks : 1); + const rStep = base / ((stacks > 0) ? stacks : 1); + + /* Scaling factors for vertex normals */ + const cosn = (height / Math.sqrt(height * height + base * base)); + const sinn = (base / Math.sqrt(height * height + base * base)); + const texCoords = []; + + /* bottom */ + geom.vertices[0] = 0; + geom.vertices[1] = 0; + geom.vertices[2] = z; + geom.vertexNormals[0] = 0; + geom.vertexNormals[1] = 0; + geom.vertexNormals[2] = -1; + geom.tangents.push(1, 0, 0); + geom.biTangents.push(0, 1, 0); + + idx = 3; // index carried over through all for loops - allows mesh buildup + /* other on bottom (get normals right) */ + + for (j = 0; j < slices; j++, idx += 3) + { + geom.vertices[idx] = table.cost[j] * r; + geom.vertices[idx + 1] = table.sint[j] * r; + geom.vertices[idx + 2] = z; + geom.vertexNormals[idx] = 0; + geom.vertexNormals[idx + 1] = 0; + geom.vertexNormals[idx + 2] = -1; + geom.tangents[idx] = 1; + geom.tangents[idx + 1] = 0; + geom.tangents[idx + 2] = 0; + geom.biTangents[idx] = 0; + geom.biTangents[idx + 1] = 1; + geom.biTangents[idx + 2] = 0; + } + + /* each stack */ + for (i = 0; i < stacks + 1; i++) + { + for (j = 0; j < slices; j++, idx += 3) + { + // gets texcoords from textured material + // xyz converts to xy for uv + texCoords[idx / 3 * 2] = 1 - j / slices; + texCoords[idx / 3 * 2 + 1] = 1 - i / stacks; + + geom.vertices[idx] = table.cost[j] * r; + geom.vertices[idx + 1] = table.sint[j] * r; + geom.vertices[idx + 2] = z; + geom.vertexNormals[idx] = table.cost[j] * cosn; + geom.vertexNormals[idx + 1] = table.sint[j] * cosn; + geom.vertexNormals[idx + 2] = sinn; + geom.tangents[idx] = -table.sint[j] * cosn; + geom.tangents[idx + 1] = table.cost[j] * cosn; + geom.tangents[idx + 2] = sinn; + geom.biTangents[idx] = table.sint[j] * cosn * sinn - table.cost[j] * cosn * sinn; + geom.biTangents[idx + 1] = sinn * (-table.sint[j] * cosn) - sinn * table.cost[j] * cosn; + geom.biTangents[idx + 2] = table.cost[j] * cosn * table.cost[j] * cosn - (-table.sint[j] * cosn) * table.sint[j] * cosn; + } + + z += zStep; + r -= rStep; + } + + /* top stack - bottom section */ + for (j = 0, idx = 0; j < slices; j++, idx += 2) + { + // makes the texture cartopol + texCoords[0] = (geom.vertices[0] / radius.get()) * 0.5 + 0.5; + texCoords[1] = 1 - (geom.vertices[1] / radius.get()) * 0.5 + 0.5; + + texCoords[j * 2 + 0] = (geom.vertices[(j) * 3] / radius.get()) * 0.5 + 0.5; + texCoords[j * 2 + 1] = 1 - (geom.vertices[(j) * 3 + 1] / radius.get()) * 0.5 + 0.5; + + geom.verticesIndices[idx] = 0; + geom.verticesIndices[idx + 1] = j + 1; /* 0 is top vertex, 1 is first for first stack */ + } + + geom.verticesIndices[idx] = 0; /* repeat first slice's idx for closing off shape */ + geom.verticesIndices[idx + 1] = 1; + + texCoords[0] = (geom.vertices[0] / radius.get()) * 0.5 + 0.5; + texCoords[1] = 1 - (geom.vertices[1] / radius.get()) * 0.5 + 0.5; + + texCoords[j * 2 + 0] = (geom.vertices[(j) * 3] / radius.get()) * 0.5 + 0.5; + texCoords[j * 2 + 1] = 1 - (geom.vertices[(j) * 3 + 1] / radius.get()) * 0.5 + 0.5; + + idx += 2; + + /* middle stacks: */ + /* Strip indices are relative to first index belonging to strip, NOT relative to first vertex/normal pair in array */ + for (i = 0; i < stacks; i++, idx += 2) + { + offset = 1 + (i + 1) * slices; /* triangle_strip indices start at 1 (0 is top vertex), and we advance one stack down as we go along */ + for (j = 0; j < slices; j++, idx += 2) + { + geom.verticesIndices[idx] = offset + j; + geom.verticesIndices[idx + 1] = offset + j + slices; + } + geom.verticesIndices[idx] = offset; /* repeat first slice's idx for closing off shape */ + geom.verticesIndices[idx + 1] = offset + slices; + } + + geom.setTexCoords(texCoords); + + mesh = new CGL.Mesh(cgl, geom); + geomOut.set(geom); +} + + +}; + +Ops.Gl.Meshes.Cone.prototype = new CABLES.Op(); +CABLES.OPS["b67027f5-8f56-4aa0-8bb3-18d42ff15ffe"]={f:Ops.Gl.Meshes.Cone,objName:"Ops.Gl.Meshes.Cone"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Corner +// +// ************************************************************** + +Ops.Gl.Meshes.Corner = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let render = op.inTrigger("Render"); +let width = op.inValueFloat("Width", 1); +let height = op.inValueFloat("Height", 1); +let thickness = op.inValueFloat("Thickness", -0.1); +let dodraw = op.inValueBool("Draw", true); +let pivotX = op.inValueSelect("pivot x", ["center", "left", "right"]); +let pivotY = op.inValueSelect("pivot y", ["center", "top", "bottom"]); + +let trigger = op.outTrigger("trigger"); +let geomOut = op.outObject("Geometry"); + +op.setPortGroup("Size", [width, height]); +op.setPortGroup("Align", [pivotX, pivotY]); + +let cgl = op.patch.cgl; +let mesh = null; +let geom = new CGL.Geometry(op.name); +geom.tangents = []; +geom.biTangents = []; + +pivotX.set("center"); +pivotY.set("center"); + +geomOut.ignoreValueSerialize = true; + +width.onChange = + pivotX.onChange = + pivotY.onChange = + height.onChange = + thickness.onChange = create; + +create(); + +render.onTriggered = function () +{ + if (dodraw.get()) mesh.render(cgl.getShader()); + trigger.trigger(); +}; + +function create() +{ + let w = width.get(); + let h = height.get(); + let x = -w / 2; + let y = -h / 2; + let th = thickness.get(); + + let pivot = pivotX.get(); + if (pivot == "right") x = -w; + else if (pivot == "left") x = 0; + + pivot = pivotY.get(); + if (pivot == "top") y = -w; + else if (pivot == "bottom") y = 0; + + geom.vertices.length = 0; + geom.vertices.push( + x, y, 0, + x + w, y, 0, + x + w, y + h, 0, + x, y + h, 0, + x - th, y, 0, + x + w + th, y - th, 0, + x + w, y + h + th, 0, + x - th, y + h + th, 0 + ); + + if (geom.vertexNormals.length === 0) geom.vertexNormals = [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]; + if (geom.tangents.length === 0) geom.tangents = [1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0]; + if (geom.biTangents.length === 0) geom.biTangents = [0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0]; + + geom.verticesIndices = [7, 6, 3, 6, 2, 3, 0, 4, 3, 4, 7, 3]; + + if (geom.texCoords.length === 0) + { + const tc = []; + for (let i = 0; i < geom.vertices.length; i += 3) + { + tc[i / 3 * 2] = geom.vertices[i + 0] / w - 0.5; + tc[i / 3 * 2 + 1] = geom.vertices[i + 1] / h - 0.5; + } + geom.texCoords = tc; + } + + if (!mesh) mesh = new CGL.Mesh(cgl, geom); + else mesh.setGeom(geom); + + geomOut.set(null); + geomOut.set(geom); +} + + +}; + +Ops.Gl.Meshes.Corner.prototype = new CABLES.Op(); +CABLES.OPS["7624c3bb-d22f-47f3-8581-2ecca73bb12f"]={f:Ops.Gl.Meshes.Corner,objName:"Ops.Gl.Meshes.Corner"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Cross +// +// ************************************************************** + +Ops.Gl.Meshes.Cross = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Render"), + size = op.inValue("Size", 1), + thick = op.inValue("Thickness", 0.25), + target = op.inValueBool("Crosshair"), + active = op.inValueBool("Active", true), + + trigger = op.outTrigger("Next"), + geomOut = op.outObject("Geometry"); + +const cgl = op.patch.cgl; +let geom = null; +let mesh = null; + +size.onChange = + thick.onChange = + target.onChange = buildMeshLater; + +render.onTriggered = function () +{ + if (!mesh)buildMesh(); + if (active.get() && mesh) mesh.render(cgl.getShader()); + trigger.trigger(); +}; + +function buildMesh() +{ + if (!geom)geom = new CGL.Geometry("crossmesh"); + geom.clear(); + + let ext = size.get() / 2.0; + let thi = thick.get(); + + if (thi < 0.0) + { + thi = 0.0; + } + else if (thi > ext) + { + thi = ext; + } + + if (ext < 0.0) + { + ext = 0.0; + thi = 0.0; + } + + // center verts + let cx = thi; + let cy = thi; + + // o is outer verts from center + let ox = ext; + let oy = ext; + + geom.vertices = [ + // center piece + -cx, -cy, 0, // 0 + -cx, cy, 0, // 1 + cx, cy, 0, // 2 + cx, -cy, 0, // 3 + + // left piece + -ox, -cy, 0, // 4 + -ox, cy, 0, // 5 + -cx, cy, 0, // 6 + -cx, -cy, 0, // 7 + + // right piece + cx, -cy, 0, // 8 + cx, cy, 0, // 9 + ox, cy, 0, // 10 + ox, -cy, 0, // 11 + + // top piece + -cx, cy, 0, // 12 + -cx, oy, 0, // 13 + cx, oy, 0, // 14 + cx, cy, 0, // 15 + + // bottom piece + -cx, -oy, 0, // 12 + -cx, -cy, 0, // 13 + cx, -cy, 0, // 14 + cx, -oy, 0 // 15 + ]; + + let texCoords = []; + texCoords.length = (geom.vertices.length / 3.0) * 2.0; + + for (let i = 0; i < geom.vertices.length; i += 3) + { + let vx = (geom.vertices[i] / (ox) + 1) / 2; + let vy = (geom.vertices[i + 1] / (oy) + 1) / 2; + let index = (i / 3.0) * 2.0; + + texCoords[index] = vx; + texCoords[index + 1] = vy; + } + + geom.setTexCoords(texCoords); + geom.tangents = geom.vertices.map(function (v, i) { return i % 3 == 0 ? 1 : 0; }); + geom.biTangents = geom.vertices.map(function (v, i) { return i % 3 == 1 ? 1 : 0; }); + geom.vertexNormals = geom.vertices.map(function (v, i) { return i % 3 == 2 ? 1 : 0; }); + + geom.vertexNormals = [ + // center piece + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + + // left + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + // right + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + // top + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + // bottom + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0 + ]; + + if (target.get() == true) + { + // draws a crosshair + geom.verticesIndices = [ + // left + 4, 5, 6, 4, 6, 7, + // right + 8, 9, 10, 8, 10, 11, + // top + 12, 13, 14, 12, 14, 15, + // bottom + 16, 17, 18, 16, 18, 19 + ]; + } + else + { + // draws a solid cross + geom.verticesIndices = [ + // center + 0, 1, 2, 0, 2, 3, + // left + 4, 5, 6, 4, 6, 7, + // right + 8, 9, 10, 8, 10, 11, + // top + 12, 13, 14, 12, 14, 15, + // bottom + 16, 17, 18, 16, 18, 19 + ]; + } + + mesh = new CGL.Mesh(cgl, geom); + geomOut.set(null); + geomOut.set(geom); +} + +function buildMeshLater() +{ + if (mesh)mesh.dispose(); + mesh = null; +} + + +}; + +Ops.Gl.Meshes.Cross.prototype = new CABLES.Op(); +CABLES.OPS["eab5773b-dd10-4617-a8a0-e3990b10477a"]={f:Ops.Gl.Meshes.Cross,objName:"Ops.Gl.Meshes.Cross"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Cube_v2 +// +// ************************************************************** + +Ops.Gl.Meshes.Cube_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Render"), + active = op.inValueBool("Render Mesh", true), + width = op.inValue("Width", 1), + len = op.inValue("Length", 1), + height = op.inValue("Height", 1), + center = op.inValueBool("Center", true), + mapping = op.inSwitch("Mapping", ["Side", "Cube +-"], "Side"), + mappingBias = op.inValue("Bias", 0), + inFlipX = op.inValueBool("Flip X", true), + sideTop = op.inValueBool("Top", true), + sideBottom = op.inValueBool("Bottom", true), + sideLeft = op.inValueBool("Left", true), + sideRight = op.inValueBool("Right", true), + sideFront = op.inValueBool("Front", true), + sideBack = op.inValueBool("Back", true), + trigger = op.outTrigger("Next"), + geomOut = op.outObject("geometry", null, "geometry"); + +const cgl = op.patch.cgl; +op.toWorkPortsNeedToBeLinked(render); + +op.setPortGroup("Mapping", [mapping, mappingBias, inFlipX]); +op.setPortGroup("Geometry", [width, height, len, center]); +op.setPortGroup("Sides", [sideTop, sideBottom, sideLeft, sideRight, sideFront, sideBack]); + +let geom = null, + mesh = null, + meshvalid = true, + needsRebuild = true; + +mappingBias.onChange = + inFlipX.onChange = + sideTop.onChange = + sideBottom.onChange = + sideLeft.onChange = + sideRight.onChange = + sideFront.onChange = + sideBack.onChange = + mapping.onChange = + width.onChange = + height.onChange = + len.onChange = + center.onChange = buildMeshLater; + +function buildMeshLater() +{ + needsRebuild = true; +} + +render.onLinkChanged = function () +{ + if (!render.isLinked()) + { + geomOut.set(null); + return; + } + buildMesh(); +}; + +render.onTriggered = function () +{ + if (needsRebuild)buildMesh(); + if (active.get() && mesh && meshvalid) mesh.render(cgl.getShader()); + trigger.trigger(); +}; + +op.preRender = function () +{ + buildMesh(); + mesh.render(cgl.getShader()); +}; + +function buildMesh() +{ + if (!geom)geom = new CGL.Geometry("cubemesh"); + geom.clear(); + + let x = width.get(); + let nx = -1 * width.get(); + let y = height.get(); + let ny = -1 * height.get(); + let z = len.get(); + let nz = -1 * len.get(); + + if (!center.get()) + { + nx = 0; + ny = 0; + nz = 0; + } + else + { + x *= 0.5; + nx *= 0.5; + y *= 0.5; + ny *= 0.5; + z *= 0.5; + nz *= 0.5; + } + + if (mapping.get() == "Side") sideMappedCube(geom, x, y, z, nx, ny, nz); + else cubeMappedCube(geom, x, y, z, nx, ny, nz); + + geom.verticesIndices = []; + if (sideTop.get()) geom.verticesIndices.push(8, 9, 10, 8, 10, 11); // Top face + if (sideBottom.get()) geom.verticesIndices.push(12, 13, 14, 12, 14, 15); // Bottom face + if (sideLeft.get()) geom.verticesIndices.push(20, 21, 22, 20, 22, 23); // Left face + if (sideRight.get()) geom.verticesIndices.push(16, 17, 18, 16, 18, 19); // Right face + if (sideBack.get()) geom.verticesIndices.push(4, 5, 6, 4, 6, 7); // Back face + if (sideFront.get()) geom.verticesIndices.push(0, 1, 2, 0, 2, 3); // Front face + + if (geom.verticesIndices.length === 0) meshvalid = false; + else meshvalid = true; + + if (mesh)mesh.dispose(); + mesh = new CGL.Mesh(cgl, geom); + geomOut.set(null); + geomOut.set(geom); + + needsRebuild = false; +} + +op.onDelete = function () +{ + if (mesh)mesh.dispose(); +}; + +function sideMappedCube(geom, x, y, z, nx, ny, nz) +{ + geom.vertices = [ + // Front face + nx, ny, z, + x, ny, z, + x, y, z, + nx, y, z, + // Back face + nx, ny, nz, + nx, y, nz, + x, y, nz, + x, ny, nz, + // Top face + nx, y, nz, + nx, y, z, + x, y, z, + x, y, nz, + // Bottom face + nx, ny, nz, + x, ny, nz, + x, ny, z, + nx, ny, z, + // Right face + x, ny, nz, + x, y, nz, + x, y, z, + x, ny, z, + // zeft face + nx, ny, nz, + nx, ny, z, + nx, y, z, + nx, y, nz + ]; + + const bias = mappingBias.get(); + + let fone = 1.0; + let fzero = 0.0; + if (inFlipX.get()) + { + fone = 0.0; + fzero = 1.0; + } + + geom.setTexCoords([ + // Front face + fzero + bias, 1 - bias, + fone - bias, 1 - bias, + fone - bias, 0 + bias, + fzero + bias, 0 + bias, + // Back face + fone - bias, 1 - bias, + fone - bias, 0 + bias, + fzero + bias, 0 + bias, + fzero + bias, 1 - bias, + // Top face + fzero + bias, 0 + bias, + fzero + bias, 1 - bias, + fone - bias, 1 - bias, + fone - bias, 0 + bias, + // Bottom face + fone - bias, 0 + bias, + fzero + bias, 0 + bias, + fzero + bias, 1 - bias, + fone - bias, 1 - bias, + // Right face + fone - bias, 1 - bias, + fone - bias, 0 + bias, + fzero + bias, 0 + bias, + fzero + bias, 1 - bias, + // Left face + fzero + bias, 1 - bias, + fone - bias, 1 - bias, + fone - bias, 0 + bias, + fzero + bias, 0 + bias, + ]); + + geom.vertexNormals = new Float32Array([ + // Front face + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + + // Back face + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + + // Top face + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + + // Bottom face + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + + // Right face + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + + // Left face + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0 + ]); + geom.tangents = new Float32Array([ + + // front face + -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, + // back face + 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, + // top face + 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, + // bottom face + -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, + // right face + 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, + // left face + 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1 + ]); + geom.biTangents = new Float32Array([ + // front face + 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, + // back face + 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, + // top face + 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, + // bottom face + 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, + // right face + 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, + // left face + 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 + ]); +} + +function cubeMappedCube(geom, x, y, z, nx, ny, nz) +{ + geom.vertices = [ + // Front face + nx, ny, z, + x, ny, z, + x, y, z, + nx, y, z, + // Back face + nx, ny, nz, + nx, y, nz, + x, y, nz, + x, ny, nz, + // Top face + nx, y, nz, + nx, y, z, + x, y, z, + x, y, nz, + // Bottom face + nx, ny, nz, + x, ny, nz, + x, ny, z, + nx, ny, z, + // Right face + x, ny, nz, + x, y, nz, + x, y, z, + x, ny, z, + // zeft face + nx, ny, nz, + nx, ny, z, + nx, y, z, + nx, y, nz + ]; + + const sx = 0.25; + const sy = 1 / 3; + const bias = mappingBias.get(); + + let flipx = 0.0; + if (inFlipX.get()) flipx = 1.0; + + const tc = []; + tc.push( + // Front face Z+ + flipx + sx + bias, sy * 2 - bias, + flipx + sx * 2 - bias, sy * 2 - bias, + flipx + sx * 2 - bias, sy + bias, + flipx + sx + bias, sy + bias, + // Back face Z- + flipx + sx * 4 - bias, sy * 2 - bias, + flipx + sx * 4 - bias, sy + bias, + flipx + sx * 3 + bias, sy + bias, + flipx + sx * 3 + bias, sy * 2 - bias); + + if (inFlipX.get()) + tc.push( + // Top face + sx + bias, 0 - bias, + sx * 2 - bias, 0 - bias, + sx * 2 - bias, sy * 1 + bias, + sx + bias, sy * 1 + bias, + // Bottom face + sx + bias, sy * 3 + bias, + sx + bias, sy * 2 - bias, + sx * 2 - bias, sy * 2 - bias, + sx * 2 - bias, sy * 3 + bias + ); + + else + tc.push( + // Top face + sx + bias, 0 + bias, + sx + bias, sy * 1 - bias, + sx * 2 - bias, sy * 1 - bias, + sx * 2 - bias, 0 + bias, + // Bottom face + sx + bias, sy * 3 - bias, + sx * 2 - bias, sy * 3 - bias, + sx * 2 - bias, sy * 2 + bias, + sx + bias, sy * 2 + bias); + + tc.push( + // Right face + flipx + sx * 3 - bias, 1.0 - sy - bias, + flipx + sx * 3 - bias, 1.0 - sy * 2 + bias, + flipx + sx * 2 + bias, 1.0 - sy * 2 + bias, + flipx + sx * 2 + bias, 1.0 - sy - bias, + // Left face + flipx + sx * 0 + bias, 1.0 - sy - bias, + flipx + sx * 1 - bias, 1.0 - sy - bias, + flipx + sx * 1 - bias, 1.0 - sy * 2 + bias, + flipx + sx * 0 + bias, 1.0 - sy * 2 + bias); + + geom.setTexCoords(tc); + + geom.vertexNormals = [ + // Front face + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + + // Back face + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + 0.0, 0.0, -1.0, + + // Top face + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + + // Bottom face + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + + // Right face + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + + // Left face + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + -1.0, 0.0, 0.0 + ]; + geom.tangents = new Float32Array([ + // front face + -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, + // back face + 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, + // top face + 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, + // bottom face + -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, + // right face + 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, + // left face + 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1 + ]); + geom.biTangents = new Float32Array([ + // front face + 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, + // back face + 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, + // top face + 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, + // bottom face + 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, + // right face + 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, + // left face + 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 + ]); +} + + +}; + +Ops.Gl.Meshes.Cube_v2.prototype = new CABLES.Op(); +CABLES.OPS["37b92ba4-cea5-42ae-bf28-a513ca28549c"]={f:Ops.Gl.Meshes.Cube_v2,objName:"Ops.Gl.Meshes.Cube_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Cylinder_v2 +// +// ************************************************************** + +Ops.Gl.Meshes.Cylinder_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inRender = op.inTrigger("render"), + inDraw = op.inValueBool("Draw", true), + inSegments = op.inValueInt("segments", 40), + inStacks = op.inValueInt("stacks", 1), + inLength = op.inValueFloat("length", 1), + inOuterRadius = op.inValueFloat("outer radius", 0.5), + inInnerRadius = op.inValueFloat("inner radius", 0), + inUVMode = op.inValueSelect("UV mode", ["simple", "atlas"], "simple"), + flipSideMapping = op.inValueBool("Flip Mapping", false), + inCaps = op.inValueBool("Caps", true), + inFlat = op.inValueBool("Flat Normals", false), + outTrigger = op.outTrigger("next"), + outGeometry = op.outObject("geometry"), + geom = new CGL.Geometry("cylinder"); + +const + TAU = Math.PI * 2, + cgl = op.patch.cgl; + +let needsRebuild = true; +let mesh = null; + +inUVMode.setUiAttribs({ "hidePort": true }); + + +op.preRender = buildMesh; + +function buildMesh() +{ + const flipTex = flipSideMapping.get(); + + const + segments = Math.max(inSegments.get(), 3) | 0, + innerRadius = Math.max(inInnerRadius.get(), 0), + outerRadius = Math.max(inOuterRadius.get(), innerRadius), + stacks = Math.max(inStacks.get(), inStacks.defaultValue) | 0, + length = inLength.get(), + stackLength = length / stacks, + segmentRadians = TAU / segments, + uvMode = inUVMode.get(); + let + positions = [], + normals = [], + tangents = [], + biTangents = [], + texcoords = [], + indices = [], + x, y, z, i, j, + a, d, o; + if (uvMode == "atlas") o = 0.5; + else o = 1; + + // for each stack + for ( + i = 0, z = -length / 2; + i <= stacks; + i++, z += stackLength + ) + { + // for each segment + for ( + j = a = 0; + j <= segments; + j++, a += segmentRadians + ) + { + positions.push( + (x = Math.sin(a)) * outerRadius, + (y = Math.cos(a)) * outerRadius, + z + ); + d = Math.sqrt(x * x + y * y); + x /= d; + y /= d; + normals.push(x, y, 0); + tangents.push(-y, x, 0); + biTangents.push(0, 0, 1); + + if (flipTex) + texcoords.push( + j / segments, + 1.0 - ((z / length + 0.5) * o) + ); + + else + texcoords.push( + (z / length + 0.5) * o, + j / segments + ); + } + } + + // create indices + for (j = 0; j < stacks; j++) + { + for ( + i = 0, d = j * (segments + 1); + i < segments; + i++, d++ + ) + { + a = d + 1; + indices.push( + d + (segments + 1), a, d, + d + (segments + 1), a + (segments + 1), a + ); + } + } + + // create inner shell + if (innerRadius) + { + d = positions.length; + for (i = j = 0; i < d; i += 3, j += 2) + { + positions.push( + (positions[i] / outerRadius) * innerRadius, + (positions[i + 1] / outerRadius) * innerRadius, + positions[i + 2] + ); + normals.push( + -normals[i], + -normals[i + 1], + 0 + ); + tangents.push( + -tangents[i], + -tangents[i + 1], + 0 + ); + biTangents.push( + 0, + -biTangents[i + 1], + -biTangents[i + 2] + ); + texcoords.push( + texcoords[j], + 1 - texcoords[j + 1] + ); + } + a = d / 3; + d = indices.length; + for (i = 0; i < d; i += 6) + { + indices.push( + a + indices[i], + a + indices[i + 2], + a + indices[i + 1], + a + indices[i + 3], + a + indices[i + 5], + a + indices[i + 4] + ); + } + + if (inCaps.get()) + { + // create caps + a = positions.length; + o = a / 2; + d = segments * 3; + + // cap positions + Array.prototype.push.apply(positions, positions.slice(0, d)); + Array.prototype.push.apply(positions, positions.slice(o, o + d)); + Array.prototype.push.apply(positions, positions.slice(o - d, o)); + Array.prototype.push.apply(positions, positions.slice(a - d, a)); + + // cap normals + d = segments * 2; + for (i = 0; i < d; i++) normals.push(0, 0, -1), tangents.push(-1, 0, 0), biTangents.push(0, -1, 0); + for (i = 0; i < d; i++) normals.push(0, 0, 1), tangents.push(1, 0, 0), biTangents.push(0, 1, 0); + + // cap uvs + if (uvMode == "atlas") + { + d = (innerRadius / outerRadius) * 0.5; + for (i = o = 0; i < segments; i++, o += segmentRadians) + texcoords.push( + Math.sin(o) * 0.25 + 0.75, + Math.cos(o) * 0.25 + 0.25 + ); + for (i = o = 0; i < segments; i++, o += segmentRadians) + texcoords.push( + (Math.sin(o) * d + 0.5) * 0.5 + 0.5, + (Math.cos(o) * d + 0.5) * 0.5 + ); + for (i = o = 0; i < segments; i++, o += segmentRadians) + texcoords.push( + Math.sin(o) * 0.25 + 0.75, + Math.cos(o) * 0.25 + 0.75 + ); + for (i = o = 0; i < segments; i++, o += segmentRadians) + texcoords.push( + (Math.sin(o) * d + 0.5) * 0.5 + 0.5, + (Math.cos(o) * d + 0.5) * 0.5 + 0.5 + ); + } + else + { + for (i = 0; i < d; i++) texcoords.push(0, 0); + for (i = 0; i < d; i++) texcoords.push(1, 1); + } + + // cap indices + for ( + i = 0, o = a / 3 + x; + i < segments - 1; + i++, o++ + ) + { + indices.push( + o + 1, o + segments, o, + o + segments + 1, o + segments, o + 1 + ); + } + indices.push( + o + segments, a / 3 + x, a / 3 + segments + x, + o + segments, o, a / 3 + x + ); + x += segments * 2; + for ( + i = 0, o = a / 3 + x; + i < segments - 1; + i++, o++ + ) + { + indices.push( + o, o + segments, o + 1, + o + 1, o + segments, o + segments + 1 + ); + } + indices.push( + a / 3 + segments + x, a / 3 + x, o + segments, + a / 3 + x, o, o + segments + ); + } + } + else + { + a = positions.length; + d = a / 3; + + positions.push(0, 0, -length / 2); + Array.prototype.push.apply(positions, positions.slice(0, segments * 3)); + for (i = 0; i <= segments; i++) normals.push(0, 0, -1), tangents.push(-1, 0, 0), biTangents.push(0, -1, 0); + + if (inCaps.get()) + { + positions.push(0, 0, length / 2); + Array.prototype.push.apply(positions, positions.slice(a - segments * 3, a)); + for (i = 0; i <= segments; i++) normals.push(0, 0, 1), tangents.push(1, 0, 0), biTangents.push(0, 1, 0); + if (uvMode == "atlas") + { + texcoords.push(0.75, 0.25); + for (i = a = 0; i < segments; i++, a += segmentRadians) + texcoords.push(Math.sin(a) * 0.25 + 0.75, Math.cos(a) * 0.25 + 0.25); + texcoords.push(0.75, 0.75); + for (i = a = 0; i < segments; i++, a += segmentRadians) + texcoords.push(Math.sin(a) * 0.25 + 0.75, Math.cos(a) * 0.25 + 0.75); + } + else + { + for (i = 0; i <= segments; i++) texcoords.push(0, 0); + for (i = 0; i <= segments; i++) texcoords.push(1, 1); + } + indices.push(d + 1, d, d + segments); + for (i = 1; i < segments; i++) + indices.push(d, d + i, d + i + 1); + d += segments + 1; + indices.push(d, d + 1, d + segments); + for (i = 1; i < segments; i++) + indices.push(d, d + i + 1, d + i); + d += segments + 1; + } + } + + // set geometry + geom.clear(); + geom.vertices = positions; + geom.texCoords = texcoords; + geom.vertexNormals = normals; + geom.tangents = tangents; + geom.biTangents = biTangents; + geom.verticesIndices = indices; + + if (inFlat.get()) geom.unIndex(); + + outGeometry.set(null); + outGeometry.set(geom); + + if (!mesh) mesh = new CGL.Mesh(cgl, geom); + else mesh.setGeom(geom); + + needsRebuild = false; +} + +// set event handlers +inRender.onTriggered = function () +{ + if (needsRebuild) buildMesh(); + if (inDraw.get()) mesh.render(cgl.getShader()); + outTrigger.trigger(); +}; + +inSegments.onChange = +inOuterRadius.onChange = +inInnerRadius.onChange = +inCaps.onChange = +inLength.onChange = +flipSideMapping.onChange = +inStacks.onChange = +inFlat.onChange = +inUVMode.onChange = function () +{ + // only calculate once, even after multiple settings could were changed + needsRebuild = true; +}; + +// set lifecycle handlers +op.onDelete = function () { if (mesh)mesh.dispose(); }; + + +}; + +Ops.Gl.Meshes.Cylinder_v2.prototype = new CABLES.Op(); +CABLES.OPS["2899ad67-1e64-4692-af2a-c3b9078f1b5f"]={f:Ops.Gl.Meshes.Cylinder_v2,objName:"Ops.Gl.Meshes.Cylinder_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.FloorGrid +// +// ************************************************************** + +Ops.Gl.Meshes.FloorGrid = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"grid_frag":"IN vec4 posColor;\nIN vec3 posFrag;\n\nvoid main()\n{\n outColor=posColor;\n outColor.a*=(1.0-(length(posFrag)/30.0));\n}","grid_vert":"IN vec3 vPosition;\nIN vec3 attrVertNormal;\nIN vec2 attrTexCoord;\n\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\n\nOUT vec4 posColor;\nOUT vec3 posFrag;\n\nvoid main()\n{\n vec4 pos = vec4( vPosition, 1. );\n mat4 mMatrix=modelMatrix;\n\n mat4 mvMatrix=viewMatrix*mMatrix;\n posFrag=vPosition;\n posColor=vec4(0.6,0.6,0.6,0.4);\n\n if(pos.x==0.0) posColor=vec4(0.3,0.3,1.0,1.0);\n else if(pos.y==0.0 && pos.z==0.0) posColor=vec4(1.0,0.3,0.3,1.0);\n else if(mod(pos.z,10.0)==0.0 && mod(pos.x,10.0)==0.0 ) posColor.a=1.0;\n\n if(pos.y>0.0 && pos.x==0.0) posColor=vec4(0.3,1.0,0.3,1.0);\n\n gl_Position = projMatrix * mvMatrix * pos;\n}\n",}; +const + render = op.inTrigger("Render"), + inActive = op.inBool("Active", true), + next = op.outTrigger("Next"); + +const num = 100; + +const cgl = op.patch.cgl; +let mesh = null; + +const shader = new CGL.Shader(cgl, "gridMaterial"); +shader.setSource(attachments.grid_vert, attachments.grid_frag); + +function init() +{ + let geomVertical = new CGL.Geometry(op.name); + + const space = 1.0; + let l = space * num / 2; + + let tc = []; + + for (var i = -num / 2; i < num / 2 + 1; i++) + { + geomVertical.vertices.push(-l); + geomVertical.vertices.push(0); + geomVertical.vertices.push(i * space); + + geomVertical.vertices.push(l); + geomVertical.vertices.push(0); + geomVertical.vertices.push(i * space); + + geomVertical.vertices.push(i * space); + geomVertical.vertices.push(0); + geomVertical.vertices.push(-l); + + geomVertical.vertices.push(i * space); + geomVertical.vertices.push(0); + geomVertical.vertices.push(l); + + if (i == 0) + { + tc.push(0, 1); + tc.push(0, 1); + tc.push(0, 0.5); + tc.push(0, 0.5); + } + else + { + tc.push(0, 0); + tc.push(0, 0); + tc.push(0, 0); + tc.push(0, 0); + } + } + + geomVertical.vertices.push(0); + geomVertical.vertices.push(0.001); + geomVertical.vertices.push(0); + + geomVertical.vertices.push(0); + geomVertical.vertices.push(10); + geomVertical.vertices.push(0); + + tc.push(0, 0, 0, 0); + + for (var i = 0; i <= 10; i++) + { + geomVertical.vertices.push(-0.25); + geomVertical.vertices.push(i); + geomVertical.vertices.push(0); + + geomVertical.vertices.push(0.25); + geomVertical.vertices.push(i); + geomVertical.vertices.push(0); + + tc.push(0, 0, 0, 0); + } + + geomVertical.setTexCoords(tc); + geomVertical.calculateNormals(); + + if (!mesh) mesh = new CGL.Mesh(cgl, geomVertical); + else mesh.setGeom(geomVertical); +} + +render.onTriggered = function () +{ + if (!mesh)init(); + + if (cgl.frameStore.shadowPass) return next.trigger(); + + cgl.pushShader(shader); + if (!shader) return; + + let oldPrim = shader.glPrimitive; + + shader.glPrimitive = cgl.gl.LINES; + + if (inActive.get()) mesh.render(shader); + cgl.popShader(); + + shader.glPrimitive = oldPrim; + + next.trigger(); +}; + + +}; + +Ops.Gl.Meshes.FloorGrid.prototype = new CABLES.Op(); +CABLES.OPS["645b3877-4fdd-42e5-a369-d9506a65e2f0"]={f:Ops.Gl.Meshes.FloorGrid,objName:"Ops.Gl.Meshes.FloorGrid"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.FreeFormPlane +// +// ************************************************************** + +Ops.Gl.Meshes.FreeFormPlane = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + + x1 = op.inValue("x 1", -1), + y1 = op.inValue("y 1", 1), + z1 = op.inValue("z 1", 0), + + x2 = op.inValue("x 2", 1), + y2 = op.inValue("y 2", 1), + z2 = op.inValue("z 2", 0), + + x3 = op.inValue("x 3", -1), + y3 = op.inValue("y 3", -1), + z3 = op.inValue("z 3", 0), + + x4 = op.inValue("x 4", 1), + y4 = op.inValue("y 4", -1), + z4 = op.inValue("z 4", 0), + + tcx1 = op.inValue("tc x 1", 0), + tcy1 = op.inValue("tc y 1", 1), + + tcx2 = op.inValue("tc x 2", 1), + tcy2 = op.inValue("tc y 2", 1), + + tcx3 = op.inValue("tc x 3", 0), + tcy3 = op.inValue("tc y 3", 0), + + tcx4 = op.inValue("tc x 4", 1), + tcy4 = op.inValue("tc y 4", 0), + trigger = op.outTrigger("trigger"); + +let geom = new CGL.Geometry(op.name); +let mesh = null; +let cgl = op.patch.cgl; + +let arrverts = []; +arrverts.length = 12; +let verts = new Float32Array(arrverts); +let indices = [2, 1, 0, 1, 2, 3]; +let tc = new Float32Array([0, 0, 0, 0, 0, 0, 0, 0]); + +let geomOut = op.addOutPort(new CABLES.Port(op, "geometry", CABLES.OP_PORT_TYPE_OBJECT)); +geomOut.ignoreValueSerialize = true; + +tcx1.onChange = + tcy1.onChange = + tcx2.onChange = + tcy2.onChange = + tcx3.onChange = + tcy3.onChange = + tcx4.onChange = + tcy4.onChange = + x1.onChange = + x2.onChange = + x3.onChange = + x4.onChange = + y1.onChange = + y2.onChange = + y3.onChange = + y4.onChange = + z1.onChange = + z2.onChange = + z3.onChange = + z4.onChange = rebuild; + +rebuild(); + +render.onTriggered = function () +{ + mesh.render(cgl.getShader()); + + if (op.isCurrentUiOp()) + { + gui.setTransformGizmo({ "posX": x1, "posY": y1, "posZ": z1 }, 0); + gui.setTransformGizmo({ "posX": x2, "posY": y2, "posZ": z2 }, 1); + gui.setTransformGizmo({ "posX": x3, "posY": y3, "posZ": z3 }, 2); + gui.setTransformGizmo({ "posX": x4, "posY": y4, "posZ": z4 }, 3); + } + + trigger.trigger(); +}; + +function rebuild() +{ + verts[0] = x1.get(); + verts[1] = y1.get(); + verts[2] = z1.get(); + + verts[3] = x2.get(); + verts[4] = y2.get(); + verts[5] = z2.get(); + + verts[6] = x3.get(); + verts[7] = y3.get(); + verts[8] = z3.get(); + + verts[9] = x4.get(); + verts[10] = y4.get(); + verts[11] = z4.get(); + + // var tc=[0,0, 1,0, 0,1, 1,1]; + + tc[0] = tcx1.get(); + tc[1] = tcy1.get(); + + tc[2] = tcx2.get(); + tc[3] = tcy2.get(); + + tc[4] = tcx3.get(); + tc[5] = tcy3.get(); + + tc[6] = tcx4.get(); + tc[7] = tcy4.get(); + + geom.vertices = verts; + geom.texCoords = tc; + geom.verticesIndices = indices; + geom.calcNormals(true); + geom.calcTangentsBitangents(); + + if (!mesh) mesh = new CGL.Mesh(cgl, geom); + else mesh.setGeom(geom); + + geomOut.set(null); + geomOut.set(geom); +} + + +}; + +Ops.Gl.Meshes.FreeFormPlane.prototype = new CABLES.Op(); +CABLES.OPS["7f03c044-ae95-4273-8d90-0e1c91ecffc7"]={f:Ops.Gl.Meshes.FreeFormPlane,objName:"Ops.Gl.Meshes.FreeFormPlane"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.FullscreenRectangle +// +// ************************************************************** + +Ops.Gl.Meshes.FullscreenRectangle = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"shader_frag":"UNI sampler2D tex;\nIN vec2 texCoord;\n\nvoid main()\n{\n outColor= texture(tex,texCoord);\n}\n\n","shader_vert":"{{MODULES_HEAD}}\n\nIN vec3 vPosition;\nUNI mat4 projMatrix;\nUNI mat4 mvMatrix;\n\nOUT vec2 texCoord;\nIN vec2 attrTexCoord;\n\nvoid main()\n{\n vec4 pos=vec4(vPosition, 1.0);\n\n texCoord=vec2(attrTexCoord.x,(1.0-attrTexCoord.y));\n\n gl_Position = projMatrix * mvMatrix * pos;\n}\n",}; +const + render = op.inTrigger("render"), + inScale = op.inSwitch("Scale", ["Stretch", "Fit"], "Fit"), + flipY = op.inValueBool("Flip Y"), + flipX = op.inValueBool("Flip X"), + inTexture = op.inTexture("Texture"), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +let mesh = null; +let geom = new CGL.Geometry("fullscreen rectangle"); +let x = 0, y = 0, z = 0, w = 0, h = 0; + +flipX.onChange = rebuildFlip; +flipY.onChange = rebuildFlip; +render.onTriggered = doRender; +inTexture.onLinkChanged = updateUi; +op.toWorkPortsNeedToBeLinked(render); + +const shader = new CGL.Shader(cgl, "fullscreenrectangle"); +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); + +shader.setSource(attachments.shader_vert, attachments.shader_frag); +shader.fullscreenRectUniform = new CGL.Uniform(shader, "t", "tex", 0); +shader.aspectUni = new CGL.Uniform(shader, "f", "aspectTex", 0); + +let useShader = false; +let updateShaderLater = true; +let fitImageAspect = false; +let oldVp = []; + +updateUi(); + +inTexture.onChange = function () +{ + updateShaderLater = true; +}; + +function updateUi() +{ + if (!CABLES.UI) return; + flipY.setUiAttribs({ "greyout": !inTexture.isLinked() }); + flipX.setUiAttribs({ "greyout": !inTexture.isLinked() }); + inScale.setUiAttribs({ "greyout": !inTexture.isLinked() }); +} + +function updateShader() +{ + let tex = inTexture.get(); + if (tex) useShader = true; + else useShader = false; +} + +op.preRender = function () +{ + updateShader(); + shader.bind(); + if (mesh)mesh.render(shader); + doRender(); +}; + +inScale.onChange = () => +{ + fitImageAspect = inScale.get() == "Fit"; +}; + +function doRender() +{ + if (cgl.getViewPort()[2] != w || cgl.getViewPort()[3] != h || !mesh) rebuild(); + + if (updateShaderLater) updateShader(); + + cgl.pushPMatrix(); + mat4.identity(cgl.pMatrix); + mat4.ortho(cgl.pMatrix, 0, w, h, 0, -10.0, 1000); + + cgl.pushModelMatrix(); + mat4.identity(cgl.mMatrix); + + cgl.pushViewMatrix(); + mat4.identity(cgl.vMatrix); + + if (fitImageAspect && inTexture.get()) + { + const rat = inTexture.get().width / inTexture.get().height; + + let _h = h; + let _w = h * rat; + + if (_w > w) + { + _h = w * 1 / rat; + _w = w; + } + + oldVp[0] = cgl.getViewPort()[0]; + oldVp[1] = cgl.getViewPort()[1]; + oldVp[2] = cgl.getViewPort()[2]; + oldVp[3] = cgl.getViewPort()[3]; + + cgl.setViewPort((w - _w) / 2, (h - _h) / 2, _w, _h); + // cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); + } + + if (useShader) + { + if (inTexture.get()) + cgl.setTexture(0, inTexture.get().tex); + + mesh.render(shader); + } + else + { + mesh.render(cgl.getShader()); + } + + cgl.gl.clear(cgl.gl.DEPTH_BUFFER_BIT); + + cgl.popPMatrix(); + cgl.popModelMatrix(); + cgl.popViewMatrix(); + + if (fitImageAspect && inTexture.get()) + cgl.setViewPort(oldVp[0], oldVp[1], oldVp[2], oldVp[3]); + + trigger.trigger(); +} + +function rebuildFlip() +{ + mesh = null; +} + +function rebuild() +{ + const currentViewPort = cgl.getViewPort(); + + if (currentViewPort[2] == w && currentViewPort[3] == h && mesh) return; + + let xx = 0, xy = 0; + + w = currentViewPort[2]; + h = currentViewPort[3]; + + geom.vertices = new Float32Array([ + xx + w, xy + h, 0.0, + xx, xy + h, 0.0, + xx + w, xy, 0.0, + xx, xy, 0.0 + ]); + + let tc = null; + + if (flipY.get()) + tc = new Float32Array([ + 1.0, 0.0, + 0.0, 0.0, + 1.0, 1.0, + 0.0, 1.0 + ]); + else + tc = new Float32Array([ + 1.0, 1.0, + 0.0, 1.0, + 1.0, 0.0, + 0.0, 0.0 + ]); + + if (flipX.get()) + { + tc[0] = 0.0; + tc[2] = 1.0; + tc[4] = 0.0; + tc[6] = 1.0; + } + + geom.setTexCoords(tc); + + geom.verticesIndices = new Uint16Array([ + 2, 1, 0, + 3, 1, 2 + ]); + + geom.vertexNormals = new Float32Array([ + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + ]); + geom.tangents = new Float32Array([ + -1, 0, 0, + -1, 0, 0, + -1, 0, 0, + -1, 0, 0]); + geom.biTangents == new Float32Array([ + 0, -1, 0, + 0, -1, 0, + 0, -1, 0, + 0, -1, 0]); + + if (!mesh) mesh = new CGL.Mesh(cgl, geom); + else mesh.setGeom(geom); +} + + +}; + +Ops.Gl.Meshes.FullscreenRectangle.prototype = new CABLES.Op(); +CABLES.OPS["255bd15b-cc91-4a12-9b4e-53c710cbb282"]={f:Ops.Gl.Meshes.FullscreenRectangle,objName:"Ops.Gl.Meshes.FullscreenRectangle"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.GeometryToTexture_v2 +// +// ************************************************************** + +Ops.Gl.Meshes.GeometryToTexture_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"fragpos_frag":"col=vec4(MOD_pos.xyz,1.0);\n","vertpos_vert":"\n#ifdef MOD_ATTRIB_POS\nMOD_pos=pos.xyz;\n#endif\n#ifdef MOD_ATTRIB_NORMAL\nMOD_pos=norm.xyz;\n#endif\n#ifdef MOD_ATTRIB_TC\nMOD_pos=vec3(attrTexCoord,1.0);\n#endif\n\nfloat tx=mod(attrVertIndex,MOD_texSize)+1.0/MOD_texSize;\nfloat ty=floor(attrVertIndex/MOD_texSize);\n\ngl_PointSize=1.0;\n\npos=vec4(tx,ty+1.0,0.0,1.0);\n",}; +const + exec = op.inTrigger("Render"), + inGeom = op.inObject("Geometry", null, "geometry"), + + inOrder = op.inDropDown("Order", ["Sequential", "Random", "Vertex X", "Vertex Y", "Vertex Z"], "Sequential"), + inAttrib = op.inSwitch("Content", ["Vertex Pos", "Normals", "TexCoords"], "Vertex Pos"), + + inSize = op.inSwitch("Size", ["Auto", "Manual"], "Auto"), + inWidth = op.inValueInt("Tex Width", 256), + tfilter = op.inValueSelect("filter", ["nearest", "linear"], "nearest"), + twrap = op.inValueSelect("wrap", ["clamp to edge", "repeat", "mirrored repeat"], "clamp to edge"), + + next = op.outTrigger("Next"), + outNumVerts = op.outNumber("Total Vertices"), + outTex = op.outTexture("Texture"); + +op.setPortGroup("Texture settings", [tfilter, twrap, inWidth, inSize]); + +const cgl = op.patch.cgl; +const prevViewPort = [0, 0, 0, 0]; +const effect = null; + +let autoSize = true; +let needsUpdate = true; +let needsUpdateSize = true; +let shader = null; +let size = 0; +let fb = null; +let needInitFb = true; +let mesh = null; +let vertNums = new Float32Array(1); +let numVerts = 1; + +tfilter.onChange = + twrap.onChange = initFbLater; + +inWidth.onChange = + inSize.onChange = updateSize; + +inAttrib.onChange = updateAttrib; + +updateUI(); + +const vertModTitle = "vert_" + op.name; +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "priority": 200, + "title": vertModTitle, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": "OUT vec3 MOD_pos;", + "srcBodyVert": attachments.vertpos_vert +}); + +mod.addModule({ + "title": op.name, + "name": "MODULE_COLOR", + "srcHeadFrag": "IN vec3 MOD_pos;", + "srcBodyFrag": attachments.fragpos_frag +}); +mod.addUniformVert("f", "MOD_texSize", 0); +updateAttrib(); + +function shuffleArray(array) +{ + let i = 0; + let j = 0; + let temp = null; + + for (i = array.length - 1; i > 0; i -= 1) + { + j = Math.floor(Math.seededRandom() * (i + 1)); + temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } +} + +inGeom.onChange = function () +{ + needsUpdateSize = true; + needsUpdate = true; +}; + +function updateAttrib() +{ + mod.toggleDefine("MOD_ATTRIB_POS", inAttrib.get() == "Vertex Pos"); + mod.toggleDefine("MOD_ATTRIB_TC", inAttrib.get() == "TexCoords"); + mod.toggleDefine("MOD_ATTRIB_NORMAL", inAttrib.get() == "Normals"); + + needsUpdate = true; +} + +inOrder.onChange = () => +{ + needsUpdate = true; +}; + +function warning() +{ +} + +function updateUI() +{ + inWidth.setUiAttribs({ "greyout": inSize.get() == "Auto" }); +} + +function initFbLater() +{ + needInitFb = true; + needsUpdate = true; + warning(); + updateUI(); +} + +function updateSize() +{ + const oldSize = size; + size = inWidth.get(); + + autoSize = inSize.get() == "Auto"; + + const geo = inGeom.get(); + + if (autoSize && !geo) + { + needsUpdateSize = true; + size = -1; + return; + } + if (autoSize && geo && geo.vertices) + { + size = Math.ceil(Math.sqrt(geo.vertices.length / 3)); + } + + size = Math.ceil(Math.max(1, size)); + + updateUI(); + if (oldSize != size) needsUpdate = true; + needsUpdateSize = false; + op.log("size", size); +} + +function initFb() +{ + if (fb) fb = fb.delete(); + outTex.set(CGL.Texture.getEmptyTexture(cgl)); + if (size < 1) return; + + let filter = CGL.Texture.FILTER_NEAREST; + if (tfilter.get() == "linear") filter = CGL.Texture.FILTER_LINEAR; + + let selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + if (twrap.get() == "repeat") selectedWrap = CGL.Texture.WRAP_REPEAT; + if (twrap.get() == "mirrored repeat") selectedWrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + + if (cgl.glVersion >= 2) + { + fb = new CGL.Framebuffer2(cgl, size, size, + { + "isFloatingPointTexture": true, + "multisampling": false, + "wrap": selectedWrap, + "filter": filter, + "depth": true, + "multisamplingSamples": 0, + "clear": true + }); + } + else + { + fb = new CGL.Framebuffer(cgl, size, size, + { + "isFloatingPointTexture": true, + "filter": filter, + "wrap": selectedWrap + }); + } + needInitFb = false; +} + +exec.onTriggered = function () +{ + updateSize(); + + if (!fb || needInitFb) initFb(); + if (!needsUpdate) return next.trigger(); + if (outTex.get() != CGL.Texture.getEmptyTexture(cgl)) outTex.set(CGL.Texture.getEmptyTexture(cgl)); + + const geo = inGeom.get(); + + if (!geo || !geo.copy || !geo.vertices) return next.trigger(); + + if (size < 1) + { + needsUpdate = true; + return; + } + + if (fb && fb.getWidth() != size) fb.setSize(size, size); + + const g = geo.copy(); + + if (!mesh)mesh = new CGL.Mesh(cgl, new CGL.Geometry("a"), cgl.gl.POINTS); + + g.glPrimitive = cgl.gl.POINTS; + mesh.setGeom(g); + numVerts = g.vertices.length / 3; + + if (vertNums.length != numVerts) vertNums = new Float32Array(numVerts); + + for (let i = 0; i < numVerts; i++) vertNums[i] = i; + + if (inOrder.get() == "Random") shuffleArray(vertNums); + if (inOrder.get() == "Vertex X") + vertNums.sort(function (a, b) { return g.vertices[a * 3 + 0] - g.vertices[b * 3 + 0]; }); + if (inOrder.get() == "Vertex Y") + vertNums.sort(function (a, b) { return g.vertices[a * 3 + 1] - g.vertices[b * 3 + 1]; }); + if (inOrder.get() == "Vertex Z") + vertNums.sort(function (a, b) { return g.vertices[a * 3 + 2] - g.vertices[b * 3 + 2]; }); + + mesh._setVertexNumbers(vertNums); + + outNumVerts.set(numVerts); + + render(); + + needsUpdate = false; + next.trigger(); +}; + +function render() +{ + if (!cgl.getShader()) + { + op.setUiError("not in mainloop", "Needs to be connected to mainloop branch"); + return; + } + else op.setUiError("not in mainloop", null); + + const vp = cgl.getViewPort(); + prevViewPort[0] = vp[0]; + prevViewPort[1] = vp[1]; + prevViewPort[2] = vp[2]; + prevViewPort[3] = vp[3]; + + fb.renderStart(cgl); + + cgl.pushPMatrix(); + mat4.identity(cgl.pMatrix); + + cgl.pushViewMatrix(); + mat4.identity(cgl.vMatrix); + + cgl.pushModelMatrix(); + mat4.identity(cgl.mMatrix); + + cgl.gl.viewport(0, 0, size, size); + + mat4.ortho( + cgl.pMatrix, + 0, size, + 0, size, + -1.00, 100); + + mod.bind(); + + mod.setUniformValue("MOD_texSize", size); + mesh.render(cgl.getShader()); + + mod.unbind(); + + cgl.popPMatrix(); + cgl.popModelMatrix(); + cgl.popViewMatrix(); + fb.renderEnd(cgl); + + outTex.set(fb.getTextureColor()); + + cgl.gl.viewport(prevViewPort[0], prevViewPort[1], prevViewPort[2], prevViewPort[3]); +} + + +}; + +Ops.Gl.Meshes.GeometryToTexture_v2.prototype = new CABLES.Op(); +CABLES.OPS["d3435879-6b19-460b-911c-87ae5a8d00ad"]={f:Ops.Gl.Meshes.GeometryToTexture_v2,objName:"Ops.Gl.Meshes.GeometryToTexture_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Grid +// +// ************************************************************** + +Ops.Gl.Meshes.Grid = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Render"), + inNum = op.inValue("Num", 10), + inSpacing = op.inValue("Spacing", 1), + inCenter = op.inBool("Center", true), + next = op.outTrigger("Next"); + +const cgl = op.patch.cgl; +let mesh = null; + +inCenter.onChange = + inNum.onChange = + inSpacing.onChange = function () + { + if (mesh)mesh.dispose(); + mesh = null; + }; + +function init() +{ + const geomStepsOne = new CGL.Geometry(op.name); + const geomX = new CGL.Geometry(op.name); + + const space = inSpacing.get(); + const num = Math.floor(inNum.get()); + const l = space * num / 2; + + const tc = []; + + let start = -num / 2; + let end = num / 2 + 1; + + for (let i = start; i < end; i++) + { + geomStepsOne.vertices.push(-l); + geomStepsOne.vertices.push(i * space); + geomStepsOne.vertices.push(0); + + geomStepsOne.vertices.push(l); + geomStepsOne.vertices.push(i * space); + geomStepsOne.vertices.push(0); + + geomStepsOne.vertices.push(i * space); + geomStepsOne.vertices.push(-l); + geomStepsOne.vertices.push(0); + + geomStepsOne.vertices.push(i * space); + geomStepsOne.vertices.push(l); + geomStepsOne.vertices.push(0); + + tc.push(0, 0); + tc.push(0, 0); + tc.push(0, 0); + tc.push(0, 0); + } + + if (!inCenter.get()) + { + for (let i = 0; i < geomStepsOne.vertices.length; i += 3) + { + geomStepsOne.vertices[i + 0] += l; + geomStepsOne.vertices[i + 1] += l; + } + } + + geomStepsOne.setTexCoords(tc); + geomStepsOne.calculateNormals(); + + if (!mesh) mesh = new CGL.Mesh(cgl, geomStepsOne); + else mesh.setGeom(geomStepsOne); +} + +render.onTriggered = function () +{ + if (!mesh)init(); + let shader = cgl.getShader(); + if (!shader) return; + + let oldPrim = shader.glPrimitive; + + shader.glPrimitive = cgl.gl.LINES; + + mesh.render(shader); + + shader.glPrimitive = oldPrim; + + next.trigger(); +}; + + +}; + +Ops.Gl.Meshes.Grid.prototype = new CABLES.Op(); +CABLES.OPS["677a7c03-6885-46b4-8a64-e4ea54ee5d7f"]={f:Ops.Gl.Meshes.Grid,objName:"Ops.Gl.Meshes.Grid"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.HeightMap +// +// ************************************************************** + +Ops.Gl.Meshes.HeightMap = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const render = op.inTrigger("render"), + filename = op.inFile("file"), + extrude = op.inValueFloat("extrude", 1), + mWidth = op.inValueFloat("width", 3), + mHeight = op.inValueFloat("height", 3), + nRows = op.inValueInt("rows", 20), + nColumns = op.inValueInt("columns", 20), + sliceTex = op.inValueBool("texCoords slice"), + flat = op.inValueBool("flat"), + trigger = op.outTrigger("trigger"); + +let outGeom = op.outObject("geometry"); +outGeom.ignoreValueSerialize = true; + +let geom = new CGL.Geometry(op.name); +let mesh = null; +let cgl = op.patch.cgl; +let image = new Image(); + +render.onTriggered = function () +{ + if (mesh) mesh.render(cgl.getShader()); + trigger.trigger(); +}; + +extrude.onChange = mHeight.onChange = mWidth.onChange = + nRows.onChange = nColumns.onChange = flat.onChange = rebuildGeom; + +filename.onChange = reload; + +function rebuildGeom() +{ + geom.clear(); + + let verts = []; + let tc = []; + let indices = []; + + let width = image.width; + let height = image.height; + let canvas = document.createElement("canvas"); + let ctx = canvas.getContext("2d"); + canvas.width = width; + canvas.height = height; + ctx.drawImage(image, 0, 0); + + let meshWidth = mWidth.get(); + let meshHeight = mHeight.get(); + + let count = 0; + + let vertStepX = meshWidth / width; + let vertStepY = meshHeight / height; + + let numRows = parseFloat(nRows.get()); + let numColumns = parseFloat(nColumns.get()); + let rowStepX = width / numColumns; + let rowStepY = height / numRows; + let heightMul = extrude.get() * 0.001; + + let stepRow = meshWidth / numRows; + let stepColumn = meshHeight / numColumns; + + let cycleTex = 0; + let oldh = 0; + + for (var r = 0; r <= numRows; r++) + { + for (var c = 0; c <= numColumns; c++) + { + let h = ctx.getImageData(Math.round(c * rowStepX), Math.round(r * rowStepY), 1, 1).data[1] * heightMul; + // verts.push( c*stepColumn - meshWidth/2 ); + // verts.push( r*stepRow - meshHeight/2 ); + verts.push(c * stepColumn); + verts.push(r * stepRow); + verts.push(h); + + if (sliceTex.get()) + { + if (h != oldh) + { + if (c % 2 == 0) tc.push(0.5); + else tc.push(1); + + tc.push(1.0 - r / numRows); + } + else + { + tc.push(1); + tc.push(0); + } + oldh = h; + } + else + { + tc.push(c / numColumns); + tc.push(1.0 - r / numRows); + } + } + } + + for (c = 0; c < numColumns; c++) + { + for (r = 0; r < numRows; r++) + { + let ind = c + (numColumns + 1) * r; + let v1 = ind; + let v2 = ind + 1; + let v3 = ind + numColumns + 1; + let v4 = ind + 1 + numColumns + 1; + + indices.push(v1); + indices.push(v2); + indices.push(v3); + + indices.push(v2); + indices.push(v3); + indices.push(v4); + } + } + + geom.vertices = verts; + geom.texCoords = tc; + geom.verticesIndices = indices; + if (flat.get())geom.unIndex(); + geom.calculateNormals({ "forceZUp": true }); + + if (!mesh) mesh = new CGL.Mesh(cgl, geom); + mesh.setGeom(geom); + outGeom.set(null); + outGeom.set(geom); +} + +function reload() +{ + image.crossOrigin = ""; + let url = op.patch.getFilePath(filename.get()); + + let loadingId = op.patch.loading.start("heightmapImage", url); + + image.onabort = image.onerror = function (e) + { + op.patch.loading.finished(loadingId); + op.log("error loading heightmap image..."); + }; + + image.onload = function (e) + { + rebuildGeom(); + op.patch.loading.finished(loadingId); + }; + image.src = url; +} + + +}; + +Ops.Gl.Meshes.HeightMap.prototype = new CABLES.Op(); +CABLES.OPS["81264799-d92b-4b71-a3f1-ad1da8331e62"]={f:Ops.Gl.Meshes.HeightMap,objName:"Ops.Gl.Meshes.HeightMap"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Helix +// +// ************************************************************** + +Ops.Gl.Meshes.Helix = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + draw = op.inValueBool("Draw", true), + segments = op.inValue("Segments", 40), + freq = op.inValue("Frequency", 1), + radius = op.inValue("Radius", 1), + radiusEnd = op.inValue("Radius End", 1), + height = op.inValue("Height"), + next = op.outTrigger("Next"), + outPoints = op.outArray("Points"); + +let cgl = op.patch.cgl; +let pos = []; +let needsCalc = true; +let mesh = null; + +segments.onChange = + radius.onChange = + height.onChange = + freq.onChange = + radiusEnd.onChange = + draw.onChange = calcLater; + +render.onTriggered = doRender; + +function doRender() +{ + if (needsCalc)calc(); + + if (mesh) + { + let shader = cgl.getShader(); + if (!shader) return; + let oldPrim = shader.glPrimitive; + shader.glPrimitive = cgl.gl.LINE_STRIP; + mesh.render(shader); + shader.glPrimitive = oldPrim; + } + + next.trigger(); +} + +function calcLater() +{ + needsCalc = true; +} + +function calc() +{ + needsCalc = false; + pos.length = 0; + + let i = 0, degInRad = 0; + let segs = Math.floor(segments.get()); + if (segs < 1)segs = 1; + + for (i = 0; i < segs; i++) + { + let perc = (i / segs); + let z = perc * height.get(); + let rad = (perc * radiusEnd.get()) + ((1.0 - perc) * radius.get()); + degInRad = (360 / segs) * i * CGL.DEG2RAD; + pos.push( + Math.sin(degInRad * freq.get()) * rad, + Math.cos(degInRad * freq.get()) * rad, + z); + } + + if (draw.get()) + { + let buff = new Float32Array(pos); + let geom = new CGL.Geometry("helix"); + geom.vertices = buff; + + mesh = new CGL.Mesh(cgl, geom); + } + else mesh = null; + + outPoints.set(null); + outPoints.set(pos); +} + + +}; + +Ops.Gl.Meshes.Helix.prototype = new CABLES.Op(); +CABLES.OPS["f41fabfc-14c0-4472-a00a-6ab1dcdcc4bc"]={f:Ops.Gl.Meshes.Helix,objName:"Ops.Gl.Meshes.Helix"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Icosahedron +// +// ************************************************************** + +Ops.Gl.Meshes.Icosahedron = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// from: http://blog.andreaskahler.com/search/label/3D + +let render = op.inTrigger("render"); +let smooth = op.inValueBool("smooth"); +let trigger = op.outTrigger("trigger"); +let geomOut = op.outObject("geometry"); + +geomOut.ignoreValueSerialize = true; + +smooth.onChange = generate; + +let mesh = null; +let cgl = op.patch.cgl; +smooth.set(false); +generate(); + +render.onTriggered = function () +{ + if (mesh) mesh.render(cgl.getShader()); + trigger.trigger(); +}; + +function generate() +{ + let t = Math.sqrt(5.0) / 2; + let tc = []; + let verts = []; + verts.push(-1, t, 0); + verts.push(1, t, 0); + verts.push(-1, -t, 0); + verts.push(1, -t, 0); + + verts.push(0, -1, t); + verts.push(0, 1, t); + verts.push(0, -1, -t); + verts.push(0, 1, -t); + + verts.push(t, 0, -1); + verts.push(t, 0, 1); + verts.push(-t, 0, -1); + verts.push(-t, 0, 1); + + let geom = new CGL.Geometry(op.name); + + geom.vertices = verts; + geom.verticesIndices = []; + + // 5 faces around point 0 + geom.verticesIndices.push(0, 11, 5); + geom.verticesIndices.push(0, 5, 1); + geom.verticesIndices.push(0, 1, 7); + geom.verticesIndices.push(0, 7, 10); + geom.verticesIndices.push(0, 10, 11); + + // 5 adjacent faces + geom.verticesIndices.push(1, 5, 9); + geom.verticesIndices.push(5, 11, 4); + geom.verticesIndices.push(11, 10, 2); + geom.verticesIndices.push(10, 7, 6); + geom.verticesIndices.push(7, 1, 8); + + // 5 faces around point 3 + geom.verticesIndices.push(3, 9, 4); + geom.verticesIndices.push(3, 4, 2); + geom.verticesIndices.push(3, 2, 6); + geom.verticesIndices.push(3, 6, 8); + geom.verticesIndices.push(3, 8, 9); + + // 5 adjacent faces + geom.verticesIndices.push(4, 9, 5); + geom.verticesIndices.push(2, 4, 11); + geom.verticesIndices.push(6, 2, 10); + geom.verticesIndices.push(8, 6, 7); + geom.verticesIndices.push(9, 8, 1); + + geom.texCoords = tc; + + geom.calcNormals(smooth.get()); + mesh = new CGL.Mesh(cgl, geom); + geomOut.set(geom); +} + + +}; + +Ops.Gl.Meshes.Icosahedron.prototype = new CABLES.Op(); +CABLES.OPS["109cead5-8eda-4726-9e3d-b23afe201abd"]={f:Ops.Gl.Meshes.Icosahedron,objName:"Ops.Gl.Meshes.Icosahedron"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Line +// +// ************************************************************** + +Ops.Gl.Meshes.Line = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Render"), + x1 = op.inValue("X 1"), + y1 = op.inValue("Y 1"), + z1 = op.inValue("Z 1"), + x2 = op.inValue("X 2", 1), + y2 = op.inValue("Y 2", 1), + z2 = op.inValue("Z 2", 1), + next = op.outTrigger("Next"); + +const cgl = op.patch.cgl; + +const geom = new CGL.Geometry("simplespline"); +geom.vertices = [x1.get(), y1.get(), z1.get(), x2.get(), y2.get(), x2.get()]; +const mesh = new CGL.Mesh(cgl, geom, cgl.gl.LINES); + +let changed = true; + +x1.onChange = function () { geom.vertices[0] = x1.get(); changed = true; }; +y1.onChange = function () { geom.vertices[1] = y1.get(); changed = true; }; +z1.onChange = function () { geom.vertices[2] = z1.get(); changed = true; }; + +x2.onChange = function () { geom.vertices[3] = x2.get(); changed = true; }; +y2.onChange = function () { geom.vertices[4] = y2.get(); changed = true; }; +z2.onChange = function () { geom.vertices[5] = z2.get(); changed = true; }; + +render.onTriggered = function () +{ + if (changed) + { + mesh.updateVertices(geom); + changed = false; + } + + let shader = cgl.getShader(); + mesh.render(shader); + next.trigger(); +}; + + +}; + +Ops.Gl.Meshes.Line.prototype = new CABLES.Op(); +CABLES.OPS["c6a0d570-a0ac-4655-b17d-74d0870b0799"]={f:Ops.Gl.Meshes.Line,objName:"Ops.Gl.Meshes.Line"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.LinesArray +// +// ************************************************************** + +Ops.Gl.Meshes.LinesArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + width = op.inValueFloat("width", 10), + height = op.inValueFloat("height", 1), + doLog = op.inValueBool("Logarithmic", false), + pivotX = op.inValueSelect("pivot x", ["center", "left", "right"], "center"), + pivotY = op.inValueSelect("pivot y", ["center", "top", "bottom"], "center"), + nColumns = op.inValueInt("num columns", 10), + nRows = op.inValueInt("num rows", 10), + axis = op.inValueSelect("axis", ["xy", "xz"], "xy"), + trigger = op.outTrigger("trigger"), + outPointArrays = op.outArray("Point Arrays"); + +const cgl = op.patch.cgl; +let meshes = []; + +op.setPortGroup("Size", [width, height]); +op.setPortGroup("Alignment", [pivotX, pivotY]); + +axis.onChange = + pivotX.onChange = + pivotY.onChange = + width.onChange = + height.onChange = + nRows.onChange = + nColumns.onChange = + doLog.onChange = rebuildDelayed; + +rebuild(); + +render.onTriggered = function () +{ + for (let i = 0; i < meshes.length; i++) meshes[i].render(cgl.getShader()); + trigger.trigger(); +}; + +let delayRebuild = 0; +function rebuildDelayed() +{ + clearTimeout(delayRebuild); + delayRebuild = setTimeout(rebuild, 60); +} + +function rebuild() +{ + let x = 0; + let y = 0; + + if (pivotX.get() == "center") x = 0; + if (pivotX.get() == "right") x = -width.get() / 2; + if (pivotX.get() == "left") x = +width.get() / 2; + + if (pivotY.get() == "center") y = 0; + if (pivotY.get() == "top") y = -height.get() / 2; + if (pivotY.get() == "bottom") y = +height.get() / 2; + + let numRows = parseInt(nRows.get(), 10); + let numColumns = parseInt(nColumns.get(), 10); + + let stepColumn = width.get() / numColumns; + let stepRow = height.get() / numRows; + + let c, r; + meshes.length = 0; + + let vx, vy, vz; + let verts = []; + let tc = []; + let indices = []; + let count = 0; + + function addMesh() + { + let geom = new CGL.Geometry(op.name); + geom.vertices = verts; + geom.texCoords = tc; + geom.verticesIndices = indices; + + let mesh = new CGL.Mesh(cgl, geom, cgl.gl.LINES); + mesh.setGeom(geom); + meshes.push(mesh); + + verts.length = 0; + tc.length = 0; + indices.length = 0; + count = 0; + lvx = null; + } + + let min = Math.log(1 / numRows); + let max = Math.log(1); + // op.log(min,max); + + let lines = []; + + for (r = numRows; r >= 0; r--) + { + // op.log(r/numRows); + var lvx = null, lvy = null, lvz = null; + let ltx = null, lty = null; + let log = 0; + let doLoga = doLog.get(); + + let linePoints = []; + lines.push(linePoints); + + + for (c = numColumns; c >= 0; c--) + { + vx = c * stepColumn - width.get() / 2 + x; + if (doLoga) + vy = (Math.log((r / numRows)) / min) * height.get() - height.get() / 2 + y; + else + vy = r * stepRow - height.get() / 2 + y; + + let tx = c / numColumns; + let ty = 1.0 - r / numRows; + if (doLoga) ty = (Math.log((r / numRows)) / min); + + vz = 0.0; + + if (axis.get() == "xz") + { + vz = vy; + vy = 0.0; + } + if (axis.get() == "xy") vz = 0.0; + + if (lvx !== null) + { + verts.push(lvx); + verts.push(lvy); + verts.push(lvz); + + linePoints.push(lvx, lvy, lvz); + + verts.push(vx); + verts.push(vy); + verts.push(vz); + + tc.push(ltx); + tc.push(lty); + + tc.push(tx); + tc.push(ty); + + indices.push(count); + count++; + indices.push(count); + count++; + } + + if (count > 64000) + { + addMesh(); + } + + ltx = tx; + lty = ty; + + lvx = vx; + lvy = vy; + lvz = vz; + } + } + + outPointArrays.set(lines); + + addMesh(); + + // op.log(meshes.length,' meshes'); +} + + +}; + +Ops.Gl.Meshes.LinesArray.prototype = new CABLES.Op(); +CABLES.OPS["a75265c2-957b-4719-9d03-7bbf00ace364"]={f:Ops.Gl.Meshes.LinesArray,objName:"Ops.Gl.Meshes.LinesArray"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.MeshInstancerFromTexture_v2 +// +// ************************************************************** + +Ops.Gl.Meshes.MeshInstancerFromTexture_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"instancer_body_frag":"#ifdef USE_TEX_COLOR\n #ifdef BLEND_MODE_MULTIPLY\n col.rgb *= frag_instColor.rgb;\n col.a *= frag_instColor.a;\n #endif\n\n #ifdef BLEND_MODE_ADD\n col.rgb += frag_instColor.rgb;\n col.a += frag_instColor.a;\n #endif\n\n #ifdef BLEND_MODE_NONE\n col.rgb = frag_instColor.rgb;\n col.a = frag_instColor.a;\n #endif\n#endif\n","instancer_body_vert":"float tx=mod(instanceIndex,(MOD_texSizeX))/MOD_texSizeX+(1.0/MOD_texSizeX*0.5);\nfloat ty=float(int((instanceIndex/(MOD_texSizeX))))/MOD_texSizeY+(1.0/MOD_texSizeY*0.5);\n\nvec3 MOD_texPos=texture(MOD_texTrans,vec2(tx,ty)).rgb*MOD_mulRGB;\nmat4 texInstMat;\nvec3 scale=vec3(1.0);\n\n#ifdef USE_TEX_SCALE\n scale*=texture(MOD_texScale,vec2(tx,ty)).rgb;\n#endif\n\ntexInstMat[0][0]=\ntexInstMat[1][1]=\ntexInstMat[2][2]=\ntexInstMat[3][3]=1.0;\n\n#ifdef USE_TEX_ROT\n vec3 MOD_texRota=texture(MOD_texRot,vec2(tx,ty)).rgb;\n texInstMat*=rotationMatrix(vec3(1.0,0.0,0.0),MOD_texRota.r*PI*2.0);\n texInstMat*=rotationMatrix(vec3(0.0,1.0,0.0),MOD_texRota.g*PI*2.0);\n texInstMat*=rotationMatrix(vec3(0.0,0.0,1.0),MOD_texRota.b*PI*2.0);\n#endif\n\ntexInstMat[3][0]=MOD_texPos.x;\ntexInstMat[3][1]=MOD_texPos.y;\ntexInstMat[3][2]=MOD_texPos.z;\n\nmat4 scalem;\nscalem[0][0]=MOD_scale*scale.x;\nscalem[1][1]=MOD_scale*scale.y;\nscalem[2][2]=MOD_scale*scale.z;\nscalem[3][3]=1.0;\ntexInstMat*=scalem;\n\nmMatrix*=texInstMat;\n\n#ifdef USE_TEX_COLOR\n\n vec4 instColor=texture(MOD_texColor,vec2(tx,ty));\n\n frag_instColor=instColor;\n#endif\n\n#ifdef USE_TEX_TC\n vec4 instTexCoords=texture(MOD_texCoords,vec2(tx,ty));\n\n texCoord=(texCoord*instTexCoords.zw)+instTexCoords.xy;\n#endif\n\n\n\n\n","instancer_head_frag":"IN vec4 frag_instColor;\n","instancer_head_vert":"IN mat4 instMat;\nIN vec4 instColor;\nIN float instanceIndex;\nOUT mat4 instModelMat;\nOUT vec4 frag_instColor;\n\n#define INSTANCING\n#define PI 3.14159265358\n\nmat3 ntorot(vec3 r)\n{\n float cx = cos(radians(r.x));\n float sx = sin(radians(r.x));\n float cy = cos(radians(r.y));\n float sy = sin(radians(r.y));\n float cz = cos(radians(r.z));\n float sz = sin(radians(r.z));\n\n return mat3(cy * cz, \tcx * sz + sx * sy * cz, \tsx * sz - cx * sy * cz,\n \t\t\t-cy * sz,\tcx * cz - sx * sy * sz,\t\tsx * cz + cx * sy * sz,\n \t\t\tsy,\t\t\t-sx * cy,\t\t\t\t\tcx * cy);\n}\n\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n axis = normalize(axis);\n float s = sin(angle);\n float c = cos(angle);\n float oc = 1.0 - c;\n\n return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0,\n oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0,\n oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0,\n 0.0, 0.0, 0.0, 1.0);\n}\n\n// vec4 MOD_rot(vec4 pos, vec3 rot, mat4 modelMatrix)\n// {\n// // pos=pos*rotationX(rot.x)*rotationY(rot.y)*rotationZ(rot.z);\n// pos.xyz*=ntorot( (rot-0.5) * 3.14*2.0 );\n\n// return pos;\n// }\n",}; +const + exe = op.inTrigger("exe"), + geom = op.inObject("Geometry", null, "geometry"), + inNum = op.inInt("Num Instances", 1000), + inTex = op.inTexture("Position Texture", null, "texture"), + inTex2 = op.inTexture("Rotation Texture", null, "texture"), + inTex3 = op.inTexture("Scale Texture", null, "texture"), + inTex4 = op.inTexture("Color Texture", null, "texture"), + inTex5 = op.inTexture("TexCoord Texture", null, "texture"), + inBlendMode = op.inSwitch("Color Texture Blendmode", ["Multiply", "Add", "Normal"], "Multiply"), + inScale = op.inValue("Scale", 1), + inMulR = op.inValue("Multiply Pos X", 1), + inMulG = op.inValue("Multiply Pos Y", 1), + inMulB = op.inValue("Multiply Pos Z", 1), + outTrigger = op.outTrigger("Trigger Out"), + outNum = op.outNumber("Num"); + +op.toWorkPortsNeedToBeLinked(geom); +op.toWorkPortsNeedToBeLinked(exe); + +geom.ignoreValueSerialize = true; + +const cgl = op.patch.cgl; +const m = mat4.create(); +let + // matrixArray = new Float32Array(1), + // instColorArray = new Float32Array(1), + mesh = null, + recalc = true, + num = 0, + arrayChangedTrans = true; + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "name": "MODULE_VERTEX_POSITION", + "title": op.name, + "priority": -2, + "srcHeadVert": attachments.instancer_head_vert, + "srcBodyVert": attachments.instancer_body_vert +}); + +mod.addModule({ + "name": "MODULE_COLOR", + "priority": -2, + "title": op.name, + "srcHeadFrag": attachments.instancer_head_frag, + "srcBodyFrag": attachments.instancer_body_frag, +}); + +mod.addUniformVert("f", "MOD_scale", inScale); +mod.addUniformVert("t", "MOD_texTrans"); +mod.addUniformVert("t", "MOD_texRot"); +mod.addUniformVert("t", "MOD_texScale"); +mod.addUniformVert("t", "MOD_texCoords"); +mod.addUniformVert("t", "MOD_texColor"); +mod.addUniformVert("f", "MOD_texSizeX", 0); +mod.addUniformVert("f", "MOD_texSizeY", 0); +mod.addUniformVert("3f", "MOD_mulRGB", inMulR, inMulG, inMulB); + +inBlendMode.onChange = +inTex.onChange = +inTex3.onChange = +inTex4.onChange = +inTex5.onChange = +inTex2.onChange = updateDefines; + +// inBlendMode.onChange = updateDefines; +// doLimit.onChange = updateLimit; +exe.onTriggered = doRender; +exe.onLinkChanged = function () +{ + if (!exe.isLinked()) removeModule(); +}; + +inNum.onChange = + function () + { + arrayChangedTrans = true; + recalc = true; + }; + +function reset() +{ + arrayChangedTrans = true; + recalc = true; +} + +function updateDefines() +{ + mod.toggleDefine("BLEND_MODE_MULTIPLY", inBlendMode.get() === "Multiply"); + mod.toggleDefine("BLEND_MODE_ADD", inBlendMode.get() === "Add"); + mod.toggleDefine("BLEND_MODE_NONE", inBlendMode.get() === "Normal"); + + mod.toggleDefine("USE_TEX_ROT", inTex2.get()); + mod.toggleDefine("USE_TEX_SCALE", inTex3.get()); + mod.toggleDefine("USE_TEX_COLOR", inTex4.get()); + mod.toggleDefine("USE_TEX_TC", inTex5.get()); +} + +geom.onChange = function () +{ + if (mesh)mesh.dispose(); + + if (!geom.get() || !geom.get().vertices) + { + mesh = null; + return; + } + mesh = new CGL.Mesh(cgl, geom.get()); + reset(); +}; + +function removeModule() +{ + +} + +function setupArray() +{ + if (!mesh) return; + + num = Math.max(0, Math.floor(inNum.get())); + + // if (matrixArray.length != num * 16) matrixArray = new Float32Array(num * 16); + + // for (let i = 0; i < num; i++) + // { + // mat4.identity(m); + // for (let a = 0; a < 16; a++) matrixArray[i * 16 + a] = m[a]; + // } + + mesh.numInstances = num; + // mesh.addAttribute("instMat", matrixArray, 16); + + recalc = false; +} + +function doRender() +{ + if (!mesh) return; + if (recalc) setupArray(); + + if (!inTex.get()) return; + if (inTex.get())mod.pushTexture("MOD_texTrans", inTex.get().tex); + if (inTex2.get())mod.pushTexture("MOD_texRot", inTex2.get().tex); + if (inTex3.get())mod.pushTexture("MOD_texScale", inTex3.get().tex); + if (inTex4.get())mod.pushTexture("MOD_texColor", inTex4.get().tex); + if (inTex5.get())mod.pushTexture("MOD_texCoords", inTex5.get().tex); + + mod.bind(); + mod.setUniformValue("MOD_texSizeX", inTex.get().width); + mod.setUniformValue("MOD_texSizeY", inTex.get().height); + + // mesh.numInstances = num; + + outNum.set(mesh.numInstances); + + if (mesh.numInstances > 0) mesh.render(cgl.getShader()); + + outTrigger.trigger(); + + mod.unbind(); +} + + +}; + +Ops.Gl.Meshes.MeshInstancerFromTexture_v2.prototype = new CABLES.Op(); +CABLES.OPS["10771b66-4b63-4f47-b050-3b9c44cb2780"]={f:Ops.Gl.Meshes.MeshInstancerFromTexture_v2,objName:"Ops.Gl.Meshes.MeshInstancerFromTexture_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.ParametricSurface +// +// ************************************************************** + +Ops.Gl.Meshes.ParametricSurface = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +/* presets for parametric surface */ +const parametricBodies = [ + { + "title": "Rectangle", + "xFunction": "u", + "yFunction": "v", + "zFunction": "0", + "uMin": 0, + "uMax": 2, + "vMin": 0, + "vMax": 1, + "isPiU": false, + "isPiV": false, + "uSegments": 24, + "vSegments": 24, + "scaleX": 1, + "scaleY": 1, + "scaleZ": 1, + "displaceU": -1, + "displaceV": -0.5 + }, + { + "title": "Archimedic Spiral", + "xFunction": "u*cos(u)", + "yFunction": "v", + "zFunction": "u*sin(u)", + + "uMin": 0, + "uMax": 50, + "vMin": 0, + "vMax": 1, + "isPiU": false, + "isPiV": false, + + "uSegments": 300, + "vSegments": 20, + + "scaleX": 0.05, + "scaleY": 0.05, + "scaleZ": 0.05, + + "displaceU": 0, + "displaceV": -3 + }, + { + "title": "Cylinder", + "xFunction": "0.5*cos(u)", + "yFunction": "v", + "zFunction": "0.5*sin(u)", + + "uMin": -1, + "uMax": 1, + "vMin": 0, + "vMax": 1, + "isPiU": true, + "isPiV": false, + + "uSegments": 50, + "vSegments": 50, + + "scaleX": 1, + "scaleY": 1, + "scaleZ": 1, + + "displaceU": 0, + "displaceV": 0 + }, + { + "title": "Pillow", + "zFunction": "cos(u)", + "yFunction": "-1*cos(v)", + "xFunction": "0.8*sin(u)*sin(v)", + + "uMin": 0, + "uMax": 1, + "vMin": -1, + "vMax": 1, + "isPiU": true, + "isPiV": true, + + "uSegments": 50, + "vSegments": 50, + + "scaleX": 0.8, + "scaleY": 0.8, + "scaleZ": 0.8, + + "displaceU": 0, + "displaceV": 0 + }, + { + "title": "Sine Surface", + "zFunction": "sin(u)", + "yFunction": "sin(v)", + "xFunction": "sin(u+v)", + + "uMin": -1, + "uMax": 1, + "vMin": -1, + "vMax": 1, + "isPiU": true, + "isPiV": true, + + "uSegments": 50, + "vSegments": 50, + + "scaleX": 0.8, + "scaleY": 0.8, + "scaleZ": 0.8, + + "displaceU": 0, + "displaceV": 0 + }, + { + "title": "Steinbach Screw", + "xFunction": "v*cos(u)", + "yFunction": "u*sin(v)", + "zFunction": "u*cos(v)", + + + "uMin": -4, + "uMax": 4, + "vMin": 0, + "vMax": 2, + "isPiU": false, + "isPiV": true, + + "uSegments": 50, + "vSegments": 50, + + "scaleX": 0.18, + "scaleY": 0.18, + "scaleZ": 0.18, + + "displaceU": 0, + "displaceV": 0 + }, + + { + "title": "Moebius Band", + "xFunction": "cos(v)*(1 + u*cos(v/2))", + "yFunction": "sin(v)*(1 + u*cos(v/2))", + "zFunction": "u*sin(v/2)", + + + "uMin": -0.3, + "uMax": 0.3, + "vMin": 0, + "vMax": 2, + "isPiU": false, + "isPiV": true, + + "uSegments": 50, + "vSegments": 50, + + "scaleX": 0.6, + "scaleY": 0.6, + "scaleZ": 0.6, + + "displaceU": 0, + "displaceV": 0 + }, + { + "title": "Wavy Sphere", + "xFunction": "u*cos(cos(u))*cos(v)", + "yFunction": "u*cos(cos(u))*sin(v)", + "zFunction": "u*sin(cos(u))", + + "uMin": 0, + "uMax": 45, + "vMin": 0, + "vMax": 2, + "isPiU": false, + "isPiV": true, + + "uSegments": 100, + "vSegments": 100, + + "scaleX": 0.02, + "scaleY": 0.02, + "scaleZ": 0.02, + + "displaceU": 0, + "displaceV": 0 + }, + { + "title": "Spring", + "xFunction": "(2 + 0.5*cos(v))*cos(u)", + "yFunction": "(2 + 0.5*cos(v))*sin(u)", + "zFunction": "0.5*(sin(v) + 2*u/PI)", + + "uMin": 0, + "uMax": 15, + "vMin": 0, + "vMax": 2, + "isPiU": true, + "isPiV": true, + + "uSegments": 100, + "vSegments": 100, + + "scaleX": 0.1, + "scaleY": 0.1, + "scaleZ": 0.1, + + "displaceU": 0, + "displaceV": 0 + }, + + { + "title": "Folium", + "xFunction": "cos(u)*(2*v/PI - tanh(v))", + "yFunction": "cos(u + 2*PI/3)/cosh(v)", + "zFunction": "cos(u - 2*PI/3)/cosh(v)", + + "uMin": -1, + "uMax": 1, + "vMin": -1, + "vMax": 1, + "isPiU": true, + "isPiV": true, + + "uSegments": 50, + "vSegments": 50, + + "scaleX": 1.3, + "scaleY": 1.3, + "scaleZ": 1.3, + + "displaceU": 0, + "displaceV": 0 + }, + { + "title": "Hyperbolic Octahedron", + "xFunction": "pow(cos(u)*cos(v), 3)", + "yFunction": "pow(sin(u)*cos(v), 3)", + "zFunction": "pow(sin(v), 3)", + + "uMin": -1 / 2, + "uMax": 1 / 2, + "vMin": -1, + "vMax": 1, + "isPiU": true, + "isPiV": true, + + "uSegments": 50, + "vSegments": 50, + + "scaleX": 1.3, + "scaleY": 1.3, + "scaleZ": 1.3, + + "displaceU": 0, + "displaceV": 0 + }, + { + "title": "Maeder's Owl", + "xFunction": "v*cos(u)-0.5*v*v*cos(2*u)", + "yFunction": "-1*v*sin(u) - 0.5*v*v*sin(2*u)", + "zFunction": "4*exp(1.5*log(v))*cos(3*u/2)/3", + + "uMin": 0, + "uMax": 4, + "vMin": 0.001, + "vMax": 4, + "isPiU": true, + "isPiV": false, + + "uSegments": 100, + "vSegments": 100, + + "scaleX": 0.071, + "scaleY": 0.071, + "scaleZ": 0.071, + + "displaceU": 0, + "displaceV": 0 + }, + { + "title": "Tranguloid Trefoil", + "xFunction": "2*sin(3*u)/(2+cos(v))", + "yFunction": "2*(sin(u) + 2*sin(2*u))/(2+cos(v+2*PI/3))", + "zFunction": "(cos(u)-2*cos(2*u))*(2+cos(v+2*PI/3))/4", + + "uMin": -1, + "uMax": 1, + "vMin": -1, + "vMax": 1, + "isPiU": true, + "isPiV": true, + + "uSegments": 50, + "vSegments": 50, + + "scaleX": 0.3, + "scaleY": 0.2, + "scaleZ": 0.3, + + "displaceU": 0, + "displaceV": 0 + }, + { + "title": "Apple", + "xFunction": "cos(u)*(5 + 4.8 *cos(v)) + pow(v/PI, 20)", + "yFunction": "-2.3*log(1-v*0.3157) + 6*sin(v) + 2*cos(v) ", + "zFunction": "sin(u)*(5 + 4.8*cos(v)) + 0.25*cos(5*u)", + + "uMin": -1, + "uMax": 1, + "vMin": -1, + "vMax": 1, + "isPiU": true, + "isPiV": true, + + "uSegments": 50, + "vSegments": 50, + + "scaleX": 0.06, + "scaleY": 0.06, + "scaleZ": 0.06, + + "displaceU": 0, + "displaceV": 0 + }, + { + "title": "Kuen's Surface", + "xFunction": "(2*(cos(u) + u*sin(u))*sin(v))/(1+u*u*sin(v)*sin(v))", + "yFunction": "(2*(-u*cos(u) + sin(u))*sin(v))/(1+u*u*sin(v)*sin(v))", + "zFunction": "log(tan(v/2)) + 2*cos(v)/(1+u*u*sin(v)*sin(v))", + + "uMin": -4.3, + "uMax": 4.3, + "vMin": 0.03, + "vMax": 31.11, + "isPiU": false, + "isPiV": false, + + "uSegments": 100, + "vSegments": 100, + + "scaleX": 0.7, + "scaleY": 0.7, + "scaleZ": 0.7, + + "displaceU": 0, + "displaceV": 0 + }, + { + "title": "Henneberg's Surface", + "xFunction": "2*cos(v)*sinh(u)-0.667*cos(3*v)*sinh(3*u)", + "yFunction": "2*sin(v)*sinh(u)+0.667*sin(3*v)*sinh(3*u)", + "zFunction": "2*cos(2*v)*cosh(2*u)", + + "uMin": -1, + "uMax": 1, + "vMin": -0.5, + "vMax": 0.5, + "isPiU": false, + "isPiV": true, + + "uSegments": 100, + "vSegments": 100, + + "scaleX": 0.1, + "scaleY": 0.1, + "scaleZ": 0.1, + + "displaceU": 0, + "displaceV": 0 + }, + { + /* +a : 1.6 +b : 1.6 +c : 1.0 +h : 1.5 +k : -7.0 +w : 0.075 +umin : -50.0 +umax : -1.0 + */ + "title": "Pseudoheliceras subcatenatum", + + "xFunction": "exp(0.075*u)*(1.5 + 1.6 * cos(v))*cos(1.0*u)", + "yFunction": "-1 * exp(0.075*u)*(1.5 + 1.6 * cos(v))*sin(1.0*u)", + "zFunction": "exp(0.075*u)*(-7 + 1.6 * sin(v))", + + "uMin": -50, + "uMax": -1, + "vMin": 0, + "vMax": 2, + "isPiU": false, + "isPiV": true, + + "uSegments": 50, + "vSegments": 50, + + "scaleX": 0.3, + "scaleY": 0.3, + "scaleZ": 0.3, + + "displaceU": 0, + "displaceV": 0 + + }, + { + "title": "Little Cycloid", + "xFunction": "cos(u/2)*cos(u/5)*(10 + cos(v)) + sin(u/5)*sin(v)*cos(v)", + "yFunction": "sin(u/2)*cos(u/5)*(10 + cos(v)) + sin(u/5)*sin(v)*cos(v)", + "zFunction": "-sin(u/5)*(10+cos(v))*sin(v)*cos(v)", + + "uMin": 0, + // 2*b*c + "uMax": 2 * 5 * 2, + "vMin": 0, + "vMax": 4, + "isPiU": true, + "isPiV": true, + + "uSegments": 100, + "vSegments": 100, + + "scaleX": 0.05, + "scaleY": 0.05, + "scaleZ": 0.05, + + "displaceU": 0, + "displaceV": -3 + }, + { + // R=50, r=12.5, p=7 und q=3 + "title": "Torus Knot", + "xFunction": "(50+90*cos(7*u) + 12.5*cos(v)) * cos(8*u)", + "yFunction": "12.5*sin(v) + 90*sin(7*u)", + "zFunction": "(50+90*cos(7*u) + 12.5*cos(v)) * sin(8*u)", + "uMin": 0, + "uMax": 2, + "vMin": 0, + "vMax": 2, + "isPiU": true, + "isPiV": true, + "uSegments": 200, + "vSegments": 200, + "scaleX": 0.005, + "scaleY": 0.005, + "scaleZ": 0.005, + "displaceU": 0, + "displaceV": 0 + }, + { + "title": "Triaxial Tritorus", + "yFunction": "sin(u)*(1 + cos(v))", + "xFunction": "sin(u+2*PI/3)*(1+cos(v+2*PI/3))", + "zFunction": "sin(u+4*PI/3)*(1+cos(v+4*PI/3))", + "uMin": -1, + "uMax": 1, + "vMin": -1, + "vMax": 1, + "isPiU": true, + "isPiV": true, + "uSegments": 100, + "vSegments": 100, + "scaleX": 0.7, + "scaleY": 0.7, + "scaleZ": 0.7, + "displaceU": 0, + "displaceV": 0 + }, + { + "title": "Triaxial Hexatorus", + "xFunction": "sin(u)/(sqrt(2)+cos(v))", + "yFunction": "sin(u+2*PI/3)/(sqrt(2)+cos(v+2*PI/3))", + "zFunction": "cos(u-2*PI/3)/(sqrt(2)+cos(v-2*PI/3))", + "uMin": 0, + "uMax": 2, + "vMin": 0, + "vMax": 2, + "isPiU": true, + "isPiV": true, + "uSegments": 100, + "vSegments": 100, + "scaleX": 0.8, + "scaleY": 0.8, + "scaleZ": 0.8, + "displaceU": 0, + "displaceV": 0 + }, + { + "title": "Hyperbolic Helicoid", + "xFunction": "sinh(v)*cos(4.13*u)/(1+cosh(u)*cosh(v))", + "yFunction": "sinh(v)*sin(4.13*u)/(1+cosh(u)*cosh(v))", + "zFunction": "cosh(v)*sinh(u)/(1+cosh(u)*cosh(v))", + "uMin": -4, + "uMax": 4, + "vMin": -4, + "vMax": 4, + "isPiU": false, + "isPiV": false, + "uSegments": 100, + "vSegments": 100, + "scaleX": 1, + "scaleY": 1, + "scaleZ": 1, + "displaceU": 0, + "displaceV": 0 + }, + + { + "title": "Triple Corkscrew III", + "xFunction": "u*1.3", + "yFunction": "0.5*(0.4*(1 - abs(u)) * cos(v) + cos(0.4)*cos(u*PI/2)*cos(u*10*PI))", + "zFunction": "0.5*(0.4*(1-abs(u))*sin(v) + cos(0.4)*cos(u*PI/2)*sin(u*10*PI))", + "uMin": -1, + "uMax": 1, + "vMin": -1, + "vMax": 1, + "isPiU": false, + "isPiV": true, + "uSegments": 190, + "vSegments": 190, + "scaleX": 1, + "scaleY": 1, + "scaleZ": 1, + "displaceU": 0, + "displaceV": 0 + }, + { + // a = 0.4 + // uMin = -13.2 + // uMax = 13.2 + // vMin = -37.4 + // vMax = 37.4 + + + // r = 1-0.4*0.4 + // w = sqrt(r) + // d = a( pow(w * cosh(a*u), 2) + pow(a*sin(w*v), 2) ) + // x = -u + (2*r*cosh(a*u)*sinh(a*u)/d) + // y = 2*w*cosh(a*u)*(-1*(w*cos(v)*cos(w*v)) - (sin(v) * sin(w*v)))/d + // z = 2*w*cosh(a*u) * (-1* (w*sin(v)*cos(w*v)) + (cos(v)*sin(w*v)))/d + /* + w = sqrt(1-0.4*0.4) + d = 0.4( pow(sqrt(1-0.4*0.4) * cosh(0.4*u), 2) + pow(0.4*sin(sqrt(1-0.4*0.4)*v), 2) ) + x = -u + (2*(1-0.4*0.4)*cosh(0.4*u)*sinh(0.4*u)/(0.4*( pow(sqrt(1-0.4*0.4) * cosh(0.4*u), 2) + pow(0.4*sin(sqrt(1-0.4*0.4)*v), 2) ))) + y = 2*(sqrt(1-0.4*0.4))*cosh(0.4*u)*(-1*((sqrt(1-0.4*0.4))*cos(v)*cos((sqrt(1-0.4*0.4))*v)) - (sin(v) * sin((sqrt(1-0.4*0.4))*v)))/(0.4*( pow(sqrt(1-0.4*0.4) * cosh(0.4*u), 2) + pow(0.4*sin(sqrt(1-0.4*0.4)*v), 2) )) + z = 2*sqrt(1-0.4*0.4)*cosh(0.4*u) * (-1* (sqrt(1-0.4*0.4)*sin(v)*cos(sqrt(1-0.4*0.4)*v)) + (cos(v)*sin(sqrt(1-0.4*0.4)*v)))/(0.4*( pow(sqrt(1-0.4*0.4) * cosh(0.4*u), 2) + pow(0.4*sin(sqrt(1-0.4*0.4)*v), 2) )) + */ + "title": "Breather Surface", + "xFunction": "-u + (2*(1-0.4*0.4)*cosh(0.4*u)*sinh(0.4*u)/(0.4*( pow(sqrt(1-0.4*0.4) * cosh(0.4*u), 2) + pow(0.4*sin(sqrt(1-0.4*0.4)*v), 2) )))", + "yFunction": "2*(sqrt(1-0.4*0.4))*cosh(0.4*u)*(-1*((sqrt(1-0.4*0.4))*cos(v)*cos((sqrt(1-0.4*0.4))*v)) - (sin(v) * sin((sqrt(1-0.4*0.4))*v)))/(0.4*( pow(sqrt(1-0.4*0.4) * cosh(0.4*u), 2) + pow(0.4*sin(sqrt(1-0.4*0.4)*v), 2) ))", + "zFunction": "2*sqrt(1-0.4*0.4)*cosh(0.4*u) * (-1* (sqrt(1-0.4*0.4)*sin(v)*cos(sqrt(1-0.4*0.4)*v)) + (cos(v)*sin(sqrt(1-0.4*0.4)*v)))/(0.4*( pow(sqrt(1-0.4*0.4) * cosh(0.4*u), 2) + pow(0.4*sin(sqrt(1-0.4*0.4)*v), 2) ))", + "uMin": -13.2, + "uMax": 13.2, + "vMin": -37.4, + "vMax": 37.4, + "isPiU": false, + "isPiV": false, + "uSegments": 190, + "vSegments": 190, + "scaleX": 0.2, + "scaleY": 0.2, + "scaleZ": 0.2, + "displaceU": 0, + "displaceV": 0 + }, + { + // a = 0.4 + // uMin = -13.2 + // uMax = 13.2 + // vMin = -37.4 + // vMax = 37.4 + + + // r = 1-0.4*0.4 + // w = sqrt(r) + // d = a( pow(w * cosh(a*u), 2) + pow(a*sin(w*v), 2) ) + // x = -u + (2*r*cosh(a*u)*sinh(a*u)/d) + // y = 2*w*cosh(a*u)*(-1*(w*cos(v)*cos(w*v)) - (sin(v) * sin(w*v)))/d + // z = 2*w*cosh(a*u) * (-1* (w*sin(v)*cos(w*v)) + (cos(v)*sin(w*v)))/d + /* + w = sqrt(1-0.4*0.4) + d = 0.4( pow(sqrt(1-0.4*0.4) * cosh(0.4*u), 2) + pow(0.4*sin(sqrt(1-0.4*0.4)*v), 2) ) + x = -u + (2*(1-0.4*0.4)*cosh(0.4*u)*sinh(0.4*u)/(0.4*( pow(sqrt(1-0.4*0.4) * cosh(0.4*u), 2) + pow(0.4*sin(sqrt(1-0.4*0.4)*v), 2) ))) + y = 2*(sqrt(1-0.4*0.4))*cosh(0.4*u)*(-1*((sqrt(1-0.4*0.4))*cos(v)*cos((sqrt(1-0.4*0.4))*v)) - (sin(v) * sin((sqrt(1-0.4*0.4))*v)))/(0.4*( pow(sqrt(1-0.4*0.4) * cosh(0.4*u), 2) + pow(0.4*sin(sqrt(1-0.4*0.4)*v), 2) )) + z = 2*sqrt(1-0.4*0.4)*cosh(0.4*u) * (-1* (sqrt(1-0.4*0.4)*sin(v)*cos(sqrt(1-0.4*0.4)*v)) + (cos(v)*sin(sqrt(1-0.4*0.4)*v)))/(0.4*( pow(sqrt(1-0.4*0.4) * cosh(0.4*u), 2) + pow(0.4*sin(sqrt(1-0.4*0.4)*v), 2) )) + */ + "title": "Breather Surface II", + "xFunction": "-u + (2*(1-0.6*0.6)*cosh(0.6*u)*sinh(0.6*u)/(0.6*( pow(sqrt(1-0.6*0.6) * cosh(0.6*u), 2) + pow(0.6*sin(sqrt(1-0.6*0.6)*v), 2) )))", + "yFunction": "2*(sqrt(1-0.6*0.6))*cosh(0.6*u)*(-1*((sqrt(1-0.6*0.6))*cos(v)*cos((sqrt(1-0.6*0.6))*v)) - (sin(v) * sin((sqrt(1-0.6*0.6))*v)))/(0.6*( pow(sqrt(1-0.6*0.6) * cosh(0.6*u), 2) + pow(0.6*sin(sqrt(1-0.6*0.6)*v), 2) ))", + "zFunction": "2*sqrt(1-0.6*0.6)*cosh(0.6*u) * (-1* (sqrt(1-0.6*0.6)*sin(v)*cos(sqrt(1-0.6*0.6)*v)) + (cos(v)*sin(sqrt(1-0.6*0.6)*v)))/(0.6*( pow(sqrt(1-0.6*0.6) * cosh(0.6*u), 2) + pow(0.6*sin(sqrt(1-0.6*0.6)*v), 2) ))", + "uMin": -8, + "uMax": 8, + "vMin": -15.55, + "vMax": 15.55, + "isPiU": false, + "isPiV": false, + "uSegments": 190, + "vSegments": 190, + "scaleX": 0.2, + "scaleY": 0.2, + "scaleZ": 0.2, + "displaceU": 0, + "displaceV": 0 + } +]; + + +let shouldRender = true; +let shouldScale = true; + +const shapes = op.inDropDown("shapes", parametricBodies.map((bod) => { return bod.title; })); + +const render = op.inTrigger("render"); +const inSegmentsU = op.inValueInt("u Segments", 48); +const inSegmentsV = op.inValueInt("v Segments", 48); +const multByPiU = op.inValueBool("Multiple of PI - u", false); +const inMinU = op.inValueFloat("uMin", -2); +const inMaxU = op.inValueFloat("uMax", 2); +const inDisplaceU = op.inValueFloat("Displace U", 0); + +const multByPiV = op.inValueBool("Multiple of PI - v", false); +const inMinV = op.inValueFloat("vMin", -1); +const inMaxV = op.inValueFloat("vMax", 1); +const inDisplaceV = op.inValueFloat("Displace V", 0); + +op.setPortGroup("Segments", [inSegmentsU, inSegmentsV]); +op.setPortGroup("V range", [multByPiV, inMaxV, inMinV, inDisplaceV]); +op.setPortGroup("U range", [multByPiU, inMaxU, inMinU, inDisplaceU]); +const inFunctionX = op.inString("X Function", "u"); +const inFunctionY = op.inString("Y Function", "v"); + +const inFunctionZ = op.inString("Z Function", "0"); +const inScaleX = op.inFloatSlider("Scale X", 1); +const inScaleY = op.inFloatSlider("Scale Y", 1); +const inScaleZ = op.inFloatSlider("Scale Z", 1); + +op.setPortGroup("XYZ Functions", [inFunctionX, inScaleX, inFunctionY, inScaleY, inFunctionZ, inScaleZ]); +op.setPortGroup("Scaling", [inScaleX, inScaleY, inScaleZ]); +const draw = op.inValueBool("Draw", true); +op.setPortGroup("Draw", [draw]); + + +const inObj = { + "xFunction": inFunctionX, + "yFunction": inFunctionY, + "zFunction": inFunctionZ, + + "isPiU": multByPiU, + "uMin": inMinU, + "uMax": inMaxU, + + "isPiV": multByPiV, + "vMin": inMinV, + "vMax": inMaxV, + + "uSegments": inSegmentsU, + "vSegments": inSegmentsV, + + "scaleX": inScaleX, + "scaleY": inScaleY, + "scaleZ": inScaleZ, + + "displaceU": inDisplaceU, + "displaceV": inDisplaceV +}; + + +const trigger = op.outTrigger("trigger"); + + +const geomOut = op.outObject("geometry"); +const outPosition = op.outArray("Position"); +const outLength = op.outNumber("Position Amount"); +geomOut.ignoreValueSerialize = true; + + +Object.keys(inObj).forEach((key) => +{ + inObj[key].set(parametricBodies[0][key]); +}); + +shapes.set("Rectangle"); + +shapes.onChange = ({ value }) => +{ + const [shape] = parametricBodies.filter((s) => { return s.title === value; }); + Object.keys(inObj).forEach((key) => + { + inObj[key].set(shape[key]); + }); + + op.refreshParams(); + create(); +}; + +const cgl = op.patch.cgl; +let mesh = null; +let geom = null; + +const create = () => +{ + if (shouldRender) + { + const uSegments = inSegmentsU.get(); + const vSegments = inSegmentsV.get(); + + let uMax = inMinU.get() > inMaxU.get() ? inMinU.get() : inMaxU.get(); + let vMax = inMinV.get() > inMaxV.get() ? inMinV.get() : inMaxV.get(); + let uMin = inMaxU.get() < inMinU.get() ? inMaxU.get() : inMinU.get(); + let vMin = inMaxV.get() < inMinV.get() ? inMaxV.get() : inMinV.get(); + + uMax = multByPiU.get() ? uMax * Math.PI : uMax; + vMax = multByPiV.get() ? vMax * Math.PI : vMax; + + uMin = multByPiU.get() ? uMin * Math.PI : uMin; + vMin = multByPiV.get() ? vMin * Math.PI : vMin; + + const displaceU = inDisplaceU.get(); + const displaceV = inDisplaceV.get(); + + const xFunctionString = inFunctionX.get(); + const yFunctionString = inFunctionY.get(); + const zFunctionString = inFunctionZ.get(); + + const scaleX = inScaleX.get(); + const scaleY = inScaleY.get(); + const scaleZ = inScaleZ.get(); + let xFunction; + let yFunction; + let zFunction; + + const coords = []; + const texCoords = []; + const paramVertexIndices = []; + let normals; + let tangents; + let bitangents; + + try + { + xFunction = new Function("m", "u", "v", `with(m) { return ${xFunctionString} }`); + yFunction = new Function("m", "u", "v", `with(m) { return ${yFunctionString} }`); + zFunction = new Function("m", "u", "v", `with(m) { return ${zFunctionString} }`); + + for (let i = 0; i <= uSegments; i += 1) + { + for (let j = 0; j <= vSegments; j += 1) + { + const u_tex = uMin + (i * (uMax - uMin) / uSegments); + const v_tex = vMin + (j * (vMax - vMin) / vSegments); + + const u = displaceU + u_tex; + const v = displaceV + v_tex; + + let x = xFunction(Math, u, v); + let y = yFunction(Math, u, v); + let z = zFunction(Math, u, v); + + if (shouldScale) + { + x *= scaleX; + y *= scaleY; + z *= scaleZ; + } + + coords.push(x, y, z); + + + texCoords.push(CABLES.map(u_tex, uMin, uMax, 0, 1), CABLES.map(v_tex, vMin, vMax, 1, 0)); + + if (i < uSegments && j < vSegments) + { + paramVertexIndices.push(i * (vSegments + 1) + j); + paramVertexIndices.push((i + 1) * (vSegments + 1) + j); + paramVertexIndices.push((i) * (vSegments + 1) + j + 1); + + paramVertexIndices.push((i + 1) * (vSegments + 1) + j); + paramVertexIndices.push((i + 1) * (vSegments + 1) + j + 1); + paramVertexIndices.push((i) * (vSegments + 1) + j + 1); + } + } + } + + tangents = []; + bitangents = []; + normals = []; + } + catch (e) + { + if (e instanceof ReferenceError || e instanceof SyntaxError) { op.logError(e); return; } + op.log(e); + } + geom = new CGL.Geometry("parametric surface"); + geom.clear(); + geom.vertices = coords || []; + geom.texCoords = texCoords; + geom.verticesIndices = paramVertexIndices; + + geom.calculateNormals(); + geom.calcTangentsBitangents(); + + if (geom.vertices.length == 0) return; + + if (!mesh) + { + mesh = new CGL.Mesh(cgl, geom); + } + else + { + mesh.setGeom(geom); + } + geomOut.set(null); + geomOut.set(geom); + } + outPosition.set(null); + outPosition.set(geom.vertices); + outLength.set(geom.vertices.length); + shouldRender = false; + shouldScale = false; +}; + +create(); + +const setRender = () => +{ + shouldScale = true; + shouldRender = true; +}; +const setScale = () => +{ + shouldScale = true; + shouldRender = true; +}; + +draw.onChange = + inSegmentsU.onChange = + inSegmentsV.onChange = + inMaxU.onChange = + inMaxV.onChange = + inMinU.onChange = + inMinV.onChange = + inDisplaceV.onChange = + inDisplaceU.onChange = + multByPiV.onChange = + multByPiU.onChange = + inFunctionX.onChange = + inFunctionY.onChange = + inFunctionZ.onChange = setRender; + +inScaleX.onChange = +inScaleY.onChange = +inScaleZ.onChange = setScale; + +render.onTriggered = function () +{ + if (shouldRender) create(); + if (draw.get()) + { + mesh.render(cgl.getShader()); + } + trigger.trigger(); +}; + + +}; + +Ops.Gl.Meshes.ParametricSurface.prototype = new CABLES.Op(); +CABLES.OPS["5d3211a6-801d-4e59-ba6f-546ffe5fd34a"]={f:Ops.Gl.Meshes.ParametricSurface,objName:"Ops.Gl.Meshes.ParametricSurface"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.PointCloudFromArray +// +// ************************************************************** + +Ops.Gl.Meshes.PointCloudFromArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + arr = op.inArray("Array", 3), + numPoints = op.inValueInt("Num Points"), + outTrigger = op.outTrigger("Trigger out"), + outGeom = op.outObject("Geometry"), + pTexCoordRand = op.inValueBool("Scramble Texcoords", true), + seed = op.inValue("Seed", 1), + inCoords = op.inArray("Coordinates", 2), + vertCols = op.inArray("Vertex Colors", 4); + +op.toWorkPortsNeedToBeLinked(arr, exe); +op.setPortGroup("Texture Coordinates", [pTexCoordRand, seed, inCoords]); + +const cgl = op.patch.cgl; +const geom = new CGL.Geometry("pointcloudfromarray"); +let deactivated = false; +let mesh = null; +let texCoords = []; +let needsRebuild = true; +let showingError = false; + +arr.setUiAttribs({ "title": "Positions" }); +inCoords.setUiAttribs({ "title": "Texture Coordinates" }); + +inCoords.onChange = + pTexCoordRand.onChange = updateTexCoordsPorts; +vertCols.onChange = updateVertCols; +numPoints.onChange = updateNumVerts; +seed.onChange = arr.onChange = vertCols.onLinkChanged = reset; + +exe.onTriggered = doRender; + +function doRender() +{ + outTrigger.trigger(); + if (CABLES.UI) + { + let shader = cgl.getShader(); + if (shader.glPrimitive != cgl.gl.POINTS) op.setUiError("nopointmat", "Using a Material not made for point rendering. Try to use PointMaterial."); + else op.setUiError("nopointmat", null); + } + + if (needsRebuild || !mesh) rebuild(); + if (!deactivated && mesh) mesh.render(cgl.getShader()); +} + +function reset() +{ + deactivated = arr.get() == null; + + if (!deactivated)needsRebuild = true; + else needsRebuild = false; +} + +function updateTexCoordsPorts() +{ + if (inCoords.isLinked()) + { + seed.setUiAttribs({ "greyout": true }); + pTexCoordRand.setUiAttribs({ "greyout": true }); + } + else + { + pTexCoordRand.setUiAttribs({ "greyout": false }); + + if (!pTexCoordRand.get()) seed.setUiAttribs({ "greyout": true }); + else seed.setUiAttribs({ "greyout": false }); + } + + mesh = null; + needsRebuild = true; +} + +function updateVertCols() +{ + if (!vertCols.get()) return; + if (!geom.vertexColors) reset(); + + if (mesh)mesh.setAttribute(CGL.SHADERVAR_VERTEX_COLOR, vertCols.get(), 4); +} + +function updateNumVerts() +{ + if (mesh) + { + mesh.setNumVertices(Math.min(geom.vertices.length / 3, numPoints.get())); + if (numPoints.get() == 0)mesh.setNumVertices(geom.vertices.length / 3); + } +} + +function rebuild() +{ + let verts = arr.get(); + + if (!verts || verts.length == 0) + { + // mesh=null; + return; + } + + if (verts.length % 3 !== 0) + { + // if (!showingError) + // { + op.setUiError("div3", "Array length not multiple of 3"); + + // op.uiAttr({ "error": "Array length not divisible by 3!" }); + // showingError = true; + // } + return; + } + else op.setUiError("div3", null); + + if (geom.vertices.length == verts.length && mesh && !inCoords.isLinked() && !vertCols.isLinked()) + { + mesh.setAttribute(CGL.SHADERVAR_VERTEX_POSITION, verts, 3); + geom.vertices = verts; + needsRebuild = false; + + return; + } + + geom.clear(); + let num = verts.length / 3; + num = Math.abs(Math.floor(num)); + + if (num == 0) return; + + if (!texCoords || texCoords.length != num * 2) texCoords = new Float32Array(num * 2); // num*2;//= + + let changed = true; + let rndTc = pTexCoordRand.get(); + + if (!inCoords.isLinked()) + { + Math.randomSeed = seed.get(); + texCoords = []; // needed otherwise its using the reference to input incoords port + // let genCoords = !inCoords.isLinked(); + + for (let i = 0; i < num; i++) + { + if (geom.vertices[i * 3] != verts[i * 3] || + geom.vertices[i * 3 + 1] != verts[i * 3 + 1] || + geom.vertices[i * 3 + 2] != verts[i * 3 + 2]) + { + // if (genCoords) + if (rndTc) + { + texCoords[i * 2] = Math.seededRandom(); + texCoords[i * 2 + 1] = Math.seededRandom(); + } + else + { + texCoords[i * 2] = i / num; + texCoords[i * 2 + 1] = i / num; + } + } + } + } + + if (vertCols.get()) + { + if (!showingError && vertCols.get().length != num * 4) + { + op.uiAttr({ "error": "Color array does not have the correct length! (should be " + num * 4 + ")" }); + showingError = true; + mesh = null; + return; + } + + geom.vertexColors = vertCols.get(); + } + else geom.vertexColors = []; + + if (changed) + { + if (inCoords.isLinked()) texCoords = inCoords.get(); + + geom.setPointVertices(verts); + geom.setTexCoords(texCoords); + // geom.verticesIndices = []; + + if (mesh)mesh.dispose(); + mesh = new CGL.Mesh(cgl, geom, cgl.gl.POINTS); + + mesh.addVertexNumbers = true; + mesh.setGeom(geom); + + outGeom.set(null); + outGeom.set(geom); + } + + updateNumVerts(); + needsRebuild = false; +} + + +}; + +Ops.Gl.Meshes.PointCloudFromArray.prototype = new CABLES.Op(); +CABLES.OPS["0a6d9c6f-6459-45ca-88ad-268a1f7304db"]={f:Ops.Gl.Meshes.PointCloudFromArray,objName:"Ops.Gl.Meshes.PointCloudFromArray"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.PointCloudFromTexture +// +// ************************************************************** + +Ops.Gl.Meshes.PointCloudFromTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"vertposbody_vert":"\n// float tx=mod(attrVertIndex,(MOD_texSize))/(MOD_texSize);\n// float ty=float(int((attrVertIndex/(MOD_texSize))))/(MOD_texSize);\n\nhighp vec4 col=texture(MOD_tex,texCoord);//vec2(tx,ty));\n\n// vec4 col=texture(MOD_tex,texCoord);\n\n#ifdef MOD_HAS_PS_TEX\n psMul*=texture(MOD_texPointSize,texCoord).r;\n // psMul*=attrVertIndex/21000.0;\n#endif\n\nvec3 MOD_pos=col.xyz+pos.xyz;\n\n#ifdef MOD_NORMALIZE\n MOD_pos=(MOD_pos.xyz-0.5)*2.0;\n#endif\n\n#ifdef MOD_AXIS_XYZ\n pos.xyz=MOD_pos.xyz+pos.xyz;\n#endif\n\n#ifdef MOD_AXIS_XY\n pos.xy=MOD_pos.xy+pos.xy;\n pos.z=0.0+pos.z;\n pos.w=1.0;\n#endif\n\n#ifdef MOD_REMOVEZERO\n if(MOD_pos.x==0.0 && MOD_pos.y==0.0 && MOD_pos.z==0.0) psMul=0.0;\n#endif\n",}; +const + render = op.inTrigger("render"), + inNum = op.inInt("Num Points", 0), + inAxis = op.inSwitch("Axis", ["XYZ", "XY"], "XYZ"), + inTex = op.inTexture("Texture", null, "texture"), + inTexPS = op.inTexture("Point Size", null, "texture"), + inNorm = op.inBool("Normalize", false), + inRemove0 = op.inBool("Remove Point at 0", false), + trigger = op.outTrigger("Trigger"), + outNumPoints = op.outNumber("Total Points", 0); + +const cgl = op.patch.cgl; +let mesh = null; +let numVerts = 0; +let currentNum = 0; + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "priority": -10, + "title": op.name, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": "", + "srcBodyVert": attachments.vertposbody_vert +}); + +mod.addUniformVert("t", "MOD_tex"); +mod.addUniformVert("t", "MOD_texPointSize"); +render.onTriggered = doRender; +updateDefines(); + +mod.addUniformVert("f", "MOD_texSize", 0); + +inNorm.onChange = + inTexPS.onChange = + inRemove0.onChange = + inAxis.onChange = updateDefines; + +let needsMeshSetup = true; + +inTex.onChange = () => { if (inTex.get() != CGL.Texture.getEmptyTexture(cgl))needsMeshSetup = true; }; +inNum.onChange = () => { needsMeshSetup = true; }; +updateDefines(); + +function updateDefines() +{ + mod.toggleDefine("MOD_REMOVEZERO", inRemove0); + mod.toggleDefine("MOD_AXIS_XY", inAxis.get() == "XY"); + mod.toggleDefine("MOD_AXIS_XYZ", inAxis.get() == "XYZ"); + mod.toggleDefine("MOD_NORMALIZE", inNorm.get()); + mod.toggleDefine("MOD_HAS_PS_TEX", inTexPS.get()); +} + +function doRender() +{ + if (inTex.get() == CGL.Texture.getEmptyTexture(cgl)) + { + trigger.trigger(); + + return; + } + + if (needsMeshSetup)setupMesh(); + if (!inTex.get() || !inTex.get().tex) return; + mod.bind(); + if (inTex.get())mod.pushTexture("MOD_tex", inTex.get().tex); + if (inTexPS.get())mod.pushTexture("MOD_texPointSize", inTexPS.get().tex); + + mod.setUniformValue("MOD_texSize", inTex.get().width + 1); + + if (numVerts > 0 && inNum.get() >= 0 && mesh) + { + if (inNum.get() > 0)mesh.setNumVertices(Math.min(numVerts, inNum.get())); + else mesh.setNumVertices(numVerts); + + mesh.render(cgl.getShader()); + } + + trigger.trigger(); + mod.unbind(); +} + +function setupMesh() +{ + if (!inTex.get()) + { + outNumPoints.set(0); + return; + } + const num = inTex.get().width * inTex.get().height; + outNumPoints.set(num); + + if (num == currentNum) return; + currentNum = num; + + let verts = new Float32Array(num * 3); + let texCoords = new Float32Array(num * 2); + + let bias = 0.5 * (1.0 / inTex.get().width); + + for (let x = 0; x < inTex.get().width; x++) + for (let y = 0; y < inTex.get().height; y++) + { + texCoords[(x + y * inTex.get().width) * 2] = (x / inTex.get().width) + bias; + texCoords[(x + y * inTex.get().width) * 2 + 1] = (y / inTex.get().height) + bias; + } + + const geom = new CGL.Geometry("pointcloudfromTexture"); + geom.setPointVertices(verts); + geom.setTexCoords(texCoords); + geom.verticesIndices = []; + numVerts = verts.length / 3; + + if (mesh)mesh.dispose(); + + if (numVerts > 0) mesh = new CGL.Mesh(cgl, geom, cgl.gl.POINTS); + + if (!mesh) return; + mesh.addVertexNumbers = true; + mesh.setGeom(geom); + needsMeshSetup = false; +} + + +}; + +Ops.Gl.Meshes.PointCloudFromTexture.prototype = new CABLES.Op(); +CABLES.OPS["105d8812-e641-47f2-bbaf-e45d5bc3ea8b"]={f:Ops.Gl.Meshes.PointCloudFromTexture,objName:"Ops.Gl.Meshes.PointCloudFromTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Polyhedron_v2 +// +// ************************************************************** + +Ops.Gl.Meshes.Polyhedron_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const notation = op.inString("Receipt", "djmeD"); + +const outGeom = op.outObject("Geometry"); + +let obj = {}; + +let faces = []; +let vertices = []; +let vertexColors = []; + +notation.onChange = buildMesh; +buildMesh(); + +function getCellVertices(cellArr) +{ + const verts = []; + for (let i = 0; i < cellArr.length; i++) + { + verts.push(obj.positions[cellArr[i]]); + } + return verts; +} + +function addFace(verts) +{ + const colR = Math.random(); + const colG = Math.random(); + const colB = Math.random(); + + if (verts.length == 3) + { + for (var i = 0; i < verts.length; i++) + { + vertices.push(verts[i][0], verts[i][1], verts[i][2]); + + var index = vertices.length / 3 - 1; + faces.push(index); + vertexColors.push(colR, colG, colB, 1); + } + } + else + if (verts.length == 4) + { + for (var i = 0; i < verts.length; i++) + { + vertices.push(verts[i][0], verts[i][1], verts[i][2]); + vertexColors.push(colR, colG, colB, 1); + } + + var index = vertices.length / 3 - 4; + faces.push(index); + faces.push(index + 1); + faces.push(index + 2); + + faces.push(index + 2); + faces.push(index + 3); + faces.push(index + 0); + } + else + { + let avgX = 0; + let avgY = 0; + let avgZ = 0; + + for (var i = 0; i < verts.length; i++) + { + avgX += verts[i][0]; + avgY += verts[i][1]; + avgZ += verts[i][2]; + } + avgX /= verts.length; + avgY /= verts.length; + avgZ /= verts.length; + + vertices.push(avgX, avgY, avgZ); + vertexColors.push(colR, colG, colB, 1); + + var index = vertices.length / 3 - 1; + + for (var i = 0; i < verts.length; i++) + { + vertices.push(verts[i][0], verts[i][1], verts[i][2]); + vertexColors.push(colR, colG, colB, 1); + } + + const indexEnd = vertices.length / 3 - 1; + + for (var i = index; i < indexEnd; i++) + { + faces.push(index); + faces.push(i); + faces.push(i + 1); + } + + faces.push(index); + faces.push(indexEnd); + faces.push(index + 1); + } +} + +function buildMesh() +{ + op.setUiError("mesh", null); + + obj = {}; + + faces = []; + vertices = []; + vertexColors = []; + const geom = new CGL.Geometry(op.name); + + try + { + obj = conwayhart(String(notation.get())); + } + catch (ex) + { + op.setUiError("mesh", ex); + op.logError(ex); + return; + } + + for (let i = 0; i < obj.cells.length; i++) + { + const verts = getCellVertices(obj.cells[i]); + addFace(verts, geom); + } + + geom.vertices = vertices; + geom.verticesIndices = faces; + geom.vertexColors = vertexColors; + geom.calculateNormals(); + geom.calcTangentsBitangents(); + + outGeom.set(null); + outGeom.set(geom); +} + + +}; + +Ops.Gl.Meshes.Polyhedron_v2.prototype = new CABLES.Op(); +CABLES.OPS["203a3bcd-7fff-4791-aab7-378f2b68bf29"]={f:Ops.Gl.Meshes.Polyhedron_v2,objName:"Ops.Gl.Meshes.Polyhedron_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Pyramid +// +// ************************************************************** + +Ops.Gl.Meshes.Pyramid = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let render = op.inTrigger("Render"); + +let sizeW = op.inValue("Width", 1); +let sizeL = op.inValue("Length", 1); +let sizeH = op.inValue("Height", 2); + +let inSmooth = op.inValueBool("Smooth", false); + +let inDraw = op.inValueBool("Draw", true); + +let trigger = op.outTrigger("trigger"); +let geomOut = op.outObject("geometry"); + +let geom = null; +let cgl = op.patch.cgl; +let mesh = null; + +sizeW.onChange = create; +sizeH.onChange = create; +sizeL.onChange = create; +inSmooth.onChange = create; +create(); + +render.onTriggered = function () +{ + if (inDraw.get())mesh.render(cgl.getShader()); + trigger.trigger(); +}; + +function create() +{ + if (!geom)geom = new CGL.Geometry(op.name); + let w = sizeW.get(); + let h = sizeH.get(); + let l = sizeL.get(); + + geom.vertices = [ + // -w,-l,0, + // w,-l,0, + // w,l,0, + // -w,l,0, + // 0,0,h, + -w, 0, -l, + w, 0, -l, + w, 0, l, + -w, 0, l, + 0, h, 0 + ]; + + geom.vertexNormals = [ + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0 + ]; + + geom.texCoords = [ + 0.5, 0.0, + 1.0, 1.0, + 0.0, 1.0, + 0.0, 1.0, + 0.0, 1.0, + ]; + + geom.verticesIndices = [ + 0, 1, 2, + 0, 2, 3, // bottom + + 4, 1, 0, + 4, 3, 2, + 0, 3, 4, + 4, 2, 1 + ]; + + if (!inSmooth.get())geom.unIndex(); + geom.calculateNormals({ "forceZUp": false }); + + mesh = new CGL.Mesh(cgl, geom); + geomOut.set(null); + geomOut.set(geom); +} + + +}; + +Ops.Gl.Meshes.Pyramid.prototype = new CABLES.Op(); +CABLES.OPS["22b175c4-591b-47be-9ac7-2eaf5ebaf641"]={f:Ops.Gl.Meshes.Pyramid,objName:"Ops.Gl.Meshes.Pyramid"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.QuadWarpTexture +// +// ************************************************************** + +Ops.Gl.Meshes.QuadWarpTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"shader_frag":"UNI sampler2D tex;\nIN vec2 texCoord;\n\nUNI vec2 a;\nUNI vec2 b;\nUNI vec2 c;\nUNI vec2 d;\n{{MODULES_HEAD}}\n\nfloat cross2d( in vec2 a, in vec2 b ) { return a.x*b.y - a.y*b.x; }\n\n// original function by iq : https://www.shadertoy.com/view/lsBSDm\nvec2 invBilinear( in vec2 p, in vec2 a, in vec2 b, in vec2 c, in vec2 d )\n{\n vec2 e = b-a;\n vec2 f = d-a;\n vec2 g = a-b+c-d;\n vec2 h = p-a;\n\n float k2 = cross2d( g, f );\n float k1 = cross2d( e, f ) + cross2d( h, g );\n float k0 = cross2d( h, e );\n\n float w = k1*k1 - 4.0*k0*k2;\n if( w<0.0 ) return vec2(-1.0);\n w = sqrt( w );\n\n // will fail for k0=0, which is only on the ba edge\n float v = 2.0*k0/(-k1 - w);\n if( v<0.0 || v>1.0 ) v = 2.0*k0/(-k1 + w);\n\n float u = (h.x - f.x*v)/(e.x + g.x*v);\n if( u<0.0 || u>1.0 || v<0.0 || v>1.0 ) return vec2(-1.0);\n return vec2( u, v );\n}\n\nvoid main()\n{\n vec2 uv=invBilinear(texCoord,a,b,c,d);\n vec4 col=texture(tex,1.0-uv);\n if(uv.x==-1.0 || uv.y==-1.0)discard;\n {{MODULE_COLOR}}\n outColor = col;\n}\n","shader_vert":"{{MODULES_HEAD}}\n\nIN vec3 vPosition;\nUNI mat4 projMatrix;\nUNI mat4 mvMatrix;\n\nOUT vec2 texCoord;\nIN vec2 attrTexCoord;\n\nvoid main()\n{\n vec4 pos=vec4(vPosition, 1.0);\n\n texCoord=attrTexCoord;\n\n gl_Position = projMatrix * mvMatrix * pos;\n}\n",}; +const + render = op.inTrigger("render"), + x1 = op.inFloat("A X", 0), + y1 = op.inFloat("A Y", 0), + x2 = op.inFloat("B X", 1), + y2 = op.inFloat("B Y", 0), + x3 = op.inFloat("C X", 1), + y3 = op.inFloat("C Y", 1), + x4 = op.inFloat("D X", 0), + y4 = op.inFloat("D Y", 1), + flipY = op.inValueBool("Flip Y"), + flipX = op.inValueBool("Flip X"), + inTexture = op.inTexture("Texture"), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +let mesh = null; +const geom = new CGL.Geometry("fullscreen rectangle"); +let x = 0, y = 0, z = 0, w = 0, h = 0; +let updateShaderLater = true; + +flipX.onChange = flipY.onChange = rebuildFlip; + +const shader = new CGL.Shader(cgl, "fullscreenrectangle"); +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); +shader.setSource(attachments.shader_vert, attachments.shader_frag); +shader.fullscreenRectUniform = new CGL.Uniform(shader, "t", "tex", 0); +shader.addUniformFrag("2f", "a", x1, y1); +shader.addUniformFrag("2f", "b", x2, y2); +shader.addUniformFrag("2f", "c", x3, y3); +shader.addUniformFrag("2f", "d", x4, y4); + +render.onTriggered = doRender; +op.toWorkPortsNeedToBeLinked(render); +op.toWorkPortsNeedToBeLinked(inTexture); + +inTexture.onChange = function () +{ + updateShaderLater = true; +}; + +function updateShader() +{ + let tex = inTexture.get(); +} + +op.preRender = function () +{ + updateShader(); + shader.bind(); + if (mesh)mesh.render(shader); + doRender(); +}; + +function doRender() +{ + if (cgl.getViewPort()[2] != w || cgl.getViewPort()[3] != h || !mesh) rebuild(); + + if (updateShaderLater) updateShader(); + + cgl.pushPMatrix(); + mat4.identity(cgl.pMatrix); + mat4.ortho(cgl.pMatrix, 0, w, h, 0, -10.0, 1000); + + cgl.pushModelMatrix(); + mat4.identity(cgl.mMatrix); + + cgl.pushViewMatrix(); + mat4.identity(cgl.vMatrix); + + + if (inTexture.get()) cgl.setTexture(0, inTexture.get().tex); + else cgl.setTexture(0, CGL.Texture.getTempTexture(cgl).tex); + + + cgl.gl.clear(cgl.gl.DEPTH_BUFFER_BIT); + mesh.render(shader); + cgl.gl.clear(cgl.gl.DEPTH_BUFFER_BIT); + + cgl.popPMatrix(); + cgl.popModelMatrix(); + cgl.popViewMatrix(); + + trigger.trigger(); +} + +function rebuildFlip() +{ + mesh = null; +} + +function rebuild() +{ + const currentViewPort = cgl.getViewPort(); + + if (currentViewPort[2] == w && currentViewPort[3] == h && mesh) return; + + let xx = 0, xy = 0; + + w = currentViewPort[2]; + h = currentViewPort[3]; + + geom.vertices = new Float32Array([ + xx + w, xy + h, 0.0, + xx, xy + h, 0.0, + xx + w, xy, 0.0, + xx, xy, 0.0 + ]); + + let tc = null; + + if (flipY.get()) + tc = new Float32Array([ + 1.0, 0.0, + 0.0, 0.0, + 1.0, 1.0, + 0.0, 1.0 + ]); + else + tc = new Float32Array([ + 1.0, 1.0, + 0.0, 1.0, + 1.0, 0.0, + 0.0, 0.0 + ]); + + if (flipX.get()) + { + tc[0] = 0.0; + tc[2] = 1.0; + tc[4] = 0.0; + tc[6] = 1.0; + } + + geom.setTexCoords(tc); + + geom.verticesIndices = new Uint16Array([ + 2, 1, 0, + 3, 1, 2 + ]); + + geom.vertexNormals = new Float32Array([ + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + ]); + geom.tangents = new Float32Array([ + -1, 0, 0, + -1, 0, 0, + -1, 0, 0, + -1, 0, 0]); + geom.biTangents == new Float32Array([ + 0, -1, 0, + 0, -1, 0, + 0, -1, 0, + 0, -1, 0]); + + if (!mesh) mesh = new CGL.Mesh(cgl, geom); + else mesh.setGeom(geom); +} + + +}; + +Ops.Gl.Meshes.QuadWarpTexture.prototype = new CABLES.Op(); +CABLES.OPS["14521baa-af4e-44d5-a92c-3cb54e9aa697"]={f:Ops.Gl.Meshes.QuadWarpTexture,objName:"Ops.Gl.Meshes.QuadWarpTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.RectangleFrame +// +// ************************************************************** + +Ops.Gl.Meshes.RectangleFrame = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Render"), + width = op.inValueFloat("Width", 1), + height = op.inValueFloat("Height", 1), + thickness = op.inValueFloat("Thickness", -0.1), + pivotX = op.inSwitch("pivot x", ["center", "left", "right"], "center"), + pivotY = op.inSwitch("pivot y", ["center", "top", "bottom"], "center"), + + trigger = op.outTrigger("trigger"), + geomOut = op.outObject("Geometry"), + + drawTop = op.inValueBool("Draw Top", true), + drawBottom = op.inValueBool("Draw Bottom", true), + drawLeft = op.inValueBool("Draw Left", true), + drawRight = op.inValueBool("Draw Right", true), + active = op.inValueBool("Active", true); + +op.setPortGroup("Geometry", [width, height, thickness]); +op.setPortGroup("Transform", [pivotX, pivotY]); +op.setPortGroup("Sections", [drawTop, drawBottom, drawLeft, drawRight]); + +const cgl = op.patch.cgl; +let mesh = null; +const geom = new CGL.Geometry(op.name); +geom.tangents = []; +geom.biTangents = []; + +geomOut.ignoreValueSerialize = true; + +width.onChange = + pivotX.onChange = + pivotY.onChange = + height.onChange = + thickness.onChange = + drawTop.onChange = + drawBottom.onChange = + drawLeft.onChange = + drawRight.onChange = create; + +create(); + +render.onTriggered = function () +{ + if (active.get()) mesh.render(cgl.getShader()); + + trigger.trigger(); +}; + +function create() +{ + const w = width.get(); + const h = height.get(); + let x = -w / 2; + let y = -h / 2; + const th = thickness.get();//* Math.min(height.get(),width.get())*-0.5; + + if (pivotX.get() == "right") x = -w; + else if (pivotX.get() == "left") x = 0; + + if (pivotY.get() == "top") y = -h; + else if (pivotY.get() == "bottom") y = 0; + + geom.vertices.length = 0; + geom.vertices.push( + x, y, 0, + x + w, y, 0, + x + w, y + h, 0, + x, y + h, 0, + x - th, y - th, 0, + x + w + th, y - th, 0, + x + w + th, y + h + th, 0, + x - th, y + h + th, 0 + ); + + if (geom.vertexNormals.length === 0) geom.vertexNormals = [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]; + if (geom.tangents.length === 0) geom.tangents = [1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0]; + if (geom.biTangents.length === 0) geom.biTangents = [0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0]; + + if (geom.verticesIndices)geom.verticesIndices.length = 0; + else geom.verticesIndices = []; + + const vertInd = []; + if (drawBottom.get()) vertInd.push(0, 1, 4, 1, 5, 4); + if (drawRight.get()) vertInd.push(1, 2, 5, 5, 2, 6); + if (drawTop.get()) vertInd.push(7, 6, 3, 6, 2, 3); + if (drawLeft.get()) vertInd.push(0, 4, 3, 4, 7, 3); + geom.verticesIndices = vertInd; + + if (geom.texCoords.length === 0) + { + const tc = []; + for (let i = 0, j = 0; i < geom.vertices.length; i += 3, j += 2) + { + tc[j] = geom.vertices[i + 0] / w - 0.5; + tc[j + 1] = geom.vertices[i + 1] / h - 0.5; + } + geom.texCoords = tc; + } + + if (!mesh) mesh = new CGL.Mesh(cgl, geom); + else mesh.setGeom(geom); + + geomOut.set(null); + geomOut.set(geom); +} + + +}; + +Ops.Gl.Meshes.RectangleFrame.prototype = new CABLES.Op(); +CABLES.OPS["e3a24a1a-a74b-4c38-b492-63abca68f6d1"]={f:Ops.Gl.Meshes.RectangleFrame,objName:"Ops.Gl.Meshes.RectangleFrame"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.RectangleRounded +// +// ************************************************************** + +Ops.Gl.Meshes.RectangleRounded = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const render = op.inTrigger('render'); +const inSegments = op.inValueInt('Segments', 24); +const trigger = op.outTrigger('trigger'); +const sizeW = op.inValueFloat('width', 1); +const sizeH = op.inValueFloat('height', 1); +const borderRadius = op.inValueSlider('border radius', 0.5); + +const geom = new CGL.Geometry('triangle'); +const geomOut = op.outObject('geometry'); + +geomOut.ignoreValueSerialize = true; + +op.setPortGroup('Size', [sizeW, sizeH, borderRadius, inSegments]); + +const inTopLeftCorner = op.inValueBool('Top Left', true); +const inTopRightCorner = op.inValueBool('Top Right', true); +const inBottomLeftCorner = op.inValueBool('Bottom Left', true); +const inBottomRightCorner = op.inValueBool('Bottom Right', true); +const CORNER_PORTS = [inTopLeftCorner, inTopRightCorner, inBottomLeftCorner, inBottomRightCorner]; +CORNER_PORTS.forEach((port) => { + port.onChange = create; +}); + +op.setPortGroup('Round Corner', CORNER_PORTS); + +const draw = op.inValueBool('Draw', true); +op.setPortGroup('Draw', [draw]); + +const cgl = op.patch.cgl; +let mesh = null; +sizeW.onChange = create; +sizeH.onChange = create; +borderRadius.onChange = create; +inSegments.onChange = create; + +create(); + +render.onTriggered = function () { + if (draw.get()) mesh.render(cgl.getShader()); + trigger.trigger(); +}; + +function create() { + const w = Math.abs(sizeW.get()); + const h = Math.abs(sizeH.get()); + + const r = w < h ? (borderRadius.get() * w) / 2 : (borderRadius.get() * h) / 2; + + const wi = w - 2 * r; + const hi = h - 2 * r; + const wiHalf = wi / 2; + const hiHalf = hi / 2; + + const segments = Math.abs(inSegments.get() || 1); + + const topLeftCircleMiddle = [-1 * wiHalf, hiHalf, 0]; + const bottomLeftCircleMiddle = [-1 * wiHalf, -1 * hiHalf, 0]; + const topRightCircleMiddle = [wiHalf, hiHalf, 0]; + const bottomRightCircleMiddle = [wiHalf, -1 * hiHalf, 0]; + + const circleVerts = []; + let lastX = 0; + let lastY = 0; + + // top left circle + if (inTopLeftCorner.get()) { + for (let i = 0; i <= segments; i += 1) { + const x = topLeftCircleMiddle[0] + (0 - r * Math.cos((i * Math.PI) / 2 / segments)); + const y = topLeftCircleMiddle[1] + r * Math.sin((i * Math.PI) / 2 / segments); + + circleVerts.push(x, y, 0); + + if (i > 1) { + circleVerts.push(lastX, lastY, 0); + } + + if (i <= segments - 1) circleVerts.push(...topLeftCircleMiddle); + + lastX = x; + lastY = y; + } + } else { + circleVerts.push(...topLeftCircleMiddle); + circleVerts.push(-wiHalf, hiHalf + r, 0); + circleVerts.push(-wiHalf - r, hiHalf + r, 0); + + circleVerts.push(...topLeftCircleMiddle); + circleVerts.push(-wiHalf - r, hiHalf + r, 0); + circleVerts.push(-wiHalf - r, hiHalf, 0); + } + + if (inTopRightCorner.get()) { + // top right circle + for (let i = 0; i <= segments; i += 1) { + const x = topRightCircleMiddle[0] + r * Math.cos((i * Math.PI) / 2 / segments); + const y = topRightCircleMiddle[1] + r * Math.sin((i * Math.PI) / 2 / segments); + + if (i > 1) { + circleVerts.push(...topRightCircleMiddle, lastX, lastY, 0); + } + + circleVerts.push(x, y, 0); + + if (i === segments - 1) circleVerts.push(...topRightCircleMiddle); + + lastX = x; + lastY = y; + } + } else { + circleVerts.push(...topRightCircleMiddle); + circleVerts.push(wiHalf + r, hiHalf, 0); + circleVerts.push(wiHalf + r, hiHalf + r, 0); + + circleVerts.push(...topRightCircleMiddle); + circleVerts.push(wiHalf + r, hiHalf + r, 0); + circleVerts.push(wiHalf, hiHalf + r, 0); + } + + if (inBottomRightCorner.get()) { + // bottom right circle + for (let i = 0; i <= segments; i += 1) { + const x = bottomRightCircleMiddle[0] + r * Math.cos((i * Math.PI) / 2 / segments); + const y = bottomRightCircleMiddle[1] + r * -1 * Math.sin((i * Math.PI) / 2 / segments); + + circleVerts.push(x, y, 0); + + if (i > 1) { + circleVerts.push(lastX, lastY, 0); + } + + if (i <= segments - 1) circleVerts.push(...bottomRightCircleMiddle); + + lastX = x; + lastY = y; + } + } else { + circleVerts.push(...bottomRightCircleMiddle); + circleVerts.push(wiHalf + r, -hiHalf - r, 0); + circleVerts.push(wiHalf + r, -hiHalf, 0); + + circleVerts.push(...bottomRightCircleMiddle); + circleVerts.push(wiHalf, -hiHalf - r, 0); + circleVerts.push(wiHalf + r, -hiHalf - r, 0); + } + + if (inBottomLeftCorner.get()) { + // bottom left circle + for (let i = 0; i <= segments; i += 1) { + const x = bottomLeftCircleMiddle[0] + r * -1 * Math.cos((i * Math.PI) / 2 / segments); + const y = bottomLeftCircleMiddle[1] + r * -1 * Math.sin((i * Math.PI) / 2 / segments); + + if (i > 1) { + circleVerts.push(lastX, lastY, 0); + } + + circleVerts.push(x, y, 0); + + if (i <= segments - 1) circleVerts.push(...bottomLeftCircleMiddle); + + lastX = x; + lastY = y; + } + } else { + circleVerts.push(...bottomLeftCircleMiddle); + circleVerts.push(-wiHalf - r, -hiHalf - r, 0); + circleVerts.push(-wiHalf, -hiHalf - r, 0); + + circleVerts.push(...bottomLeftCircleMiddle); + circleVerts.push(-wiHalf - r, -hiHalf, 0); + circleVerts.push(-wiHalf - r, -hiHalf - r, 0); + } + + geom.vertices = [ + //inner rectangle + + -1*wiHalf, -hiHalf, 0, + wiHalf, hiHalf, 0, + -1*wiHalf, hiHalf, 0, + + + -1*wiHalf, -1*hiHalf,0, + wiHalf, -1*hiHalf, 0, + wiHalf, hiHalf, 0, + + // left rectangle + + -1*wiHalf-r, -1*hiHalf, 0, + -1*wiHalf, -1*hiHalf, 0, + -1*wiHalf-r, hiHalf, 0, + + -1*wiHalf-r, hiHalf, 0, + -1*wiHalf, -1*hiHalf, 0, + -1*wiHalf, hiHalf, 0, + + // top rectangle + + -1*wiHalf, hiHalf, 0, + wiHalf, hiHalf+r, 0, + -1*wiHalf, hiHalf+r, 0, + + wiHalf, hiHalf + r, 0, + -1*wiHalf, hiHalf, 0, + wiHalf, hiHalf, 0, + + // bottom rectangle + -1*wiHalf, -1*hiHalf, 0, + -1*wiHalf, -1*hiHalf-r, 0, + wiHalf, -1*hiHalf-r, 0, + + wiHalf, -1*hiHalf, 0, + -1*wiHalf, -1*hiHalf, 0, + wiHalf, -1*hiHalf-r, 0, + + // right rectangle + + wiHalf+r, hiHalf, 0, + wiHalf, hiHalf, 0, + wiHalf+r, -1*hiHalf, 0, + + wiHalf+r, -1*hiHalf, 0, + wiHalf, hiHalf, 0, + wiHalf, -1*hiHalf, 0, + ...circleVerts + ] + + geom.texCoords = []; + const wAbs = Math.abs(w); + const hAbs = Math.abs(h); + + for (let i = 0; i < geom.vertices.length; i += 3) { + geom.texCoords[(i / 3) * 2 + 0] = Math.abs(geom.vertices[i + 0] / -wAbs - 0.5); + geom.texCoords[(i / 3) * 2 + 1] = Math.abs(geom.vertices[i + 1] / hAbs - 0.5); + } + + + geom.vertexNormals = geom.vertices.map((vert, i) => (i % 3 === 2 ? 1.0 : 0.0)); + geom.tangents = geom.vertices.map((vert, i) => (i % 3 === 0 ? -1.0 : 0.0)); + geom.biTangents = geom.vertices.map((vert, i) => (i % 3 === 1 ? -1.0 : 0.0)); + + if (geom.vertices.length == 0) return; + if (mesh) mesh.dispose(); + mesh = null; + mesh = new CGL.Mesh(cgl, geom); + geomOut.set(null); + geomOut.set(geom); +} + + +}; + +Ops.Gl.Meshes.RectangleRounded.prototype = new CABLES.Op(); +CABLES.OPS["86c99074-4929-44d0-a826-49e7f8bdf5c4"]={f:Ops.Gl.Meshes.RectangleRounded,objName:"Ops.Gl.Meshes.RectangleRounded"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Rectangle_v3 +// +// ************************************************************** + +Ops.Gl.Meshes.Rectangle_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + doRender = op.inValueBool("dorender", true), + width = op.inValue("width", 1), + height = op.inValue("height", 1), + pivotX = op.inSwitch("pivot x", ["left", "center", "right"], "center"), + pivotY = op.inSwitch("pivot y", ["top", "center", "bottom"], "center"), + axis = op.inSwitch("axis", ["xy", "xz"], "xy"), + flipTcX = op.inBool("Flip TexCoord X", false), + flipTcY = op.inBool("Flip TexCoord Y", true), + nColumns = op.inValueInt("num columns", 1), + nRows = op.inValueInt("num rows", 1), + trigger = op.outTrigger("trigger"), + geomOut = op.outObject("geometry", null, "geometry"); + +geomOut.ignoreValueSerialize = true; + +const geom = new CGL.Geometry("rectangle"); + +doRender.setUiAttribs({ "title": "Render" }); +render.setUiAttribs({ "title": "Trigger" }); +trigger.setUiAttribs({ "title": "Next" }); +op.setPortGroup("Pivot", [pivotX, pivotY, axis]); +op.setPortGroup("Size", [width, height]); +op.setPortGroup("Structure", [nColumns, nRows]); +op.toWorkPortsNeedToBeLinked(render); + +let mesh = null; +let needsRebuild = true; + +axis.onChange = + pivotX.onChange = + pivotY.onChange = + flipTcX.onChange = + flipTcY.onChange = + width.onChange = + height.onChange = + nRows.onChange = + nColumns.onChange = rebuildLater; + +function rebuildLater() +{ + needsRebuild = true; +} + +render.onLinkChanged = () => +{ + if (!trigger.isLinked()) + { + if (mesh) mesh.dispose(); + mesh = null; + geomOut.set(null); + rebuildLater(); + } +}; + +op.preRender = +render.onTriggered = function () +{ + if (needsRebuild) rebuild(); + if (mesh && doRender.get()) mesh.render(op.patch.cg.getShader()); + trigger.trigger(); +}; + +op.onDelete = function () +{ + if (mesh)mesh.dispose(); + rebuildLater(); +}; + +function rebuild() +{ + let w = width.get(); + let h = parseFloat(height.get()); + let x = 0; + let y = 0; + + if (typeof w == "string")w = parseFloat(w); + if (typeof h == "string")h = parseFloat(h); + + if (pivotX.get() == "center") x = 0; + else if (pivotX.get() == "right") x = -w / 2; + else if (pivotX.get() == "left") x = +w / 2; + + if (pivotY.get() == "center") y = 0; + else if (pivotY.get() == "top") y = -h / 2; + else if (pivotY.get() == "bottom") y = +h / 2; + + const verts = []; + const tc = []; + const norms = []; + const tangents = []; + const biTangents = []; + const indices = []; + + const numRows = Math.round(nRows.get()); + const numColumns = Math.round(nColumns.get()); + + const stepColumn = w / numColumns; + const stepRow = h / numRows; + + op.log("rect build"); + + let c, r, a; + a = axis.get(); + for (r = 0; r <= numRows; r++) + { + for (c = 0; c <= numColumns; c++) + { + verts.push(c * stepColumn - width.get() / 2 + x); + if (a == "xz") verts.push(0.0); + verts.push(r * stepRow - height.get() / 2 + y); + if (a == "xy") verts.push(0.0); + + tc.push(c / numColumns); + tc.push(r / numRows); + + if (a == "xy") // default + { + norms.push(0, 0, 1); + tangents.push(1, 0, 0); + biTangents.push(0, 1, 0); + } + else if (a == "xz") + { + norms.push(0, 1, 0); + tangents.push(1, 0, 0); + biTangents.push(0, 0, 1); + } + } + } + + for (c = 0; c < numColumns; c++) + { + for (r = 0; r < numRows; r++) + { + const ind = c + (numColumns + 1) * r; + const v1 = ind; + const v2 = ind + 1; + const v3 = ind + numColumns + 1; + const v4 = ind + 1 + numColumns + 1; + + if (a == "xy") // default + { + indices.push(v1); + indices.push(v2); + indices.push(v3); + + indices.push(v3); + indices.push(v2); + indices.push(v4); + } + else + if (a == "xz") + { + indices.push(v1); + indices.push(v3); + indices.push(v2); + + indices.push(v2); + indices.push(v3); + indices.push(v4); + } + } + } + + if (flipTcY.get()) for (let i = 0; i < tc.length; i += 2)tc[i + 1] = 1.0 - tc[i + 1]; + if (flipTcX.get()) for (let i = 0; i < tc.length; i += 2)tc[i] = 1.0 - tc[i]; + + geom.clear(); + geom.vertices = verts; + geom.texCoords = tc; + geom.verticesIndices = indices; + geom.vertexNormals = norms; + geom.tangents = tangents; + geom.biTangents = biTangents; + + if (numColumns * numRows > 64000)geom.unIndex(); + + const cgl = op.patch.cgl; + + if (!mesh) mesh = op.patch.cg.createMesh(geom); + else mesh.setGeom(geom); + + geomOut.set(null); + geomOut.set(geom); + needsRebuild = false; +} + + +}; + +Ops.Gl.Meshes.Rectangle_v3.prototype = new CABLES.Op(); +CABLES.OPS["82bb2f8a-77f4-4218-a3ae-8f158f1b7fb1"]={f:Ops.Gl.Meshes.Rectangle_v3,objName:"Ops.Gl.Meshes.Rectangle_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.SimpleSpline +// +// ************************************************************** + +Ops.Gl.Meshes.SimpleSpline = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Render"), + inPoints = op.inArray("Points"), + numPoints = op.inValueInt("Num Points"), + strip = op.inBool("Line Strip", true), + outGeom = op.outObject("Geometry"), + // a=op.inSwitch("Mode",["Line Strip","Line Loop","Lines"]), // next version! + texCoords = op.inSwitch("TexCoords", ["0", "0-1", "Random", "Fill"], "0"), + inTexCoords = op.inArray("TexCoords Array"), + inVertCols = op.inArray("Vertex Colors"), + next = op.outTrigger("Next"); + +const cgl = op.patch.cgl; +const geom = new CGL.Geometry("simplespline"); +outGeom.set(geom); + +geom.vertices = [0, 0, 0, 0, 0, 0, 0, 0, 0]; +const mesh = new CGL.Mesh(cgl, geom); +let buff = new Float32Array(); +let bufTexCoord = new Float32Array(); +let bufNorms = new Float32Array(); +let needsRebuild = true; +let attr; +let currentTexCoords = ""; + +inVertCols.onChange = +inTexCoords.onChange = +texCoords.onChange = + numPoints.onChange = + inPoints.onChange = + function () { needsRebuild = true; }; + +op.toWorkPortsNeedToBeLinked(inPoints); + +function rebuild() +{ + const points = inPoints.get(); + + if (!points || points.length === 0) return; + + const newLength = points.length; + + if (!(points instanceof Float32Array)) + { + if (newLength != buff.length) + { + buff = new Float32Array(newLength); + bufNorms = new Float32Array(newLength); + mesh.setAttribute(CGL.SHADERVAR_VERTEX_NORMAL, bufNorms, 3); + + buff.set(points); + } + else + { + buff.set(points); + } + } + else + { + buff = points; + } + + attr = mesh.setAttribute(CGL.SHADERVAR_VERTEX_POSITION, buff, 3); + + if (inVertCols.get()) + { + const attrTc = mesh.setAttribute(CGL.SHADERVAR_VERTEX_COLOR || "attrVertColor", inVertCols.get(), 4); + } + + const numTc = (newLength / 3) * 2; + + if (inTexCoords.get()) + { + const intc = inTexCoords.get(); + const attrTc = mesh.setAttribute(CGL.SHADERVAR_VERTEX_TEXCOORD, intc, 2); + } + else + if (currentTexCoords != texCoords.get() || mesh.getAttribute(CGL.SHADERVAR_VERTEX_TEXCOORD).numItems != numTc / 2) + { + currentTexCoords = texCoords.get(); + + if (bufTexCoord.length != numTc) bufTexCoord = new Float32Array(numTc); + + if (texCoords.get() == "0-1") + { + for (let i = 0; i < numTc; i += 2) + { + bufTexCoord[i] = i / numTc; + // bufTexCoord[i+1] = i / numTc; + bufTexCoord[i + 1] = 0.5; + } + } + else if (texCoords.get() == "Fill") + { + const sizel = Math.sqrt(numTc / 2); + + let idx = 0; + for (let j = 0; j < sizel; j++) + { + for (let i = 0; i < sizel; i++) + { + idx++; + bufTexCoord[idx * 2 + 0] = i / sizel; + bufTexCoord[idx * 2 + 1] = j / sizel; + } + } + } + else if (texCoords.get() == "Random") + { + for (let i = 0; i < numTc; i += 2) + { + bufTexCoord[i] = Math.random(); + bufTexCoord[i + 1] = Math.random(); + } + } + else + { + for (let i = 0; i < numTc; i += 2) + { + bufTexCoord[i] = 0; + bufTexCoord[i + 1] = 0; + } + } + const attrTc = mesh.setAttribute(CGL.SHADERVAR_VERTEX_TEXCOORD, bufTexCoord, 2); + } + + needsRebuild = false; +} + +render.onTriggered = function () +{ + if (!inPoints.get()) return; + + if (needsRebuild)rebuild(); + const shader = cgl.getShader(); + if (!shader) return; + + const oldPrim = shader.glPrimitive; + if (strip.get()) shader.glPrimitive = cgl.gl.LINE_STRIP; // LINE_LOOP + else shader.glPrimitive = cgl.gl.LINES; + + if (attr) + if (numPoints.get() <= 0)attr.numItems = buff.length / 3; + else attr.numItems = Math.min(numPoints.get(), buff.length / 3); + + if (mesh && buff.length !== 0) mesh.render(shader); + + shader.glPrimitive = oldPrim; + + next.trigger(); +}; + + +}; + +Ops.Gl.Meshes.SimpleSpline.prototype = new CABLES.Op(); +CABLES.OPS["af3fd0e8-ef3d-4124-a6ee-3482e9a85b45"]={f:Ops.Gl.Meshes.SimpleSpline,objName:"Ops.Gl.Meshes.SimpleSpline"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.SimpleWireframe +// +// ************************************************************** + +Ops.Gl.Meshes.SimpleWireframe = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Render"), + inGeom = op.inObject("Geometry", null, "geometry"), + next = op.outTrigger("Next"); +const cgl = op.patch.cgl; + +op.toWorkPortsNeedToBeLinked(inGeom); + +render.onTriggered = doRender; + +let mesh = null; +let verts = []; +let tc = []; +let normals = []; +let prim = cgl.gl.LINE_STRIP; + +inGeom.onChange = function () +{ + let geom = inGeom.get(); + if (!geom) + { + mesh = null; + return; + } + + verts.length = 0; + normals.length = 0; + tc.length = 0; + let i = 0; + + if (geom.isIndexed()) + { + for (i = 0; i < geom.verticesIndices.length; i += 3) + { + let index = geom.verticesIndices[i + 0]; + let index1 = geom.verticesIndices[i + 1]; + let index2 = geom.verticesIndices[i + 2]; + + verts.push(geom.vertices[index * 3 + 0], geom.vertices[index * 3 + 1], geom.vertices[index * 3 + 2]); + verts.push(geom.vertices[index1 * 3 + 0], geom.vertices[index1 * 3 + 1], geom.vertices[index1 * 3 + 2]); + verts.push(geom.vertices[index1 * 3 + 0], geom.vertices[index1 * 3 + 1], geom.vertices[index1 * 3 + 2]); + verts.push(geom.vertices[index2 * 3 + 0], geom.vertices[index2 * 3 + 1], geom.vertices[index2 * 3 + 2]); + verts.push(geom.vertices[index2 * 3 + 0], geom.vertices[index2 * 3 + 1], geom.vertices[index2 * 3 + 2]); + verts.push(geom.vertices[index * 3 + 0], geom.vertices[index * 3 + 1], geom.vertices[index * 3 + 2]); + + normals.push(geom.vertexNormals[index * 3 + 0], geom.vertexNormals[index * 3 + 1], geom.vertexNormals[index * 3 + 2]); + normals.push(geom.vertexNormals[index1 * 3 + 0], geom.vertexNormals[index1 * 3 + 1], geom.vertexNormals[index1 * 3 + 2]); + normals.push(geom.vertexNormals[index1 * 3 + 0], geom.vertexNormals[index1 * 3 + 1], geom.vertexNormals[index1 * 3 + 2]); + normals.push(geom.vertexNormals[index2 * 3 + 0], geom.vertexNormals[index2 * 3 + 1], geom.vertexNormals[index2 * 3 + 2]); + normals.push(geom.vertexNormals[index2 * 3 + 0], geom.vertexNormals[index2 * 3 + 1], geom.vertexNormals[index2 * 3 + 2]); + normals.push(geom.vertexNormals[index * 3 + 0], geom.vertexNormals[index * 3 + 1], geom.vertexNormals[index * 3 + 2]); + + tc.push(geom.texCoords[index * 2 + 0], geom.texCoords[index * 2 + 1]); + tc.push(geom.texCoords[index1 * 2 + 0], geom.texCoords[index1 * 2 + 1]); + tc.push(geom.texCoords[index1 * 2 + 0], geom.texCoords[index1 * 2 + 1]); + tc.push(geom.texCoords[index2 * 2 + 0], geom.texCoords[index2 * 2 + 1]); + tc.push(geom.texCoords[index2 * 2 + 0], geom.texCoords[index2 * 2 + 1]); + tc.push(geom.texCoords[index * 2 + 0], geom.texCoords[index * 2 + 1]); + } + prim = cgl.gl.LINES; + } + else + { + for (i = 0; i < geom.vertices.length; i += 9) + { + verts.push(geom.vertices[i + 0], geom.vertices[i + 1], geom.vertices[i + 2]); + verts.push(geom.vertices[i + 3], geom.vertices[i + 4], geom.vertices[i + 5]); + + verts.push(geom.vertices[i + 3], geom.vertices[i + 4], geom.vertices[i + 5]); + verts.push(geom.vertices[i + 6], geom.vertices[i + 7], geom.vertices[i + 8]); + + verts.push(geom.vertices[i + 6], geom.vertices[i + 7], geom.vertices[i + 8]); + verts.push(geom.vertices[i + 0], geom.vertices[i + 1], geom.vertices[i + 2]); + } + + prim = cgl.gl.LINES; + } + + geom = new CGL.Geometry("wireframelinegeom"); + // if(verts.length>60000)geom.setVertices(verts); + // else + geom.setVertices(verts); + geom.setTexCoords(tc); + geom.vertexNormals = normals; + + mesh = new CGL.Mesh(cgl, geom, prim); +}; + +function doRender() +{ + let shader = cgl.getShader(); + if (!shader) return; + + let oldPrim = shader.glPrimitive; + shader.glPrimitive = prim; + if (mesh) mesh.render(shader); + shader.glPrimitive = oldPrim; + next.trigger(); +} + + +}; + +Ops.Gl.Meshes.SimpleWireframe.prototype = new CABLES.Op(); +CABLES.OPS["89264e0a-512f-48a4-a7bb-ec8f12aa19c1"]={f:Ops.Gl.Meshes.SimpleWireframe,objName:"Ops.Gl.Meshes.SimpleWireframe"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Sphere_v2 +// +// ************************************************************** + +Ops.Gl.Meshes.Sphere_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + TAU = Math.PI * 2, + cgl = op.patch.cgl, + inTrigger = op.inTrigger("render"), + inRadius = op.inValue("radius", 0.5), + inStacks = op.inValue("stacks", 32), + inSlices = op.inValue("slices", 32), + inStacklimit = op.inValueSlider("Filloffset", 1), + inDraw = op.inValueBool("Render", true), + outTrigger = op.outTrigger("trigger"), + outGeometry = op.outObject("geometry", null, "geometry"), + UP = vec3.fromValues(0, 1, 0), + RIGHT = vec3.fromValues(1, 0, 0); + +let + geom = new CGL.Geometry("Sphere"), + tmpNormal = vec3.create(), + tmpVec = vec3.create(), + needsRebuild = true, + mesh; + +function buildMesh() +{ + const + stacks = Math.ceil(Math.max(inStacks.get(), 2)), + slices = Math.ceil(Math.max(inSlices.get(), 3)), + stackLimit = Math.min(Math.max(inStacklimit.get() * stacks, 1), stacks), + radius = inRadius.get(); + let + positions = [], + texcoords = [], + normals = [], + tangents = [], + biTangents = [], + indices = [], + x, y, z, d, t, a, + o, u, v, i, j; + for (i = o = 0; i < stacks + 1; i++) + { + v = (i / stacks - 0.5) * Math.PI; + y = Math.sin(v); + a = Math.cos(v); + // for (j = 0; j < slices+1; j++) { + for (j = slices; j >= 0; j--) + { + u = (j / slices) * TAU; + x = Math.cos(u) * a; + z = Math.sin(u) * a; + + positions.push(x * radius, y * radius, z * radius); + // texcoords.push(i/(stacks+1),j/slices); + texcoords.push(j / slices, i / (stacks + 1)); + + d = Math.sqrt(x * x + y * y + z * z); + normals.push( + tmpNormal[0] = x / d, + tmpNormal[1] = y / d, + tmpNormal[2] = z / d + ); + + if (y == d) t = RIGHT; + else t = UP; + vec3.cross(tmpVec, tmpNormal, t); + vec3.normalize(tmpVec, tmpVec); + Array.prototype.push.apply(tangents, tmpVec); + vec3.cross(tmpVec, tmpVec, tmpNormal); + Array.prototype.push.apply(biTangents, tmpVec); + } + if (i == 0 || i > stackLimit) continue; + for (j = 0; j < slices; j++, o++) + { + indices.push( + o, o + 1, o + slices + 1, + o + 1, o + slices + 2, o + slices + 1 + ); + } + o++; + } + + // set geometry + geom.clear(); + geom.vertices = positions; + geom.texCoords = texcoords; + geom.vertexNormals = normals; + geom.tangents = tangents; + geom.biTangents = biTangents; + geom.verticesIndices = indices; + + outGeometry.set(null); + outGeometry.set(geom); + + if (!mesh) mesh = new CGL.Mesh(cgl, geom); + else mesh.setGeom(geom); + + needsRebuild = false; +} + +// set event handlers +inTrigger.onTriggered = function () +{ + if (needsRebuild) buildMesh(); + if (inDraw.get()) mesh.render(cgl.getShader()); + outTrigger.trigger(); +}; + +inStacks.onChange = +inSlices.onChange = +inStacklimit.onChange = +inRadius.onChange = function () +{ + // only calculate once, even after multiple settings could were changed + needsRebuild = true; +}; + +// set lifecycle handlers +op.onDelete = function () { if (mesh)mesh.dispose(); }; + + +}; + +Ops.Gl.Meshes.Sphere_v2.prototype = new CABLES.Op(); +CABLES.OPS["450b4d68-2278-4d9f-9849-0abdfa37ef69"]={f:Ops.Gl.Meshes.Sphere_v2,objName:"Ops.Gl.Meshes.Sphere_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.SplineMeshMaterial_v2 +// +// ************************************************************** + +Ops.Gl.Meshes.SplineMeshMaterial_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"splinemat_frag":"IN vec2 texCoord;\nIN float splineDoDrawFrag;\nUNI vec4 color;\nUNI sampler2D tex;\nUNI sampler2D texMask;\n\n{{MODULES_HEAD}}\n\nvoid main()\n{\n vec4 col=color;\n\n #ifdef USE_TEXTURE\n #ifdef TEX_COLORIZE\n col*=texture(tex,texCoord);\n #endif\n #ifndef TEX_COLORIZE\n col=texture(tex,texCoord);\n #endif\n #endif\n\n col.a=color.a;\n\n #ifdef USE_TEXMASK\n col.a*=texture(texMask,texCoord).r;\n if(col.a==0.0) discard;\n #endif\n\n {{MODULE_COLOR}}\n\n // if(splineDoDrawFrag==0.0) col.rgb=vec3(1.0,0.0,0.0);\n if(splineDoDrawFrag==0.0) discard;\n\n outColor = col;\n}","splinemat_vert":"{{MODULES_HEAD}}\n\nIN vec3 vPosition;\nIN float attrVertIndex;\nIN float splineProgress;\nIN vec3 spline,spline2,spline3;\nIN float splineDoDraw;\n\nOUT float splineDoDrawFrag;\nOUT vec2 texCoord;\nOUT vec3 norm;\nUNI mat4 projMatrix;\nUNI mat4 viewMatrix;\nUNI mat4 modelMatrix;\n\nUNI float width;\nUNI float texOffset;\n\n#define PI 3.1415926538\n\nvec2 rotate(vec2 v, float a)\n{\n\tfloat s = sin(a);\n\tfloat c = cos(a);\n\tmat2 m = mat2(c, -s, s, c);\n\treturn m * v;\n}\n\nfloat aspect=1.7777; // todo uniform ?\n\nvec2 fix( vec4 i )\n{\n vec2 res = i.xy / i.w;\n res.x *= aspect;\n return res;\n}\n\nvoid main()\n{\n texCoord=vPosition.xy;\n texCoord.y=texCoord.y*0.5+0.5;\n #ifdef TEX_MAP_FULL\n texCoord.x=splineProgress;\n #endif\n texCoord.x+=texOffset;\n\n mat4 mMatrix=modelMatrix;\n mat4 mvMatrix=viewMatrix * mMatrix;\n\n splineDoDrawFrag=splineDoDraw;\n\n // vec4 pos=vec4((spline2+spline3+spline)/3.0*vPosition,1.0);\n vec4 pos=vec4(spline2,1.0);\n\n {{MODULE_VERTEX_POSITION}}\n\n vec4 finalPosition = projMatrix * mvMatrix * (vec4(spline2,1.0));\n vec4 finalPosition2 = projMatrix * mvMatrix * (vec4(spline3,1.0));\n\n vec2 screenPos =fix(projMatrix * mvMatrix * vec4(spline,1.0));\n vec2 screenPos2=fix(projMatrix * mvMatrix * vec4(spline2,1.0));\n vec2 screenPos3=fix(projMatrix * mvMatrix * vec4(spline3,1.0));\n\n float wid=width/10.0;\n\n #ifndef PERSPWIDTH\n wid=width*finalPosition.w*0.0025;\n #endif\n\n vec2 dir1 = normalize( screenPos2 - screenPos );\n vec2 dir2 = normalize( screenPos3 - screenPos2 );\n\n\tif( screenPos2 == screenPos ) dir1 = normalize( screenPos3 - screenPos2 );\n\n vec2 normal = vec2( -dir1.y, dir1.x ) * 0.5 * wid;\n vec2 normal2 = vec2( -dir2.y, dir2.x ) * 0.5 * wid;\n\n vec4 offset = vec4( mix(normal,normal2,vPosition.x) * vPosition.y, 0.0, 1.0 );\n\n finalPosition = mix(finalPosition,finalPosition2,vPosition.x);\n\tfinalPosition.xy += offset.xy;\n\n gl_Position = finalPosition;\n}\n\n\n\n\n\n\n\n",}; +const + render = op.inTrigger("Render"), + inWidth = op.inFloat("Width", 0.2), + inPerspective = op.inBool("Width Perspective", true), + inTexture = op.inTexture("Texture"), + inTextureMask = op.inTexture("Texture Mask"), + inTexMap = op.inSwitch("Mapping", ["Full", "Face"], "Full"), + inTexColorize = op.inBool("Colorize Texture", false), + inTexOffset = op.inFloat("Offset", 0), + r = op.inValueSlider("r", Math.random()), + g = op.inValueSlider("g", Math.random()), + b = op.inValueSlider("b", Math.random()), + a = op.inValueSlider("a", 1), + trigger = op.outTrigger("Trigger"), + shaderOut = op.outObject("Shader"); + +r.setUiAttribs({ "colorPick": true }); +shaderOut.ignoreValueSerialize = true; + +const cgl = op.patch.cgl; + +op.toWorkPortsNeedToBeLinked(render); +op.setPortGroup("Color", [r, g, b, a]); +op.setPortGroup("Texture", [inTexture, inTexMap, inTexColorize]); + +const shader = new CGL.Shader(cgl, "splinemesh_material"); +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); +shader.setSource(attachments.splinemat_vert, attachments.splinemat_frag); +shaderOut.set(shader); + +const uniTex = shader.addUniformFrag("t", "tex"); +const uniTexMask = shader.addUniformFrag("t", "texMask"); + +shader.addUniformFrag("4f", "color", r, g, b, a); +shader.addUniformFrag("f", "width", inWidth); +shader.addUniformFrag("f", "texOffset", inTexOffset); +shader.toggleDefine("PERSPWIDTH", inPerspective); +shader.toggleDefine("USE_TEXTURE", inTexture); +shader.toggleDefine("TEX_COLORIZE", inTexColorize); +shader.toggleDefine("USE_TEXMASK", inTextureMask); + +inTexMap.on("change", updateMapping); + +render.onTriggered = doRender; +updateMapping(); + +function doRender() +{ + if (!shader) return; + + cgl.pushShader(shader); + shader.popTextures(); + + if (uniTex && inTexture.get()) shader.pushTexture(uniTex, inTexture.get().tex); + if (uniTexMask && inTextureMask.get()) shader.pushTexture(uniTexMask, inTextureMask.get().tex); + + trigger.trigger(); + + cgl.popShader(); +} + +function updateMapping() +{ + shader.toggleDefine("TEX_MAP_FULL", inTexMap.get() === "Full"); +} + + +}; + +Ops.Gl.Meshes.SplineMeshMaterial_v2.prototype = new CABLES.Op(); +CABLES.OPS["5ff7c643-cbea-44cc-9f34-fb18a44bcfff"]={f:Ops.Gl.Meshes.SplineMeshMaterial_v2,objName:"Ops.Gl.Meshes.SplineMeshMaterial_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.SplineMesh_v2 +// +// ************************************************************** + +Ops.Gl.Meshes.SplineMesh_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Render"), + inPoints = op.inArray("Points"), + inHardEdges = op.inBool("Tesselate Edges", false), + inRenderMesh = op.inBool("Render Mesh", true), + next = op.outTrigger("Next"); + +const geom = new CGL.Geometry("splinemesh_2"); +geom.vertices = []; +geom.clear(); + +let thePoints = []; +const cgl = op.patch.cgl; +let points = new Float32Array(); +let points2 = new Float32Array(); +let points3 = new Float32Array(); +let doDraw = new Float32Array(); +let splineIndex = null; + +let pointsProgress = new Float32Array(); +const pointsDoDraw = new Float32Array(); +const arrEdges = []; + +const verts = [0, 0, 0]; + +let mesh = new CGL.Mesh(cgl, geom); +mesh.addVertexNumbers = true; + +let rebuildLater = true; + +inHardEdges.onChange = + inPoints.onChange = () => { rebuildLater = true; }; + +render.onTriggered = renderMesh; + +let shader = null; + +function renderMesh() +{ + if (rebuildLater)rebuild(); + if (mesh && inRenderMesh.get()) + { + if (shader != cgl.getShader()) + { + shader = cgl.getShader(); + if (!shader) return; + if (shader.getName() != "splinemesh_material") op.setUiError("nosplinemat", "Splinemesh needs a SplineMeshMaterial!"); + else op.setUiError("nosplinemat"); + + shader = cgl.getShader(); + } + + if (verts.length > 0) mesh.render(shader); + } + + next.trigger(); +} + +function buildMesh() +{ + verts.length = 0; + + const max = 1; + const min = -max; + + for (let i = 0; i < thePoints.length / 3; i++) + { + verts.push( + max, min, 0, 0, min, 0, max, max, 0, + 0, min, 0, 0, max, 0, max, max, 0 + ); + } + geom.vertices = verts; + + // if(mesh)mesh.dispose(); + if (!mesh) mesh = new CGL.Mesh(cgl, geom); + + mesh.addVertexNumbers = true; + mesh.setGeom(geom); + mesh.addVertexNumbers = true; +} + +function rebuild() +{ + const inpoints = inPoints.get(); + + if (!inpoints || inpoints.length === 0) + { + mesh = null; + return; + } + + if (inpoints[0].length) + { + const arr = []; + splineIndex = []; + let count = 0; + + for (let i = 0; i < inpoints.length; i++) + { + for (let j = 0; j < inpoints[i].length / 3; j++) + { + splineIndex[(count - 3) / 3] = i;// (i) / inpoints.length; + + arr[count++] = inpoints[i][j * 3 + 0]; + arr[count++] = inpoints[i][j * 3 + 1]; + arr[count++] = inpoints[i][j * 3 + 2]; + } + } + thePoints = arr; + } + else + { + splineIndex = null; + thePoints = inpoints; + } + + if (inHardEdges.get()) thePoints = tessEdges(thePoints); + + buildMesh(); + + const newLength = thePoints.length * 6; + let count = 0; + let lastIndex = 0; + let drawable = 0; + + if (points.length != newLength) + { + points = new Float32Array(newLength); + points2 = new Float32Array(newLength); + points3 = new Float32Array(newLength); + + doDraw = new Float32Array(newLength / 3); + pointsProgress = new Float32Array(newLength / 3); + + for (let i = 0; i < newLength / 3; i++) pointsProgress[i] = i / (newLength / 3); + } + + for (let i = 0; i < thePoints.length / 3; i++) + { + if (splineIndex) + { + if (i > 1 && lastIndex != splineIndex[i]) drawable = 0.0; + else drawable = 1.0; + lastIndex = splineIndex[i]; + } + else drawable = 1.0; + + for (let j = 0; j < 6; j++) + { + doDraw[count / 3] = drawable; + + for (let k = 0; k < 3; k++) + { + points[count] = thePoints[(Math.max(0, i - 1)) * 3 + k]; + points2[count] = thePoints[(i + 0) * 3 + k]; + points3[count] = thePoints[(i + 1) * 3 + k]; + count++; + } + } + } + + mesh.setAttribute("spline", points, 3); + mesh.setAttribute("spline2", points2, 3); + mesh.setAttribute("spline3", points3, 3); + mesh.setAttribute("splineDoDraw", doDraw, 1); + mesh.setAttribute("splineProgress", pointsProgress, 1); + + rebuildLater = false; +} + +function ip(a, b, p) +{ + return a + p * (b - a); +} + +function tessEdges(oldArr) +{ + let count = 0; + const step = 0.001; + const oneMinusStep = 1 - step; + const l = oldArr.length * 3 - 3; + arrEdges.length = l; + + const tessSplineIndex = []; + + if (splineIndex) tessSplineIndex[0] = splineIndex[1]; + + for (let i = 0; i < oldArr.length - 3; i += 3) + { + arrEdges[count++] = oldArr[i + 0]; + arrEdges[count++] = oldArr[i + 1]; + arrEdges[count++] = oldArr[i + 2]; + if (splineIndex) tessSplineIndex[count / 3] = splineIndex[i / 3]; + + arrEdges[count++] = ip(oldArr[i + 0], oldArr[i + 3], step); + arrEdges[count++] = ip(oldArr[i + 1], oldArr[i + 4], step); + arrEdges[count++] = ip(oldArr[i + 2], oldArr[i + 5], step); + if (splineIndex) tessSplineIndex[count / 3] = splineIndex[i / 3]; + + arrEdges[count++] = ip(oldArr[i + 0], oldArr[i + 3], oneMinusStep); + arrEdges[count++] = ip(oldArr[i + 1], oldArr[i + 4], oneMinusStep); + arrEdges[count++] = ip(oldArr[i + 2], oldArr[i + 5], oneMinusStep); + if (splineIndex) tessSplineIndex[count / 3] = splineIndex[i / 3]; + } + + if (splineIndex) splineIndex = tessSplineIndex; + + return arrEdges; +} + + +}; + +Ops.Gl.Meshes.SplineMesh_v2.prototype = new CABLES.Op(); +CABLES.OPS["287abf6c-5501-4bc9-a627-70ec3c3766d2"]={f:Ops.Gl.Meshes.SplineMesh_v2,objName:"Ops.Gl.Meshes.SplineMesh_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Star +// +// ************************************************************** + +Ops.Gl.Meshes.Star = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + segments = op.inValue("segments", 40), + radius = op.inValue("radius", 1), + shape = op.inValueSelect("Shape", ["Star", "Saw", "Gear"], "Star"), + outerRadius = op.inValue("Length", 1.5), + zDiff = op.inFloat("Peak Z Pos", 0), + percent = op.inValueSlider("percent"), + fill = op.inValueBool("Fill"), + trigger = op.outTrigger("trigger"), + geomOut = op.addOutPort(new CABLES.Port(op, "geometry", CABLES.OP_PORT_TYPE_OBJECT)); + +geomOut.ignoreValueSerialize = true; +let cgl = op.patch.cgl; + +let oldPrim = 0; +let shader = null; +percent.set(1); + +let geom = new CGL.Geometry("circle"); +let mesh = null; +let lastSegs = -1; + +zDiff.onChange = + segments.onChange = + radius.onChange = + percent.onChange = + shape.onChange = + fill.onChange = + outerRadius.onChange = calc; +calc(); + +render.onTriggered = function () +{ + if (op.instanced(render)) return; + + shader = cgl.getShader(); + if (!shader) return; + oldPrim = shader.glPrimitive; + + mesh.render(shader); + trigger.trigger(); + + shader.glPrimitive = oldPrim; +}; + +function calc() +{ + let segs = Math.max(3, Math.floor(segments.get())); + + geom.clear(); + + let + faces = [], + normals = [], + tangents = [], + biTangents = []; + let i = 0, degInRad = 0; + let oldPosX = 0, oldPosY = 0; + let oldPosXTexCoord = 0, oldPosYTexCoord = 0; + + let oldPosXIn = 0, oldPosYIn = 0; + let oldPosXTexCoordIn = 0, oldPosYTexCoordIn = 0; + + let posxTexCoordIn = 0, posyTexCoordIn = 0; + let posxTexCoord = 0, posyTexCoord = 0; + let posx = 0, posy = 0; + + let verts = []; + let outX = 0, outY = 0; + + let imode = 0; + if (shape.get() == "Saw")imode = 1; + if (shape.get() == "Gear")imode = 2; + + let cycleGear = true; + + for (i = 0; i <= segs * percent.get(); i++) + { + degInRad = (360 / segs) * i * CGL.DEG2RAD; + posx = Math.cos(degInRad) * radius.get(); + posy = Math.sin(degInRad) * radius.get(); + + // saw mode + cycleGear = !cycleGear; + + switch (imode) + { + case 0: + outX = ((posx + oldPosX) * 0.5) * outerRadius.get(); + outY = ((posy + oldPosY) * 0.5) * outerRadius.get(); + break; + + case 1: + outX = (posx) * outerRadius.get(); + outY = (posy) * outerRadius.get(); + break; + + case 2: + if (cycleGear) + { + outX = (posx) * outerRadius.get(); + outY = (posy) * outerRadius.get(); + + degInRad = (360 / segs) * (i - 1) * CGL.DEG2RAD; + let ooutX = Math.cos(degInRad) * radius.get(); + let ooutY = Math.sin(degInRad) * radius.get(); + + ooutX *= outerRadius.get(); + ooutY *= outerRadius.get(); + + faces.push( + [ooutX, ooutY, 0], + [outX, outY, 0], + [oldPosX, oldPosY, 0] + ); + normals.push(0, 0, 1, 0, 0, 1, 0, 0, 1); + tangents.push(1, 0, 0, 1, 0, 0, 1, 0, 0); + biTangents.push(0, 1, 0, 0, 1, 0, 0, 1, 0); + } + + break; + } + + if (fill.get()) + { + faces.push( + [posx, posy, 0], + [oldPosX, oldPosY, 0], + [0, 0, 0] + ); + normals.push(0, 0, 1, 0, 0, 1, 0, 0, 1); + tangents.push(1, 0, 0, 1, 0, 0, 1, 0, 0); + biTangents.push(0, 1, 0, 0, 1, 0, 0, 1, 0); + } + + if (imode != 2 || cycleGear) + { + faces.push( + [posx, posy, 0], + [oldPosX, oldPosY, 0], + [outX, outY, zDiff.get()] + ); + normals.push(0, 0, 1, 0, 0, 1, 0, 0, 1); + tangents.push(1, 0, 0, 1, 0, 0, 1, 0, 0); + biTangents.push(0, 1, 0, 0, 1, 0, 0, 1, 0); + } + + oldPosX = posx; + oldPosY = posy; + } + + geom = CGL.Geometry.buildFromFaces(faces); + geom.vertexNormals = normals; + geom.tangents = tangents; + geom.biTangents = biTangents; + geom.mapTexCoords2d(); + + geomOut.set(null); + geomOut.set(geom); + + if (geom.vertices.length == 0) return; + if (!mesh)mesh = new CGL.Mesh(cgl, geom); + mesh.setGeom(geom); +} + + +}; + +Ops.Gl.Meshes.Star.prototype = new CABLES.Op(); +CABLES.OPS["25feb18a-8df6-473f-b548-59c514c6f949"]={f:Ops.Gl.Meshes.Star,objName:"Ops.Gl.Meshes.Star"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.SuperShape +// +// ************************************************************** + +Ops.Gl.Meshes.SuperShape = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// from https://github.com/ahoiin/supershape.js/blob/master/js/objects.js + +const render = op.inTrigger("render"); + +let pNormalizeSize = op.inValueBool("Normalize Size", true); +let asPointCloud = op.inValueBool("Point Cloud", false); +let pStep = op.inFloat("Step", 0.05); + +let a1 = op.inFloat("a1", 1); +let b1 = op.inFloat("b1", 1); +let m1 = op.inFloat("m1", 5); +let n11 = op.inFloat("n11", 1); +let n21 = op.inFloat("n21", 1); +let n31 = op.inFloat("n31", 2); + +let a2 = op.inFloat("a2", 1); +let b2 = op.inFloat("b2", 1); +let m2 = op.inFloat("m2", 5); +let n12 = op.inFloat("n12", 1); +let n22 = op.inFloat("n22", 1); +let n32 = op.inFloat("n32", 3); + +let trigger = op.outTrigger("Trigger"); +let outNumVerts = op.outNumber("Num Vertices"); +let outGeom = op.outObject("geom", null, "geometry"); + +let needsUpdate = true; +let geometry = new CGL.Geometry(op.name); +let mesh = null; +let verts = []; + +pNormalizeSize.onChange = + pStep.onChange = + a1.onChange = + b1.onChange = + m1.onChange = + n11.onChange = + n21.onChange = + n31.onChange = + a2.onChange = + b2.onChange = + m2.onChange = + n12.onChange = + n22.onChange = + n32.onChange = doUpdate; + +function doUpdate() +{ + needsUpdate = true; +} + +asPointCloud.onChange = function () +{ + mesh = null; + needsUpdate = true; +}; + +render.onTriggered = function () +{ + if (needsUpdate)update(); + if (mesh) mesh.render(op.patch.cgl.getShader()); + + trigger.trigger(); +}; +function update() +{ + verts.length = 0; + geometry.clear(); + // geometry=new CGL.Geometry(op.name); + needsUpdate = false; + // geometry.dynamic = true; + let step = pStep.get(); + let q = parseInt(2 * Math.PI / step + 1.3462); + let o = parseInt(Math.PI / step + 1.5); + + let resize = pNormalizeSize.get(); + let max = 0; + + for (let l = 0; l < (q); l++) + { + var u = -Math.PI + l * step; + for (let h = 0; h < (o); h++) + { + var s = -Math.PI / 2 + h * step; + var m, k, n, g, v, e, t; + let f = 0; + let p = 0; + let w = 0; + m = Math.cos(m1.get() * u / 4); + m = 1 / a1.get() * Math.abs(m); + m = Math.abs(m); + k = Math.sin(m1.get() * u / 4); + k = 1 / b1.get() * Math.abs(k); + k = Math.abs(k); + g = Math.pow(m, n21.get()) + Math.pow(k, n31.get()); + v = Math.abs(g); + v = Math.pow(v, (-1 / n11.get())); + m = Math.cos(m2.get() * s / 4); + m = 1 / a2.get() * Math.abs(m); + m = Math.abs(m); + k = Math.sin(m2.get() * s / 4); + k = 1 / b2.get() * Math.abs(k); + k = Math.abs(k); + e = Math.pow(m, n22.get()) + Math.pow(k, n32.get()); + t = Math.abs(e); + t = Math.pow(t, (-1 / n12.get())); + f = v * Math.cos(u) * t * Math.cos(s); + p = v * Math.sin(u) * t * Math.cos(s); + w = t * Math.sin(s); + verts.push(f); + verts.push(p); + verts.push(w); + + if (resize) + { + max = Math.max(max, Math.abs(f)); + max = Math.max(max, Math.abs(p)); + max = Math.max(max, Math.abs(w)); + } + } + } + + if (resize && max > 1) for (let i = 0; i < verts.length; i++) verts[i] /= max; + + if (asPointCloud.get()) + { + geometry.setPointVertices(verts); + geometry.mapTexCoords2d(); + + mesh = new CGL.Mesh(op.patch.cgl, geometry, op.patch.cgl.gl.POINTS); + mesh.addVertexNumbers = true; + mesh.setGeom(geometry); + } + else + { + for (var u = 0; u < (q - 1); u++) + { + for (var s = 0; s < (o - 1); s++) + { + let d = u * o + s; + let c = u * o + s + 1; + let b = (u + 1) * o + s + 1; + let a = (u + 1) * o + s; + // geometry.faces.push(new THREE.Face4(d, c, b, a)); + geometry.verticesIndices.push(d); + geometry.verticesIndices.push(c); + geometry.verticesIndices.push(b); + + geometry.verticesIndices.push(a); + geometry.verticesIndices.push(b); + geometry.verticesIndices.push(d); + } + } + geometry.vertices = verts; + geometry.mapTexCoords2d(); + + outNumVerts.set(verts.length); + + geometry.calculateNormals({ "forceZUp": true }); + + if (!mesh) mesh = new CGL.Mesh(op.patch.cgl, geometry); + else mesh.setGeom(geometry); + } + + outGeom.set(null); + outGeom.set(geometry); +} + + +}; + +Ops.Gl.Meshes.SuperShape.prototype = new CABLES.Op(); +CABLES.OPS["ed8b5db0-b928-4f5d-87d7-4b2491ae7b00"]={f:Ops.Gl.Meshes.SuperShape,objName:"Ops.Gl.Meshes.SuperShape"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.TextMesh_v2 +// +// ************************************************************** + +Ops.Gl.Meshes.TextMesh_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"textmesh_frag":"UNI sampler2D tex;\n#ifdef DO_MULTEX\n UNI sampler2D texMul;\n#endif\n#ifdef DO_MULTEX_MASK\n UNI sampler2D texMulMask;\n#endif\nIN vec2 texCoord;\nIN vec2 texPos;\nUNI float r;\nUNI float g;\nUNI float b;\nUNI float a;\n\nvoid main()\n{\n vec4 col=texture(tex,texCoord);\n col.a=col.r;\n col.r*=r;\n col.g*=g;\n col.b*=b;\n col*=a;\n\n if(col.a==0.0)discard;\n\n #ifdef DO_MULTEX\n col*=texture(texMul,texPos);\n #endif\n\n #ifdef DO_MULTEX_MASK\n col*=texture(texMulMask,texPos).r;\n #endif\n\n outColor=col;\n}","textmesh_vert":"UNI sampler2D tex;\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\nUNI float scale;\nIN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN mat4 instMat;\nIN vec2 attrTexOffsets;\nIN vec2 attrTexSize;\nIN vec2 attrTexPos;\nOUT vec2 texPos;\n\nOUT vec2 texCoord;\n\nvoid main()\n{\n texCoord=(attrTexCoord*(attrTexSize)) + attrTexOffsets;\n mat4 instMVMat=instMat;\n instMVMat[3][0]*=scale;\n\n texPos=attrTexPos;\n\n vec4 vert=vec4( vPosition.x*(attrTexSize.x/attrTexSize.y)*scale,vPosition.y*scale,vPosition.z*scale, 1. );\n\n mat4 mvMatrix=viewMatrix * modelMatrix * instMVMat;\n\n gl_Position = projMatrix * mvMatrix * vert;\n}\n",}; +const + render = op.inTrigger("Render"), + str = op.inString("Text", "cables"), + scale = op.inValueFloat("Scale", 1), + inFont = op.inString("Font", "Arial"), + align = op.inValueSelect("align", ["left", "center", "right"], "center"), + valign = op.inValueSelect("vertical align", ["Top", "Middle", "Bottom"], "Middle"), + lineHeight = op.inValueFloat("Line Height", 1), + letterSpace = op.inValueFloat("Letter Spacing"), + + tfilter = op.inSwitch("filter", ["nearest", "linear", "mipmap"], "mipmap"), + aniso = op.inSwitch("Anisotropic", [0, 1, 2, 4, 8, 16], 0), + + inMulTex = op.inTexture("Texture Color"), + inMulTexMask = op.inTexture("Texture Mask"), + next = op.outTrigger("Next"), + textureOut = op.outTexture("texture"), + outLines = op.outNumber("Total Lines", 0), + outWidth = op.outNumber("Width", 0), + loaded = op.outBoolNum("Font Available", 0); + +const cgl = op.patch.cgl; + +op.setPortGroup("Masking", [inMulTex, inMulTexMask]); + +const textureSize = 1024; +let fontLoaded = false; +let needUpdate = true; + +align.onChange = + str.onChange = + lineHeight.onChange = generateMeshLater; + +function generateMeshLater() +{ + needUpdate = true; +} + +let canvasid = null; +CABLES.OpTextureMeshCanvas = {}; +let valignMode = 0; + +const geom = null; +let mesh = null; + +let createMesh = true; +let createTexture = true; + +aniso.onChange = +tfilter.onChange = () => +{ + getFont().texture = null; + createTexture = true; +}; + +inMulTexMask.onChange = +inMulTex.onChange = function () +{ + shader.toggleDefine("DO_MULTEX", inMulTex.get()); + shader.toggleDefine("DO_MULTEX_MASK", inMulTexMask.get()); +}; + +textureOut.set(null); +inFont.onChange = function () +{ + createTexture = true; + createMesh = true; + checkFont(); +}; + +op.patch.on("fontLoaded", (fontName) => +{ + if (fontName == inFont.get()) + { + createTexture = true; + createMesh = true; + } +}); + +function checkFont() +{ + const oldFontLoaded = fontLoaded; + try + { + fontLoaded = document.fonts.check("20px \"" + inFont.get() + "\""); + } + catch (ex) + { + op.logError(ex); + } + + if (!oldFontLoaded && fontLoaded) + { + loaded.set(true); + createTexture = true; + createMesh = true; + } + + if (!fontLoaded) setTimeout(checkFont, 250); +} + +valign.onChange = function () +{ + if (valign.get() == "Middle")valignMode = 0; + else if (valign.get() == "Top")valignMode = 1; + else if (valign.get() == "Bottom")valignMode = 2; +}; + +function getFont() +{ + canvasid = "" + inFont.get(); + if (CABLES.OpTextureMeshCanvas.hasOwnProperty(canvasid)) + return CABLES.OpTextureMeshCanvas[canvasid]; + + const fontImage = document.createElement("canvas"); + fontImage.dataset.font = inFont.get(); + fontImage.id = "texturetext_" + CABLES.generateUUID(); + fontImage.style.display = "none"; + const body = document.getElementsByTagName("body")[0]; + body.appendChild(fontImage); + const _ctx = fontImage.getContext("2d"); + CABLES.OpTextureMeshCanvas[canvasid] = + { + "ctx": _ctx, + "canvas": fontImage, + "chars": {}, + "characters": "", + "fontSize": 320 + }; + return CABLES.OpTextureMeshCanvas[canvasid]; +} + +op.onDelete = function () +{ + if (canvasid && CABLES.OpTextureMeshCanvas[canvasid]) + CABLES.OpTextureMeshCanvas[canvasid].canvas.remove(); +}; + +const shader = new CGL.Shader(cgl, "TextMesh"); +shader.setSource(attachments.textmesh_vert, attachments.textmesh_frag); +const uniTex = new CGL.Uniform(shader, "t", "tex", 0); +const uniTexMul = new CGL.Uniform(shader, "t", "texMul", 1); +const uniTexMulMask = new CGL.Uniform(shader, "t", "texMulMask", 2); +const uniScale = new CGL.Uniform(shader, "f", "scale", scale); + +const + r = op.inValueSlider("r", 1), + g = op.inValueSlider("g", 1), + b = op.inValueSlider("b", 1), + a = op.inValueSlider("a", 1), + runiform = new CGL.Uniform(shader, "f", "r", r), + guniform = new CGL.Uniform(shader, "f", "g", g), + buniform = new CGL.Uniform(shader, "f", "b", b), + auniform = new CGL.Uniform(shader, "f", "a", a); +r.setUiAttribs({ "colorPick": true }); + +op.setPortGroup("Display", [scale, inFont]); +op.setPortGroup("Alignment", [align, valign]); +op.setPortGroup("Color", [r, g, b, a]); + +let height = 0; +const vec = vec3.create(); +let lastTextureChange = -1; +let disabled = false; + +render.onTriggered = function () +{ + if (needUpdate) + { + generateMesh(); + needUpdate = false; + } + const font = getFont(); + if (font.lastChange != lastTextureChange) + { + createMesh = true; + lastTextureChange = font.lastChange; + } + + if (createTexture) generateTexture(); + if (createMesh)generateMesh(); + + if (mesh && mesh.numInstances > 0) + { + cgl.pushBlendMode(CGL.BLEND_NORMAL, true); + cgl.pushShader(shader); + cgl.setTexture(0, textureOut.get().tex); + + const mulTex = inMulTex.get(); + if (mulTex)cgl.setTexture(1, mulTex.tex); + + const mulTexMask = inMulTexMask.get(); + if (mulTexMask)cgl.setTexture(2, mulTexMask.tex); + + if (valignMode === 2) vec3.set(vec, 0, height, 0); + else if (valignMode === 1) vec3.set(vec, 0, 0, 0); + else if (valignMode === 0) vec3.set(vec, 0, height / 2, 0); + + vec[1] -= lineHeight.get(); + cgl.pushModelMatrix(); + mat4.translate(cgl.mMatrix, cgl.mMatrix, vec); + if (!disabled)mesh.render(cgl.getShader()); + + cgl.popModelMatrix(); + + cgl.setTexture(0, null); + cgl.popShader(); + cgl.popBlendMode(); + } + + next.trigger(); +}; + +letterSpace.onChange = function () +{ + createMesh = true; +}; + +function generateMesh() +{ + const theString = String(str.get() + ""); + if (!textureOut.get()) return; + + const font = getFont(); + if (!font.geom) + { + font.geom = new CGL.Geometry("textmesh"); + + font.geom.vertices = [ + 1.0, 1.0, 0.0, + 0.0, 1.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 0.0, 0.0 + ]; + + font.geom.texCoords = new Float32Array([ + 1.0, 1.0, + 0.0, 1.0, + 1.0, 0.0, + 0.0, 0.0 + ]); + + font.geom.verticesIndices = [ + 0, 1, 2, + 2, 1, 3 + ]; + } + + if (!mesh)mesh = new CGL.Mesh(cgl, font.geom); + + const strings = (theString).split("\n"); + outLines.set(strings.length); + + const transformations = []; + const tcOffsets = [];// new Float32Array(str.get().length*2); + const tcSize = [];// new Float32Array(str.get().length*2); + const texPos = []; + let charCounter = 0; + createTexture = false; + const m = mat4.create(); + + let maxWidth = 0; + + for (let s = 0; s < strings.length; s++) + { + const txt = strings[s]; + const numChars = txt.length; + + let pos = 0; + let offX = 0; + let width = 0; + + for (let i = 0; i < numChars; i++) + { + const chStr = txt.substring(i, i + 1); + const char = font.chars[String(chStr)]; + if (char) + { + width += (char.texCoordWidth / char.texCoordHeight); + width += letterSpace.get(); + } + } + + width -= letterSpace.get(); + + height = 0; + + if (align.get() == "left") offX = 0; + else if (align.get() == "right") offX = width; + else if (align.get() == "center") offX = width / 2; + + height = (s + 1) * lineHeight.get(); + + for (let i = 0; i < numChars; i++) + { + const chStr = txt.substring(i, i + 1); + const char = font.chars[String(chStr)]; + + if (!char) + { + createTexture = true; + return; + } + else + { + texPos.push(pos / width * 0.99 + 0.005, (1.0 - (s / (strings.length - 1))) * 0.99 + 0.005); + tcOffsets.push(char.texCoordX, 1 - char.texCoordY - char.texCoordHeight); + tcSize.push(char.texCoordWidth, char.texCoordHeight); + + mat4.identity(m); + mat4.translate(m, m, [pos - offX, 0 - s * lineHeight.get(), 0]); + + pos += (char.texCoordWidth / char.texCoordHeight) + letterSpace.get(); + maxWidth = Math.max(maxWidth, pos - offX); + + transformations.push(Array.prototype.slice.call(m)); + + charCounter++; + } + } + } + + const transMats = [].concat.apply([], transformations); + + disabled = false; + if (transMats.length == 0)disabled = true; + + mesh.numInstances = transMats.length / 16; + + if (mesh.numInstances == 0) + { + disabled = true; + return; + } + + outWidth.set(maxWidth * scale.get()); + mesh.setAttribute("instMat", new Float32Array(transMats), 16, { "instanced": true }); + mesh.setAttribute("attrTexOffsets", new Float32Array(tcOffsets), 2, { "instanced": true }); + mesh.setAttribute("attrTexSize", new Float32Array(tcSize), 2, { "instanced": true }); + mesh.setAttribute("attrTexPos", new Float32Array(texPos), 2, { "instanced": true }); + + createMesh = false; + + if (createTexture) generateTexture(); +} + +function printChars(fontSize, simulate) +{ + const font = getFont(); + if (!simulate) font.chars = {}; + + const ctx = font.ctx; + + ctx.font = fontSize + "px " + inFont.get(); + ctx.textAlign = "left"; + + let posy = 0; + let posx = 0; + const lineHeight = fontSize * 1.4; + const result = + { + "fits": true + }; + + for (let i = 0; i < font.characters.length; i++) + { + const chStr = String(font.characters.substring(i, i + 1)); + const chWidth = (ctx.measureText(chStr).width); + + if (posx + chWidth >= textureSize) + { + posy += lineHeight + 2; + posx = 0; + } + + if (!simulate) + { + font.chars[chStr] = + { + "str": chStr, + "texCoordX": posx / textureSize, + "texCoordY": posy / textureSize, + "texCoordWidth": chWidth / textureSize, + "texCoordHeight": lineHeight / textureSize, + }; + + ctx.fillText(chStr, posx, posy + fontSize); + } + + posx += chWidth + 12; + } + + if (posy > textureSize - lineHeight) + { + result.fits = false; + } + + result.spaceLeft = textureSize - posy; + + return result; +} + +function generateTexture() +{ + let filter = CGL.Texture.FILTER_LINEAR; + if (tfilter.get() == "nearest") filter = CGL.Texture.FILTER_NEAREST; + if (tfilter.get() == "mipmap") filter = CGL.Texture.FILTER_MIPMAP; + + const font = getFont(); + let string = String(str.get()); + if (string == null || string == undefined)string = ""; + for (let i = 0; i < string.length; i++) + { + const ch = string.substring(i, i + 1); + if (font.characters.indexOf(ch) == -1) + { + font.characters += ch; + createTexture = true; + } + } + + const ctx = font.ctx; + font.canvas.width = font.canvas.height = textureSize; + + if (!font.texture) + font.texture = CGL.Texture.createFromImage(cgl, font.canvas, + { + "filter": filter, + "anisotropic": parseFloat(aniso.get()) + }); + + font.texture.setSize(textureSize, textureSize); + + ctx.fillStyle = "transparent"; + ctx.clearRect(0, 0, textureSize, textureSize); + ctx.fillStyle = "rgba(255,255,255,255)"; + + let fontSize = font.fontSize + 40; + let simu = printChars(fontSize, true); + + while (!simu.fits) + { + fontSize -= 5; + simu = printChars(fontSize, true); + } + + printChars(fontSize, false); + + ctx.restore(); + + font.texture.initTexture(font.canvas, filter); + font.texture.unpackAlpha = true; + textureOut.set(font.texture); + + font.lastChange = CABLES.now(); + + createMesh = true; + createTexture = false; +} + + +}; + +Ops.Gl.Meshes.TextMesh_v2.prototype = new CABLES.Op(); +CABLES.OPS["2390f6b3-2122-412e-8c8d-5c2f574e8bd1"]={f:Ops.Gl.Meshes.TextMesh_v2,objName:"Ops.Gl.Meshes.TextMesh_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Torus +// +// ************************************************************** + +Ops.Gl.Meshes.Torus = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + sides = op.inValue("sides", 32), + rings = op.inValue("rings", 32), + innerRadius = op.inValue("innerRadius", 0.5), + outerRadius = op.inValue("outerRadius", 1), + indraw = op.inBool("Draw", true), + trigger = op.outTrigger("trigger"), + geomOut = op.outObject("geometry"); + +const UP = vec3.fromValues(0, 1, 0), RIGHT = vec3.fromValues(1, 0, 0); +let tmpNormal = vec3.create(), tmpVec = vec3.create(); + +geomOut.ignoreValueSerialize = true; + +let cgl = op.patch.cgl; +let mesh = null; +let geom = null; +let j = 0, i = 0, idx = 0; +let needsUpdate = true; + +rings.onChange = +sides.onChange = +innerRadius.onChange = +outerRadius.onChange = function () +{ + needsUpdate = true; +}; + +render.onTriggered = function () +{ + if (needsUpdate) updateMesh(); + if (indraw.get() && mesh !== null) mesh.render(cgl.getShader()); + + trigger.trigger(); +}; + +function updateMesh() +{ + let nrings = Math.round(rings.get()); + let nsides = Math.round(sides.get()); + if (nrings < 2)nrings = 2; + if (nsides < 2)nsides = 2; + let r = innerRadius.get(); + let r2 = outerRadius.get(); + generateTorus(r, r2, nrings, nsides); + needsUpdate = false; +} + +function circleTable(n, halfCircle) +{ + let i; + /* Table size, the sign of n flips the circle direction */ + let size = Math.abs(n); + + /* Determine the angle between samples */ + let angle = (halfCircle ? 1 : 2) * Math.PI / n;// ( n === 0 ) ? 1 : n ; + + /* Allocate memory for n samples, plus duplicate of first entry at the end */ + let sint = []; + let cost = []; + + /* Compute cos and sin around the circle */ + sint[0] = 0.0; + cost[0] = 1.0; + + for (i = 1; i < size; i++) + { + sint[i] = Math.sin(angle * i); + cost[i] = Math.cos(angle * i); + } + + if (halfCircle) + { + sint[size] = 0.0; /* sin PI */ + cost[size] = -1.0; /* cos PI */ + } + else + { + /* Last sample is duplicate of the first (sin or cos of 2 PI) */ + sint[size] = sint[0]; + cost[size] = cost[0]; + } + return { "cost": cost, "sint": sint }; +} + +function generateTorus(iradius, oradius, nRings, nSides) +{ + let table1 = circleTable(nRings, false); + let table2 = circleTable(-nSides, false); + let t; + + geom = new CGL.Geometry("torus"); + geom.glPrimitive = cgl.gl.TRIANGLE_STRIP; + let tangents = []; + let biTangents = []; + let vertexNormals = []; + let tc = []; + + for (j = 0; j < nRings; j++) + { + for (i = 0; i < nSides; i++) + { + var offset = 3 * (j * nSides + i); + var offset2 = 2 * (j * nSides + i); + + geom.vertices[offset] = table1.cost[j] * (oradius + table2.cost[i] * iradius); + geom.vertices[offset + 1] = table1.sint[j] * (oradius + table2.cost[i] * iradius); + geom.vertices[offset + 2] = table2.sint[i] * iradius; + vertexNormals[offset] = tmpNormal[0] = table1.cost[j] * table2.cost[i]; + vertexNormals[offset + 1] = tmpNormal[1] = table1.sint[j] * table2.cost[i]; + vertexNormals[offset + 2] = tmpNormal[2] = table2.sint[i]; + + if (Math.abs(tmpNormal[1]) == 1) t = RIGHT; + else t = UP; + + vec3.cross(tmpVec, tmpNormal, t); + vec3.normalize(tmpVec, tmpVec); + tangents[offset] = tmpVec[0]; + tangents[offset + 1] = tmpVec[1]; + tangents[offset + 2] = tmpVec[2]; + vec3.cross(tmpVec, tmpVec, tmpNormal); + biTangents[offset] = tmpVec[0]; + biTangents[offset + 1] = tmpVec[1]; + biTangents[offset + 2] = tmpVec[2]; + + tc[offset2] = j / (nRings - 1); + tc[offset2 + 1] = i / (nSides - 1); + } + } + + for (i = 0, idx = 0; i < nSides; i++) + { + let ioff = 1; + if (i == nSides - 1) ioff = -i; + + for (j = 0; j < nRings; j++, idx += 2) + { + var offset = j * nSides + i; + geom.verticesIndices[idx] = offset; + geom.verticesIndices[idx + 1] = offset + ioff; + + tc[offset2] = j / (nRings + 1); + tc[offset2 + 1] = i / (nSides + 1); + } + + /* repeat first to close off shape */ + geom.verticesIndices[idx] = i; + geom.verticesIndices[idx + 1] = i + ioff; + + idx += 2; + } + + if (geom.biTangents.length == biTangents.length)geom.biTangents.set(biTangents); + else geom.biTangents = new Float32Array(biTangents); + + if (geom.tangents.length == tangents.length)geom.tangents.set(tangents); + else geom.tangents = new Float32Array(tangents); + + if (geom.vertexNormals.length == vertexNormals.length)geom.vertexNormals.set(vertexNormals); + else geom.vertexNormals = new Float32Array(vertexNormals); + + geom.setTexCoords(tc); + + geomOut.set(null); + geomOut.set(geom); + + if (!mesh)mesh = new CGL.Mesh(cgl, geom, cgl.gl.TRIANGLE_STRIP); + else mesh.setGeom(geom); +} + + +}; + +Ops.Gl.Meshes.Torus.prototype = new CABLES.Op(); +CABLES.OPS["d921e008-21b9-4cf5-84a2-4dedca34f0c8"]={f:Ops.Gl.Meshes.Torus,objName:"Ops.Gl.Meshes.Torus"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Triangle +// +// ************************************************************** + +Ops.Gl.Meshes.Triangle = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + sizeW = op.inValueFloat("width", 1), + sizeH = op.inValueFloat("height", 1), + draw = op.inValueBool("Draw", true), + geom = new CGL.Geometry("triangle"), + geomOut = op.outObject("geometry"); + +geomOut.ignoreValueSerialize = true; + +op.setPortGroup("Size", [sizeW, sizeH]); + +const cgl = op.patch.cgl; +let mesh = null; +sizeW.onChange = create; +sizeH.onChange = create; + +create(); + +op.preRender = create; + +render.onTriggered = function () +{ + if (draw.get())mesh.render(cgl.getShader()); + trigger.trigger(); +}; + +function create() +{ + geom.vertices = [ + 0.0, sizeH.get(), 0.0, + -sizeW.get(), -sizeH.get(), 0.0, + sizeW.get(), -sizeH.get(), 0.0 + ]; + + geom.vertexNormals = [ + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0, + 0.0, 0.0, 1.0 + ]; + geom.tangents = [ + 1, 0, 0, + 1, 0, 0, + 1, 0, 0 + ]; + geom.biTangents = [ + 0, 1, 0, + 0, 1, 0, + 0, 1, 0 + ]; + + geom.texCoords = [ + 0.5, 0.0, + 1.0, 1.0, + 0.0, 1.0, + ]; + + geom.verticesIndices = [ + 0, 1, 2 + ]; + + mesh = new CGL.Mesh(cgl, geom); + geomOut.set(null); + geomOut.set(geom); +} + + +}; + +Ops.Gl.Meshes.Triangle.prototype = new CABLES.Op(); +CABLES.OPS["331bc9dc-d44c-43bd-be18-a2673fba124e"]={f:Ops.Gl.Meshes.Triangle,objName:"Ops.Gl.Meshes.Triangle"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.TriangleArray_v2 +// +// ************************************************************** + +Ops.Gl.Meshes.TriangleArray_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Render"), + inArr = op.inArray("Points", 3), + inVertCols = op.inArray("Vertex Colors", 4), + inTexCoords = op.inArray("TexCoords", 2), + inFlat = op.inValueBool("Flat", false), + inRenderMesh = op.inBool("Render Mesh", true), + next = op.outTrigger("Next"), + geomOut = op.outObject("Geometry"); + +let geom = new CGL.Geometry("triangle array"); + +let mesh = null; +let verts = null; +let needsUpdate = true; +const cgl = op.patch.cgl; + +op.toWorkPortsNeedToBeLinked(inArr, render); + +inArr.onChange = +inVertCols.onChange = +inTexCoords.onChange = () => +{ + needsUpdate = true; +}; +inFlat.onChange = () => +{ + geom = new CGL.Geometry("triangle array"); + update(); +}; + +function update() +{ + op.setUiError("coordsMismatch", null); + op.setUiError("colorsMismatch", null); + + verts = inArr.get(); + if (!verts) return; + + let num = verts.length / 3; + num = Math.abs(Math.floor(num)); + + let tc = []; + const texCoords = inTexCoords.get(); + if (texCoords) + { + if (texCoords.length !== (num * 2)) + { + op.setUiError("coordsMismatch", "Coords array does not have the correct length! (should be " + num * 2 + ")"); + } + tc = texCoords; + } + else + { + for (let i = 0; i < verts.length / 3; i++) + { + tc.push(0, 0, 0, 1, 1, 1); + } + } + + geom.vertices = verts; + geom.texCoords = tc; + + mesh = new CGL.Mesh(cgl, geom); + + const vertexColors = inVertCols.get(); + if (vertexColors) + { + if (vertexColors.length !== (num * 4)) + { + op.setUiError("colorsMismatch", "Color array does not have the correct length! (should be " + num * 4 + ")"); + return; + } + geom.vertexColors = vertexColors; + } + + if (!inFlat.get()) index(verts, geom); + else + { + geom.vertices = verts; + } + + geom.calculateNormals(); + geomOut.set(null); + geomOut.set(geom); + needsUpdate = false; +} + +render.onTriggered = function () +{ + if (needsUpdate)update(); + if (mesh && verts && inRenderMesh.get()) mesh.render(cgl.getShader()); + next.trigger(); +}; + +function index(vertsToIndex, geometry) +{ + const num = vertsToIndex.length / 3; + const arr = []; + const ind = []; + let delta = 0.0001; + + for (let i = 0; i < num; i++) + { + let found = false; + + for (let j = 0; j < arr.length; j += 3) + { + if ( + arr[j] < vertsToIndex[i * 3] + delta && + arr[j + 1] < vertsToIndex[i * 3 + 1] + delta && + arr[j + 2] < vertsToIndex[i * 3 + 2] + delta && + arr[j] > vertsToIndex[i * 3] - delta && + arr[j + 1] > vertsToIndex[i * 3 + 1] - delta && + arr[j + 2] > vertsToIndex[i * 3 + 2] - delta) + { + ind.push(j / 3); + found = true; + } + } + + if (!found) + { + arr.push(vertsToIndex[i * 3]); + arr.push(vertsToIndex[i * 3 + 1]); + arr.push(vertsToIndex[i * 3 + 2]); + ind.push(arr.length / 3 - 1); + } + } + + geometry.verticesIndices = ind; + geometry.vertices = arr; +} + + +}; + +Ops.Gl.Meshes.TriangleArray_v2.prototype = new CABLES.Op(); +CABLES.OPS["ee4d9fa8-996d-44a4-80a0-4f14bbd85502"]={f:Ops.Gl.Meshes.TriangleArray_v2,objName:"Ops.Gl.Meshes.TriangleArray_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.TriangleSphere +// +// ************************************************************** + +Ops.Gl.Meshes.TriangleSphere = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// http://paulbourke.net/geometry/circlesphere/ + +// http://paulbourke.net/geometry/circlesphere/csource3.c +//! !!! http://paulbourke.net/geometry/circlesphere/csource2.c + +const render = op.inTrigger("render"); +const next = op.outTrigger("next"); + +const inIterations = op.inValue("Iterations", 4); +const geomOut = op.outObject("Geometry"); + +const flat = op.inValueBool("Flat", false); +const inDraw = op.inValueBool("Draw", true); + +let verts = []; +let geom = null; +let mesh = null; +const cgl = op.patch.cgl; + +inIterations.onChange = generate; + +generate(); + +flat.onChange = generate; + +render.onTriggered = function () +{ + // cgl.gl.cullFace(cgl.gl.BACK); + // cgl.gl.enable(cgl.gl.CULL_FACE); + + if (inDraw.get() && mesh) mesh.render(cgl.getShader()); + next.trigger(); + + // cgl.gl.disable(cgl.gl.CULL_FACE); +}; + +function normalize(v) +{ + const len = Math.sqrt((v[0] * v[0]) + (v[1] * v[1]) + (v[2] * v[2])); + v[0] /= len; + v[1] /= len; + v[2] /= len; + return v; +} + +function index(verts, geom) +{ + const num = verts.length / 3; + const arr = []; + const ind = [], tc = []; + + for (let i = 0; i < num; i++) + { + let found = false; + + for (let j = 0; j < arr.length; j += 3) + { + if ( + arr[j + 0] == verts[i * 3 + 0] && + arr[j + 1] == verts[i * 3 + 1] && + arr[j + 2] == verts[i * 3 + 2]) + { + ind.push(j / 3); + found = true; + continue; + } + } + + if (!found) + { + arr.push(verts[i * 3 + 0]); + arr.push(verts[i * 3 + 1]); + arr.push(verts[i * 3 + 2]); + ind.push(arr.length / 3 - 1); + + tc.push(verts[i * 3 + 0]); + tc.push(verts[i * 3 + 1]); + } + } + + geom.verticesIndices = ind; + geom.vertices = arr; + geom.texCoords = tc; +} + +function generate() +{ + let iterations = Math.max(1, Math.floor(inIterations.get())); + iterations = Math.min(6, iterations); + const f = []; + let i, it; + const p = [[0, 0, 1], [0, 0, -1], [-1, -1, 0], [1, -1, 0], [1, 1, 0], [-1, 1, 0]]; + + let nt = 0, ntold; + + /* Create the level 0 object */ + const a = 1 / Math.sqrt(2.0); + for (i = 0; i < 6; i++) + { + p[i][0] *= a; + p[i][1] *= a; + } + + for (i = 0; i < 8; i++) + { + f[i] = [[], [], []]; + } + f[0][0] = p[0]; f[0][1] = p[3]; f[0][2] = p[4]; + f[1][0] = p[0]; f[1][1] = p[4]; f[1][2] = p[5]; + f[2][0] = p[0]; f[2][1] = p[5]; f[2][2] = p[2]; + f[3][0] = p[0]; f[3][1] = p[2]; f[3][2] = p[3]; + f[4][0] = p[1]; f[4][1] = p[4]; f[4][2] = p[3]; + f[5][0] = p[1]; f[5][1] = p[5]; f[5][2] = p[4]; + f[6][0] = p[1]; f[6][1] = p[2]; f[6][2] = p[5]; + f[7][0] = p[1]; f[7][1] = p[3]; f[7][2] = p[2]; + nt = 8; + + if (iterations > 1) + { + /* Bisect each edge and move to the surface of a unit sphere */ + for (it = 0; it < iterations; it++) + { + ntold = nt; + for (i = 0; i < ntold; i++) + { + const pa = [], pb = [], pc = []; + pa[0] = (f[i][0][0] + f[i][1][0]) / 2; + pa[1] = (f[i][0][1] + f[i][1][1]) / 2; + pa[2] = (f[i][0][2] + f[i][1][2]) / 2; + pb[0] = (f[i][1][0] + f[i][2][0]) / 2; + pb[1] = (f[i][1][1] + f[i][2][1]) / 2; + pb[2] = (f[i][1][2] + f[i][2][2]) / 2; + pc[0] = (f[i][2][0] + f[i][0][0]) / 2; + pc[1] = (f[i][2][1] + f[i][0][1]) / 2; + pc[2] = (f[i][2][2] + f[i][0][2]) / 2; + + normalize(pa); + normalize(pb); + normalize(pc); + + f.push([]); + f[nt][0] = f[i][0]; f[nt][1] = pa; f[nt][2] = pc; nt++; + f.push([]); + f[nt][0] = pa; f[nt][1] = f[i][1]; f[nt][2] = pb; nt++; + f.push([]); + f[nt][0] = pb; f[nt][1] = f[i][2]; f[nt][2] = pc; nt++; + + f[i][0] = pa; + f[i][1] = pb; + f[i][2] = pc; + } + } + } + + if (!geom)geom = new CGL.Geometry(op.name); + geom.clear(); + + verts = f.flat(Infinity); + + if (!flat.get()) index(verts, geom); + else + { + geom.unIndex(); + const indices = []; + for (i = 0; i < verts.length / 3; i++)indices.push(i); + geom.vertices = verts; + geom.verticesIndices = indices; + } + + geom.calculateNormals({ "forceZUp": false }); + geom.calcTangentsBitangents(); + + mesh = new CGL.Mesh(cgl, geom); + geomOut.set(null); + geomOut.set(geom); +} + + +}; + +Ops.Gl.Meshes.TriangleSphere.prototype = new CABLES.Op(); +CABLES.OPS["ad0e8831-9554-46b3-ac03-c5c166921eda"]={f:Ops.Gl.Meshes.TriangleSphere,objName:"Ops.Gl.Meshes.TriangleSphere"}; + + + + +// ************************************************************** +// +// Ops.Gl.NormalizeScreenCoordinates +// +// ************************************************************** + +Ops.Gl.NormalizeScreenCoordinates = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inX = op.inValue("X"), + inY = op.inValue("Y"), + outX = op.outNumber("Result X"), + outY = op.outNumber("Result Y"), + range = op.inValueBool("-1 to 1"); + +inX.onChange = + inY.onChange = + range.onChange = update; + +function update() +{ + let x = inX.get() / op.patch.cgl.canvas.width; + let y = inY.get() / op.patch.cgl.canvas.height; + + outX.set(x); + outY.set(y); + + if (range.get()) + { + x = x * 2 - 1; + y = y * 2 - 1; + } + + outX.set(x); + outY.set(y); +} + + +}; + +Ops.Gl.NormalizeScreenCoordinates.prototype = new CABLES.Op(); +CABLES.OPS["84d4f2a6-5ab7-4c97-85e0-2985bfcba70d"]={f:Ops.Gl.NormalizeScreenCoordinates,objName:"Ops.Gl.NormalizeScreenCoordinates"}; + + + + +// ************************************************************** +// +// Ops.Gl.OrTexture +// +// ************************************************************** + +Ops.Gl.OrTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + str0 = op.inTexture("Texture 1"), + str1 = op.inTexture("Texture 2"), + str2 = op.inTexture("Texture 3"), + str3 = op.inTexture("Texture 4"), + str4 = op.inTexture("Texture 5"), + str5 = op.inTexture("Texture 6"), + str6 = op.inTexture("Texture 7"), + str7 = op.inTexture("Texture 8"), + result = op.outTexture("Result"); + +str0.onChange = + str1.onChange = + str2.onChange = + str3.onChange = + str4.onChange = + str5.onChange = + str6.onChange = + str7.onChange = exec; + +const emptyTex = CGL.Texture.getEmptyTexture(op.patch.cgl); +const defaultTex = CGL.Texture.getTempTexture(op.patch.cgl); + +function exec() +{ + if (str0.get() && str0.get() != emptyTex && str0.get() != defaultTex) result.set(str0.get()); + else if (str1.get() && str1.get() != emptyTex && str1.get() != defaultTex) result.set(str1.get()); + else if (str2.get() && str2.get() != emptyTex && str2.get() != defaultTex) result.set(str2.get()); + else if (str3.get() && str3.get() != emptyTex && str3.get() != defaultTex) result.set(str3.get()); + else if (str4.get() && str4.get() != emptyTex && str4.get() != defaultTex) result.set(str4.get()); + else if (str5.get() && str5.get() != emptyTex && str5.get() != defaultTex) result.set(str5.get()); + else if (str6.get() && str6.get() != emptyTex && str6.get() != defaultTex) result.set(str6.get()); + else if (str7.get() && str7.get() != emptyTex && str7.get() != defaultTex) result.set(str7.get()); + else result.set(emptyTex); +} + + +}; + +Ops.Gl.OrTexture.prototype = new CABLES.Op(); +CABLES.OPS["9a383587-272d-429b-95a3-5c9b6007f8ea"]={f:Ops.Gl.OrTexture,objName:"Ops.Gl.OrTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.Orthogonal_v2 +// +// ************************************************************** + +Ops.Gl.Orthogonal_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + bounds = op.inValue("bounds", 2), + fixAxis = op.inSwitch("Axis", ["X", "Y", "None"], "X"), + zNear = op.inValue("frustum near", -100), + zFar = op.inValue("frustum far", 100), + trigger = op.outTrigger("trigger"), + outRatio = op.outNumber("Ratio"), + outWidth = op.outNumber("Width"), + outHeight = op.outNumber("Height"); +const cgl = op.patch.cgl; + +render.onTriggered = function () +{ + const vp = cgl.getViewPort(); + + if (fixAxis.get() == "X") + { + const ratio = vp[3] / vp[2]; + + cgl.pushPMatrix(); + mat4.ortho( + cgl.pMatrix, + -bounds.get(), + bounds.get(), + -bounds.get() * ratio, + bounds.get() * ratio, + parseFloat(zNear.get()), + parseFloat(zFar.get()) + ); + + outWidth.set(bounds.get() * 2); + outHeight.set(bounds.get() * ratio * 2); + outRatio.set(ratio); + } + else if (fixAxis.get() == "Y") + { + const ratio = vp[2] / vp[3]; + + cgl.pushPMatrix(); + mat4.ortho( + cgl.pMatrix, + -bounds.get() * ratio, + bounds.get() * ratio, + -bounds.get(), + bounds.get(), + parseFloat(zNear.get()), + parseFloat(zFar.get()) + ); + + outWidth.set(bounds.get() * ratio * 2); + outHeight.set(bounds.get() * 2); + outRatio.set(ratio); + } + else + { + cgl.pushPMatrix(); + mat4.ortho( + cgl.pMatrix, + -bounds.get(), + bounds.get(), + -bounds.get(), + bounds.get(), + parseFloat(zNear.get()), + parseFloat(zFar.get()) + ); + + outWidth.set(bounds.get() * 2); + outHeight.set(bounds.get() * 2); + outRatio.set(1); + } + + trigger.trigger(); + cgl.popPMatrix(); +}; + + +}; + +Ops.Gl.Orthogonal_v2.prototype = new CABLES.Op(); +CABLES.OPS["b9235490-eaf2-4960-b1be-4279a4051ec6"]={f:Ops.Gl.Orthogonal_v2,objName:"Ops.Gl.Orthogonal_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.OverwriteViewportSize +// +// ************************************************************** + +Ops.Gl.OverwriteViewportSize = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Exec"), + next = op.outTrigger("next"), + w = op.inValueInt("Width", 1920), + h = op.inValueInt("Height", 1080); + +render.onTriggered = doit; + +let oldFunc = null; +let cgl = op.patch.cgl; +let vp = [0, 0, 0, 0]; + +function newGetViewPort() +{ + return vp; +} + +function doit() +{ + let oldWidth = cgl.getViewPort()[2]; + let oldHeight = cgl.getViewPort()[3]; + + // cgl.forceViewPortSize(0,0,w.get(),h.get()); + + cgl.setViewPort(0, 0, w.get(), h.get()); + + next.trigger(); + + cgl.setViewPort(0, 0, oldWidth, oldHeight); +} + + +}; + +Ops.Gl.OverwriteViewportSize.prototype = new CABLES.Op(); +CABLES.OPS["20e370c7-d6e9-4e29-acab-1dd2eb4b921f"]={f:Ops.Gl.OverwriteViewportSize,objName:"Ops.Gl.OverwriteViewportSize"}; + + + + +// ************************************************************** +// +// Ops.Gl.Pbr.PbrEnvironmentLight +// +// ************************************************************** + +Ops.Gl.Pbr.PbrEnvironmentLight = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"IBLLUT_frag":"precision highp float;\nprecision highp int;\nprecision highp sampler2D;\n\n#ifndef WEBGL1\n#define NUM_SAMPLES 1024u\n#else\n#define NUM_SAMPLES 1024\n#endif\n#define PI 3.14159265358\n\nIN vec3 P;\n{{MODULES_HEAD}}\n\n// from https://github.com/BabylonJS/Babylon.js/blob/5e6321d887637877d8b28b417410abbbeb651c6e/src/Shaders/ShadersInclude/hdrFilteringFunctions.fx\n// modified to use different syntax for a number of variables\n#if NUM_SAMPLES > 0\n #ifndef WEBGL1\n // https://learnopengl.com/PBR/IBL/Specular-IBL\n // Hammersley\n float radicalInverse_VdC(uint bits)\n {\n bits = (bits << 16u) | (bits >> 16u);\n bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);\n bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);\n bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);\n bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);\n return float(bits) * 2.3283064365386963e-10; // / 0x100000000\n }\n\n vec2 hammersley(uint i, uint N)\n {\n return vec2(float(i)/float(N), radicalInverse_VdC(i));\n }\n #else\n float vanDerCorpus(int n, int base)\n {\n float invBase = 1.0 / float(base);\n float denom = 1.0;\n float result = 0.0;\n\n for(int i = 0; i < 32; ++i)\n {\n if(n > 0)\n {\n denom = mod(float(n), 2.0);\n result += denom * invBase;\n invBase = invBase / 2.0;\n n = int(float(n) / 2.0);\n }\n }\n\n return result;\n }\n\n vec2 hammersley(int i, int N)\n {\n return vec2(float(i)/float(N), vanDerCorpus(i, 2));\n }\n #endif\n\n\t// from https://github.com/BabylonJS/Babylon.js/blob/5e6321d887637877d8b28b417410abbbeb651c6e/src/Shaders/ShadersInclude/importanceSampling.fx\n\tvec3 hemisphereImportanceSampleDggx(vec2 u, float a) {\n\t\t// pdf = D(a) * cosTheta\n\t\tfloat phi = 2. * PI * u.x;\n\n\t\t// NOTE: (aa-1) == (a-1)(a+1) produces better fp accuracy\n\t\tfloat cosTheta2 = (1. - u.y) / (1. + (a + 1.) * ((a - 1.) * u.y));\n\t\tfloat cosTheta = sqrt(cosTheta2);\n\t\tfloat sinTheta = sqrt(1. - cosTheta2);\n\n\t\treturn vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);\n\t}\n\n\t// from https://google.github.io/filament/Filament.md.html#toc9.5\n\t// modified to use different syntax for a number of variables\n const float NUM_SAMPLES_FLOAT = float(NUM_SAMPLES);\n const float NUM_SAMPLES_FLOAT_INVERSED = 1. / NUM_SAMPLES_FLOAT;\n const float NUM_SAMPLES_FLOAT_INVERSED4 = 4. / NUM_SAMPLES_FLOAT;\n\n float Visibility(float NdotV, float NdotL, float alphaG)\n {\n // from https://github.com/BabylonJS/Babylon.js/blob/5e6321d887637877d8b28b417410abbbeb651c6e/src/Shaders/ShadersInclude/pbrBRDFFunctions.fx\n #ifdef WEBGL1\n // Appply simplification as all squared root terms are below 1 and squared\n float GGXV = NdotL * (NdotV * (1.0 - alphaG) + alphaG);\n float GGXL = NdotV * (NdotL * (1.0 - alphaG) + alphaG);\n return 0.5 / (GGXV + GGXL);\n #else\n float a2 = alphaG * alphaG;\n float GGXV = NdotL * sqrt(NdotV * (NdotV - a2 * NdotV) + a2);\n float GGXL = NdotV * sqrt(NdotL * (NdotL - a2 * NdotL) + a2);\n return 0.5 / (GGXV + GGXL);\n #endif\n }\n\n\tvoid main()\n\t{\n\t // actual implementation (not documentation) here: https://github.com/google/filament/blob/94ff2ea6b1e39d909e9066459f2ce8c2942eb876/libs/ibl/src/CubemapIBL.cpp\n\t\t{{MODULE_BEGIN_FRAG}}\n\t\tfloat NoV = P.x;\n\t\tfloat a = P.y;\n\n\t\tvec3 V;\n\t\tV.x = sqrt(1.0 - NoV*NoV);\n\t\tV.y = 0.0;\n\t\tV.z = NoV;\n\n\t\tvec2 r = vec2(0.0);\n\n #ifndef WEBGL1\n for(uint i = 0u; i < NUM_SAMPLES; i++)\n #else\n for(int i = 0; i < NUM_SAMPLES; i++)\n #endif\n {\n\t\t\tvec2 Xi = hammersley(i, NUM_SAMPLES);\n\t\t\tvec3 H = hemisphereImportanceSampleDggx(Xi, a);\n\t\t\tvec3 L = 2.0 * dot(V, H) * H - V;\n\n\t\t\tfloat VoH = clamp(dot(V, H), 0.0, 1.0);\n\t\t\tfloat NoL = clamp(L.z, 0.0, 1.0);\n\t\t\tfloat NoH = clamp(H.z, 0.0, 1.0);\n\n\t\t\tif (NoL > 0.0) {\n\t\t\t\tfloat Gv = Visibility(NoV, NoL, a) * NoL * (VoH / NoH);\n\t\t\t\tfloat Fc = pow(1.0 - VoH, 5.0);\n\n\t\t\t\t// modified for multiscattering https://google.github.io/filament/Filament.md.html#toc5.3.4.7\n\t\t\t r.x += Gv * Fc;\n\t\t\t\tr.y += Gv;\n\t\t\t}\n\t\t}\n\t\tr *= NUM_SAMPLES_FLOAT_INVERSED4;\n\n\t\t{{MODULE_COLOR}}\n\t\toutColor = vec4(r.x, r.y, 0.0, 1.0);\n\t}\n#endif\n","IBLLUT_vert":"precision highp float;\nprecision highp int;\nprecision highp sampler2D;\n\n{{MODULES_HEAD}}\nIN vec3 vPosition;\nOUT vec3 P;\nUNI mat4 projMatrix;\nUNI mat4 viewMatrix;\nUNI mat4 modelMatrix;\n\nvoid main()\n{\n vec4 pos = vec4(vPosition, 1.0);\n mat4 mMatrix = modelMatrix;\n\n {{MODULE_VERTEX_POSITION}}\n\n gl_Position = pos;\n\n P = (vPosition + 1.0) * 0.5;\n}\n","irradiance_frag":"precision highp float;\nprecision highp int;\nprecision highp sampler2D;\n\n\n// from https://github.com/BabylonJS/Babylon.js/blob/5e6321d887637877d8b28b417410abbbeb651c6e/src/Shaders/ShadersInclude/hdrFilteringFunctions.fx\n// modified to use different syntax for a number of variables, equirectangular projection and rgbe encoding\n{{MODULES_HEAD}}\n#ifndef WEBGL1\n#define NUM_SAMPLES 2048u\n#else\n#define NUM_SAMPLES 2048\n#endif\n#define PI 3.14159265358\n#define PI_TWO 2.*PI\n#define RECIPROCAL_PI 1./PI\n#define RECIPROCAL_PI2 RECIPROCAL_PI/2.\n\n\n#ifdef WEBGL1\n #ifdef GL_EXT_shader_texture_lod\n #define textureLod texture2DLodEXT\n #endif\n#endif\n#define SAMPLETEX textureLod\n\n// set by cables\nUNI vec3 camPos;\n\nIN vec3 FragPos;\nUNI float rotation;\nUNI vec2 filteringInfo;\nUNI sampler2D EquiCubemap;\n\nvec2 SampleSphericalMap(vec3 direction, float rotation)\n{\n #ifndef WEBGL1\n vec3 newDirection = normalize(direction);\n\t\tvec2 sampleUV;\n\t\tsampleUV.x = -1. * (atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5);\n\t\tsampleUV.y = asin( clamp(direction.y, -1., 1.) ) * RECIPROCAL_PI + 0.5;\n #endif\n\n #ifdef WEBGL1\n vec3 newDirection = normalize(direction);\n\t\tvec2 sampleUV = vec2(atan(newDirection.z, newDirection.x), asin(newDirection.y+1e-6));\n sampleUV *= vec2(-0.1591, 0.3183);\n sampleUV += 0.5;\n #endif\n sampleUV.x += rotation;\n return sampleUV * vec2(-1.,1.);\n}\n\n// https://community.khronos.org/t/addition-of-two-hdr-rgbe-values/55669\nvec4 EncodeRGBE8(vec3 rgb)\n{\n vec4 vEncoded;\n float maxComponent = max(max(rgb.r, rgb.g), rgb.b);\n float fExp = ceil(log2(maxComponent));\n vEncoded.rgb = rgb / exp2(fExp);\n vEncoded.a = (fExp + 128.0) / 255.0;\n return vEncoded;\n}\n// https://enkimute.github.io/hdrpng.js/\nvec3 DecodeRGBE8(vec4 rgbe)\n{\n vec3 vDecoded = rgbe.rgb * pow(2.0, rgbe.a * 255.0 - 128.0);\n return vDecoded;\n}\n\n// from https://github.com/BabylonJS/Babylon.js/blob/5e6321d887637877d8b28b417410abbbeb651c6e/src/Shaders/ShadersInclude/importanceSampling.fx\nvec3 hemisphereCosSample(vec2 u) {\n // pdf = cosTheta / M_PI;\n float phi = 2. * PI * u.x;\n\n float cosTheta2 = 1. - u.y;\n float cosTheta = sqrt(cosTheta2);\n float sinTheta = sqrt(1. - cosTheta2);\n\n return vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);\n}\n\n#ifndef WEBGL1\n // https://learnopengl.com/PBR/IBL/Specular-IBL\n // Hammersley\n float radicalInverse_VdC(uint bits)\n {\n bits = (bits << 16u) | (bits >> 16u);\n bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);\n bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);\n bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);\n bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);\n return float(bits) * 2.3283064365386963e-10; // / 0x100000000\n }\n\n vec2 hammersley(uint i, uint N)\n {\n return vec2(float(i)/float(N), radicalInverse_VdC(i));\n }\n#else\n float vanDerCorpus(int n, int base)\n {\n float invBase = 1.0 / float(base);\n float denom = 1.0;\n float result = 0.0;\n\n for(int i = 0; i < 32; ++i)\n {\n if(n > 0)\n {\n denom = mod(float(n), 2.0);\n result += denom * invBase;\n invBase = invBase / 2.0;\n n = int(float(n) / 2.0);\n }\n }\n\n return result;\n }\n\n vec2 hammersley(int i, int N)\n {\n return vec2(float(i)/float(N), vanDerCorpus(i, 2));\n }\n#endif\n\n// from https://github.com/google/filament/blob/main/shaders/src/light_indirect.fs\nfloat prefilteredImportanceSampling(float ipdf, float omegaP)\n{\n // See: \"Real-time Shading with Filtered Importance Sampling\", Jaroslav Krivanek\n // Prefiltering doesn't work with anisotropy\n const float numSamples = float(NUM_SAMPLES);\n const float invNumSamples = 1.0 / float(numSamples);\n const float K = 4.0;\n float omegaS = invNumSamples * ipdf;\n float mipLevel = log2(K * omegaS / omegaP) * 0.5; // log4\n return mipLevel;\n}\n\nconst float NUM_SAMPLES_FLOAT = float(NUM_SAMPLES);\nconst float NUM_SAMPLES_FLOAT_INVERSED = 1. / NUM_SAMPLES_FLOAT;\n\nconst float K = 4.;\n\nvoid main()\n{\n {{MODULE_BEGIN_FRAG}}\n vec4 col = vec4(0.0, 0.0, 0.0, 0.0);\n\n vec3 n = normalize(FragPos);\n vec3 tangent = normalize(cross(vec3(0.0, 0.0, 1.0), n));\n vec3 bitangent = cross(n, tangent);\n mat3 tbn = mat3(tangent, bitangent, n);\n\n float maxLevel = filteringInfo.y;\n float dim0 = filteringInfo.x;\n float omegaP = (4. * PI) / (6. * dim0 * dim0);\n\n #ifndef WEBGL1\n for(uint i = 0u; i < NUM_SAMPLES; ++i)\n #else\n for(int i = 0; i < NUM_SAMPLES; ++i)\n #endif\n {\n vec2 Xi = hammersley(i, NUM_SAMPLES);\n vec3 Ls = hemisphereCosSample(Xi);\n\n Ls = normalize(Ls);\n\n vec3 Ns = vec3(0., 0., 1.);\n\n float NoL = dot(Ns, Ls);\n\n if (NoL > 0.) {\n float pdf_inversed = PI / NoL;\n\n float omegaS = NUM_SAMPLES_FLOAT_INVERSED * pdf_inversed;\n // from https://github.com/google/filament/blob/main/shaders/src/light_indirect.fs\n float l = log2(K * omegaS / omegaP) * 0.5;\n float mipLevel = clamp(l + 1.0, 0.0, maxLevel);\n\n #ifndef DONT_USE_RGBE_CUBEMAPS\n vec3 c = DecodeRGBE8(SAMPLETEX(EquiCubemap, SampleSphericalMap(tbn * Ls, rotation), mipLevel)).rgb;\n #else\n vec3 c = SAMPLETEX(EquiCubemap, SampleSphericalMap(tbn * Ls, rotation), mipLevel).rgb;\n #endif\n col.rgb += c;\n }\n }\n\n col = EncodeRGBE8(col.rgb * PI * NUM_SAMPLES_FLOAT_INVERSED);\n\n {{MODULE_COLOR}}\n outColor = col;\n}\n","irradiance_vert":"precision highp float;\nprecision highp int;\nprecision highp sampler2D;\n\n\n{{MODULES_HEAD}}\nIN vec3 vPosition;\nIN float attrVertIndex;\n\nOUT vec3 FragPos;\nUNI mat4 projMatrix;\nUNI mat4 viewMatrix;\nUNI mat4 modelMatrix;\n\n\nvoid main()\n{\n FragPos = vPosition;\n\n {{MODULE_VERTEX_POSITION}}\n gl_Position = projMatrix * viewMatrix * modelMatrix * vec4(vPosition, 1.0);\n gl_Position = gl_Position.xyww;\n}\n","prefiltering_frag":"precision highp float;\nprecision highp int;\nprecision highp sampler2D;\n\n\n// from https://github.com/BabylonJS/Babylon.js/blob/5e6321d887637877d8b28b417410abbbeb651c6e/src/Shaders/ShadersInclude/hdrFilteringFunctions.fx\n// modified to use different syntax for a number of variables, equirectangular projection and rgbe encoding\n{{MODULES_HEAD}}\n#ifndef WEBGL1\n#define NUM_SAMPLES 2048u\n#else\n#define NUM_SAMPLES 2048\n#endif\n#define PI 3.14159265358\n#define PI_TWO 2.*PI\n#define RECIPROCAL_PI 1./PI\n#define RECIPROCAL_PI2 RECIPROCAL_PI/2.\n#define MINIMUMVARIANCE 0.0005\n\n\n#ifdef WEBGL1\n #ifdef GL_EXT_shader_texture_lod\n #define textureLod texture2DLodEXT\n #endif\n#endif\n#define SAMPLETEX textureLod\n\nIN vec3 FragPos;\nUNI float roughness;\nUNI float rotation;\nUNI vec2 filteringInfo;\nUNI sampler2D EquiCubemap;\n\nvec2 SampleSphericalMap(vec3 direction, float rotation)\n{\n #ifndef WEBGL1\n vec3 newDirection = normalize(direction);\n\t\tvec2 sampleUV;\n\t\tsampleUV.x = -1. * (atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5);\n\t\tsampleUV.y = asin( clamp(direction.y, -1., 1.) ) * RECIPROCAL_PI + 0.5;\n #endif\n\n #ifdef WEBGL1\n vec3 newDirection = normalize(direction);\n\t\tvec2 sampleUV = vec2(atan(newDirection.z, newDirection.x), asin(newDirection.y+1e-6));\n sampleUV *= vec2(-0.1591, 0.3183);\n sampleUV += 0.5;\n #endif\n sampleUV.x += rotation;\n return sampleUV * vec2(-1.,1.);\n}\n\n// https://community.khronos.org/t/addition-of-two-hdr-rgbe-values/55669\nvec4 EncodeRGBE8(vec3 rgb)\n{\n vec4 vEncoded;\n float maxComponent = max(max(rgb.r, rgb.g), rgb.b);\n float fExp = ceil(log2(maxComponent));\n vEncoded.rgb = rgb / exp2(fExp);\n vEncoded.a = (fExp + 128.0) / 255.0;\n return vEncoded;\n}\n// https://enkimute.github.io/hdrpng.js/\nvec3 DecodeRGBE8(vec4 rgbe)\n{\n vec3 vDecoded = rgbe.rgb * pow(2.0, rgbe.a * 255.0-128.0);\n return vDecoded;\n}\n\n// from https://github.com/BabylonJS/Babylon.js/blob/5e6321d887637877d8b28b417410abbbeb651c6e/src/Shaders/ShadersInclude/importanceSampling.fx\nvec3 hemisphereImportanceSampleDggx(vec2 u, float a) {\n // pdf = D(a) * cosTheta\n float phi = 2. * PI * u.x;\n\n // NOTE: (aa-1) == (a-1)(a+1) produces better fp accuracy\n float cosTheta2 = (1. - u.y) / (1. + (a + 1.) * ((a - 1.) * u.y));\n float cosTheta = sqrt(cosTheta2);\n float sinTheta = sqrt(1. - cosTheta2);\n\n return vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);\n}\n\n// from https://github.com/BabylonJS/Babylon.js/blob/5e6321d887637877d8b28b417410abbbeb651c6e/src/Shaders/ShadersInclude/pbrBRDFFunctions.fx\nfloat normalDistributionFunction_TrowbridgeReitzGGX(float NdotH, float alphaG)\n{\n // Note: alphaG is average slope (gradient) of the normals in slope-space.\n // It is also the (trigonometric) tangent of the median distribution value, i.e. 50% of normals have\n // a tangent (gradient) closer to the macrosurface than this slope.\n float a2 = alphaG * alphaG;\n float d = NdotH * NdotH * (a2 - 1.0) + 1.0;\n return a2 / (PI * d * d);\n}\n\n// from https://github.com/BabylonJS/Babylon.js/blob/5e6321d887637877d8b28b417410abbbeb651c6e/src/Shaders/ShadersInclude/pbrHelperFunctions.fx\nfloat convertRoughnessToAverageSlope(float roughness)\n{\n // Calculate AlphaG as square of roughness (add epsilon to avoid numerical issues)\n return (roughness * roughness) + MINIMUMVARIANCE;\n}\n\n\n#ifndef WEBGL1\n // https://learnopengl.com/PBR/IBL/Specular-IBL\n // Hammersley\n float radicalInverse_VdC(uint bits)\n {\n bits = (bits << 16u) | (bits >> 16u);\n bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);\n bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);\n bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);\n bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);\n return float(bits) * 2.3283064365386963e-10; // / 0x100000000\n }\n\n vec2 hammersley(uint i, uint N)\n {\n return vec2(float(i)/float(N), radicalInverse_VdC(i));\n }\n#else\n float vanDerCorpus(int n, int base)\n {\n float invBase = 1.0 / float(base);\n float denom = 1.0;\n float result = 0.0;\n\n for(int i = 0; i < 32; ++i)\n {\n if(n > 0)\n {\n denom = mod(float(n), 2.0);\n result += denom * invBase;\n invBase = invBase / 2.0;\n n = int(float(n) / 2.0);\n }\n }\n\n return result;\n }\n\n vec2 hammersley(int i, int N)\n {\n return vec2(float(i)/float(N), vanDerCorpus(i, 2));\n }\n#endif\n\nfloat log4(float x)\n{\n return log2(x) / 2.;\n}\n\nconst float NUM_SAMPLES_FLOAT = float(NUM_SAMPLES);\nconst float NUM_SAMPLES_FLOAT_INVERSED = 1. / NUM_SAMPLES_FLOAT;\n\nconst float K = 4.;\n\nvoid main()\n{\n {{MODULE_BEGIN_FRAG}}\n vec3 n = normalize(FragPos);\n float alphaG = convertRoughnessToAverageSlope(roughness);\n vec4 result = vec4(0.);\n\n if (alphaG == 0.)\n {\n result = SAMPLETEX(EquiCubemap, SampleSphericalMap(n, rotation), 0.0);\n }\n else\n {\n vec3 tangent = abs(n.z) < 0.999 ? vec3(0., 0., 1.) : vec3(1., 0., 0.);\n tangent = normalize(cross(tangent, n));\n vec3 bitangent = cross(n, tangent);\n mat3 tbn = mat3(tangent, bitangent, n);\n\n float maxLevel = filteringInfo.y;\n float dim0 = filteringInfo.x;\n float omegaP = (4. * PI) / (6. * dim0 * dim0);\n\n float weight = 0.;\n #if defined(WEBGL2)\n for(uint i = 0u; i < NUM_SAMPLES; ++i)\n #else\n for(int i = 0; i < NUM_SAMPLES; ++i)\n #endif\n {\n vec2 Xi = hammersley(i, NUM_SAMPLES);\n vec3 H = hemisphereImportanceSampleDggx(Xi, alphaG);\n\n float NoV = 1.;\n float NoH = H.z;\n float NoH2 = H.z * H.z;\n float NoL = 2. * NoH2 - 1.;\n vec3 L = vec3(2. * NoH * H.x, 2. * NoH * H.y, NoL);\n L = normalize(L);\n\n if (NoL > 0.)\n {\n float pdf_inversed = 4. / normalDistributionFunction_TrowbridgeReitzGGX(NoH, alphaG);\n\n float omegaS = NUM_SAMPLES_FLOAT_INVERSED * pdf_inversed;\n float l = log4(omegaS) - log4(omegaP) + log4(K);\n float mipLevel = clamp(l, 0.0, maxLevel);\n\n weight += NoL;\n\n #ifndef DONT_USE_RGBE_CUBEMAPS\n vec3 c = DecodeRGBE8(SAMPLETEX(EquiCubemap, SampleSphericalMap(tbn * L, rotation), mipLevel)).rgb;\n #else\n vec3 c = SAMPLETEX(EquiCubemap, SampleSphericalMap(tbn * L, rotation), mipLevel).rgb;\n #endif\n result.rgb += c * NoL;\n }\n }\n\n result = result / weight;\n result = EncodeRGBE8(result.rgb);\n }\n\n {{MODULE_COLOR}}\n outColor = result;\n}\n","prefiltering_vert":"precision highp float;\nprecision highp int;\nprecision highp sampler2D;\n\n{{MODULES_HEAD}}\nIN vec3 vPosition;\nIN float attrVertIndex;\n\nOUT vec3 FragPos;\nUNI mat4 projMatrix;\nUNI mat4 viewMatrix;\nUNI mat4 modelMatrix;\n\n\nvoid main()\n{\n FragPos = vPosition;\n\n {{MODULE_VERTEX_POSITION}}\n gl_Position = projMatrix * viewMatrix * modelMatrix * vec4(vPosition, 1.0);\n gl_Position = gl_Position.xyww;\n}\n",}; +// utility +const cgl = op.patch.cgl; +const IS_WEBGL_1 = cgl.glVersion == 1; + +const BB = new CABLES.CG.BoundingBox(); +const geometry = new CGL.Geometry("unit cube"); +geometry.vertices = new Float32Array([ + -1.0, 1.0, -1.0, + -1.0, -1.0, -1.0, + 1.0, -1.0, -1.0, + 1.0, -1.0, -1.0, + 1.0, 1.0, -1.0, + -1.0, 1.0, -1.0, + + -1.0, -1.0, 1.0, + -1.0, -1.0, -1.0, + -1.0, 1.0, -1.0, + -1.0, 1.0, -1.0, + -1.0, 1.0, 1.0, + -1.0, -1.0, 1.0, + + 1.0, -1.0, -1.0, + 1.0, -1.0, 1.0, + 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + 1.0, 1.0, -1.0, + 1.0, -1.0, -1.0, + + -1.0, -1.0, 1.0, + -1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + 1.0, -1.0, 1.0, + -1.0, -1.0, 1.0, + + -1.0, 1.0, -1.0, + 1.0, 1.0, -1.0, + 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + -1.0, 1.0, 1.0, + -1.0, 1.0, -1.0, + + -1.0, -1.0, -1.0, + -1.0, -1.0, 1.0, + 1.0, -1.0, -1.0, + 1.0, -1.0, -1.0, + -1.0, -1.0, 1.0, + 1.0, -1.0, 1.0 +]); +const mesh = new CGL.Mesh(cgl, geometry); +const fullscreenRectangle = CGL.MESHES.getSimpleRect(cgl, "fullscreenRectangle"); +// inputs +const inTrigger = op.inTrigger("render"); +// const inTriggerRecapture = op.inTriggerButton("recapture"); + +const inCubemap = op.inTexture("RGBE Environment map"); + +const inIrradianceSize = op.inDropDown("Size Irradiance map", [16, 32, 64], 64); +const inPrefilteredSize = op.inDropDown("Size pre-filtered environment", [64, 128], 128); +const inIBLLUTSize = op.inDropDown("Size IBL LUT", [128, 256, 512, 1024], 256); +const inToggleRGBE = op.inBool("Environment map does not contain RGBE data", false); +const inRotation = op.inFloat("Rotation", 0.0); +const inUseParallaxCorrection = op.inValueBool("Use parallax correction", false); + +const inPCOriginX = op.inFloat("center X", 0); +const inPCOriginY = op.inFloat("center Y", 1.8); +const inPCOriginZ = op.inFloat("center Z", 0); +const inPCboxMinX = op.inFloat("Box min X", -1); +const inPCboxMinY = op.inFloat("Box min Y", -1); +const inPCboxMinZ = op.inFloat("Box min Z", -1); +const inPCboxMaxX = op.inFloat("Box max X", 1); +const inPCboxMaxY = op.inFloat("Box max Y", 1); +const inPCboxMaxZ = op.inFloat("Box max Z", 1); + +op.setPortGroup("Parallax Correction", [ + inUseParallaxCorrection, + inPCOriginX, + inPCOriginY, + inPCOriginZ, + inPCboxMinX, + inPCboxMinY, + inPCboxMinZ, + inPCboxMaxX, + inPCboxMaxY, + inPCboxMaxZ +]); + +let IrradianceSizeChanged = true; +let PrefilteredSizeChanged = true; +let IBLLUTSizeChanged = true; +inIrradianceSize.onChange = () => { IrradianceSizeChanged = true; }; +inPrefilteredSize.onChange = () => { PrefilteredSizeChanged = true; }; +inIBLLUTSize.onChange = () => { IBLLUTSizeChanged = true; }; + +// outputs +const outTrigger = op.outTrigger("next"); + +const outTexIBLLUT = op.outTexture("IBL LUT"); +const outTexIrradiance = op.outTexture("cubemap (diffuse irradiance)"); +const outTexPrefiltered = op.outTexture("cubemap (pre-filtered environment map)"); +const outMipLevels = op.outNumber("Number of Pre-filtered mip levels"); +// UI stuff +op.toWorkPortsNeedToBeLinked(inCubemap); + +// globals +let irradianceFrameBuffer = null; +let PrefilteredTexture = null; +let prefilteredFrameBuffer = null; +let iblLutFrameBuffer = null; +let maxMipLevels = null; +const pbrEnv = {}; +const IrradianceShader = new CGL.Shader(cgl, "IrradianceShader"); +const PrefilteringShader = new CGL.Shader(cgl, "PrefilteringShader"); +IrradianceShader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); +PrefilteringShader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); + +if (cgl.glVersion == 1) +{ + if (!cgl.gl.getExtension("EXT_shader_texture_lod")) + { + op.log("no EXT_shader_texture_lod texture extension"); + throw "no EXT_shader_texture_lod texture extension"; + } + else + { + IrradianceShader.enableExtension("GL_EXT_shader_texture_lod"); + PrefilteringShader.enableExtension("GL_EXT_shader_texture_lod"); + cgl.gl.getExtension("OES_texture_float"); + cgl.gl.getExtension("OES_texture_float_linear"); + cgl.gl.getExtension("OES_texture_half_float"); + cgl.gl.getExtension("OES_texture_half_float_linear"); + + cgl.gl.getExtension("WEBGL_color_buffer_float"); + + IrradianceShader.enableExtension("GL_OES_standard_derivatives"); + IrradianceShader.enableExtension("GL_OES_texture_float"); + IrradianceShader.enableExtension("GL_OES_texture_float_linear"); + IrradianceShader.enableExtension("GL_OES_texture_half_float"); + IrradianceShader.enableExtension("GL_OES_texture_half_float_linear"); + PrefilteringShader.enableExtension("GL_OES_standard_derivatives"); + PrefilteringShader.enableExtension("GL_OES_texture_float"); + PrefilteringShader.enableExtension("GL_OES_texture_float_linear"); + PrefilteringShader.enableExtension("GL_OES_texture_half_float"); + PrefilteringShader.enableExtension("GL_OES_texture_half_float_linear"); + } +} + +let filteringInfo = [0, 0]; +IrradianceShader.offScreenPass = true; +const uniformIrradianceCubemap = new CGL.Uniform(IrradianceShader, "t", "EquiCubemap", 0); +const uniformFilteringInfo = new CGL.Uniform(IrradianceShader, "2f", "filteringInfo", filteringInfo); +const uniformRotation = new CGL.Uniform(IrradianceShader, "f", "rotation", 0); +IrradianceShader.setSource(attachments.irradiance_vert, attachments.irradiance_frag); + +let prefilteringInfo = [0, 0]; +PrefilteringShader.offScreenPass = true; +const uniformPrefilteringCubemap = new CGL.Uniform(PrefilteringShader, "t", "EquiCubemap", 0); +const uniformPrefilteringRoughness = new CGL.Uniform(PrefilteringShader, "f", "roughness", 0); +const uniformPrefilteringRotation = new CGL.Uniform(PrefilteringShader, "f", "rotation", 0); +const uniformPrefilteringInfo = new CGL.Uniform(PrefilteringShader, "2f", "filteringInfo", prefilteringInfo); +PrefilteringShader.setSource(attachments.prefiltering_vert, attachments.prefiltering_frag); + +const IBLLUTShader = new CGL.Shader(cgl, "IBLLUTShader"); +IBLLUTShader.offScreenPass = true; +IBLLUTShader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); +IBLLUTShader.setSource(attachments.IBLLUT_vert, attachments.IBLLUT_frag); + +inToggleRGBE.onChange = () => +{ + IrradianceShader.toggleDefine("DONT_USE_RGBE_CUBEMAPS", inToggleRGBE); + PrefilteringShader.toggleDefine("DONT_USE_RGBE_CUBEMAPS", inToggleRGBE); + + IrradianceSizeChanged = true; + PrefilteredSizeChanged = true; +}; + +inRotation.onChange = () => +{ + PrefilteredSizeChanged = + IrradianceSizeChanged = true; +}; + +// utility functions +function captureIrradianceCubemap(size) +{ + if (irradianceFrameBuffer) irradianceFrameBuffer.dispose(); + + irradianceFrameBuffer = new CGL.CubemapFramebuffer(cgl, Number(size), Number(size), { + "isFloatingPointTexture": false, + "clear": false, + "filter": CGL.Texture.FILTER_NEAREST, // due to banding with rgbe + "wrap": CGL.Texture.WRAP_CLAMP_TO_EDGE + }); + + filteringInfo[0] = size; + filteringInfo[1] = 1.0 + Math.floor(Math.log(size) * 1.44269504088896340736); + + IrradianceShader.popTextures(); + IrradianceShader.pushTexture(uniformIrradianceCubemap, inCubemap.get().tex); + uniformRotation.setValue(inRotation.get() / 360.0); + + irradianceFrameBuffer.renderStart(cgl); + for (let i = 0; i < 6; i += 1) + { + irradianceFrameBuffer.renderStartCubemapFace(i); + + // cgl.gl.clearColor(0, 0, 0, 0); + // if(i==0) cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); + mesh.render(IrradianceShader); + irradianceFrameBuffer.renderEndCubemapFace(); + } + irradianceFrameBuffer.renderEnd(); + + outTexIrradiance.set(null); // pandur + outTexIrradiance.set(irradianceFrameBuffer.getTextureColor()); +} + +function capturePrefilteredCubemap(size) +{ + size = Number(size); + let captureFBO = new CGL.CubemapFramebuffer(cgl, size, size, { + // "isFloatingPointTexture": true, + "clear": false, + "filter": CGL.Texture.FILTER_LINEAR, + "wrap": CGL.Texture.WRAP_CLAMP_TO_EDGE + }); + + if (prefilteredFrameBuffer) prefilteredFrameBuffer.dispose(); + + prefilteredFrameBuffer = new CGL.CubemapFramebuffer(cgl, size, size, { + "isFloatingPointTexture": false, + "clear": false, + "filter": CGL.Texture.FILTER_MIPMAP, + "wrap": CGL.Texture.WRAP_CLAMP_TO_EDGE + }); + + cgl.gl.bindTexture(cgl.gl.TEXTURE_CUBE_MAP, prefilteredFrameBuffer.getTextureColor().tex); + cgl.gl.texParameteri(cgl.gl.TEXTURE_CUBE_MAP, cgl.gl.TEXTURE_WRAP_R, cgl.gl.CLAMP_TO_EDGE); + + cgl.gl.texParameteri(cgl.gl.TEXTURE_CUBE_MAP, cgl.gl.TEXTURE_MIN_FILTER, cgl.gl.LINEAR_MIPMAP_LINEAR); + cgl.gl.texParameteri(cgl.gl.TEXTURE_CUBE_MAP, cgl.gl.TEXTURE_MAG_FILTER, cgl.gl.LINEAR); + cgl.gl.generateMipmap(cgl.gl.TEXTURE_CUBE_MAP); // make sure memory is assigned for mips + + maxMipLevels = 1.0 + Math.floor(Math.log(size) * 1.44269504088896340736); + outMipLevels.set(maxMipLevels); + prefilteringInfo[0] = size; + prefilteringInfo[1] = maxMipLevels; + + PrefilteringShader.popTextures(); + PrefilteringShader.pushTexture(uniformPrefilteringCubemap, inCubemap.get().tex); + uniformPrefilteringRotation.setValue(inRotation.get() / 360.0); + + for (let mip = 0; mip <= maxMipLevels; ++mip) + { + let currentMipSize = size * Math.pow(0.5, mip); + let roughness = mip / (maxMipLevels - 1); + uniformPrefilteringRoughness.setValue(roughness); + + captureFBO.setSize(Number(currentMipSize), Number(currentMipSize)); + captureFBO.renderStart(cgl); + for (let i = 0; i < 6; i += 1) + { + captureFBO.renderStartCubemapFace(i); + + // if(i==0)cgl.gl.clearColor(0, 0.1, 0.2, 0); + // if(i==0)cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); + + mesh.render(PrefilteringShader); + cgl.gl.bindTexture(cgl.gl.TEXTURE_CUBE_MAP, prefilteredFrameBuffer.getTextureColor().tex); + cgl.gl.copyTexImage2D(cgl.gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, mip, cgl.gl.RGBA, 0, 0, Number(currentMipSize), Number(currentMipSize), null); + captureFBO.renderEndCubemapFace(); + } + captureFBO.renderEnd(); + } + captureFBO.delete(); + cgl.setTexture(0, null); + + outTexPrefiltered.set(null); + outTexPrefiltered.set(prefilteredFrameBuffer.getTextureColor()); +} + +function computeIBLLUT(size) +{ + size = Number(size); + if (iblLutFrameBuffer) iblLutFrameBuffer.dispose(); + + if (IS_WEBGL_1) + { + iblLutFrameBuffer = new CGL.Framebuffer(cgl, size, size, { + "isFloatingPointTexture": true, + "filter": CGL.Texture.FILTER_LINEAR, + "wrap": CGL.Texture.WRAP_CLAMP_TO_EDGE + }); + } + else + { + iblLutFrameBuffer = new CGL.Framebuffer2(cgl, size, size, { + "isFloatingPointTexture": true, + "filter": CGL.Texture.FILTER_LINEAR, + "wrap": CGL.Texture.WRAP_CLAMP_TO_EDGE, + }); + } + + cgl.frameStore.renderOffscreen = true; + iblLutFrameBuffer.renderStart(cgl); + fullscreenRectangle.render(IBLLUTShader); + iblLutFrameBuffer.renderEnd(); + cgl.frameStore.renderOffscreen = false; + outTexIBLLUT.set(iblLutFrameBuffer.getTextureColor()); +} + +inCubemap.onChange = () => +{ + if (inCubemap.get()) + op.setUiError("nocubemapinput", null); + + PrefilteredSizeChanged = + IrradianceSizeChanged = true; +}; + +function drawHelpers() +{ + gui.setTransformGizmo({ + "posX": inPCOriginX, + "posY": inPCOriginY, + "posZ": inPCOriginZ, + }); + gui.setTransformGizmo({ + "posX": inPCboxMinX, + "posY": inPCboxMinY, + "posZ": inPCboxMinZ, + }, 1); + gui.setTransformGizmo({ + "posX": inPCboxMaxX, + "posY": inPCboxMaxY, + "posZ": inPCboxMaxZ, + }, 2); + if (CABLES.UI.renderHelper) + { + cgl.pushShader(CABLES.GL_MARKER.getDefaultShader(cgl)); + } + else + { + cgl.pushShader(CABLES.GL_MARKER.getSelectedShader(cgl)); + } + cgl.pushModelMatrix(); + // translate + mat4.translate(cgl.mMatrix, cgl.mMatrix, [(inPCboxMinX.get() + inPCboxMaxX.get()) / 2.0, (inPCboxMinY.get() + inPCboxMaxY.get()) / 2.0, (inPCboxMinZ.get() + inPCboxMaxZ.get()) / 2.0]); + // scale to bounds + mat4.scale(cgl.mMatrix, cgl.mMatrix, [(inPCboxMaxX.get() - inPCboxMinX.get()) / 2.0, (inPCboxMaxY.get() - inPCboxMinY.get()) / 2.0, (inPCboxMaxZ.get() - inPCboxMinZ.get()) / 2.0]); + // draw + BB.render(cgl); + cgl.popShader(); + cgl.popModelMatrix(); +} + +inUseParallaxCorrection.onChange = () => +{ + const active = inUseParallaxCorrection.get(); + inPCOriginX.setUiAttribs({ "greyout": !active }); + inPCOriginY.setUiAttribs({ "greyout": !active }); + inPCOriginZ.setUiAttribs({ "greyout": !active }); + inPCboxMinX.setUiAttribs({ "greyout": !active }); + inPCboxMinY.setUiAttribs({ "greyout": !active }); + inPCboxMinZ.setUiAttribs({ "greyout": !active }); + inPCboxMaxX.setUiAttribs({ "greyout": !active }); + inPCboxMaxY.setUiAttribs({ "greyout": !active }); + inPCboxMaxZ.setUiAttribs({ "greyout": !active }); +}; + +// onTriggered +inTrigger.onTriggered = function () +{ + if (!inCubemap.get()) + { + outTrigger.trigger(); + op.setUiError("nocubemapinput", "No Environment Texture connected"); + return; + } + + uniformFilteringInfo.setValue(filteringInfo); + uniformPrefilteringInfo.setValue(prefilteringInfo); + + if (!cgl.frameStore.shadowPass) + { + if (IBLLUTSizeChanged) + { + computeIBLLUT(Number(inIBLLUTSize.get())); + IBLLUTSizeChanged = false; + } + + if (PrefilteredSizeChanged) + { + capturePrefilteredCubemap(Number(inPrefilteredSize.get())); + PrefilteredSizeChanged = false; + } + + if (IrradianceSizeChanged) + { + captureIrradianceCubemap(Number(inIrradianceSize.get())); + IrradianceSizeChanged = false; + } + } + + pbrEnv.texIBLLUT = outTexIBLLUT.get(); + pbrEnv.texDiffIrr = outTexIrradiance.get(); + pbrEnv.texPreFiltered = outTexPrefiltered.get(); + pbrEnv.texPreFilteredMipLevels = outMipLevels.get(); + + pbrEnv.UseParallaxCorrection = inUseParallaxCorrection.get(); + pbrEnv.PCOrigin = [inPCOriginX.get(), inPCOriginY.get(), inPCOriginZ.get()]; + pbrEnv.PCboxMin = [inPCboxMinX.get(), inPCboxMinY.get(), inPCboxMinZ.get()]; + pbrEnv.PCboxMax = [inPCboxMaxX.get(), inPCboxMaxY.get(), inPCboxMaxZ.get()]; + + cgl.frameStore.pbrEnvStack = cgl.frameStore.pbrEnvStack || []; + cgl.frameStore.pbrEnvStack.push(pbrEnv); + + if (cgl.shouldDrawHelpers(op) && pbrEnv.UseParallaxCorrection && !cgl.frameStore.shadowPass) drawHelpers(); + + outTrigger.trigger(); + cgl.frameStore.pbrEnvStack.pop(); +}; + + +}; + +Ops.Gl.Pbr.PbrEnvironmentLight.prototype = new CABLES.Op(); +CABLES.OPS["7110f169-adfd-4649-a77a-c825751eaa9b"]={f:Ops.Gl.Pbr.PbrEnvironmentLight,objName:"Ops.Gl.Pbr.PbrEnvironmentLight"}; + + + + +// ************************************************************** +// +// Ops.Gl.Pbr.PbrMaterial +// +// ************************************************************** + +Ops.Gl.Pbr.PbrMaterial = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"BasicPBR_frag":"precision highp float;\nprecision highp int;\n{{MODULES_HEAD}}\n\n// set by cables\nUNI vec3 camPos;\n// utility maps\n#ifdef USE_ENVIRONMENT_LIGHTING\n UNI sampler2D IBL_BRDF_LUT;\n#endif\n// mesh maps\n#ifdef USE_ALBEDO_TEX\n UNI sampler2D _AlbedoMap;\n#else\n UNI vec4 _Albedo;\n#endif\n#ifdef USE_NORMAL_TEX\n UNI sampler2D _NormalMap;\n#endif\n#ifdef USE_HEIGHT_TEX\n UNI sampler2D _HeightMap;\n#endif\n#ifdef USE_AORM_TEX\n UNI sampler2D _AORMMap;\n#else\n UNI float _Roughness;\n UNI float _Metalness;\n#endif\n\n#ifdef USE_LIGHTMAP\n #ifndef VERTEX_COLORS\n UNI sampler2D _Lightmap;\n #else\n #ifndef VCOL_LIGHTMAP\n UNI sampler2D _Lightmap;\n #endif\n #endif\n#endif\n#ifdef USE_CLEAR_COAT\n UNI float _ClearCoatRoughness;\n#endif\n// IBL inputs\n#ifdef USE_ENVIRONMENT_LIGHTING\n UNI samplerCube _irradiance;\n UNI samplerCube _prefilteredEnvironmentColour;\n UNI float MAX_REFLECTION_LOD;\n UNI float diffuseIntensity;\n UNI float specularIntensity;\n#endif\n#ifdef USE_LIGHTMAP\n UNI float lightmapIntensity;\n#endif\nUNI float tonemappingExposure;\n#ifdef USE_HEIGHT_TEX\n UNI float _HeightDepth;\n #ifndef USE_OPTIMIZED_HEIGHT\n UNI mat4 modelMatrix;\n #endif\n#endif\n#ifdef USE_PARALLAX_CORRECTION\n UNI vec3 _PCOrigin;\n UNI vec3 _PCboxMin;\n UNI vec3 _PCboxMax;\n#endif\n\nIN vec2 texCoord;\n#ifdef USE_LIGHTMAP\n #ifndef ATTRIB_texCoord1\n #ifndef VERTEX_COLORS\n IN vec2 texCoord1;\n #else\n #ifndef VCOL_LIGHTMAP\n IN vec2 texCoord1;\n #endif\n #endif\n #endif\n#endif\nIN vec4 FragPos;\nIN mat3 TBN;\nIN vec3 norm;\nIN vec3 normM;\n#ifdef VERTEX_COLORS\n IN vec4 vertCol;\n#endif\n#ifdef USE_HEIGHT_TEX\n #ifdef USE_OPTIMIZED_HEIGHT\n IN vec3 fragTangentViewDir;\n #else\n IN mat3 invTBN;\n #endif\n#endif\n\n// structs\nstruct Light {\n vec3 color;\n vec3 position;\n vec3 specular;\n\n #define INTENSITY x\n #define ATTENUATION y\n #define FALLOFF z\n #define RADIUS w\n vec4 lightProperties;\n\n int castLight;\n\n vec3 conePointAt;\n #define COSCONEANGLE x\n #define COSCONEANGLEINNER y\n #define SPOTEXPONENT z\n vec3 spotProperties;\n};\n\n\n#ifdef WEBGL1\n #ifdef GL_EXT_shader_texture_lod\n #define textureLod textureCubeLodEXT\n #endif\n#endif\n#define SAMPLETEX textureLod\n\n// https://community.khronos.org/t/addition-of-two-hdr-rgbe-values/55669\nhighp vec4 EncodeRGBE8(highp vec3 rgb)\n{\n highp vec4 vEncoded;\n float maxComponent = max(max(rgb.r, rgb.g), rgb.b);\n float fExp = ceil(log2(maxComponent));\n vEncoded.rgb = rgb / exp2(fExp);\n vEncoded.a = (fExp + 128.0) / 255.0;\n return vEncoded;\n}\n// https://enkimute.github.io/hdrpng.js/\nhighp vec3 DecodeRGBE8(highp vec4 rgbe)\n{\n highp vec3 vDecoded = rgbe.rgb * pow(2.0, rgbe.a * 255.0-128.0);\n return vDecoded;\n}\n\n// from https://github.com/BabylonJS/Babylon.js/blob/master/src/Shaders/ShadersInclude/pbrIBLFunctions.fx\nfloat environmentRadianceOcclusion(float ambientOcclusion, float NdotVUnclamped) {\n // Best balanced (implementation time vs result vs perf) analytical environment specular occlusion found.\n // http://research.tri-ace.com/Data/cedec2011_RealtimePBR_Implementation_e.pptx\n float temp = NdotVUnclamped + ambientOcclusion;\n return clamp(temp * temp - 1.0 + ambientOcclusion, 0.0, 1.0);\n}\nfloat environmentHorizonOcclusion(vec3 view, vec3 normal, vec3 geometricNormal) {\n // http://marmosetco.tumblr.com/post/81245981087\n vec3 reflection = reflect(view, normal);\n float temp = clamp(1.0 + 1.1 * dot(reflection, geometricNormal), 0.0, 1.0);\n return temp * temp;\n}\n#ifdef ALPHA_DITHERED\n// from https://github.com/google/filament/blob/main/shaders/src/dithering.fs\n// modified to use this to discard based on factor instead of dithering\nfloat interleavedGradientNoise(highp vec2 n) {\n return fract(52.982919 * fract(dot(vec2(0.06711, 0.00584), n)));\n}\nfloat Dither_InterleavedGradientNoise(float a) {\n // Jimenez 2014, \"Next Generation Post-Processing in Call of Duty\"\n highp vec2 uv = gl_FragCoord.xy;\n\n // The noise variable must be highp to workaround Adreno bug #1096.\n highp float noise = interleavedGradientNoise(uv);\n\n return step(noise, a);\n}\n#endif\n\n#ifdef USE_HEIGHT_TEX\n#ifndef WEBGL1\n// based on Jasper Flicks great tutorials (:\nfloat getSurfaceHeight(sampler2D surfaceHeightMap, vec2 UV)\n{\n\treturn texture(surfaceHeightMap, UV).r;\n}\n\nvec2 RaymarchedParallax(vec2 UV, sampler2D surfaceHeightMap, float strength, vec3 viewDir)\n{\n #ifndef USE_OPTIMIZED_HEIGHT\n\t#define PARALLAX_RAYMARCHING_STEPS 50\n #else\n #define PARALLAX_RAYMARCHING_STEPS 20\n #endif\n\tvec2 uvOffset = vec2(0.0);\n\tfloat stepSize = 1.0 / float(PARALLAX_RAYMARCHING_STEPS);\n\tvec2 uvDelta = vec2(viewDir * (stepSize * strength));\n\tfloat stepHeight = 1.0;\n\tfloat surfaceHeight = getSurfaceHeight(surfaceHeightMap, UV);\n\n\tvec2 prevUVOffset = uvOffset;\n\tfloat prevStepHeight = stepHeight;\n\tfloat prevSurfaceHeight = surfaceHeight;\n\n // doesnt work with webgl 1.0 as the && condition is not fixed length for loop\n\tfor (int i = 1; i < PARALLAX_RAYMARCHING_STEPS && stepHeight > surfaceHeight; ++i)\n\t{\n\t\tprevUVOffset = uvOffset;\n\t\tprevStepHeight = stepHeight;\n\t\tprevSurfaceHeight = surfaceHeight;\n\n\t\tuvOffset -= uvDelta;\n\t\tstepHeight -= stepSize;\n\t\tsurfaceHeight = getSurfaceHeight(surfaceHeightMap, UV + uvOffset);\n\t}\n\n\tfloat prevDifference = prevStepHeight - prevSurfaceHeight;\n\tfloat difference = surfaceHeight - stepHeight;\n\tfloat t = prevDifference / (prevDifference + difference);\n\tuvOffset = mix(prevUVOffset, uvOffset, t);\n\treturn uvOffset;\n}\n#endif // TODO: use non raymarched parallax mapping here if webgl 1.0?\n#endif\n\n#ifdef USE_PARALLAX_CORRECTION\nvec3 BoxProjection(vec3 direction, vec3 position, vec3 cubemapPosition, vec3 boxMin, vec3 boxMax)\n{\n\tboxMin -= position;\n\tboxMax -= position;\n\tfloat x = (direction.x > 0.0 ? boxMax.x : boxMin.x) / direction.x;\n\tfloat y = (direction.y > 0.0 ? boxMax.y : boxMin.y) / direction.y;\n\tfloat z = (direction.z > 0.0 ? boxMax.z : boxMin.z) / direction.z;\n\tfloat scalar = min(min(x, y), z);\n\n\treturn direction * scalar + (position - cubemapPosition);\n}\n#endif\n\n{{PBR_FRAGMENT_HEAD}}\nvoid main()\n{\n vec4 col;\n\n // set up interpolated vertex data\n vec2 UV0 = texCoord;\n #ifdef USE_LIGHTMAP\n #ifndef VERTEX_COLORS\n vec2 UV1 = texCoord1;\n #else\n #ifndef VCOL_LIGHTMAP\n vec2 UV1 = texCoord1;\n #endif\n #endif\n #endif\n vec3 V = normalize(camPos - FragPos.xyz);\n\n #ifdef USE_HEIGHT_TEX\n #ifndef USE_OPTIMIZED_HEIGHT\n vec3 fragTangentViewDir = normalize(invTBN * (camPos - FragPos.xyz));\n #endif\n #ifndef WEBGL1\n UV0 += RaymarchedParallax(UV0, _HeightMap, _HeightDepth * 0.1, fragTangentViewDir);\n #endif\n #endif\n\n // load relevant mesh maps\n #ifdef USE_ALBEDO_TEX\n vec4 AlbedoMap = texture(_AlbedoMap, UV0);\n #else\n vec4 AlbedoMap = _Albedo;\n #endif\n #ifdef ALPHA_MASKED\n\tif ( AlbedoMap.a <= 0.5 )\n\t discard;\n\t#endif\n\n\t#ifdef ALPHA_DITHERED\n\tif ( Dither_InterleavedGradientNoise(AlbedoMap.a) <= 0.5 )\n\t discard;\n\t#endif\n\n #ifdef USE_AORM_TEX\n vec4 AORM = texture(_AORMMap, UV0);\n #else\n vec4 AORM = vec4(1.0, _Roughness, _Metalness, 1.0);\n #endif\n #ifdef USE_NORMAL_TEX\n vec3 internalNormals = texture(_NormalMap, UV0).rgb;\n internalNormals = internalNormals * 2.0 - 1.0;\n internalNormals = normalize(TBN * internalNormals);\n #else\n vec3 internalNormals = normM;\n #endif\n\t#ifdef USE_LIGHTMAP\n \t#ifndef VERTEX_COLORS\n\t #ifndef LIGHTMAP_IS_RGBE\n vec3 Lightmap = texture(_Lightmap, UV1).rgb;\n #else\n vec3 Lightmap = DecodeRGBE8(texture(_Lightmap, UV1));\n #endif\n #else\n #ifdef VCOL_LIGHTMAP\n vec3 Lightmap = pow(vertCol.rgb, vec3(2.2));\n #else\n \t #ifndef LIGHTMAP_IS_RGBE\n vec3 Lightmap = texture(_Lightmap, UV1).rgb;\n #else\n vec3 Lightmap = DecodeRGBE8(texture(_Lightmap, UV1));\n #endif\n #endif\n #endif\n #endif\n // initialize texture values\n float AO = AORM.r;\n float specK = AORM.g;\n float metalness = AORM.b;\n vec3 N = normalize(internalNormals);\n vec3 albedo = pow(AlbedoMap.rgb, vec3(2.2));\n\n #ifdef VERTEX_COLORS\n #ifdef VCOL_COLOUR\n albedo.rgb *= pow(vertCol.rgb, vec3(2.2));\n AlbedoMap.rgb *= pow(vertCol.rgb, vec3(2.2));\n #endif\n #ifdef VCOL_AORM\n AO = vertCol.r;\n specK = vertCol.g;\n metalness = vertCol.b;\n #endif\n #ifdef VCOL_AO\n AO = vertCol.r;\n #endif\n #ifdef VCOL_R\n specK = vertCol.g;\n #endif\n #ifdef VCOL_M\n metalness = vertCol.b;\n #endif\n #endif\n\n // set up values for later calculations\n float NdotV = abs(dot(N, V));\n vec3 F0 = mix(vec3(0.04), AlbedoMap.rgb, metalness);\n\n #ifndef WEBGL1\n #ifndef DONT_USE_GR\n // from https://github.com/BabylonJS/Babylon.js/blob/5e6321d887637877d8b28b417410abbbeb651c6e/src/Shaders/ShadersInclude/pbrHelperFunctions.fx\n // modified to fit variable names\n #ifndef DONT_USE_NMGR\n vec3 nDfdx = dFdx(normM.xyz);\n vec3 nDfdy = dFdy(normM.xyz);\n #else\n vec3 nDfdx = dFdx(N.xyz) + dFdx(normM.xyz);\n vec3 nDfdy = dFdy(N.xyz) + dFdy(normM.xyz);\n #endif\n float slopeSquare = max(dot(nDfdx, nDfdx), dot(nDfdy, nDfdy));\n\n // Vive analytical lights roughness factor.\n float geometricRoughnessFactor = pow(clamp(slopeSquare, 0.0, 1.0), 0.333);\n\n specK = max(specK, geometricRoughnessFactor);\n #endif\n #endif\n\n \t// IBL\n \t// from https://github.com/google/filament/blob/df6a100fcba66d9c99328a49d41fe3adecc0165d/shaders/src/light_indirect.fs\n \t// and https://github.com/google/filament/blob/df6a100fcba66d9c99328a49d41fe3adecc0165d/shaders/src/shading_lit.fs\n \t// modified to fit structure/variable names\n \t#ifdef USE_ENVIRONMENT_LIGHTING\n \tvec2 envBRDF = texture(IBL_BRDF_LUT, vec2(NdotV, specK)).xy;\n \tvec3 E = mix(envBRDF.xxx, envBRDF.yyy, F0);\n #endif\n\n float specOcclusion = environmentRadianceOcclusion(AO, NdotV);\n float horizonOcclusion = environmentHorizonOcclusion(-V, N, normM);\n\n #ifdef USE_ENVIRONMENT_LIGHTING\n float envSampleSpecK = specK * MAX_REFLECTION_LOD;\n vec3 R = reflect(-V, N);\n\n #ifdef USE_PARALLAX_CORRECTION\n R = BoxProjection(R, FragPos.xyz, _PCOrigin, _PCboxMin, _PCboxMax);\n #endif\n\n \t vec3 prefilteredEnvColour = DecodeRGBE8(SAMPLETEX(_prefilteredEnvironmentColour, R, envSampleSpecK)) * specularIntensity;\n\n \tvec3 Fr = E * prefilteredEnvColour;\n \tFr *= specOcclusion * horizonOcclusion * (1.0 + F0 * (1.0 / envBRDF.y - 1.0));\n \tFr *= 1.0 + F0; // TODO: this might be wrong, figure this out\n\n \t#ifdef USE_LIGHTMAP\n vec3 IBLIrradiance = Lightmap * lightmapIntensity;\n #else\n vec3 IBLIrradiance = DecodeRGBE8(SAMPLETEX(_irradiance, N, 0.0)) * diffuseIntensity;\n #endif\n\t vec3 Fd = (1.0 - metalness) * albedo * IBLIrradiance * (1.0 - E) * AO;\n #endif\n vec3 directLighting = vec3(0.0);\n\n {{PBR_FRAGMENT_BODY}}\n\n // combine IBL\n col.rgb = directLighting;\n #ifdef USE_ENVIRONMENT_LIGHTING\n col.rgb += Fr + Fd;\n #ifdef USE_CLEAR_COAT\n float CCEnvSampleSpecK = _ClearCoatRoughness * MAX_REFLECTION_LOD;\n vec3 CCR = reflect(-V, normM);\n\n #ifdef USE_PARALLAX_CORRECTION\n CCR = BoxProjection(CCR, FragPos.xyz, _PCOrigin, _PCboxMin, _PCboxMax);\n #endif\n\n \tvec3 CCPrefilteredEnvColour = DecodeRGBE8(SAMPLETEX(_prefilteredEnvironmentColour, CCR, CCEnvSampleSpecK));\n \tvec3 CCFr = E * CCPrefilteredEnvColour;\n \tCCFr *= specOcclusion * horizonOcclusion * (0.96 + (0.04 / envBRDF.y));\n \tCCFr *= 1.04;\n \tcol.rgb += CCFr;\n #endif\n #else\n #ifdef USE_LIGHTMAP\n col.rgb += (1.0 - metalness) * albedo * Lightmap * lightmapIntensity;\n #endif\n #endif\n col.a = 1.0;\n\n #ifdef ALPHA_BLEND\n col.a = AlbedoMap.a;\n #endif\n\n // from https://github.com/BabylonJS/Babylon.js/blob/5e6321d887637877d8b28b417410abbbeb651c6e/src/Shaders/tonemap.fragment.fx\n // modified to fit variable names\n #ifdef TONEMAP_HejiDawson\n col.rgb *= tonemappingExposure;\n\n vec3 X = max(vec3(0.0, 0.0, 0.0), col.rgb - 0.004);\n vec3 retColor = (X * (6.2 * X + 0.5)) / (X * (6.2 * X + 1.7) + 0.06);\n\n col.rgb = retColor * retColor;\n #elif defined(TONEMAP_Photographic)\n col.rgb = vec3(1.0, 1.0, 1.0) - exp2(-tonemappingExposure * col.rgb);\n #else\n col.rgb *= tonemappingExposure;\n //col.rgb = clamp(col.rgb, vec3(0.0), vec3(1.0));\n #endif\n\n col.rgb = pow(col.rgb, vec3(1.0/2.2));\n {{MODULE_COLOR}}\n\n outColor = col;\n}\n","BasicPBR_vert":"precision highp float;\nprecision highp int;\n\nUNI vec3 camPos;\n\nIN vec3 vPosition;\nIN vec2 attrTexCoord;\n#ifdef USE_LIGHTMAP\n #ifndef ATTRIB_attrTexCoord1\n IN vec2 attrTexCoord1;\n OUT vec2 texCoord1;\n #define ATTRIB_attrTexCoord1\n #define ATTRIB_texCoord1\n #endif\n#endif\nIN vec3 attrVertNormal;\nIN vec3 attrTangent;\nIN vec3 attrBiTangent;\nIN float attrVertIndex;\n#ifdef VERTEX_COLORS\nIN vec4 attrVertColor;\n#endif\n\n{{MODULES_HEAD}}\n\nOUT vec2 texCoord;\n\nOUT vec4 FragPos;\nOUT mat3 TBN;\nOUT vec3 norm;\nOUT vec3 normM;\n#ifdef VERTEX_COLORS\nOUT vec4 vertCol;\n#endif\n#ifdef USE_HEIGHT_TEX\n#ifdef USE_OPTIMIZED_HEIGHT\nOUT vec3 fragTangentViewDir;\n#else\nOUT mat3 invTBN;\n#endif\n#endif\nUNI mat4 projMatrix;\nUNI mat4 viewMatrix;\nUNI mat4 modelMatrix;\n\nvoid main()\n{\n mat4 mMatrix = modelMatrix; // needed to make vertex effects work\n #ifdef USE_LIGHTMAP\n texCoord1 = attrTexCoord1;\n #endif\n texCoord = attrTexCoord;\n texCoord.y = 1.0 - texCoord.y;\n vec4 pos = vec4(vPosition, 1.0);\n norm = attrVertNormal;\n vec3 tangent = attrTangent;\n vec3 bitangent = attrBiTangent;\n\n {{MODULE_VERTEX_POSITION}}\n\n #ifndef INSTANCING\n FragPos = mMatrix * pos;\n #else\n FragPos = instMat * pos;\n #endif\n\n #ifndef INSTANCING\n tangent = normalize(vec3(mMatrix * vec4(tangent, 0.0)));\n vec3 N = normalize(vec3(mMatrix * vec4(norm, 0.0)));\n #else\n tangent = normalize(vec3(instMat * vec4(tangent, 0.0)));\n vec3 N = normalize(vec3(instMat * vec4(norm, 0.0)));\n #endif\n\n #ifndef INSTANCING\n bitangent = normalize(vec3(mMatrix * vec4(bitangent, 0.0)));\n #else\n bitangent = normalize(vec3(instMat * vec4(bitangent, 0.0)));\n #endif\n\n #ifdef VERTEX_COLORS\n vertCol = attrVertColor;\n #endif\n\n TBN = mat3(tangent, bitangent, N);\n\n #ifdef USE_HEIGHT_TEX\n #ifndef WEBGL1\n #ifdef USE_OPTIMIZED_HEIGHT\n fragTangentViewDir = normalize(transpose(TBN) * (camPos - FragPos.xyz));\n #else\n invTBN = transpose(TBN);\n #endif\n #endif\n #endif\n\n normM = N;\n gl_Position = projMatrix * (viewMatrix*mMatrix) * pos;\n}\n","light_body_directional_frag":"\nvec3 L{{LIGHT_INDEX}} = normalize(lightOP{{LIGHT_INDEX}}.position);\n#ifdef USE_ENVIRONMENT_LIGHTING\ndirectLighting += evaluateLighting(lightOP{{LIGHT_INDEX}}, L{{LIGHT_INDEX}}, FragPos, V, N, albedo, specK, NdotV, F0, envBRDF.y, AO, false);\n#else\ndirectLighting += evaluateLighting(lightOP{{LIGHT_INDEX}}, L{{LIGHT_INDEX}}, FragPos, V, N, albedo, specK, NdotV, F0, AO, false);\n#endif\n","light_body_point_frag":"\nvec3 L{{LIGHT_INDEX}} = normalize(lightOP{{LIGHT_INDEX}}.position - FragPos.xyz);\n#ifdef USE_ENVIRONMENT_LIGHTING\ndirectLighting += evaluateLighting(lightOP{{LIGHT_INDEX}}, L{{LIGHT_INDEX}}, FragPos, V, N, albedo, specK, NdotV, F0, envBRDF.y, AO, true);\n#else\ndirectLighting += evaluateLighting(lightOP{{LIGHT_INDEX}}, L{{LIGHT_INDEX}}, FragPos, V, N, albedo, specK, NdotV, F0, AO, true);\n#endif\n","light_body_spot_frag":"\nvec3 L{{LIGHT_INDEX}} = normalize(lightOP{{LIGHT_INDEX}}.position - FragPos.xyz);\nfloat spotIntensity{{LIGHT_INDEX}} = CalculateSpotLightEffect(\n lightOP{{LIGHT_INDEX}}.position, lightOP{{LIGHT_INDEX}}.conePointAt, lightOP{{LIGHT_INDEX}}.spotProperties.COSCONEANGLE,\n lightOP{{LIGHT_INDEX}}.spotProperties.COSCONEANGLEINNER, lightOP{{LIGHT_INDEX}}.spotProperties.SPOTEXPONENT,\n L{{LIGHT_INDEX}}\n);\n#ifdef USE_ENVIRONMENT_LIGHTING\ndirectLighting += evaluateLighting(lightOP{{LIGHT_INDEX}}, L{{LIGHT_INDEX}}, FragPos, V, N, albedo, specK, NdotV, F0, envBRDF.y, AO * spotIntensity{{LIGHT_INDEX}}, true);\n#else\ndirectLighting += evaluateLighting(lightOP{{LIGHT_INDEX}}, L{{LIGHT_INDEX}}, FragPos, V, N, albedo, specK, NdotV, F0, AO * spotIntensity{{LIGHT_INDEX}}, true);\n#endif\n","light_head_frag":"UNI Light lightOP{{LIGHT_INDEX}};\n","light_includes_frag":"\n#define PI 3.14159265359\n\n// from https://github.com/google/filament/blob/036bfa9b20d730bb8e5852ed449b024570167648/shaders/src/brdf.fs\n// modified to fit variable names / structure\nfloat F_Schlick(float f0, float f90, float VoH)\n{\n return f0 + (f90 - f0) * pow(1.0 - VoH, 5.0);\n}\nvec3 F_Schlick(const vec3 f0, float VoH)\n{\n float f = pow(1.0 - VoH, 5.0);\n return f + f0 * (1.0 - f);\n}\nfloat Fd_Burley(float roughness, float NoV, float NoL, float LoH)\n{\n // Burley 2012, \"Physically-Based Shading at Disney\"\n float f90 = 0.5 + 2.0 * roughness * LoH * LoH;\n float lightScatter = F_Schlick(1.0, f90, NoL);\n float viewScatter = F_Schlick(1.0, f90, NoV);\n return lightScatter * viewScatter * (1.0 / PI);\n}\nfloat D_GGX(float roughness, float NoH, const vec3 h)\n{\n float oneMinusNoHSquared = 1.0 - NoH * NoH;\n\n float a = NoH * roughness;\n float k = roughness / (oneMinusNoHSquared + a * a);\n float d = k * k * (1.0 / PI);\n return clamp(d, 0.0, 1.0);\n}\nfloat V_SmithGGXCorrelated(float roughness, float NoV, float NoL)\n{\n // Heitz 2014, \"Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs\"\n float a2 = roughness * roughness;\n // TODO: lambdaV can be pre-computed for all the lights, it should be moved out of this function\n float lambdaV = NoL * sqrt((NoV - a2 * NoV) * NoV + a2);\n float lambdaL = NoV * sqrt((NoL - a2 * NoL) * NoL + a2);\n float v = 0.5 / (lambdaV + lambdaL);\n // a2=0 => v = 1 / 4*NoL*NoV => min=1/4, max=+inf\n // a2=1 => v = 1 / 2*(NoL+NoV) => min=1/4, max=+inf\n // clamp to the maximum value representable in mediump\n return clamp(v, 0.0, 1.0);\n}\n// from https://github.com/google/filament/blob/73e339b05d67749e3b1d1d243650441162c10f8a/shaders/src/light_punctual.fs\n// modified to fit variable names\nfloat getSquareFalloffAttenuation(float distanceSquare, float falloff)\n{\n float factor = distanceSquare * falloff;\n float smoothFactor = clamp(1.0 - factor * factor, 0.0, 1.0);\n // We would normally divide by the square distance here\n // but we do it at the call site\n return smoothFactor * smoothFactor;\n}\n\nfloat getDistanceAttenuation(vec3 posToLight, float falloff, vec3 V, float volume)\n{\n float distanceSquare = dot(posToLight, posToLight);\n float attenuation = getSquareFalloffAttenuation(distanceSquare, falloff);\n // light far attenuation\n float d = dot(V, V);\n float f = 100.0; // CONFIG_Z_LIGHT_FAR, ttps://github.com/google/filament/blob/df6a100fcba66d9c99328a49d41fe3adecc0165d/filament/src/details/Engine.h\n vec2 lightFarAttenuationParams = 0.5 * vec2(10.0, 10.0 / (f * f));\n attenuation *= clamp(lightFarAttenuationParams.x - d * lightFarAttenuationParams.y, 0.0, 1.0);\n // Assume a punctual light occupies a min volume of 1cm to avoid a division by 0\n return attenuation / max(distanceSquare, max(1e-4, volume));\n}\n\n#ifdef USE_CLEAR_COAT\n// from https://github.com/google/filament/blob/73e339b05d67749e3b1d1d243650441162c10f8a/shaders/src/shading_model_standard.fs\n// modified to fit variable names / structure\nfloat clearCoatLobe(vec3 shading_clearCoatNormal, vec3 h, float LoH, float CCSpecK)\n{\n float clearCoatNoH = clamp(dot(shading_clearCoatNormal, h), 0.0, 1.0);\n\n // clear coat specular lobe\n float D = D_GGX(CCSpecK, clearCoatNoH, h);\n // from https://github.com/google/filament/blob/036bfa9b20d730bb8e5852ed449b024570167648/shaders/src/brdf.fs\n float V = clamp(0.25 / (LoH * LoH), 0.0, 1.0);\n float F = F_Schlick(0.04, 1.0, LoH); // fix IOR to 1.5\n\n return D * V * F;\n}\n#endif\n\n#ifdef USE_ENVIRONMENT_LIGHTING\nvec3 evaluateLighting(Light light, vec3 L, vec4 FragPos, vec3 V, vec3 N, vec3 albedo, float specK, float NdotV, vec3 F0, float envBRDFY, float AO, bool hasFalloff)\n#else\nvec3 evaluateLighting(Light light, vec3 L, vec4 FragPos, vec3 V, vec3 N, vec3 albedo, float specK, float NdotV, vec3 F0, float AO, bool hasFalloff)\n#endif\n{\n vec3 directLightingResult = vec3(0.0);\n if (light.castLight == 1)\n {\n specK = max(0.08, specK);\n // from https://github.com/google/filament/blob/73e339b05d67749e3b1d1d243650441162c10f8a/shaders/src/shading_model_standard.fs\n // modified to fit variable names / structure\n vec3 H = normalize(V + L);\n\n float NdotL = clamp(dot(N, L), 0.0, 1.0);\n float NdotH = clamp(dot(N, H), 0.0, 1.0);\n float LdotH = clamp(dot(L, H), 0.0, 1.0);\n\n vec3 Fd = albedo * Fd_Burley(specK, NdotV, NdotL, LdotH);\n\n float D = D_GGX(specK, NdotH, H);\n float V2 = V_SmithGGXCorrelated(specK, NdotV, NdotL);\n vec3 F = F_Schlick(F0, LdotH);\n\n // TODO: modify this with the radius\n vec3 Fr = (D * V2) * F;\n\n #ifdef USE_ENVIRONMENT_LIGHTING\n vec3 directLighting = Fd + Fr * (1.0 + F0 * (1.0 / envBRDFY - 1.0));\n #else\n vec3 directLighting = Fd + Fr;\n #endif\n\n float attenuation = getDistanceAttenuation(L, hasFalloff ? light.lightProperties.FALLOFF : 0.0, V, light.lightProperties.RADIUS);\n\n directLightingResult = (directLighting * light.color) *\n (light.lightProperties.INTENSITY * attenuation * NdotL * AO);\n\n #ifdef USE_CLEAR_COAT\n directLightingResult += clearCoatLobe(normM, H, LdotH, _ClearCoatRoughness);\n #endif\n }\n return directLightingResult;\n}\n\n// from phong OP to make sure the light parameters change lighting similar to what people are used to\nfloat CalculateSpotLightEffect(vec3 lightPosition, vec3 conePointAt, float cosConeAngle, float cosConeAngleInner, float spotExponent, vec3 lightDirection) {\n vec3 spotLightDirection = normalize(lightPosition-conePointAt);\n float spotAngle = dot(-lightDirection, spotLightDirection);\n float epsilon = cosConeAngle - cosConeAngleInner;\n\n float spotIntensity = clamp((spotAngle - cosConeAngle)/epsilon, 0.0, 1.0);\n spotIntensity = pow(spotIntensity, max(0.01, spotExponent));\n\n return max(0., spotIntensity);\n}\n",}; +// utility +const cgl = op.patch.cgl; +// inputs +const inTrigger = op.inTrigger("render"); + +const inDiffuseR = op.inFloat("R", Math.random()); +const inDiffuseG = op.inFloat("G", Math.random()); +const inDiffuseB = op.inFloat("B", Math.random()); +const inDiffuseA = op.inFloatSlider("A", 1); +const diffuseColors = [inDiffuseR, inDiffuseG, inDiffuseB, inDiffuseA]; +op.setPortGroup("Diffuse Color", diffuseColors); + +const inRoughness = op.inFloatSlider("Roughness", 0.5); +const inMetalness = op.inFloatSlider("Metalness", 0.0); +const inAlphaMode = op.inSwitch("Alpha Mode", ["Opaque", "Masked", "Dithered", "Blend"], "Blend"); + +const inTonemapping = op.inSwitch("Tonemapping", ["sRGB", "HejiDawson", "Photographic"], "sRGB"); +const inTonemappingExposure = op.inFloat("Exposure", 1.0); + +const inToggleGR = op.inBool("Disable geometric roughness", false); +const inToggleNMGR = op.inBool("Use roughness from normal map", false); +const inUseVertexColours = op.inValueBool("Use Vertex Colours", false); +const inVertexColourMode = op.inSwitch("Vertex Colour Mode", ["colour", "AORM", "AO", "R", "M", "lightmap"], "colour"); +const inHeightDepth = op.inFloat("Height Intensity", 1.0); +const inUseOptimizedHeight = op.inValueBool("Faster heightmapping", false); +const inUseClearCoat = op.inValueBool("Use Clear Coat", false); +const inClearCoatRoughness = op.inFloatSlider("Clear Coat Roughness", 0.5); + +// texture inputs +const inTexIBLLUT = op.inTexture("IBL LUT"); +const inTexIrradiance = op.inTexture("Diffuse Irradiance"); +const inTexPrefiltered = op.inTexture("Pre-filtered envmap"); +const inMipLevels = op.inInt("Num mip levels"); + +const inTexAlbedo = op.inTexture("Albedo"); +const inTexAORM = op.inTexture("AORM"); +const inTexNormal = op.inTexture("Normal map"); +const inTexHeight = op.inTexture("Height"); +const inLightmap = op.inTexture("Lightmap"); +const inDiffuseIntensity = op.inFloat("Diffuse Intensity", 1.0); +const inSpecularIntensity = op.inFloat("Specular Intensity", 1.0); +const inLightmapRGBE = op.inBool("Lightmap is RGBE", false); +const inLightmapIntensity = op.inFloat("Lightmap Intensity", 1.0); + +inTrigger.onTriggered = doRender; + +// outputs +const outTrigger = op.outTrigger("Next"); +const shaderOut = op.outObject("Shader"); +shaderOut.ignoreValueSerialize = true; +// UI stuff +op.toWorkPortsNeedToBeLinked(inTrigger); + +inDiffuseR.setUiAttribs({ "colorPick": true }); +op.setPortGroup("Shader Parameters", [inRoughness, inMetalness, inAlphaMode]); +op.setPortGroup("Advanced Shader Parameters", [inToggleGR, inToggleNMGR, inUseVertexColours, inVertexColourMode, inHeightDepth, inUseOptimizedHeight, inUseClearCoat, inClearCoatRoughness]); +op.setPortGroup("Textures", [inTexAlbedo, inTexAORM, inTexNormal, inTexHeight, inLightmap]); +op.setPortGroup("Lighting", [inDiffuseIntensity, inSpecularIntensity, inLightmapIntensity, inLightmapRGBE, inTexIBLLUT, inTexIrradiance, inTexPrefiltered, inMipLevels]); +op.setPortGroup("Tonemapping", [inTonemapping, inTonemappingExposure]); +// globals +const PBRShader = new CGL.Shader(cgl, "PBRShader"); +PBRShader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); +// light sources (except IBL) +let PBRLightStack = []; +const lightUniforms = []; +const LIGHT_INDEX_REGEX = new RegExp("{{LIGHT_INDEX}}", "g"); +const FRAGMENT_HEAD_REGEX = new RegExp("{{PBR_FRAGMENT_HEAD}}", "g"); +const FRAGMENT_BODY_REGEX = new RegExp("{{PBR_FRAGMENT_BODY}}", "g"); +const lightFragmentHead = attachments.light_head_frag; +const lightFragmentBodies = { + "point": attachments.light_body_point_frag, + "directional": attachments.light_body_directional_frag, + "spot": attachments.light_body_spot_frag, +}; +const createLightFragmentHead = (n) => { return lightFragmentHead.replace("{{LIGHT_INDEX}}", n); }; +const createLightFragmentBody = (n, type) => +{ return (lightFragmentBodies[type] || "").replace(LIGHT_INDEX_REGEX, n); }; +let currentLightCount = -1; +const defaultLightStack = [{ + "type": "point", + "position": [5, 5, 5], + "color": [1, 1, 1], + "specular": [1, 1, 1], + "intensity": 120, + "attenuation": 0, + "falloff": 0.5, + "radius": 60, + "castLight": 1, +}]; + +if (cgl.glVersion == 1) +{ + if (!cgl.gl.getExtension("EXT_shader_texture_lod")) + { + op.log("no EXT_shader_texture_lod texture extension"); + throw "no EXT_shader_texture_lod texture extension"; + } + else + { + PBRShader.enableExtension("GL_EXT_shader_texture_lod"); + cgl.gl.getExtension("OES_texture_float"); + cgl.gl.getExtension("OES_texture_float_linear"); + cgl.gl.getExtension("OES_texture_half_float"); + cgl.gl.getExtension("OES_texture_half_float_linear"); + + PBRShader.enableExtension("GL_OES_standard_derivatives"); + PBRShader.enableExtension("GL_OES_texture_float"); + PBRShader.enableExtension("GL_OES_texture_float_linear"); + PBRShader.enableExtension("GL_OES_texture_half_float"); + PBRShader.enableExtension("GL_OES_texture_half_float_linear"); + } +} + +buildShader(); +// uniforms +const inAlbedoUniform = new CGL.Uniform(PBRShader, "t", "_AlbedoMap", 0); +const inAORMUniform = new CGL.Uniform(PBRShader, "t", "_AORMMap", 0); +const inNormalUniform = new CGL.Uniform(PBRShader, "t", "_NormalMap", 0); +const inIBLLUTUniform = new CGL.Uniform(PBRShader, "t", "IBL_BRDF_LUT", 0); +const inIrradianceUniform = new CGL.Uniform(PBRShader, "tc", "_irradiance", 1); +const inPrefilteredUniform = new CGL.Uniform(PBRShader, "tc", "_prefilteredEnvironmentColour", 1); +const inMipLevelsUniform = new CGL.Uniform(PBRShader, "f", "MAX_REFLECTION_LOD", 0); + +const inTonemappingExposureUniform = new CGL.Uniform(PBRShader, "f", "tonemappingExposure", inTonemappingExposure); +const inDiffuseIntensityUniform = new CGL.Uniform(PBRShader, "f", "diffuseIntensity", inDiffuseIntensity); +const inSpecularIntensityUniform = new CGL.Uniform(PBRShader, "f", "specularIntensity", inSpecularIntensity); + +const inHeightUniform = new CGL.Uniform(PBRShader, "t", "_HeightMap", 0); +const inLightmapUniform = new CGL.Uniform(PBRShader, "t", "_Lightmap", 0); +const inLightmapIntensityUniform = new CGL.Uniform(PBRShader, "f", "lightmapIntensity", inLightmapIntensity); + +const inDiffuseColor = new CGL.Uniform(PBRShader, "4f", "_Albedo", inDiffuseR, inDiffuseG, inDiffuseB, inDiffuseA); +const inRoughnessUniform = new CGL.Uniform(PBRShader, "f", "_Roughness", inRoughness); +const inMetalnessUniform = new CGL.Uniform(PBRShader, "f", "_Metalness", inMetalness); +const inHeightDepthUniform = new CGL.Uniform(PBRShader, "f", "_HeightDepth", inHeightDepth); +const inClearCoatRoughnessUniform = new CGL.Uniform(PBRShader, "f", "_ClearCoatRoughness", inClearCoatRoughness); + +const inPCOrigin = new CGL.Uniform(PBRShader, "3f", "_PCOrigin", [0, 0, 0]); +const inPCboxMin = new CGL.Uniform(PBRShader, "3f", "_PCboxMin", [-1, -1, -1]); +const inPCboxMax = new CGL.Uniform(PBRShader, "3f", "_PCboxMax", [1, 1, 1]); + +PBRShader.uniformColorDiffuse = inDiffuseColor; +PBRShader.uniformPbrMetalness = inMetalnessUniform; +PBRShader.uniformPbrRoughness = inRoughnessUniform; + +inTexPrefiltered.onChange = updateIBLTexDefines; + +inTexAORM.onChange = + inLightmapRGBE.onChange = + inUseClearCoat.onChange = + inTexAlbedo.onChange = + inTexNormal.onChange = + inTexHeight.onChange = + inAlphaMode.onChange = + inToggleNMGR.onChange = + inTonemapping.onChange = + inLightmap.onChange = + inUseOptimizedHeight.onChange = + inUseVertexColours.onChange = + inToggleGR.onChange = + inVertexColourMode.onChange = updateDefines; + +function updateDefines() +{ + PBRShader.toggleDefine("USE_OPTIMIZED_HEIGHT", inUseOptimizedHeight.get()); + PBRShader.toggleDefine("USE_CLEAR_COAT", inUseClearCoat.get()); + PBRShader.toggleDefine("LIGHTMAP_IS_RGBE", inLightmapRGBE.get()); + PBRShader.toggleDefine("USE_LIGHTMAP", inLightmap.isLinked() || inVertexColourMode.get() === "lightmap"); + PBRShader.toggleDefine("USE_NORMAL_TEX", inTexNormal.isLinked()); + PBRShader.toggleDefine("USE_HEIGHT_TEX", inTexHeight.isLinked()); + PBRShader.toggleDefine("DONT_USE_NMGR", inToggleNMGR.get()); + PBRShader.toggleDefine("DONT_USE_GR", inToggleGR.get()); + + // VERTEX_COLORS + PBRShader.toggleDefine("VCOL_COLOUR", inVertexColourMode.get() === "colour"); + PBRShader.toggleDefine("VCOL_AORM", inVertexColourMode.get() === "AORM"); + PBRShader.toggleDefine("VCOL_AO", inVertexColourMode.get() === "AO"); + PBRShader.toggleDefine("VCOL_R", inVertexColourMode.get() === "R"); + PBRShader.toggleDefine("VCOL_M", inVertexColourMode.get() === "M"); + PBRShader.toggleDefine("VCOL_LIGHTMAP", inVertexColourMode.get() === "lightmap"); + + // ALBEDO TEX + PBRShader.toggleDefine("USE_ALBEDO_TEX", inTexAlbedo.get()); + inDiffuseR.setUiAttribs({ "greyout": inTexAlbedo.isLinked() }); + inDiffuseG.setUiAttribs({ "greyout": inTexAlbedo.isLinked() }); + inDiffuseB.setUiAttribs({ "greyout": inTexAlbedo.isLinked() }); + inDiffuseA.setUiAttribs({ "greyout": inTexAlbedo.isLinked() }); + + // AORM + PBRShader.toggleDefine("USE_AORM_TEX", inTexAORM.get()); + inRoughness.setUiAttribs({ "greyout": inTexAORM.isLinked() }); + inMetalness.setUiAttribs({ "greyout": inTexAORM.isLinked() }); + + // lightmaps + PBRShader.toggleDefine("VERTEX_COLORS", inUseVertexColours.get()); + + if (!inUseVertexColours.get()) + { + PBRShader.toggleDefine("USE_LIGHTMAP", inLightmap.get()); + } + else + { + if (inVertexColourMode.get() === "lightmap") + { + PBRShader.define("USE_LIGHTMAP"); + } + } + + // alpha mode + PBRShader.toggleDefine("ALPHA_MASKED", inAlphaMode.get() === "Masked"); + PBRShader.toggleDefine("ALPHA_DITHERED", inAlphaMode.get() === "Dithered"); + PBRShader.toggleDefine("ALPHA_BLEND", inAlphaMode.get() === "Blend"); + + // tonemapping + PBRShader.toggleDefine("TONEMAP_sRGB", inTonemapping.get() === "sRGB"); + PBRShader.toggleDefine("TONEMAP_HejiDawson", inTonemapping.get() === "HejiDawson"); + PBRShader.toggleDefine("TONEMAP_Photographic", inTonemapping.get() === "Photographic"); +} + +updateDefines(); + +function setEnvironmentLighting(enabled) +{ + PBRShader.toggleDefine("USE_ENVIRONMENT_LIGHTING", enabled); +} + +op.preRender = function () +{ + PBRShader.bind(); + doRender(); +}; + +function updateIBLTexDefines() +{ + inMipLevels.setUiAttribs({ "greyout": !inTexPrefiltered.get() }); +} + +function updateLightUniforms() +{ + for (let i = 0; i < PBRLightStack.length; i += 1) + { + const light = PBRLightStack[i]; + light.isUsed = true; + + lightUniforms[i].position.setValue(light.position); + lightUniforms[i].color.setValue(light.color); + lightUniforms[i].specular.setValue(light.specular); + + lightUniforms[i].lightProperties.setValue([ + light.intensity, + light.attenuation, + light.falloff, + light.radius, + ]); + + lightUniforms[i].conePointAt.setValue(light.conePointAt); + lightUniforms[i].spotProperties.setValue([ + light.cosConeAngle, + light.cosConeAngleInner, + light.spotExponent, + ]); + + lightUniforms[i].castLight.setValue(light.castLight); + } +} + +function buildShader() +{ + const vertexShader = attachments.BasicPBR_vert; + const lightIncludes = attachments.light_includes_frag; + let fragmentShader = attachments.BasicPBR_frag; + + let fragmentHead = ""; + let fragmentBody = ""; + + if (PBRLightStack.length > 0) + { + fragmentHead = fragmentHead.concat(lightIncludes); + } + + for (let i = 0; i < PBRLightStack.length; i += 1) + { + const light = PBRLightStack[i]; + const type = light.type; + + fragmentHead = fragmentHead.concat(createLightFragmentHead(i) || ""); + fragmentBody = fragmentBody.concat(createLightFragmentBody(i, light.type) || ""); + } + + fragmentShader = fragmentShader.replace(FRAGMENT_HEAD_REGEX, fragmentHead || ""); + fragmentShader = fragmentShader.replace(FRAGMENT_BODY_REGEX, fragmentBody || ""); + + PBRShader.setSource(vertexShader, fragmentShader); + shaderOut.set(PBRShader); + + for (let i = 0; i < PBRLightStack.length; i += 1) + { + lightUniforms[i] = null; + if (!lightUniforms[i]) + { + lightUniforms[i] = { + "color": new CGL.Uniform(PBRShader, "3f", "lightOP" + i + ".color", [1, 1, 1]), + "position": new CGL.Uniform(PBRShader, "3f", "lightOP" + i + ".position", [0, 11, 0]), + "specular": new CGL.Uniform(PBRShader, "3f", "lightOP" + i + ".specular", [1, 1, 1]), + "lightProperties": new CGL.Uniform(PBRShader, "4f", "lightOP" + i + ".lightProperties", [1, 1, 1, 1]), + + "conePointAt": new CGL.Uniform(PBRShader, "3f", "lightOP" + i + ".conePointAt", vec3.create()), + "spotProperties": new CGL.Uniform(PBRShader, "3f", "lightOP" + i + ".spotProperties", [0, 0, 0, 0]), + "castLight": new CGL.Uniform(PBRShader, "i", "lightOP" + i + ".castLight", 1), + + }; + } + } +} + +function updateLights() +{ + if (cgl.frameStore.lightStack) + { + let changed = currentLightCount !== cgl.frameStore.lightStack.length; + + if (!changed) + { + for (let i = 0; i < cgl.frameStore.lightStack.length; i++) + { + if (PBRLightStack[i] != cgl.frameStore.lightStack[i]) + { + changed = true; + break; + } + } + } + + if (changed) + { + PBRLightStack = cgl.frameStore.lightStack; + buildShader(); + + currentLightCount = cgl.frameStore.lightStack.length; + } + } +} + +function doRender() +{ + cgl.pushShader(PBRShader); + let useDefaultLight = false; + + PBRShader.popTextures(); + + let numLights = 0; + if (cgl.frameStore.lightStack)numLights = cgl.frameStore.lightStack.length; + + if ((!cgl.frameStore.pbrEnvStack || cgl.frameStore.pbrEnvStack.length == 0) && + !inLightmap.isLinked() && numLights == 0) + + { + useDefaultLight = true; + op.setUiError("deflight", "Default light is enabled. Please add lights or PBREnvironmentLights to your patch to make this warning disappear.", 1); + } + else op.setUiError("deflight", null); + + if (cgl.frameStore.pbrEnvStack && cgl.frameStore.pbrEnvStack.length > 0 && + cgl.frameStore.pbrEnvStack[cgl.frameStore.pbrEnvStack.length - 1].texIBLLUT.tex && cgl.frameStore.pbrEnvStack[cgl.frameStore.pbrEnvStack.length - 1].texDiffIrr.tex && cgl.frameStore.pbrEnvStack[cgl.frameStore.pbrEnvStack.length - 1].texPreFiltered.tex) + { + const pbrEnv = cgl.frameStore.pbrEnvStack[cgl.frameStore.pbrEnvStack.length - 1]; + + PBRShader.pushTexture(inIBLLUTUniform, pbrEnv.texIBLLUT.tex); + PBRShader.pushTexture(inIrradianceUniform, pbrEnv.texDiffIrr.tex, cgl.gl.TEXTURE_CUBE_MAP); + PBRShader.pushTexture(inPrefilteredUniform, pbrEnv.texPreFiltered.tex, cgl.gl.TEXTURE_CUBE_MAP); + inMipLevelsUniform.setValue(pbrEnv.texPreFilteredMipLevels || 7); + + PBRShader.toggleDefine("USE_PARALLAX_CORRECTION", pbrEnv.UseParallaxCorrection); + if (pbrEnv.UseParallaxCorrection) + { + inPCOrigin.setValue(pbrEnv.PCOrigin); + inPCboxMin.setValue(pbrEnv.PCboxMin); + inPCboxMax.setValue(pbrEnv.PCboxMax); + } + + setEnvironmentLighting(true); + } + else + { + setEnvironmentLighting(false); + } + + if (useDefaultLight) + { + const iViewMatrix = mat4.create(); + mat4.invert(iViewMatrix, cgl.vMatrix); + + defaultLightStack[0].position = [iViewMatrix[12], iViewMatrix[13], iViewMatrix[14]]; + cgl.frameStore.lightStack = defaultLightStack; + } + + if (inTexIBLLUT.get()) + { + setEnvironmentLighting(true); + PBRShader.pushTexture(inIBLLUTUniform, inTexIBLLUT.get().tex); + inMipLevelsUniform.setValue(inMipLevels.get()); + if (inTexIrradiance.get()) PBRShader.pushTexture(inIrradianceUniform, inTexIrradiance.get().cubemap, cgl.gl.TEXTURE_CUBE_MAP); + if (inTexPrefiltered.get()) PBRShader.pushTexture(inPrefilteredUniform, inTexPrefiltered.get().cubemap, cgl.gl.TEXTURE_CUBE_MAP); + } + + if (inTexAlbedo.get()) PBRShader.pushTexture(inAlbedoUniform, inTexAlbedo.get().tex); + if (inTexAORM.get()) PBRShader.pushTexture(inAORMUniform, inTexAORM.get().tex); + if (inTexNormal.get()) PBRShader.pushTexture(inNormalUniform, inTexNormal.get().tex); + if (inTexHeight.get()) PBRShader.pushTexture(inHeightUniform, inTexHeight.get().tex); + if (inLightmap.get()) PBRShader.pushTexture(inLightmapUniform, inLightmap.get().tex); + + updateLights(); + updateLightUniforms(); + + outTrigger.trigger(); + cgl.popShader(); + + if (useDefaultLight) cgl.frameStore.lightStack = []; +} + + +}; + +Ops.Gl.Pbr.PbrMaterial.prototype = new CABLES.Op(); +CABLES.OPS["a5234947-f65a-41e2-a691-b81382903a71"]={f:Ops.Gl.Pbr.PbrMaterial,objName:"Ops.Gl.Pbr.PbrMaterial"}; + + + + +// ************************************************************** +// +// Ops.Gl.Performance +// +// ************************************************************** + +Ops.Gl.Performance = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + inShow = op.inValueBool("Visible", true), + next = op.outTrigger("childs"), + position = op.inSwitch("Position", ["top", "bottom"], "top"), + openDefault = op.inBool("Open", false), + smoothGraph = op.inBool("Smooth Graph", true), + inScaleGraph = op.inFloat("Scale", 4), + inSizeGraph = op.inFloat("Size", 128), + outCanv = op.outObject("Canvas"), + outFPS = op.outNumber("FPS"); + +const cgl = op.patch.cgl; +const element = document.createElement("div"); + +let elementMeasures = null; +let ctx = null; +let opened = false; +let frameCount = 0; +let fps = 0; +let fpsStartTime = 0; +let childsTime = 0; +let avgMsChilds = 0; +const queue = []; +const timesMainloop = []; +const timesOnFrame = []; +const timesGPU = []; +let avgMs = 0; +let selfTime = 0; +let canvas = null; +let lastTime = 0; +let loadingCounter = 0; +const loadingChars = ["|", "/", "-", "\\"]; +let initMeasures = true; + +const colorRAFSlow = "#ffffff"; +const colorBg = "#222222"; +const colorRAF = "#003f5c"; // color: https://learnui.design/tools/data-color-picker.html +const colorMainloop = "#7a5195"; +const colorOnFrame = "#ef5675"; +const colorGPU = "#ffa600"; + +let startedQuery = false; + +let currentTimeGPU = 0; +let currentTimeMainloop = 0; +let currentTimeOnFrame = 0; + +const gl = op.patch.cgl.gl; +const glQueryExt = gl.getExtension("EXT_disjoint_timer_query_webgl2"); +// let query = null; + +exe.onLinkChanged = + inShow.onChange = () => + { + updateOpened(); + updateVisibility(); + }; + +position.onChange = updatePos; +inSizeGraph.onChange = updateSize; + +element.id = "performance"; +element.style.position = "absolute"; +element.style.left = "0px"; +element.style.opacity = "0.8"; +element.style.padding = "10px"; +element.style.cursor = "pointer"; +element.style.background = "#222"; +element.style.color = "white"; +element.style["font-family"] = "monospace"; +element.style["font-size"] = "12px"; +element.style["z-index"] = "99999"; + +element.innerHTML = " "; +element.addEventListener("click", toggleOpened); + +const container = op.patch.cgl.canvas.parentElement; +container.appendChild(element); + +updateSize(); +updateOpened(); +updatePos(); +updateVisibility(); + +op.onDelete = function () +{ + if (canvas)canvas.remove(); + if (element)element.remove(); +}; + +function updatePos() +{ + canvas.style["pointer-events"] = "none"; + if (position.get() == "top") + { + canvas.style.top = element.style.top = "0px"; + canvas.style.bottom = element.style.bottom = "initial"; + } + else + { + canvas.style.bottom = element.style.bottom = "0px"; + canvas.style.top = element.style.top = "initial"; + } +} + +function updateVisibility() +{ + if (!inShow.get() || !exe.isLinked()) + { + element.style.display = "none"; + element.style.opacity = 0; + canvas.style.display = "none"; + } + else + { + element.style.display = "block"; + element.style.opacity = 1; + canvas.style.display = "block"; + } +} + +function updateSize() +{ + if (!canvas) return; + + const num = Math.max(0, parseInt(inSizeGraph.get())); + + canvas.width = num; + canvas.height = num; + element.style.left = num + "px"; + + queue.length = 0; + timesMainloop.length = 0; + timesOnFrame.length = 0; + timesGPU.length = 0; + + for (let i = 0; i < num; i++) + { + queue[i] = -1; + timesMainloop[i] = -1; + timesOnFrame[i] = -1; + timesGPU[i] = -1; + } +} + +openDefault.onChange = function () +{ + opened = openDefault.get(); + updateOpened(); +}; + +function toggleOpened() +{ + if (!inShow.get()) return; + element.style.opacity = 1; + opened = !opened; + updateOpened(); +} + +function updateOpened() +{ + updateText(); + if (!canvas)createCanvas(); + if (opened) + { + canvas.style.display = "block"; + element.style.left = inSizeGraph.get() + "px"; + element.style["min-height"] = "56px"; + } + else + { + canvas.style.display = "none"; + element.style.left = "0px"; + element.style["min-height"] = "auto"; + } +} + +function updateCanvas() +{ + const height = canvas.height; + const hmul = inScaleGraph.get(); + + ctx.fillStyle = colorBg; + ctx.fillRect(0, 0, canvas.width, height); + ctx.fillStyle = colorRAF; + + let k = 0; + const numBars = Math.max(0, parseInt(inSizeGraph.get())); + + for (k = numBars; k >= 0; k--) + { + if (queue[k] > 30)ctx.fillStyle = colorRAFSlow; + ctx.fillRect(numBars - k, height - queue[k] * hmul, 1, queue[k] * hmul); + if (queue[k] > 30)ctx.fillStyle = colorRAF; + } + + for (k = numBars; k >= 0; k--) + { + let sum = 0; + ctx.fillStyle = colorMainloop; + sum = timesMainloop[k]; + ctx.fillRect(numBars - k, height - sum * hmul, 1, timesMainloop[k] * hmul); + + ctx.fillStyle = colorOnFrame; + sum += timesOnFrame[k]; + ctx.fillRect(numBars - k, height - sum * hmul, 1, timesOnFrame[k] * hmul); + + ctx.fillStyle = colorGPU; + sum += timesGPU[k]; + ctx.fillRect(numBars - k, height - sum * hmul, 1, timesGPU[k] * hmul); + } +} + +function createCanvas() +{ + canvas = document.createElement("canvas"); + canvas.id = "performance_" + op.patch.config.glCanvasId; + canvas.width = inSizeGraph.get(); + canvas.height = inSizeGraph.get(); + canvas.style.display = "block"; + canvas.style.opacity = 0.9; + canvas.style.position = "absolute"; + canvas.style.left = "0px"; + canvas.style.cursor = "pointer"; + canvas.style.top = "-64px"; + canvas.style["z-index"] = "99998"; + container.appendChild(canvas); + ctx = canvas.getContext("2d"); + + canvas.addEventListener("click", toggleOpened); + + updateSize(); +} + +function updateText() +{ + if (!inShow.get()) return; + let warn = ""; + + if (op.patch.cgl.profileData.profileShaderCompiles > 0)warn += "Shader compile (" + op.patch.cgl.profileData.profileShaderCompileName + ") "; + if (op.patch.cgl.profileData.profileShaderGetUniform > 0)warn += "Shader get uni loc! (" + op.patch.cgl.profileData.profileShaderGetUniformName + ")"; + if (op.patch.cgl.profileData.profileTextureResize > 0)warn += "Texture resize! "; + if (op.patch.cgl.profileData.profileFrameBuffercreate > 0)warn += "Framebuffer create! "; + if (op.patch.cgl.profileData.profileEffectBuffercreate > 0)warn += "Effectbuffer create! "; + if (op.patch.cgl.profileData.profileTextureDelete > 0)warn += "Texture delete! "; + if (op.patch.cgl.profileData.profileNonTypedAttrib > 0)warn += "Not-Typed Buffer Attrib! " + op.patch.cgl.profileData.profileNonTypedAttribNames; + if (op.patch.cgl.profileData.profileTextureNew > 0)warn += "new texture created! "; + if (op.patch.cgl.profileData.profileGenMipMap > 0)warn += "generating mip maps!"; + + if (warn.length > 0) + { + warn = "| WARNING: " + warn + ""; + } + + let html = ""; + + if (opened) + { + html += " " + fps + " fps "; + html += " " + Math.round(currentTimeMainloop * 100) / 100 + "ms mainloop "; + html += " " + Math.round((currentTimeOnFrame) * 100) / 100 + "ms onframe "; + if (currentTimeGPU) html += " " + Math.round(currentTimeGPU * 100) / 100 + "ms GPU"; + html += warn; + element.innerHTML = html; + } + else + { + html += fps + " fps / "; + html += "CPU: " + Math.round((currentTimeMainloop + op.patch.cgl.profileData.profileOnAnimFrameOps) * 100) / 100 + "ms / "; + if (currentTimeGPU)html += "GPU: " + Math.round(currentTimeGPU * 100) / 100 + "ms "; + element.innerHTML = html; + } + + if (op.patch.loading.getProgress() != 1.0) + { + element.innerHTML += "
loading " + Math.round(op.patch.loading.getProgress() * 100) + "% " + loadingChars[(++loadingCounter) % loadingChars.length]; + } + + if (opened) + { + let count = 0; + avgMs = 0; + avgMsChilds = 0; + for (let i = queue.length; i > queue.length - queue.length / 3; i--) + { + if (queue[i] > -1) + { + avgMs += queue[i]; + count++; + } + + if (timesMainloop[i] > -1) avgMsChilds += timesMainloop[i]; + } + + avgMs /= count; + avgMsChilds /= count; + + element.innerHTML += "
" + cgl.canvasWidth + " x " + cgl.canvasHeight + " (x" + cgl.pixelDensity + ") "; + element.innerHTML += "
frame avg: " + Math.round(avgMsChilds * 100) / 100 + " ms (" + Math.round(avgMsChilds / avgMs * 100) + "%) / " + Math.round(avgMs * 100) / 100 + " ms"; + element.innerHTML += " (self: " + Math.round((selfTime) * 100) / 100 + " ms) "; + + element.innerHTML += "
shader binds: " + Math.ceil(op.patch.cgl.profileData.profileShaderBinds / fps) + + " uniforms: " + Math.ceil(op.patch.cgl.profileData.profileUniformCount / fps) + + " mvp_uni_mat4: " + Math.ceil(op.patch.cgl.profileData.profileMVPMatrixCount / fps) + + " num glPrimitives: " + Math.ceil(op.patch.cgl.profileData.profileMeshNumElements / (fps)) + + + " mesh.setGeom: " + op.patch.cgl.profileData.profileMeshSetGeom + + " videos: " + op.patch.cgl.profileData.profileVideosPlaying + + " tex preview: " + op.patch.cgl.profileData.profileTexPreviews; + + element.innerHTML += + " draw meshes: " + Math.ceil(op.patch.cgl.profileData.profileMeshDraw / fps) + + " framebuffer blit: " + Math.ceil(op.patch.cgl.profileData.profileFramebuffer / fps) + + " texeffect blit: " + Math.ceil(op.patch.cgl.profileData.profileTextureEffect / fps); + + element.innerHTML += " all shader compiletime: " + Math.round(op.patch.cgl.profileData.shaderCompileTime * 100) / 100; + } + + op.patch.cgl.profileData.clear(); +} + +function styleMeasureEle(ele) +{ + ele.style.padding = "0px"; + ele.style.margin = "0px"; +} + +function addMeasureChild(m, parentEle, timeSum, level) +{ + const height = 20; + m.usedAvg = (m.usedAvg || m.used); + + if (!m.ele || initMeasures) + { + const newEle = document.createElement("div"); + m.ele = newEle; + + if (m.childs && m.childs.length > 0) newEle.style.height = "500px"; + else newEle.style.height = height + "px"; + + newEle.style.overflow = "hidden"; + newEle.style.display = "inline-block"; + + if (!m.isRoot) + { + newEle.innerHTML = "
 " + m.name + "
"; + newEle.style["background-color"] = "rgb(" + m.colR + "," + m.colG + "," + m.colB + ")"; + newEle.style["border-left"] = "1px solid black"; + } + + parentEle.appendChild(newEle); + } + + if (!m.isRoot) + { + if (performance.now() - m.lastTime > 200) + { + m.ele.style.display = "none"; + m.hidden = true; + } + else + { + if (m.hidden) + { + m.ele.style.display = "inline-block"; + m.hidden = false; + } + } + + m.ele.style.float = "left"; + m.ele.style.width = Math.floor((m.usedAvg / timeSum) * 98.0) + "%"; + } + else + { + m.ele.style.width = "100%"; + m.ele.style.clear = "both"; + m.ele.style.float = "none"; + } + + if (m && m.childs && m.childs.length > 0) + { + let thisTimeSum = 0; + for (var i = 0; i < m.childs.length; i++) + { + m.childs[i].usedAvg = (m.childs[i].usedAvg || m.childs[i].used) * 0.95 + m.childs[i].used * 0.05; + thisTimeSum += m.childs[i].usedAvg; + } + for (var i = 0; i < m.childs.length; i++) + { + addMeasureChild(m.childs[i], m.ele, thisTimeSum, level + 1); + } + } +} + +function clearMeasures(p) +{ + for (let i = 0; i < p.childs.length; i++) clearMeasures(p.childs[i]); + p.childs.length = 0; +} + +function measures() +{ + if (!CGL.performanceMeasures) return; + + if (!elementMeasures) + { + op.log("create measure ele"); + elementMeasures = document.createElement("div"); + elementMeasures.style.width = "100%"; + elementMeasures.style["background-color"] = "#444"; + elementMeasures.style.bottom = "10px"; + elementMeasures.style.height = "100px"; + elementMeasures.style.opacity = "1"; + elementMeasures.style.position = "absolute"; + elementMeasures.style["z-index"] = "99999"; + elementMeasures.innerHTML = ""; + container.appendChild(elementMeasures); + } + + let timeSum = 0; + const root = CGL.performanceMeasures[0]; + + for (let i = 0; i < root.childs.length; i++) timeSum += root.childs[i].used; + + addMeasureChild(CGL.performanceMeasures[0], elementMeasures, timeSum, 0); + + root.childs.length = 0; + + clearMeasures(CGL.performanceMeasures[0]); + + CGL.performanceMeasures.length = 0; + initMeasures = false; +} + +exe.onTriggered = render; + +function render() +{ + const selfTimeStart = performance.now(); + frameCount++; + + if (glQueryExt && inShow.get())op.patch.cgl.profileData.doProfileGlQuery = true; + + if (fpsStartTime === 0)fpsStartTime = Date.now(); + if (Date.now() - fpsStartTime >= 1000) + { + // query=null; + fps = frameCount; + frameCount = 0; + // frames = 0; + outFPS.set(fps); + if (inShow.get())updateText(); + + fpsStartTime = Date.now(); + } + + const glQueryData = op.patch.cgl.profileData.glQueryData; + currentTimeGPU = 0; + if (glQueryData) + { + let count = 0; + for (let i in glQueryData) + { + count++; + if (glQueryData[i].time) + currentTimeGPU += glQueryData[i].time; + } + } + + if (inShow.get()) + { + measures(); + + if (opened && !op.patch.cgl.profileData.pause) + { + const timeUsed = performance.now() - lastTime; + queue.push(timeUsed); + queue.shift(); + + timesMainloop.push(childsTime); + timesMainloop.shift(); + + timesOnFrame.push(op.patch.cgl.profileData.profileOnAnimFrameOps - op.patch.cgl.profileData.profileMainloopMs); + timesOnFrame.shift(); + + timesGPU.push(currentTimeGPU); + timesGPU.shift(); + + updateCanvas(); + } + } + + lastTime = performance.now(); + selfTime = performance.now() - selfTimeStart; + const startTimeChilds = performance.now(); + + outCanv.set(null); + outCanv.set(canvas); + + // startGlQuery(); + next.trigger(); + // endGlQuery(); + + const nChildsTime = performance.now() - startTimeChilds; + const nCurrentTimeMainloop = op.patch.cgl.profileData.profileMainloopMs; + const nCurrentTimeOnFrame = op.patch.cgl.profileData.profileOnAnimFrameOps - op.patch.cgl.profileData.profileMainloopMs; + + if (smoothGraph.get()) + { + childsTime = childsTime * 0.9 + nChildsTime * 0.1; + currentTimeMainloop = currentTimeMainloop * 0.5 + nCurrentTimeMainloop * 0.5; + currentTimeOnFrame = currentTimeOnFrame * 0.5 + nCurrentTimeOnFrame * 0.5; + } + else + { + childsTime = nChildsTime; + currentTimeMainloop = nCurrentTimeMainloop; + currentTimeOnFrame = nCurrentTimeOnFrame; + } + + op.patch.cgl.profileData.clearGlQuery(); +} + + +}; + +Ops.Gl.Performance.prototype = new CABLES.Op(); +CABLES.OPS["9cd2d9de-000f-4a14-bd13-e7d5f057583c"]={f:Ops.Gl.Performance,objName:"Ops.Gl.Performance"}; + + + + +// ************************************************************** +// +// Ops.Gl.PerformanceMeasure +// +// ************************************************************** + +Ops.Gl.PerformanceMeasure = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Execute"), + inName = op.inString("Name"), + outNext = op.outTrigger("Childs"), + outUsed = op.outNumber("Time Used"); + +inExec.onTriggered = update; + +// var Measurement=function(_name) +// { +// this.name=_name; +// this.childs=[]; +// this.used=0; +// this.lastTime=performance.now(); +// this.colR=Math.floor(Math.random()*100)+128; +// this.colG=Math.floor(Math.random()*100)+128; +// this.colB=Math.floor(Math.random()*100)+128; +// }; + +// inExec.onLinkChanged=removeEle; +// outNext.onLinkChanged=removeEle; +// op.onDelete=removeEle; + +// function removeEle() +// { +// theMeasure.used=0; +// if(theMeasure.ele) +// theMeasure.ele.remove(); + +// theMeasure.ele=null; +// }; + +// inName.onChange=function() +// { +// theMeasure.name=inName.get(); +// removeEle(); +// }; + +// var theMeasure=new Measurement("m"); + +function update() +{ + // if(!CGL.performanceMeasures||CGL.performanceMeasures.length===0) + // { + + // CGL.rootMeasure=CGL.rootMeasure||new Measurement("Root"); + // CGL.rootMeasure.isRoot=true; + // CGL.performanceMeasures=[]; + // CGL.performanceMeasures.push(CGL.rootMeasure); + // CGL.currentPerfMeasurement=CGL.performanceMeasures[0]; + // } + + // theMeasure.childs.length=0; + // var prevMeasure=CGL.currentPerfMeasurement; + + // CGL.currentPerfMeasurement.childs.push(theMeasure); + // CGL.currentPerfMeasurement=theMeasure; + const startTime = performance.now(); + outNext.trigger(); + const used = performance.now() - startTime; + // theMeasure.used=(theMeasure.used*0.8+used*0.2); + // theMeasure.used=used; + // theMeasure.lastTime=performance.now(); + + // CGL.currentPerfMeasurement=prevMeasure; + outUsed.set(used); +} + + +}; + +Ops.Gl.PerformanceMeasure.prototype = new CABLES.Op(); +CABLES.OPS["a2f90e82-a907-4984-a3a1-8e036cf2eee5"]={f:Ops.Gl.PerformanceMeasure,objName:"Ops.Gl.PerformanceMeasure"}; + + + + +// ************************************************************** +// +// Ops.Gl.Perspective +// +// ************************************************************** + +Ops.Gl.Perspective = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + inAxis = op.inSwitch("Axis", ["Vertical", "Horizontal"], "Vertical"), + fovY = op.inValueFloat("fov y", 45), + zNear = op.inValueFloat("frustum near", 0.1), + zFar = op.inValueFloat("frustum far", 20), + autoAspect = op.inValueBool("Auto Aspect Ratio", true), + aspect = op.inValue("Aspect Ratio"), + trigger = op.outTrigger("trigger"), + outAsp = op.outNumber("Aspect"); + +fovY.onChange = zFar.onChange = zNear.onChange = changed; +fovY.setUiAttribs({ "title": "FOV Degrees" }); + +op.setPortGroup("Field of View", [fovY]); +op.setPortGroup("Frustrum", [zNear, zFar]); + +let asp = 0; +let axis = 0; + +changed(); + +inAxis.onChange = () => +{ + axis = 0; + if (inAxis.get() == "Horizontal")axis = 1; +}; + +render.onTriggered = function () +{ + const cg = op.patch.cg; + + asp = cg.getViewPort()[2] / cg.getViewPort()[3]; + if (!autoAspect.get())asp = aspect.get(); + outAsp.set(asp); + + cg.pushPMatrix(); + + if (axis == 0) + mat4.perspective(cg.pMatrix, fovY.get() * 0.0174533, asp, zNear.get(), zFar.get()); + else + perspectiveFovX(cg.pMatrix, fovY.get() * 0.0174533, asp, zNear.get(), zFar.get()); + + trigger.trigger(); + + cg.popPMatrix(); +}; + +function changed() +{ + op.patch.cgl.frameStore.perspective = + { + "fovy": fovY.get(), + "zFar": zFar.get(), + "zNear": zNear.get(), + }; +} + +function perspectiveFovX(out, fovx, aspect, near, far) +{ + let nf; + let f = 1 / (fovx) * 2; + // Math.tan(1 / fovx * 2), + // f=Math.max(0,f); + + op.log(f); + out[0] = f; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = f / (1.0 / aspect); + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[11] = -1; + out[12] = 0; + out[13] = 0; + out[15] = 0; + + if (far != null && far !== Infinity) + { + nf = 1 / (near - far); + out[10] = (far + near) * nf; + out[14] = 2 * far * near * nf; + } + else + { + out[10] = -1; + out[14] = -2 * near; + } + return out; +} + + +}; + +Ops.Gl.Perspective.prototype = new CABLES.Op(); +CABLES.OPS["7a78e163-d28c-4f70-a6d0-6d952da79f50"]={f:Ops.Gl.Perspective,objName:"Ops.Gl.Perspective"}; + + + + +// ************************************************************** +// +// Ops.Gl.Phong.AmbientLight_v4 +// +// ************************************************************** + +Ops.Gl.Phong.AmbientLight_v4 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inTrigger = op.inTrigger("Trigger In"); +const inR = op.inValueSlider("R", 0.1); +inR.setUiAttribs({ "colorPick": true }); +const inG = op.inValueSlider("G", 0.125); +const inB = op.inValueSlider("B", 0.15); +const inIntensity = op.inValueSlider("Intensity", 1); +const colorIn = [inR, inG, inB]; +op.setPortGroup("Color", colorIn); + +const outTrigger = op.outTrigger("Trigger Out"); +// your new op +// have a look at the documentation at: +// https://docs.cables.gl/dev_hello_op/dev_hello_op.html + +function Light(config) +{ + this.type = config.type || "point"; + this.color = config.color || [1, 1, 1]; + this.specular = config.specular || [0, 0, 0]; + this.position = config.position || null; + this.intensity = config.intensity || 1; + this.constantAttenuation = config.constantAttenuation || 0; + this.linearAttenuation = config.linearAttenuation || 0; + this.quadraticAttenuation = config.quadraticAttenuation || 0; + this.radius = config.radius || 1; + this.falloff = config.falloff || 1; + this.spotExponent = config.spotExponent || 1; + this.coneAngleInner = config.coneAngleInner || 0; // spot light + this.coneAngle = config.coneAngle || 0; // spot light + this.cosConeAngle = Math.cos(CGL.DEG2RAD * this.coneAngle); + this.conePointAt = config.conePointAt || [0, 0, 0]; + + // * shadow + this.nearFar = [0, 0]; + this.shadowStrength = 0; + this.shadowBias = 0; + + return this; +} + +const cgl = op.patch.cgl; + +const light = new Light({ + "type": "ambient", + "color": [0, 1, 2].map(function (i) { return colorIn[i].get(); }), + "intensity": inIntensity.get(), +}); + +const inLight = { + "color": [inR, inG, inB], + "intensity": inIntensity, +}; + +Object.keys(inLight).forEach(function (key) +{ + if (inLight[key].length) + { + for (let i = 0; i < inLight[key].length; i += 1) + { + inLight[key][i].onChange = function () + { + light[key][i] = inLight[key][i].get(); + }; + } + } + else + { + inLight[key].onChange = function () + { + light[key] = inLight[key].get(); + }; + } +}); + +inTrigger.onTriggered = function () +{ + if (!cgl.frameStore.lightStack) cgl.frameStore.lightStack = []; + + cgl.frameStore.lightStack.push(light); + outTrigger.trigger(); + cgl.frameStore.lightStack.pop(); +}; + + +}; + +Ops.Gl.Phong.AmbientLight_v4.prototype = new CABLES.Op(); +CABLES.OPS["235a18d1-a8de-4034-962d-2848017e27cd"]={f:Ops.Gl.Phong.AmbientLight_v4,objName:"Ops.Gl.Phong.AmbientLight_v4"}; + + + + +// ************************************************************** +// +// Ops.Gl.Phong.DirectionalLight_v5 +// +// ************************************************************** + +Ops.Gl.Phong.DirectionalLight_v5 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const cgl = op.patch.cgl; + +// * OP START * +const inTrigger = op.inTrigger("Trigger In"); + +const inCastLight = op.inBool("Cast Light", true); +const inIntensity = op.inFloat("Intensity", 1); +const attribIns = [inCastLight, inIntensity]; +op.setPortGroup("Light Attributes", attribIns); + +const inPosX = op.inFloat("X", 0); +const inPosY = op.inFloat("Y", 3); +const inPosZ = op.inFloat("Z", 5); + +const positionIn = [inPosX, inPosY, inPosZ]; +op.setPortGroup("Direction", positionIn); + +const inR = op.inFloat("R", 1); +const inG = op.inFloat("G", 1); +const inB = op.inFloat("B", 1); + +inR.setUiAttribs({ "colorPick": true }); +const colorIn = [inR, inG, inB]; +op.setPortGroup("Color", colorIn); + +const inSpecularR = op.inFloat("Specular R", 0.2); +const inSpecularG = op.inFloat("Specular G", 0.2); +const inSpecularB = op.inFloat("Specular B", 0.2); + +inSpecularR.setUiAttribs({ "colorPick": true }); +const colorSpecularIn = [inSpecularR, inSpecularG, inSpecularB]; +op.setPortGroup("Specular Color", colorSpecularIn); + +const inCastShadow = op.inBool("Cast Shadow", false); +const inRenderMapActive = op.inBool("Rendering Active", true); +const inMapSize = op.inSwitch("Map Size", [256, 512, 1024, 2048], 512); +const inShadowStrength = op.inFloatSlider("Shadow Strength", 1); +const inLRBT = op.inFloat("LR-BottomTop", 8); +const inNear = op.inFloat("Near", 0.1); +const inFar = op.inFloat("Far", 30); +const inBias = op.inFloatSlider("Bias", 0.004); +const inPolygonOffset = op.inInt("Polygon Offset", 0); +const inNormalOffset = op.inFloatSlider("Normal Offset", 0); +const inBlur = op.inFloatSlider("Blur Amount", 0); +op.setPortGroup("", [inCastShadow]); +op.setPortGroup("Shadow Map Settings", [inMapSize, inRenderMapActive, inShadowStrength, inLRBT, inNear, inFar, inBias, inPolygonOffset, inNormalOffset, inBlur]); + +inMapSize.setUiAttribs({ "greyout": true }); +inRenderMapActive.setUiAttribs({ "greyout": true }); +inShadowStrength.setUiAttribs({ "greyout": true }); +inLRBT.setUiAttribs({ "greyout": true, "hidePort": true }); +inNear.setUiAttribs({ "greyout": true, "hidePort": true }); +inFar.setUiAttribs({ "greyout": true, "hidePort": true }); +inBias.setUiAttribs({ "greyout": true, "hidePort": true }); +inNormalOffset.setUiAttribs({ "greyout": true, "hidePort": true }); +inPolygonOffset.setUiAttribs({ "greyout": true, "hidePort": true }); +inBlur.setUiAttribs({ "greyout": true }); + +const inAdvanced = op.inBool("Enable Advanced", false); +const inMSAA = op.inSwitch("MSAA", ["none", "2x", "4x", "8x"], "none"); +const inFilterType = op.inSwitch("Texture Filter", ["Linear", "Nearest", "Mip Map"], "Linear"); +const inAnisotropic = op.inSwitch("Anisotropic", [0, 1, 2, 4, 8, 16], "0"); +inMSAA.setUiAttribs({ "greyout": true, "hidePort": true }); +inFilterType.setUiAttribs({ "greyout": true, "hidePort": true }); +inAnisotropic.setUiAttribs({ "greyout": true, "hidePort": true }); +op.setPortGroup("Advanced Options", [inAdvanced, inMSAA, inFilterType, inAnisotropic]); + +inAdvanced.onChange = function () +{ + inMSAA.setUiAttribs({ "greyout": !inAdvanced.get() }); + inFilterType.setUiAttribs({ "greyout": !inAdvanced.get() }); + inAnisotropic.setUiAttribs({ "greyout": !inAdvanced.get() }); +}; + +const outTrigger = op.outTrigger("Trigger Out"); +const outTexture = op.outTexture("Shadow Map"); + +let texelSize = 1 / Number(inMapSize.get()); + +const newLight = new CGL.Light(cgl, { + "type": "directional", + "position": [0, 1, 2].map(function (i) { return positionIn[i].get(); }), + "color": [0, 1, 2].map(function (i) { return colorIn[i].get(); }), + "specular": [0, 1, 2].map(function (i) { return colorSpecularIn[i].get(); }), + "intensity": inIntensity.get(), + "castShadow": false, + "shadowStrength": inShadowStrength.get(), +}); +newLight.castLight = inCastLight.get(); + +let updating = false; + +function updateBuffers() +{ + updating = true; + const MSAA = Number(inMSAA.get().charAt(0)); + + let filterType = null; + const anisotropyFactor = Number(inAnisotropic.get()); + + if (inFilterType.get() == "Linear") + { + filterType = CGL.Texture.FILTER_LINEAR; + } + else if (inFilterType.get() == "Nearest") + { + filterType = CGL.Texture.FILTER_NEAREST; + } + else if (inFilterType.get() == "Mip Map") + { + filterType = CGL.Texture.FILTER_MIPMAP; + } + + const mapSize = Number(inMapSize.get()); + const textureOptions = { + "isFloatingPointTexture": true, + "filter": filterType, + }; + + if (MSAA) Object.assign(textureOptions, { "multisampling": true, "multisamplingSamples": MSAA }); + Object.assign(textureOptions, { "anisotropic": anisotropyFactor }); + + newLight.createFramebuffer(mapSize, mapSize, textureOptions); + newLight.createBlurEffect(textureOptions); + updating = false; +} + +function updateShadowMapFramebuffer() +{ + const size = Number(inMapSize.get()); + texelSize = 1 / size; + + if (inCastShadow.get()) + { + newLight.createFramebuffer(Number(inMapSize.get()), Number(inMapSize.get()), {}); + newLight.createShadowMapShader(); + newLight.createBlurEffect({}); + newLight.createBlurShader(); + newLight.updateProjectionMatrix(inLRBT.get(), inNear.get(), inFar.get(), null); + } + + if (inAdvanced.get()) updateBuffers(); + + updating = false; + updateLight = true; +} + +inMSAA.onChange = inAnisotropic.onChange = inFilterType.onChange = inMapSize.onChange = function () +{ + updating = true; +}; + +inR.onChange = inG.onChange = inB.onChange = inSpecularR.onChange = inSpecularG.onChange = inSpecularB.onChange += inPosX.onChange = inPosY.onChange = inPosZ.onChange += inBias.onChange = inIntensity.onChange = inCastLight.onChange = inShadowStrength.onChange = inNormalOffset.onChange = updateLightParameters; + +let updateLight = false; +function updateLightParameters(param) +{ + updateLight = true; +} + +inCastShadow.onChange = function () +{ + updating = true; + updateLight = true; + + const castShadow = inCastShadow.get(); + + inMapSize.setUiAttribs({ "greyout": !castShadow }); + inRenderMapActive.setUiAttribs({ "greyout": !castShadow }); + inShadowStrength.setUiAttribs({ "greyout": !castShadow }); + inLRBT.setUiAttribs({ "greyout": !castShadow }); + inNear.setUiAttribs({ "greyout": !castShadow }); + inFar.setUiAttribs({ "greyout": !castShadow }); + inBlur.setUiAttribs({ "greyout": !castShadow }); + inBias.setUiAttribs({ "greyout": !castShadow }); + inNormalOffset.setUiAttribs({ "greyout": !castShadow }); + inPolygonOffset.setUiAttribs({ "greyout": !castShadow }); +}; + +inLRBT.onChange = inNear.onChange = inFar.onChange = function () +{ + updateLight = true; +}; + +function drawHelpers() +{ + if (cgl.shouldDrawHelpers(op)) + { + gui.setTransformGizmo({ + "posX": inPosX, + "posY": inPosY, + "posZ": inPosZ, + }); + CABLES.GL_MARKER.drawLineSourceDest( + op, + -200 * newLight.position[0], + -200 * newLight.position[1], + -200 * newLight.position[2], + 200 * newLight.position[0], + 200 * newLight.position[1], + 200 * newLight.position[2], + ); + } +} + +let errorActive = false; +inTrigger.onTriggered = function () +{ + if (updating) + { + if (cgl.frameStore.shadowPass) return; + updateShadowMapFramebuffer(); + } + + if (!cgl.frameStore.shadowPass) + { + if (!newLight.isUsed && !errorActive) + { + op.setUiError("lightUsed", "No operator is using this light. Make sure this op is positioned before an operator that uses lights. Also make sure there is an operator that uses lights after this.", 1); // newLight.isUsed = false; + errorActive = true; + } + else if (!newLight.isUsed && errorActive) {} + else if (newLight.isUsed && errorActive) + { + op.setUiError("lightUsed", null); + errorActive = false; + } + else if (newLight.isUsed && !errorActive) {} + newLight.isUsed = false; + } + + if (updateLight) + { + newLight.color = [inR.get(), inG.get(), inB.get()]; + newLight.specular = [inSpecularR.get(), inSpecularG.get(), inSpecularB.get()]; + newLight.intensity = inIntensity.get(); + newLight.castLight = inCastLight.get(); + newLight.position = [inPosX.get(), inPosY.get(), inPosZ.get()]; + newLight.updateProjectionMatrix(inLRBT.get(), inNear.get(), inFar.get(), null); + newLight.castShadow = inCastShadow.get(); + + newLight.normalOffset = inNormalOffset.get(); + newLight.shadowBias = inBias.get(); + newLight.shadowStrength = inShadowStrength.get(); + updateLight = false; + } + + if (!cgl.frameStore.lightStack) cgl.frameStore.lightStack = []; + + if (!cgl.frameStore.shadowPass) drawHelpers(); + + cgl.frameStore.lightStack.push(newLight); + + if (inCastShadow.get()) + { + const blurAmount = 1.5 * inBlur.get() * texelSize; + if (inRenderMapActive.get()) newLight.renderPasses(inPolygonOffset.get(), blurAmount, function () { outTrigger.trigger(); }); + newLight.blurAmount = inBlur.get(); + outTexture.set(null); + outTexture.set(newLight.getShadowMapDepth()); + // remove light from stack and readd it with shadow map & mvp matrix + cgl.frameStore.lightStack.pop(); + + cgl.frameStore.lightStack.push(newLight); + } + else + { + outTexture.set(null); + } + + outTrigger.trigger(); + + cgl.frameStore.lightStack.pop(); +}; + + +}; + +Ops.Gl.Phong.DirectionalLight_v5.prototype = new CABLES.Op(); +CABLES.OPS["9f41bf91-f4e0-4ce4-89d8-72627b76261e"]={f:Ops.Gl.Phong.DirectionalLight_v5,objName:"Ops.Gl.Phong.DirectionalLight_v5"}; + + + + +// ************************************************************** +// +// Ops.Gl.Phong.LambertMaterial_v2 +// +// ************************************************************** + +Ops.Gl.Phong.LambertMaterial_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"lambert_frag":"{{MODULES_HEAD}}\n\n#define AMBIENT 0\n#define POINT 1\n#define DIRECTIONAL 2\n#define SPOT 3\n\nIN vec3 norm;\nIN vec4 modelPos;\n\n// UNI mat4 normalMatrix;\nIN mat3 normalMatrix; // when instancing...\n\nIN vec2 texCoord;\n\nIN vec3 mvNormal;\nIN vec3 mvTangent;\nIN vec3 mvBiTangent;\n\nUNI vec4 materialColor;//r,g,b,a;\n\nstruct Light {\n vec3 position;\n vec3 color;\n // * SPOT LIGHT * //\n #ifdef HAS_SPOT\n vec3 conePointAt;\n #define COSCONEANGLE x\n #define COSCONEANGLEINNER y\n #define SPOTEXPONENT z\n vec3 spotProperties;\n #endif\n\n #define INTENSITY x\n #define ATTENUATION y\n #define FALLOFF z\n #define RADIUS w\n vec4 lightProperties;\n\n int type;\n int castLight;\n #define CASTLIGHT x\n #define TYPE y\n ivec2 castLightType;\n};\n#ifdef HAS_TEXTURES\n #ifdef HAS_TEXTURE_DIFFUSE\n UNI sampler2D texDiffuse;\n #endif\n#endif\n\nUNI Light lights[NUM_LIGHTS];\n\n// * UTILITY FUNCTIONS */\nfloat when_gt(float x, float y) { return max(sign(x - y), 0.0); } // comparator function\nfloat when_eq(float x, float y) { return 1. - abs(sign(x - y)); } // comparator function\nfloat when_neq(float x, float y) { return abs(sign(x - y)); } // comparator function\n\n\n// * LIGHT CALCULATIONS */\nfloat CalculateFalloff(float radius, float falloff, float distLight)\n{\n float denom = distLight / radius + 1.0;\n float attenuation = 1.0 / (denom*denom);\n float t = (attenuation - 0.1) / (1.0 - 0.1);\n\n t = t * (20.0 * (1. - falloff) * 20.0 * (1. - falloff));\n\n return min(1.0,max(t, 0.0));\n}\n\nfloat Falloff2(vec3 lightDirection, float falloff) {\n float distanceSquared = dot(lightDirection, lightDirection);\n float factor = distanceSquared * falloff;\n float smoothFactor = clamp(1. - factor * factor, 0., 1.);\n float attenuation = smoothFactor * smoothFactor;\n\n return attenuation * 1. / max(distanceSquared, 0.00001);\n}\n\n#ifdef HAS_SPOT\n float CalculateSpotLightEffect(vec3 lightPosition, vec3 conePointAt, float cosConeAngle, float cosConeAngleInner, float spotExponent, vec3 lightDirection) {\n vec3 spotLightDirection = normalize(lightPosition-conePointAt);\n float spotAngle = dot(-lightDirection, spotLightDirection);\n float epsilon = cosConeAngle - cosConeAngleInner;\n\n float spotIntensity = clamp((spotAngle - cosConeAngle)/epsilon, 0.0, 1.0);\n spotIntensity = pow(spotIntensity, max(0.01, spotExponent));\n\n return max(0., spotIntensity);\n }\n#endif\nvec3 CalculateDiffuseColor(vec3 lightDirection, vec3 normal, vec3 lightColor, vec3 materialColor, inout float lambert) {\n lambert = clamp(dot(lightDirection, normal), 0., 1.);\n vec3 diffuseColor = lambert * lightColor * materialColor;\n return diffuseColor;\n}\n\n\n// MAIN\nvoid main()\n{\n {{MODULE_BEGIN_FRAG}}\n\n vec4 col=vec4(0.0);\n vec3 normal = normalize(mat3(normalMatrix)*norm);\n\n #ifdef DOUBLE_SIDED\n if(!gl_FrontFacing) normal = normal*-1.0;\n #endif\n\n vec3 matColor = materialColor.rgb;\n\n #ifdef HAS_TEXTURES\n #ifdef HAS_TEXTURE_DIFFUSE\n matColor = texture(texDiffuse, texCoord).rgb;\n #ifdef COLORIZE_TEXTURE\n matColor *= materialColor.rgb;\n #endif\n #endif\n #endif\n\n for(int l=0;l { return attachmentFragmentHead.replace("{{LIGHT_INDEX}}", n); }; +const createFragmentBody = (n, type) => { return snippets[type].replace(LIGHT_INDEX_REGEX, n); }; + +function createDefaultShader() +{ + const vertexShader = attachments.phong_vert; + let fragmentShader = attachments.phong_frag; + let fragmentHead = ""; + let fragmentBody = ""; + + fragmentHead = fragmentHead.concat(createFragmentHead(0)); + fragmentBody = fragmentBody.concat(createFragmentBody(0, DEFAULT_LIGHTSTACK[0].type)); + + fragmentShader = fragmentShader.replace(FRAGMENT_HEAD_REGEX, fragmentHead); + fragmentShader = fragmentShader.replace(FRAGMENT_BODY_REGEX, fragmentBody); + + shader.setSource(vertexShader, fragmentShader); + shader.define("HAS_POINT"); + shader.removeDefine("HAS_SPOT"); + shader.removeDefine("HAS_DIRECTIONAL"); + shader.removeDefine("HAS_AMBIENT"); +} + +const inTrigger = op.inTrigger("Trigger In"); + +// * DIFFUSE * +const inDiffuseR = op.inFloat("R", Math.random()); +const inDiffuseG = op.inFloat("G", Math.random()); +const inDiffuseB = op.inFloat("B", Math.random()); +const inDiffuseA = op.inFloatSlider("A", 1); +const diffuseColors = [inDiffuseR, inDiffuseG, inDiffuseB, inDiffuseA]; +op.setPortGroup("Diffuse Color", diffuseColors); + +const inToggleOrenNayar = op.inBool("Enable", false); +const inAlbedo = op.inFloatSlider("Albedo", 0.707); +const inRoughness = op.inFloatSlider("Roughness", 0.835); + +inToggleOrenNayar.setUiAttribs({ "hidePort": true }); +inAlbedo.setUiAttribs({ "greyout": true }); +inRoughness.setUiAttribs({ "greyout": true }); +inDiffuseR.setUiAttribs({ "colorPick": true }); +op.setPortGroup("Oren-Nayar Diffuse", [inToggleOrenNayar, inAlbedo, inRoughness]); + +inToggleOrenNayar.onChange = function () +{ + shader.toggleDefine("ENABLE_OREN_NAYAR_DIFFUSE", inToggleOrenNayar); + inAlbedo.setUiAttribs({ "greyout": !inToggleOrenNayar.get() }); + inRoughness.setUiAttribs({ "greyout": !inToggleOrenNayar.get() }); +}; + +// * FRESNEL * +const inToggleFresnel = op.inValueBool("Active", false); +inToggleFresnel.setUiAttribs({ "hidePort": true }); +const inFresnel = op.inValueSlider("Fresnel Intensity", 0.7); +const inFresnelWidth = op.inFloat("Fresnel Width", 1); +const inFresnelExponent = op.inFloat("Fresnel Exponent", 6); +const inFresnelR = op.inFloat("Fresnel R", 1); +const inFresnelG = op.inFloat("Fresnel G", 1); +const inFresnelB = op.inFloat("Fresnel B", 1); +inFresnelR.setUiAttribs({ "colorPick": true }); + +const fresnelArr = [inFresnel, inFresnelWidth, inFresnelExponent, inFresnelR, inFresnelG, inFresnelB]; +fresnelArr.forEach(function (port) { port.setUiAttribs({ "greyout": true }); }); +op.setPortGroup("Fresnel", fresnelArr.concat([inToggleFresnel])); + +let uniFresnel = null; +let uniFresnelWidthExponent = null; +inToggleFresnel.onChange = function () +{ + shader.toggleDefine("ENABLE_FRESNEL", inToggleFresnel); + if (inToggleFresnel.get()) + { + if (!uniFresnel) uniFresnel = new CGL.Uniform(shader, "4f", "inFresnel", inFresnelR, inFresnelG, inFresnelB, inFresnel); + if (!uniFresnelWidthExponent) uniFresnelWidthExponent = new CGL.Uniform(shader, "2f", "inFresnelWidthExponent", inFresnelWidth, inFresnelExponent); + } + else + { + if (uniFresnel) + { + shader.removeUniform("inFresnel"); + uniFresnel = null; + } + + if (uniFresnelWidthExponent) + { + shader.removeUniform("inFresnelWidthExponent"); + uniFresnelWidthExponent = null; + } + } + + fresnelArr.forEach(function (port) { port.setUiAttribs({ "greyout": !inToggleFresnel.get() }); }); +}; +// * EMISSIVE * +const inEmissiveActive = op.inBool("Emissive Active", false); +const inEmissiveColorIntensity = op.inFloatSlider("Color Intensity", 0.3); +const inEmissiveR = op.inFloatSlider("Emissive R", Math.random()); +const inEmissiveG = op.inFloatSlider("Emissive G", Math.random()); +const inEmissiveB = op.inFloatSlider("Emissive B", Math.random()); +inEmissiveR.setUiAttribs({ "colorPick": true }); +op.setPortGroup("Emissive Color", [inEmissiveActive, inEmissiveColorIntensity, inEmissiveR, inEmissiveG, inEmissiveB]); + +inEmissiveColorIntensity.setUiAttribs({ "greyout": !inEmissiveActive.get() }); +inEmissiveR.setUiAttribs({ "greyout": !inEmissiveActive.get() }); +inEmissiveG.setUiAttribs({ "greyout": !inEmissiveActive.get() }); +inEmissiveB.setUiAttribs({ "greyout": !inEmissiveActive.get() }); + +let uniEmissiveColor = null; + +inEmissiveActive.onChange = () => +{ + shader.toggleDefine("ADD_EMISSIVE_COLOR", inEmissiveActive); + + if (inEmissiveActive.get()) + { + uniEmissiveColor = new CGL.Uniform(shader, "4f", "inEmissiveColor", inEmissiveR, inEmissiveG, inEmissiveB, inEmissiveColorIntensity); + inEmissiveTexture.setUiAttribs({ "greyout": false }); + inEmissiveMaskTexture.setUiAttribs({ "greyout": false }); + + if (inEmissiveTexture.get()) inEmissiveIntensity.setUiAttribs({ "greyout": false }); + if (inEmissiveMaskTexture.get()) inEmissiveMaskIntensity.setUiAttribs({ "greyout": false }); + } + else + { + op.log("ayayay"); + inEmissiveTexture.setUiAttribs({ "greyout": true }); + inEmissiveMaskTexture.setUiAttribs({ "greyout": true }); + inEmissiveIntensity.setUiAttribs({ "greyout": true }); + inEmissiveMaskIntensity.setUiAttribs({ "greyout": true }); + + shader.removeUniform("inEmissiveColor"); + uniEmissiveColor = null; + } + + if (inEmissiveTexture.get()) + { + inEmissiveColorIntensity.setUiAttribs({ "greyout": true }); + inEmissiveR.setUiAttribs({ "greyout": true }); + inEmissiveG.setUiAttribs({ "greyout": true }); + inEmissiveB.setUiAttribs({ "greyout": true }); + } + else + { + if (inEmissiveActive.get()) + { + inEmissiveColorIntensity.setUiAttribs({ "greyout": false }); + inEmissiveR.setUiAttribs({ "greyout": false }); + inEmissiveG.setUiAttribs({ "greyout": false }); + inEmissiveB.setUiAttribs({ "greyout": false }); + } + else + { + inEmissiveColorIntensity.setUiAttribs({ "greyout": true }); + inEmissiveR.setUiAttribs({ "greyout": true }); + inEmissiveG.setUiAttribs({ "greyout": true }); + inEmissiveB.setUiAttribs({ "greyout": true }); + } + } +}; +// * SPECULAR * +const inShininess = op.inFloat("Shininess", 4); +const inSpecularCoefficient = op.inFloatSlider("Specular Amount", 0.5); +const inSpecularMode = op.inSwitch("Specular Model", ["Blinn", "Schlick", "Phong", "Gauss"], "Blinn"); + +inSpecularMode.setUiAttribs({ "hidePort": true }); +const specularColors = [inShininess, inSpecularCoefficient, inSpecularMode]; +op.setPortGroup("Specular", specularColors); + +// * LIGHT * +const inEnergyConservation = op.inValueBool("Energy Conservation", false); +const inToggleDoubleSided = op.inBool("Double Sided Material", false); +const inFalloffMode = op.inSwitch("Falloff Mode", ["A", "B", "C", "D"], "A"); +inEnergyConservation.setUiAttribs({ "hidePort": true }); +inToggleDoubleSided.setUiAttribs({ "hidePort": true }); +inFalloffMode.setUiAttribs({ "hidePort": true }); +inFalloffMode.onChange = () => +{ + const MODES = ["A", "B", "C", "D"]; + shader.define("FALLOFF_MODE_" + inFalloffMode.get()); + MODES.filter((mode) => { return mode !== inFalloffMode.get(); }) + .forEach((mode) => { return shader.removeDefine("FALLOFF_MODE_" + mode); }); +}; + +const lightProps = [inEnergyConservation, inToggleDoubleSided, inFalloffMode]; +op.setPortGroup("Light Options", lightProps); + +// TEXTURES +const inDiffuseTexture = op.inTexture("Diffuse Texture"); +const inSpecularTexture = op.inTexture("Specular Texture"); +const inNormalTexture = op.inTexture("Normal Map"); +const inAoTexture = op.inTexture("AO Texture"); +const inEmissiveTexture = op.inTexture("Emissive Texture"); +const inEmissiveMaskTexture = op.inTexture("Emissive Mask"); +const inAlphaTexture = op.inTexture("Opacity Texture"); +const inEnvTexture = op.inTexture("Environment Map"); +const inLuminanceMaskTexture = op.inTexture("Env Map Mask"); +op.setPortGroup("Textures", [inDiffuseTexture, inSpecularTexture, inNormalTexture, inAoTexture, inEmissiveTexture, inEmissiveMaskTexture, inAlphaTexture, inEnvTexture, inLuminanceMaskTexture]); + +// TEXTURE TRANSFORMS +const inColorizeTexture = op.inBool("Colorize Texture", false); +const inDiffuseRepeatX = op.inFloat("Diffuse Repeat X", 1); +const inDiffuseRepeatY = op.inFloat("Diffuse Repeat Y", 1); +const inTextureOffsetX = op.inFloat("Texture Offset X", 0); +const inTextureOffsetY = op.inFloat("Texture Offset Y", 0); + +const inSpecularIntensity = op.inFloatSlider("Specular Intensity", 1); +const inNormalIntensity = op.inFloatSlider("Normal Map Intensity", 0.5); +const inAoIntensity = op.inFloatSlider("AO Intensity", 1); +const inEmissiveIntensity = op.inFloatSlider("Emissive Intensity", 1); +const inEmissiveMaskIntensity = op.inFloatSlider("Emissive Mask Intensity", 1); +const inEnvMapIntensity = op.inFloatSlider("Env Map Intensity", 1); +const inEnvMapBlend = op.inSwitch("Env Map Blend", ["Add", "Multiply", "Mix"], "Add"); +const inLuminanceMaskIntensity = op.inFloatSlider("Env Mask Intensity", 1); + +inColorizeTexture.setUiAttribs({ "hidePort": true }); +op.setPortGroup("Texture Transforms", [inColorizeTexture, inDiffuseRepeatY, inDiffuseRepeatX, inTextureOffsetY, inTextureOffsetX]); +op.setPortGroup("Texture Intensities", [inNormalIntensity, inAoIntensity, inSpecularIntensity, inEmissiveIntensity, inEnvMapBlend, inEmissiveMaskIntensity, inEnvMapIntensity, inLuminanceMaskIntensity]); +const alphaMaskSource = op.inSwitch("Alpha Mask Source", ["Luminance", "R", "G", "B", "A"], "Luminance"); +alphaMaskSource.setUiAttribs({ "greyout": true }); + +const discardTransPxl = op.inValueBool("Discard Transparent Pixels"); +discardTransPxl.setUiAttribs({ "hidePort": true }); + +op.setPortGroup("Opacity Texture", [alphaMaskSource, discardTransPxl]); + +const outTrigger = op.outTrigger("Trigger Out"); +const shaderOut = op.outObject("Shader", null, "shader"); +shaderOut.ignoreValueSerialize = true; + +const shader = new CGL.Shader(cgl, "phongmaterial_" + op.id); +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG", "MODULE_BASE_COLOR"]); +shader.setSource(attachments.simosphong_vert, attachments.simosphong_frag); +let recompileShader = false; +shader.define("FALLOFF_MODE_A"); + +if (cgl.glVersion < 2) +{ + shader.enableExtension("GL_OES_standard_derivatives"); + + if (cgl.gl.getExtension("OES_texture_float")) shader.enableExtension("GL_OES_texture_float"); + else op.log("error loading extension OES_texture_float"); + + if (cgl.gl.getExtension("OES_texture_float_linear")) shader.enableExtension("GL_OES_texture_float_linear"); + else op.log("error loading extention OES_texture_float_linear"); + + if (cgl.gl.getExtension("GL_OES_texture_half_float")) shader.enableExtension("GL_OES_texture_half_float"); + else op.log("error loading extention GL_OES_texture_half_float"); + + if (cgl.gl.getExtension("GL_OES_texture_half_float_linear")) shader.enableExtension("GL_OES_texture_half_float_linear"); + else op.log("error loading extention GL_OES_texture_half_float_linear"); +} + +const FRAGMENT_HEAD_REGEX = new RegExp("{{PHONG_FRAGMENT_HEAD}}", "g"); +const FRAGMENT_BODY_REGEX = new RegExp("{{PHONG_FRAGMENT_BODY}}", "g"); + +const hasLight = { + "directional": false, + "spot": false, + "ambient": false, + "point": false, +}; + +function createShader(lightStack) +{ + let fragmentShader = attachments.phong_frag; + + let fragmentHead = ""; + let fragmentBody = ""; + + hasLight.directional = false; + hasLight.spot = false; + hasLight.ambient = false; + hasLight.point = false; + + for (let i = 0; i < lightStack.length; i += 1) + { + const light = lightStack[i]; + + const type = light.type; + + if (!hasLight[type]) + { + hasLight[type] = true; + } + + fragmentHead = fragmentHead.concat(createFragmentHead(i)); + fragmentBody = fragmentBody.concat(createFragmentBody(i, light.type)); + } + + fragmentShader = fragmentShader.replace(FRAGMENT_HEAD_REGEX, fragmentHead); + fragmentShader = fragmentShader.replace(FRAGMENT_BODY_REGEX, fragmentBody); + + shader.setSource(attachments.phong_vert, fragmentShader); + + for (let i = 0, keys = Object.keys(hasLight); i < keys.length; i += 1) + { + const key = keys[i]; + + if (hasLight[key]) + { + if (!shader.hasDefine("HAS_" + key.toUpperCase())) + { + shader.define("HAS_" + key.toUpperCase()); + } + } + else + { + if (shader.hasDefine("HAS_" + key.toUpperCase())) + { + shader.removeDefine("HAS_" + key.toUpperCase()); + } + } + } +} + +shaderOut.set(shader); + +let diffuseTextureUniform = null; +let specularTextureUniform = null; +let normalTextureUniform = null; +let aoTextureUniform = null; +let emissiveTextureUniform = null; +let emissiveMaskTextureUniform = null; +let emissiveMaskIntensityUniform = null; +let alphaTextureUniform = null; +let envTextureUniform = null; +let inEnvMapIntensityUni = null; +let inEnvMapWidthUni = null; +let luminanceTextureUniform = null; +let inLuminanceMaskIntensityUniform = null; + +inColorizeTexture.onChange = function () +{ + shader.toggleDefine("COLORIZE_TEXTURE", inColorizeTexture.get()); +}; + +function updateDiffuseTexture() +{ + if (inDiffuseTexture.get()) + { + if (!shader.hasDefine("HAS_TEXTURE_DIFFUSE")) + { + shader.define("HAS_TEXTURE_DIFFUSE"); + if (!diffuseTextureUniform) diffuseTextureUniform = new CGL.Uniform(shader, "t", "texDiffuse", 0); + } + } + else + { + shader.removeUniform("texDiffuse"); + shader.removeDefine("HAS_TEXTURE_DIFFUSE"); + diffuseTextureUniform = null; + } +} + +function updateSpecularTexture() +{ + if (inSpecularTexture.get()) + { + inSpecularIntensity.setUiAttribs({ "greyout": false }); + if (!shader.hasDefine("HAS_TEXTURE_SPECULAR")) + { + shader.define("HAS_TEXTURE_SPECULAR"); + if (!specularTextureUniform) specularTextureUniform = new CGL.Uniform(shader, "t", "texSpecular", 0); + } + } + else + { + inSpecularIntensity.setUiAttribs({ "greyout": true }); + shader.removeUniform("texSpecular"); + shader.removeDefine("HAS_TEXTURE_SPECULAR"); + specularTextureUniform = null; + } +} + +function updateNormalTexture() +{ + if (inNormalTexture.get()) + { + inNormalIntensity.setUiAttribs({ "greyout": false }); + + if (!shader.hasDefine("HAS_TEXTURE_NORMAL")) + { + shader.define("HAS_TEXTURE_NORMAL"); + if (!normalTextureUniform) normalTextureUniform = new CGL.Uniform(shader, "t", "texNormal", 0); + } + } + else + { + inNormalIntensity.setUiAttribs({ "greyout": true }); + + shader.removeUniform("texNormal"); + shader.removeDefine("HAS_TEXTURE_NORMAL"); + normalTextureUniform = null; + } +} + +aoTextureUniform = new CGL.Uniform(shader, "t", "texAO"); + +function updateAoTexture() +{ + shader.toggleDefine("HAS_TEXTURE_AO", inAoTexture.get()); + + inAoIntensity.setUiAttribs({ "greyout": !inAoTexture.get() }); + + // if (inAoTexture.get()) + // { + // // inAoIntensity.setUiAttribs({ "greyout": false }); + + // // if (!shader.hasDefine("HAS_TEXTURE_AO")) + // // { + // // shader.define("HAS_TEXTURE_AO"); + // // if (!aoTextureUniform) + // aoTextureUniform = new CGL.Uniform(shader, "t", "texAO", 0); + // // } + // } + // else + // { + // // inAoIntensity.setUiAttribs({ "greyout": true }); + + // shader.removeUniform("texAO"); + // // shader.removeDefine("HAS_TEXTURE_AO"); + // aoTextureUniform = null; + // } +} + +function updateEmissiveTexture() +{ + if (inEmissiveTexture.get()) + { + inEmissiveR.setUiAttribs({ "greyout": true }); + inEmissiveG.setUiAttribs({ "greyout": true }); + inEmissiveB.setUiAttribs({ "greyout": true }); + inEmissiveColorIntensity.setUiAttribs({ "greyout": true }); + + if (inEmissiveActive.get()) + { + inEmissiveIntensity.setUiAttribs({ "greyout": false }); + } + + if (!shader.hasDefine("HAS_TEXTURE_EMISSIVE")) + { + shader.define("HAS_TEXTURE_EMISSIVE"); + if (!emissiveTextureUniform) emissiveTextureUniform = new CGL.Uniform(shader, "t", "texEmissive", 0); + } + } + else + { + inEmissiveIntensity.setUiAttribs({ "greyout": true }); + + if (inEmissiveActive.get()) + { + inEmissiveR.setUiAttribs({ "greyout": false }); + inEmissiveG.setUiAttribs({ "greyout": false }); + inEmissiveB.setUiAttribs({ "greyout": false }); + inEmissiveColorIntensity.setUiAttribs({ "greyout": false }); + } + else + { + inEmissiveTexture.setUiAttribs({ "greyout": true }); + } + + shader.removeUniform("texEmissive"); + shader.removeDefine("HAS_TEXTURE_EMISSIVE"); + emissiveTextureUniform = null; + } +} + +function updateEmissiveMaskTexture() +{ + if (inEmissiveMaskTexture.get()) + { // we have a emissive texture + if (inEmissiveActive.get()) + { + inEmissiveMaskIntensity.setUiAttribs({ "greyout": false }); + } + + if (!shader.hasDefine("HAS_TEXTURE_EMISSIVE_MASK")) + { + shader.define("HAS_TEXTURE_EMISSIVE_MASK"); + if (!emissiveMaskTextureUniform) emissiveMaskTextureUniform = new CGL.Uniform(shader, "t", "texMaskEmissive", 0); + if (!emissiveMaskIntensityUniform) emissiveMaskIntensityUniform = new CGL.Uniform(shader, "f", "inEmissiveMaskIntensity", inEmissiveMaskIntensity); + } + } + else + { + if (!inEmissiveActive.get()) + { + inEmissiveMaskTexture.setUiAttribs({ "greyout": true }); + } + inEmissiveMaskIntensity.setUiAttribs({ "greyout": true }); + shader.removeUniform("texMaskEmissive"); + shader.removeUniform("inEmissiveMaskIntensity"); + shader.removeDefine("HAS_TEXTURE_EMISSIVE_MASK"); + emissiveMaskTextureUniform = null; + emissiveMaskIntensityUniform = null; + } +} + +let updateEnvTextureLater = false; +function updateEnvTexture() +{ + shader.toggleDefine("HAS_TEXTURE_ENV", inEnvTexture.get()); + + inEnvMapIntensity.setUiAttribs({ "greyout": !inEnvTexture.get() }); + + if (inEnvTexture.get()) + { + if (!envTextureUniform) envTextureUniform = new CGL.Uniform(shader, "t", "texEnv", 0); + + shader.toggleDefine("TEX_FORMAT_CUBEMAP", inEnvTexture.get().cubemap); + + if (inEnvTexture.get().cubemap) + { + shader.removeDefine("TEX_FORMAT_EQUIRECT"); + shader.removeDefine("ENVMAP_MATCAP"); + if (!inEnvMapIntensityUni)inEnvMapIntensityUni = new CGL.Uniform(shader, "f", "inEnvMapIntensity", inEnvMapIntensity); + if (!inEnvMapWidthUni)inEnvMapWidthUni = new CGL.Uniform(shader, "f", "inEnvMapWidth", inEnvTexture.get().cubemap.width); + } + else + { + const isSquare = inEnvTexture.get().width === inEnvTexture.get().height; + shader.toggleDefine("TEX_FORMAT_EQUIRECT", !isSquare); + shader.toggleDefine("ENVMAP_MATCAP", isSquare); + + if (!inEnvMapIntensityUni)inEnvMapIntensityUni = new CGL.Uniform(shader, "f", "inEnvMapIntensity", inEnvMapIntensity); + if (!inEnvMapWidthUni) inEnvMapWidthUni = new CGL.Uniform(shader, "f", "inEnvMapWidth", inEnvTexture.get().width); + } + } + else + { + shader.removeUniform("inEnvMapIntensity"); + shader.removeUniform("inEnvMapWidth"); + shader.removeUniform("texEnv"); + shader.removeDefine("HAS_TEXTURE_ENV"); + shader.removeDefine("ENVMAP_MATCAP"); + envTextureUniform = null; + inEnvMapIntensityUni = null; + } + + updateEnvTextureLater = false; +} + +function updateLuminanceMaskTexture() +{ + if (inLuminanceMaskTexture.get()) + { + inLuminanceMaskIntensity.setUiAttribs({ "greyout": false }); + if (!luminanceTextureUniform) + { + shader.define("HAS_TEXTURE_LUMINANCE_MASK"); + luminanceTextureUniform = new CGL.Uniform(shader, "t", "texLuminance", 0); + inLuminanceMaskIntensityUniform = new CGL.Uniform(shader, "f", "inLuminanceMaskIntensity", inLuminanceMaskIntensity); + } + } + else + { + inLuminanceMaskIntensity.setUiAttribs({ "greyout": true }); + shader.removeDefine("HAS_TEXTURE_LUMINANCE_MASK"); + shader.removeUniform("inLuminanceMaskIntensity"); + shader.removeUniform("texLuminance"); + luminanceTextureUniform = null; + inLuminanceMaskIntensityUniform = null; + } +} + +// TEX OPACITY + +function updateDefines() +{ + shader.toggleDefine("ENV_BLEND_ADD", inEnvMapBlend.get() == "Add"); + shader.toggleDefine("ENV_BLEND_MUL", inEnvMapBlend.get() == "Multiply"); + shader.toggleDefine("ENV_BLEND_MIX", inEnvMapBlend.get() == "Mix"); + + shader.toggleDefine("ALPHA_MASK_ALPHA", alphaMaskSource.get() == "Alpha Channel"); + shader.toggleDefine("ALPHA_MASK_LUMI", alphaMaskSource.get() == "Luminance"); + shader.toggleDefine("ALPHA_MASK_R", alphaMaskSource.get() == "R"); + shader.toggleDefine("ALPHA_MASK_G", alphaMaskSource.get() == "G"); + shader.toggleDefine("ALPHA_MASK_B", alphaMaskSource.get() == "B"); +} + +inEnvMapBlend.onChange = updateDefines; +alphaMaskSource.onChange = updateDefines; + +function updateAlphaTexture() +{ + if (inAlphaTexture.get()) + { + if (alphaTextureUniform !== null) return; + shader.removeUniform("texAlpha"); + shader.define("HAS_TEXTURE_ALPHA"); + if (!alphaTextureUniform) alphaTextureUniform = new CGL.Uniform(shader, "t", "texAlpha", 0); + + alphaMaskSource.setUiAttribs({ "greyout": false }); + discardTransPxl.setUiAttribs({ "greyout": false }); + } + else + { + shader.removeUniform("texAlpha"); + shader.removeDefine("HAS_TEXTURE_ALPHA"); + alphaTextureUniform = null; + + alphaMaskSource.setUiAttribs({ "greyout": true }); + discardTransPxl.setUiAttribs({ "greyout": true }); + } + updateDefines(); +} + +discardTransPxl.onChange = function () +{ + shader.toggleDefine("DISCARDTRANS", discardTransPxl.get()); +}; + +inDiffuseTexture.onChange = updateDiffuseTexture; +inSpecularTexture.onChange = updateSpecularTexture; +inNormalTexture.onChange = updateNormalTexture; +inAoTexture.onChange = updateAoTexture; +inEmissiveTexture.onChange = updateEmissiveTexture; +inEmissiveMaskTexture.onChange = updateEmissiveMaskTexture; +inAlphaTexture.onChange = updateAlphaTexture; +inEnvTexture.onChange = () => { updateEnvTextureLater = true; }; +inLuminanceMaskTexture.onChange = updateLuminanceMaskTexture; + +const MAX_UNIFORM_FRAGMENTS = cgl.maxUniformsFrag; +const MAX_LIGHTS = MAX_UNIFORM_FRAGMENTS === 64 ? 6 : 16; + +shader.define("MAX_LIGHTS", MAX_LIGHTS.toString()); +shader.define("SPECULAR_PHONG"); + +inSpecularMode.onChange = function () +{ + if (inSpecularMode.get() === "Phong") + { + shader.define("SPECULAR_PHONG"); + shader.removeDefine("SPECULAR_BLINN"); + shader.removeDefine("SPECULAR_GAUSS"); + shader.removeDefine("SPECULAR_SCHLICK"); + } + else if (inSpecularMode.get() === "Blinn") + { + shader.define("SPECULAR_BLINN"); + shader.removeDefine("SPECULAR_PHONG"); + shader.removeDefine("SPECULAR_GAUSS"); + shader.removeDefine("SPECULAR_SCHLICK"); + } + else if (inSpecularMode.get() === "Gauss") + { + shader.define("SPECULAR_GAUSS"); + shader.removeDefine("SPECULAR_BLINN"); + shader.removeDefine("SPECULAR_PHONG"); + shader.removeDefine("SPECULAR_SCHLICK"); + } + else if (inSpecularMode.get() === "Schlick") + { + shader.define("SPECULAR_SCHLICK"); + shader.removeDefine("SPECULAR_BLINN"); + shader.removeDefine("SPECULAR_PHONG"); + shader.removeDefine("SPECULAR_GAUSS"); + } +}; + +inEnergyConservation.onChange = function () +{ + shader.toggleDefine("CONSERVE_ENERGY", inEnergyConservation.get()); +}; + +inToggleDoubleSided.onChange = function () +{ + shader.toggleDefine("DOUBLE_SIDED", inToggleDoubleSided.get()); +}; + +// * INIT UNIFORMS * + +const uniMaterialProps = new CGL.Uniform(shader, "4f", "inMaterialProperties", inAlbedo, inRoughness, inShininess, inSpecularCoefficient); +const uniDiffuseColor = new CGL.Uniform(shader, "4f", "inDiffuseColor", inDiffuseR, inDiffuseG, inDiffuseB, inDiffuseA); +const uniTextureIntensities = new CGL.Uniform(shader, "4f", "inTextureIntensities", inNormalIntensity, inAoIntensity, inSpecularIntensity, inEmissiveIntensity); +const uniTextureRepeatOffset = new CGL.Uniform(shader, "4f", "inTextureRepeatOffset", inDiffuseRepeatX, inDiffuseRepeatY, inTextureOffsetX, inTextureOffsetY); + +shader.uniformColorDiffuse = uniDiffuseColor; + +const lightUniforms = []; +let oldCount = 0; + +function createUniforms(lightsCount) +{ + for (let i = 0; i < lightUniforms.length; i += 1) + { + lightUniforms[i] = null; + } + + for (let i = 0; i < lightsCount; i += 1) + { + lightUniforms[i] = null; + if (!lightUniforms[i]) + { + lightUniforms[i] = { + "color": new CGL.Uniform(shader, "3f", "phongLight" + i + ".color", [1, 1, 1]), + "position": new CGL.Uniform(shader, "3f", "phongLight" + i + ".position", [0, 11, 0]), + "specular": new CGL.Uniform(shader, "3f", "phongLight" + i + ".specular", [1, 1, 1]), + // intensity, attenuation, falloff, radius + "lightProperties": new CGL.Uniform(shader, "4f", "phongLight" + i + ".lightProperties", [1, 1, 1, 1]), + + "conePointAt": new CGL.Uniform(shader, "3f", "phongLight" + i + ".conePointAt", vec3.create()), + "spotProperties": new CGL.Uniform(shader, "3f", "phongLight" + i + ".spotProperties", [0, 0, 0, 0]), + "castLight": new CGL.Uniform(shader, "i", "phongLight" + i + ".castLight", 1), + + }; + } + } +} + +function setDefaultUniform(light) +{ + defaultUniform.position.setValue(light.position); + defaultUniform.color.setValue(light.color); + defaultUniform.specular.setValue(light.specular); + defaultUniform.lightProperties.setValue([ + light.intensity, + light.attenuation, + light.falloff, + light.radius, + ]); + + defaultUniform.conePointAt.setValue(light.conePointAt); + defaultUniform.spotProperties.setValue([ + light.cosConeAngle, + light.cosConeAngleInner, + light.spotExponent, + ]); +} + +function setUniforms(lightStack) +{ + for (let i = 0; i < lightStack.length; i += 1) + { + const light = lightStack[i]; + light.isUsed = true; + + lightUniforms[i].position.setValue(light.position); + lightUniforms[i].color.setValue(light.color); + lightUniforms[i].specular.setValue(light.specular); + + lightUniforms[i].lightProperties.setValue([ + light.intensity, + light.attenuation, + light.falloff, + light.radius, + ]); + + lightUniforms[i].conePointAt.setValue(light.conePointAt); + lightUniforms[i].spotProperties.setValue([ + light.cosConeAngle, + light.cosConeAngleInner, + light.spotExponent, + ]); + + lightUniforms[i].castLight.setValue(light.castLight); + } +} + +function compareLights(lightStack) +{ + if (lightStack.length !== oldCount) + { + createShader(lightStack); + createUniforms(lightStack.length); + oldCount = lightStack.length; + setUniforms(lightStack); + recompileShader = false; + } + else + { + if (recompileShader) + { + createShader(lightStack); + createUniforms(lightStack.length); + recompileShader = false; + } + setUniforms(lightStack); + } +} + +let defaultUniform = null; + +function createDefaultUniform() +{ + defaultUniform = { + "color": new CGL.Uniform(shader, "3f", "phongLight" + 0 + ".color", [1, 1, 1]), + "specular": new CGL.Uniform(shader, "3f", "phongLight" + 0 + ".specular", [1, 1, 1]), + "position": new CGL.Uniform(shader, "3f", "phongLight" + 0 + ".position", [0, 11, 0]), + // intensity, attenuation, falloff, radius + "lightProperties": new CGL.Uniform(shader, "4f", "phongLight" + 0 + ".lightProperties", [1, 1, 1, 1]), + "conePointAt": new CGL.Uniform(shader, "3f", "phongLight" + 0 + ".conePointAt", vec3.create()), + "spotProperties": new CGL.Uniform(shader, "3f", "phongLight" + 0 + ".spotProperties", [0, 0, 0, 0]), + "castLight": new CGL.Uniform(shader, "i", "phongLight" + 0 + ".castLight", 1), + }; +} + +const DEFAULT_LIGHTSTACK = [{ + "type": "point", + "position": [5, 5, 5], + "color": [1, 1, 1], + "specular": [1, 1, 1], + "intensity": 1, + "attenuation": 0, + "falloff": 0.5, + "radius": 80, + "castLight": 1, +}]; + +const iViewMatrix = mat4.create(); + +function updateLights() +{ + if (cgl.frameStore.lightStack) + { + if (cgl.frameStore.lightStack.length === 0) + { + op.setUiError("deflight", "Default light is enabled. Please add lights to your patch to make this warning disappear.", 1); + } + else op.setUiError("deflight", null); + } + + if ((!cgl.frameStore.lightStack || !cgl.frameStore.lightStack.length)) + { + // if no light in light stack, use default light & set count to -1 + // so when a new light gets added, the shader does recompile + if (!defaultUniform) + { + createDefaultShader(); + createDefaultUniform(); + } + + mat4.invert(iViewMatrix, cgl.vMatrix); + // set default light position to camera position + DEFAULT_LIGHTSTACK[0].position = [iViewMatrix[12], iViewMatrix[13], iViewMatrix[14]]; + setDefaultUniform(DEFAULT_LIGHTSTACK[0]); + + oldCount = -1; + } + else + { + if (shader) + { + if (cgl.frameStore.lightStack) + { + if (cgl.frameStore.lightStack.length) + { + defaultUniform = null; + compareLights(cgl.frameStore.lightStack); + } + } + } + } +} + +const render = function () +{ + if (!shader) + { + op.log("NO SHADER"); + return; + } + + cgl.pushShader(shader); + shader.popTextures(); + + outTrigger.trigger(); + cgl.popShader(); +}; + +op.preRender = function () +{ + shader.bind(); + render(); +}; + +/* transform for default light */ +const inverseViewMat = mat4.create(); +const vecTemp = vec3.create(); +const camPos = vec3.create(); + +inTrigger.onTriggered = function () +{ + if (!shader) + { + op.log("phong has no shader..."); + return; + } + + if (updateEnvTextureLater)updateEnvTexture(); + + cgl.pushShader(shader); + + shader.popTextures(); + + if (inDiffuseTexture.get()) shader.pushTexture(diffuseTextureUniform, inDiffuseTexture.get()); + if (inSpecularTexture.get()) shader.pushTexture(specularTextureUniform, inSpecularTexture.get()); + if (inNormalTexture.get()) shader.pushTexture(normalTextureUniform, inNormalTexture.get()); + if (inAoTexture.get()) shader.pushTexture(aoTextureUniform, inAoTexture.get()); + if (inEmissiveTexture.get()) shader.pushTexture(emissiveTextureUniform, inEmissiveTexture.get()); + if (inEmissiveMaskTexture.get()) shader.pushTexture(emissiveMaskTextureUniform, inEmissiveMaskTexture.get()); + if (inAlphaTexture.get()) shader.pushTexture(alphaTextureUniform, inAlphaTexture.get()); + if (inEnvTexture.get()) + { + if (inEnvTexture.get().cubemap) shader.pushTexture(envTextureUniform, inEnvTexture.get().cubemap, cgl.gl.TEXTURE_CUBE_MAP); + else shader.pushTexture(envTextureUniform, inEnvTexture.get()); + } + + if (inLuminanceMaskTexture.get()) + { + shader.pushTexture(luminanceTextureUniform, inLuminanceMaskTexture.get()); + } + + updateLights(); + + outTrigger.trigger(); + + cgl.popShader(); +}; + +if (cgl.glVersion == 1) +{ + if (!cgl.gl.getExtension("EXT_shader_texture_lod")) + { + op.log("no EXT_shader_texture_lod texture extension"); + // throw "no EXT_shader_texture_lod texture extension"; + } + else + { + shader.enableExtension("GL_EXT_shader_texture_lod"); + cgl.gl.getExtension("OES_texture_float"); + cgl.gl.getExtension("OES_texture_float_linear"); + cgl.gl.getExtension("OES_texture_half_float"); + cgl.gl.getExtension("OES_texture_half_float_linear"); + + shader.enableExtension("GL_OES_standard_derivatives"); + shader.enableExtension("GL_OES_texture_float"); + shader.enableExtension("GL_OES_texture_float_linear"); + shader.enableExtension("GL_OES_texture_half_float"); + shader.enableExtension("GL_OES_texture_half_float_linear"); + } +} + +updateDiffuseTexture(); +updateSpecularTexture(); +updateNormalTexture(); +updateAoTexture(); +updateAlphaTexture(); +updateEmissiveTexture(); +updateEmissiveMaskTexture(); +updateEnvTexture(); +updateLuminanceMaskTexture(); + + +}; + +Ops.Gl.Phong.PhongMaterial_v6.prototype = new CABLES.Op(); +CABLES.OPS["0d83ed06-cdbe-4fe0-87bb-0ccece7fb6e1"]={f:Ops.Gl.Phong.PhongMaterial_v6,objName:"Ops.Gl.Phong.PhongMaterial_v6"}; + + + + +// ************************************************************** +// +// Ops.Gl.Phong.PointLight_v5 +// +// ************************************************************** + +Ops.Gl.Phong.PointLight_v5 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const cgl = op.patch.cgl; +const gl = cgl.gl; +const mesh = CGL.MESHES.getSimpleRect(cgl, "fullscreenRectangle"); + +function Light(config) +{ + this.type = config.type || "point"; + this.color = config.color || [1, 1, 1]; + this.specular = config.specular || [0, 0, 0]; + this.position = config.position || null; + this.intensity = config.intensity || 1; + this.radius = config.radius || 1; + this.falloff = config.falloff || 1; + this.spotExponent = config.spotExponent || 1; + this.cosConeAngle = Math.cos(CGL.DEG2RAD * this.coneAngle); + this.conePointAt = config.conePointAt || [0, 0, 0]; + this.castShadow = config.castShadow || false; + return this; +} + +// * OP START * +const inTrigger = op.inTrigger("Trigger In"); +const inCastLight = op.inBool("Cast Light", true); +const inIntensity = op.inFloat("Intensity", 2); +const inRadius = op.inFloat("Radius", 15); + +const inPosX = op.inFloat("X", 0); +const inPosY = op.inFloat("Y", 2); +const inPosZ = op.inFloat("Z", 0.75); + +const positionIn = [inPosX, inPosY, inPosZ]; +op.setPortGroup("Position", positionIn); + +const inR = op.inFloat("R", 0.8); +const inG = op.inFloat("G", 0.8); +const inB = op.inFloat("B", 0.8); + +inR.setUiAttribs({ "colorPick": true }); +const colorIn = [inR, inG, inB]; +op.setPortGroup("Color", colorIn); + +const inSpecularR = op.inFloat("Specular R", 1); +const inSpecularG = op.inFloat("Specular G", 1); +const inSpecularB = op.inFloat("Specular B", 1); + +inSpecularR.setUiAttribs({ "colorPick": true }); +const colorSpecularIn = [inSpecularR, inSpecularG, inSpecularB]; +op.setPortGroup("Specular Color", colorSpecularIn); + +const inFalloff = op.inFloatSlider("Falloff", 0.5); + +const attribIns = [inIntensity, inCastLight, inRadius]; +op.setPortGroup("Light Attributes", attribIns); + +const inCastShadow = op.inBool("Cast Shadow", false); +const inRenderMapActive = op.inBool("Rendering Active", true); +const inMapSize = op.inSwitch("Map Size", [256, 512, 1024, 2048], 512); +const inShadowStrength = op.inFloatSlider("Shadow Strength", 1); +const inNear = op.inFloat("Near", 0.1); +const inFar = op.inFloat("Far", 30); +const inBias = op.inFloatSlider("Bias", 0.004); +const inPolygonOffset = op.inInt("Polygon Offset", 0); +op.setPortGroup("", [inCastShadow]); +op.setPortGroup("Shadow Map Settings", [inMapSize, inRenderMapActive, inShadowStrength, inNear, inFar, inBias, inPolygonOffset]); +const shadowProperties = [inNear, inFar]; +inMapSize.setUiAttribs({ "greyout": !inCastShadow.get() }); +inRenderMapActive.setUiAttribs({ "greyout": !inCastShadow.get() }); +inShadowStrength.setUiAttribs({ "greyout": !inCastShadow.get() }); +inNear.setUiAttribs({ "greyout": !inCastShadow.get() }); +inBias.setUiAttribs({ "greyout": !inCastShadow.get() }); +inFar.setUiAttribs({ "greyout": !inCastShadow.get() }); +inPolygonOffset.setUiAttribs({ "greyout": !inCastShadow.get() }); + +let updating = false; + +inCastShadow.onChange = function () +{ + updating = true; + updateLight = true; + + inMapSize.setUiAttribs({ "greyout": !inCastShadow.get() }); + inRenderMapActive.setUiAttribs({ "greyout": !inCastShadow.get() }); + inShadowStrength.setUiAttribs({ "greyout": !inCastShadow.get() }); + inNear.setUiAttribs({ "greyout": !inCastShadow.get() }); + inFar.setUiAttribs({ "greyout": !inCastShadow.get() }); + inBias.setUiAttribs({ "greyout": !inCastShadow.get() }); + inPolygonOffset.setUiAttribs({ "greyout": !inCastShadow.get() }); +}; + +const outTrigger = op.outTrigger("Trigger Out"); +const outCubemap = op.outObject("Cubemap", null, "texture"); +const outWorldPosX = op.outNumber("World Position X"); +const outWorldPosY = op.outNumber("World Position Y"); +const outWorldPosZ = op.outNumber("World Position Z"); + +const newLight = new CGL.Light(cgl, { + "type": "point", + "position": [0, 1, 2].map(function (i) { return positionIn[i].get(); }), + "color": [0, 1, 2].map(function (i) { return colorIn[i].get(); }), + "specular": [0, 1, 2].map(function (i) { return colorSpecularIn[i].get(); }), + "intensity": inIntensity.get(), + "radius": inRadius.get(), + "falloff": inFalloff.get(), + "shadowStrength": inShadowStrength.get(), + "shadowBias": inBias.get() +}); +newLight.castLight = inCastLight.get(); + +let updateLight = false; + +inPosX.onChange = inPosY.onChange = inPosZ.onChange = inR.onChange = inG.onChange = inB.onChange += inSpecularR.onChange = inSpecularG.onChange = inSpecularB.onChange = inIntensity.onChange += inCastLight.onChange = inRadius.onChange = inFalloff.onChange = inNear.onChange = inFar.onChange = inShadowStrength.onChange = function () + { + updateLight = true; + }; + +inMapSize.onChange = function () +{ + // TODO: update this one + updating = true; +}; + +function updateShadowMapFramebuffer() +{ + if (inCastShadow.get()) + { + const size = inMapSize.get(); + newLight.createFramebuffer(size, size, {}); + newLight.createShadowMapShader(); + } + updating = false; +} + +const sc = vec3.create(); +const result = vec3.create(); +const position = vec3.create(); +const transVec = vec3.create(); + +function drawHelpers() +{ + if (cgl.frameStore.shadowPass) return; + if (cgl.shouldDrawHelpers(op)) + { + gui.setTransformGizmo({ + "posX": inPosX, + "posY": inPosY, + "posZ": inPosZ, + }); + + cgl.pushModelMatrix(); + mat4.translate(cgl.mMatrix, cgl.mMatrix, transVec); + CABLES.GL_MARKER.drawSphere(op, inRadius.get()); + cgl.popModelMatrix(); + } +} + +let errorActive = false; + +inTrigger.onTriggered = function () +{ + if (updating) + { + if (cgl.frameStore.shadowPass) return; + updateShadowMapFramebuffer(); + } + + if (!cgl.frameStore.shadowPass) + { + if (!newLight.isUsed && !errorActive) + { + op.setUiError("lightUsed", "No operator is using this light. Make sure this op is positioned before an operator that uses lights. Also make sure there is an operator that uses lights after this.", 1); // newLight.isUsed = false; + errorActive = true; + } + else if (!newLight.isUsed && errorActive) {} + else if (newLight.isUsed && errorActive) + { + op.setUiError("lightUsed", null); + errorActive = false; + } + else if (newLight.isUsed && !errorActive) {} + + newLight.isUsed = false; + } + + if (updateLight) + { + newLight.position = [0, 1, 2].map(function (i) { return positionIn[i].get(); }); + newLight.color = [0, 1, 2].map(function (i) { return colorIn[i].get(); }); + newLight.specular = [0, 1, 2].map(function (i) { return colorSpecularIn[i].get(); }); + newLight.intensity = inIntensity.get(); + newLight.radius = inRadius.get(); + newLight.falloff = inFalloff.get(); + newLight.castShadow = inCastShadow.get(); + newLight.castLight = inCastLight.get(); + newLight.updateProjectionMatrix(null, inNear.get(), inFar.get(), null); + updateLight = false; + } + + if (!cgl.frameStore.lightStack) cgl.frameStore.lightStack = []; + + vec3.set(transVec, inPosX.get(), inPosY.get(), inPosZ.get()); + vec3.transformMat4(position, transVec, cgl.mMatrix); + + newLight.position = position; + + outWorldPosX.set(newLight.position[0]); + outWorldPosY.set(newLight.position[1]); + outWorldPosZ.set(newLight.position[2]); + + if (!cgl.frameStore.shadowPass) drawHelpers(); + + cgl.frameStore.lightStack.push(newLight); + + if (inCastShadow.get()) + { + if (inRenderMapActive.get()) newLight.renderPasses(inPolygonOffset.get(), null, function () { outTrigger.trigger(); }); + + if (!cgl.frameStore.shadowPass) + { + cgl.frameStore.lightStack.pop(); + newLight.castShadow = inCastShadow.get(); + newLight.shadowBias = inBias.get(); + newLight.shadowStrength = inShadowStrength.get(); + + if (newLight.shadowCubeMap) + { + if (newLight.shadowCubeMap.cubemap) + { + outCubemap.set(null); + outCubemap.set(newLight.shadowCubeMap); + if (inRenderMapActive.get()) + { + // needs to be "cloned", cannot save reference. + newLight.positionForShadowMap = [newLight.position[0], newLight.position[1], newLight.position[2]]; + } + } + } + cgl.frameStore.lightStack.push(newLight); + } + } + else + { + outCubemap.set(null); + } + + outTrigger.trigger(); + cgl.frameStore.lightStack.pop(); +}; + + +}; + +Ops.Gl.Phong.PointLight_v5.prototype = new CABLES.Op(); +CABLES.OPS["54e5d3f5-e3f4-4381-990d-d5e32b9a2d39"]={f:Ops.Gl.Phong.PointLight_v5,objName:"Ops.Gl.Phong.PointLight_v5"}; + + + + +// ************************************************************** +// +// Ops.Gl.Phong.ResetLights +// +// ************************************************************** + +Ops.Gl.Phong.ResetLights = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const cgl = op.patch.cgl; +const inTrigger = op.inTrigger("Trigger In"); +const inBool = op.inBool("Reset Lights", true); +const outTrigger = op.outTrigger("Trigger Out"); + +inTrigger.onTriggered = () => +{ + if (inBool.get()) + { + const oldStack = cgl.frameStore.lightStack; + cgl.frameStore.lightStack = []; + outTrigger.trigger(); + cgl.frameStore.lightStack = oldStack; + return; + } + + outTrigger.trigger(); +}; + + +}; + +Ops.Gl.Phong.ResetLights.prototype = new CABLES.Op(); +CABLES.OPS["3954ca2b-56c8-4501-9b47-feeaba71d75f"]={f:Ops.Gl.Phong.ResetLights,objName:"Ops.Gl.Phong.ResetLights"}; + + + + +// ************************************************************** +// +// Ops.Gl.Phong.SpotLight_v5 +// +// ************************************************************** + +Ops.Gl.Phong.SpotLight_v5 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const cgl = op.patch.cgl; + +// * OP START * +const inTrigger = op.inTrigger("Trigger In"); + +const inCastLight = op.inBool("Cast Light", true); +const inIntensity = op.inFloat("Intensity", 2); +const inRadius = op.inFloat("Radius", 10); + +const inPosX = op.inFloat("X", 1); +const inPosY = op.inFloat("Y", 3); +const inPosZ = op.inFloat("Z", 1); + +const positionIn = [inPosX, inPosY, inPosZ]; +op.setPortGroup("Position", positionIn); + +const inPointAtX = op.inFloat("Point At X", 0); +const inPointAtY = op.inFloat("Point At Y", 0); +const inPointAtZ = op.inFloat("Point At Z", 0); +const pointAtIn = [inPointAtX, inPointAtY, inPointAtZ]; +op.setPortGroup("Point At", pointAtIn); + +const inR = op.inFloatSlider("R", 1); +const inG = op.inFloatSlider("G", 1); +const inB = op.inFloatSlider("B", 1); +inR.setUiAttribs({ "colorPick": true }); +const colorIn = [inR, inG, inB]; +op.setPortGroup("Color", colorIn); + +const inSpecularR = op.inFloatSlider("Specular R", 1); +const inSpecularG = op.inFloatSlider("Specular G", 1); +const inSpecularB = op.inFloatSlider("Specular B", 1); +inSpecularR.setUiAttribs({ "colorPick": true }); +const colorSpecularIn = [inSpecularR, inSpecularG, inSpecularB]; +op.setPortGroup("Specular Color", colorSpecularIn); + +const inConeAngle = op.inFloat("Cone Angle", 120); +const inConeAngleInner = op.inFloat("Inner Cone Angle", 60); +const inSpotExponent = op.inFloat("Spot Exponent", 0.97); +const coneAttribsIn = [inConeAngle, inConeAngleInner, inSpotExponent]; +op.setPortGroup("Cone Attributes", coneAttribsIn); + +const inFalloff = op.inFloatSlider("Falloff", 0.00001); +const lightAttribsIn = [inCastLight, inIntensity, inRadius]; +op.setPortGroup("Light Attributes", lightAttribsIn); + +const inCastShadow = op.inBool("Cast Shadow", false); +const inRenderMapActive = op.inBool("Rendering Active", true); +const inMapSize = op.inSwitch("Map Size", [256, 512, 1024, 2048], 512); +const inShadowStrength = op.inFloatSlider("Shadow Strength", 0.99); +const inNear = op.inFloat("Near", 0.1); +const inFar = op.inFloat("Far", 30); +const inBias = op.inFloatSlider("Bias", 0.0001); +const inPolygonOffset = op.inInt("Polygon Offset", 0); +const inNormalOffset = op.inFloatSlider("Normal Offset", 0); +const inBlur = op.inFloatSlider("Blur Amount", 0); +op.setPortGroup("", [inCastShadow]); +op.setPortGroup("Shadow Map Settings", [ + inMapSize, + inRenderMapActive, + inShadowStrength, + inNear, + inFar, + inBias, + inPolygonOffset, + inNormalOffset, + inBlur +]); + +inMapSize.setUiAttribs({ "greyout": true, "hidePort": true }); +inRenderMapActive.setUiAttribs({ "greyout": true }); +inShadowStrength.setUiAttribs({ "greyout": true }); +inNear.setUiAttribs({ "greyout": true, "hidePort": true }); +inFar.setUiAttribs({ "greyout": true, "hidePort": true }); +inBlur.setUiAttribs({ "greyout": true, "hidePort": true }); +inPolygonOffset.setUiAttribs({ "greyout": true, "hidePort": true }); +inNormalOffset.setUiAttribs({ "greyout": true, "hidePort": true }); +inBias.setUiAttribs({ "greyout": true, "hidePort": true }); + +const inAdvanced = op.inBool("Enable Advanced", false); +const inMSAA = op.inSwitch("MSAA", ["none", "2x", "4x", "8x"], "none"); +const inFilterType = op.inSwitch("Texture Filter", ["Linear", "Nearest", "Mip Map"], "Linear"); +const inAnisotropic = op.inSwitch("Anisotropic", [0, 1, 2, 4, 8, 16], "0"); +inMSAA.setUiAttribs({ "greyout": true, "hidePort": true }); +inFilterType.setUiAttribs({ "greyout": true, "hidePort": true }); +inAnisotropic.setUiAttribs({ "greyout": true, "hidePort": true }); +op.setPortGroup("Advanced Options", [inAdvanced, inMSAA, inFilterType, inAnisotropic]); + +let updating = false; + +inAdvanced.setUiAttribs({ "hidePort": true }); + +inAdvanced.onChange = function () +{ + inMSAA.setUiAttribs({ "greyout": !inAdvanced.get() }); + inFilterType.setUiAttribs({ "greyout": !inAdvanced.get() }); + inAnisotropic.setUiAttribs({ "greyout": !inAdvanced.get() }); +}; + +const outTrigger = op.outTrigger("Trigger Out"); +const outTexture = op.outTexture("Shadow Map"); +const outWorldPosX = op.outNumber("World Position X"); +const outWorldPosY = op.outNumber("World Position Y"); +const outWorldPosZ = op.outNumber("World Position Z"); + +const newLight = new CGL.Light(cgl, { + "type": "spot", + "position": [0, 1, 2].map(function (i) { return positionIn[i].get(); }), + "color": [0, 1, 2].map(function (i) { return colorIn[i].get(); }), + "specular": [0, 1, 2].map(function (i) { return colorSpecularIn[i].get(); }), + "conePointAt": [0, 1, 2].map(function (i) { return pointAtIn[i].get(); }), + "intensity": inIntensity.get(), + "radius": inRadius.get(), + "falloff": inFalloff.get(), + "cosConeAngleInner": Math.cos(CGL.DEG2RAD * inConeAngleInner.get()), + "cosConeAngle": Math.cos(CGL.DEG2RAD * inConeAngle.get()), + "spotExponent": inSpotExponent.get(), + "castShadow": false, + "shadowStrength": inShadowStrength.get(), + "shadowBias": inBias.get(), + "normalOffset": inNormalOffset.get(), +}); +newLight.castLight = inCastLight.get(); + +let updateLight = false; +inR.onChange = inG.onChange = inB.onChange = inSpecularR.onChange = inSpecularG.onChange = inSpecularB.onChange += inPointAtX.onChange = inPointAtY.onChange = inPointAtZ.onChange = inPosX.onChange = inPosY.onChange = inPosZ.onChange; +inCastLight.onChange = inIntensity.onChange = inRadius.onChange = inFalloff.onChange = inConeAngle.onChange = inConeAngleInner.onChange += inSpotExponent.onChange = inShadowStrength.onChange = inNear.onChange = inFar.onChange = updateLightParameters; + +function updateLightParameters() +{ + updateLight = true; +} + +inCastShadow.onChange = function () +{ + updating = true; + const castShadow = inCastShadow.get(); + + inMapSize.setUiAttribs({ "greyout": !castShadow }); + inRenderMapActive.setUiAttribs({ "greyout": !castShadow }); + inShadowStrength.setUiAttribs({ "greyout": !castShadow }); + inNear.setUiAttribs({ "greyout": !castShadow }); + inFar.setUiAttribs({ "greyout": !castShadow }); + inNormalOffset.setUiAttribs({ "greyout": !castShadow }); + inBlur.setUiAttribs({ "greyout": !castShadow }); + inBias.setUiAttribs({ "greyout": !castShadow }); + inPolygonOffset.setUiAttribs({ "greyout": !castShadow }); + + updateLight = true; +}; + +let texelSize = 1 / Number(inMapSize.get()); + +function updateBuffers() +{ + const MSAA = Number(inMSAA.get().charAt(0)); + + let filterType = null; + const anisotropyFactor = Number(inAnisotropic.get()); + + if (inFilterType.get() == "Linear") + { + filterType = CGL.Texture.FILTER_LINEAR; + } + else if (inFilterType.get() == "Nearest") + { + filterType = CGL.Texture.FILTER_NEAREST; + } + else if (inFilterType.get() == "Mip Map") + { + filterType = CGL.Texture.FILTER_MIPMAP; + } + + const mapSize = Number(inMapSize.get()); + const textureOptions = { + "isFloatingPointTexture": true, + "filter": filterType, + }; + + if (MSAA) Object.assign(textureOptions, { "multisampling": true, "multisamplingSamples": MSAA }); + Object.assign(textureOptions, { "anisotropic": anisotropyFactor }); + + newLight.createFramebuffer(mapSize, mapSize, textureOptions); + newLight.createBlurEffect(textureOptions); +} + +inMSAA.onChange = inAnisotropic.onChange = inFilterType.onChange = inMapSize.onChange = function () +{ + updating = true; +}; + +function updateShadowMapFramebuffer() +{ + const size = Number(inMapSize.get()); + texelSize = 1 / size; + + if (inCastShadow.get()) + { + newLight.createFramebuffer(Number(inMapSize.get()), Number(inMapSize.get()), {}); + newLight.createShadowMapShader(); + newLight.createBlurEffect({}); + newLight.createBlurShader(); + newLight.updateProjectionMatrix(null, inNear.get(), inFar.get(), inConeAngle.get()); + } + + if (inAdvanced.get()) updateBuffers(); + + updating = false; +} + +const position = vec3.create(); +const pointAtPos = vec3.create(); +const resultPos = vec3.create(); +const resultPointAt = vec3.create(); + +function drawHelpers() +{ + if (cgl.frameStore.shadowPass) return; + if (cgl.shouldDrawHelpers(op)) + { + gui.setTransformGizmo({ + "posX": inPosX, + "posY": inPosY, + "posZ": inPosZ, + }); + + CABLES.GL_MARKER.drawLineSourceDest( + op, + newLight.position[0], + newLight.position[1], + newLight.position[2], + newLight.conePointAt[0], + newLight.conePointAt[1], + newLight.conePointAt[2], + ); + } +} + +let errorActive = false; +inTrigger.onTriggered = renderLight; + +op.preRender = () => +{ + updateShadowMapFramebuffer(); + renderLight(); +}; + +function renderLight() +{ + if (updating) + { + if (cgl.frameStore.shadowPass) return; + updateShadowMapFramebuffer(); + } + + if (!cgl.frameStore.shadowPass) + { + if (!newLight.isUsed && !errorActive) + { + op.setUiError("lightUsed", "No operator is using this light. Make sure this op is positioned before an operator that uses lights. Also make sure there is an operator that uses lights after this.", 1); // newLight.isUsed = false; + errorActive = true; + } + else if (!newLight.isUsed && errorActive) {} + else if (newLight.isUsed && errorActive) + { + op.setUiError("lightUsed", null); + errorActive = false; + } + else if (newLight.isUsed && !errorActive) {} + newLight.isUsed = false; + } + + if (updateLight) + { + newLight.position = [0, 1, 2].map(function (i) { return positionIn[i].get(); }); + newLight.color = [0, 1, 2].map(function (i) { return colorIn[i].get(); }); + newLight.specular = [0, 1, 2].map(function (i) { return colorSpecularIn[i].get(); }); + newLight.conePointAt = [0, 1, 2].map(function (i) { return pointAtIn[i].get(); }); + newLight.intensity = inIntensity.get(); + newLight.castLight = inCastLight.get(); + newLight.radius = inRadius.get(); + newLight.falloff = inFalloff.get(); + newLight.cosConeAngleInner = Math.cos(CGL.DEG2RAD * inConeAngleInner.get()); + newLight.cosConeAngle = Math.cos(CGL.DEG2RAD * inConeAngle.get()); + newLight.spotExponent = inSpotExponent.get(); + newLight.castShadow = inCastShadow.get(); + newLight.updateProjectionMatrix(null, inNear.get(), inFar.get(), inConeAngle.get()); + } + + if (!cgl.frameStore.lightStack) cgl.frameStore.lightStack = []; + + vec3.set(position, inPosX.get(), inPosY.get(), inPosZ.get()); + vec3.set(pointAtPos, inPointAtX.get(), inPointAtY.get(), inPointAtZ.get()); + + vec3.transformMat4(resultPos, position, cgl.mMatrix); + vec3.transformMat4(resultPointAt, pointAtPos, cgl.mMatrix); + + newLight.position = resultPos; + newLight.conePointAt = resultPointAt; + + outWorldPosX.set(newLight.position[0]); + outWorldPosY.set(newLight.position[1]); + outWorldPosZ.set(newLight.position[2]); + + if (!cgl.frameStore.shadowPass) drawHelpers(); + + cgl.frameStore.lightStack.push(newLight); + + if (inCastShadow.get()) + { + const blurAmount = 1.5 * inBlur.get() * texelSize; + if (inRenderMapActive.get()) newLight.renderPasses(inPolygonOffset.get(), blurAmount, function () { outTrigger.trigger(); }); + outTexture.set(null); + outTexture.set(newLight.getShadowMapDepth()); + + // remove light from stack and readd it with shadow map & mvp matrix + cgl.frameStore.lightStack.pop(); + + newLight.castShadow = inCastShadow.get(); + newLight.blurAmount = inBlur.get(); + newLight.normalOffset = inNormalOffset.get(); + newLight.shadowBias = inBias.get(); + newLight.shadowStrength = inShadowStrength.get(); + cgl.frameStore.lightStack.push(newLight); + } + + outTrigger.trigger(); + + cgl.frameStore.lightStack.pop(); +} + + +}; + +Ops.Gl.Phong.SpotLight_v5.prototype = new CABLES.Op(); +CABLES.OPS["76418c17-abd5-401b-82e2-688db6f966ee"]={f:Ops.Gl.Phong.SpotLight_v5,objName:"Ops.Gl.Phong.SpotLight_v5"}; + + + + +// ************************************************************** +// +// Ops.Gl.PixelProjection +// +// ************************************************************** + +Ops.Gl.PixelProjection = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + useVPSize = op.inBool("use viewport size", true), + width = op.inFloat("Width", 500), + height = op.inFloat("Height", 500), + zNear = op.inFloat("frustum near", -500), + zFar = op.inFloat("frustum far", 500), + fixAxis = op.inSwitch("Axis", ["X", "Y"], "X"), + inAlign = op.inSwitch("Position 0,0", ["Top Left ", "Top Right", "Center", "Bottom Right", "Bottom Left"], "Bottom Left"), + + flipX = op.inBool("Flip X", false), + flipY = op.inBool("Flip Y", false), + zeroY = op.inBool("Zero Y", false), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; + +op.setPortGroup("Canvas size", [useVPSize, width, height]); +op.setPortGroup("Clipping", [zNear, zFar]); +op.setPortGroup("Flip", [flipX, flipY]); +op.toWorkPortsNeedToBeLinked(render); + +render.onTriggered = exec; +useVPSize.onChange = updateSizeUI; +updateSizeUI(); + +function updateSizeUI() +{ + width.setUiAttribs({ "greyout": useVPSize.get() }); + height.setUiAttribs({ "greyout": useVPSize.get() }); +} + +function exec() +{ + let xl = 0; + let yt = 0; + let xr = 0; + let yb = 0; + + let w = width.get(); + let h = height.get(); + + let x0 = 0; + let y0 = 0; + + if (useVPSize.get()) + { + xr = cgl.getViewPort()[2] / cgl.pixelDensity; + yb = cgl.getViewPort()[3] / cgl.pixelDensity; + w = cgl.getViewPort()[2] / cgl.pixelDensity; + h = cgl.getViewPort()[3] / cgl.pixelDensity; + } + else + { + xr = w; + yb = h; + } + + if (flipX.get()) + { + const temp = xr; + xr = x0; + xl = temp; + } + + if (flipY.get()) + { + const temp = yb; + yb = y0; + yt = temp; + } + + if (inAlign.get() === "Center") + { + xl -= w / 2; + xr -= w / 2; + yt -= h / 2; + yb -= h / 2; + } + else + if (inAlign.get() === "Bottom Right") + { + xl -= w; + xr = x0; + yt = y0; + yb = -h; + } + else + if (inAlign.get() === "Top Right") + { + xl -= w; + xr = x0; + yt -= h; + yb = y0; + } + if (inAlign.get() === "Top Left ") + { + xl = x0; + xr = w; + yt = -h; + yb = y0; + } + + cgl.pushPMatrix(); + + mat4.ortho( + cgl.pMatrix, + xl, + xr, + yt, + yb, + parseFloat(zNear.get()), + parseFloat(zFar.get()) + ); + + trigger.trigger(); + cgl.popPMatrix(); +} + + +}; + +Ops.Gl.PixelProjection.prototype = new CABLES.Op(); +CABLES.OPS["949d6daf-d677-4ed6-a921-51a5732b64ac"]={f:Ops.Gl.PixelProjection,objName:"Ops.Gl.PixelProjection"}; + + + + +// ************************************************************** +// +// Ops.Gl.PointCollector +// +// ************************************************************** + +Ops.Gl.PointCollector = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + outPoints = op.outArray("Points", null, 3); + // outPoints=op.addOutPort(new CABLES.Port(op,"Points",CABLES.OP_PORT_TYPE_ARRAY)), + +outPoints.ignoreValueSerialize = true; + +let inAbsolute = op.inValueBool("Absolute", true); + +let points = []; +let cgl = op.patch.cgl; + +let oldSplinePoints = null; + +let pos = vec3.create(); +let empty = vec3.create(); +let m = mat4.create(); + +let mySplinePoints = []; + +render.onTriggered = function () +{ + if (cgl.frameStore.SplinePoints) + { + oldSplinePoints = cgl.frameStore.SplinePoints; + cgl.frameStore.SplinePoints = []; + } + + cgl.frameStore.SplinePointCounter = 0; + + cgl.frameStore.SplinePoints = mySplinePoints;// cgl.frameStore.SplinePoints||[]; + + if (cgl.frameStore.SplinePointCounter != cgl.frameStore.SplinePoints.length) + cgl.frameStore.SplinePoints.length = cgl.frameStore.SplinePointCounter; + + if (!inAbsolute.get()) + { + mat4.invert(m, cgl.mMatrix); + cgl.frameStore.SplinePointsInverseOriginalMatrix = m; + } + else + { + cgl.frameStore.SplinePointsInverseOriginalMatrix = null; + } + + trigger.trigger(); + + outPoints.set(null); + outPoints.set(cgl.frameStore.SplinePoints); + + if (oldSplinePoints) cgl.frameStore.SplinePoints = oldSplinePoints; +}; + + +}; + +Ops.Gl.PointCollector.prototype = new CABLES.Op(); +CABLES.OPS["52f368ee-303b-4d84-919d-450b0c002e39"]={f:Ops.Gl.PointCollector,objName:"Ops.Gl.PointCollector"}; + + + + +// ************************************************************** +// +// Ops.Gl.PointCollectorCollect +// +// ************************************************************** + +Ops.Gl.PointCollectorCollect = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; + +let pos = vec3.create(); +let empty = vec3.create(); +let tempMat = mat4.create(); + +render.onTriggered = function () +{ + if (!cgl.frameStore.SplinePoints) return; + + if (cgl.frameStore.SplinePointsInverseOriginalMatrix) + { + mat4.multiply(tempMat, cgl.frameStore.SplinePointsInverseOriginalMatrix, cgl.mMatrix); + vec3.transformMat4(pos, empty, tempMat); + } + else + { + vec3.transformMat4(pos, empty, cgl.mMatrix); + } + + cgl.frameStore.SplinePoints[cgl.frameStore.SplinePointCounter + 0] = pos[0]; + cgl.frameStore.SplinePoints[cgl.frameStore.SplinePointCounter + 1] = pos[1]; + cgl.frameStore.SplinePoints[cgl.frameStore.SplinePointCounter + 2] = pos[2]; + + cgl.frameStore.SplinePointCounter += 3; + + trigger.trigger(); +}; + + +}; + +Ops.Gl.PointCollectorCollect.prototype = new CABLES.Op(); +CABLES.OPS["766147f4-94c5-4197-8e0b-f41320aac2c6"]={f:Ops.Gl.PointCollectorCollect,objName:"Ops.Gl.PointCollectorCollect"}; + + + + +// ************************************************************** +// +// Ops.Gl.PointCollectorScreenCoords +// +// ************************************************************** + +Ops.Gl.PointCollectorScreenCoords = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let render = op.inTrigger("render"); +let trigger = op.outTrigger("trigger"); + +let cgl = op.patch.cgl; + +let m = mat4.create(); +let pos = [0, 0, 0]; +let trans = vec3.create(); + +render.onTriggered = function () +{ + if (!cgl.frameStore.SplinePoints) return; + + // vec3.transformMat4(pos, [0,0,0], cgl.mMatrix); + + mat4.multiply(m, cgl.vMatrix, cgl.mMatrix); + vec3.transformMat4(pos, [0, 0, 0], m); + + vec3.transformMat4(trans, pos, cgl.pMatrix); + + let vp = cgl.getViewPort(); + + cgl.frameStore.SplinePoints[cgl.frameStore.SplinePointCounter + 0] = vp[2] - (vp[2] * 0.5 - trans[0] * vp[2] * 0.5 / trans[2]); + cgl.frameStore.SplinePoints[cgl.frameStore.SplinePointCounter + 1] = vp[3] - (vp[3] * 0.5 + trans[1] * vp[3] * 0.5 / trans[2]); + + cgl.frameStore.SplinePointCounter += 2; + + trigger.trigger(); +}; + + +}; + +Ops.Gl.PointCollectorScreenCoords.prototype = new CABLES.Op(); +CABLES.OPS["ada03d29-07be-48f1-a428-7d0e8c52a163"]={f:Ops.Gl.PointCollectorScreenCoords,objName:"Ops.Gl.PointCollectorScreenCoords"}; + + + + +// ************************************************************** +// +// Ops.Gl.RandomCluster +// +// ************************************************************** + +Ops.Gl.RandomCluster = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + num = op.inValueInt("num"), + seed = op.inValueFloat("random seed", 1.5), + round = op.inValueBool("round", false), + size = op.inValueFloat("size", 10), + scaleX = op.inValueFloat("scaleX", 1), + scaleY = op.inValueFloat("scaleY", 1), + scaleZ = op.inValueFloat("scaleZ", 1), + trigger = op.outTrigger("trigger"), + idx = op.outNumber("index"), + rnd = op.outNumber("rnd"), + rotX = op.inValueSlider("Rotate X", 1), + rotY = op.inValueSlider("Rotate Y", 1), + rotZ = op.inValueSlider("Rotate Z", 1), + scrollX = op.inValue("Scroll X", 0); + +op.setPortGroup("Area", [size, scaleX, scaleY, scaleZ]); +op.setPortGroup("Rotation", [rotX, rotY, rotZ]); +op.setPortGroup("Parameters", [num, round, seed]); +op.toWorkPortsNeedToBeLinked(exe, trigger); + +const cgl = op.patch.cgl; +const randoms = []; +const origRandoms = []; +const randomsRot = []; +const randomsFloats = []; + +const transVec = vec3.create(); +const mat = mat4.create(); + +function doRender() +{ + if (cgl.shouldDrawHelpers(op)) + { + CABLES.GL_MARKER.drawCube(op, + size.get() / 2 * scaleX.get(), + size.get() / 2 * scaleY.get(), + size.get() / 2 * scaleZ.get()); + } + + if (scrollX.get() != 0) + { + for (let i = 0; i < origRandoms.length; i++) + { + randoms[i][0] = origRandoms[i][0] + scrollX.get(); + randoms[i][0] = (randoms[i][0] % size.get()) - (size.get() / 2); + } + } + + for (let i = 0; i < randoms.length; i++) + { + cgl.pushModelMatrix(); + + mat4.translate(cgl.mMatrix, cgl.mMatrix, randoms[i]); + + if (randomsRot[i][0]) mat4.rotateX(cgl.mMatrix, cgl.mMatrix, randomsRot[i][0]); + if (randomsRot[i][1]) mat4.rotateY(cgl.mMatrix, cgl.mMatrix, randomsRot[i][1]); + if (randomsRot[i][2]) mat4.rotateZ(cgl.mMatrix, cgl.mMatrix, randomsRot[i][2]); + + idx.set(i); + rnd.set(randomsFloats[i]); + + trigger.trigger(); + // op.patch.instancing.increment(); + + cgl.popModelMatrix(); + } + // op.patch.instancing.popLoop(); +} + +exe.onTriggered = doRender; + +function getRandomPos() +{ + return vec3.fromValues( + scaleX.get() * (Math.seededRandom() - 0.5) * size.get(), + scaleY.get() * (Math.seededRandom() - 0.5) * size.get(), + scaleZ.get() * (Math.seededRandom() - 0.5) * size.get() + ); +} + +function reset() +{ + randoms.length = 0; + randomsRot.length = 0; + randomsFloats.length = 0; + origRandoms.length = 0; + + Math.randomSeed = seed.get(); + + const makeRound = round.get(); + + for (let i = 0; i < num.get(); i++) + { + randomsFloats.push(Math.seededRandom()); + + let v = getRandomPos(); + + if (makeRound && size.get() > 0) + while (vec3.len(v) > size.get() / 2) + v = getRandomPos(); + + origRandoms.push([v[0], v[1], v[2]]); + randoms.push(v); + + randomsRot.push(vec3.fromValues( + Math.seededRandom() * 360 * CGL.DEG2RAD * rotX.get(), + Math.seededRandom() * 360 * CGL.DEG2RAD * rotY.get(), + Math.seededRandom() * 360 * CGL.DEG2RAD * rotZ.get() + )); + } +} + +seed.onChange = reset; +num.onChange = reset; +size.onChange = reset; +scaleX.onChange = reset; +scaleZ.onChange = reset; +scaleY.onChange = reset; +round.onChange = reset; +rotX.onChange = reset; +rotY.onChange = reset; +rotZ.onChange = reset; + +num.set(100); + + +}; + +Ops.Gl.RandomCluster.prototype = new CABLES.Op(); +CABLES.OPS["ca3bc984-e596-48fb-b53d-502eb13979b0"]={f:Ops.Gl.RandomCluster,objName:"Ops.Gl.RandomCluster"}; + + + + +// ************************************************************** +// +// Ops.Gl.RandomizeTriangles +// +// ************************************************************** + +Ops.Gl.RandomizeTriangles = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inGeom = op.inObject("Geometry"), + outGeom = op.outObject("Result"), + inSeed = op.inValue("Seed", 1); + +inGeom.ignoreValueSerialize = true; +outGeom.ignoreValueSerialize = true; + +inSeed.onChange = +inGeom.onChange = function () +{ + const geom = inGeom.get(); + if (!geom) return; + if (geom.verticesIndices && geom.verticesIndices.length > 0) + { + op.logError("cannot randomize indexed geom "); + return; + } + + const newGeom = geom.copy(); + let order = []; + let i = 0; + order.length = geom.vertices.length / 9; + for (i = 0; i < order.length; i++)order[i] = i; + Math.randomSeed = inSeed.get(); + order = CABLES.shuffleArray(order); + + const verts = []; + verts.length = geom.vertices.length; + + for (i = 0; i < order.length; i++) + { + const ind = order[i]; + for (let j = 0; j < 9; j++) + verts[i * 9 + j] = geom.vertices[ind * 9 + j]; + } + + newGeom.setVertices(verts); + + outGeom.set(null); + outGeom.set(newGeom); +}; + + +}; + +Ops.Gl.RandomizeTriangles.prototype = new CABLES.Op(); +CABLES.OPS["e8a27786-bd11-4818-88a6-74eeb52018bd"]={f:Ops.Gl.RandomizeTriangles,objName:"Ops.Gl.RandomizeTriangles"}; + + + + +// ************************************************************** +// +// Ops.Gl.Render2Texture +// +// ************************************************************** + +Ops.Gl.Render2Texture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const cgl = op.patch.cgl; + +const + render = op.inTrigger("render"), + useVPSize = op.inValueBool("use viewport size", true), + width = op.inValueInt("texture width", 512), + height = op.inValueInt("texture height", 512), + aspect = op.inBool("Auto Aspect", false), + tfilter = op.inSwitch("filter", ["nearest", "linear", "mipmap"], "linear"), + twrap = op.inSwitch("Wrap", ["Clamp", "Repeat", "Mirror"], "Repeat"), + msaa = op.inSwitch("MSAA", ["none", "2x", "4x", "8x"], "none"), + trigger = op.outTrigger("trigger"), + tex = op.outTexture("texture"), + texDepth = op.outTexture("textureDepth"), + fpTexture = op.inValueBool("HDR"), + depth = op.inValueBool("Depth", true), + clear = op.inValueBool("Clear", true); + +let fb = null; +let reInitFb = true; +tex.set(CGL.Texture.getEmptyTexture(cgl)); + +op.setPortGroup("Size", [useVPSize, width, height, aspect]); + +const prevViewPort = [0, 0, 0, 0]; + +fpTexture.setUiAttribs({ "title": "Pixelformat Float 32bit" }); + +fpTexture.onChange = + depth.onChange = + clear.onChange = + tfilter.onChange = + twrap.onChange = + msaa.onChange = initFbLater; + +useVPSize.onChange = updateVpSize; + +render.onTriggered = + op.preRender = doRender; + +updateVpSize(); + +function updateVpSize() +{ + width.setUiAttribs({ "greyout": useVPSize.get() }); + height.setUiAttribs({ "greyout": useVPSize.get() }); + aspect.setUiAttribs({ "greyout": useVPSize.get() }); +} + +function initFbLater() +{ + reInitFb = true; +} + +function doRender() +{ + const vp = cgl.getViewPort(); + prevViewPort[0] = vp[0]; + prevViewPort[1] = vp[1]; + prevViewPort[2] = vp[2]; + prevViewPort[3] = vp[3]; + + if (!fb || reInitFb) + { + if (fb) fb.delete(); + + let selectedWrap = CGL.Texture.WRAP_REPEAT; + if (twrap.get() == "Clamp") selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + else if (twrap.get() == "Mirror") selectedWrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + + let selectFilter = CGL.Texture.FILTER_NEAREST; + if (tfilter.get() == "nearest") selectFilter = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "linear") selectFilter = CGL.Texture.FILTER_LINEAR; + else if (tfilter.get() == "mipmap") selectFilter = CGL.Texture.FILTER_MIPMAP; + + if (fpTexture.get() && tfilter.get() == "mipmap") op.setUiError("fpmipmap", "Don't use mipmap and HDR at the same time, many systems do not support this."); + else op.setUiError("fpmipmap", null); + + if (cgl.glVersion >= 2) + { + let ms = true; + let msSamples = 4; + + if (msaa.get() == "none") + { + msSamples = 0; + ms = false; + } + if (msaa.get() == "2x") msSamples = 2; + if (msaa.get() == "4x") msSamples = 4; + if (msaa.get() == "8x") msSamples = 8; + + fb = new CGL.Framebuffer2(cgl, 8, 8, + { + "name": "render2texture " + op.id, + "isFloatingPointTexture": fpTexture.get(), + "multisampling": ms, + "wrap": selectedWrap, + "filter": selectFilter, + "depth": depth.get(), + "multisamplingSamples": msSamples, + "clear": clear.get() + }); + } + else + { + fb = new CGL.Framebuffer(cgl, 8, 8, { "isFloatingPointTexture": fpTexture.get(), "clear": clear.get() }); + } + + texDepth.set(fb.getTextureDepth()); + reInitFb = false; + } + + if (useVPSize.get()) + { + width.set(cgl.getViewPort()[2]); + height.set(cgl.getViewPort()[3]); + } + + if (fb.getWidth() != Math.ceil(width.get()) || fb.getHeight() != Math.ceil(height.get())) + { + fb.setSize( + Math.max(1, Math.ceil(width.get())), + Math.max(1, Math.ceil(height.get()))); + } + + fb.renderStart(cgl); + + if (aspect.get()) mat4.perspective(cgl.pMatrix, 45, width.get() / height.get(), 0.1, 1000.0); + + trigger.trigger(); + fb.renderEnd(cgl); + + // cgl.resetViewPort(); + cgl.setViewPort(prevViewPort[0], prevViewPort[1], prevViewPort[2], prevViewPort[3]); + + tex.set(CGL.Texture.getEmptyTexture(op.patch.cgl)); + tex.set(fb.getTextureColor()); +} + + +}; + +Ops.Gl.Render2Texture.prototype = new CABLES.Op(); +CABLES.OPS["d01fa820-396c-4cb5-9d78-6b14762852af"]={f:Ops.Gl.Render2Texture,objName:"Ops.Gl.Render2Texture"}; + + + + +// ************************************************************** +// +// Ops.Gl.Render2Textures +// +// ************************************************************** + +Ops.Gl.Render2Textures = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const render = op.inTrigger("Render"); +const trigger = op.outTrigger("Next"); +const msaa = op.inValueSelect("MSAA", ["none", "2x", "4x", "8x"], "none"); +const useVPSize = op.inValueBool("use viewport size"); + +const width = op.inValueInt("texture width"); +const height = op.inValueInt("texture height"); +const tfilter = op.inValueSelect("Filter", ["nearest", "linear", "mipmap"], "none"); + +const tex0 = op.outTexture("texture 0"); +const tex1 = op.outTexture("texture 1"); +const tex2 = op.outTexture("texture 2"); +const tex3 = op.outTexture("texture 3"); + +const texDepth = op.outTexture("textureDepth"); + +const fpTexture = op.inValueBool("HDR"); +const depth = op.inValueBool("Depth", true); +const clear = op.inValueBool("Clear", true); + +const cgl = op.patch.cgl; + +let fb = null; +width.set(512); +height.set(512); +useVPSize.set(true); +tfilter.set("linear"); +let reInitFb = true; + +render.onTriggered = doRender; +useVPSize.onChange = updateVpSize; + +tfilter.onChange = + fpTexture.onChange = + depth.onChange = + clear.onChange = + msaa.onChange = reInitLater; + +updateVpSize(); + +function updateVpSize() +{ + if (useVPSize.get()) + { + width.setUiAttribs({ "hidePort": true, "greyout": true }); + height.setUiAttribs({ "hidePort": true, "greyout": true }); + } + else + { + width.setUiAttribs({ "hidePort": false, "greyout": false }); + height.setUiAttribs({ "hidePort": false, "greyout": false }); + } +} + +function reInitLater() +{ + reInitFb = true; +} + +function doRender() +{ + if (!fb || reInitFb) + { + if (fb) fb.delete(); + if (cgl.glVersion >= 2) + { + let ms = true; + let msSamples = 4; + + if (msaa.get() == "none") + { + msSamples = 0; + ms = false; + } + if (msaa.get() == "2x")msSamples = 2; + if (msaa.get() == "4x")msSamples = 4; + if (msaa.get() == "8x")msSamples = 8; + + fb = new CGL.Framebuffer2(cgl, 8, 8, + { + "numRenderBuffers": 4, + "isFloatingPointTexture": fpTexture.get(), + "multisampling": ms, + "depth": depth.get(), + "multisamplingSamples": msSamples, + "clear": clear.get() + }); + } + else + { + fb = new CGL.Framebuffer(cgl, 8, 8, { "isFloatingPointTexture": fpTexture.get() }); + } + + if (tfilter.get() == "nearest") fb.setFilter(CGL.Texture.FILTER_NEAREST); + else if (tfilter.get() == "linear") fb.setFilter(CGL.Texture.FILTER_LINEAR); + else if (tfilter.get() == "mipmap") fb.setFilter(CGL.Texture.FILTER_MIPMAP); + + tex0.set(fb.getTextureColorNum(0)); + tex1.set(fb.getTextureColorNum(1)); + tex2.set(fb.getTextureColorNum(2)); + tex3.set(fb.getTextureColorNum(3)); + texDepth.set(fb.getTextureDepth()); + reInitFb = false; + } + + if (useVPSize.get()) + { + width.set(cgl.getViewPort()[2]); + height.set(cgl.getViewPort()[3]); + } + + if (fb.getWidth() != Math.ceil(width.get()) || fb.getHeight() != Math.ceil(height.get())) fb.setSize(width.get(), height.get()); + + fb.renderStart(cgl); + trigger.trigger(); + fb.renderEnd(cgl); + + cgl.resetViewPort(); +} + + +}; + +Ops.Gl.Render2Textures.prototype = new CABLES.Op(); +CABLES.OPS["72f95dbd-7b36-4e88-9d59-1bb2d3f2144e"]={f:Ops.Gl.Render2Textures,objName:"Ops.Gl.Render2Textures"}; + + + + +// ************************************************************** +// +// Ops.Gl.RenderAnim_v2 +// +// ************************************************************** + +Ops.Gl.RenderAnim_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Render"), + next = op.outTrigger("Next"), + inType = op.inDropDown("File Type", ["PNG", "JPG", "WebP", "WebM"], "PNG"), + inZip = op.inBool("ZIP multiple files", false), + inDownload = op.inBool("Download Files", true), + inFilePrefix = op.inString("Filename", "cables"), + inQuality = op.inFloatSlider("Quality", 0.8), + inDurType = op.inSwitch("Duration Type", ["Seconds", "Frames"], "Seconds"), + inDuration = op.inInt("Duration", 1), + inFps = op.inInt("FPS", 30), + inTransparency = op.inValueBool("Transparency", false), + useCanvasSize = op.inValueBool("Use Canvas Size", true), + inWidth = op.inValueInt("texture width", 512), + inHeight = op.inValueInt("texture height", 512), + inStart = op.inTriggerButton("Start"), + outProgress = op.outNumber("Progress", 0), + outFrame = op.outNumber("Frame", 0), + outStatus = op.outString("Status", "Waiting"), + outStarted = op.outBool("Started"), + outUrl = op.outString("Data URL"), + outFinished = op.outTrigger("Finished"); + +op.setPortGroup("File", [inType, inZip, inDownload, inFilePrefix, inQuality]); +op.setPortGroup("Size", [useCanvasSize, inWidth, inHeight]); +op.setPortGroup("Timing", [inFps, inDurType, inDuration]); + +outUrl.ignoreValueSerialize = true; + +exec.onTriggered = render; + +let started = false; +let countFrames = 0; +const finished = true; +let fps = 30; +let numFrames = 31; + +const cycle = false; +let shortId = CABLES.shortId(); +let frameStarted = false; +const frames = []; +let lastFrame = -1; +let time = 0; + +let filenamePrefix = ""; + +let zip = null; + +let oldSizeW = op.patch.cgl.canvasWidth; +let oldSizeH = op.patch.cgl.canvasHeight; + +inType.onChange = updateQuality; +useCanvasSize.onChange = updateSize; + +updateQuality(); +updateSize(); + +inZip.onChange = () => +{ + zip = null; +}; + +function updateQuality() +{ + inQuality.setUiAttribs({ "greyout": inType.get() == "PNG" }); +} + +function updateSize() +{ + inWidth.setUiAttribs({ "greyout": useCanvasSize.get() }); + inHeight.setUiAttribs({ "greyout": useCanvasSize.get() }); +} + +inStart.onTriggered = function () +{ + filenamePrefix = inFilePrefix.get(); + op.log("pref", filenamePrefix); + frames.length = 0; + outStatus.set("Starting"); + fps = inFps.get(); + numFrames = inDuration.get() * fps; + if (inDurType.get() == "Frames")numFrames = inDuration.get(); + shortId = CABLES.shortId(); + updateTime(); + + if (inZip.get()) zip = new JSZip(); + + if (!useCanvasSize.get()) + { + oldSizeW = CABLES.patch.cgl.canvasWidth; + oldSizeH = CABLES.patch.cgl.canvasHeight; + op.patch.cgl.setSize(inWidth.get() / CABLES.patch.cgl.pixelDensity, inHeight.get() / CABLES.patch.cgl.pixelDensity); + op.patch.cgl.updateSize(); + } + + if (numFrames == 0) + { + countFrames = 0; + started = true; + } + else + { + countFrames = -20; + started = true; + lastFrame = -9999; + } +}; + +function updateTime() +{ + if (numFrames >= 0) + { + time = Math.max(0, countFrames * (1.0 / fps)); + op.patch.timer.setTime(time); + CABLES.overwriteTime = time;// - 1 / fps; + op.patch.freeTimer.setTime(time); + } +} + +function stopRendering() +{ + started = false; + CABLES.overwriteTime = undefined; + outStatus.set("Finished"); +} + +function render() +{ + outStarted.set(started); + + if (!started) + { + next.trigger(); + return; + } + + const oldInternalNow = CABLES.internalNow; + + if (started) + { + CABLES.internalNow = function () + { + return time * 1000; + }; + + updateTime(); + // CABLES.overwriteTime = time; + // op.patch.timer.setTime(time); + // op.patch.freeTimer.setTime(time); + } + + if (lastFrame == countFrames) + { + next.trigger(); + return; + } + + lastFrame = countFrames; + + let prog = countFrames / numFrames; + if (prog < 0.0) prog = 0.0; + outProgress.set(prog); + outFrame.set(countFrames); + + next.trigger(); + + CABLES.internalNow = oldInternalNow; + + frameStarted = false; + if (countFrames > numFrames) + { + op.log("FINISHED..."); + op.log("ffmpeg -y -framerate 30 -f image2 -i " + filenamePrefix + "_%d.png -b 9999k -vcodec mpeg4 " + shortId + ".mp4"); + + if (!useCanvasSize.get()) + { + op.patch.cgl.setSize(oldSizeW, oldSizeH); + op.patch.cgl.updateSize(); + } + + if (zip) + { + zip.generateAsync({ "type": "blob" }) + .then(function (blob) + { + const anchor = document.createElement("a"); + anchor.download = filenamePrefix + ".zip"; + anchor.href = URL.createObjectURL(blob); + if (inDownload.get()) + { + anchor.click(); + } + stopRendering(); + if (outUrl.isLinked()) + { + blobToDataURL(blob, (dataUrl) => { outUrl.set(dataUrl); outFinished.trigger(); }); + } + else + { + outUrl.set(null); + outFinished.trigger(); + } + }); + } + else + if (inType.get() == "WebM") + { + try + { + outStatus.set("Creating Video File from frames"); + op.log("webm frames", frames.length); + + const video = Whammy.fromImageArray(frames, fps); + const url = window.URL.createObjectURL(video); + const anchor = document.createElement("a"); + + anchor.setAttribute("download", filenamePrefix + ".webm"); + anchor.setAttribute("href", url); + document.body.appendChild(anchor); + if (inDownload.get()) + { + anchor.click(); + } + stopRendering(); + if (outUrl.isLinked()) + { + blobToDataURL(video, (dataUrl) => { outUrl.set(dataUrl); outFinished.trigger(); }); + } + else + { + outUrl.set(null); + outFinished.trigger(); + } + } + catch (e) + { + op.logError(e); + } + + frames.length = 0; + } + else + stopRendering(); + + return; + } + + let mimetype = "image/png"; + let suffix = "png"; + + if (inType.get() == "JPG") + { + mimetype = "image/jpeg"; + suffix = "jpg"; + } + else if (inType.get() == "WebP") + { + mimetype = "image/webp"; + suffix = "webp"; + } + + if (countFrames > 0) + { + outStatus.set("Rendering Frame " + countFrames + " of " + numFrames); + op.log("Rendering Frame " + countFrames + " of " + numFrames, time); + if (inType.get() == "WebM") + { + frames.push(op.patch.cgl.canvas.toDataURL("image/webp", inQuality.get() * 0.999)); + countFrames++; + updateTime(); + } + else + { + op.log("screenshotting frame...", countFrames); + op.patch.cgl.screenShot((blob) => + { + if (blob) + { + if (zip) + { + let filename = filenamePrefix + "_" + countFrames + "." + suffix; + + zip.file(filename, blob, { "base64": false }); + countFrames++; + updateTime(); + } + else + { + let filename = filenamePrefix + "_" + shortId + "_" + countFrames + "." + suffix; + + const anchor = document.createElement("a"); + anchor.download = filename; + anchor.href = URL.createObjectURL(blob); + + setTimeout(() => + { + if (outUrl.isLinked()) + { + blobToDataURL(blob, (dataUrl) => { outUrl.set(dataUrl); }); + } + else + { + outUrl.set(null); + } + if (inDownload.get()) + { + anchor.click(); + } + countFrames++; + updateTime(); + }, 200); + } + } + else + { + op.log("screenshot: no blob"); + } + }, !inTransparency.get(), mimetype, inQuality.get()); + } + } + else + { + outStatus.set("Prerendering..."); + op.log("pre ", countFrames, time); + op.patch.cgl.screenShot((blob) => + { + countFrames++; + updateTime(); + }); + } +} + +function blobToDataURL(blob, callback) +{ + let a = new FileReader(); + a.onload = function (e) { callback(e.target.result); }; + a.readAsDataURL(blob); +} + + +}; + +Ops.Gl.RenderAnim_v2.prototype = new CABLES.Op(); +CABLES.OPS["c05e54a3-3ed5-4941-a412-01134f53f0ac"]={f:Ops.Gl.RenderAnim_v2,objName:"Ops.Gl.RenderAnim_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.RenderGeometry +// +// ************************************************************** + +Ops.Gl.RenderGeometry = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + geometry = op.inObject("Geometry", null, "geometry"), + updateAll = op.inValueBool("Update All", true), + updateFaces = op.inValueBool("Update Face Indices", false), + updateVerts = op.inValueBool("Update Vertices", false), + updateTexcoords = op.inValueBool("Update Texcoords", false), + vertNums = op.inValueBool("Vertex Numbers", true), + trigger = op.outTrigger("trigger"); + +geometry.ignoreValueSerialize = true; + +vertNums.onChange = + geometry.onChange = update; + +let mesh = null; + +op.toWorkPortsNeedToBeLinked(geometry, render); + +render.onTriggered = function () +{ + if (mesh) mesh.render(op.patch.cgl.getShader()); + trigger.trigger(); +}; + +function update() +{ + const geom = geometry.get(); + if (geom && geom instanceof CGL.Geometry) + { + if (mesh) + { + mesh.dispose(); + mesh = null; + } + if (!mesh) + { + mesh = new CGL.Mesh(op.patch.cgl, geom); + mesh.addVertexNumbers = vertNums.get(); + mesh.setGeom(geom); + } + + if (updateFaces.get() || updateAll.get()) + mesh.setVertexIndices(geom.verticesIndices); + + if (updateTexcoords.get() || updateAll.get()) + mesh.updateTexCoords(geom); + + if (updateVerts.get() || updateAll.get()) + mesh.updateVertices(geom); + + mesh.addVertexNumbers = vertNums.get(); + + if (updateAll.get()) + { + if (geom.hasOwnProperty("tangents") && geom.tangents && geom.tangents.length > 0) mesh.setAttribute("attrTangent", geom.tangents, 3); + if (geom.hasOwnProperty("biTangents") && geom.biTangents && geom.biTangents.length > 0) mesh.setAttribute("attrBiTangent", geom.biTangents, 3); + } + } + else + { + mesh = null; + } +} + + +}; + +Ops.Gl.RenderGeometry.prototype = new CABLES.Op(); +CABLES.OPS["40fa6f13-ee0e-4386-a86b-711e1fbcf1bc"]={f:Ops.Gl.RenderGeometry,objName:"Ops.Gl.RenderGeometry"}; + + + + +// ************************************************************** +// +// Ops.Gl.ResetTransform +// +// ************************************************************** + +Ops.Gl.ResetTransform = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + trigger = op.outTrigger("trigger"), + inM = op.inBool("Reset Model Transform", true), + inV = op.inBool("Reset View Transform", true), + inDV = op.inBool("Default View", true), + cgl = op.patch.cgl; + +let doView = false, + doModel = false, + vDefault = false; + +const identView = vec3.create(); +vec3.set(identView, 0, 0, -2); + +exe.onTriggered = ex; + +inM.onChange = + inDV.onChange = + inV.onChange = updateState; +updateState(); + +function updateState() +{ + doView = inV.get(); + doModel = inM.get(); + vDefault = inDV.get(); + inDV.setUiAttribs({ "greyout": !doView }); +} + + +function ex() +{ + if (doView) + { + cgl.pushViewMatrix(); + mat4.identity(cgl.vMatrix); + if (vDefault) + { + mat4.translate(cgl.vMatrix, cgl.vMatrix, identView); + } + } + + if (doModel) + { + cgl.pushModelMatrix(); + mat4.identity(cgl.mMatrix); + } + + trigger.trigger(); + + if (doView) cgl.popViewMatrix(); + if (doModel) cgl.popModelMatrix(); +} + + +}; + +Ops.Gl.ResetTransform.prototype = new CABLES.Op(); +CABLES.OPS["1bf7c63e-e2c2-42e2-abb3-42235e7e24f0"]={f:Ops.Gl.ResetTransform,objName:"Ops.Gl.ResetTransform"}; + + + + +// ************************************************************** +// +// Ops.Gl.SaveScreenShot_v3 +// +// ************************************************************** + +Ops.Gl.SaveScreenShot_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + filename = op.inString("Filename", "cables"), + exe = op.inTriggerButton("Screenshot"), + outNext = op.outTrigger("Finished"); + + +const cgl = op.patch.cgl; + +exe.onTriggered = function () +{ + cgl.saveScreenshot( + filename.get(), + function () + { + outNext.trigger(); + + op.patch.resume(); + } + ); +}; + + + +}; + +Ops.Gl.SaveScreenShot_v3.prototype = new CABLES.Op(); +CABLES.OPS["76843a4d-947f-41ca-9c8f-0faa6ce7380a"]={f:Ops.Gl.SaveScreenShot_v3,objName:"Ops.Gl.SaveScreenShot_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.AttributeAsColorMaterial +// +// ************************************************************** + +Ops.Gl.Shader.AttributeAsColorMaterial = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"normalsmaterial_frag":"IN vec3 normal;\nIN vec3 outTangent;\nIN vec3 outBiTangent;\nIN mat4 mMatrix;\nIN vec2 texCoord;\nIN vec3 vert;\nIN mat4 mvMatrix;\n\n\n{{MODULES_HEAD}}\n\nvoid main()\n{\n #ifdef MULMODEL\n vec4 attr;\n attr.w=1.0;\n #endif\n #ifndef MULMODEL\n vec3 attr;\n #endif\n\n #ifdef SHOW_NORMALS\n attr.xyz=normal;\n #endif\n #ifdef SHOW_BITANGENTS\n attr.xyz=outBiTangent;\n #endif\n #ifdef SHOW_TANGENTS\n attr.xyz=outTangent;\n #endif\n #ifdef SHOW_TEXCOORDS\n attr.xy=texCoord;\n #endif\n #ifdef SHOW_POSITION\n attr.xyz=vert;\n #endif\n\n #ifdef MULMODEL\n attr*=mMatrix;\n attr.xyz=normalize(vec3(attr.x,attr.y,attr.z));\n #endif\n\n vec4 col=vec4(attr.x,attr.y,attr.z,1.0);\n\n #ifdef ABS\n col=abs(col);\n #endif\n\n {{MODULE_COLOR}}\n\n outColor=col;\n}","normalsmaterial_vert":"IN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal,attrTangent,attrBiTangent;\nOUT vec2 texCoord;\nOUT vec3 normal;\nOUT vec3 tangent;\nOUT vec3 bitangent;\nOUT vec3 outTangent,outBiTangent;\nOUT mat4 mMatrix;\nOUT vec3 vert;\nOUT mat4 mvMatrix;\nUNI mat4 projMatrix;\n\n// UNI mat4 mvMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\n\n\n{{MODULES_HEAD}}\n\nvoid main()\n{\n texCoord=attrTexCoord;\n vec3 norm=attrVertNormal;\n tangent=attrTangent;\n bitangent=attrBiTangent;\n\n vec4 pos=vec4(vPosition,1.0);\n mMatrix=modelMatrix;\n\n {{MODULE_VERTEX_POSITION}}\n\n mat4 mvMatrix=viewMatrix*mMatrix;\n\n vert=pos.xyz;\n normal=norm;\n outTangent=tangent;\n outBiTangent=bitangent;\n\n gl_Position = projMatrix * mvMatrix * pos;\n}",}; +const + render = op.inTrigger("render"), + inAttr = op.inSwitch("Attribute", ["TexCoords", "Normals", "Tangents", "BiTangents"], "Normals"), + inAbs = op.inBool("Absolute", false), + inMulModel = op.inBool("World Space", false), + trigger = op.outTrigger("trigger"), + outShader = op.outObject("Shader"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(attachments.normalsmaterial_vert, attachments.normalsmaterial_frag); +outShader.set(shader); +render.onTriggered = doRender; +updateAttr(); +inMulModel.onChange = inAbs.onChange = inAttr.onChange = updateAttr; + +function updateAttr() +{ + shader.toggleDefine("SHOW_NORMALS", inAttr.get() == "Normals"); + shader.toggleDefine("SHOW_TANGENTS", inAttr.get() == "Tangents"); + shader.toggleDefine("SHOW_BITANGENTS", inAttr.get() == "BiTangents"); + shader.toggleDefine("SHOW_TEXCOORDS", inAttr.get() == "TexCoords"); + + shader.toggleDefine("ABS", inAbs.get()); + shader.toggleDefine("MULMODEL", inMulModel.get()); +} + +function doRender() +{ + cgl.pushShader(shader); + trigger.trigger(); + cgl.popShader(); +} + + +}; + +Ops.Gl.Shader.AttributeAsColorMaterial.prototype = new CABLES.Op(); +CABLES.OPS["2963fd23-a860-461a-a3cf-394b8261159f"]={f:Ops.Gl.Shader.AttributeAsColorMaterial,objName:"Ops.Gl.Shader.AttributeAsColorMaterial"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.BasicMaterial_v3 +// +// ************************************************************** + +Ops.Gl.Shader.BasicMaterial_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"basicmaterial_frag":"{{MODULES_HEAD}}\n\nIN vec2 texCoord;\n\n#ifdef VERTEX_COLORS\nIN vec4 vertCol;\n#endif\n\n#ifdef HAS_TEXTURES\n IN vec2 texCoordOrig;\n #ifdef HAS_TEXTURE_DIFFUSE\n UNI sampler2D tex;\n #endif\n #ifdef HAS_TEXTURE_OPACITY\n UNI sampler2D texOpacity;\n #endif\n#endif\n\nvoid main()\n{\n {{MODULE_BEGIN_FRAG}}\n vec4 col=color;\n\n\n #ifdef HAS_TEXTURES\n vec2 uv=texCoord;\n\n #ifdef CROP_TEXCOORDS\n if(uv.x<0.0 || uv.x>1.0 || uv.y<0.0 || uv.y>1.0) discard;\n #endif\n\n #ifdef HAS_TEXTURE_DIFFUSE\n col=texture(tex,uv);\n\n #ifdef COLORIZE_TEXTURE\n col.r*=color.r;\n col.g*=color.g;\n col.b*=color.b;\n #endif\n #endif\n col.a*=color.a;\n #ifdef HAS_TEXTURE_OPACITY\n #ifdef TRANSFORMALPHATEXCOORDS\n uv=texCoordOrig;\n #endif\n #ifdef ALPHA_MASK_IALPHA\n col.a*=1.0-texture(texOpacity,uv).a;\n #endif\n #ifdef ALPHA_MASK_ALPHA\n col.a*=texture(texOpacity,uv).a;\n #endif\n #ifdef ALPHA_MASK_LUMI\n col.a*=dot(vec3(0.2126,0.7152,0.0722), texture(texOpacity,uv).rgb);\n #endif\n #ifdef ALPHA_MASK_R\n col.a*=texture(texOpacity,uv).r;\n #endif\n #ifdef ALPHA_MASK_G\n col.a*=texture(texOpacity,uv).g;\n #endif\n #ifdef ALPHA_MASK_B\n col.a*=texture(texOpacity,uv).b;\n #endif\n // #endif\n #endif\n #endif\n\n {{MODULE_COLOR}}\n\n #ifdef DISCARDTRANS\n if(col.a<0.2) discard;\n #endif\n\n #ifdef VERTEX_COLORS\n col*=vertCol;\n #endif\n\n outColor = col;\n}\n","basicmaterial_vert":"\n{{MODULES_HEAD}}\n\n// OUT vec3 norm;\nOUT vec2 texCoord;\nOUT vec2 texCoordOrig;\n\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\n\n#ifdef HAS_TEXTURES\n UNI float diffuseRepeatX;\n UNI float diffuseRepeatY;\n UNI float texOffsetX;\n UNI float texOffsetY;\n#endif\n\n#ifdef VERTEX_COLORS\n in vec4 attrVertColor;\n out vec4 vertCol;\n\n#endif\n\n\nvoid main()\n{\n mat4 mMatrix=modelMatrix;\n mat4 mvMatrix;\n\n norm=attrVertNormal;\n texCoordOrig=attrTexCoord;\n texCoord=attrTexCoord;\n #ifdef HAS_TEXTURES\n texCoord.x=texCoord.x*diffuseRepeatX+texOffsetX;\n texCoord.y=(1.0-texCoord.y)*diffuseRepeatY+texOffsetY;\n #endif\n\n #ifdef VERTEX_COLORS\n vertCol=attrVertColor;\n #endif\n\n vec4 pos = vec4(vPosition, 1.0);\n\n #ifdef BILLBOARD\n vec3 position=vPosition;\n mvMatrix=viewMatrix*modelMatrix;\n\n gl_Position = projMatrix * mvMatrix * vec4((\n position.x * vec3(\n mvMatrix[0][0],\n mvMatrix[1][0],\n mvMatrix[2][0] ) +\n position.y * vec3(\n mvMatrix[0][1],\n mvMatrix[1][1],\n mvMatrix[2][1]) ), 1.0);\n #endif\n\n {{MODULE_VERTEX_POSITION}}\n\n #ifndef BILLBOARD\n mvMatrix=viewMatrix * mMatrix;\n #endif\n\n\n #ifndef BILLBOARD\n // gl_Position = projMatrix * viewMatrix * modelMatrix * pos;\n gl_Position = projMatrix * mvMatrix * pos;\n #endif\n}\n",}; +const render = op.inTrigger("render"); + +const trigger = op.outTrigger("trigger"); +const shaderOut = op.outObject("shader", null, "shader"); + +shaderOut.ignoreValueSerialize = true; + +op.toWorkPortsNeedToBeLinked(render); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "basicmaterialnew"); +shader.addAttribute({ "type": "vec3", "name": "vPosition" }); +shader.addAttribute({ "type": "vec2", "name": "attrTexCoord" }); +shader.addAttribute({ "type": "vec3", "name": "attrVertNormal", "nameFrag": "norm" }); +shader.addAttribute({ "type": "float", "name": "attrVertIndex" }); + +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); + +shader.setSource(attachments.basicmaterial_vert, attachments.basicmaterial_frag); + +shaderOut.set(shader); + +render.onTriggered = doRender; + +// rgba colors +const r = op.inValueSlider("r", Math.random()); +const g = op.inValueSlider("g", Math.random()); +const b = op.inValueSlider("b", Math.random()); +const a = op.inValueSlider("a", 1); +r.setUiAttribs({ "colorPick": true }); + +// const uniColor=new CGL.Uniform(shader,'4f','color',r,g,b,a); +const colUni = shader.addUniformFrag("4f", "color", r, g, b, a); + +shader.uniformColorDiffuse = colUni; + +// diffuse outTexture + +const diffuseTexture = op.inTexture("texture"); +let diffuseTextureUniform = null; +diffuseTexture.onChange = updateDiffuseTexture; + +const colorizeTexture = op.inValueBool("colorizeTexture", false); +const vertexColors = op.inValueBool("Vertex Colors", false); + +// opacity texture +const textureOpacity = op.inTexture("textureOpacity"); +let textureOpacityUniform = null; + +const alphaMaskSource = op.inSwitch("Alpha Mask Source", ["Luminance", "R", "G", "B", "A", "1-A"], "Luminance"); +alphaMaskSource.setUiAttribs({ "greyout": true }); +textureOpacity.onChange = updateOpacity; + +const texCoordAlpha = op.inValueBool("Opacity TexCoords Transform", false); +const discardTransPxl = op.inValueBool("Discard Transparent Pixels"); + +// texture coords +const + diffuseRepeatX = op.inValue("diffuseRepeatX", 1), + diffuseRepeatY = op.inValue("diffuseRepeatY", 1), + diffuseOffsetX = op.inValue("Tex Offset X", 0), + diffuseOffsetY = op.inValue("Tex Offset Y", 0), + cropRepeat = op.inBool("Crop TexCoords", false); + +shader.addUniformFrag("f", "diffuseRepeatX", diffuseRepeatX); +shader.addUniformFrag("f", "diffuseRepeatY", diffuseRepeatY); +shader.addUniformFrag("f", "texOffsetX", diffuseOffsetX); +shader.addUniformFrag("f", "texOffsetY", diffuseOffsetY); + +const doBillboard = op.inValueBool("billboard", false); + +alphaMaskSource.onChange = + doBillboard.onChange = + discardTransPxl.onChange = + texCoordAlpha.onChange = + cropRepeat.onChange = + vertexColors.onChange = + colorizeTexture.onChange = updateDefines; + +op.setPortGroup("Color", [r, g, b, a]); +op.setPortGroup("Color Texture", [diffuseTexture, vertexColors, colorizeTexture]); +op.setPortGroup("Opacity", [textureOpacity, alphaMaskSource, discardTransPxl, texCoordAlpha]); +op.setPortGroup("Texture Transform", [diffuseRepeatX, diffuseRepeatY, diffuseOffsetX, diffuseOffsetY, cropRepeat]); + +updateOpacity(); +updateDiffuseTexture(); + +op.preRender = function () +{ + shader.bind(); + doRender(); +}; + +function doRender() +{ + if (!shader) return; + + cgl.pushShader(shader); + shader.popTextures(); + + if (diffuseTextureUniform && diffuseTexture.get()) shader.pushTexture(diffuseTextureUniform, diffuseTexture.get()); + if (textureOpacityUniform && textureOpacity.get()) shader.pushTexture(textureOpacityUniform, textureOpacity.get()); + + trigger.trigger(); + + cgl.popShader(); +} + +function updateOpacity() +{ + if (textureOpacity.get()) + { + if (textureOpacityUniform !== null) return; + shader.removeUniform("texOpacity"); + shader.define("HAS_TEXTURE_OPACITY"); + if (!textureOpacityUniform)textureOpacityUniform = new CGL.Uniform(shader, "t", "texOpacity"); + + alphaMaskSource.setUiAttribs({ "greyout": false }); + texCoordAlpha.setUiAttribs({ "greyout": false }); + } + else + { + shader.removeUniform("texOpacity"); + shader.removeDefine("HAS_TEXTURE_OPACITY"); + textureOpacityUniform = null; + + alphaMaskSource.setUiAttribs({ "greyout": true }); + texCoordAlpha.setUiAttribs({ "greyout": true }); + } + + updateDefines(); +} + +function updateDiffuseTexture() +{ + if (diffuseTexture.get()) + { + if (!shader.hasDefine("HAS_TEXTURE_DIFFUSE"))shader.define("HAS_TEXTURE_DIFFUSE"); + if (!diffuseTextureUniform)diffuseTextureUniform = new CGL.Uniform(shader, "t", "texDiffuse"); + + diffuseRepeatX.setUiAttribs({ "greyout": false }); + diffuseRepeatY.setUiAttribs({ "greyout": false }); + diffuseOffsetX.setUiAttribs({ "greyout": false }); + diffuseOffsetY.setUiAttribs({ "greyout": false }); + colorizeTexture.setUiAttribs({ "greyout": false }); + } + else + { + shader.removeUniform("texDiffuse"); + shader.removeDefine("HAS_TEXTURE_DIFFUSE"); + diffuseTextureUniform = null; + + diffuseRepeatX.setUiAttribs({ "greyout": true }); + diffuseRepeatY.setUiAttribs({ "greyout": true }); + diffuseOffsetX.setUiAttribs({ "greyout": true }); + diffuseOffsetY.setUiAttribs({ "greyout": true }); + colorizeTexture.setUiAttribs({ "greyout": true }); + } +} + +function updateDefines() +{ + shader.toggleDefine("VERTEX_COLORS", vertexColors.get()); + shader.toggleDefine("CROP_TEXCOORDS", cropRepeat.get()); + shader.toggleDefine("COLORIZE_TEXTURE", colorizeTexture.get()); + shader.toggleDefine("TRANSFORMALPHATEXCOORDS", texCoordAlpha.get()); + shader.toggleDefine("DISCARDTRANS", discardTransPxl.get()); + shader.toggleDefine("BILLBOARD", doBillboard.get()); + + shader.toggleDefine("ALPHA_MASK_ALPHA", alphaMaskSource.get() == "A"); + shader.toggleDefine("ALPHA_MASK_IALPHA", alphaMaskSource.get() == "1-A"); + shader.toggleDefine("ALPHA_MASK_LUMI", alphaMaskSource.get() == "Luminance"); + shader.toggleDefine("ALPHA_MASK_R", alphaMaskSource.get() == "R"); + shader.toggleDefine("ALPHA_MASK_G", alphaMaskSource.get() == "G"); + shader.toggleDefine("ALPHA_MASK_B", alphaMaskSource.get() == "B"); +} + + +}; + +Ops.Gl.Shader.BasicMaterial_v3.prototype = new CABLES.Op(); +CABLES.OPS["ec55d252-3843-41b1-b731-0482dbd9e72b"]={f:Ops.Gl.Shader.BasicMaterial_v3,objName:"Ops.Gl.Shader.BasicMaterial_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.ChromaKeyMaterial +// +// ************************************************************** + +Ops.Gl.Shader.ChromaKeyMaterial = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"chromakeymaterial_frag":"{{MODULE_BEGIN_FRAG}}\n\nIN vec2 texCoord;\n\nUNI sampler2D tex;\nUNI float r;\nUNI float g;\nUNI float b;\nUNI float weightMul;\nUNI float white;\n\nvec3 rgb2hsv(vec4 rgb)\n{\n\tfloat Cmax = max(rgb.r, max(rgb.g, rgb.b));\n\tfloat Cmin = min(rgb.r, min(rgb.g, rgb.b));\n float delta = Cmax - Cmin;\n\n\tvec3 hsv = vec3(0., 0., Cmax);\n\n\tif (Cmax > Cmin)\n\t{\n\t\thsv.y = delta / Cmax;\n\n\t\tif (rgb.r == Cmax)\n\t\t\thsv.x = (rgb.g - rgb.b) / delta;\n\t\telse\n\t\t{\n\t\t\tif (rgb.g == Cmax)\n\t\t\t\thsv.x = 2. + (rgb.b - rgb.r) / delta;\n\t\t\telse\n\t\t\t\thsv.x = 4. + (rgb.r - rgb.g) / delta;\n\t\t}\n\t\thsv.x = fract(hsv.x / 6.);\n\t}\n\treturn hsv;\n}\n\nfloat chromaKey(vec4 color)\n{\n vec4 backgroundColor = vec4(r,g,b,0.0);\n vec3 weights = vec3(4.*weightMul, 1., 2.*weightMul);\n\n vec3 hsv = rgb2hsv(color);\n vec3 target = rgb2hsv(backgroundColor);\n float dist = length(weights * (target - hsv));\n\n return 1. - clamp(3. * dist - 1.5, 0., 1.);\n}\n\nfloat random(vec2 co)\n{\n return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * (43758.5453));\n}\n\nvoid main()\n{\n vec4 col=vec4(1.0,1.0,0.0,1.0);\n {{MODULE_COLOR}}\n col=texture(tex,texCoord);\n\n #ifdef MODE_R\n float maxrb = max( col.g, col.b );\n float perc = min(1.0,(col.r*weightMul-maxrb)*2.0);\n #endif\n\n #ifdef MODE_G\n float maxrb = max( col.r, col.b );\n float perc = min(1.0,(col.g*weightMul-maxrb)*2.0);\n col.g=min(maxrb,col.g);\n #endif\n\n #ifdef MODE_COLOR\n float perc=chromaKey(col);\n #endif\n\n float len=length(col);\n col=normalize(col)*len;\n\n col.a=1.0-perc;\n outColor= col;\n}\n","chromakeymaterial_vert":"{{MODULES_HEAD}}\n\nIN vec3 vPosition;\nUNI mat4 projMatrix;\nUNI mat4 mvMatrix;\nIN vec2 attrTexCoord;\nOUT vec2 texCoord;\n\nUNI float diffuseRepeatX;\nUNI float diffuseRepeatY;\nUNI float texOffsetX;\nUNI float texOffsetY;\n\nvoid main()\n{\n texCoord=vec2(attrTexCoord.x,1.0-attrTexCoord.y);\n\n texCoord.s=texCoord.s*diffuseRepeatX+texOffsetX;\n texCoord.t=texCoord.t*diffuseRepeatY+texOffsetY;\n\n vec4 pos=vec4(vPosition, 1.0);\n {{MODULE_VERTEX_POSITION}}\n gl_Position = projMatrix * mvMatrix * pos;\n}\n",}; +const render = op.inTrigger("render"); +const texture = op.inTexture("texture"); + +const inMode = op.inValueSelect("Mode", ["G", "R", "COLOR"], "COLOR"); +const trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; + +render.onTriggered = doRender; + +let textureUniform = null; +let shader = new CGL.Shader(cgl, "MinimalMaterial"); +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); +shader.setSource(attachments.chromakeymaterial_vert, attachments.chromakeymaterial_frag); +shader.define("MODE_COLOR"); + +op.toWorkPortsNeedToBeLinked(texture); + +function doRender() +{ + if (shader) + { + cgl.pushShader(shader); + shader.bindTextures(); + trigger.trigger(); + cgl.popShader(); + } +} + +shader.bindTextures = function () +{ + if (texture.get()) cgl.setTexture(0, texture.get().tex); + // else cgl.setTexture(0, CGL.Texture.getTemporaryTexture()); +}; + +inMode.onChange = function () +{ + shader.removeDefine("MODE_G"); + shader.removeDefine("MODE_R"); + shader.removeDefine("MODE_COLOR"); + if (inMode.get() == "R") shader.define("MODE_R"); + else if (inMode.get() == "G") shader.define("MODE_G"); + else if (inMode.get() == "COLOR") shader.define("MODE_COLOR"); +}; + +texture.onChange = function () +{ + if (texture.get()) + { + if (textureUniform !== null) return; + shader.removeUniform("tex"); + shader.define("HAS_TEXTURE_DIFFUSE"); + textureUniform = new CGL.Uniform(shader, "t", "tex", 0); + } + else + { + shader.removeUniform("tex"); + shader.removeDefine("HAS_TEXTURE_DIFFUSE"); + textureUniform = null; + } +}; + +let w = op.inValueSlider("weightMul", 0.6); +w.uniform = new CGL.Uniform(shader, "f", "weightMul", w); + +const r = op.inValueSlider("r", Math.random()); +const g = op.inValueSlider("g", Math.random()); +const b = op.inValueSlider("b", Math.random()); +r.setUiAttribs({ "colorPick": true }); + +r.set(0.467); +r.uniform = new CGL.Uniform(shader, "f", "r", r); + +g.set(0.836); +g.uniform = new CGL.Uniform(shader, "f", "g", g); + +b.set(0.098); +b.uniform = new CGL.Uniform(shader, "f", "b", b); + +let white = op.inValueSlider("white", 0); +white.uniform = new CGL.Uniform(shader, "f", "white", white); + +const diffuseRepeatX = op.inValue("diffuseRepeatX", 1); +const diffuseRepeatY = op.inValue("diffuseRepeatY", 1); + +const diffuseOffsetX = op.inValue("Tex Offset X", 0); +const diffuseOffsetY = op.inValue("Tex Offset Y", 0); + +const diffuseRepeatXUniform = new CGL.Uniform(shader, "f", "diffuseRepeatX", diffuseRepeatX); +const diffuseRepeatYUniform = new CGL.Uniform(shader, "f", "diffuseRepeatY", diffuseRepeatY); +const diffuseOffsetXUniform = new CGL.Uniform(shader, "f", "texOffsetX", diffuseOffsetX); +const diffuseOffsetYUniform = new CGL.Uniform(shader, "f", "texOffsetY", diffuseOffsetY); + + +}; + +Ops.Gl.Shader.ChromaKeyMaterial.prototype = new CABLES.Op(); +CABLES.OPS["20be6064-b332-447c-a220-e70d5bc506e0"]={f:Ops.Gl.Shader.ChromaKeyMaterial,objName:"Ops.Gl.Shader.ChromaKeyMaterial"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.CustomShader_v2 +// +// ************************************************************** + +Ops.Gl.Shader.CustomShader_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + fragmentShader = op.inStringEditor("Fragment Code"), + vertexShader = op.inStringEditor("Vertex Code"), + asMaterial = op.inValueBool("Use As Material", true), + trigger = op.outTrigger("trigger"), + outShader = op.outObject("Shader", null, "shader"), + outErrors = op.outBool("Has Errors"); + +const cgl = op.patch.cgl; +const uniformInputs = []; +const uniformTextures = []; +const vectors = []; + +op.toWorkPortsNeedToBeLinked(render); + +fragmentShader.setUiAttribs({ "editorSyntax": "glsl" }); +vertexShader.setUiAttribs({ "editorSyntax": "glsl" }); + +const shader = new CGL.Shader(cgl, op.name); + +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); + +op.setPortGroup("Source Code", [fragmentShader, vertexShader]); +op.setPortGroup("Options", [asMaterial]); + +fragmentShader.set(CGL.Shader.getDefaultFragmentShader()); +vertexShader.set(CGL.Shader.getDefaultVertexShader()); + +fragmentShader.onChange = vertexShader.onChange = function () +{ + if (fragmentShader.isLinked() && !fragmentShader.get()) return; + needsUpdate = true; +}; + +render.onTriggered = doRender; + +let needsUpdate = true; +op.onLoadedValueSet = initDataOnLoad; + +function initDataOnLoad(data) +{ + updateShader(); + + // set uniform values AFTER shader has been compiled and uniforms are extracted and uniform ports are created. + for (let i = 0; i < uniformInputs.length; i++) + for (let j = 0; j < data.portsIn.length; j++) + if (uniformInputs[i] && uniformInputs[i].name == data.portsIn[j].name) + { + uniformInputs[i].set(data.portsIn[j].value); + uniformInputs[i].deSerializeSettings(data.portsIn[j]); + } +} + +op.init = function () +{ + updateShader(); +}; + +function doRender() +{ + setVectorValues(); + if (needsUpdate)updateShader(); + if (asMaterial.get()) cgl.pushShader(shader); + pushTextures(); + trigger.trigger(); + shader.popTextures(); + if (asMaterial.get()) cgl.popShader(); +} + +function pushTextures() +{ + for (let i = 0; i < uniformTextures.length; i++) + if (uniformTextures[i] && uniformTextures[i].get() && uniformTextures[i].get().tex) + shader.pushTexture(uniformTextures[i].uniform, uniformTextures[i].get().tex); + else + shader.pushTexture(uniformTextures[i], CGL.Texture.getEmptyTexture(cgl)); +} + +function bindTextures()// old - should be removed in next version ? +{ + for (let i = 0; i < uniformTextures.length; i++) + if (uniformTextures[i] && uniformTextures[i].get() && uniformTextures[i].get().tex) + cgl.setTexture(0 + i + 3, uniformTextures[i].get().tex); +} + +function hasUniformInput(name) +{ + for (let i = 0; i < uniformInputs.length; i++) if (uniformInputs[i] && uniformInputs[i].name == name) return true; + for (let i = 0; i < uniformTextures.length; i++) if (uniformTextures[i] && uniformTextures[i].name == name) return true; + return false; +} + +const tempMat4 = mat4.create(); +const uniformNameBlacklist = [ + "modelMatrix", + "viewMatrix", + "normalMatrix", + "mvMatrix", + "projMatrix", + "inverseViewMatrix", + "camPos" +]; + +let countTexture = 0; +const foundNames = []; + +function parseUniforms(src) +{ + const lblines = src.split("\n"); + const groupUniforms = []; + + for (let k = 0; k < lblines.length; k++) + { + const lines = lblines[k].split(";"); + + for (let i = 0; i < lines.length; i++) + { + let words = lines[i].split(" "); + + for (let j = 0; j < words.length; j++) words[j] = (words[j] + "").trim(); + + if (words[0] === "UNI" || words[0] === "uniform") + { + let varnames = words[2]; + if (words.length > 4) for (let j = 3; j < words.length; j++)varnames += words[j]; + + words = words.filter(function (el) { return el !== ""; }); + const type = words[1]; + + let names = [varnames]; + if (varnames.indexOf(",") > -1) names = varnames.split(","); + + for (let l = 0; l < names.length; l++) + { + if (uniformNameBlacklist.indexOf(names[l]) > -1) continue; + const uniName = names[l].trim(); + + if (type === "float") + { + foundNames.push(uniName); + if (!hasUniformInput(uniName)) + { + const newInput = op.inFloat(uniName, 0); + newInput.uniform = new CGL.Uniform(shader, "f", uniName, newInput); + uniformInputs.push(newInput); + groupUniforms.push(newInput); + } + } + else if (type === "int") + { + foundNames.push(uniName); + if (!hasUniformInput(uniName)) + { + const newInput = op.inInt(uniName, 0); + newInput.uniform = new CGL.Uniform(shader, "i", uniName, newInput); + uniformInputs.push(newInput); + groupUniforms.push(newInput); + } + } + else if (type === "bool") + { + foundNames.push(uniName); + if (!hasUniformInput(uniName)) + { + const newInput = op.inBool(uniName, false); + newInput.uniform = new CGL.Uniform(shader, "b", uniName, newInput); + uniformInputs.push(newInput); + groupUniforms.push(newInput); + } + } + else if (type === "mat4") + { + foundNames.push(uniName); + if (!hasUniformInput(uniName)) + { + const newInput = op.inArray(uniName, 0); + newInput.uniform = new CGL.Uniform(shader, "m4", uniName, newInput); + uniformInputs.push(newInput); + groupUniforms.push(newInput); + + const vec = { + "name": uniName, + "num": 16, + "port": newInput, + "uni": newInput.uniform, + "changed": false + }; + newInput.onChange = function () { this.changed = true; }.bind(vec); + + vectors.push(vec); + } + } + else if (type === "sampler2D" || type === "samplerCube") + { + foundNames.push(uniName); + if (!hasUniformInput(uniName)) + { + const newInputTex = op.inObject(uniName); + + let uniType = "t"; + if (type === "samplerCube")uniType = "tc"; + + newInputTex.uniform = new CGL.Uniform(shader, uniType, uniName, 3 + uniformTextures.length); + uniformTextures.push(newInputTex); + groupUniforms.push(newInputTex); + newInputTex.set(CGL.Texture.getTempTexture(cgl)); + newInputTex.on("change", (v, p) => + { + if (!v)p.set(CGL.Texture.getTempTexture(cgl)); + }); + countTexture++; + } + } + else if (type === "vec3" || type === "vec2" || type === "vec4") + { + let num = 2; + if (type === "vec4")num = 4; + if (type === "vec3")num = 3; + foundNames.push(uniName + " X"); + foundNames.push(uniName + " Y"); + if (num > 2)foundNames.push(uniName + " Z"); + if (num > 3)foundNames.push(uniName + " W"); + + if (!hasUniformInput(uniName + " X")) + { + const group = []; + const vec = { + "name": uniName, + "num": num, + "changed": false, + }; + vectors.push(vec); + initVectorUniform(vec); + + const newInputX = op.inFloat(uniName + " X", 0); + newInputX.onChange = function () { this.changed = true; }.bind(vec); + uniformInputs.push(newInputX); + group.push(newInputX); + vec.x = newInputX; + + const newInputY = op.inFloat(uniName + " Y", 0); + newInputY.onChange = function () { this.changed = true; }.bind(vec); + uniformInputs.push(newInputY); + group.push(newInputY); + vec.y = newInputY; + + if (num > 2) + { + const newInputZ = op.inFloat(uniName + " Z", 0); + newInputZ.onChange = function () { this.changed = true; }.bind(vec); + uniformInputs.push(newInputZ); + group.push(newInputZ); + vec.z = newInputZ; + } + if (num > 3) + { + const newInputW = op.inFloat(uniName + " W", 0); + newInputW.onChange = function () { this.changed = true; }.bind(vec); + uniformInputs.push(newInputW); + group.push(newInputW); + vec.w = newInputW; + } + + op.setPortGroup(uniName, group); + } + } + } + } + } + } + op.setPortGroup("uniforms", groupUniforms); +} + +function updateShader() +{ + if (!shader) return; + + shader.bindTextures = bindTextures.bind(this); + shader.setSource(vertexShader.get(), fragmentShader.get()); + + if (cgl.glVersion == 1) + { + cgl.gl.getExtension("OES_standard_derivatives"); + // cgl.gl.getExtension('OES_texture_float'); + // cgl.gl.getExtension('OES_texture_float_linear'); + // cgl.gl.getExtension('OES_texture_half_float'); + // cgl.gl.getExtension('OES_texture_half_float_linear'); + + shader.enableExtension("GL_OES_standard_derivatives"); + // shader.enableExtension("GL_OES_texture_float"); + // shader.enableExtension("GL_OES_texture_float_linear"); + // shader.enableExtension("GL_OES_texture_half_float"); + // shader.enableExtension("GL_OES_texture_half_float_linear"); + } + + countTexture = 0; + foundNames.length = 0; + + parseUniforms(vertexShader.get()); + parseUniforms(fragmentShader.get()); + + for (let j = 0; j < uniformTextures.length; j++) + for (let i = 0; i < foundNames.length; i++) + if (uniformTextures[j] && foundNames.indexOf(uniformTextures[j].name) == -1) + { + uniformTextures[j].remove(); + uniformTextures[j] = null; + } + + for (let j = 0; j < uniformInputs.length; j++) + for (let i = 0; i < foundNames.length; i++) + if (uniformInputs[j] && foundNames.indexOf(uniformInputs[j].name) == -1) + { + uniformInputs[j].remove(); + uniformInputs[j] = null; + } + + for (let j = 0; j < vectors.length; j++) + { + initVectorUniform(vectors[j]); + vectors[j].changed = true; + } + + for (let i = 0; i < uniformInputs.length; i++) + if (uniformInputs[i] && uniformInputs[i].uniform)uniformInputs[i].uniform.needsUpdate = true; + + shader.compile(); + + op.refreshParams(); + + outShader.set(null); + outShader.set(shader); + needsUpdate = false; + + if (shader.hasErrors()) op.setUiError("compile", "Shader has errors"); + else op.setUiError("compile", null); + + outErrors.set(shader.hasErrors()); +} + +function initVectorUniform(vec) +{ + if (vec.num == 2) vec.uni = new CGL.Uniform(shader, "2f", vec.name, [0, 0]); + else if (vec.num == 3) vec.uni = new CGL.Uniform(shader, "3f", vec.name, [0, 0, 0]); + else if (vec.num == 4) vec.uni = new CGL.Uniform(shader, "4f", vec.name, [0, 0, 0, 0]); +} + +function setVectorValues() +{ + for (let i = 0; i < vectors.length; i++) + { + const v = vectors[i]; + if (v.changed) + { + if (v.num === 2) v.uni.setValue([v.x.get(), v.y.get()]); + else if (v.num === 3) v.uni.setValue([v.x.get(), v.y.get(), v.z.get()]); + else if (v.num === 4) v.uni.setValue([v.x.get(), v.y.get(), v.z.get(), v.w.get()]); + + else if (v.num > 4) + { + v.uni.setValue(v.port.get()); + } + + v.changed = false; + } + } +} + + +}; + +Ops.Gl.Shader.CustomShader_v2.prototype = new CABLES.Op(); +CABLES.OPS["a165fc89-a35b-4d39-8930-7345b098bd9d"]={f:Ops.Gl.Shader.CustomShader_v2,objName:"Ops.Gl.Shader.CustomShader_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.ErrorMaterial +// +// ************************************************************** + +Ops.Gl.Shader.ErrorMaterial = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "errormaterial"); + +shader.setSource(CGL.Shader.getDefaultVertexShader(), CGL.Shader.getErrorFragmentShader()); +render.onTriggered = doRender; + +function doRender() +{ + cgl.pushShader(shader); + trigger.trigger(); + cgl.popShader(); +} + + +}; + +Ops.Gl.Shader.ErrorMaterial.prototype = new CABLES.Op(); +CABLES.OPS["a16c565a-574d-48d2-a95e-1bdce96dc00f"]={f:Ops.Gl.Shader.ErrorMaterial,objName:"Ops.Gl.Shader.ErrorMaterial"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.FrontBacksideMaterial +// +// ************************************************************** + +Ops.Gl.Shader.FrontBacksideMaterial = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"frontbacksidematerial_frag":"void main()\n{\n if(!gl_FrontFacing) outColor= vec4(1.0,0.0,0.0,1.0);\n else outColor=vec4(0.0,1.0,0.0,1.0);\n}",}; +const render=op.inTrigger("render"); +const next=op.outTrigger("next"); +const cgl=op.patch.cgl; + +const shader=new CGL.Shader(cgl,'showtexcoords material'); +shader.setSource(shader.getDefaultVertexShader(),attachments.frontbacksidematerial_frag); +render.onTriggered=doRender; + +function doRender() +{ + cgl.pushShader(shader); + next.trigger(); + cgl.popShader(); +} + + + +}; + +Ops.Gl.Shader.FrontBacksideMaterial.prototype = new CABLES.Op(); +CABLES.OPS["beb92b81-8fe8-4871-b790-efb71bfeefc4"]={f:Ops.Gl.Shader.FrontBacksideMaterial,objName:"Ops.Gl.Shader.FrontBacksideMaterial"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.GetShader +// +// ************************************************************** + +Ops.Gl.Shader.GetShader = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTrigger = op.inTrigger("Update"), + next = op.outTrigger("Next"), + outShader = op.outObject("Shader"); + +inTrigger.onTriggered = () => +{ + outShader.set(op.patch.cgl.getShader()); + next.trigger(); +}; + + +}; + +Ops.Gl.Shader.GetShader.prototype = new CABLES.Op(); +CABLES.OPS["5cca905a-d72b-4a07-9574-d4e4f9a8f300"]={f:Ops.Gl.Shader.GetShader,objName:"Ops.Gl.Shader.GetShader"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.MatCapMaterialNew_v3 +// +// ************************************************************** + +Ops.Gl.Shader.MatCapMaterialNew_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"matcap_frag":"{{MODULES_HEAD}}\n\n#ifdef HAS_TEXTURES\n IN vec2 texCoord;\n#endif\n\nIN vec3 transformedNormal;\nIN vec3 viewSpacePosition;\n\nUNI vec4 inColor;\n\nUNI sampler2D texMatcap;\n\n#ifdef HAS_DIFFUSE_TEXTURE\n UNI sampler2D texDiffuse;\n#endif\n\n#ifdef USE_SPECULAR_TEXTURE\n UNI sampler2D texSpec;\n UNI sampler2D texSpecMatCap;\n#endif\n\n#ifdef HAS_AO_TEXTURE\n UNI sampler2D texAo;\n UNI float aoIntensity;\n#endif\n\n#ifdef HAS_NORMAL_TEXTURE\n IN vec3 vBiTangent;\n IN vec3 vTangent;\n IN mat3 normalMatrix;\n\n UNI sampler2D texNormal;\n UNI float normalMapIntensity;\n#endif\n\n#ifdef HAS_TEXTURE_OPACITY\n UNI sampler2D texOpacity;\n#endif\n\n#ifdef CALC_SSNORMALS\n IN vec3 eye_relative_pos;\n\n // from https://www.enkisoftware.com/devlogpost-20150131-1-Normal_generation_in_the_pixel_shader\n vec3 CalculateScreenSpaceNormals() {\n \tvec3 dFdxPos = dFdx(eye_relative_pos);\n \tvec3 dFdyPos = dFdy(eye_relative_pos);\n \tvec3 screenSpaceNormal = normalize( cross(dFdxPos, dFdyPos));\n return normalize(screenSpaceNormal);\n }\n#endif\n\n// * taken & modified from https://github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/ShaderLib/meshmatcap_frag.glsl.js\nvec2 getMatCapUV(vec3 viewSpacePosition, vec3 normal) {\n vec3 viewDir = normalize(-viewSpacePosition);\n\tvec3 x = normalize(vec3(viewDir.z, 0.0, - viewDir.x));\n\tvec3 y = normalize(cross(viewDir, x));\n\tvec2 uv = vec2(dot(x, normal), dot(y, normal)) * 0.495 + 0.5; // 0.495 to remove artifacts caused by undersized matcap disks\n\treturn uv;\n}\n\nvoid main()\n{\n vec3 viewSpaceNormal = normalize(transformedNormal);\n\n #ifdef HAS_TEXTURES\n vec2 texCoords = texCoord;\n {{MODULE_BEGIN_FRAG}}\n #endif\n\n\n #ifdef CALC_SSNORMALS\n viewSpaceNormal = CalculateScreenSpaceNormals();\n #endif\n\n\n #ifdef HAS_NORMAL_TEXTURE\n vec3 normalFromMap = texture( texNormal, texCoord ).xyz * 2.0 - 1.0;\n normalFromMap = normalize(normalFromMap);\n\n vec3 tangent;\n vec3 binormal;\n\n #ifdef CALC_TANGENT\n vec3 c1 = cross(normalFromMap, vec3(0.0, 0.0, 1.0));\n vec3 c2 = cross(normalFromMap, vec3(0.0, 1.0, 0.0));\n\n tangent = c1;\n tangent = normalize(tangent);\n binormal = cross(viewSpaceNormal, tangent);\n binormal = normalize(binormal);\n #endif\n\n #ifndef CALC_TANGENT\n tangent = normalize(normalMatrix * vTangent);\n vec3 bitangent = normalize(normalMatrix * vBiTangent);\n binormal = normalize(cross(viewSpaceNormal, bitangent));\n #endif\n\n normalFromMap = normalize(\n tangent * normalFromMap.x\n + binormal * normalFromMap.y\n + viewSpaceNormal * normalFromMap.z\n );\n\n vec3 mixedNormal = normalize(viewSpaceNormal + normalFromMap * normalMapIntensity);\n\n viewSpaceNormal = mixedNormal;\n #endif\n\n vec4 col = texture(texMatcap, getMatCapUV(viewSpacePosition, viewSpaceNormal));\n\n #ifdef HAS_DIFFUSE_TEXTURE\n col = col*texture(texDiffuse, texCoords);\n #endif\n\n col.rgb *= inColor.rgb;\n\n\n #ifdef HAS_AO_TEXTURE\n col = col\n * mix(\n vec4(1.0,1.0,1.0,1.0),\n texture(texAo, texCoords),\n aoIntensity\n );\n #endif\n\n #ifdef USE_SPECULAR_TEXTURE\n vec4 spec = texture(texSpecMatCap, getMatCapUV(viewSpacePosition, viewSpaceNormal));\n spec *= texture(texSpec, texCoords);\n col += spec;\n #endif\n\n col.a *= inColor.a;\n\n #ifdef HAS_TEXTURE_OPACITY\n #ifdef TRANSFORMALPHATEXCOORDS\n texCoords=vec2(texCoord.s,1.0-texCoord.t);\n texCoords.y = 1. - texCoords.y;\n #endif\n #ifdef ALPHA_MASK_ALPHA\n col.a*=texture(texOpacity,texCoords).a;\n #endif\n #ifdef ALPHA_MASK_LUMI\n col.a*=dot(vec3(0.2126,0.7152,0.0722), texture(texOpacity,texCoords).rgb);\n #endif\n #ifdef ALPHA_MASK_R\n col.a*=texture(texOpacity,texCoords).r;\n #endif\n #ifdef ALPHA_MASK_G\n col.a*=texture(texOpacity,texCoords).g;\n #endif\n #ifdef ALPHA_MASK_B\n col.a*=texture(texOpacity,texCoords).b;\n #endif\n\n #ifdef DISCARDTRANS\n if(col.a < 0.2) discard;\n #endif\n #endif\n\n {{MODULE_COLOR}}\n\n outColor = col;\n}","matcap_vert":"IN vec3 vPosition;\n\n#ifdef HAS_TEXTURES\n IN vec2 attrTexCoord;\n#endif\n\nIN vec3 attrVertNormal;\nIN float attrVertIndex;\n\n#ifdef HAS_NORMAL_TEXTURE\n IN vec3 attrTangent;\n IN vec3 attrBiTangent;\n OUT vec3 vBiTangent;\n OUT vec3 vTangent;\n#endif\n\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\nUNI vec3 camPos;\n\n#ifdef HAS_TEXTURES\n UNI vec2 texOffset;\n UNI vec2 texRepeat;\n OUT vec2 texCoord;\n#endif\n\nOUT mat3 normalMatrix;\nOUT vec3 viewSpacePosition;\nOUT vec3 transformedNormal;\n\n{{MODULES_HEAD}}\n\n#ifdef CALC_SSNORMALS\n // from https://www.enkisoftware.com/devlogpost-20150131-1-Normal_generation_in_the_pixel_shader\n OUT vec3 eye_relative_pos;\n#endif\n\nmat3 transposeMat3(mat3 m) {\n return mat3(m[0][0], m[1][0], m[2][0],\n m[0][1], m[1][1], m[2][1],\n m[0][2], m[1][2], m[2][2]);\n}\n\n mat3 inverseMat3(mat3 m) {\n float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];\n float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];\n float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];\n\n float b01 = a22 * a11 - a12 * a21;\n float b11 = -a22 * a10 + a12 * a20;\n float b21 = a21 * a10 - a11 * a20;\n\n float det = a00 * b01 + a01 * b11 + a02 * b21;\n\n return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),\n b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),\n b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;\n}\n\nvoid main()\n{\n #ifdef HAS_TEXTURES\n texCoord = texRepeat * vec2(attrTexCoord.x, attrTexCoord.y) + texOffset;\n texCoord.y = 1. - texCoord.y;\n #endif\n\n mat4 mMatrix = modelMatrix;\n mat4 mvMatrix;\n\n #ifdef HAS_NORMAL_TEXTURE\n vec3 tangent = attrTangent;\n vec3 bitangent = attrBiTangent;\n vTangent = attrTangent;\n vBiTangent = attrBiTangent;\n #endif\n\n vec4 pos = vec4(vPosition, 1.);\n vec3 norm = attrVertNormal;\n\n {{MODULE_VERTEX_POSITION}}\n\n mvMatrix = viewMatrix * mMatrix;\n vec3 normal = norm;\n\n normalMatrix = transposeMat3(inverseMat3(mat3(mvMatrix)));\n\n vec3 fragPos = vec3((mvMatrix) * pos);\n viewSpacePosition = normalize(fragPos);\n\n #ifdef CALC_SSNORMALS\n eye_relative_pos = -(vec3(viewMatrix * vec4(camPos, 1.)) - fragPos);\n #endif\n\n transformedNormal = normalize(mat3(normalMatrix) * normal);\n\n gl_Position = projMatrix * mvMatrix * pos;\n\n}",}; +const cgl = op.patch.cgl; + +const + render = op.inTrigger("Render"), + textureMatcap = op.inTexture("MatCap"), + textureDiffuse = op.inTexture("Diffuse"), + textureNormal = op.inTexture("Normal"), + textureSpec = op.inTexture("Specular Mask"), + textureSpecMatCap = op.inTexture("Specular MatCap"), + textureAo = op.inTexture("AO Texture"), + textureOpacity = op.inTexture("Opacity Texture"), + r = op.inValueSlider("r", 1), + g = op.inValueSlider("g", 1), + b = op.inValueSlider("b", 1), + pOpacity = op.inValueSlider("Opacity", 1), + aoIntensity = op.inValueSlider("AO Intensity", 1.0), + normalMapIntensity = op.inFloatSlider("Normal Map Intensity", 1), + repeatX = op.inValue("Repeat X", 1), + repeatY = op.inValue("Repeat Y", 1), + offsetX = op.inValue("Offset X", 0), + offsetY = op.inValue("Offset Y", 0), + ssNormals = op.inValueBool("Screen Space Normals"), + calcTangents = op.inValueBool("Calc normal tangents", true), + texCoordAlpha = op.inValueBool("Opacity TexCoords Transform", false), + discardTransPxl = op.inValueBool("Discard Transparent Pixels"), + + next = op.outTrigger("Next"), + shaderOut = op.outObject("Shader"); + +r.setUiAttribs({ "colorPick": true }); + +const alphaMaskSource = op.inSwitch("Alpha Mask Source", ["Luminance", "R", "G", "B", "A"], "Luminance"); +alphaMaskSource.setUiAttribs({ "greyout": true }); + +op.setPortGroup("Texture Opacity", [alphaMaskSource, texCoordAlpha, discardTransPxl]); +op.setPortGroup("Texture Transforms", [aoIntensity, normalMapIntensity, repeatX, repeatY, offsetX, offsetY, calcTangents, ssNormals]); +op.setPortGroup("Texture Maps", [textureDiffuse, textureNormal, textureSpec, textureSpecMatCap, textureAo, textureOpacity]); +op.setPortGroup("Color", [r, g, b, pOpacity]); + +const shader = new CGL.Shader(cgl, "MatCapMaterialNew3"); +const uniOpacity = new CGL.Uniform(shader, "f", "opacity", pOpacity); + +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); +shader.setSource(attachments.matcap_vert, attachments.matcap_frag); +shaderOut.set(shader); + +const textureMatcapUniform = new CGL.Uniform(shader, "t", "texMatcap"); +let textureDiffuseUniform = null; +let textureNormalUniform = null; +let normalMapIntensityUniform = null; +let textureSpecUniform = null; +let textureSpecMatCapUniform = null; +let textureAoUniform = null; +const offsetUniform = new CGL.Uniform(shader, "2f", "texOffset", offsetX, offsetY); +const repeatUniform = new CGL.Uniform(shader, "2f", "texRepeat", repeatX, repeatY); + +const aoIntensityUniform = new CGL.Uniform(shader, "f", "aoIntensity", aoIntensity); +const colorUniform = new CGL.Uniform(shader, "4f", "inColor", r, g, b, pOpacity); + +calcTangents.onChange = updateDefines; +updateDefines(); + +function updateDefines() +{ + if (calcTangents.get()) shader.define("CALC_TANGENT"); + else shader.removeDefine("CALC_TANGENT"); +} + +ssNormals.onChange = function () +{ + if (ssNormals.get()) + { + if (cgl.glVersion < 2) + { + cgl.gl.getExtension("OES_standard_derivatives"); + shader.enableExtension("GL_OES_standard_derivatives"); + } + + shader.define("CALC_SSNORMALS"); + } + else shader.removeDefine("CALC_SSNORMALS"); +}; + +textureMatcap.onChange = updateMatcap; + +function updateMatcap() +{ + if (!cgl.defaultMatcapTex3) + { + const pixels = new Uint8Array(256 * 4); + for (let x = 0; x < 16; x++) + { + for (let y = 0; y < 16; y++) + { + let c = y * 16; + c *= Math.min(1, (x + y / 3) / 8); + pixels[(x + y * 16) * 4 + 0] = pixels[(x + y * 16) * 4 + 1] = pixels[(x + y * 16) * 4 + 2] = c; + pixels[(x + y * 16) * 4 + 3] = 255; + } + } + + cgl.defaultMatcapTex3 = new CGL.Texture(cgl); + cgl.defaultMatcapTex3.initFromData(pixels, 16, 16, CGL.Texture.FILTER_LINEAR, CGL.Texture.WRAP_REPEAT); + } +} + +textureDiffuse.onChange = function () +{ + if (textureDiffuse.get()) + { + if (textureDiffuseUniform !== null) return; + shader.define("HAS_DIFFUSE_TEXTURE"); + shader.removeUniform("texDiffuse"); + textureDiffuseUniform = new CGL.Uniform(shader, "t", "texDiffuse"); + } + else + { + shader.removeDefine("HAS_DIFFUSE_TEXTURE"); + shader.removeUniform("texDiffuse"); + textureDiffuseUniform = null; + } +}; + +textureNormal.onChange = function () +{ + if (textureNormal.get()) + { + if (textureNormalUniform !== null) return; + shader.define("HAS_NORMAL_TEXTURE"); + shader.removeUniform("texNormal"); + textureNormalUniform = new CGL.Uniform(shader, "t", "texNormal"); + if (!normalMapIntensityUniform) normalMapIntensityUniform = new CGL.Uniform(shader, "f", "normalMapIntensity", normalMapIntensity); + } + else + { + shader.removeDefine("HAS_NORMAL_TEXTURE"); + shader.removeUniform("texNormal"); + textureNormalUniform = null; + } +}; + +textureAo.onChange = function () +{ + if (textureAo.get()) + { + if (textureAoUniform !== null) return; + shader.define("HAS_AO_TEXTURE"); + shader.removeUniform("texAo"); + textureAoUniform = new CGL.Uniform(shader, "t", "texAo"); + } + else + { + shader.removeDefine("HAS_AO_TEXTURE"); + shader.removeUniform("texAo"); + textureAoUniform = null; + } +}; + +textureSpec.onChange = textureSpecMatCap.onChange = function () +{ + if (textureSpec.get() && textureSpecMatCap.get()) + { + if (textureSpecUniform !== null) return; + shader.define("USE_SPECULAR_TEXTURE"); + shader.removeUniform("texSpec"); + shader.removeUniform("texSpecMatCap"); + textureSpecUniform = new CGL.Uniform(shader, "t", "texSpec"); + textureSpecMatCapUniform = new CGL.Uniform(shader, "t", "texSpecMatCap"); + } + else + { + shader.removeDefine("USE_SPECULAR_TEXTURE"); + shader.removeUniform("texSpec"); + shader.removeUniform("texSpecMatCap"); + textureSpecUniform = null; + textureSpecMatCapUniform = null; + } +}; + +// TEX OPACITY + +function updateAlphaMaskMethod() +{ + if (alphaMaskSource.get() == "Alpha Channel") shader.define("ALPHA_MASK_ALPHA"); + else shader.removeDefine("ALPHA_MASK_ALPHA"); + + if (alphaMaskSource.get() == "Luminance") shader.define("ALPHA_MASK_LUMI"); + else shader.removeDefine("ALPHA_MASK_LUMI"); + + if (alphaMaskSource.get() == "R") shader.define("ALPHA_MASK_R"); + else shader.removeDefine("ALPHA_MASK_R"); + + if (alphaMaskSource.get() == "G") shader.define("ALPHA_MASK_G"); + else shader.removeDefine("ALPHA_MASK_G"); + + if (alphaMaskSource.get() == "B") shader.define("ALPHA_MASK_B"); + else shader.removeDefine("ALPHA_MASK_B"); +} +alphaMaskSource.onChange = updateAlphaMaskMethod; +textureOpacity.onChange = updateOpacity; + +let textureOpacityUniform = null; + +function updateOpacity() +{ + if (textureOpacity.get()) + { + if (textureOpacityUniform !== null) return; + shader.removeUniform("texOpacity"); + shader.define("HAS_TEXTURE_OPACITY"); + if (!textureOpacityUniform) textureOpacityUniform = new CGL.Uniform(shader, "t", "texOpacity"); + + alphaMaskSource.setUiAttribs({ "greyout": false }); + discardTransPxl.setUiAttribs({ "greyout": false }); + texCoordAlpha.setUiAttribs({ "greyout": false }); + } + else + { + shader.removeUniform("texOpacity"); + shader.removeDefine("HAS_TEXTURE_OPACITY"); + textureOpacityUniform = null; + + alphaMaskSource.setUiAttribs({ "greyout": true }); + discardTransPxl.setUiAttribs({ "greyout": true }); + texCoordAlpha.setUiAttribs({ "greyout": true }); + } + updateAlphaMaskMethod(); +} + +discardTransPxl.onChange = function () +{ + if (discardTransPxl.get()) shader.define("DISCARDTRANS"); + else shader.removeDefine("DISCARDTRANS"); +}; + +texCoordAlpha.onChange = function () +{ + if (texCoordAlpha.get()) shader.define("TRANSFORMALPHATEXCOORDS"); + else shader.removeDefine("TRANSFORMALPHATEXCOORDS"); +}; + +function checkUiErrors() +{ + if (textureSpec.get() && !textureSpecMatCap.get()) + { + op.setUiError("specNoMatCapSpec", "You connected a specular texture but have not connected a specular matcap texture. You need to connect both texture inputs for the specular input to work.", 1); + op.setUiError("noSpecMatCapSpec", null); + } + else if (!textureSpec.get() && textureSpecMatCap.get()) + { + op.setUiError("noSpecMatCapSpec", "You connected a specular matcap texture but have not connected a specular texture. You need to connect both texture inputs for the specular input to work.", 1); + op.setUiError("specNoMatCapSpec", null); + } + else if (textureSpec.get() && textureSpecMatCap.get()) + { + op.setUiError("specNoMatCapSpec", null); + op.setUiError("noSpecMatCapSpec", null); + } + else + { + op.setUiError("specNoMatCapSpec", null); + op.setUiError("noSpecMatCapSpec", null); + } +} + +render.onTriggered = function () +{ + checkUiErrors(); + + if (!cgl.defaultMatcapTex3) updateMatcap(); + shader.popTextures(); + + const tex = textureMatcap.get() || cgl.defaultMatcapTex3; + shader.pushTexture(textureMatcapUniform, tex.tex); + + if (textureDiffuse.get() && textureDiffuseUniform) shader.pushTexture(textureDiffuseUniform, textureDiffuse.get().tex); + if (textureNormal.get() && textureNormalUniform) shader.pushTexture(textureNormalUniform, textureNormal.get().tex); + if (textureSpec.get() && textureSpecUniform) shader.pushTexture(textureSpecUniform, textureSpec.get().tex); + if (textureSpecMatCap.get() && textureSpecMatCapUniform) shader.pushTexture(textureSpecMatCapUniform, textureSpecMatCap.get().tex); + if (textureAo.get() && textureAoUniform) shader.pushTexture(textureAoUniform, textureAo.get().tex); + if (textureOpacity.get() && textureOpacityUniform) shader.pushTexture(textureOpacityUniform, textureOpacity.get().tex); + + cgl.pushShader(shader); + next.trigger(); + cgl.popShader(); +}; + + +}; + +Ops.Gl.Shader.MatCapMaterialNew_v3.prototype = new CABLES.Op(); +CABLES.OPS["c1dd6e76-61b4-471a-b8d1-f550a5a9a4f4"]={f:Ops.Gl.Shader.MatCapMaterialNew_v3,objName:"Ops.Gl.Shader.MatCapMaterialNew_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.Picker +// +// ************************************************************** + +Ops.Gl.Shader.Picker = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +op.render = op.inTrigger("render"); + +const useMouseCoords = op.inBool("Use Mouse Coordinates", true); + +op.x = op.inFloat("x"); +op.y = op.inFloat("y"); +const inEnabled = op.inBool("enabled"); +inEnabled.set(true); + +op.trigger = op.outTrigger("trigger"); +const somethingPicked = op.outBool("Something Picked"); + +const cursor = op.inDropDown("cursor", ["", "pointer", "auto", "default", "crosshair", "move", "n-resize", "ne-resize", "e-resize", "se-resize", "s-resize", "sw-resize", "w-resize", "nw-resize", "text", "wait", "help"]); + +// inValueSelect +cursor.set("default"); + +const pixelRGB = new Uint8Array(4); +let fb = null; +const cgl = op.patch.cgl; +let lastReadPixel = 0; +let canceledTouch = false; +if (cgl.glVersion == 1) fb = new CGL.Framebuffer(cgl, 4, 4); +else +{ + fb = new CGL.Framebuffer2(cgl, 4, 4, { "multisampling": false }); +} + +const tex = op.outTexture("pick texture"); +tex.set(fb.getTextureColor()); +useMouseCoords.onChange = updateListeners; +updateListeners(); + +function renderPickingPass() +{ + cgl.frameStore.renderOffscreen = true; + cgl.frameStore.pickingpass = true; + cgl.frameStore.pickingpassNum = 0; + op.trigger.trigger(); + cgl.frameStore.pickingpass = false; + cgl.frameStore.renderOffscreen = false; +} + +function mouseMove(e) +{ + if (e && e.hasOwnProperty("offsetX") >= 0) + { + op.x.set(e.offsetX * (window.devicePixelRatio || 1)); + op.y.set(e.offsetY * (window.devicePixelRatio || 1)); + } +} + +function updateListeners() +{ + cgl.canvas.removeEventListener("mouseleave", mouseleave); + cgl.canvas.removeEventListener("mousemove", mouseMove); + cgl.canvas.removeEventListener("touchmove", ontouchmove); + cgl.canvas.removeEventListener("touchstart", ontouchstart); + cgl.canvas.removeEventListener("touchend", ontouchend); + cgl.canvas.removeEventListener("touchcancel", ontouchend); + + if (useMouseCoords.get()) + { + cgl.canvas.addEventListener("mouseleave", mouseleave); + cgl.canvas.addEventListener("mousemove", mouseMove); + cgl.canvas.addEventListener("touchmove", ontouchmove); + cgl.canvas.addEventListener("touchstart", ontouchstart); + cgl.canvas.addEventListener("touchend", ontouchend); + cgl.canvas.addEventListener("touchcancel", ontouchend); + } +} + +function fixTouchEvent(touchEvent) +{ + if (touchEvent) + { + touchEvent.offsetX = touchEvent.pageX - touchEvent.target.offsetLeft; + touchEvent.offsetY = touchEvent.pageY - touchEvent.target.offsetTop; + + if (!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) + { + touchEvent.offsetX *= (window.devicePixelRatio || 1); + touchEvent.offsetY *= (window.devicePixelRatio || 1); + } + + return touchEvent; + } +} + +function ontouchstart(event) +{ + canceledTouch = false; + if (event.touches && event.touches.length > 0) + { + ontouchmove(event); + } +} + +function mouseleave(event) +{ + op.x.set(-1000); + op.y.set(-1000); +} + +function ontouchend(event) +{ + canceledTouch = true; + op.x.set(-1000); + op.y.set(-1000); +} + +function ontouchmove(event) +{ + if (event.touches && event.touches.length > 0) + { + mouseMove(fixTouchEvent(event.touches[0])); + } +} + +const doRender = function () +{ + if (cursor.get() != cgl.canvas.style.cursor) + { + cgl.canvas.style.cursor = cursor.get(); + } + + if (inEnabled.get() && op.x.get() >= 0 && !canceledTouch) + { + if (CABLES.now() - lastReadPixel >= 50) + { + const minimizeFB = 2; + cgl.resetViewPort(); + + const vpW = Math.floor(cgl.canvasWidth / minimizeFB); + const vpH = Math.floor(cgl.canvasHeight / minimizeFB); + + if (vpW != fb.getWidth() || vpH != fb.getHeight()) + { + tex.set(null); + fb.setSize(vpW, vpH); + tex.set(fb.getTextureColor()); + } + + cgl.pushModelMatrix(); + fb.renderStart(); + // cgl.gl.clear(cgl.gl.DEPTH_BUFFER_BIT | cgl.gl.COLOR_BUFFER_BIT); + + renderPickingPass(); + + let x = Math.floor(op.x.get() / minimizeFB); + let y = Math.floor(vpH - op.y.get() / minimizeFB); + if (x < 0)x = 0; + if (y < 0)y = 0; + + cgl.gl.readPixels(x, y, 1, 1, cgl.gl.RGBA, cgl.gl.UNSIGNED_BYTE, pixelRGB); + lastReadPixel = CABLES.now(); + + fb.renderEnd(); + cgl.popModelMatrix(); + } + + cgl.frameStore.pickedColor = pixelRGB[0] + pixelRGB[2]; + + if (cgl.frameStore.pickedColor)somethingPicked.set(true); + else somethingPicked.set(false); + + cgl.frameStore.pickingpassNum = 0; + op.trigger.trigger(); + } + else + { + cgl.frameStore.pickedColor = -1000; + op.trigger.trigger(); + somethingPicked.set(false); + } +}; + +function preview() +{ + render(); + tex.get().preview(); +} + +// tex.onPreviewChanged = function () +// { +// if (tex.showPreview) op.render.onTriggered = doRender; +// else op.render.onTriggered = doRender; +// }; + +op.render.onTriggered = doRender; + + +}; + +Ops.Gl.Shader.Picker.prototype = new CABLES.Op(); +CABLES.OPS["09122fbf-3b6b-4a05-ac76-fca031b505b9"]={f:Ops.Gl.Shader.Picker,objName:"Ops.Gl.Shader.Picker"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.PickingMaterial +// +// ************************************************************** + +Ops.Gl.Shader.PickingMaterial = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"pick_frag":"UNI float r;\n\nvoid main()\n{\n outColor= vec4(r,1.0,r,1.0);\n}","pick_vert":"IN vec3 vPosition;\nUNI mat4 projMatrix;\n// UNI mat4 mvMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\n{{MODULES_HEAD}}\n\nvoid main()\n{\n vec4 pos = vec4( vPosition, 1. );\n mat4 mMatrix=modelMatrix;\n\n #ifdef BILLBOARD\n mat4 mvMatrix=viewMatrix*mMatrix;\n\n vec3 position=vPosition;\n gl_Position = projMatrix * mvMatrix * vec4((\n position.x * vec3(\n mvMatrix[0][0],\n mvMatrix[1][0],\n mvMatrix[2][0] ) +\n position.y * vec3(\n mvMatrix[0][1],\n mvMatrix[1][1],\n mvMatrix[2][1]) ), 1.0);\n #endif\n\n\n {{MODULE_VERTEX_POSITION}}\n\n\n #ifndef BILLBOARD\n\n mat4 mvMatrix=viewMatrix*mMatrix;\n gl_Position = projMatrix * mvMatrix * vec4(vPosition, 1.0);\n #endif\n}",}; +const cgl = op.patch.cgl; + +const render = op.inTrigger("render"); +const next = op.outTrigger("trigger"); + +const isPicked = op.outBool("is picked"); + +const pickedTrigger = op.outTrigger("On Picked"); + +const doBillboard = op.inBool("billboard", false); // op.addInPort(new CABLES.Port(op, "billboard", CABLES.OP_PORT_TYPE_VALUE, { "display": "bool" })); +doBillboard.set(false); + +doBillboard.onChange = function () +{ + if (doBillboard.get()) shader.define("BILLBOARD"); + else shader.removeDefine("BILLBOARD"); +}; + +const cursor = op.inDropDown("cursor", ["pointer", "auto", "default", "crosshair", "move", "n-resize", "ne-resize", "e-resize", "se-resize", "s-resize", "sw-resize", "w-resize", "nw-resize", "text", "wait", "help"]); + +cursor.set("pointer"); + +function doRender() +{ + cgl.frameStore.pickingpassNum += 2; + const currentPickingColor = cgl.frameStore.pickingpassNum; + + if (cgl.frameStore.pickingpass) + { + // isPicked.set(false); + + pickColorUniformR.setValue(currentPickingColor / 511); + cgl.pushShader(shader); + next.trigger(); + cgl.popShader(); + } + else + { + isPicked.set(cgl.frameStore.pickedColor == currentPickingColor); + + if (cgl.frameStore.pickedColor == currentPickingColor) + { + if (cursor.get().length > 0 && cgl.canvas.style.cursor != cursor.get()) + { + cgl.canvas.style.cursor = cursor.get(); + } + pickedTrigger.trigger(); + } + else + { + } + + next.trigger(); + } +} + +const srcVert = attachments.pick_vert; + +const srcFrag = attachments.pick_frag; + +const shader = new CGL.Shader(cgl, "PickingMaterial"); +shader.offScreenPass = true; +shader.setSource(srcVert, srcFrag); + +const pickColorUniformR = new CGL.Uniform(shader, "f", "r", 0); + +render.onTriggered = doRender; +doRender(); + + +}; + +Ops.Gl.Shader.PickingMaterial.prototype = new CABLES.Op(); +CABLES.OPS["2b58daad-4dde-4edb-af22-03ac55ab06ab"]={f:Ops.Gl.Shader.PickingMaterial,objName:"Ops.Gl.Shader.PickingMaterial"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.PointMaterial_v4 +// +// ************************************************************** + +Ops.Gl.Shader.PointMaterial_v4 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"pointmat_frag":"\n{{MODULES_HEAD}}\n\nUNI vec4 color;\n// IN vec2 pointCoord;\nIN float ps;\n\n#ifdef HAS_TEXTURE_DIFFUSE\n UNI sampler2D diffTex;\n#endif\n#ifdef HAS_TEXTURE_MASK\n UNI sampler2D texMask;\n#endif\n#ifdef HAS_TEXTURE_COLORIZE\n IN vec4 colorize;\n#endif\n#ifdef HAS_TEXTURE_OPACITY\n IN float opacity;\n#endif\n#ifdef VERTEX_COLORS\n IN vec4 vertexColor;\n#endif\n\nvoid main()\n{\n #ifdef FLIP_TEX\n vec2 pointCoord=vec2(gl_PointCoord.x,(1.0-gl_PointCoord.y));\n #endif\n #ifndef FLIP_TEX\n vec2 pointCoord=gl_PointCoord;\n #endif\n {{MODULE_BEGIN_FRAG}}\n\n if(ps<1.0)discard;\n\n vec4 col=color;\n\n #ifdef HAS_TEXTURE_MASK\n float mask;\n #ifdef TEXTURE_MASK_R\n mask=texture(texMask,pointCoord).r;\n #endif\n #ifdef TEXTURE_MASK_A\n mask=texture(texMask,pointCoord).a;\n #endif\n #ifdef TEXTURE_MASK_LUMI\n \tvec3 lumcoeff = vec3(0.299,0.587,0.114);\n \tmask = dot(texture(texMask,pointCoord).rgb, lumcoeff);\n #endif\n\n #endif\n\n #ifdef HAS_TEXTURE_DIFFUSE\n col=texture(diffTex,pointCoord);\n #ifdef COLORIZE_TEXTURE\n col.rgb*=color.rgb;\n #endif\n #endif\n col.a*=color.a;\n\n {{MODULE_COLOR}}\n\n #ifdef MAKE_ROUND\n\n #ifndef MAKE_ROUNDAA\n if ((gl_PointCoord.x-0.5)*(gl_PointCoord.x-0.5) + (gl_PointCoord.y-0.5)*(gl_PointCoord.y-0.5) > 0.25) discard; //col.a=0.0;\n #endif\n\n #ifdef MAKE_ROUNDAA\n float circ=(gl_PointCoord.x-0.5)*(gl_PointCoord.x-0.5) + (gl_PointCoord.y-0.5)*(gl_PointCoord.y-0.5);\n\n float a=smoothstep(0.25,0.25-fwidth(gl_PointCoord.x),circ);\n if(a==0.0)discard;\n col.a=a*color.a;\n #endif\n #endif\n\n #ifdef HAS_TEXTURE_COLORIZE\n col*=colorize;\n #endif\n\n #ifdef TEXTURE_COLORIZE_MUL\n col*=color;\n #endif\n\n #ifdef HAS_TEXTURE_MASK\n col.a*=mask;\n #endif\n\n #ifdef HAS_TEXTURE_OPACITY\n col.a*=opacity;\n #endif\n\n #ifdef VERTEX_COLORS\n col.rgb = vertexColor.rgb;\n col.a *= vertexColor.a;\n #endif\n\n if (col.a <= 0.0) discard;\n\n #ifdef HAS_TEXTURE_COLORIZE\n col*=colorize;\n #endif\n\n outColor = col;\n}\n","pointmat_vert":"{{MODULES_HEAD}}\nIN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\nIN vec3 attrTangent;\nIN vec3 attrBiTangent;\n\n#ifdef VERTEX_COLORS\n IN vec4 attrVertColor;\n OUT vec4 vertexColor;\n#endif\n\nOUT vec3 norm;\nOUT float ps;\n\nOUT vec2 texCoord;\n\n\n#ifdef HAS_TEXTURES\n#endif\n\n#ifdef HAS_TEXTURE_COLORIZE\n UNI sampler2D texColorize;\n OUT vec4 colorize;\n#endif\n#ifdef HAS_TEXTURE_OPACITY\n UNI sampler2D texOpacity;\n OUT float opacity;\n#endif\n\n#ifdef HAS_TEXTURE_POINTSIZE\n UNI sampler2D texPointSize;\n UNI float texPointSizeMul;\n#endif\n\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\n\nUNI float pointSize;\nUNI vec3 camPos;\n\nUNI float canvasWidth;\nUNI float canvasHeight;\nUNI float camDistMul;\nUNI float randomSize;\n\nIN float attrVertIndex;\n\n\n\nfloat rand(float n){return fract(sin(n) * 5711.5711123);}\n\n#define POINTMATERIAL\n\nvoid main()\n{\n norm=attrVertNormal;\n #ifdef PIXELSIZE\n float psMul=1.0;\n #endif\n\n #ifndef PIXELSIZE\n float psMul=sqrt(canvasWidth/canvasHeight)+0.00000000001;\n #endif\n\n // float sizeMultiply=1.0;\n\n vec3 tangent=attrTangent;\n vec3 bitangent=attrBiTangent;\n\n\n #ifdef VERTEX_COLORS\n vertexColor=attrVertColor;\n #endif\n\n // #ifdef HAS_TEXTURES\n texCoord=attrTexCoord;\n // #endif\n\n #ifdef HAS_TEXTURE_OPACITY\n // opacity=texture(texOpacity,vec2(rand(attrVertIndex+texCoord.x*texCoord.y+texCoord.y+texCoord.x),rand(texCoord.y*texCoord.x-texCoord.x-texCoord.y-attrVertIndex))).r;\n opacity=texture(texOpacity,texCoord).r;\n #endif\n\n\n #ifdef HAS_TEXTURE_COLORIZE\n #ifdef RANDOM_COLORIZE\n colorize=texture(texColorize,vec2(rand(attrVertIndex+texCoord.x*texCoord.y+texCoord.y+texCoord.x),rand(texCoord.y*texCoord.x-texCoord.x-texCoord.y-attrVertIndex)));\n #endif\n #ifndef RANDOM_COLORIZE\n colorize=texture(texColorize,texCoord);\n #endif\n #endif\n\n\n\n\n\n mat4 mMatrix=modelMatrix;\n vec4 pos = vec4( vPosition, 1. );\n\n gl_PointSize=0.0;\n\n {{MODULE_VERTEX_POSITION}}\n\n vec4 model=mMatrix * pos;\n\n psMul+=rand(texCoord.x*texCoord.y+texCoord.y*3.0+texCoord.x*2.0+attrVertIndex)*randomSize;\n // psMul*=sizeMultiply;\n\n float addPointSize=0.0;\n #ifdef HAS_TEXTURE_POINTSIZE\n\n #ifdef POINTSIZE_CHAN_R\n addPointSize=texture(texPointSize,texCoord).r;\n #endif\n #ifdef POINTSIZE_CHAN_G\n addPointSize=texture(texPointSize,texCoord).g;\n #endif\n #ifdef POINTSIZE_CHAN_B\n addPointSize=texture(texPointSize,texCoord).b;\n #endif\n\n\n #ifdef DOTSIZEREMAPABS\n // addPointSize=(( (texture(texPointSize,texCoord).r) * texPointSizeMul)-0.5)*2.0;\n\n addPointSize=1.0-(distance(addPointSize,0.5)*2.0);\n // addPointSize=abs(1.0-(distance(addPointSize,0.5)*2.0));\n addPointSize=addPointSize*addPointSize*addPointSize*2.0;\n\n // addPointSize=(( (texture(texPointSize,texCoord).r) * texPointSizeMul)-0.5)*2.0;\n #endif\n\n addPointSize*=texPointSizeMul;\n\n #endif\n\n ps=0.0;\n #ifndef SCALE_BY_DISTANCE\n ps = (pointSize+addPointSize) * psMul;\n #endif\n #ifdef SCALE_BY_DISTANCE\n float cameraDist = distance(model.xyz, camPos);\n ps = ( (pointSize+addPointSize) / cameraDist) * psMul;\n #endif\n\n gl_PointSize += ps;\n\n\n gl_Position = projMatrix * viewMatrix * model;\n}\n",}; +const cgl = op.patch.cgl; + +const + render = op.inTrigger("render"), + pointSize = op.inValueFloat("PointSize", 3), + inPixelSize = op.inBool("Size in Pixels", false), + randomSize = op.inValue("Random Size", 0), + makeRound = op.inValueBool("Round", true), + makeRoundAA = op.inValueBool("Round Antialias", false), + doScale = op.inValueBool("Scale by Distance", false), + r = op.inValueSlider("r", Math.random()), + g = op.inValueSlider("g", Math.random()), + b = op.inValueSlider("b", Math.random()), + a = op.inValueSlider("a", 1), + vertCols = op.inBool("Vertex Colors", false), + texture = op.inTexture("texture"), + textureMulColor = op.inBool("Colorize Texture"), + textureMask = op.inTexture("Texture Mask"), + texMaskChan = op.inSwitch("Mask Channel", ["R", "A", "Luminance"], "R"), + textureColorize = op.inTexture("Texture Colorize"), + colorizeRandom = op.inValueBool("Colorize Randomize", true), + textureOpacity = op.inTexture("Texture Opacity"), + texturePointSize = op.inTexture("Texture Point Size"), + texturePointSizeChannel = op.inSwitch("Point Size Channel", ["R", "G", "B"], "R"), + texturePointSizeMul = op.inFloat("Texture Point Size Mul", 1), + texturePointSizeMap = op.inSwitch("Map Size 0", ["Black", "Grey"], "Black"), + flipTex = op.inValueBool("Flip Texture", false), + + trigger = op.outTrigger("trigger"), + shaderOut = op.outObject("shader", null, "shader"); + +op.setPortGroup("Texture", [texture, textureMulColor, textureMask, texMaskChan, textureColorize, textureOpacity, colorizeRandom]); +op.setPortGroup("Color", [r, g, b, a, vertCols]); +op.setPortGroup("Size", [pointSize, randomSize, makeRound, makeRoundAA, doScale, inPixelSize, texturePointSize, texturePointSizeMul, texturePointSizeChannel, texturePointSizeMap]); +r.setUiAttribs({ "colorPick": true }); + +const shader = new CGL.Shader(cgl, "PointMaterial"); +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); +shader.define("MAKE_ROUND"); + +const + uniPointSize = new CGL.Uniform(shader, "f", "pointSize", pointSize), + texturePointSizeMulUniform = new CGL.Uniform(shader, "f", "texPointSizeMul", texturePointSizeMul), + uniRandomSize = new CGL.Uniform(shader, "f", "randomSize", randomSize), + uniColor = new CGL.Uniform(shader, "4f", "color", r, g, b, a), + uniWidth = new CGL.Uniform(shader, "f", "canvasWidth", cgl.canvasWidth), + uniHeight = new CGL.Uniform(shader, "f", "canvasHeight", cgl.canvasHeight), + textureUniform = new CGL.Uniform(shader, "t", "diffTex"), + textureColorizeUniform = new CGL.Uniform(shader, "t", "texColorize"), + textureOpacityUniform = new CGL.Uniform(shader, "t", "texOpacity"), + textureColoPointSize = new CGL.Uniform(shader, "t", "texPointSize"), + texturePointSizeUniform = new CGL.Uniform(shader, "t", "texPointSize"), + textureMaskUniform = new CGL.Uniform(shader, "t", "texMask"); + +shader.setSource(attachments.pointmat_vert, attachments.pointmat_frag); +shader.glPrimitive = cgl.gl.POINTS; +shaderOut.set(shader); +shaderOut.ignoreValueSerialize = true; + +render.onTriggered = doRender; +doScale.onChange = + makeRound.onChange = + makeRoundAA.onChange = + texture.onChange = + textureColorize.onChange = + textureMask.onChange = + colorizeRandom.onChange = + flipTex.onChange = + texMaskChan.onChange = + inPixelSize.onChange = + textureOpacity.onChange = + texturePointSize.onChange = + texturePointSizeMap.onChange = + texturePointSizeChannel.onChange = + textureMulColor.onChange = + vertCols.onChange = updateDefines; + +updateUi(); + +op.preRender = function () +{ + if (shader)shader.bind(); + doRender(); +}; + +function doRender() +{ + uniWidth.setValue(cgl.canvasWidth); + uniHeight.setValue(cgl.canvasHeight); + + cgl.pushShader(shader); + shader.popTextures(); + if (texture.get() && !texture.get().deleted) shader.pushTexture(textureUniform, texture.get()); + if (textureMask.get()) shader.pushTexture(textureMaskUniform, textureMask.get()); + if (textureColorize.get()) shader.pushTexture(textureColorizeUniform, textureColorize.get()); + if (textureOpacity.get()) shader.pushTexture(textureOpacityUniform, textureOpacity.get()); + if (texturePointSize.get()) shader.pushTexture(texturePointSizeUniform, texturePointSize.get()); + + trigger.trigger(); + + cgl.popShader(); +} + +function updateUi() +{ + texMaskChan.setUiAttribs({ "greyout": !textureMask.isLinked() }); + + texturePointSizeChannel.setUiAttribs({ "greyout": !texturePointSize.isLinked() }); + texturePointSizeMul.setUiAttribs({ "greyout": !texturePointSize.isLinked() }); + texturePointSizeMap.setUiAttribs({ "greyout": !texturePointSize.isLinked() }); +} + +function updateDefines() +{ + shader.toggleDefine("SCALE_BY_DISTANCE", doScale.get()); + shader.toggleDefine("MAKE_ROUND", makeRound.get()); + shader.toggleDefine("MAKE_ROUNDAA", makeRoundAA.get()); + + shader.toggleDefine("VERTEX_COLORS", vertCols.get()); + shader.toggleDefine("RANDOM_COLORIZE", colorizeRandom.get()); + shader.toggleDefine("HAS_TEXTURE_DIFFUSE", texture.get()); + shader.toggleDefine("HAS_TEXTURE_MASK", textureMask.get()); + shader.toggleDefine("HAS_TEXTURE_COLORIZE", textureColorize.get()); + shader.toggleDefine("HAS_TEXTURE_OPACITY", textureOpacity.get()); + shader.toggleDefine("HAS_TEXTURE_POINTSIZE", texturePointSize.get()); + + shader.toggleDefine("TEXTURE_COLORIZE_MUL", textureMulColor.get()); + + shader.toggleDefine("FLIP_TEX", flipTex.get()); + shader.toggleDefine("TEXTURE_MASK_R", texMaskChan.get() == "R"); + shader.toggleDefine("TEXTURE_MASK_A", texMaskChan.get() == "A"); + shader.toggleDefine("TEXTURE_MASK_LUMI", texMaskChan.get() == "Luminance"); + shader.toggleDefine("PIXELSIZE", inPixelSize.get()); + + shader.toggleDefine("POINTSIZE_CHAN_R", texturePointSizeChannel.get() == "R"); + shader.toggleDefine("POINTSIZE_CHAN_G", texturePointSizeChannel.get() == "G"); + shader.toggleDefine("POINTSIZE_CHAN_B", texturePointSizeChannel.get() == "B"); + + shader.toggleDefine("DOTSIZEREMAPABS", texturePointSizeMap.get() == "Grey"); + updateUi(); +} + + +}; + +Ops.Gl.Shader.PointMaterial_v4.prototype = new CABLES.Op(); +CABLES.OPS["a7cb5d1c-cd4a-4c28-bb13-7bb9bda187ed"]={f:Ops.Gl.Shader.PointMaterial_v4,objName:"Ops.Gl.Shader.PointMaterial_v4"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.PositionAsColorMaterial +// +// ************************************************************** + +Ops.Gl.Shader.PositionAsColorMaterial = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"pos_frag":"IN vec3 vert;\n\nvoid main()\n{\n vec4 col=vec4(vert,1.0);\n\n\n outColor= col;\n}","pos_vert":"IN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal,attrTangent,attrBiTangent;\nOUT mat4 mMatrix;\nOUT vec3 vert;\nOUT mat4 mvMatrix;\nUNI mat4 projMatrix;\n\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\n\n{{MODULES_HEAD}}\n\nvoid main()\n{\n\n vec4 pos=vec4(vPosition,1.0);\n mMatrix=modelMatrix;\n\n\n\n {{MODULE_VERTEX_POSITION}}\n\n mat4 mvMatrix=viewMatrix*mMatrix;\n\n\n vert=(mMatrix*pos).xyz;\n\n\n gl_Position = projMatrix * mvMatrix * pos;\n}",}; +const render = op.inTrigger("render"); +const trigger = op.outTrigger("trigger"); +const cgl = op.patch.cgl; + +function doRender() +{ + cgl.pushShader(shader); + trigger.trigger(); + cgl.popShader(); +} + +const shader = new CGL.Shader(cgl, "showtexcoords material"); + +shader.setSource(attachments.pos_vert, attachments.pos_frag); + +render.onTriggered = doRender; +doRender(); + + +}; + +Ops.Gl.Shader.PositionAsColorMaterial.prototype = new CABLES.Op(); +CABLES.OPS["a654bbb7-bbde-4178-9fef-3209d0c352a4"]={f:Ops.Gl.Shader.PositionAsColorMaterial,objName:"Ops.Gl.Shader.PositionAsColorMaterial"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.SetShader +// +// ************************************************************** + +Ops.Gl.Shader.SetShader = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const render = op.inTrigger("render"); +const shader = op.inObject("shader", null, "shader"); +const trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +shader.ignoreValueSerialize = true; +render.onTriggered = doRender; + +function doRender() +{ + if (shader.get()) + { + cgl.pushShader(shader.get()); + if (shader.get().bindTextures) shader.get().bindTextures(); + trigger.trigger(); + cgl.popShader(); + } + else + { + trigger.trigger(); + } +} + + +}; + +Ops.Gl.Shader.SetShader.prototype = new CABLES.Op(); +CABLES.OPS["11d24181-1f1b-4131-bba0-3df410385a66"]={f:Ops.Gl.Shader.SetShader,objName:"Ops.Gl.Shader.SetShader"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.SetUniformFloat_v2 +// +// ************************************************************** + +Ops.Gl.Shader.SetUniformFloat_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// should be called setuniformfloat ? + +const + inRender = op.inTrigger("Render"), + inSelect = op.inValueSelect("Uniform"), + inX = op.inValue("X", 1), + inY = op.inValue("Y", 1), + inZ = op.inValue("Z", 1), + inW = op.inValue("W", 1), + next = op.outTrigger("Next"), + outType = op.outString("Type"); + +let shader = null; +const cgl = op.patch.cgl; +let doSetupUniform = true; +let uniform = null; +let shaderLastCompile = -1; +let unis = []; + +inRender.onTriggered = function () +{ + if (cgl.getShader() && (shader != cgl.getShader() || shader.lastCompile != shaderLastCompile)) + { + shader = cgl.getShader(); + setupShader(); + doSetupUniform = true; + } + + if (doSetupUniform) setupUniform(); + + if (uniform) + { + outType.set(uniform.getType()); + const oldValue = uniform.getValue(); + + uniform.setValue([inX.get(), inY.get(), inZ.get(), inW.get()]); + + next.trigger(); + uniform.setValue(oldValue); + } + else + { + next.trigger(); + } +}; + +inSelect.onChange = function () +{ + doSetupUniform = true; +}; + +function setupUniform() +{ + if (shader) + { + uniform = shader.getUniform((inSelect.get() || "").split(" ")[0]); + + if (uniform) + { + inY.setUiAttribs({ "greyout": uniform.getType() == "f" }); + inZ.setUiAttribs({ "greyout": uniform.getType() == "f" || uniform.getType() == "2f" }); + inW.setUiAttribs({ "greyout": uniform.getType() == "f" || uniform.getType() == "2f" || uniform.getType() == "3f" }); + } + + if (!uniform) op.setUiError("nouni", "uniform unknown", 1);// op.uiAttr({ "error": "uniform unknown. maybe shader changed" }); + else op.setUiError("nouni", null); + + doSetupUniform = false; + } +} + +function setupShader() +{ + unis = shader.getUniforms(); + + shaderLastCompile = shader.lastCompile; + const names = ["..."]; + + for (let i = 0; i < unis.length; i++) + { + if (unis[i].getType() == "f" || unis[i].getType() == "2f" || unis[i].getType() == "3f" || unis[i].getType() == "4f") + names.push(unis[i].getName() + " (" + unis[i].getType() + ")"); + } + + inSelect.setUiAttribs({ "values": names }); +} + + +}; + +Ops.Gl.Shader.SetUniformFloat_v2.prototype = new CABLES.Op(); +CABLES.OPS["9e6328da-457d-4d80-a881-dcab25a0e0f8"]={f:Ops.Gl.Shader.SetUniformFloat_v2,objName:"Ops.Gl.Shader.SetUniformFloat_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.SetUniformTexture +// +// ************************************************************** + +Ops.Gl.Shader.SetUniformTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inRender = op.inTrigger("Render"), + inSelect = op.inValueSelect("Uniform"), + // inValue = op.inValue("Value"), + inValue = op.inTexture("Texture"), + next = op.outTrigger("Next"), + outType = op.outString("Type"); + +let shader = null; +const cgl = op.patch.cgl; +let doSetupUniform = true; +let uniform = null; +let shaderLastCompile = -1; +let unis = []; +let old = null; + +inRender.onTriggered = function () +{ + if (cgl.getShader() && (shader != cgl.getShader() || shader.lastCompile != shaderLastCompile)) + { + shader = cgl.getShader(); + setupShader(); + doSetupUniform = true; + } + + if (doSetupUniform) setupUniform(); + + if (uniform) + { + // outType.set(uniform.getType()); + // const oldValue = uniform.getValue(); + + // shader.pushTexture(uniform, inValue.get()); + + old = shader.setUniformTexture(uniform, inValue.get()); + } + CGL.MESH.lastShader = null; + CGL.MESH.lastMesh = null; + + next.trigger(); + + if (uniform && old) shader.setUniformTexture(uniform, old); + CGL.MESH.lastShader = null; + CGL.MESH.lastMesh = null; +}; + +inSelect.onChange = function () +{ + doSetupUniform = true; +}; + +function setupUniform() +{ + if (shader) + { + uniform = shader.getUniform((inSelect.get() || "").split(" ")[0]); + + if (!uniform) op.setUiError("nouni", "uniform unknown", 1);// op.uiAttr({ "error": "uniform unknown. maybe shader changed" }); + else op.setUiError("nouni", null); + + doSetupUniform = false; + } +} + +function setupShader() +{ + unis = shader.getUniforms(); + + shaderLastCompile = shader.lastCompile; + const names = ["..."]; + + for (let i = 0; i < unis.length; i++) + if (unis[i].getType() == "t") + names.push(unis[i].getName() + " (" + unis[i].getType() + ")"); + + inSelect.setUiAttribs({ "values": names }); +} + + +}; + +Ops.Gl.Shader.SetUniformTexture.prototype = new CABLES.Op(); +CABLES.OPS["e43be3e0-b75b-4881-95c3-2c6ee81bff8c"]={f:Ops.Gl.Shader.SetUniformTexture,objName:"Ops.Gl.Shader.SetUniformTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.Shader2Texture +// +// ************************************************************** + +Ops.Gl.Shader.Shader2Texture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Render"), + inShader = op.inObject("Shader", null, "shader"), + inVPSize = op.inValueBool("Use Viewport Size", true), + inWidth = op.inValueInt("Width", 512), + inHeight = op.inValueInt("Height", 512), + tfilter = op.inValueSelect("filter", ["nearest", "linear", "mipmap"]), + twrap = op.inValueSelect("wrap", ["clamp to edge", "repeat", "mirrored repeat"], "clamp to edge"), + inFloatingPoint = op.inValueBool("Floating Point", false), + inNumTex = op.inSwitch("Num Textures", ["1", "4"], "1"), + next = op.outTrigger("Next"), + outTex = op.outTexture("Texture"), + outTex2 = op.outTexture("Texture 2"), + outTex3 = op.outTexture("Texture 3"), + outTex4 = op.outTexture("Texture 4"); + +op.setPortGroup("Texture Size", [inVPSize, inWidth, inHeight]); +op.setPortGroup("Texture settings", [tfilter, twrap, inFloatingPoint]); + +let numTextures = 1; +const cgl = op.patch.cgl; +const prevViewPort = [0, 0, 0, 0]; +const effect = null; +const drawBuffArr = []; +let lastShader = null; +let shader = null; + +inWidth.onChange = + inHeight.onChange = + inFloatingPoint.onChange = + tfilter.onChange = + inNumTex.onChange = + twrap.onChange = initFbLater; + +inVPSize.onChange = updateUI; + +const showingError = false; + +let fb = null; +const tex = null; +let needInit = true; + +const mesh = CGL.MESHES.getSimpleRect(cgl, "shader2texture rect"); + +op.toWorkPortsNeedToBeLinked(inShader); + +tfilter.set("nearest"); + +updateUI(); + +function warning() +{ + if (tfilter.get() == "mipmap" && inFloatingPoint.get()) + { + op.setUiError("warning", "HDR and mipmap filtering at the same time is not possible"); + } + else + { + op.setUiError("warning", null); + } +} + +function updateUI() +{ + inWidth.setUiAttribs({ "greyout": inVPSize.get() }); + inHeight.setUiAttribs({ "greyout": inVPSize.get() }); + + inWidth.set(cgl.getViewPort()[2]); + inHeight.set(cgl.getViewPort()[3]); +} + +function initFbLater() +{ + needInit = true; + warning(); +} + +function resetShader() +{ + if (shader) shader.dispose(); + lastShader = null; + shader = null; +} + +function initFb() +{ + needInit = false; + if (fb)fb.delete(); + + const oldLen = drawBuffArr.length; + numTextures = parseInt(inNumTex.get()); + drawBuffArr.length = 0; + for (let i = 0; i < numTextures; i++)drawBuffArr[i] = true; + + if (oldLen != drawBuffArr.length) + { + resetShader(); + } + + fb = null; + + let w = inWidth.get(); + let h = inHeight.get(); + + if (inVPSize.get()) + { + w = cgl.getViewPort()[2]; + h = cgl.getViewPort()[3]; + } + + let filter = CGL.Texture.FILTER_NEAREST; + if (tfilter.get() == "linear") filter = CGL.Texture.FILTER_LINEAR; + else if (tfilter.get() == "mipmap") filter = CGL.Texture.FILTER_MIPMAP; + + let selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + if (twrap.get() == "repeat") selectedWrap = CGL.Texture.WRAP_REPEAT; + if (twrap.get() == "mirrored repeat") selectedWrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + + if (cgl.glVersion >= 2) + { + fb = new CGL.Framebuffer2(cgl, w, h, + { + "isFloatingPointTexture": inFloatingPoint.get(), + "multisampling": false, + "numRenderBuffers": numTextures, + "wrap": selectedWrap, + "filter": filter, + "depth": true, + "multisamplingSamples": 0, + "clear": true + }); + } + else + { + fb = new CGL.Framebuffer(cgl, inWidth.get(), inHeight.get(), + { + "isFloatingPointTexture": inFloatingPoint.get(), + "filter": filter, + "wrap": selectedWrap + }); + } +} + +exec.onTriggered = function () +{ + const vp = cgl.getViewPort(); + + if (!fb || needInit)initFb(); + if (inVPSize.get() && fb && (vp[2] != fb.getTextureColor().width || vp[3] != fb.getTextureColor().height)) initFb(); + + if (!inShader.get() || !inShader.get().setDrawBuffers) return; + + if (inShader.get() != lastShader) + { + lastShader = inShader.get(); + shader = inShader.get().copy(); + + shader.setDrawBuffers(drawBuffArr); + } + + if (!shader) + { + outTex.set(null); + return; + } + + prevViewPort[0] = vp[0]; + prevViewPort[1] = vp[1]; + prevViewPort[2] = vp[2]; + prevViewPort[3] = vp[3]; + + fb.renderStart(cgl); + + cgl.pushPMatrix(); + mat4.identity(cgl.pMatrix); + + cgl.pushViewMatrix(); + mat4.identity(cgl.vMatrix); + + cgl.pushModelMatrix(); + mat4.identity(cgl.mMatrix); + + cgl.pushShader(inShader.get()); + if (shader.bindTextures) shader.bindTextures(); + + cgl.pushBlend(false); + + mesh.render(inShader.get()); + + cgl.popBlend(); + + cgl.popPMatrix(); + cgl.popModelMatrix(); + cgl.popViewMatrix(); + fb.renderEnd(cgl); + + if (numTextures >= 2) + { + outTex.set(fb.getTextureColorNum(0)); + outTex2.set(fb.getTextureColorNum(1)); + outTex3.set(fb.getTextureColorNum(2)); + outTex4.set(fb.getTextureColorNum(3)); + } + else outTex.set(fb.getTextureColor()); + + cgl.popShader(); + + cgl.gl.viewport(prevViewPort[0], prevViewPort[1], prevViewPort[2], prevViewPort[3]); + + next.trigger(); +}; + + +}; + +Ops.Gl.Shader.Shader2Texture.prototype = new CABLES.Op(); +CABLES.OPS["a3debb76-7d84-4548-9e7b-24891423dcce"]={f:Ops.Gl.Shader.Shader2Texture,objName:"Ops.Gl.Shader.Shader2Texture"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.ShaderDefine +// +// ************************************************************** + +Ops.Gl.Shader.ShaderDefine = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inShader=op.inObject("Shader"), + inDefineName=op.inString("Name"), + inDefineValue=op.inString("Value"), + inActive=op.inValueBool("Active") + ; + + +inShader.onChange= + inDefineName.onChange= + inDefineValue.onChange= + inActive.onChange=update; +update(); + +function update() +{ + var shader=inShader.get(); + if(!shader) + { + return; + } + + if(!inActive.get()) shader.removeDefine(inDefineName.get()); + else shader.define(inDefineName.get(),inDefineValue.get()); + +} + +}; + +Ops.Gl.Shader.ShaderDefine.prototype = new CABLES.Op(); +CABLES.OPS["1f870586-1ae4-4b7e-9dd7-24c300c989ba"]={f:Ops.Gl.Shader.ShaderDefine,objName:"Ops.Gl.Shader.ShaderDefine"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.ShaderInfo +// +// ************************************************************** + +Ops.Gl.Shader.ShaderInfo = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Exec"), + showFrag = op.inTriggerButton("Show Fragment"), + showVert = op.inTriggerButton("Show Vertex"), + showModules = op.inTriggerButton("Show Modules"), + showUniforms = op.inTriggerButton("Show Uniforms"), + showState = op.inTriggerButton("State Info"), + next = op.outTrigger("Next"), + + outSrcFrag = op.outString("Source Frag"), + outSrcVert = op.outString("Source Vert"), + + outName = op.outString("Name"), + outId = op.outString("Id"), + outNeedsBarycentric = op.outBoolNum("needsBarycentric"), + outNumUniforms = op.outNumber("Num Uniforms"), + outNumAttributes = op.outNumber("Num Attributes"), + outAttributeNames = op.outArray("Arributes Names"), + outDefines = op.outArray("Num Defines"); + +const cgl = op.patch.cgl; +let shader = null; + +function showCodeModal(title, code, type) +{ + if (!CABLES.UI || !CABLES.UI.ModalDialog) + { + op.log(title, code); + } + + let html = ""; + html += "

Code

"; + html += "" + title + " "; + html += "

"; + html += "

"; + + code = code || ""; + code = code.replace(/\/g, ">"); // for > + + html += "
" + code + "
"; + + new CABLES.UI.ModalDialog({ + "title": title, + "html": html + }); +} + +showFrag.onTriggered = function () +{ + if (CABLES.UI && shader) showCodeModal("fragment shader", shader.finalShaderFrag, "GLSL"); +}; + +showVert.onTriggered = function () +{ + if (CABLES.UI && shader) showCodeModal("vertex shader", shader.finalShaderVert, "GLSL"); +}; + +let doStateDump = false; +let doUniformDump = false; + +showState.onTriggered = function () +{ + if (!CABLES.UI || !shader) return; + doStateDump = true; +}; + +showUniforms.onTriggered = function () +{ + if (!CABLES.UI || !shader) return; + doUniformDump = true; +}; + +exec.onTriggered = function () +{ + if (cgl.frameStore.shadowPass) return; + shader = cgl.getShader(); + next.trigger(); + + shader.bind(); + + if (!shader.getProgram()) op.setUiError("prognull", "Shader is not compiled"); + else op.setUiError("prognull", null); + + if (!shader) op.setUiError("noshader", "No Shader.."); + else op.setUiError("noshader", null); + + if (shader && shader.getProgram()) + { + const activeUniforms = cgl.gl.getProgramParameter(shader.getProgram(), cgl.gl.ACTIVE_UNIFORMS); + outNumUniforms.set(activeUniforms); + outNumAttributes.set(cgl.gl.getProgramParameter(shader.getProgram(), cgl.gl.ACTIVE_ATTRIBUTES)); + + let i = 0; + const attribNames = []; + for (i = 0; i < cgl.gl.getProgramParameter(shader.getProgram(), cgl.gl.ACTIVE_ATTRIBUTES); i++) + { + const name = cgl.gl.getActiveAttrib(shader.getProgram(), i).name; + attribNames.push(name); + } + outAttributeNames.set(attribNames); + outDefines.set(shader.getDefines()); + outName.set(shader.getName()); + outNeedsBarycentric.set(shader.wireframe); + outId.set(shader.id); + + op.setUiError("prognull", null); + } + else + { + outNumUniforms.set(0); + outNumAttributes.set(0); + outDefines.set(0); + outAttributeNames.set(null); + } + + if (doUniformDump) + { + const json = []; + for (let i = 0; i < shader._uniforms.length; i++) + { + json.push({ + "validLoc": shader._uniforms[i]._isValidLoc(), + "name": shader._uniforms[i]._name, + "type": shader._uniforms[i]._type, + "value": shader._uniforms[i]._value, + "structName": shader._uniforms[i]._structName, + "structUniformName": shader._uniforms[i]._structUniformName + }); + } + showCodeModal("shader uniforms", JSON.stringify(json, false, 2), "json"); + + doUniformDump = false; + } + + if (doStateDump) + { + doStateDump = false; + stateDump(); + } + + outSrcFrag.set(shader.finalShaderFrag); + outSrcVert.set(shader.finalShaderVert); +}; + +function stateDump() +{ + let txt = ""; + txt += ""; + + txt += "defines (" + outDefines.get().length + ")\n\n"; + + for (let i = 0; i < outDefines.get().length; i++) + { + txt += "- "; + txt += outDefines.get()[i][0]; + if (outDefines.get()[i][1]) + { + txt += ": "; + txt += outDefines.get()[i][1]; + } + txt += "\n"; + } + + txt += "\n\n"; + txt += "texturestack (" + shader._textureStackUni.length + ")\n\n"; + + for (let i = 0; i < shader._textureStackUni.length; i++) + { + txt += "- "; + txt += shader._textureStackUni[i]._name; + txt += "(" + shader._textureStackUni[i].shaderType + ")\n"; + if (shader._textureStackTexCgl[i]) txt += JSON.stringify(shader._textureStackTexCgl[i].getInfo()); + txt += "\n"; + } + + txt += "\n\n"; + txt += "uniforms: (" + shader._uniforms.length + ")\n\n"; + + for (let i = 0; i < shader._uniforms.length; i++) + { + txt += "- "; + txt += shader._uniforms[i]._name; + txt += ": "; + txt += shader._uniforms[i].getValue(); + + if (shader._uniforms[i].comment) + { + txt += " // "; + txt += shader._uniforms[i].comment; + } + txt += "\n"; + } + + showCodeModal("state info", txt); +} + +showModules.onTriggered = function () +{ + if (!shader) return; + const mods = shader.getCurrentModules(); + + showCodeModal("vertex shader", JSON.stringify(mods, false, 4), "json"); +}; + +// + + +}; + +Ops.Gl.Shader.ShaderInfo.prototype = new CABLES.Op(); +CABLES.OPS["7afaa77e-a976-4e65-8eb1-a6302b91c0d3"]={f:Ops.Gl.Shader.ShaderInfo,objName:"Ops.Gl.Shader.ShaderInfo"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.SwitchShader +// +// ************************************************************** + +Ops.Gl.Shader.SwitchShader = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + value = op.inValueBool("value"), + shader = op.inObject("shader true"), + shader2 = op.inObject("shader false"), + trigger = op.outTrigger("trigger"), + shaderOut = op.outObject("shaderOut"); + +const cgl = op.patch.cgl; + +shaderOut.ignoreValueSerialize = true; +shader.ignoreValueSerialize = true; +shader2.ignoreValueSerialize = true; + +render.onTriggered = doRender; +doRender(); + +function doRender() +{ + if (value.get()) + { + if (shader.get()) + { + cgl.pushShader(shader.get()); + shaderOut.set(shader.get()); + shader.get().bindTextures(); + trigger.trigger(); + cgl.popShader(); + } + } + else + { + if (shader2.get()) + { + cgl.pushShader(shader2.get()); + shaderOut.set(shader2.get()); + shader2.get().bindTextures(); + trigger.trigger(); + cgl.popShader(); + } + } +} + + +}; + +Ops.Gl.Shader.SwitchShader.prototype = new CABLES.Op(); +CABLES.OPS["34ae93a7-ceb4-4e02-8d6f-a38f5e6c732b"]={f:Ops.Gl.Shader.SwitchShader,objName:"Ops.Gl.Shader.SwitchShader"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.VertexColorMaterial +// +// ************************************************************** + +Ops.Gl.Shader.VertexColorMaterial = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"vertexcolor_frag":"{{MODULES_HEAD}}\n\nIN vec4 vertColor;\nUNI float opacity;\n\nvoid main()\n{\n{{MODULE_BEGIN_FRAG}}\n vec4 col=vertColor;\n{{MODULE_COLOR}}\n\n col.a=opacity;\n outColor= col;\n}","vertexcolor_vert":"{{MODULES_HEAD}}\n\nIN vec3 vPosition;\nIN vec3 attrVertColor;\nOUT vec4 vertColor;\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\nIN vec3 attrVertNormal;\n\nvoid main()\n{\n mat4 mMatrix=modelMatrix;\n vertColor.rgb=attrVertColor;\n vec3 norm=attrVertNormal;\n vec4 pos = vec4( vPosition, 1. );\n\n {{MODULE_VERTEX_POSITION}}\n\n mat4 mvMatrix=viewMatrix*mMatrix;\n\n gl_Position = projMatrix * mvMatrix * pos;\n}",}; +const cgl = op.patch.cgl, + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + opacity = op.inValueFloat("opacity", 1); + +const shader = new CGL.Shader(cgl, "vertex color material"); +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); +shader.uniOpacity = new CGL.Uniform(shader, "f", "opacity", opacity.get()); +shader.setSource(attachments.vertexcolor_vert, attachments.vertexcolor_frag); + +render.onTriggered = doRender; + +opacity.onChange = function () +{ + shader.uniOpacity.setValue(opacity.get()); +}; + +function doRender() +{ + cgl.pushShader(shader); + trigger.trigger(); + cgl.popShader(); +} + + +}; + +Ops.Gl.Shader.VertexColorMaterial.prototype = new CABLES.Op(); +CABLES.OPS["a01d592b-0e5e-48f3-a9fd-54b87ffd623b"]={f:Ops.Gl.Shader.VertexColorMaterial,objName:"Ops.Gl.Shader.VertexColorMaterial"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.VertexNumberMaterial +// +// ************************************************************** + +Ops.Gl.Shader.VertexNumberMaterial = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const cgl = op.patch.cgl; + +const render = op.inTrigger("render"); +const trigger = op.outTrigger("trigger"); + +const srcVert = "" + .endl() + "IN float attrVertIndex;" + .endl() + "UNI mat4 projMatrix;" + .endl() + "UNI mat4 mvMatrix;" + .endl() + "IN vec3 vPosition;" + .endl() + "OUT float num;" + + .endl() + "void main()" + .endl() + "{" + .endl() + " num=attrVertIndex;" + .endl() + " gl_Position = projMatrix * mvMatrix * vec4(vPosition, 1.0);" + .endl() + "}"; + +const srcFrag = "" + .endl() + "IN float num;" + .endl() + "UNI float numVertices;" + + .endl() + "void main()" + .endl() + "{" + + .endl() + "float c = num/numVertices/3.0;" + .endl() + "c = mod(c,0.1)*10.0;" + + .endl() + " outColor= vec4(c,c,c,1.0);" + + .endl() + "}"; + +function doRender() +{ + cgl.pushShader(shader); + trigger.trigger(); + cgl.popShader(); +} + +const shader = new CGL.Shader(cgl, "vertexnumber material"); +shader.setSource(srcVert, srcFrag); + +render.onTriggered = doRender; + +doRender(); + + +}; + +Ops.Gl.Shader.VertexNumberMaterial.prototype = new CABLES.Op(); +CABLES.OPS["732ff263-1aeb-4f39-969f-c781d7776cc8"]={f:Ops.Gl.Shader.VertexNumberMaterial,objName:"Ops.Gl.Shader.VertexNumberMaterial"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.WireframeMaterial +// +// ************************************************************** + +Ops.Gl.Shader.WireframeMaterial = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"wireframe_frag":"{{MODULES_HEAD}}\n\nIN vec3 barycentric;\nUNI float width;\nUNI float opacity;\nUNI float r,g,b;\nUNI float fr,fg,fb;\nIN vec3 norm;\n\nfloat edgeFactor()\n{\n vec3 d = fwidth(barycentric);\n vec3 a3 = smoothstep(vec3(0.0), d*width*4.0, barycentric);\n return min(min(a3.x, a3.y), a3.z);\n}\n\nvoid main()\n{\n {{MODULE_BEGIN_FRAG}}\n\n vec4 col;\n\n #ifdef WIREFRAME_FILL\n float v=opacity*(1.0-edgeFactor())*0.95;\n vec3 wire = vec3(fr, fg, fb);\n col.rgb = vec3(r, g, b);\n col.rgb = mix(wire,col.rgb,v);\n col.a = opacity;\n #endif\n\n #ifndef WIREFRAME_FILL\n col = vec4(r,g,b, opacity*(1.0-edgeFactor())*0.95);\n #endif\n\n {{MODULE_COLOR}}\n\n// col=vec4(1.0);\n outColor=col;\n}","wireframe_vert":"{{MODULES_HEAD}}\n\nIN vec3 vPosition;\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\nOUT vec3 barycentric;\nIN vec2 attrTexCoord;\nOUT vec2 texCoord;\n\nIN vec3 attrBarycentric;\nIN vec3 attrVertNormal;\nOUT vec3 norm;\n\nvoid main()\n{\n norm=attrVertNormal;\n texCoord=attrTexCoord;\n barycentric=attrBarycentric;\n mat4 mMatrix=modelMatrix;\n vec4 pos=vec4(vPosition, 1.0);\n\n {{MODULE_VERTEX_POSITION}}\n\n gl_Position = projMatrix * viewMatrix * mMatrix * pos;\n}\n",}; +let cgl = op.patch.cgl; + +let render = op.inTrigger("render"); +let trigger = op.outTrigger("trigger"); + +let enableDepth = op.inValueBool("enable depth testing", true); + +let fill = op.inValueBool("fill", true); + +function setDefines() +{ + if (shader) + if (fill.get()) shader.define("WIREFRAME_FILL"); + else shader.removeDefine("WIREFRAME_FILL"); +} + +fill.onChange = function () +{ + setDefines(); +}; + +let w = op.inValueSlider("width", 0.25); +w.onChange = function () { uniformWidth.setValue(w.get()); }; + +let opacity = op.inValueSlider("opacity", 1); +opacity.onChange = function () { uniformOpacity.setValue(opacity.get()); }; + +if (cgl.glVersion == 1 && !cgl.gl.getExtension("OES_standard_derivatives")) +{ + op.uiAttr({ "error": "no oes standart derivatives!" }); +} +else +{ + op.uiAttr({ "error": null }); +} + +let doRender = function () +{ + // if(true!==enableDepth.get()) cgl.gl.disable(cgl.gl.DEPTH_TEST); + // else cgl.gl.enable(cgl.gl.DEPTH_TEST); + cgl.pushDepthTest(enableDepth.get()); + + cgl.pushShader(shader); + trigger.trigger(); + cgl.popShader(); + + // if(true!==enableDepth.get()) cgl.gl.enable(cgl.gl.DEPTH_TEST); + cgl.popDepthTest(); +}; + +const shader = new CGL.Shader(cgl, "Wireframe Material"); + +if (cgl.glVersion > 1)shader.glslVersion = 300; +const uniformWidth = new CGL.Uniform(shader, "f", "width", w.get()); +const uniformOpacity = new CGL.Uniform(shader, "f", "opacity", opacity.get()); + +if (cgl.glVersion == 1)shader.enableExtension("OES_standard_derivatives"); + +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); +shader.setSource(attachments.wireframe_vert || "", attachments.wireframe_frag || ""); +shader.wireframe = true; +setDefines(); + +// diffuse color +let r = op.inValueSlider("diffuse r", Math.random()); +let g = op.inValueSlider("diffuse g", Math.random()); +let b = op.inValueSlider("diffuse b", Math.random()); + +r.setUiAttribs({ "colorPick": true }); + +g.uniform = new CGL.Uniform(shader, "f", "g", g); +r.uniform = new CGL.Uniform(shader, "f", "r", r); +b.uniform = new CGL.Uniform(shader, "f", "b", b); + +{ + // diffuse color + + let fr = op.inValueSlider("Fill R", Math.random()); + fr.setUiAttribs({ "colorPick": true }); + fr.uniform = new CGL.Uniform(shader, "f", "fr", fr); + + let fg = op.inValueSlider("Fill G", Math.random()); + fg.uniform = new CGL.Uniform(shader, "f", "fg", fg); + + let fb = op.inValueSlider("Fill B", Math.random()); + fb.uniform = new CGL.Uniform(shader, "f", "fb", fb); +} + +render.onTriggered = doRender; + +doRender(); + + +}; + +Ops.Gl.Shader.WireframeMaterial.prototype = new CABLES.Op(); +CABLES.OPS["e5d64a7d-b161-4f85-907e-e10a34691733"]={f:Ops.Gl.Shader.WireframeMaterial,objName:"Ops.Gl.Shader.WireframeMaterial"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.AreaDiscardPixel_v2 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.AreaDiscardPixel_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"areadiscard_frag":"\n\nfloat MOD_de=0.0;\n\n#ifdef MOD_AREA_SPHERE\n MOD_de=distance(vec3(MOD_x,MOD_y,MOD_z)/MOD_sizeAxis,MOD_areaPos.xyz/MOD_sizeAxis);\n#endif\n\n#ifdef MOD_AREA_BOX\n if( abs(MOD_y/MOD_sizeAxis.y-MOD_areaPos.y/(MOD_sizeAxis.y*MOD_size))>0.5 ||\n abs(MOD_x/MOD_sizeAxis.x-MOD_areaPos.x/(MOD_sizeAxis.x*MOD_size))>0.5 ||\n abs(MOD_z/MOD_sizeAxis.z-MOD_areaPos.z/(MOD_sizeAxis.z*MOD_size))>0.5 ) MOD_de=1.0;\n#endif\n\n#ifdef MOD_AREA_AXIS_X\n MOD_de=abs(MOD_x-MOD_areaPos.x);\n#endif\n#ifdef MOD_AREA_AXIS_XY\n MOD_de=abs(MOD_x-MOD_areaPos.x+MOD_areaPos.y);\n#endif\n#ifdef MOD_AREA_AXIS_XZ\n MOD_de=abs(MOD_x-MOD_areaPos.x+MOD_areaPos.z);\n#endif\n#ifdef MOD_AREA_AXIS_YZ\n MOD_de=abs(MOD_y-MOD_areaPos.y+MOD_areaPos.z);\n#endif\n#ifdef MOD_AREA_AXIS_Y\n MOD_de=abs(MOD_y-MOD_areaPos.y);\n#endif\n#ifdef MOD_AREA_AXIS_Z\n MOD_de=abs(MOD_z-MOD_areaPos.z);\n#endif\n\n#ifdef MOD_AREA_AXIS_X_INFINITE\n MOD_de=MOD_x-MOD_areaPos.x;\n#endif\n#ifdef MOD_AREA_AXIS_Y_INFINITE\n MOD_de=MOD_y-MOD_areaPos.y;\n#endif\n#ifdef MOD_AREA_AXIS_Z_INFINITE\n MOD_de=MOD_z-MOD_areaPos.z;\n#endif\n\n#ifdef MOD_AREA_REPEAT\n MOD_de=mod(MOD_de,MOD_size+MOD_repeat);\n#endif\n\nMOD_de=MOD_de/MOD_size;\n\n#ifdef MOD_AREA_INVERT\n MOD_de=1.0-MOD_de;\n#endif\n\n\nif(MOD_de<=0.5) discard;\n\n","areadiscard_head_frag":"IN vec4 MOD_areaPos;\n",}; +const + render = op.inTrigger("render"), + inInvert = op.inValueBool("Invert"), + inArea = op.inValueSelect("Area", ["Sphere", "Box", "Axis X", "Axis Y", "Axis Z", "Axis XY", "Axis XZ", "Axis YZ", "Axis X Infinite", "Axis Y Infinite", "Axis Z Infinite"], "Sphere"), + inSize = op.inValue("Size", 1), + inSizeX = op.inValueFloat("Size X", 1), + inSizeY = op.inValueFloat("Size Y", 1), + inSizeZ = op.inValueFloat("Size Z", 1), + inRepeat = op.inValueBool("Repeat"), + inRepeatDist = op.inValueFloat("Repeat Distance", 0.0), + x = op.inValue("x"), + y = op.inValue("y"), + z = op.inValue("z"), + inWorldSpace = op.inValueBool("WorldSpace", true), + next = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; + +op.setPortGroup("Size", [inSize, inSizeY, inSizeX, inSizeZ]); +op.setPortGroup("Position", [x, y, z, inWorldSpace]); + + +const srcHeadVert = "" + .endl() + "OUT vec4 MOD_areaPos;" + .endl(); + +const srcBodyVert = "" + .endl() + "#ifndef MOD_WORLDSPACE" + .endl() + " MOD_areaPos=pos;" + .endl() + "#endif" + .endl() + "#ifdef MOD_WORLDSPACE" + .endl() + " MOD_areaPos=mMatrix*pos;" + .endl() + "#endif" + .endl(); + +inWorldSpace.onChange = +inInvert.onChange = +inRepeat.onChange = +inArea.onChange = updateDefines; + +const mod = new CGL.ShaderModifier(cgl, op.name); + +mod.addModule({ + "priority": 2, + "title": op.objName, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": srcHeadVert, + "srcBodyVert": srcBodyVert +}); +mod.addModule({ + "title": op.objName, + "name": "MODULE_COLOR", + "srcHeadFrag": attachments.areadiscard_head_frag || "", + "srcBodyFrag": attachments.areadiscard_frag || "" +}); + +mod.addUniformFrag("f", "MOD_size", inSize); +mod.addUniformFrag("f", "MOD_x", x); +mod.addUniformFrag("f", "MOD_y", y); +mod.addUniformFrag("f", "MOD_z", z); +mod.addUniformFrag("3f", "MOD_sizeAxis", inSizeX, inSizeY, inSizeZ); +mod.addUniformFrag("f", "MOD_repeat", inRepeatDist); + +updateDefines(); + +function updateDefines() +{ + mod.toggleDefine("MOD_WORLDSPACE", inWorldSpace.get()); + mod.toggleDefine("MOD_AREA_INVERT", inInvert.get()); + mod.toggleDefine("MOD_AREA_REPEAT", inRepeat.get()); + mod.toggleDefine("MOD_AREA_BOX", inArea.get() == "Box"); + mod.toggleDefine("MOD_AREA_SPHERE", inArea.get() == "Sphere"); + mod.toggleDefine("MOD_AREA_AXIS_X", inArea.get() == "Axis X"); + mod.toggleDefine("MOD_AREA_AXIS_Y", inArea.get() == "Axis Y"); + mod.toggleDefine("MOD_AREA_AXIS_Z", inArea.get() == "Axis Z"); + mod.toggleDefine("MOD_AREA_AXIS_XY", inArea.get() == "Axis XY"); + mod.toggleDefine("MOD_AREA_AXIS_XZ", inArea.get() == "Axis XZ"); + mod.toggleDefine("MOD_AREA_AXIS_YZ", inArea.get() == "Axis YZ"); + mod.toggleDefine("MOD_AREA_AXIS_X_INFINITE", inArea.get() == "Axis X Infinite"); + mod.toggleDefine("MOD_AREA_AXIS_Y_INFINITE", inArea.get() == "Axis Y Infinite"); + mod.toggleDefine("MOD_AREA_AXIS_Z_INFINITE", inArea.get() == "Axis Z Infinite"); +} + +render.onTriggered = function () +{ + if (op.isCurrentUiOp()) + gui.setTransformGizmo( + { + "posX": x, + "posY": y, + "posZ": z + }); + + if (cgl.shouldDrawHelpers(op)) CABLES.GL_MARKER.drawSphere(op, inSize.get()); + + mod.bind(); + next.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.ShaderEffects.AreaDiscardPixel_v2.prototype = new CABLES.Op(); +CABLES.OPS["0d39986b-c594-44d5-815d-c46a280fe16c"]={f:Ops.Gl.ShaderEffects.AreaDiscardPixel_v2,objName:"Ops.Gl.ShaderEffects.AreaDiscardPixel_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.AreaRotate_v2 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.AreaRotate_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"area_rotate_vert":"\n\nvec4 MOD_scaler(vec4 pos,mat4 modelMatrix)\n{\n vec3 forcePos=vec3(MOD_x,MOD_y,MOD_z);\n vec3 vecToOrigin=(modelMatrix*pos).xyz-forcePos;\n float dist=abs(length(vecToOrigin));\n float distAlpha = (MOD_size - dist) ;\n\n if(MOD_smooth) distAlpha=smoothstep(0.0,MOD_size,distAlpha);\n\n // pos.xyz*=(1.0+(distAlpha*MOD_strength));\n\n mat3 rotation = mat3(\n vec3( cos(MOD_strength*distAlpha), sin(MOD_strength*distAlpha), 0.0),\n vec3(-sin(MOD_strength*distAlpha), cos(MOD_strength*distAlpha), 0.0),\n vec3( 0.0, 0.0, 1.0)\n );\n pos =vec4(rotation * pos.xyz, 1.0);\n\n\n return pos;\n}\n",}; +const + render=op.inTrigger("render"), + inSize=op.inValue("Size",1), + inStrength=op.inValue("Strength",1), + inSmooth=op.inValueBool("Smooth",true), + x=op.inValue("x"), + y=op.inValue("y"), + z=op.inValue("z"), + next=op.outTrigger("trigger"); + +const cgl=op.patch.cgl; +const srcBodyVert='' + .endl()+'pos=MOD_scaler(pos,mMatrix);' + .endl(); + +const mod = new CGL.ShaderModifier(cgl, op.name); + +mod.addModule({ + "priority": 2, + "title": "vert"+op.name, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": attachments.area_rotate_vert, + "srcBodyVert": srcBodyVert +}); + +mod.addUniform("f", "MOD_x", x); +mod.addUniform("f", "MOD_y", y); +mod.addUniform("f", "MOD_z", z); + +mod.addUniform("f", "MOD_size", inSize); +mod.addUniform("f", "MOD_strength", inStrength); +mod.addUniform("b", "MOD_smooth", inSmooth); + + +render.onTriggered=function() +{ + if(!cgl.getShader()) + { + next.trigger(); + return; + } + + if(op.isCurrentUiOp()) gui.setTransformGizmo( {posX:x,posY:y,posZ:z }); + + mod.bind(); + next.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.ShaderEffects.AreaRotate_v2.prototype = new CABLES.Op(); +CABLES.OPS["ebfd3f0c-7a58-44d3-aba0-72d91fafd7ae"]={f:Ops.Gl.ShaderEffects.AreaRotate_v2,objName:"Ops.Gl.ShaderEffects.AreaRotate_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.AreaScaler_v3 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.AreaScaler_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"areascale_vert":"\nvec4 MOD_scaler(vec4 pos,vec4 worldPos,vec3 normal,mat4 mMatrix)\n{\n vec3 forcePos = vec3(MOD_x,MOD_y,MOD_z);\n\n #ifdef MOD_OBJECT_POS\n worldPos=mMatrix*vec4(0.0,0.0,0.0,1.0);\n #endif\n\n vec3 vecToOrigin = worldPos.xyz-forcePos;\n\n float dist = abs(length(vecToOrigin)) ;\n\n\n float distAlpha = (MOD_size - dist) ;\n\n if(MOD_smooth) distAlpha = smoothstep(0.0,MOD_size,distAlpha);\n\n float m = distAlpha * MOD_strength;\n\n #ifdef MOD_TO_ZERO\n m+=1.0;\n #endif\n\n if(m<0.0)m=0.0;\n\n #ifdef MOD_CLAMP_SIZE\n pos.xyz*=clamp(m,MOD_clampMin,MOD_clampMax);\n #else\n pos.xyz*=m ;\n #endif\n\n return pos;\n}\n",}; +const + exec = op.inTrigger("render"), + inSize = op.inValue("Area size", 1), + inSrc = op.inSwitch("Source", ["Vertex position", "Object position"], "Vertex position"), + inStrength = op.inValue("Strength", 1), + inSmooth = op.inValueBool("Smoothstep", false), + inToZero = op.inValueBool("Min Size Original", false), + inClampBool = op.inBool("Clamp size", false), + inClampMin = op.inFloat("Clamp min", 0), + inClampMax = op.inFloat("Clamp max", 1.0), + x = op.inValue("Pos X"), + y = op.inValue("Pos Y"), + z = op.inValue("Pos Z"), + next = op.outTrigger("Next"); + +const cgl = op.patch.cgl; +let needsUpdateToZero = true; +const mscaleUni = null; +let shader = null; + +op.setPortGroup("Position", [x, y, z]); +op.setPortGroup("Influence", [inSrc, inStrength, inSmooth, inToZero]); + +const srcBodyVert = "" + .endl() + "pos=MOD_scaler(pos,mMatrix*pos,attrVertNormal,mMatrix);" // modelMatrix* + .endl(); + +let moduleVert = null; + +// op.onDelete = exec.onLinkChanged = removeModule; +inToZero.onChange = inSrc.onChange = inClampBool.onChange = updateToZero; + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "priority": 2, + "title": "vert_" + op.name, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": attachments.areascale_vert, + "srcBodyVert": srcBodyVert +}); + + +mod.addUniform("f", "MOD_size", inSize); +mod.addUniform("f", "MOD_strength", inStrength); +mod.addUniform("b", "MOD_smooth", inSmooth); + +mod.addUniform("f", "MOD_clampMin", inClampMin); +mod.addUniform("f", "MOD_clampMax", inClampMax); + +mod.addUniform("f", "MOD_x", x); +mod.addUniform("f", "MOD_y", y); +mod.addUniform("f", "MOD_z", z); + + +// function removeModule() +// { +// if (shader && moduleVert) shader.removeModule(moduleVert); +// shader = null; +// } + +function updateToZero() +{ + // if (!shader) + // { + // needsUpdateToZero = true; + // return; + // } + + mod.toggleDefine("MOD_TO_ZERO", inToZero.get()); + mod.toggleDefine("MOD_OBJECT_POS", inSrc.get() == "Object position"); + mod.toggleDefine("MOD_CLAMP_SIZE", inClampBool.get()); + + needsUpdateToZero = false; + + inClampMin.setUiAttribs({ "greyout": !inClampBool.get() }); + inClampMax.setUiAttribs({ "greyout": !inClampBool.get() }); +} + + +exec.onTriggered = function () +{ + if (!cgl.getShader()) + { + next.trigger(); + return; + } + + if (CABLES.UI) + { + if (op.isCurrentUiOp()) gui.setTransformGizmo({ "posX": x, "posY": y, "posZ": z }); + + if (cgl.shouldDrawHelpers(op)) + { + cgl.pushModelMatrix(); + mat4.translate(cgl.mMatrix, cgl.mMatrix, [x.get(), y.get(), z.get()]); + CABLES.GL_MARKER.drawSphere(op, inSize.get()); + cgl.popModelMatrix(); + } + } + + // if (cgl.getShader() != shader) + // { + // if (shader) removeModule(); + // shader = cgl.getShader(); + + // moduleVert = shader.addModule( + // { + // "title": op.objName, + // "name": "MODULE_VERTEX_POSITION", + // "srcHeadVert": attachments.areascale_vert, + // "srcBodyVert": srcBodyVert + // }); + + // inSize.uniform = new CGL.Uniform(shader, "f", "MOD_size", inSize); + // inStrength.uniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "strength", inStrength); + // inSmooth.uniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "smooth", inSmooth); + + // x.uniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "x", x); + // y.uniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "y", y); + // z.uniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "z", z); + + // inClampMin.uniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "clampMin", inClampMin); + // inClampMax.uniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "clampMax", inClampMax); + // } + + if (needsUpdateToZero)updateToZero(); + // if (!shader) return; + + + mod.bind(); + next.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.ShaderEffects.AreaScaler_v3.prototype = new CABLES.Op(); +CABLES.OPS["3b7c5601-881a-4748-91d1-aea4c7c1bf67"]={f:Ops.Gl.ShaderEffects.AreaScaler_v3,objName:"Ops.Gl.ShaderEffects.AreaScaler_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.AreaTranslateFBMNoise +// +// ************************************************************** + +Ops.Gl.ShaderEffects.AreaTranslateFBMNoise = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"areascale_vert":"UNI bool MOD_smooth;\nUNI float MOD_x,MOD_y,MOD_z;\nUNI float MOD_tx,MOD_ty,MOD_tz;\nUNI float MOD_strength;\nUNI float MOD_size;\nUNI float MOD_noiseScale;\n\n\n\n\nfloat MOD_mod289(float x){return x - floor(x * (1.0 / 289.0)) * 289.0;}\nvec4 MOD_mod289(vec4 x){return x - floor(x * (1.0 / 289.0)) * 289.0;}\nvec4 MOD_perm(vec4 x){return MOD_mod289(((x * 34.0) + 1.0) * x);}\n\nfloat MOD_noise(vec3 p){\n vec3 a = floor(p);\n vec3 d = p - a;\n d = d * d * (3.0 - 2.0 * d);\n\n vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0);\n vec4 k1 = MOD_perm(b.xyxy);\n vec4 k2 = MOD_perm(k1.xyxy + b.zzww);\n\n vec4 c = k2 + a.zzzz;\n vec4 k3 = MOD_perm(c);\n vec4 k4 = MOD_perm(c + 1.0);\n\n vec4 o1 = fract(k3 * (1.0 / 41.0));\n vec4 o2 = fract(k4 * (1.0 / 41.0));\n\n vec4 o3 = o2 * d.z + o1 * (1.0 - d.z);\n vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x);\n\n return o4.y * d.y + o4.x * (1.0 - d.y);\n}\n\n\n\nfloat MOD_fbm(vec3 x)\n{\n const int NUM_OCTAVES=8;\n float time=0.0;\n\n\tfloat v = 0.0;\n\tfloat a = 0.5;\n\tvec3 shift = vec3(100.0+time);\n\tfor (int i = 0; i < NUM_OCTAVES; ++i) {\n\t\tv += a * MOD_noise(x);\n\t\tx = x * 2.0 + shift;\n\t\ta *= 0.5;\n\t}\n\treturn v;\n}\n\n\n\nmat4 MOD_rotation3d(vec3 axis, float angle) {\n axis = normalize(axis);\n float s = sin(angle);\n float c = cos(angle);\n float oc = 1.0 - c;\n\n return mat4(\n\t\toc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0,\n oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0,\n oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0,\n\t\t0.0, 0.0, 0.0, 1.0\n\t);\n}\n\n\nmat4 MOD_translate(mat4 mat)\n{\n vec3 forcePos=vec3(MOD_x,MOD_y,MOD_z);\n vec3 noisePos=vec3(MOD_tx,MOD_ty,MOD_tz);\n vec3 worldPos=vec3(mat[3][0],mat[3][1],mat[3][2]);\n // vec3 worldPosInst=vec3(instMat[3][0],instMat[3][1],instMat[3][2]);\n\n vec3 vecToOrigin=worldPos-forcePos;\n float dist=abs(length(vecToOrigin));\n float distAlpha = (MOD_size - dist) ;\n\n if(MOD_smooth) distAlpha=smoothstep(0.0,MOD_size,distAlpha);\n else\n {\n if(distAlpha>0.0) distAlpha=1.0;\n else distAlpha=0.0;\n }\n\n distAlpha*=MOD_strength;\n\n vec3 tr=vec3(distAlpha);\n\n float nois=(MOD_fbm(MOD_noiseScale*(worldPos+noisePos))-0.5);\n float nois2=(MOD_fbm(MOD_noiseScale*(worldPos+noisePos*5.711))-0.5);\n float nois3=(MOD_fbm(MOD_noiseScale*(worldPos+noisePos*2.0))-0.5);\n // tr=nois*tr;\n\n\n #ifdef MOD_DO_ROTATE\n if(distAlpha>0.0) mat*=MOD_rotation3d( vec3(distAlpha)*vec3(nois,nois2,nois3), MOD_strength/57.297);\n #endif\n\n #ifdef MOD_DO_TRANSLATE\n mat[3][0] += nois*distAlpha;\n mat[3][1] += nois2*distAlpha;\n mat[3][2] += nois3*distAlpha;\n #endif\n\n return mat;\n}\n",}; +const + render = op.inTrigger("render"), + next = op.outTrigger("trigger"), + inMode = op.inSwitch("Mode", ["Rotate", "Translate"], "Translate"), + inSize = op.inValue("Size", 1), + inStrength = op.inValue("Strength", 1), + inSmooth = op.inValueBool("Smooth", true), + x = op.inValue("x"), + y = op.inValue("y"), + z = op.inValue("z"), + inNoiseScale = op.inValue("Noise Scale", 0.5), + tx = op.inValue("Noise X"), + ty = op.inValue("Noise Y"), + tz = op.inValue("Noise Z"); + +const cgl = op.patch.cgl; +op.setPortGroup("Noise", [inNoiseScale, tx, ty, tz]); +op.setPortGroup("Area Position", [x, y, z]); + +let needsUpdateToZero = true; +let mscaleUni = null; +let shader = null; +let uniforms = {}; +let srcHeadVert = attachments.areascale_vert; +let moduleVert = null; +let srcBodyVert = "" + .endl() + "mMatrix=MOD_translate(mMatrix);" // modelMatrix* + .endl(); + +render.onLinkChanged = removeModule; +inMode.onChange = updateMode; + +function removeModule() +{ + if (shader && moduleVert) shader.removeModule(moduleVert); + shader = null; +} + +function updateMode() +{ + if (!shader) return; + shader.toggleDefine(moduleVert.prefix + "DO_ROTATE", inMode.get() == "Rotate"); + shader.toggleDefine(moduleVert.prefix + "DO_TRANSLATE", inMode.get() == "Translate"); +} + +render.onTriggered = function () +{ + if (!cgl.getShader()) + { + next.trigger(); + return; + } + + if (CABLES.UI) + { + if (op.isCurrentUiOp()) gui.setTransformGizmo({ "posX": x, "posY": y, "posZ": z }); + if (cgl.shouldDrawHelpers(op)) + { + cgl.pushModelMatrix(); + mat4.translate(cgl.mMatrix, cgl.mMatrix, [x.get(), y.get(), z.get()]); + CABLES.GL_MARKER.drawSphere(op, inSize.get()); + cgl.popModelMatrix(); + } + } + + if (cgl.getShader() != shader) + { + if (shader) removeModule(); + shader = cgl.getShader(); + + moduleVert = shader.addModule( + { + "title": op.objName, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": srcHeadVert, + "srcBodyVert": srcBodyVert + }); + + updateMode(); + + uniforms.inSizeUniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "size", inSize); + uniforms.inStrengthUniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "strength", inStrength); + uniforms.inSmoothUniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "smooth", inSmooth); + uniforms.inNoiseScaleUniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "noiseScale", inNoiseScale); + + uniforms.xUniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "x", x); + uniforms.yUniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "y", y); + uniforms.zUniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "z", z); + + uniforms.txUniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "tx", tx); + uniforms.tyUniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "ty", ty); + uniforms.tzUniform = new CGL.Uniform(shader, "f", moduleVert.prefix + "tz", tz); + } + + + if (!shader) return; + + next.trigger(); +}; + + +}; + +Ops.Gl.ShaderEffects.AreaTranslateFBMNoise.prototype = new CABLES.Op(); +CABLES.OPS["e755e88e-a2a7-4db2-84b3-0e76c423bdb6"]={f:Ops.Gl.ShaderEffects.AreaTranslateFBMNoise,objName:"Ops.Gl.ShaderEffects.AreaTranslateFBMNoise"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.AreaTranslateMeshes_v3 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.AreaTranslateMeshes_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"areascale_vert":"\nmat4 MOD_translate(mat4 mat)\n{\n // vec3 forcePos=vec3(MOD_posx,MOD_posy,MOD_posz);\n vec3 worldPos=vec3(mat[3][0],mat[3][1],mat[3][2]);\n vec3 vecToOrigin=worldPos-MOD_pos;\n float dist=abs(length(vecToOrigin));\n float distAlpha = (MOD_size - dist) ;\n\n distAlpha=clamp(distAlpha,0.0,1.0);\n\n distAlpha*=MOD_strength;\n\n vec3 tr=normalize(vecToOrigin)*distAlpha;\n\ntr*=MOD_mul;\n\n mat[3][0] += tr.x;\n mat[3][1] += tr.y;\n mat[3][2] += tr.z;\n\n return mat;\n}\n\n",}; +const + render = op.inTrigger("render"), + next = op.outTrigger("trigger"), + inSize = op.inValue("Size", 1), + inStrength = op.inValue("Strength", 0.5), + x = op.inValue("x"), + y = op.inValue("y"), + z = op.inValue("z"), + mulx = op.inValue("Multiply x", 1), + muly = op.inValue("Multiply y", 1), + mulz = op.inValue("Multiply z", 1); + +const cgl = op.patch.cgl; + +op.setPortGroup("Area Position", [x, y, z]); +op.setPortGroup("Axis Multiply", [mulx, muly, mulz]); + +const needsUpdateToZero = true; +const mscaleUni = null; +let shader = null; +const srcHeadVert = attachments.areascale_vert; +const uniforms = {}; +const srcBodyVert = "" + .endl() + "mMatrix=MOD_translate(mMatrix);" // modelMatrix* + .endl(); + +let moduleVert = null; + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "title": op.name, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": srcHeadVert, + "srcBodyVert": srcBodyVert +}); + +mod.addUniformVert("f", "MOD_size", inSize); +mod.addUniformVert("f", "MOD_strength", inStrength); + +mod.addUniformVert("3f", "MOD_pos", x, y, z); +mod.addUniformVert("3f", "MOD_mul", mulx, muly, mulz); + +render.onTriggered = function () +{ + if (!cgl.getShader()) + { + next.trigger(); + return; + } + + if (CABLES.UI) + { + if (op.isCurrentUiOp()) + gui.setTransformGizmo( + { + "posX": x, + "posY": y, + "posZ": z + }); + + if (cgl.shouldDrawHelpers(op)) + { + cgl.pushModelMatrix(); + mat4.translate(cgl.mMatrix, cgl.mMatrix, [x.get(), y.get(), z.get()]); + CABLES.GL_MARKER.drawSphere(op, inSize.get()); + cgl.popModelMatrix(); + } + } + + mod.bind(); + next.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.ShaderEffects.AreaTranslateMeshes_v3.prototype = new CABLES.Op(); +CABLES.OPS["69f7a5b5-4824-441a-960c-e7b13b17790d"]={f:Ops.Gl.ShaderEffects.AreaTranslateMeshes_v3,objName:"Ops.Gl.ShaderEffects.AreaTranslateMeshes_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.Bend_v2 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.Bend_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"bend_vert":"\n\nvoid MOD_bendDistort(inout vec3 pos, inout vec3 norm)\n{\n pos = (MOD_transMatrix * vec4(pos, 1.0)).xyz;\n norm = (vec4(norm, 0.0) * MOD_invTransMatrix).xyz;\n\n float PI = 3.14159265;\n if (abs(MOD_amount) > 1e-5) {\n float bendAngle = MOD_amount;\n float radius = 1.0 / bendAngle;\n\n // float d = clamp(pos.x, MOD_range.x, MOD_range.y);\n float d = clamp(pos.x, MOD_range.x, MOD_range.y);\n float th = PI * 0.5 + (bendAngle * d);\n float s = sin(th);\n float c = cos(th);\n pos.xy = vec2(s * (pos.x - d) - c * (radius + pos.y),\n c * (pos.x - d) + s * (radius + pos.y) - radius);\n norm.xy = vec2(s * norm.x - c * norm.y,\n c * norm.x + s * norm.y);\n }\n\n pos = (MOD_invTransMatrix * vec4(pos, 1.0)).xyz;\n norm = (vec4(norm, 0.0) * MOD_transMatrix).xyz;\n}\n",}; +const render = op.inTrigger("render"); +const amount = op.inValue("Amount"); +const rotX = op.inValue("RotX"); +const rotY = op.inValue("RotY"); +const rotZ = op.inValue("RotZ"); +const scale = op.inValue("Scale", 2); +const offset = op.inValue("Offset", 0.25); +const limited = op.inValueBool("Limited", true); + +const next = op.outTrigger("trigger"); + +const srcHeadVert = attachments.bend_vert; +const srcBodyVert = "" + .endl() + " MOD_bendDistort(pos.xyz, norm);" + .endl(); + +const uniAmount = null; +const uniRange = null; +const uniTransMatrix = null; +const uniInvTransMatrix = null; +const cgl = op.patch.cgl; + +let matricesValid = false; +const transMatrix = mat4.create(); +const invTransMatrix = mat4.create(); +let amountRadians = 0; + +function invalidateMatrices() +{ + matricesValid = false; +} + +rotX.onChange = invalidateMatrices; +rotY.onChange = invalidateMatrices; +rotZ.onChange = invalidateMatrices; +scale.onChange = invalidateMatrices; +offset.onChange = invalidateMatrices; + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": attachments.bend_vert, + "srcBodyVert": srcBodyVert +}); + +mod.addUniformVert("f", "MOD_amount", 0); +mod.addUniformVert("2f", "MOD_range", [0, 1]); +mod.addUniformVert("m4", "MOD_transMatrix", transMatrix); +mod.addUniformVert("m4", "MOD_invTransMatrix", invTransMatrix); + +amount.onChange = function () { amountRadians = amount.get() * CGL.DEG2RAD; }; + +mat4.identity(transMatrix); +mat4.identity(invTransMatrix); + +const tvec = vec3.create(); +const svec = vec4.create(); +function updateMatrices() +{ + if (matricesValid) return; + + vec3.set(tvec, offset.get(), 0, 0); + + const s = 1 / scale.get(); + vec3.set(svec, s, s, s); + + mat4.identity(transMatrix); + mat4.translate(transMatrix, transMatrix, tvec); + + mat4.rotateX(transMatrix, transMatrix, rotX.get() * CGL.DEG2RAD); + mat4.rotateY(transMatrix, transMatrix, rotY.get() * CGL.DEG2RAD); + mat4.rotateZ(transMatrix, transMatrix, rotZ.get() * CGL.DEG2RAD); + + mat4.scale(transMatrix, transMatrix, svec); + + mat4.invert(invTransMatrix, transMatrix); + matricesValid = true; +} + +render.onTriggered = function () +{ + mod.setUniformValue("MOD_range", limited.get() ? [0, 1] : [-99999, 99999]); + + updateMatrices(); + + mod.bind(); + mod.setUniformValue("MOD_amount", amountRadians); + next.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.ShaderEffects.Bend_v2.prototype = new CABLES.Op(); +CABLES.OPS["7476156e-3ca3-445a-bd30-1b9373a6af4c"]={f:Ops.Gl.ShaderEffects.Bend_v2,objName:"Ops.Gl.ShaderEffects.Bend_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.ClampVertexPosition_v2 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.ClampVertexPosition_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"restrictVertex_vert":"\n\n#ifndef RESTRICT_UPDATENORMALS\n\n #ifdef MOD_RESTRICT_AXIS_X\n pos.x=min(MOD_max,pos.x);\n pos.x=max(MOD_min,pos.x);\n #endif\n #ifdef MOD_RESTRICT_AXIS_Y\n pos.y=min(MOD_max,pos.y);\n pos.y=max(MOD_min,pos.y);\n #endif\n #ifdef MOD_RESTRICT_AXIS_Z\n pos.z=min(MOD_max,pos.z);\n pos.z=max(MOD_min,pos.z);\n #endif\n\n\n#endif\n\n#ifdef RESTRICT_UPDATENORMALS\n #ifdef MOD_RESTRICT_AXIS_X\n if(pos.x>MOD_max)\n {\n pos.x=MOD_max;\n pos.y=0.0;\n pos.z=0.0;\n norm=vec3(0.0,1.0,0.0);\n }\n if(pos.xMOD_max)\n {\n pos.y=MOD_max;\n pos.x=0.0;\n pos.z=0.0;\n norm=vec3(0.0,0.0,1.0);\n }\n if(pos.yMOD_max)\n {\n pos.z=MOD_max;\n pos.y=0.0;\n pos.x=0.0;\n norm=vec3(1.0,0.0,0.0);\n }\n if(pos.z MOD_inSizeAmountFalloffSizeX.x ||\n abs((MOD_vertPos.xyz*MOD_size).y-(MOD_pos.xyz*MOD_size).y) > MOD_inSizeAmountFalloffSizeX.x ||\n abs((MOD_vertPos.xyz*MOD_size).z-(MOD_pos.xyz*MOD_size).z) > MOD_inSizeAmountFalloffSizeX.x ) MOD_de=0.0;\n#endif\n\n#ifdef MOD_AREA_AXIS_X\n float MOD_de=abs(MOD_pos.x-MOD_vertPos.x);\n#endif\n#ifdef MOD_AREA_AXIS_Y\n float MOD_de=abs(MOD_pos.y-MOD_vertPos.y);\n#endif\n#ifdef MOD_AREA_AXIS_Z\n float MOD_de=abs(MOD_pos.z-MOD_vertPos.z);\n#endif\n\n#ifdef MOD_AREA_AXIS_X_INFINITE\n float MOD_de=MOD_pos.x-MOD_vertPos.x;\n#endif\n#ifdef MOD_AREA_AXIS_Y_INFINITE\n float MOD_de=MOD_pos.y-MOD_vertPos.y;\n#endif\n#ifdef MOD_AREA_AXIS_Z_INFINITE\n float MOD_de=MOD_pos.z-MOD_vertPos.z;\n#endif\n\n#ifndef MOD_AREA_BOX\n MOD_de=1.0-smoothstep(MOD_inSizeAmountFalloffSizeX.z*MOD_inSizeAmountFalloffSizeX.x,MOD_inSizeAmountFalloffSizeX.x,MOD_de);\n#endif\n\n#ifdef MOD_AREA_INVERT\n MOD_de=1.0-MOD_de;\n#endif\n\n#ifdef MOD_BLEND_NORMAL\n col.rgb=mix(col.rgb,MOD_col, MOD_de*MOD_inSizeAmountFalloffSizeX.y);\n#endif\n\n\n#ifdef MOD_BLEND_MULTIPLY\n col.rgb=mix(col.rgb,col.rgb*MOD_col,MOD_de*MOD_inSizeAmountFalloffSizeX.y);\n#endif\n\n#ifdef MOD_BLEND_ADD\n col.rgb+=MOD_de*MOD_inSizeAmountFalloffSizeX.y*MOD_col;\n#endif\n\n\n#ifdef MOD_BLEND_OPACITY\n col.a*=(1.0-MOD_de*MOD_inSizeAmountFalloffSizeX.y);\n#endif\n\n#ifdef MOD_BLEND_DISCARD\n if(MOD_de*MOD_inSizeAmountFalloffSizeX.y>=0.999)discard;\n#endif\n\n// col.rgb=vec3(distance(MOD_vertPos.xyz,MOD_pos.xyz))*0.1\n// col.rgb=MOD_pos.xyz;","colorarea_head_frag":"IN vec4 MOD_vertPos;\n",}; +const + render = op.inTrigger("Render"), + inArea = op.inValueSelect("Area", ["Sphere", "Box", "Axis X", "Axis Y", "Axis Z", "Axis X Infinite", "Axis Y Infinite", "Axis Z Infinite"], "Sphere"), + inSize = op.inValue("Size", 1), + inAmount = op.inValueSlider("Amount", 0.5), + inFalloff = op.inValueSlider("Falloff", 0), + inInvert = op.inValueBool("Invert"), + inBlend = op.inSwitch("Blend ", ["Normal", "Multiply", "Opacity", "Add", "Discard"], "Normal"), + r = op.inValueSlider("r", Math.random()), + g = op.inValueSlider("g", Math.random()), + b = op.inValueSlider("b", Math.random()), + x = op.inValue("x"), + y = op.inValue("y"), + z = op.inValue("z"), + doScale = op.inBool("Change Size", false), + sizeX = op.inFloat("Size X", 1), + sizeY = op.inFloat("Size Y", 1), + sizeZ = op.inFloat("Size Z", 1), + inTex = op.inTexture("Texture"), + + inWorldSpace = op.inValueBool("WorldSpace", true), + inPrio = op.inBool("Priority", true), + next = op.outTrigger("Next"); + +op.setPortGroup("Scale", [doScale, sizeX, sizeZ, sizeY]); +op.setPortGroup("Position", [x, y, z]); +op.setPortGroup("Color", [inBlend, r, g, b]); +r.setUiAttribs({ "colorPick": true }); + +const cgl = op.patch.cgl; + +const srcHeadVert = "" + .endl() + "OUT vec4 MOD_vertPos;" + .endl(); + +const srcBodyVert = "" + .endl() + "#ifndef MOD_WORLDSPACE" + .endl() + " MOD_vertPos=vec4(vPosition,1.0);" + .endl() + "#endif" + + .endl() + "#ifdef MOD_WORLDSPACE" + .endl() + " MOD_vertPos=mMatrix*pos;" + .endl() + "#endif" + .endl(); + +inWorldSpace.onChange = + inTex.onLinkChanged = + inArea.onChange = + inInvert.onChange = + doScale.onChange = + inBlend.onChange = updateDefines; + +render.onTriggered = doRender; + +const vertModTitle = "vert_" + op.name; +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "priority": 2, + "title": vertModTitle, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": srcHeadVert, + "srcBodyVert": srcBodyVert +}); + +mod.addModule({ + "title": op.name, + "name": "MODULE_COLOR", + "srcHeadFrag": attachments.colorarea_head_frag, + "srcBodyFrag": attachments.colorarea_frag +}); + +mod.addUniform("4f", "MOD_inSizeAmountFalloffSizeX", inSize, inAmount, inFalloff, 0); +mod.addUniform("3f", "MOD_color", r, g, b); +mod.addUniform("3f", "MOD_pos", x, y, z); +mod.addUniform("3f", "MOD_scale", sizeX, sizeY, sizeZ); +mod.addUniform("t", "MOD_tex"); + +updateDefines(); + +inPrio.onChange = updatePrio; +updatePrio(); + +function updatePrio() +{ + mod.removeModule(vertModTitle); + + const vmod = { + // "priority": 0, + "title": vertModTitle, + "name": "MODULE_VERTEX_POSITION", + srcHeadVert, + srcBodyVert + }; + + if (inPrio.get()) vmod.priority = 2; + + mod.addModule(vmod); +} + +function updateDefines() +{ + mod.toggleDefine("MOD_BLEND_NORMAL", inBlend.get() == "Normal"); + mod.toggleDefine("MOD_BLEND_OPACITY", inBlend.get() == "Opacity"); + mod.toggleDefine("MOD_BLEND_MULTIPLY", inBlend.get() == "Multiply"); + mod.toggleDefine("MOD_BLEND_DISCARD", inBlend.get() == "Discard"); + mod.toggleDefine("MOD_BLEND_ADD", inBlend.get() == "Add"); + + mod.toggleDefine("MOD_AREA_SIZE", doScale.get()); + + mod.toggleDefine("MOD_AREA_INVERT", inInvert.get()); + mod.toggleDefine("MOD_WORLDSPACE", inWorldSpace.get()); + + mod.toggleDefine("MOD_AREA_AXIS_X", inArea.get() == "Axis X"); + mod.toggleDefine("MOD_AREA_AXIS_Y", inArea.get() == "Axis Y"); + mod.toggleDefine("MOD_AREA_AXIS_Z", inArea.get() == "Axis Z"); + mod.toggleDefine("MOD_AREA_AXIS_X_INFINITE", inArea.get() == "Axis X Infinite"); + mod.toggleDefine("MOD_AREA_AXIS_Y_INFINITE", inArea.get() == "Axis Y Infinite"); + mod.toggleDefine("MOD_AREA_AXIS_Z_INFINITE", inArea.get() == "Axis Z Infinite"); + mod.toggleDefine("MOD_AREA_SPHERE", inArea.get() == "Sphere"); + mod.toggleDefine("MOD_AREA_BOX", inArea.get() == "Box"); + + mod.toggleDefine("MOD_DOSCALE", doScale.get()); + + // mod.removeUniform("3f", "MOD_scale",sizeX,sizeY,sizeZ); + sizeX.setUiAttribs({ "greyout": !doScale.get() }); + sizeY.setUiAttribs({ "greyout": !doScale.get() }); + sizeZ.setUiAttribs({ "greyout": !doScale.get() }); + + mod.toggleDefine("MOD_USE_TEX", inTex.isLinked()); +} + +function drawHelpers() +{ + if (cgl.frameStore.shadowPass) return; + if (cgl.shouldDrawHelpers(op)) gui.setTransformGizmo({ "posX": x, "posY": y, "posZ": z }); +} + +function doRender() +{ + // if(doScale.get()) mod.setUniformValue("MOD_scale",[sizeX.get(),sizeY.get(),sizeZ.get()]); + mod.bind(); + + if (inTex.isLinked()) + { + let tex = inTex.get(); + + if (!tex) tex = CGL.Texture.getEmptyTexture(cgl).tex; + else tex = tex.tex; + + mod.pushTexture("MOD_tex", tex); + } + + drawHelpers(); + next.trigger(); + + mod.unbind(); +} + + +}; + +Ops.Gl.ShaderEffects.ColorArea_v4.prototype = new CABLES.Op(); +CABLES.OPS["83a4b2b8-23ff-4491-b538-e89ac7934d1a"]={f:Ops.Gl.ShaderEffects.ColorArea_v4,objName:"Ops.Gl.ShaderEffects.ColorArea_v4"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.ColorizeInstancedMeshes +// +// ************************************************************** + +Ops.Gl.ShaderEffects.ColorizeInstancedMeshes = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"colorize_instances_frag":"\n\n// col.rgb*=MOD_random(vec2(instanceIndexFrag/1000.0,instanceIndexFrag/1000.0));\n\nfloat MOD_rand=fract(sin(instanceIndexFrag));\n\n#ifdef LOOKUPTEX\n // col.rgb*= (texture( MOD_lut, vec2(MOD_rand,0.5) ).rgb-vec3(0.5))*2.0*MOD_strength;\n col.rgb*= ( (texture( MOD_lut, vec2(MOD_rand,0.5) ).rgb+0.5)*MOD_strength);\n // col.rgb*=MOD_strength;\n#endif\n\n#ifdef MULCOLOR\n col.rgb*=(MOD_rand*2.0)*MOD_strength;\n#endif\n\n",}; +const cgl = op.patch.cgl; + +op.render = op.inTrigger("render"); +op.trigger = op.outTrigger("trigger"); + +const inStrength = op.inValueSlider("Amount", 1); +const mulColor = op.inValueBool("Multiply Color"); +const inLookup = op.inTexture("Lookup Texture"); + +let shader = null; + +let srcBodyVert = "" + .endl() + "instanceIndexFrag=instanceIndex;" + .endl(); + +let srcHeadVert = "" + .endl() + "#ifndef ATTRIB_instanceIndex" + .endl() + " #define ATTRIB_instanceIndex" + .endl() + " IN float instanceIndex;" + .endl() + "#endif" + .endl() + "#ifndef ATTRIB_instanceIndexFrag" + .endl() + " #define ATTRIB_instanceIndexFrag" + .endl() + " OUT float instanceIndexFrag;" + .endl() + "#endif" + .endl(); + +let srcHeadFrag = "" + + .endl() + "UNI float MOD_strength;" + .endl() + "#ifdef LOOKUPTEX" + .endl() + " UNI sampler2D MOD_lut;" + .endl() + "#endif" + .endl() + "#ifndef ATTRIB_instanceIndexFrag" + .endl() + " #define ATTRIB_instanceIndexFrag" + .endl() + " IN float instanceIndexFrag;" + .endl() + "#endif" + .endl() + "float MOD_random(vec2 co)" + .endl() + "{" + .endl() + " return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 437511.5453);" + .endl() + "}" + + .endl(); + +let moduleVert = null; +let moduleFrag = null; +function removeModule() +{ + if (shader && moduleVert) shader.removeModule(moduleVert); + if (shader && moduleFrag) shader.removeModule(moduleFrag); + shader = null; +} + +mulColor.onChange = updateMulColor; +function updateMulColor() +{ + if (shader) + if (mulColor.get())shader.define("MULCOLOR"); + else shader.removeDefine("MULCOLOR"); +} + +op.render.onLinkChanged = removeModule; + +inLookup.onChange = updateLookupTexture; +function updateLookupTexture() +{ + if (shader) + { + if (inLookup.get())shader.define("LOOKUPTEX"); + else shader.removeDefine("LOOKUPTEX"); + inLookup.uniform = new CGL.Uniform(shader, "t", moduleFrag.prefix + "lut", 5); + } +} + +op.render.onTriggered = function () +{ + if (!cgl.getShader()) + { + op.trigger.trigger(); + return; + } + + if (cgl.getShader() != shader) + { + if (shader) removeModule(); + shader = cgl.getShader(); + + moduleVert = shader.addModule( + { + "title": op.objName, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": srcHeadVert, + "srcBodyVert": srcBodyVert + }); + + moduleFrag = shader.addModule( + { + "title": op.objName, + "name": "MODULE_COLOR", + "srcHeadFrag": srcHeadFrag, + "srcBodyFrag": attachments.colorize_instances_frag + }); + + inStrength.uniform = new CGL.Uniform(shader, "f", moduleFrag.prefix + "strength", inStrength); + + updateMulColor(); + updateLookupTexture(); + } + + if (inLookup.get()) + { + cgl.setTexture(5, inLookup.get().tex); + // cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, inLookup.get().tex); + } + + if (!shader) return; + + op.trigger.trigger(); +}; + + +}; + +Ops.Gl.ShaderEffects.ColorizeInstancedMeshes.prototype = new CABLES.Op(); +CABLES.OPS["2939f8ec-dd70-40ad-999d-7242e87296b9"]={f:Ops.Gl.ShaderEffects.ColorizeInstancedMeshes,objName:"Ops.Gl.ShaderEffects.ColorizeInstancedMeshes"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.DeformArea +// +// ************************************************************** + +Ops.Gl.ShaderEffects.DeformArea = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"deformarea_vert":"vec4 MOD_deform(vec4 pos,mat4 mMatrix)\n{\n vec4 modelPos=pos;\n\n #ifdef MOD_WORLDSPACE\n modelPos=mMatrix*pos;\n #endif\n\n vec3 forcePos=vec3(MOD_x,MOD_y,MOD_z);\n vec3 vecToOrigin=modelPos.xyz-forcePos;\n float dist=abs(length(vecToOrigin));\n float distAlpha = (MOD_size - dist) / MOD_size;\n\n if(MOD_size > dist)\n {\n vec3 vecNormal=normalize(vecToOrigin);\n\n if(MOD_smooth>0.0) distAlpha=smoothstep(0.0,MOD_size,distAlpha);\n\n vec3 velocity = (vecNormal * distAlpha * MOD_strength );\n\n pos.xyz+=velocity*0.1;\n }\n\n return pos;\n\n}\n",}; +const + render = op.inTrigger("render"), + next = op.outTrigger("trigger"), + inSize = op.inValue("Size", 1), + inStrength = op.inValue("Strength", 0.5), + inSmooth = op.inValueBool("Smooth", true), + inWorldSpace = op.inValueBool("WorldSpace", false), + x = op.inValue("x"), + y = op.inValue("y"), + z = op.inValue("z"); + +const cgl = op.patch.cgl; + +inWorldSpace.onChange = updateWorldspace; + +// let shader = null; +const srcHeadVert = attachments.deformarea_vert; + +const srcBodyVert = "" + .endl() + "pos=MOD_deform(pos,mMatrix);" + .endl(); + +// let moduleVert = null; + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "title": op.name, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": attachments.deformarea_vert, + "srcBodyVert": srcBodyVert +}); + +mod.addUniformVert("f", "MOD_size", inSize); +mod.addUniformVert("f", "MOD_strength", inStrength); +mod.addUniformVert("f", "MOD_smooth", inSmooth); + +mod.addUniformVert("f", "MOD_x", x); +mod.addUniformVert("f", "MOD_y", y); +mod.addUniformVert("f", "MOD_z", z); + +render.onTriggered = function () +{ + if (CABLES.UI) + { + if (op.isCurrentUiOp()) gui.setTransformGizmo({ "posX": x, "posY": y, "posZ": z }); + + if (cgl.shouldDrawHelpers(op)) + { + cgl.pushModelMatrix(); + mat4.translate(cgl.mMatrix, cgl.mMatrix, [x.get(), y.get(), z.get()]); + CABLES.GL_MARKER.drawSphere(op, inSize.get()); + cgl.popModelMatrix(); + } + } + + mod.bind(); + next.trigger(); + mod.unbind(); +}; + +function updateWorldspace() +{ + mod.toggleDefine("MOD_WORLDSPACE", inWorldSpace.get()); +} + + +}; + +Ops.Gl.ShaderEffects.DeformArea.prototype = new CABLES.Op(); +CABLES.OPS["6c40cfcb-75c8-4c64-bc13-c37faaea73df"]={f:Ops.Gl.ShaderEffects.DeformArea,objName:"Ops.Gl.ShaderEffects.DeformArea"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.DiscardMaterialAlpha +// +// ************************************************************** + +Ops.Gl.ShaderEffects.DiscardMaterialAlpha = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"alpha_frag":"\n\n#ifdef ALPHA_THRESHOLD\n if(col.a +{ + mod.toggleDefine("ENABLE_FRESNEL_MOD", inActive); + inR.setUiAttribs({ "greyout": !inActive.get() }); + inG.setUiAttribs({ "greyout": !inActive.get() }); + inB.setUiAttribs({ "greyout": !inActive.get() }); + inIntensity.setUiAttribs({ "greyout": !inActive.get() }); + inExponent.setUiAttribs({ "greyout": !inActive.get() }); +}; + +const outTrigger = op.outTrigger("Trigger Out"); + + +const mod = new CGL.ShaderModifier(cgl, "fresnelGlow"); +mod.toggleDefine("ENABLE_FRESNEL_MOD", inActive); + +mod.addModule({ + "priority": 2, + "title": "fresnelGlow", + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": attachments.fresnel_head_vert, + "srcBodyVert": attachments.fresnel_body_vert +}); + +mod.addModule({ + "title": "fresnelGlow", + "name": "MODULE_COLOR", + "srcHeadFrag": attachments.fresnel_head_frag, + "srcBodyFrag": attachments.fresnel_body_frag +}); + +mod.addUniform("4f", "MOD_inFresnel", inR, inG, inB, inIntensity); +mod.addUniform("f", "MOD_inFresnelExponent", inExponent); + +inTrigger.onTriggered = () => +{ + mod.bind(); + outTrigger.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.ShaderEffects.FresnelGlow.prototype = new CABLES.Op(); +CABLES.OPS["89979937-68a6-4736-8241-3c6b748103d4"]={f:Ops.Gl.ShaderEffects.FresnelGlow,objName:"Ops.Gl.ShaderEffects.FresnelGlow"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.InstancedDisplacementMap_v2 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.InstancedDisplacementMap_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"displace_vert":"\n#ifdef INSTANCING\n\n #ifdef MOD_SRC_INSTMAT\n vec3 MOD_p=vec3(instMat[3][0],instMat[3][1],instMat[3][2]);\n #endif\n\n #ifdef MOD_SRC_MMAT\n vec3 MOD_p=vec3(mMatrix[3][0],mMatrix[3][1],mMatrix[3][2]);\n #endif\n // vec3 MOD_p=(mMatrix*vec4(0.0,0.0,0.0,1.0)).xyz;//vec3(mMatrix[3][0],mMatrix[3][1],mMatrix[3][2]);\n\n vec2 MOD_coord=MOD_p.xy*(1.0/MOD_scale)+MOD_offset-vec2(0.5,0.5);\n\n // vec3 MOD_dis\n\n #ifdef MOD_CHAN_R\n vec3 MOD_dis=vec3( texture(MOD_texture,MOD_coord).r );\n #endif\n #ifdef MOD_CHAN_G\n vec3 MOD_dis=vec3( texture(MOD_texture,MOD_coord).g );\n #endif\n #ifdef MOD_CHAN_B\n vec3 MOD_dis=vec3( texture(MOD_texture,MOD_coord).b );\n #endif\n\n #ifdef MOD_CHAN_RGB\n vec3 MOD_dis=vec3( texture(MOD_texture,MOD_coord).rgb );\n #endif\n\n #ifdef MOD_COLORIZE\n MOD_dispColor=MOD_dis;\n #endif\n\n #ifdef MOD_DEBUG\n MOD_dispColor.rg=mod(MOD_coord,1.0).rg;\n #endif\n\n\n #ifdef MOD_NORMALIZE\n MOD_dis=(MOD_dis-0.5)*2.0;\n #endif\n\n\n #ifdef MOD_CLAMP\n if(MOD_coord.x>1.0||MOD_coord.x<0.0|| MOD_coord.y>1.0 || MOD_coord.y<0.0)\n {\n MOD_dis=vec3(0.0);\n #ifdef MOD_COLORIZE\n MOD_dispColor=vec3(0.0);\n #endif\n }\n #endif\n\n\n #ifdef MOD_MODE_TRANS\n MOD_dis*=MOD_strength;\n MOD_dis+=MOD_min;\n\n #ifdef MOD_AXIS_X\n // pos.x+=MOD_dis;\n mMatrix[3][0] += MOD_dis.x;\n #endif\n #ifdef MOD_AXIS_Y\n // pos.y+=MOD_dis;\n mMatrix[3][1] += MOD_dis.y;\n #endif\n #ifdef MOD_AXIS_Z\n // pos.z+=MOD_dis;\n mMatrix[3][2] += MOD_dis.z;\n #endif\n #endif\n\n #ifdef MOD_MODE_SCALE\n MOD_dis*=MOD_strength;\n MOD_dis+=MOD_min;\n\n #ifdef MOD_ABS\n MOD_dis=abs(MOD_dis);\n #endif\n\n #ifdef MOD_AXIS_X\n pos.x*=MOD_dis.x;\n #endif\n #ifdef MOD_AXIS_Y\n pos.y*=MOD_dis.y;\n #endif\n #ifdef MOD_AXIS_Z\n pos.z*=MOD_dis.z;\n #endif\n #endif\n\n #ifdef MOD_MODE_ROT\n #define MOD_PI 3.14159265358\n MOD_dis*=MOD_strength;\n MOD_dis+=MOD_min;\n\n #ifdef MOD_AXIS_X\n pos*=MOD_rot(vec3(1.0,0.0,0.0), MOD_dis.x*3.14);\n norm=((vec4(norm,0.0)*MOD_rot(vec3(1.0,0.0,0.0), MOD_dis.x*MOD_PI)).xyz);\n #endif\n #ifdef MOD_AXIS_Y\n pos*=MOD_rot(vec3(0.0,1.0,0.0), MOD_dis.y*MOD_PI);\n norm=((vec4(norm,0.0)*MOD_rot(vec3(0.0,1.0,0.0), MOD_dis.y*MOD_PI)).xyz);\n #endif\n #ifdef MOD_AXIS_Z\n pos*=MOD_rot(vec3(0.0,0.0,1.0), MOD_dis.z*MOD_PI);\n norm=((vec4(norm,0.0)*MOD_rot(vec3(0.0,0.0,1.0), MOD_dis.z*MOD_PI)).xyz);\n #endif\n\n norm=normalize(norm);\n #endif\n\n#endif\n","displace_head_vert":"\n#ifdef MOD_COLORIZE\nOUT vec3 MOD_dispColor;\n#endif\n\n\n\n#ifdef MOD_MODE_ROT\n\n mat4 MOD_rot(vec3 axis, float angle)\n {\n axis = normalize(axis);\n float s = sin(angle);\n float c = cos(angle);\n float oc = 1.0 - c;\n\n return mat4(\n \t\toc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0,\n oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0,\n oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0,\n \t\t0.0, 0.0, 0.0, 1.0\n \t);\n }\n\n#endif",}; +const + inTrigger = op.inTrigger("Trigger"), + inTex = op.inTexture("Texture"), + inSrc = op.inSwitch("Source", ["Model Pos", "Inst Pos"], "Model Pos"), + inMode = op.inSwitch("Mode", ["Translate", "Scale", "Rotate"], "Translate"), + inStrength = op.inFloat("Strength", 1), + inMin = op.inFloat("Min", 0), + inScale = op.inFloat("Scale", 1), + inClamp = op.inBool("Clamp", false), + inColorize = op.inBool("Colorize", false), + inDebug = op.inBool("Debug Bounds", false), + inNormalize = op.inBool("Normalize", false), + inOffsetX = op.inFloat("Offset X", 0), + inOffsetY = op.inFloat("Offset Y", 0), + inAbs = op.inBool("Abs", false), + inChannel = op.inSwitch("Channel", ["R", "G", "B", "RGB"], "R"), + + inAxisX = op.inBool("X", false), + inAxisY = op.inBool("Y", false), + inAxisZ = op.inBool("Z", true), + + next = op.outTrigger("Next"); + +inAxisX.onChange = +inTex.onChange = + inAxisY.onChange = + inAxisZ.onChange = + inClamp.onChange = + inMode.onChange = + inNormalize.onChange = + inDebug.onChange = + inChannel.onChange = + inAbs.onChange = + inColorize.onChange = updateDefines; +inTrigger.onTriggered = render; + +const cgl = op.patch.cgl; + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "title": op.name, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": attachments.displace_head_vert || "", + "srcBodyVert": attachments.displace_vert || "" +}); + +mod.addModule({ + "title": op.name, + "name": "MODULE_COLOR", + "srcHeadFrag": "#ifdef MOD_COLORIZE\nIN vec3 MOD_dispColor;\n#endif", + "srcBodyFrag": "#ifdef MOD_COLORIZE\ncol.rgb*=MOD_dispColor;\n#endif" +}); + +mod.addUniformVert("t", "MOD_texture", 0); +mod.addUniformVert("2f", "MOD_offset", inOffsetX, inOffsetY); +mod.addUniformVert("f", "MOD_scale", inScale); +mod.addUniformVert("f", "MOD_strength", inStrength); +mod.addUniformVert("f", "MOD_min", inMin); +updateDefines(); + +function updateDefines() +{ + op.setUiAttrib({ "extendTitle": inMode.get() }); + + mod.toggleDefine("MOD_MODE_TRANS", inMode.get() === "Translate"); + mod.toggleDefine("MOD_MODE_SCALE", inMode.get() === "Scale"); + mod.toggleDefine("MOD_MODE_ROT", inMode.get() === "Rotate"); + + mod.toggleDefine("MOD_CHAN_R", inChannel.get() != "G" && inChannel.get() != "B" && inChannel.get() != "RGB"); + mod.toggleDefine("MOD_CHAN_G", inChannel.get() == "G"); + mod.toggleDefine("MOD_CHAN_B", inChannel.get() == "B"); + mod.toggleDefine("MOD_CHAN_RGB", inChannel.get() == "RGB"); + + mod.toggleDefine("MOD_SRC_INSTMAT", inSrc.get() == "Inst Pos"); + mod.toggleDefine("MOD_SRC_MMAT", inSrc.get() == "Model Pos"); + + mod.toggleDefine("MOD_AXIS_X", inAxisX.get()); + mod.toggleDefine("MOD_AXIS_Y", inAxisY.get()); + mod.toggleDefine("MOD_AXIS_Z", inAxisZ.get()); + + mod.toggleDefine("MOD_ABS", inAbs.get()); + + mod.toggleDefine("MOD_CLAMP", inClamp.get()); + mod.toggleDefine("MOD_COLORIZE", inColorize.get() || inDebug.get()); + mod.toggleDefine("MOD_NORMALIZE", inNormalize.get()); + + mod.toggleDefine("MOD_DEBUG", inDebug.get()); +} + +function render() +{ + mod.bind(); + + if (inTex.get()) mod.pushTexture("MOD_texture", inTex.get().tex); + else mod.pushTexture("MOD_texture", CGL.Texture.getEmptyTexture(cgl).tex); + + next.trigger(); + mod.unbind(); +} + + +}; + +Ops.Gl.ShaderEffects.InstancedDisplacementMap_v2.prototype = new CABLES.Op(); +CABLES.OPS["e6ba9d95-20f3-4c1c-9967-26d48d278f0a"]={f:Ops.Gl.ShaderEffects.InstancedDisplacementMap_v2,objName:"Ops.Gl.ShaderEffects.InstancedDisplacementMap_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.InstancedPerlinPosition_v2 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.InstancedPerlinPosition_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"perlin_instposition_vert":"\nfloat MOD_Interpolation_C2( float x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); } // 6x^5-15x^4+10x^3\t( Quintic Curve. As used by Perlin in Improved Noise. http://mrl.nyu.edu/~perlin/paper445.pdf )\nvec2 MOD_Interpolation_C2( vec2 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec3 MOD_Interpolation_C2( vec3 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 MOD_Interpolation_C2( vec4 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 MOD_Interpolation_C2_InterpAndDeriv( vec2 x ) { return x.xyxy * x.xyxy * ( x.xyxy * ( x.xyxy * ( x.xyxy * vec2( 6.0, 0.0 ).xxyy + vec2( -15.0, 30.0 ).xxyy ) + vec2( 10.0, -60.0 ).xxyy ) + vec2( 0.0, 30.0 ).xxyy ); }\nvec3 MOD_Interpolation_C2_Deriv( vec3 x ) { return x * x * (x * (x * 30.0 - 60.0) + 30.0); }\n\n\nvoid MOD_FAST32_hash_3D( \tvec3 gridcell,\n out vec4 lowz_hash_0,\n out vec4 lowz_hash_1,\n out vec4 lowz_hash_2,\n out vec4 highz_hash_0,\n out vec4 highz_hash_1,\n out vec4 highz_hash_2\t)\t\t//\tgenerates 3 random numbers for each of the 8 cell corners\n{\n // gridcell is assumed to be an integer coordinate\n\n //\tTODO: \tthese constants need tweaked to find the best possible noise.\n //\t\t\tprobably requires some kind of brute force computational searching or something....\n const vec2 OFFSET = vec2( 50.0, 161.0 );\n const float DOMAIN = 69.0;\n const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );\n const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );\n\n //\ttruncate the domain\n gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;\n vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );\n\n //\tcalculate the noise\n vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;\n P *= P;\n P = P.xzxz * P.yyww;\n vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );\n vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );\n lowz_hash_0 = fract( P * lowz_mod.xxxx );\n highz_hash_0 = fract( P * highz_mod.xxxx );\n lowz_hash_1 = fract( P * lowz_mod.yyyy );\n highz_hash_1 = fract( P * highz_mod.yyyy );\n lowz_hash_2 = fract( P * lowz_mod.zzzz );\n highz_hash_2 = fract( P * highz_mod.zzzz );\n}\n\n//\n//\tPerlin Noise 3D ( gradient noise )\n//\tReturn value range of -1.0->1.0\n//\thttp://briansharpe.files.wordpress.com/2011/11/perlinsample.jpg\n//\nfloat MOD_Perlin3D( vec3 P )\n{\n //\testablish our grid cell and unit position\n vec3 Pi = floor(P);\n vec3 Pf = P - Pi;\n vec3 Pf_min1 = Pf - 1.0;\n\n#if 1\n //\n //\tclassic noise.\n //\trequires 3 random values per point. with an efficent hash function will run faster than improved noise\n //\n\n //\tcalculate the hash.\n //\t( various hashing methods listed in order of speed )\n vec4 hashx0, hashy0, hashz0, hashx1, hashy1, hashz1;\n MOD_FAST32_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n //SGPP_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n\n //\tcalculate the gradients\n vec4 grad_x0 = hashx0 - 0.49999;\n vec4 grad_y0 = hashy0 - 0.49999;\n vec4 grad_z0 = hashz0 - 0.49999;\n vec4 grad_x1 = hashx1 - 0.49999;\n vec4 grad_y1 = hashy1 - 0.49999;\n vec4 grad_z1 = hashz1 - 0.49999;\n vec4 grad_results_0 = inversesqrt( grad_x0 * grad_x0 + grad_y0 * grad_y0 + grad_z0 * grad_z0 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x0 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y0 + Pf.zzzz * grad_z0 );\n vec4 grad_results_1 = inversesqrt( grad_x1 * grad_x1 + grad_y1 * grad_y1 + grad_z1 * grad_z1 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x1 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y1 + Pf_min1.zzzz * grad_z1 );\n\n#if 1\n //\tClassic Perlin Interpolation\n vec3 blend = MOD_Interpolation_C2( Pf );\n vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n float final = dot( res0, blend2.zxzx * blend2.wwyy );\n final *= 1.1547005383792515290182975610039;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range *= 1.0/sqrt(0.75)\n return final;\n#else\n //\tClassic Perlin Surflet\n //\thttp://briansharpe.wordpress.com/2012/03/09/modifications-to-classic-perlin-noise/\n Pf *= Pf;\n Pf_min1 *= Pf_min1;\n vec4 vecs_len_sq = vec4( Pf.x, Pf_min1.x, Pf.x, Pf_min1.x ) + vec4( Pf.yy, Pf_min1.yy );\n float final = dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf.zzzz ) ), grad_results_0 ) + dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf_min1.zzzz ) ), grad_results_1 );\n final *= 2.3703703703703703703703703703704;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range *= 1.0/cube(0.75)\n return final;\n#endif\n\n#else\n //\n //\timproved noise.\n //\trequires 1 random value per point. Will run faster than classic noise if a slow hashing function is used\n //\n\n //\tcalculate the hash.\n //\t( various hashing methods listed in order of speed )\n vec4 hash_lowz, hash_highz;\n MOD_FAST32_hash_3D( Pi, hash_lowz, hash_highz );\n //BBS_hash_3D( Pi, hash_lowz, hash_highz );\n //SGPP_hash_3D( Pi, hash_lowz, hash_highz );\n\n //\n //\t\"improved\" noise using 8 corner gradients. Faster than the 12 mid-edge point method.\n //\tKen mentions using diagonals like this can cause \"clumping\", but we'll live with that.\n //\t[1,1,1] [-1,1,1] [1,-1,1] [-1,-1,1]\n //\t[1,1,-1] [-1,1,-1] [1,-1,-1] [-1,-1,-1]\n //\n hash_lowz -= 0.5;\n vec4 grad_results_0_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_lowz );\n hash_lowz = abs( hash_lowz ) - 0.25;\n vec4 grad_results_0_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_lowz );\n vec4 grad_results_0_2 = Pf.zzzz * sign( abs( hash_lowz ) - 0.125 );\n vec4 grad_results_0 = grad_results_0_0 + grad_results_0_1 + grad_results_0_2;\n\n hash_highz -= 0.5;\n vec4 grad_results_1_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_highz );\n hash_highz = abs( hash_highz ) - 0.25;\n vec4 grad_results_1_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_highz );\n vec4 grad_results_1_2 = Pf_min1.zzzz * sign( abs( hash_highz ) - 0.125 );\n vec4 grad_results_1 = grad_results_1_0 + grad_results_1_1 + grad_results_1_2;\n\n //\tblend the gradients and return\n vec3 blend = MOD_Interpolation_C2( Pf );\n vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n return dot( res0, blend2.zxzx * blend2.wwyy ) * (2.0 / 3.0);\t//\t(optionally) mult by (2.0/3.0) to scale to a strict -1.0->1.0 range\n#endif\n}\n\nvec4 MOD_deform(mat4 mMatrix,mat4 instMat,vec4 pos)\n{\n\n vec3 ppos=vec3(mMatrix[3][0]+instMat[3][0]*MOD_scale+MOD_scrollx,mMatrix[3][1]+instMat[3][1]*MOD_scale+MOD_scrolly,mMatrix[3][2]+instMat[3][2]*MOD_scale+MOD_scrollz);\n float p=MOD_Perlin3D(ppos)*MOD_strength;\n\n #ifdef MOD_METH_TRANSLATE\n pos.x+=p*MOD_mulAxis.x;\n pos.y+=p*MOD_mulAxis.y;\n pos.z+=p*MOD_mulAxis.z;\n #endif\n #ifdef MOD_METH_SCALE\n p=clamp(p,0.0,99999.0);\n pos.x*=p*MOD_mulAxis.x+MOD_minScale;\n pos.y*=p*MOD_mulAxis.y+MOD_minScale;\n pos.z*=p*MOD_mulAxis.z+MOD_minScale;\n #endif\n\n return pos;\n}\n\n",}; +const + render = op.inTrigger("Render"), + next = op.outTrigger("Next"), + inStrength = op.inValue("Strength", 1), + scrollx = op.inValue("Scroll X"), + scrolly = op.inValue("Scroll Y"), + scrollz = op.inValue("Scroll Z"), + scale = op.inValue("Scale", 1), + meth = op.inSwitch("Method", ["Translate", "Scale"], "Translate"), + mulx = op.inValue("Mul X", 1), + muly = op.inValue("Mul Y", 1), + mulz = op.inValue("Mul Z", 1), + minScale = op.inValue("Min Scale", 0), + inWorldSpace = op.inValueBool("WorldSpace"); + +const cgl = op.patch.cgl; + +let srcBodyVert = "" + .endl() + "#ifdef INSTANCING" + .endl() + " pos=MOD_deform(mMatrix,instMat,pos);" + .endl() + "#endif" + .endl() + "#ifndef INSTANCING" + .endl() + " pos=MOD_deform(mMatrix,mMatrix,pos);" + .endl() + "#endif" + + .endl(); + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": attachments.perlin_instposition_vert, + "srcBodyVert": srcBodyVert +}); + +mod.addUniform("f", "MOD_strength", inStrength); +mod.addUniform("f", "MOD_scrollx", scrollx); +mod.addUniform("f", "MOD_scrolly", scrolly); +mod.addUniform("f", "MOD_scrollz", scrollz); +mod.addUniform("f", "MOD_scale", scale); +mod.addUniform("f", "MOD_minScale", minScale); +mod.addUniform("3f", "MOD_mulAxis", mulx, muly, mulz); + +meth.onChange = +inWorldSpace.onChange = updateDefines; +updateDefines(); + +function updateDefines() +{ + mod.toggleDefine("MOD_WORLDSPACE", inWorldSpace.get()); + mod.toggleDefine("MOD_METH_TRANSLATE", meth.get() == "Translate"); + mod.toggleDefine("MOD_METH_SCALE", meth.get() == "Scale"); +} + +render.onTriggered = function () +{ + mod.bind(); + next.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.ShaderEffects.InstancedPerlinPosition_v2.prototype = new CABLES.Op(); +CABLES.OPS["716a9004-cbb8-4032-9f29-2b2f8c8973ba"]={f:Ops.Gl.ShaderEffects.InstancedPerlinPosition_v2,objName:"Ops.Gl.ShaderEffects.InstancedPerlinPosition_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.InstancedTextureColorize +// +// ************************************************************** + +Ops.Gl.ShaderEffects.InstancedTextureColorize = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"colorize_frag":"\n\n\n\nvec4 MOD_col=texture(MOD_texture,MOD_coord);\n\n#ifdef METH_ADD\ncol.rgb+=MOD_col.rgb*MOD_strength;\n#endif\n#ifdef METH_MUL\ncol.rgb*=MOD_col.rgb*MOD_strength;\n#endif\n\n#ifdef MOD_DEBUG\n col.rg=mod(MOD_coord,1.0).rg;\n#endif\n","colorize_head_frag":"\nIN vec2 MOD_coord;\n\nUNI sampler2D MOD_texture;\nUNI float MOD_strength;","displace_vert":"\n#ifdef INSTANCING\n\n vec3 MOD_p=vec3(mMatrix[3][0],mMatrix[3][1],mMatrix[3][2]);\n MOD_coord=MOD_p.xy*(1.0/MOD_scale)+MOD_offset-vec2(0.5,0.5);\n\n#endif\n\n","displace_head_vert":"OUT vec2 MOD_coord;\n\n",}; +const + inTrigger = op.inTrigger("Trigger"), + inTex = op.inTexture("Texture"), + inStrength = op.inFloatSlider("Strength", 1), + inScale = op.inFloat("Scale", 1), + inClamp = op.inBool("Clamp", false), + inDebug = op.inBool("Debug Bounds", false), + inOffsetX = op.inFloat("Offset X", 0), + inOffsetY = op.inFloat("Offset Y", 0), + inMode = op.inSwitch("Method", ["Add", "Mul"], "Add"), + next = op.outTrigger("Next"); + +inTex.onChange = + inClamp.onChange = + inMode.onChange = + inDebug.onChange = updateDefines; +inTrigger.onTriggered = render; + +const cgl = op.patch.cgl; + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "title": op.name, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": attachments.displace_head_vert || "", + "srcBodyVert": attachments.displace_vert || "" +}); + +mod.addModule({ + "title": op.name, + "name": "MODULE_COLOR", + "srcHeadFrag": attachments.colorize_head_frag, + "srcBodyFrag": attachments.colorize_frag +}); + +mod.addUniformVert("t", "MOD_texture", 0); +mod.addUniformVert("2f", "MOD_offset", inOffsetX, inOffsetY); +mod.addUniformVert("f", "MOD_scale", inScale); +mod.addUniformVert("f", "MOD_strength", inStrength); + +function updateDefines() +{ + mod.toggleDefine("MOD_CLAMP", inClamp.get()); + mod.toggleDefine("MOD_DEBUG", inDebug.get()); + mod.toggleDefine("METH_ADD", inMode.get() == "Add"); + mod.toggleDefine("METH_MUL", inMode.get() == "Mul"); +} + +function render() +{ + mod.bind(); + + if (inTex.get()) mod.pushTexture("MOD_texture", inTex.get().tex); + else mod.pushTexture("MOD_texture", CGL.Texture.getEmptyTexture(cgl).tex); + + next.trigger(); + mod.unbind(); +} + + +}; + +Ops.Gl.ShaderEffects.InstancedTextureColorize.prototype = new CABLES.Op(); +CABLES.OPS["7a13a699-6a7f-4fd1-84bb-51dd6c13c820"]={f:Ops.Gl.ShaderEffects.InstancedTextureColorize,objName:"Ops.Gl.ShaderEffects.InstancedTextureColorize"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.LimitMeshByTexCoord +// +// ************************************************************** + +Ops.Gl.ShaderEffects.LimitMeshByTexCoord = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"limitByTexCoords_frag":"\nfloat MOD_offset=0.0;\n\n#ifdef MOD_ANIN_SIN\n #ifdef MOD_ANIN_SIN_TCX\n MOD_offset=sin((texCoord.x)*MOD_freq+MOD_time)*(MOD_ampl/1000.0);\n #endif\n #ifdef MOD_ANIN_SIN_TCY\n MOD_offset=sin((texCoord.y)*MOD_freq+MOD_time)*(MOD_ampl/1000.0);\n #endif\n#endif\n\n#ifdef MOD_AXIS_X\n if(texCoord.x+MOD_offset>=MOD_treshhold)discard;\n#endif\n#ifdef MOD_AXIS_Y\n if(texCoord.y+MOD_offset>=MOD_treshhold)discard;\n#endif\n#ifdef MOD_AXIS_XY\n if((texCoord.y+texCoord.x)/2.0+MOD_offset>=MOD_treshhold)discard;\n#endif\n#ifdef MOD_AXIS_X_INV\n if(1.0-texCoord.x+MOD_offset>=MOD_treshhold)discard;\n#endif\n#ifdef MOD_AXIS_Y_INV\n if(1.0-texCoord.y+MOD_offset>=MOD_treshhold)discard;\n#endif\n#ifdef MOD_AXIS_XY_INV\n if(1.0-((texCoord.y+texCoord.x)/2.0)+MOD_offset>=MOD_treshhold)discard;\n#endif\n\n\n",}; +op.render = op.inTrigger("render"); +op.trigger = op.outTrigger("trigger"); + +const axis = op.inValueSelect("Axis", ["X", "Y", "XY", "X Inverted", "Y Inverted", "XY Inverted"], "X"); +const inTreshhold = op.inValueSlider("treshhold", 0.3); + +const inSinAnim = op.inValueBool("Sine Animation", false); +const inTime = op.inValueFloat("Time"); +const inSinAxis = op.inValueSelect("Sine Source", ["Texcoord X", "Texcoord Y"], "Texcoord X"); + +const inFreq = op.inValueFloat("Frequency", 10); +const inAmpl = op.inValueFloat("Amplitude", 10); + +op.setPortGroup("Sine Animation", [inTime, inSinAnim, inFreq, inAmpl, inSinAxis]); + +const cgl = op.patch.cgl; +let shader = null; + +let srcHeadFrag = "" + .endl() + "UNI float MOD_treshhold;" + .endl() + "UNI float MOD_time;" + .endl() + "UNI float MOD_ampl;" + .endl() + "UNI float MOD_freq;" + .endl(); + +let moduleFrag = null; + +inSinAxis.onChange = inSinAnim.onChange = axis.onChange = updateAxis; + +function updateAxis() +{ + if (!shader) return; + shader.toggleDefine(moduleFrag.prefix + "AXIS_X", axis.get() == "X"); + shader.toggleDefine(moduleFrag.prefix + "AXIS_Y", axis.get() == "Y"); + shader.toggleDefine(moduleFrag.prefix + "AXIS_XY", axis.get() == "XY"); + shader.toggleDefine(moduleFrag.prefix + "AXIS_X_INV", axis.get() == "X Inverted"); + shader.toggleDefine(moduleFrag.prefix + "AXIS_Y_INV", axis.get() == "Y Inverted"); + shader.toggleDefine(moduleFrag.prefix + "AXIS_XY_INV", axis.get() == "XY Inverted"); + + shader.toggleDefine(moduleFrag.prefix + "ANIN_SIN", inSinAnim.get()); + + shader.toggleDefine(moduleFrag.prefix + "ANIN_SIN_TCX", inSinAxis.get() == "Texcoord X"); + shader.toggleDefine(moduleFrag.prefix + "ANIN_SIN_TCY", inSinAxis.get() == "Texcoord Y"); +} + +function removeModule() +{ + if (shader && moduleFrag) shader.removeModule(moduleFrag); + shader = null; +} + +op.render.onLinkChanged = removeModule; +let + uniTime = null, + uniFreq = null, + uniAmpl = null, + uniTreshhold = null; + +op.render.onTriggered = function () +{ + if (!cgl.getShader()) + { + op.trigger.trigger(); + return; + } + + if (cgl.getShader() != shader) + { + if (shader) removeModule(); + shader = cgl.getShader(); + + moduleFrag = shader.addModule( + { + "title": op.objName, + "name": "MODULE_COLOR", + "srcHeadFrag": srcHeadFrag, + "srcBodyFrag": attachments.limitByTexCoords_frag || "" + }); + + uniTreshhold = new CGL.Uniform(shader, "f", moduleFrag.prefix + "treshhold", inTreshhold); + uniTime = new CGL.Uniform(shader, "f", moduleFrag.prefix + "time", inTime); + uniFreq = new CGL.Uniform(shader, "f", moduleFrag.prefix + "freq", inFreq); + uniAmpl = new CGL.Uniform(shader, "f", moduleFrag.prefix + "ampl", inAmpl); + + updateAxis(); + } + + if (!shader) return; + + op.trigger.trigger(); +}; + + +}; + +Ops.Gl.ShaderEffects.LimitMeshByTexCoord.prototype = new CABLES.Op(); +CABLES.OPS["b7482d75-913d-4564-92ae-81f8dbead3ce"]={f:Ops.Gl.ShaderEffects.LimitMeshByTexCoord,objName:"Ops.Gl.ShaderEffects.LimitMeshByTexCoord"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.MeshPixelNoise_v2 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.MeshPixelNoise_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"pixelnoise_frag":"IN vec4 MOD_pos;\n\nfloat MOD_mod289(float x){return x - floor(x * (1.0 / 289.0)) * 289.0;}\nvec4 MOD_mod289(vec4 x){return x - floor(x * (1.0 / 289.0)) * 289.0;}\nvec4 MOD_perm(vec4 x){return MOD_mod289(((x * 34.0) + 1.0) * x);}\n\nfloat MOD_meshPixelNoise(vec3 p){\n p+=vec3(MOD_x,MOD_y,MOD_z);\n vec3 a = floor(p);\n vec3 d = p - a;\n d = d * d * (3.0 - 2.0 * d);\n\n vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0);\n vec4 k1 = MOD_perm(b.xyxy);\n vec4 k2 = MOD_perm(k1.xyxy + b.zzww);\n\n vec4 c = k2 + a.zzzz;\n vec4 k3 = MOD_perm(c);\n vec4 k4 = MOD_perm(c + 1.0);\n\n vec4 o1 = fract(k3 * (1.0 / 41.0));\n vec4 o2 = fract(k4 * (1.0 / 41.0));\n\n vec4 o3 = o2 * d.z + o1 * (1.0 - d.z);\n vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x);\n\n return o4.y * d.y + o4.x * (1.0 - d.y);\n}\n",}; +const + render = op.inTrigger("render"), + next = op.outTrigger("trigger"), + inScale = op.inValue("Scale", 10), + inAmount = op.inValueSlider("Amount", 0.3), + inBlend = op.inSwitch("Blendmode", ["Sub", "Add", "Mul"], "Sub"), + inWorldSpace = op.inValueBool("WorldSpace"), + r = op.inValueSlider("r", 0), + g = op.inValueSlider("g", 0), + b = op.inValueSlider("b", 0), + x = op.inFloat("x", 0), + y = op.inFloat("y", 0), + z = op.inFloat("z", 0); + +r.setUiAttribs({ "colorPick": true }); + +op.setPortGroup("Color", [r, g, b]); +op.setPortGroup("Position", [x, y, z]); +const cgl = op.patch.cgl; + +inBlend.onChange = +inWorldSpace.onChange = updateDefines; + +const srcHeadVert = "" + .endl() + "OUT vec4 MOD_pos;" + .endl(); + +const srcBodyVert = "" + .endl() + "#ifndef MOD_WORLDSPACE" + .endl() + " MOD_pos=vec4(pos.xyz,1.0);" + .endl() + "#endif" + .endl() + "#ifdef MOD_WORLDSPACE" + .endl() + " MOD_pos=vec4(pos.xyz,1.0)*mMatrix;" + .endl() + "#endif" + .endl(); + +const srcHeadFrag = attachments.pixelnoise_frag; + +const srcBodyFrag = "" + .endl() + "vec3 MOD_rndVal = vec3(1.-MOD_r,1.-MOD_g,1.-MOD_b)*MOD_meshPixelNoise(MOD_pos.xyz*MOD_scale)*MOD_amount/4.0;" + + .endl() + "#ifdef MOD_BLEND_MUL" + .endl() + " col.rgb *= MOD_rndVal;" + .endl() + "#endif" + .endl() + "#ifdef MOD_BLEND_SUB" + .endl() + " col.rgb -= MOD_rndVal;" + .endl() + "#endif" + .endl() + "#ifdef MOD_BLEND_ADD" + .endl() + " col.rgb += MOD_rndVal;" + .endl() + "#endif" + .endl(); + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "title": op.name, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": srcHeadVert, + "srcBodyVert": srcBodyVert +}); + +mod.addModule({ + "title": op.name, + "name": "MODULE_COLOR", + "srcHeadFrag": attachments.pixelnoise_frag, + "srcBodyFrag": srcBodyFrag +}); + +mod.addUniformFrag("f", "MOD_scale", inScale); +mod.addUniformFrag("f", "MOD_amount", inAmount); +mod.addUniformFrag("f", "MOD_r", r); +mod.addUniformFrag("f", "MOD_g", g); +mod.addUniformFrag("f", "MOD_b", b); +mod.addUniformFrag("f", "MOD_x", x); +mod.addUniformFrag("f", "MOD_y", y); +mod.addUniformFrag("f", "MOD_z", z); +updateDefines(); + +function updateDefines() +{ + mod.toggleDefine("MOD_WORLDSPACE", inWorldSpace.get()); + + mod.toggleDefine("MOD_BLEND_ADD", inBlend.get() == "Add"); + mod.toggleDefine("MOD_BLEND_SUB", inBlend.get() == "Sub"); + mod.toggleDefine("MOD_BLEND_MUL", inBlend.get() == "Mul"); +} + +render.onTriggered = function () +{ + mod.bind(); + next.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.ShaderEffects.MeshPixelNoise_v2.prototype = new CABLES.Op(); +CABLES.OPS["f6240484-56b5-4bb8-92e6-ead30431771a"]={f:Ops.Gl.ShaderEffects.MeshPixelNoise_v2,objName:"Ops.Gl.ShaderEffects.MeshPixelNoise_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.ModuloVertexPosition +// +// ************************************************************** + +Ops.Gl.ShaderEffects.ModuloVertexPosition = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"trans_vert":"\n#ifdef MOD_AXIS_X\npos.x=mod(pos.x,MOD_modulo);\n#endif\n\n#ifdef MOD_AXIS_Y\npos.y=mod(pos.y,MOD_modulo);\n#endif\n\n#ifdef MOD_AXIS_Z\npos.z=mod(pos.z,MOD_modulo);\n#endif",}; +const + render = op.inTrigger("render"), + axis = op.inValueSelect("Axis", ["X", "Y", "Z"], "X"), + inModu = op.inFloat("Modulo", 1), + trigger = op.outTrigger("Trigger"); + +const cgl = op.patch.cgl; +const mod = new CGL.ShaderModifier(cgl, op.name); + +mod.addModule({ + "name": "MODULE_VERTEX_POSITION", + "srcBodyVert": attachments.trans_vert || "" +}); + +mod.addUniformVert("f", "MOD_modulo", inModu); + +axis.onChange = updateDefines; + +updateDefines(); + +function updateDefines() +{ + mod.toggleDefine("MOD_AXIS_X", axis.get() == "X"); + mod.toggleDefine("MOD_AXIS_Y", axis.get() == "Y"); + mod.toggleDefine("MOD_AXIS_Z", axis.get() == "Z"); +} + +render.onTriggered = function () +{ + mod.bind(); + trigger.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.ShaderEffects.ModuloVertexPosition.prototype = new CABLES.Op(); +CABLES.OPS["5b657c67-2d43-43b7-855d-76c8aad90a0d"]={f:Ops.Gl.ShaderEffects.ModuloVertexPosition,objName:"Ops.Gl.ShaderEffects.ModuloVertexPosition"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.PerlinAreaDeform_v4 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.PerlinAreaDeform_v4 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"perlindeform_vert":"vec3 MOD_newTangent,MOD_newBiTangent;\n\n#ifndef PERLINDEFORM\n#define PERLINDEFORM\nfloat Interpolation_C2( float x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); } // 6x^5-15x^4+10x^3\t( Quintic Curve. As used by Perlin in Improved Noise. http://mrl.nyu.edu/~perlin/paper445.pdf )\nvec2 Interpolation_C2( vec2 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec3 Interpolation_C2( vec3 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2( vec4 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2_InterpAndDeriv( vec2 x ) { return x.xyxy * x.xyxy * ( x.xyxy * ( x.xyxy * ( x.xyxy * vec2( 6.0, 0.0 ).xxyy + vec2( -15.0, 30.0 ).xxyy ) + vec2( 10.0, -60.0 ).xxyy ) + vec2( 0.0, 30.0 ).xxyy ); }\nvec3 Interpolation_C2_Deriv( vec3 x ) { return x * x * (x * (x * 30.0 - 60.0) + 30.0); }\n\n\nvoid FAST32_hash_3D( \tvec3 gridcell,\n out vec4 lowz_hash_0,\n out vec4 lowz_hash_1,\n out vec4 lowz_hash_2,\n out vec4 highz_hash_0,\n out vec4 highz_hash_1,\n out vec4 highz_hash_2\t)\t\t//\tgenerates 3 random numbers for each of the 8 cell corners\n{\n // gridcell is assumed to be an integer coordinate\n\n //\tTODO: \tthese constants need tweaked to find the best possible noise.\n //\t\t\tprobably requires some kind of brute force computational searching or something....\n const vec2 OFFSET = vec2( 50.0, 161.0 );\n const float DOMAIN = 69.0;\n const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );\n const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );\n\n //\ttruncate the domain\n gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;\n vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );\n\n //\tcalculate the noise\n vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;\n P *= P;\n P = P.xzxz * P.yyww;\n vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );\n vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );\n lowz_hash_0 = fract( P * lowz_mod.xxxx );\n highz_hash_0 = fract( P * highz_mod.xxxx );\n lowz_hash_1 = fract( P * lowz_mod.yyyy );\n highz_hash_1 = fract( P * highz_mod.yyyy );\n lowz_hash_2 = fract( P * lowz_mod.zzzz );\n highz_hash_2 = fract( P * highz_mod.zzzz );\n}\n\n//\n//\tPerlin Noise 3D ( gradient noise )\n//\tReturn value range of -1.0->1.0\n//\thttp://briansharpe.files.wordpress.com/2011/11/perlinsample.jpg\n//\nfloat Perlin3D( vec3 P )\n{\n //\testablish our grid cell and unit position\n vec3 Pi = floor(P);\n vec3 Pf = P - Pi;\n vec3 Pf_min1 = Pf - 1.0;\n\n#if 1\n //\n //\tclassic noise.\n //\trequires 3 random values per point. with an efficent hash function will run faster than improved noise\n //\n\n //\tcalculate the hash.\n //\t( various hashing methods listed in order of speed )\n vec4 hashx0, hashy0, hashz0, hashx1, hashy1, hashz1;\n FAST32_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n //SGPP_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n\n //\tcalculate the gradients\n vec4 grad_x0 = hashx0 - 0.49999;\n vec4 grad_y0 = hashy0 - 0.49999;\n vec4 grad_z0 = hashz0 - 0.49999;\n vec4 grad_x1 = hashx1 - 0.49999;\n vec4 grad_y1 = hashy1 - 0.49999;\n vec4 grad_z1 = hashz1 - 0.49999;\n vec4 grad_results_0 = inversesqrt( grad_x0 * grad_x0 + grad_y0 * grad_y0 + grad_z0 * grad_z0 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x0 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y0 + Pf.zzzz * grad_z0 );\n vec4 grad_results_1 = inversesqrt( grad_x1 * grad_x1 + grad_y1 * grad_y1 + grad_z1 * grad_z1 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x1 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y1 + Pf_min1.zzzz * grad_z1 );\n\n#if 1\n //\tClassic Perlin Interpolation\n vec3 blend = Interpolation_C2( Pf );\n vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n float final = dot( res0, blend2.zxzx * blend2.wwyy );\n final *= 1.1547005383792515290182975610039;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range *= 1.0/sqrt(0.75)\n return final;\n#else\n //\tClassic Perlin Surflet\n //\thttp://briansharpe.wordpress.com/2012/03/09/modifications-to-classic-perlin-noise/\n Pf *= Pf;\n Pf_min1 *= Pf_min1;\n vec4 vecs_len_sq = vec4( Pf.x, Pf_min1.x, Pf.x, Pf_min1.x ) + vec4( Pf.yy, Pf_min1.yy );\n float final = dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf.zzzz ) ), grad_results_0 ) + dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf_min1.zzzz ) ), grad_results_1 );\n final *= 2.3703703703703703703703703703704;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range *= 1.0/cube(0.75)\n return final;\n#endif\n\n#else\n //\n //\timproved noise.\n //\trequires 1 random value per point. Will run faster than classic noise if a slow hashing function is used\n //\n\n //\tcalculate the hash.\n //\t( various hashing methods listed in order of speed )\n vec4 hash_lowz, hash_highz;\n FAST32_hash_3D( Pi, hash_lowz, hash_highz );\n //BBS_hash_3D( Pi, hash_lowz, hash_highz );\n //SGPP_hash_3D( Pi, hash_lowz, hash_highz );\n\n //\n //\t\"improved\" noise using 8 corner gradients. Faster than the 12 mid-edge point method.\n //\tKen mentions using diagonals like this can cause \"clumping\", but we'll live with that.\n //\t[1,1,1] [-1,1,1] [1,-1,1] [-1,-1,1]\n //\t[1,1,-1] [-1,1,-1] [1,-1,-1] [-1,-1,-1]\n //\n hash_lowz -= 0.5;\n vec4 grad_results_0_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_lowz );\n hash_lowz = abs( hash_lowz ) - 0.25;\n vec4 grad_results_0_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_lowz );\n vec4 grad_results_0_2 = Pf.zzzz * sign( abs( hash_lowz ) - 0.125 );\n vec4 grad_results_0 = grad_results_0_0 + grad_results_0_1 + grad_results_0_2;\n\n hash_highz -= 0.5;\n vec4 grad_results_1_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_highz );\n hash_highz = abs( hash_highz ) - 0.25;\n vec4 grad_results_1_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_highz );\n vec4 grad_results_1_2 = Pf_min1.zzzz * sign( abs( hash_highz ) - 0.125 );\n vec4 grad_results_1 = grad_results_1_0 + grad_results_1_1 + grad_results_1_2;\n\n //\tblend the gradients and return\n vec3 blend = Interpolation_C2( Pf );\n vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n return dot( res0, blend2.zxzx * blend2.wwyy ) * (2.0 / 3.0);\t//\t(optionally) mult by (2.0/3.0) to scale to a strict -1.0->1.0 range\n#endif\n}\n\n#endif\n\nvec3 MOD_deform(vec3 pos,vec3 norm)\n{\n vec3 modelPos=pos;\n vec3 forcePos=vec3(MOD_x,MOD_y,MOD_z);\n\n vec3 vecToOrigin=modelPos-forcePos;\n float dist=abs(length(vecToOrigin));\n // float distAlpha = (MOD_size - dist) / MOD_size;\n\n if(dist*MOD_mScale +{ + inOpacityThreshold.setUiAttribs({ "greyout": !inDiscardTransparent.get() }); + inAlphaMaskSource.setUiAttribs({ "greyout": !inDiscardTransparent.get() }); +}; + +inAlphaMaskSource.onChange = () => +{ + shadowShaderModule.toggleDefine("MOD_ALPHA_MASK_LUMINANCE", inAlphaMaskSource.get() === "Luminance"); + shadowShaderModule.toggleDefine("MOD_ALPHA_MASK_R", inAlphaMaskSource.get() === "R"); + shadowShaderModule.toggleDefine("MOD_ALPHA_MASK_G", inAlphaMaskSource.get() === "G"); + shadowShaderModule.toggleDefine("MOD_ALPHA_MASK_B", inAlphaMaskSource.get() === "B"); + shadowShaderModule.toggleDefine("MOD_ALPHA_MASK_A", inAlphaMaskSource.get() === "A"); +}; + +inReceiveShadow.onChange = () => +{ + inAlgorithm.setUiAttribs({ "greyout": !inReceiveShadow.get() }); + setAlgorithmGreyouts(); +}; + +inAlgorithm.onChange = () => +{ + const current = inAlgorithm.get(); + algorithms.forEach((alg) => shaderModule.toggleDefine("MODE_" + alg.toUpperCase(), alg === current)); + + setAlgorithmGreyouts(); +}; + +function setAlgorithmGreyouts() +{ + if (!inReceiveShadow.get()) + { + inSamples.setUiAttribs({ "greyout": true }); + inSpread.setUiAttribs({ "greyout": true }); + return; + } + + if (inAlgorithm.get() === "PCF" || inAlgorithm.get() === "Poisson") + { + inSamples.setUiAttribs({ "greyout": false }); + inSpread.setUiAttribs({ "greyout": false }); + } + else + { + inSamples.setUiAttribs({ "greyout": true }); + inSpread.setUiAttribs({ "greyout": true }); + } +} + +inSamples.onChange = () => +{ + shaderModule.define("SAMPLE_AMOUNT", "float(" + clamp(Number(inSamples.get()), 1, 16).toString() + ")"); +}; + +const outTrigger = op.outTrigger("Trigger Out"); + +const createVertexHead = (n, type) => +{ + if (type === "ambient") return ""; + if (type === "point") return attachments.shadow_head_point_vert.replace(LIGHT_INDEX_REGEX, n); + if (type === "spot") return attachments.shadow_head_spot_vert.replace(LIGHT_INDEX_REGEX, n); + if (type === "directional") return attachments.shadow_head_directional_vert.replace(LIGHT_INDEX_REGEX, n); +}; + +const createVertexBody = (n, type) => +{ + if (type === "ambient") return ""; + if (type === "point") return attachments.shadow_body_point_vert.replace(LIGHT_INDEX_REGEX, n); + if (type === "spot") return attachments.shadow_body_spot_vert.replace(LIGHT_INDEX_REGEX, n); + if (type === "directional") return attachments.shadow_body_directional_vert.replace(LIGHT_INDEX_REGEX, n); +}; + +const createFragmentHead = (n, type) => +{ + if (type === "ambient") return ""; + if (type === "point") return attachments.shadow_head_point_frag.replace(LIGHT_INDEX_REGEX, n); + if (type === "spot") return attachments.shadow_head_spot_frag.replace(LIGHT_INDEX_REGEX, n); + if (type === "directional") return attachments.shadow_head_directional_frag.replace(LIGHT_INDEX_REGEX, n); +}; + +const createFragmentBody = (n, type) => +{ + if (type === "ambient") return ""; + let fragmentCode = ""; + if (type === "spot") + { + fragmentCode = fragmentCode.concat(attachments.shadow_body_spot_frag.replace(LIGHT_INDEX_REGEX, n)); + } + else if (type === "directional") + { + fragmentCode = fragmentCode.concat(attachments.shadow_body_directional_frag.replace(LIGHT_INDEX_REGEX, n)); + } + else if (type === "point") + { + fragmentCode = fragmentCode.concat(attachments.shadow_body_point_frag.replace(LIGHT_INDEX_REGEX, n)); + } + + return fragmentCode; +}; + +const STATE = { + "lastLength": 0, + "updating": false +}; + +function renderShadowPassWithModule() +{ + if (inDiscardTransparent.get()) + { + if (inOpacityTexture.get()) + { + if (!shadowShaderModule.hasUniform("MOD_texOpacity")) + { + shadowShaderModule.addUniformFrag("t", "MOD_texOpacity", 0); + } + + if (!shadowShaderModule.hasDefine("MOD_HAS_TEXTURE_OPACITY")) shadowShaderModule.define("MOD_HAS_TEXTURE_OPACITY", ""); + shadowShaderModule.pushTexture("MOD_texOpacity", inOpacityTexture.get().tex); + } + else + { + if (shadowShaderModule.hasUniform("MOD_texOpacity")) + shadowShaderModule.removeUniform("MOD_texOpacity"); + + if (shadowShaderModule.hasDefine("MOD_HAS_TEXTURE_OPACITY")) shadowShaderModule.removeDefine("MOD_HAS_TEXTURE_OPACITY"); + } + + shadowShaderModule.bind(); + outTrigger.trigger(); + shadowShaderModule.unbind(); + } + else + { + outTrigger.trigger(); + } +} + +function createModuleShaders() +{ + STATE.updating = true; + removeUniforms(); + + let vertexHead = ""; + let fragmentHead = ""; + let vertexBody = ""; + let fragmentBody = ""; + + for (let i = 0; i < cgl.frameStore.lightStack.length; i += 1) + { + const light = cgl.frameStore.lightStack[i]; + vertexHead = vertexHead.concat(createVertexHead(i, light.type)); + vertexBody = vertexBody.concat(createVertexBody(i, light.type)); + + fragmentHead = fragmentHead.concat(createFragmentHead(i, light.type)); + fragmentBody = fragmentBody.concat(createFragmentBody(i, light.type, light.castShadow)); + } + + srcHeadVert = srcHeadVertBase.concat(vertexHead); + srcBodyVert = srcBodyVertBase.concat(vertexBody); + srcHeadFrag = srcHeadFragBase.concat(fragmentHead); + srcBodyFrag = srcBodyFragBase.concat(fragmentBody); + + shaderModule.removeModule(op.objName); + + shaderModule.addModule({ + "name": "MODULE_VERTEX_POSITION", + "title": op.objName, + // "priority": -2, + "srcHeadVert": srcHeadVert, + "srcBodyVert": srcBodyVert + }); + + shaderModule.addModule({ + "name": "MODULE_COLOR", + // "priority": -2, + "title": op.objName, + "srcHeadFrag": srcHeadFrag, + "srcBodyFrag": srcBodyFrag, + }); + + createUniforms(); +} + +// * SHADOW PASS MODULE * +const shadowShaderModule = new CGL.ShaderModifier(cgl, "shadowPassModifier_" + op.id); +shadowShaderModule.addModule({ + "name": "MODULE_COLOR", + // "priority": -2, + "title": op.objName + "shadowPass", + "srcHeadFrag": "", + "srcBodyFrag": ` + #ifdef MOD_HAS_TEXTURE_OPACITY + #ifdef MOD_ALPHA_MASK_LUMINANCE + outColor.a *= dot(vec3(0.2126,0.7152,0.0722), texture(MOD_texOpacity, texCoord).rgb); + #endif + #ifdef MOD_ALPHA_MASK_R + outColor.a *= texture(MOD_texOpacity, texCoord).r; + #endif + #ifdef MOD_ALPHA_MASK_G + outColor.a *= texture(MOD_texOpacity, texCoord).g; + #endif + #ifdef MOD_ALPHA_MASK_B + outColor.a *= texture(MOD_texOpacity, texCoord).b; + #endif + #ifdef MOD_ALPHA_MASK_A + outColor.a *= texture(MOD_texOpacity, texCoord).a; + #endif + if (outColor.a < MOD_inOpacityThreshold) discard; + #endif + ` +}); + +shadowShaderModule.addUniformFrag("f", "MOD_inOpacityThreshold", inOpacityThreshold); + +shadowShaderModule.toggleDefine("MOD_ALPHA_MASK_LUMINANCE", inAlphaMaskSource.get() === "Luminance"); +shadowShaderModule.toggleDefine("MOD_ALPHA_MASK_R", inAlphaMaskSource.get() === "R"); +shadowShaderModule.toggleDefine("MOD_ALPHA_MASK_G", inAlphaMaskSource.get() === "G"); +shadowShaderModule.toggleDefine("MOD_ALPHA_MASK_B", inAlphaMaskSource.get() === "B"); +shadowShaderModule.toggleDefine("MOD_ALPHA_MASK_A", inAlphaMaskSource.get() === "A"); + +const srcHeadVertBase = attachments.head_vert; +const srcBodyVertBase = ""; +const srcHeadFragBase = attachments.head_frag; +const srcBodyFragBase = ""; + +let srcHeadVert = srcHeadVertBase; +let srcBodyVert = srcBodyVertBase; +let srcHeadFrag = srcHeadFragBase; +let srcBodyFrag = srcBodyFragBase; + +// * MAIN PASS MODULE * +const shaderModule = new CGL.ShaderModifier(cgl, "shadowModule_" + op.id); +shaderModule.define("SAMPLE_AMOUNT", "float(" + clamp(Number(inSamples.get()), 1, 16).toString() + ")"); +shaderModule.toggleDefine("RECEIVE_SHADOW", inReceiveShadow); + +algorithms.forEach((alg) => shaderModule.toggleDefine("MODE_" + alg.toUpperCase(), alg === inAlgorithm.get())); + +const hasShadowMap = []; +const hasShadowCubemap = []; + +function removeUniforms() +{ + for (let i = 0; i < STATE.lastLength; i += 1) + { + shaderModule.removeUniformStruct("MOD_light" + i); + shaderModule.removeUniform("MOD_shadowMap" + i); + shaderModule.removeUniform("MOD_shadowMapCube" + i); + shaderModule.removeUniform("MOD_normalOffset" + i); + shaderModule.removeUniform("MOD_lightMatrix" + i); + shaderModule.removeDefine("HAS_SHADOW_MAP_" + i); + } + + if (STATE.lastLength > 0) + { + shaderModule.removeUniform("MOD_sampleSpread"); + shaderModule.removeUniform("MOD_camPos"); + } + hasShadowMap.length = 0; + hasShadowCubemap.length = 0; +} + +function createUniforms() +{ + for (let i = 0; i < cgl.frameStore.lightStack.length; i += 1) + { + const light = cgl.frameStore.lightStack[i]; + + shaderModule.addUniformStructFrag("MOD_Light", "MOD_light" + i, [ + { "type": "3f", "name": "position", "v1": null }, + { "type": "2i", "name": "typeCastShadow", "v1": null }, + { "type": "4f", "name": "shadowProperties", "v1": [light.nearFar[0], light.nearFar[1], 512, light.shadowBias] }, + { "type": "f", "name": "shadowStrength", "v1": light.shadowStrength }, + ]); + + hasShadowMap[i] = false; + hasShadowCubemap[i] = false; + + if (light.type !== "point") + { + shaderModule.addUniformVert("m4", "MOD_lightMatrix" + i, mat4.create(), null, null, null); + shaderModule.addUniformVert("f", "MOD_normalOffset" + i, 0, null, null, null, null); + shaderModule.addUniformFrag("t", "MOD_shadowMap" + i, 0, null, null, null); + } + else shaderModule.addUniformFrag("tc", "MOD_shadowMapCube" + i, 0, null, null, null); + } + + if (cgl.frameStore.lightStack.length > 0) + { + shaderModule.addUniformFrag("3f", "MOD_shadowColor", inShadowColorR, inShadowColorG, inShadowColorB, null); + shaderModule.addUniformFrag("f", "MOD_sampleSpread", inSpread, null, null, null); + if (cgl.frameStore.lightStack.map((l) => l.type).indexOf("point") !== -1) shaderModule.addUniformFrag("3f", "MOD_camPos", [0, 0, 0], null, null, null); + } + + STATE.lastLength = cgl.frameStore.lightStack.length; + STATE.updating = false; +} + +function setUniforms() +{ + if (STATE.updating) return; + const receiveShadow = inReceiveShadow.get(); + + for (let i = 0; i < cgl.frameStore.lightStack.length; i += 1) + { + const light = cgl.frameStore.lightStack[i]; + + if (light.type === "ambient") continue; + + if (!light.isUsed) light.isUsed = true; + + if (light.type !== "point") shaderModule.setUniformValue("MOD_light" + i + ".position", light.position); + else + { + shaderModule.setUniformValue("MOD_light" + i + ".position", light.positionForShadowMap); + } + shaderModule.setUniformValue("MOD_light" + i + ".typeCastShadow", [ + LIGHT_TYPES[light.type], + Number(light.castShadow), + ]); + + shaderModule.setUniformValue("MOD_light" + i + ".shadowStrength", light.shadowStrength); + + if (light.shadowMap) + { + if (!hasShadowMap[i]) + { + hasShadowMap[i] = true; + hasShadowCubemap[i] = false; + } + if (!shaderModule.hasDefine("HAS_SHADOW_MAP_" + i)) + { + shaderModule.define("HAS_SHADOW_MAP_" + i, true); + } + + if (light.type !== "point") + { + shaderModule.setUniformValue("MOD_lightMatrix" + i, light.lightMatrix); + shaderModule.setUniformValue("MOD_normalOffset" + i, light.normalOffset); + } + + shaderModule.setUniformValue("MOD_light" + i + ".shadowProperties", [ + light.nearFar[0], + light.nearFar[1], + light.shadowMap.width, + light.shadowBias + ]); + + if (light.type === "point") shaderModule.setUniformValue("MOD_camPos", [_tempCamPosMatrix[12], _tempCamPosMatrix[13], _tempCamPosMatrix[14]]); + + if (hasShadowMap[i]) + { + if (light.shadowMap.tex) shaderModule.pushTexture("MOD_shadowMap" + i, light.shadowMap.tex); + } + continue; + } + + if (light.shadowCubeMap) + { + if (!hasShadowCubemap[i]) + { + hasShadowCubemap[i] = true; + hasShadowMap[i] = false; + } + + if (!shaderModule.hasDefine("HAS_SHADOW_MAP_" + i)) shaderModule.define("HAS_SHADOW_MAP_" + i, ""); + + shaderModule.setUniformValue("MOD_light" + i + ".shadowProperties", [ + light.nearFar[0], + light.nearFar[1], + light.shadowCubeMap.size, + light.shadowBias + ]); + + if (hasShadowCubemap[i]) + { + if (light.shadowCubeMap.cubemap) shaderModule.pushTexture("MOD_shadowMapCube" + i, light.shadowCubeMap.cubemap, cgl.gl.TEXTURE_CUBE_MAP); + } + continue; + } + + else + { + if (hasShadowMap[i]) + { + if (shaderModule.hasDefine("HAS_SHADOW_MAP_" + i)) + { + shaderModule.removeDefine("HAS_SHADOW_MAP_" + i); + } + hasShadowMap[i] = false; + } + else if (hasShadowCubemap[i]) + { + if (shaderModule.hasDefine("HAS_SHADOW_MAP_" + i)) shaderModule.removeDefine("HAS_SHADOW_MAP_" + i); + hasShadowCubemap[i] = false; + } + continue; + } + } +} + +function updateShader() +{ + if (cgl.frameStore.lightStack.length !== STATE.lastLength) + createModuleShaders(); + + setUniforms(); +} + +inTrigger.onLinkChanged = function () +{ + if (!inTrigger.isLinked()) STATE.lastLength = 0; + hasShadowMap.length = 0; + hasShadowCubemap.length = 0; +}; +outTrigger.onLinkChanged = function () +{ + if (!outTrigger.isLinked()) STATE.lastLength = 0; + hasShadowMap.length = 0; + hasShadowCubemap.length = 0; +}; + +const _tempCamPosMatrix = mat4.create(); + +inTrigger.onTriggered = () => +{ + if (STATE.updating) + { + outTrigger.trigger(); + return; + } + + if (cgl.frameStore.shadowPass) + { + if (!inCastShadow.get()) return; + renderShadowPassWithModule(); + return; + } + + if (!inReceiveShadow.get()) + { + outTrigger.trigger(); + return; + } + + checkUiErrors(); + + mat4.invert(_tempCamPosMatrix, cgl.vMatrix); + + if (cgl.frameStore.lightStack) + { + if (cgl.frameStore.lightStack.length) + { + updateShader(); + + shaderModule.bind(); + outTrigger.trigger(); + shaderModule.unbind(); + } + else + { + outTrigger.trigger(); + STATE.lastLength = 0; + hasShadowMap.length = 0; + hasShadowCubemap.length = 0; + } + } + else + { + outTrigger.trigger(); + } +}; + +function checkUiErrors() +{ + if (cgl.frameStore.lightStack) + { + if (cgl.frameStore.lightStack.length === 0) + { + op.setUiError("nolights", "There are no lights in the patch. Please add lights before this op and activate their \"Cast Shadow\" property to be able to use shadows.", 1); + } + else + { + op.setUiError("nolights", null); + + let oneLightCastsShadow = false; + let allLightsBlurAboveZero = true; + + for (let i = 0; i < cgl.frameStore.lightStack.length; i += 1) + { + oneLightCastsShadow = oneLightCastsShadow || cgl.frameStore.lightStack[i].castShadow; + + if (cgl.frameStore.lightStack[i].castShadow && cgl.frameStore.lightStack[i].type !== "point") + allLightsBlurAboveZero = allLightsBlurAboveZero && (cgl.frameStore.lightStack[i].blurAmount > 0); + } + + if (oneLightCastsShadow) + { + op.setUiError("nolights2", null); + if (inReceiveShadow.get()) + { + op.setUiError("inReceiveShadowActive", null); + } + else + { + op.setUiError("inReceiveShadowActive", "Your lights cast shadows but the \"Receive Shadow\" option in this op is not active. Please enable it to use shadows.", 1); + } + } + else + { + op.setUiError("nolights2", "There are lights in the patch but none that cast shadows. Please activate the \"Cast Shadow\" property of one of your lights in the patch to make shadows visible.", 1); + op.setUiError("inReceiveShadowActive", null); + } + + if (!allLightsBlurAboveZero) + { + if (inAlgorithm.get() === "VSM") + { + op.setUiError("vsmBlurZero", "You chose the VSM algorithm but one of your lights still has a blur amount of 0. For VSM to work correctly, consider raising the blur amount in your lights.", 1); + } + else + { + op.setUiError("vsmBlurZero", null); + } + } + else + { + op.setUiError("vsmBlurZero", null); + } + } + } + else + { + op.setUiError("nolights", "There are no lights in the patch. Please add lights before this op and activate their \"Cast Shadow\" property to be able to use shadows.", 1); + } +} + + +}; + +Ops.Gl.ShaderEffects.Shadow_v2.prototype = new CABLES.Op(); +CABLES.OPS["f5214bd2-575d-4c0c-a7a9-4eff76915ac1"]={f:Ops.Gl.ShaderEffects.Shadow_v2,objName:"Ops.Gl.ShaderEffects.Shadow_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.SplineDeform_v2 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.SplineDeform_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"splinedeform_vert":"\n\n\npos.xyz=MOD_splineDeform(pos,0);\n\nnorm=normalize(norm*MOD_splineDeform(pos,1));\n\n","splinedeform_head_vert":"\nUNI vec3 MOD_points[SPLINE_POINTS];\n\nvec3 ip(float v)\n{\n int index0=int(abs(mod(v,max(0.0,float(SPLINE_POINTS)))));\n int index1=int(abs(mod(v+1.0,max(0.0,float(SPLINE_POINTS)))));\n float fr=fract(abs(mod(v,max(0.0,float(SPLINE_POINTS)))));\n return mix( MOD_points[index0] ,MOD_points[index1] ,fr);\n}\n\nvec3 MOD_splineDeform(vec4 pos, int isNormal)\n{\n float off=MOD_offset+( (pos.x)*MOD_size);\n\n vec3 bezierPointPrevious=ip(off-1.0);\n vec3 bezierPoint=ip(off);\n vec3 bezierPointNext=ip(off+1.0);\n\n vec3 _Up=vec3(0.0,1.0,0.0);\n vec3 _Forward=vec3(1.0,0.0,0.0);\n vec3 _Right=vec3(0.0,0.0,1.0);\n\n\tfloat vertexForward = pos.x * _Forward.x + pos.y * _Forward.y + pos.z * _Forward.z;\n\tfloat vertexRight = pos.x * _Right.x + pos.y * _Right.y + pos.z * _Right.z;\n\tfloat vertexUp = pos.x * _Up.x + pos.y * _Up.y + pos.z * _Up.z;\n\n\tfloat angle = atan(vertexUp,vertexRight);\n\tfloat radius = length(vec2(vertexRight, vertexUp));\n\n\tvec3 forward = normalize(bezierPointNext - bezierPoint);\n\tvec3 backward = normalize(bezierPointPrevious - bezierPoint);\n\tvec3 up = normalize(cross(forward, backward));\n\tvec3 right = normalize(cross(forward, up));\n\n if(isNormal==0)\n {\n pos.xyz = bezierPoint + right * cos(angle) * radius + up * sin(angle) * radius;\n }\n else\n {\n pos.xyz = pos.xyz-( (bezierPoint) + right * cos(angle) * radius + up * sin(angle) * radius);\n }\n\n return pos.xyz;\n}",}; +const + render = op.inTrigger("Render"), + next = op.outTrigger("Next"), + inSize = op.inValue("Size", 1), + inOffset = op.inValue("offset"), + inPoints = op.inArray("Points"); + +const cgl = op.patch.cgl; +const srcHeadVert = attachments.splinedeform_head_vert || ""; +const srcBodyVert = attachments.splinedeform_vert || ""; + +let needsUpdate = true; + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "title": op.name, + "name": "MODULE_VERTEX_POSITION", + srcHeadVert, + srcBodyVert +}); + +mod.addUniform("f", "MOD_size", inSize); +mod.addUniform("f", "MOD_offset", inOffset); +mod.addUniform("3f[]", "MOD_points", new Float32Array([0, 0, 0, 0, 0, 0])); +mod.define("SPLINE_POINTS", 1); + +inPoints.onChange = () => +{ + needsUpdate = true; +}; + +render.onTriggered = function () +{ + mod.bind(); + let pointArray = inPoints.get(); + + if (needsUpdate) + { + if (inPoints.get()) + { + if (pointArray && pointArray.length > 0) + { + mod.define("SPLINE_POINTS", Math.floor(pointArray.length / 3)); + needsUpdate = false; + } + } + } + + if (pointArray && pointArray.length > 0) + mod.setUniformValue("MOD_points", pointArray); + + next.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.ShaderEffects.SplineDeform_v2.prototype = new CABLES.Op(); +CABLES.OPS["d0cac165-2146-4a3c-863c-5042149c0e95"]={f:Ops.Gl.ShaderEffects.SplineDeform_v2,objName:"Ops.Gl.ShaderEffects.SplineDeform_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.TextureProjection_v2 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.TextureProjection_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"maptexture_frag":"IN vec2 MOD_tc;\n\n#ifdef MOD_MAP_TRIPLANAR\n IN vec2 MOD_tc1;\n IN vec2 MOD_tc2;\n IN vec3 MOD_blendingTri;\n#endif\n\n\n{{CGL.BLENDMODES3}}","maptexture_vert":"vec3 MOD_pos;\n\n#ifndef MOD_WORLDSPACE\n MOD_pos=(vec4(vPosition,1.0)*1.0/MOD_scale).xyz;\n#endif\n#ifdef MOD_WORLDSPACE\n MOD_pos=(mMatrix*pos).xyz*1.0/MOD_scale;\n#endif\n\nMOD_pos=(vec4(MOD_pos,1.0)*MOD_rotationX(MOD_rotX*MOD_DEG2RAD)).xyz;\nMOD_pos=(vec4(MOD_pos,1.0)*MOD_rotationY(MOD_rotY*MOD_DEG2RAD)).xyz;\nMOD_pos=(vec4(MOD_pos,1.0)*MOD_rotationZ(MOD_rotZ*MOD_DEG2RAD)).xyz;\n\n#ifdef MOD_MAP_XY\n MOD_tc=MOD_pos.xy;\n#endif\n#ifdef MOD_MAP_XZ\n MOD_tc=MOD_pos.xz;\n#endif\n#ifdef MOD_MAP_YZ\n MOD_tc=MOD_pos.yz;\n#endif\n\nMOD_tc.xy+=vec2(0.5,0.5);\nMOD_tc.xy+=MOD_offset;\n\n\n#ifdef MOD_TARGET_POINTSIZE\n\n gl_PointSize+=texture(MOD_tex,MOD_tc).x*MOD_amount;\n\n#endif\n\n\n#ifdef MOD_MAP_TRIPLANAR\n mapTriplanar((mMatrix*vec4(attrVertNormal,1.0)).xyz,MOD_pos);\n#endif\n\n","maptexture_body_frag":"#ifndef MOD_TARGET_POINTSIZE\n\n\n vec4 MOD_color;\n\n #ifdef MOD_MAP_TRIPLANAR\n vec4 xaxis = texture( MOD_tex, MOD_tc);\n vec4 yaxis = texture( MOD_tex, MOD_tc1);\n vec4 zaxis = texture( MOD_tex, MOD_tc2);\n MOD_color = xaxis *MOD_blendingTri.x + yaxis *MOD_blendingTri.y + zaxis *MOD_blendingTri.z;\n MOD_color.a=1.0;\n #endif\n\n\n vec2 MOD_ntc=MOD_tc;\n\n #ifdef MOD_MAP_SCREEN\n MOD_ntc=(vec2(gl_FragCoord.x,gl_FragCoord.y)/vec2(MOD_viewPortW,MOD_viewPortH));\n\n MOD_ntc-=vec2(0.5,0.5);\n MOD_ntc*=1.0/MOD_scale;\n MOD_ntc+=vec2(0.5,0.5);\n MOD_ntc-=MOD_offset;\n #endif\n\n #ifdef MOD_MAP_TEXCOORD\n MOD_ntc=texCoord;\n #endif\n\n #ifdef MOD_MAP_TEXCOORD1\n MOD_ntc=texCoord1;\n #endif\n\n #ifdef MOD_MAP_TEXCOORD2\n MOD_ntc=texCoord2;\n #endif\n\n\n #ifdef MOD_DISCARD\n if(MOD_ntc.x>0.0 && MOD_ntc.x<1.0 && MOD_ntc.y>0.0 && MOD_ntc.y<1.0)\n {\n #endif\n\n #ifndef MOD_MAP_TRIPLANAR\n MOD_color=texture(MOD_tex,MOD_ntc);\n #endif\n\n #ifdef MOD_USE_IMGALPHA\n col.a=MOD_color.a;\n #endif\n\n #ifdef MOD_TARGET_COLOR\n col=cgl_blendPixel(col,MOD_color,MOD_amount*col.a);\n #endif\n #ifdef MOD_TARGET_ALPHA\n col.a=1.0-MOD_color.r*MOD_amount;\n #endif\n\n #ifdef MOD_DISCARD\n }\n\n #endif\n#endif\n","maptexture_body_vert":"OUT vec2 MOD_tc;\n\nconst float MOD_DEG2RAD = 0.017453292519943;\n\n#ifdef MOD_MAP_TRIPLANAR\n\n OUT vec2 MOD_tc1;\n OUT vec2 MOD_tc2;\n OUT vec3 MOD_blendingTri;\n\n void mapTriplanar(vec3 wNorm,vec3 pos)\n {\n vec3 blending = abs( wNorm );\n blending = normalize(max(blending, 0.1));\n float b = (blending.x + blending.y + blending.z);\n blending /= vec3(b);\n MOD_blendingTri=blending;\n\n MOD_tc = pos.yz;\n MOD_tc1 = pos.xz;\n MOD_tc2 = pos.xy;\n }\n\n#endif\n\nmat4 MOD_rotationX( in float angle ) {\n\treturn mat4(\t1.0,\t\t0,\t\t\t0,\t\t\t0,\n\t\t\t \t\t0, \tcos(angle),\t-sin(angle),\t\t0,\n\t\t\t\t\t0, \tsin(angle),\t cos(angle),\t\t0,\n\t\t\t\t\t0, \t\t\t0,\t\t\t 0, \t\t1);\n}\n\nmat4 MOD_rotationY( in float angle ) {\n\treturn mat4(\tcos(angle),\t\t0,\t\tsin(angle),\t0,\n\t\t\t \t\t\t\t0,\t\t1.0,\t\t\t 0,\t0,\n\t\t\t\t\t-sin(angle),\t0,\t\tcos(angle),\t0,\n\t\t\t\t\t\t\t0, \t\t0,\t\t\t\t0,\t1);\n}\n\nmat4 MOD_rotationZ( in float angle ) {\n\treturn mat4(\tcos(angle),\t\t-sin(angle),\t0,\t0,\n\t\t\t \t\tsin(angle),\t\tcos(angle),\t\t0,\t0,\n\t\t\t\t\t\t\t0,\t\t\t\t0,\t\t1,\t0,\n\t\t\t\t\t\t\t0,\t\t\t\t0,\t\t0,\t1);\n}\n",}; +const + render = op.inTrigger("render"), + next = op.outTrigger("trigger"), + inTex = op.inTexture("Texture"), + + inScale = op.inValue("Scale", 10), + + inTarget = op.inSwitch("Target", ["Color", "Pointsize", "Alpha"], "Color"), + + inBlend = CGL.TextureEffect.AddBlendSelect(op, "blendMode"), + inAmount = op.inValueSlider("Amount", 0.3), + + inUseTexAlpha = op.inBool("Use Texture Alpha", false), + + inPosX = op.inFloat("Pos X", 0), + inPosY = op.inFloat("Pos Y", 0), + + inRotX = op.inFloat("Rot X", 0), + inRotY = op.inFloat("Rot Y", 0), + inRotZ = op.inFloat("Rot Z", 0), + + inMethod = op.inValueSelect("Mapping", ["Triplanar", "XY", "XZ", "YZ", "Screen", "TexCoords 1", "TexCoords 2", "TexCoords 3"], "XY"), + inDiscard = op.inValueBool("Discard"), + inWorldSpace = op.inValueBool("WorldSpace"); + +const cgl = op.patch.cgl; + +inUseTexAlpha.onChange = +inTarget.onChange = +inBlend.onChange = inDiscard.onChange = inWorldSpace.onChange = inMethod.onChange = updateDefines; + +op.setPortGroup("Rotation", [inRotX, inRotY, inRotZ]); +op.setPortGroup("Position", [inPosX, inPosY]); + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "title": op.name, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": attachments.maptexture_body_vert, + "srcBodyVert": attachments.maptexture_vert, + "attributes": [ + { "type": "vec2", "name": "attrTexCoord1", "nameFrag": "texCoord1" }, + { "type": "vec2", "name": "attrTexCoord2", "nameFrag": "texCoord2" }] +}); + +let head_frag = attachments.maptexture_frag; +head_frag = head_frag.replace("{{BLENDCODE}}", CGL.TextureEffect.getBlendCode(3)); + +mod.addModule({ + "title": op.name, + "name": "MODULE_COLOR", + "srcHeadFrag": head_frag, + "srcBodyFrag": attachments.maptexture_body_frag +}); + +mod.addUniformBoth("f", "MOD_rotX", inRotX); +mod.addUniformBoth("f", "MOD_rotY", inRotY); +mod.addUniformBoth("f", "MOD_rotZ", inRotZ); + +mod.addUniformBoth("t", "MOD_tex"); +mod.addUniformBoth("f", "MOD_scale", inScale); +mod.addUniformBoth("f", "MOD_amount", inAmount); +mod.addUniformBoth("2f", "MOD_offset", inPosX, inPosY); + +const uniWidth = mod.addUniformFrag("f", "MOD_viewPortW"); +const uniHeight = mod.addUniformFrag("f", "MOD_viewPortH"); + +CGL.TextureEffect.setupBlending(op, mod, inBlend, inAmount); + +updateDefines(); + +function updateDefines() +{ + mod.toggleDefine("MOD_USE_IMGALPHA", inUseTexAlpha.get()); + mod.toggleDefine("MOD_WORLDSPACE", inWorldSpace.get()); + mod.toggleDefine("MOD_MAP_XY", inMethod.get() == "XY"); + mod.toggleDefine("MOD_MAP_XZ", inMethod.get() == "XZ"); + mod.toggleDefine("MOD_MAP_YZ", inMethod.get() == "YZ"); + mod.toggleDefine("MOD_MAP_TEXCOORD", inMethod.get() == "TexCoords 1"); + mod.toggleDefine("MOD_MAP_TEXCOORD1", inMethod.get() == "TexCoords 2"); + mod.toggleDefine("MOD_MAP_TEXCOORD2", inMethod.get() == "TexCoords 3"); + mod.toggleDefine("MOD_MAP_SCREEN", inMethod.get() == "Screen"); + mod.toggleDefine("MOD_MAP_TRIPLANAR", inMethod.get() == "Triplanar"); + mod.toggleDefine("MOD_DISCARD", inDiscard.get()); + + mod.toggleDefine("MOD_BLEND_NORMAL", inBlend.get() == "Normal"); + mod.toggleDefine("MOD_BLEND_ADD", inBlend.get() == "Add"); + mod.toggleDefine("MOD_BLEND_MUL", inBlend.get() == "Mul"); + mod.toggleDefine("MOD_BLEND_MUL", inBlend.get() == "Mul"); + + mod.toggleDefine("MOD_TARGET_ALPHA", inTarget.get() == "Alpha"); + mod.toggleDefine("MOD_TARGET_COLOR", inTarget.get() == "Color"); + mod.toggleDefine("MOD_TARGET_POINTSIZE", inTarget.get() == "Pointsize"); +} + +render.onTriggered = function () +{ + const vp = cgl.getViewPort(); + + mod.setUniformValue("MOD_viewPortW", vp[2]); + mod.setUniformValue("MOD_viewPortH", vp[3]); + + mod.bind(); + let tex = inTex.get(); + if (!tex) tex = CGL.Texture.getEmptyTexture(cgl).tex; + else tex = tex.tex; + + mod.pushTexture("MOD_tex", tex); + + next.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.ShaderEffects.TextureProjection_v2.prototype = new CABLES.Op(); +CABLES.OPS["9be647c2-7afd-40ed-b669-9826ea6a50ca"]={f:Ops.Gl.ShaderEffects.TextureProjection_v2,objName:"Ops.Gl.ShaderEffects.TextureProjection_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.TransformTextureCoordinates +// +// ************************************************************** + +Ops.Gl.ShaderEffects.TransformTextureCoordinates = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"trans_vert":"\n#ifdef MOD_FLIPX\n texCoord.x=1.0-texCoord.x;\n#endif\n#ifdef MOD_FLIPY\n texCoord.y=1.0-texCoord.y;\n#endif\n\ntexCoord*=MOD_scale;\ntexCoord+=MOD_trans;",}; +const + render = op.inTrigger("render"), + next = op.outTrigger("Trigger"), + + transX = op.inValue("Translate X", 0), + transY = op.inValue("Translate Y", 0), + + scaleX = op.inValue("Repeat X", 1), + scaleY = op.inValue("Repeat Y", 1), + + inFlipX=op.inBool("Flip X",false), + inFlipY=op.inBool("Flip Y",false) + ; + +const cgl = op.patch.cgl; +const mod = new CGL.ShaderModifier(cgl, op.name); + +mod.addModule({ + "priority": -2, + "name": "MODULE_VERTEX_POSITION", + "srcBodyVert": attachments.trans_vert || "" +}); + +mod.addUniformVert("2f", "MOD_trans", transX, transY); +mod.addUniformVert("2f", "MOD_scale", scaleX, scaleY); + + +inFlipX.onChange= + inFlipY.onChange=updateDefines; + +updateDefines(); + +function updateDefines() +{ + mod.toggleDefine("MOD_FLIPX",inFlipX.get()); + mod.toggleDefine("MOD_FLIPY",inFlipY.get()); +} + +render.onTriggered = function () +{ + mod.bind(); + next.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.ShaderEffects.TransformTextureCoordinates.prototype = new CABLES.Op(); +CABLES.OPS["54eeb750-1491-4fdf-bfd5-290e1b29bafd"]={f:Ops.Gl.ShaderEffects.TransformTextureCoordinates,objName:"Ops.Gl.ShaderEffects.TransformTextureCoordinates"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.TransformVertex +// +// ************************************************************** + +Ops.Gl.ShaderEffects.TransformVertex = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"trans_vert":"\n\n\npos.xyz*=vec3(MOD_scale);\npos.xyz+=vec3(MOD_translate);\n\nmat4 MOD_rmat=\n MOD_rotationX(MOD_rot.x*0.0174533)*\n MOD_rotationY(MOD_rot.y*0.0174533)*\n MOD_rotationZ(MOD_rot.z*0.0174533);\n\npos*=MOD_rmat;\n\n#ifdef MOD_TRANS_NORMS\n norm=(vec4(norm,1.0)*MOD_rmat).xyz;\n bitangent=(vec4(bitangent,1.0)*MOD_rmat).xyz;\n tangent=(vec4(tangent,1.0)*MOD_rmat).xyz;\n#endif","trans_head_vert":"\nmat4 MOD_rotationX( in float angle ) {\n\treturn mat4(\t1.0,\t\t0,\t\t\t0,\t\t\t0,\n\t\t\t \t\t0, \tcos(angle),\t-sin(angle),\t\t0,\n\t\t\t\t\t0, \tsin(angle),\t cos(angle),\t\t0,\n\t\t\t\t\t0, \t\t\t0,\t\t\t 0, \t\t1);\n}\n\nmat4 MOD_rotationY( in float angle ) {\n\treturn mat4(\tcos(angle),\t\t0,\t\tsin(angle),\t0,\n\t\t\t \t\t\t\t0,\t\t1.0,\t\t\t 0,\t0,\n\t\t\t\t\t-sin(angle),\t0,\t\tcos(angle),\t0,\n\t\t\t\t\t\t\t0, \t\t0,\t\t\t\t0,\t1);\n}\n\nmat4 MOD_rotationZ( in float angle ) {\n\treturn mat4(\tcos(angle),\t\t-sin(angle),\t0,\t0,\n\t\t\t \t\tsin(angle),\t\tcos(angle),\t\t0,\t0,\n\t\t\t\t\t\t\t0,\t\t\t\t0,\t\t1,\t0,\n\t\t\t\t\t\t\t0,\t\t\t\t0,\t\t0,\t1);\n}\n",}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("Trigger"), + transX = op.inValue("Translate X", 0), + transY = op.inValue("Translate Y", 0), + transZ = op.inValue("Translate Z", 0), + + scaleX = op.inValue("Scale X", 1), + scaleY = op.inValue("Scale Y", 1), + scaleZ = op.inValue("Scale Z", 1), + + rotX = op.inValue("Rotation X", 0), + rotY = op.inValue("Rotation Y", 0), + rotZ = op.inValue("Rotation Z", 0), + transNorm = op.inBool("Transform normals", false); + +const cgl = op.patch.cgl; +const mod = new CGL.ShaderModifier(cgl, op.name); + +mod.addModule({ + "priority": -2, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": attachments.trans_head_vert || "", + "srcBodyVert": attachments.trans_vert || "" +}); + +mod.addUniformVert("3f", "MOD_translate", transX, transY, transZ); +mod.addUniformVert("3f", "MOD_scale", scaleX, scaleY, scaleZ); +mod.addUniformVert("3f", "MOD_rot", rotX, rotY, rotZ); + +transNorm.onChange = updateDefines; + +updateDefines(); + +function updateDefines() +{ + mod.toggleDefine("MOD_TRANS_NORMS", transNorm.get()); +} + +render.onTriggered = function () +{ + mod.bind(); + trigger.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.ShaderEffects.TransformVertex.prototype = new CABLES.Op(); +CABLES.OPS["68ca4a91-c3ce-4e81-bb84-3ba5f50dfaa1"]={f:Ops.Gl.ShaderEffects.TransformVertex,objName:"Ops.Gl.ShaderEffects.TransformVertex"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.Twist_v3 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.Twist_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"twist_vert":"\nfloat MOD_angle_rad = MOD_amount * 3.14159 / 180.0;\n\nfloat MOD_axis=pos.y;\n\n#ifdef MOD_AXIS_Z\n MOD_axis=pos.z;\n#endif\n\n#ifdef MOD_AXIS_X\n MOD_axis=pos.x;\n#endif\n\nfloat MOD_ang = (MOD_height*0.5 + MOD_axis)/MOD_height * MOD_angle_rad;\n\npos = MOD_twist(pos, MOD_ang);\n\n\nnorm = normalize(MOD_twist( vec4(norm, 1.0), MOD_ang ).xyz);\n","twist_head_vert":"vec4 MOD_twist(vec4 pos, float t)\n{\n\tfloat st = sin(t);\n\tfloat ct = cos(t);\n\tvec4 new_pos;\n\n\tnew_pos.x = pos.x;\n\tnew_pos.y = pos.y;\n\tnew_pos.z = pos.z;\n\tnew_pos.w = pos.w;\n\n #ifdef MOD_AXIS_Z\n \tnew_pos.x = pos.y*ct - pos.x*st;\n \tnew_pos.y = pos.y*st + pos.x*ct;\n #endif\n\n #ifdef MOD_AXIS_Y\n \tnew_pos.x = pos.x*ct - pos.z*st;\n \tnew_pos.z = pos.x*st + pos.z*ct;\n #endif\n\n #ifdef MOD_AXIS_X\n \tnew_pos.y = pos.y*ct - pos.z*st;\n \tnew_pos.z = pos.y*st + pos.z*ct;\n #endif\n\n\treturn( new_pos );\n}\n",}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("Trigger"), + amount = op.inFloat("Degree", 180), + height = op.inFloat("Height", 2), + axis = op.inValueSelect("Axis", ["X", "Y", "Z"], "Y"); + +const cgl = op.patch.cgl; + +axis.onChange = updateAxis; + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": attachments.twist_head_vert, + "srcBodyVert": attachments.twist_vert +}); + +updateAxis(); + +mod.addUniformVert("f", "MOD_amount", amount); +mod.addUniformVert("f", "MOD_height", height); + +function updateAxis() +{ + mod.toggleDefine("MOD_AXIS_X", axis.get() == "X"); + mod.toggleDefine("MOD_AXIS_Y", axis.get() == "Y"); + mod.toggleDefine("MOD_AXIS_Z", axis.get() == "Z"); +} + +render.onTriggered = function () +{ + if (cgl.shouldDrawHelpers(op)) + { + CABLES.GL_MARKER.drawCube(op, 1, height.get() / 2, 1); + } + + mod.bind(); + trigger.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.ShaderEffects.Twist_v3.prototype = new CABLES.Op(); +CABLES.OPS["4635abe3-a6b1-413f-9cd1-fbf64f8c4942"]={f:Ops.Gl.ShaderEffects.Twist_v3,objName:"Ops.Gl.ShaderEffects.Twist_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.UseVertexColor +// +// ************************************************************** + +Ops.Gl.ShaderEffects.UseVertexColor = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"colorarea_frag":"baseColor.rgb=vertColor.rgb;","colorarea_head_frag":"IN vec4 vertColor;\n",}; +const + render = op.inTrigger("Render"), + next = op.outTrigger("Next"); + +const cgl = op.patch.cgl; + +const srcHeadVert = "" + .endl() + "IN vec4 attrVertColor;" + .endl() + "OUT vec4 vertColor;" + .endl(); + +const srcBodyVert = "" + .endl() + " vertColor=attrVertColor;" + .endl(); + + +render.onTriggered = doRender; + +const vertModTitle = "vert_" + op.name; +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "title": vertModTitle, + "name": "MODULE_VERTEX_POSITION", + srcHeadVert, + srcBodyVert +}); + +mod.addModule({ + "title": op.name, + "name": "MODULE_BASE_COLOR", + "srcHeadFrag": attachments.colorarea_head_frag, + "srcBodyFrag": attachments.colorarea_frag +}); + + +function doRender() +{ + mod.bind(); + next.trigger(); + + mod.unbind(); +} + + +}; + +Ops.Gl.ShaderEffects.UseVertexColor.prototype = new CABLES.Op(); +CABLES.OPS["8c3cc332-3bab-4cb7-ad0a-368814eb8282"]={f:Ops.Gl.ShaderEffects.UseVertexColor,objName:"Ops.Gl.ShaderEffects.UseVertexColor"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.VertexColorAsAlpha +// +// ************************************************************** + +Ops.Gl.ShaderEffects.VertexColorAsAlpha = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"colorarea_frag":"\nfloat MOD_vca=1.0;\n\n#ifdef MOD_INPUT_LUMI\n float MOD_lumi = dot(vec3(0.2126,0.7152,0.0722), col.rgb);\n\n MOD_vca=MOD_lumi;\n#endif\n#ifdef MOD_INPUT_R\n MOD_vca=vertColor.r;\n#endif\n#ifdef MOD_INPUT_G\n MOD_vca=vertColor.g;\n#endif\n#ifdef MOD_INPUT_B\n MOD_vca=vertColor.b;\n#endif\n\n#ifdef MOD_INVERT\n col.a=1.0-MOD_vca;\n#endif\n#ifndef MOD_INVERT\n col.a=MOD_vca;\n#endif","colorarea_head_frag":"IN vec4 vertColor;\n",}; +const + render = op.inTrigger("Render"), + inInput=op.inSwitch("Input",['Luminance','R','G','B'],'default'), + inInvert=op.inBool("Invert",false), + next = op.outTrigger("Next"); + + +const cgl = op.patch.cgl; + +const srcHeadVert = "" + .endl() + "IN vec3 attrVertColor;" + .endl() + "OUT vec4 vertColor;" + + .endl(); + +const srcBodyVert = "" + .endl() + "vertColor.rgb=attrVertColor;" + .endl(); + +inInput.onChange = + inInvert.onChange = updateDefines; + +render.onTriggered = doRender; + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "priority": 2, + "title": op.name, + "name": "MODULE_VERTEX_POSITION", + srcHeadVert, + srcBodyVert +}); + +mod.addModule({ + "title": op.name, + "name": "MODULE_COLOR", + "srcHeadFrag": attachments.colorarea_head_frag, + "srcBodyFrag": attachments.colorarea_frag +}); + +updateDefines(); + + +function updateDefines() +{ + mod.toggleDefine("MOD_INPUT_R", inInput.get()==="R"); + mod.toggleDefine("MOD_INPUT_G", inInput.get()==="G"); + mod.toggleDefine("MOD_INPUT_B", inInput.get()==="B"); + mod.toggleDefine("MOD_INPUT_LUMI", inInput.get()==="Luminance"); + mod.toggleDefine("MOD_INVERT", inInvert.get()); +} + + + +function doRender() +{ + mod.bind(); + next.trigger(); + + mod.unbind(); +} + + +}; + +Ops.Gl.ShaderEffects.VertexColorAsAlpha.prototype = new CABLES.Op(); +CABLES.OPS["3a3a4c1f-3824-4fa2-b287-1368bde0f0a0"]={f:Ops.Gl.ShaderEffects.VertexColorAsAlpha,objName:"Ops.Gl.ShaderEffects.VertexColorAsAlpha"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.VertexDisplacementMap_v4 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.VertexDisplacementMap_v4 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"vertdisplace_body_vert":"\nvec2 MOD_tc=texCoord;\n\n#ifdef MOD_COORD_MESHXY\n MOD_tc=pos.xy;\n#endif\n#ifdef MOD_COORD_MESHXZ\n MOD_tc=pos.xz;\n#endif\n\n\n#ifdef MOD_FLIP_Y\n MOD_tc.y=1.0-MOD_tc.y;\n#endif\n#ifdef MOD_FLIP_X\n MOD_tc.x=1.0-MOD_tc.x;\n#endif\n#ifdef MOD_FLIP_XY\n MOD_tc=1.0-MOD_tc;\n#endif\n\nMOD_tc*=MOD_scale;\n\nvec4 MOD_sample=texture( MOD_texture, vec2(MOD_tc.x+MOD_offsetX,MOD_tc.y+MOD_offsetY) );\nvec3 MOD_disp;\n\n#ifdef MOD_INPUT_R\n MOD_disp=vec3(MOD_sample.r);\n#endif\n#ifdef MOD_INPUT_G\n MOD_disp=vec3(MOD_sample.g);\n#endif\n#ifdef MOD_INPUT_B\n MOD_disp=vec3(MOD_sample.b);\n#endif\n#ifdef MOD_INPUT_A\n MOD_disp=vec3(MOD_sample.a);\n#endif\n#ifdef MOD_INPUT_RGB\n MOD_disp=MOD_sample.rgb;\n#endif\n#ifdef MOD_INPUT_LUMI\n MOD_disp=vec3(dot(vec3(0.2126,0.7152,0.0722), MOD_sample.rgb));\n#endif\n\n\n\n#ifdef MOD_HEIGHTMAP_INVERT\n MOD_disp=1.0-MOD_disp;\n#endif\n// #ifdef MOD_HEIGHTMAP_NORMALIZE\n// MOD_disp-=0.5;\n// MOD_disp*=2.0;\n// #endif\n\n\n#ifdef MOD_HEIGHTMAP_NORMALIZE\n MOD_disp=(MOD_disp-0.5)*2.0;\n // MOD_disp=(MOD_disp-0.5)*-1.0+0.5;\n#endif\n\n\nfloat MOD_zero=0.0;\n\n#ifdef MOD_MODE_DIV\n MOD_zero=1.0;\n#endif\n#ifdef MOD_MODE_MUL\n MOD_zero=1.0;\n#endif\n\n\n\nvec3 MOD_mask=vec3(1.0);\n\n#ifdef MOD_AXIS_X\n MOD_mask=vec3(1.,0.,0.);\n MOD_disp*=MOD_mask*MOD_extrude;\n#endif\n#ifdef MOD_AXIS_Y\n MOD_mask=vec3(0.,1.,0.);\n MOD_disp*=MOD_mask*MOD_extrude;\n#endif\n#ifdef MOD_AXIS_Z\n MOD_mask=vec3(0.,0.,1.);\n MOD_disp*=MOD_mask*MOD_extrude;\n#endif\n#ifdef MOD_AXIS_XY\n MOD_mask=vec3(1.,1.,0.);\n MOD_disp*=MOD_mask*MOD_extrude;\n#endif\n#ifdef MOD_AXIS_XYZ\n MOD_mask=vec3(1.,1.,1.);\n MOD_disp*=MOD_mask*MOD_extrude;\n#endif\n\n\n// MOD_disp=smoothstep(-1.,1.,MOD_disp*MOD_disp*MOD_disp);\n// MOD_disp=MOD_disp*MOD_disp*MOD_disp;\n\n// #ifdef MOD_FLIP_Y\n// MOD_mask.y=1.0-MOD_mask.y;\n// #endif\n// #ifdef MOD_FLIP_X\n// MOD_mask.x=1.0-MOD_mask.x;\n// #endif\n// #ifdef MOD_FLIP_XY\n// MOD_mask.xy=1.0-MOD_mask.xy;\n// #endif\n\n\n\n#ifdef MOD_MODE_DIV\n pos.xyz/=MOD_disp*MOD_mask;\n#endif\n\n#ifdef MOD_MODE_MUL\n pos.xyz*=MOD_disp*MOD_mask;\n#endif\n\n#ifdef MOD_MODE_ADD\n pos.xyz+=MOD_disp*MOD_mask;\n#endif\n\n#ifdef MOD_MODE_NORMAL\n\n vec3 MOD_t=norm;\n #ifdef MOD_SMOOTHSTEP\n MOD_t=smoothstep(-1.,1.,MOD_t);\n #endif\n\n pos.xyz+=MOD_t*MOD_disp*MOD_mask;\n\n#endif\n\n#ifdef MOD_MODE_TANGENT\n MOD_disp*=-1.0;\n\n vec3 MOD_t=attrTangent;\n #ifdef MOD_SMOOTHSTEP\n MOD_t=smoothstep(-1.,1.,MOD_t);\n #endif\n\n pos.xyz+=MOD_t*MOD_disp*MOD_mask;\n\n#endif\n\n#ifdef MOD_MODE_BITANGENT\n MOD_disp*=-1.0;\n vec3 MOD_t=attrBiTangent;\n\n #ifdef MOD_SMOOTHSTEP\n MOD_t=smoothstep(-1.,1.,MOD_t);\n #endif\n\n pos.xyz+=MOD_t*MOD_disp*MOD_mask;\n\n#endif\n\n#ifdef MOD_MODE_VERTCOL\n vec3 MOD_t=attrVertColor.rgb*vec3(2.0)-vec3(1.0);\n\n #ifdef MOD_SMOOTHSTEP\n MOD_t=smoothstep(-1.,1.,MOD_t);\n #endif\n\n pos.xyz+=MOD_t*MOD_disp*MOD_mask;\n\n#endif\n\n\n// pos.y*=-1.0;\n // pos.xy+=vec2(MOD_texVal*MOD_extrude)*normalize(pos.xy);\n\n\nMOD_displHeightMapColor=MOD_disp;\n\n\n#ifdef CALC_NORMALS\n norm+=MOD_calcNormal(MOD_texture,MOD_tc);\n#endif","vertdisplace_head_vert":"OUT vec3 MOD_displHeightMapColor;\n\n#ifdef MOD_MODE_VERTCOL\n#ifndef VERTEX_COLORS\nIN vec4 attrVertColor;\n#endif\n#endif\n\n// mat4 rotationX( in float angle ) {\n// \treturn mat4(\t1.0,\t\t0,\t\t\t0,\t\t\t0,\n// \t\t\t \t\t0, \tcos(angle),\t-sin(angle),\t\t0,\n// \t\t\t\t\t0, \tsin(angle),\t cos(angle),\t\t0,\n// \t\t\t\t\t0, \t\t\t0,\t\t\t 0, \t\t1);\n// }\n\n// mat4 rotationY( in float angle ) {\n// \treturn mat4(\tcos(angle),\t\t0,\t\tsin(angle),\t0,\n// \t\t\t \t\t\t\t0,\t\t1.0,\t\t\t 0,\t0,\n// \t\t\t\t\t-sin(angle),\t0,\t\tcos(angle),\t0,\n// \t\t\t\t\t\t\t0, \t\t0,\t\t\t\t0,\t1);\n// }\n\n// mat4 rotationZ( in float angle ) {\n// \treturn mat4(\tcos(angle),\t\t-sin(angle),\t0,\t0,\n// \t\t\t \t\tsin(angle),\t\tcos(angle),\t\t0,\t0,\n// \t\t\t\t\t\t\t0,\t\t\t\t0,\t\t1,\t0,\n// \t\t\t\t\t\t\t0,\t\t\t\t0,\t\t0,\t1);\n// }\n\n\nvec3 MOD_calcNormal(sampler2D tex,vec2 uv)\n{\n float strength=13.0;\n float texelSize=1.0/512.0;\n\n float tl = abs(texture(tex, uv + texelSize * vec2(-1.0, -1.0)).x); // top left\n float l = abs(texture(tex, uv + texelSize * vec2(-1.0, 0.0)).x); // left\n float bl = abs(texture(tex, uv + texelSize * vec2(-1.0, 1.0)).x); // bottom left\n float t = abs(texture(tex, uv + texelSize * vec2( 0.0, -1.0)).x); // top\n float b = abs(texture(tex, uv + texelSize * vec2( 0.0, 1.0)).x); // bottom\n float tr = abs(texture(tex, uv + texelSize * vec2( 1.0, -1.0)).x); // top right\n float r = abs(texture(tex, uv + texelSize * vec2( 1.0, 0.0)).x); // right\n float br = abs(texture(tex, uv + texelSize * vec2( 1.0, 1.0)).x); // bottom right\n\n // // Compute dx using Sobel:\n // // -1 0 1\n // // -2 0 2\n // // -1 0 1\n float dX = tr + 2.0*r + br -tl - 2.0*l - bl;\n\n // // Compute dy using Sobel:\n // // -1 -2 -1\n // // 0 0 0\n // // 1 2 1\n float dY = bl + 2.0*b + br -tl - 2.0*t - tr;\n\n // // Build the normalized normal\n\n vec3 N = normalize(vec3(dX,dY, 1.0 / strength));\n\n // //convert (-1.0 , 1.0) to (0.0 , 1.0), if needed\n N= N * 0.5 + 0.5;\n\n return N;\n}\n",}; +const + render = op.inTrigger("Render"), + + // meth = op.inValueSelect("Mode", ["normal", "normal xy", "mul xyz", "mul xy", "sub x", "add x", "add xy", "add y", "add z", "mul y", "mul z", "sub z", "normal2", "normal RGB", "m14"], "normal"), + extrude = op.inValue("Extrude", 0.5), + meth = op.inSwitch("Mode", ["Norm", "Tang", "BiTang", "VertCol", "*", "+", "/"], "Norm"), + axis = op.inSwitch("Axis", ["XYZ", "XY", "X", "Y", "Z"], "XYZ"), + src = op.inSwitch("Coordinates", ["Tex Coords", "Mesh XY", "Mesh XZ"], "Tex Coords"), + + texture = op.inTexture("Texture", null, "texture"), + channel = op.inSwitch("Channel", ["Luminance", "R", "G", "B", "A", "RGB"], "Luminance"), + flip = op.inSwitch("Flip", ["None", "X", "Y", "XY"], "None"), + range = op.inSwitch("Range", ["0-1", "1-0", "Normalized"], "0-1"), + offsetX = op.inValueFloat("Offset X"), + offsetY = op.inValueFloat("Offset Y"), + scale = op.inValueFloat("Scale", 1), + + calcNormals = op.inValueBool("Calc Normals", false), + removeZero = op.inValueBool("Discard Zero Values"), + colorize = op.inValueBool("colorize", false), + colorizeMin = op.inValueSlider("Colorize Min", 0), + colorizeMax = op.inValueSlider("Colorize Max", 1), + next = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; + +op.setPortGroup("Input", [texture, flip, channel, range, offsetX, offsetY, scale]); +op.setPortGroup("Colorize", [colorize, colorizeMin, colorizeMax]); + +op.toWorkPortsNeedToBeLinked(texture, next, render); + +render.onTriggered = dorender; + +channel.onChange = +colorize.onChange = +axis.onChange = + range.onChange = + removeZero.onChange = + flip.onChange = + calcNormals.onChange = + src.onChange = + meth.onChange = updateDefines; + +const srcHeadVert = attachments.vertdisplace_head_vert; +const srcBodyVert = attachments.vertdisplace_body_vert; + +const srcHeadFrag = "" + .endl() + "IN vec3 MOD_displHeightMapColor;" + .endl() + "vec3 MOD_map(vec3 value, float inMin, float inMax, float outMin, float outMax) { return outMin + (outMax - outMin) * (value - inMin) / (inMax - inMin);}" + + .endl(); + +const srcBodyFrag = "" + .endl() + "#ifdef MOD_HEIGHTMAP_COLORIZE" + .endl() + " col.rgb*=MOD_map( MOD_displHeightMapColor, 0.0,1.0 , MOD_colorizeMin,MOD_colorizeMax);" + .endl() + "#endif" + .endl() + "#ifdef MOD_DISPLACE_REMOVE_ZERO" + .endl() + " if(MOD_displHeightMapColor.r==0.0)discard;" + .endl() + "#endif" + .endl(); + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "title": op.name, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": srcHeadVert, + "srcBodyVert": srcBodyVert +}); + +mod.addModule({ + "title": op.name, + "name": "MODULE_COLOR", + "srcHeadFrag": srcHeadFrag, + "srcBodyFrag": srcBodyFrag +}); + +mod.addUniformVert("t", "MOD_texture", 0); +mod.addUniformVert("f", "MOD_extrude", extrude); +mod.addUniformVert("f", "MOD_offsetX", offsetX); +mod.addUniformVert("f", "MOD_offsetY", offsetY); +mod.addUniformVert("f", "MOD_scale", scale); + +mod.addUniformFrag("f", "MOD_colorizeMin", colorizeMin); +mod.addUniformFrag("f", "MOD_colorizeMax", colorizeMax); + +updateDefines(); + +function updateDefines() +{ + mod.toggleDefine("MOD_HEIGHTMAP_COLORIZE", colorize.get()); + + mod.toggleDefine("MOD_HEIGHTMAP_INVERT", range.get() == "1-0"); + mod.toggleDefine("MOD_HEIGHTMAP_NORMALIZE", range.get() == "Normalized"); + + mod.toggleDefine("MOD_DISPLACE_REMOVE_ZERO", removeZero.get()); + + mod.toggleDefine("MOD_INPUT_R", channel.get() == "R"); + mod.toggleDefine("MOD_INPUT_G", channel.get() == "G"); + mod.toggleDefine("MOD_INPUT_B", channel.get() == "B"); + mod.toggleDefine("MOD_INPUT_A", channel.get() == "A"); + mod.toggleDefine("MOD_INPUT_RGB", channel.get() == "RGB"); + mod.toggleDefine("MOD_INPUT_LUMI", channel.get() == "Luminance"); + + mod.toggleDefine("MOD_FLIP_X", flip.get() == "X"); + mod.toggleDefine("MOD_FLIP_Y", flip.get() == "Y"); + mod.toggleDefine("MOD_FLIP_XY", flip.get() == "XY"); + + mod.toggleDefine("MOD_AXIS_X", axis.get() == "X"); + mod.toggleDefine("MOD_AXIS_Y", axis.get() == "Y"); + mod.toggleDefine("MOD_AXIS_Z", axis.get() == "Z"); + mod.toggleDefine("MOD_AXIS_XYZ", axis.get() == "XYZ"); + mod.toggleDefine("MOD_AXIS_XY", axis.get() == "XY"); + + mod.toggleDefine("MOD_MODE_BITANGENT", meth.get() == "BiTang"); + mod.toggleDefine("MOD_MODE_TANGENT", meth.get() == "Tang"); + mod.toggleDefine("MOD_MODE_NORMAL", meth.get() == "Norm"); + mod.toggleDefine("MOD_MODE_VERTCOL", meth.get() == "VertCol"); + mod.toggleDefine("MOD_MODE_MUL", meth.get() == "*"); + mod.toggleDefine("MOD_MODE_ADD", meth.get() == "+"); + mod.toggleDefine("MOD_MODE_DIV", meth.get() == "/"); + mod.toggleDefine("MOD_SMOOTHSTEP", 0); + + mod.toggleDefine("MOD_COORD_TC", src.get() == "Tex Coords"); + mod.toggleDefine("MOD_COORD_MESHXY", src.get() == "Mesh XY"); + mod.toggleDefine("MOD_COORD_MESHXZ", src.get() == "Mesh XZ"); + + mod.toggleDefine("CALC_NORMALS", calcNormals.get()); +} + +function dorender() +{ + mod.bind(); + + if (texture.get() && !texture.get().deleted) mod.pushTexture("MOD_texture", texture.get()); + else mod.pushTexture("MOD_texture", CGL.Texture.getEmptyTexture(cgl)); + + next.trigger(); + + mod.unbind(); +} + + +}; + +Ops.Gl.ShaderEffects.VertexDisplacementMap_v4.prototype = new CABLES.Op(); +CABLES.OPS["ed36e5ad-457b-4ac6-a929-11b66951cb6c"]={f:Ops.Gl.ShaderEffects.VertexDisplacementMap_v4,objName:"Ops.Gl.ShaderEffects.VertexDisplacementMap_v4"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.VertexNumberLimit_v2 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.VertexNumberLimit_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Render"), + limitMin = op.inValueInt("Min", 0), + limitMax = op.inValueInt("Max", 1000), + inv=op.inBool("Invert",false); + +const trigger = op.outTrigger("Next"); +const cgl = op.patch.cgl; + +const srcHeadVert = "" + .endl() + "OUT float MOD_discard;" + .endl(); + +const srcBodyVert = "" + .endl() + "MOD_discard=1.0; " + + .endl() + "#ifndef MOD_INVERT" + .endl() + " if(attrVertIndex >= MOD_vertLimit.x && attrVertIndex <= MOD_vertLimit.y) MOD_discard=0.0; " + .endl() + "#endif" + + .endl() + "#ifdef MOD_INVERT" + .endl() + " if(attrVertIndex < MOD_vertLimit.x || attrVertIndex > MOD_vertLimit.y) MOD_discard=0.0; " + .endl() + "#endif" + .endl(); + +const srcHeadFrag = "" + .endl() + "IN float MOD_discard;" + .endl(); + +const srcBodyFrag = "" + .endl() + "if(MOD_discard>0.0) discard;" + .endl(); + + +const mod = new CGL.ShaderModifier(cgl, op.name); + +mod.addModule({ + "title": op.name, + "name": "MODULE_VERTEX_POSITION", + srcHeadVert, + srcBodyVert +}); + +mod.addModule({ + "title": op.name, + "name": "MODULE_COLOR", + "srcHeadFrag": srcHeadFrag, + "srcBodyFrag": srcBodyFrag +}); + +mod.addUniform("2f", "MOD_vertLimit", limitMin,limitMax); +inv.onChange=updateDefines; + + +function updateDefines() +{ + mod.toggleDefine("MOD_INVERT",inv.get()); +} + +render.onTriggered = function () +{ + mod.bind(); + trigger.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.ShaderEffects.VertexNumberLimit_v2.prototype = new CABLES.Op(); +CABLES.OPS["3c1043bd-e65d-42ea-a154-456f235b197c"]={f:Ops.Gl.ShaderEffects.VertexNumberLimit_v2,objName:"Ops.Gl.ShaderEffects.VertexNumberLimit_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.VertexPositionFromTexture_v2 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.VertexPositionFromTexture_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"vertposbody_vert":"vec4 col=texture(MOD_tex,texCoord);\n\nvec3 MOD_pos=col.xyz;\n\n#ifdef MOD_ADD\npos.xyz+=MOD_pos.xyz;\n#endif\n\n#ifdef MOD_ABS\npos.xyz=MOD_pos.xyz;\n#endif\n\n",}; +const + render = op.inTrigger("render"), + inTex = op.inTexture("Texture"), + inMode = op.inSwitch("Mode", ["Absolute", "Add"], "Absolute"), + trigger = op.outTrigger("Trigger"); + +const cgl = op.patch.cgl; + +const mod = new CGL.ShaderModifier(cgl, op.name); +mod.addModule({ + "priority": 2, + "title": op.name, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": "", + "srcBodyVert": attachments.vertposbody_vert +}); + +mod.addUniformVert("t", "MOD_tex"); +inMode.onChange = updateDefines; +render.onTriggered = doRender; +updateDefines(); + +function updateDefines() +{ + mod.toggleDefine("MOD_ADD", inMode.get() == "Add"); + mod.toggleDefine("MOD_ABS", inMode.get() == "Absolute"); +} + +function doRender() +{ + mod.bind(); + if (inTex.get())mod.pushTexture("MOD_tex", inTex.get().tex); + + trigger.trigger(); + mod.unbind(); +} + + +}; + +Ops.Gl.ShaderEffects.VertexPositionFromTexture_v2.prototype = new CABLES.Op(); +CABLES.OPS["30eea555-afda-456e-9c50-9a40b370fa1f"]={f:Ops.Gl.ShaderEffects.VertexPositionFromTexture_v2,objName:"Ops.Gl.ShaderEffects.VertexPositionFromTexture_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShaderEffects.VertexWobble_v2 +// +// ************************************************************** + +Ops.Gl.ShaderEffects.VertexWobble_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"sinewobble_vert":"\n#ifndef MOD_WORLDSPACE\n vec4 MOD_vertPos=vec4(vPosition,1.0);\n#endif\n#ifdef MOD_WORLDSPACE\n vec4 MOD_vertPos=mMatrix*pos;\n#endif\n\n#ifdef MOD_AREA_SPHERE\n float MOD_de=distance(\n MOD_posSize.xyz,\n vec3(MOD_vertPos.x,MOD_vertPos.y,MOD_vertPos.z)\n );\n#endif\n\n#ifdef MOD_AREA_BOX\n float MOD_de=0.0;\n if(abs(MOD_vertPos.y-MOD_posSize.y)>MOD_posSize.w ||\n abs(MOD_vertPos.x-MOD_posSize.x)>MOD_posSize.w ||\n abs(MOD_vertPos.z-MOD_posSize.z)>MOD_posSize.w ) MOD_de=1.0;\n#endif\n\n#ifdef MOD_AREA_AXIS_X\n float MOD_de=abs(MOD_posSize.x-MOD_vertPos.x);\n#endif\n#ifdef MOD_AREA_AXIS_Y\n float MOD_de=abs(MOD_posSize.y-MOD_vertPos.y);\n#endif\n#ifdef MOD_AREA_AXIS_Z\n float MOD_de=abs(MOD_posSize.z-MOD_vertPos.z);\n#endif\n\n#ifdef MOD_AREA_AXIS_X_INFINITE\n float MOD_de=MOD_posSize.x-MOD_vertPos.x;\n#endif\n#ifdef MOD_AREA_AXIS_Y_INFINITE\n float MOD_de=MOD_posSize.y-MOD_vertPos.y;\n#endif\n#ifdef MOD_AREA_AXIS_Z_INFINITE\n float MOD_de=MOD_posSize.z-MOD_vertPos.z;\n#endif\n\n#ifndef MOD_AREA_BOX\n MOD_de=1.0-smoothstep(MOD_falloff,MOD_posSize.w,MOD_de);\n#endif\n\n#ifdef MOD_AREA_INVERT\n MOD_de=1.0-MOD_de;\n#endif\n\nfloat MOD_v=0.0;\n\n#ifdef MOD_SRC_XZ\n MOD_v=(MOD_vertPos.x+MOD_vertPos.z);\n#endif\n#ifdef MOD_SRC_XY\n MOD_v=(MOD_vertPos.x+MOD_vertPos.y);\n#endif\n#ifdef MOD_SRC_X\n MOD_v=MOD_vertPos.x;\n#endif\n#ifdef MOD_SRC_Y\n MOD_v=MOD_vertPos.y;\n#endif\n#ifdef MOD_SRC_Z\n MOD_v=MOD_vertPos.z;\n#endif\n\n\nfloat MOD_amnt=MOD_amount*MOD_de;\n\nMOD_v=sin( (MOD_time)+( MOD_v*MOD_scale ) ) ;\n#ifdef MOD_POSITIVE\n MOD_v=(MOD_v+1.0)/2.0;\n#endif\nMOD_v*=MOD_amnt;\n\n\n\n\n#ifdef MOD_TO_AXIS_X\n pos.x+=MOD_v;\n// norm.x+=MOD_v;\n#endif\n\n#ifdef MOD_TO_AXIS_Y\n pos.y+=MOD_v;\n// norm.y+=MOD_v;\n#endif\n\n#ifdef MOD_TO_AXIS_Z\n pos.z+=MOD_v;\n// norm.z+=MOD_v;\n#endif\n\n// norm=normalize(norm);\n\n\n\n\n\n",}; +let self = this; +const cgl = op.patch.cgl; + +const render = op.inTrigger("render"); +let src = op.inValueSelect("Source", [ + "X * Z + Time", + "X * Y + Time", + "X + Time", + "Y + Time", + "Z + Time"], "X * Z + Time"); + +const + amount = op.inValueSlider("amount", 0.1), + inTime=op.inFloat("Time",0), + mul = op.inValueFloat("Scale", 3), + toAxisX = op.inValueBool("axisX", true), + toAxisY = op.inValueBool("axisY", true), + toAxisZ = op.inValueBool("axisZ", true), + positive = op.inSwitch("Range",['-1 to 1','0 to 1'],'-1 to 1'), + + inArea = op.inValueSelect("Area", ["Sphere", "Box", "Axis X", "Axis Y", "Axis Z", "Axis X Infinite", "Axis Y Infinite", "Axis Z Infinite"], "Sphere"), + inSize = op.inValue("Size", 1), + inFalloff = op.inValueSlider("Falloff", 0), + + x = op.inValue("x"), + y = op.inValue("y"), + z = op.inValue("z"), + inWorldSpace = op.inValueBool("WorldSpace", true), + inInvert = op.inValueBool("Invert"), + + next = this.outTrigger("trigger"); + +op.setPortGroup("Area",[inArea,inSize,x,y,z,inFalloff,inWorldSpace,inInvert]); + +positive.onChange= +inArea.onChange= + inWorldSpace.onChange= + inSize.onChange= + src.onChange = + toAxisZ.onChange = + toAxisX.onChange = + toAxisY.onChange = setDefines; + +const srcHeadVert = ""; +// let startTime = CABLES.now() / 1000.0; +const mod = new CGL.ShaderModifier(cgl, op.name); + +mod.addModule({ + "title": op.name, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": srcHeadVert, + "srcBodyVert": attachments.sinewobble_vert +}); + +mod.addUniform("4f", "MOD_posSize", x, y, z,inSize); +mod.addUniformVert("f", "MOD_time", inTime); +mod.addUniformVert("f", "MOD_amount", amount); +mod.addUniformVert("f", "MOD_scale", mul); +mod.addUniformVert("f", "MOD_falloff", inFalloff); + +setDefines(); + +function setDefines() +{ + mod.toggleDefine("MOD_AREA_INVERT", inInvert.get()); + mod.toggleDefine("MOD_POSITIVE", positive.get()=="0 to 1"); + + mod.toggleDefine("MOD_WORLDSPACE", inWorldSpace.get() ); + mod.toggleDefine("MOD_AREA_AXIS_X", inArea.get() == "Axis X"); + mod.toggleDefine("MOD_AREA_AXIS_Y", inArea.get() == "Axis Y"); + mod.toggleDefine("MOD_AREA_AXIS_Z", inArea.get() == "Axis Z"); + mod.toggleDefine("MOD_AREA_AXIS_X_INFINITE", inArea.get() == "Axis X Infinite"); + mod.toggleDefine("MOD_AREA_AXIS_Y_INFINITE", inArea.get() == "Axis Y Infinite"); + mod.toggleDefine("MOD_AREA_AXIS_Z_INFINITE", inArea.get() == "Axis Z Infinite"); + mod.toggleDefine("MOD_AREA_SPHERE", inArea.get() == "Sphere"); + mod.toggleDefine("MOD_AREA_BOX", inArea.get() == "Box"); + + mod.toggleDefine("MOD_TO_AXIS_X", toAxisX.get()); + mod.toggleDefine("MOD_TO_AXIS_Y", toAxisY.get()); + mod.toggleDefine("MOD_TO_AXIS_Z", toAxisZ.get()); + mod.toggleDefine("MOD_SRC_XZ", !src.get() || src.get() == "X * Z + Time" || src.get() === ""); + mod.toggleDefine("MOD_SRC_XY", src.get() == "X * Y + Time"); + mod.toggleDefine("MOD_SRC_X", src.get() == "X + Time"); + mod.toggleDefine("MOD_SRC_Y", src.get() == "Y + Time"); + mod.toggleDefine("MOD_SRC_Z", src.get() == "Z + Time"); +} + +render.onTriggered = function () +{ + mod.bind(); + next.trigger(); + mod.unbind(); +}; + + +}; + +Ops.Gl.ShaderEffects.VertexWobble_v2.prototype = new CABLES.Op(); +CABLES.OPS["76983d1c-be6d-453d-b34f-472efe8221e7"]={f:Ops.Gl.ShaderEffects.VertexWobble_v2,objName:"Ops.Gl.ShaderEffects.VertexWobble_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.ShowNormals_v2 +// +// ************************************************************** + +Ops.Gl.ShowNormals_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"colorize_normals_frag":"UNI vec4 inColor;\n\nvoid main() {\n {{MODULE_BEGIN_FRAG}}\n vec4 col = inColor;\n\n {{MODULE_COLOR}}\n\n outColor = col;\n}",}; +const + render = op.inTrigger("render"), + inDoRender = op.inBool("Draw", true), + geometry = op.inObject("geometry", null, "geometry"), + dropdown = op.inSwitch("Vectors", ["Normals", "Tangents", "Bitangents"], "Normals"), + mul = op.inValueFloat("Length", 0.1), + inColorize = op.inBool("Colorize", true), + inR = op.inFloat("R", 0), + inG = op.inFloat("G", 0.8), + inB = op.inFloat("B", 0), + inA = op.inFloatSlider("A", 1), + trigger = op.outTrigger("trigger"), + outGeom = op.outObject("Line Geom", null, "geometry"); + +inR.setUiAttribs({ "colorPick": true, "greyout": true }); +inG.setUiAttribs({ "greyout": true }); +inB.setUiAttribs({ "greyout": true }); +inA.setUiAttribs({ "greyout": true }); + +geometry.ignoreValueSerialize = true; + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "colorizeNormals"); +shader.setSource(shader.getDefaultVertexShader(), attachments.colorize_normals_frag); +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); +shader.glPrimitive = cgl.gl.LINES; + +const inColorUniform = new CGL.Uniform(shader, "4f", "inColor", inR, inG, inB, inA); + +geometry.onChange = mul.onChange = dropdown.onChange = buildMesh; +inColorize.onChange = handleColorizeChange; +handleColorizeChange(); + +let mesh = null; +const position = vec3.create(); + +buildMesh(); + +function handleColorizeChange() +{ + inR.setUiAttribs({ "greyout": !inColorize.get() }); + inG.setUiAttribs({ "greyout": !inColorize.get() }); + inB.setUiAttribs({ "greyout": !inColorize.get() }); + inA.setUiAttribs({ "greyout": !inColorize.get() }); + + if (inColorize.get()) + { + shader.setSource(shader.getDefaultVertexShader(), attachments.colorize_normals_frag); + } + else + { + shader.setSource(shader.getDefaultVertexShader(), shader.getDefaultFragmentShader()); + } +} + +function buildMesh() +{ + const geom = new CGL.Geometry("shownormals"); + + const points = []; + const tc = []; + const geometryInput = geometry.get(); + + if (geometryInput && geometryInput.vertices) + { + op.setUiError("noVertices", null); + for (let i = 0; i < geometryInput.vertices.length; i += 3) + { + points.push(geometryInput.vertices[i + 0]); + points.push(geometryInput.vertices[i + 1]); + points.push(geometryInput.vertices[i + 2]); + + tc.push(0, 1); + tc.push(0, 1); + if (dropdown.get() === "Normals") + { + if (!geometryInput.vertexNormals || !geometryInput.vertexNormals.length) + { + op.setUiError("noNormals", "Input geometry has no normals!", 1); + } + else + { + op.setUiError("noNormals", null); + points.push(geometryInput.vertices[i + 0] + geometryInput.vertexNormals[i + 0] * mul.get()); + points.push(geometryInput.vertices[i + 1] + geometryInput.vertexNormals[i + 1] * mul.get()); + points.push(geometryInput.vertices[i + 2] + geometryInput.vertexNormals[i + 2] * mul.get()); + } + } + + if (dropdown.get() === "Tangents") + { + if (!geometryInput.tangents || !geometryInput.tangents.length) + { + op.setUiError("noTangents", "Input geometry has no tangents!", 1); + } + else + { + op.setUiError("noTangents", null); + points.push(geometryInput.vertices[i + 0] + geometryInput.tangents[i + 0] * mul.get()); + points.push(geometryInput.vertices[i + 1] + geometryInput.tangents[i + 1] * mul.get()); + points.push(geometryInput.vertices[i + 2] + geometryInput.tangents[i + 2] * mul.get()); + } + } + if (dropdown.get() === "Bitangents") + { + if (!geometryInput.biTangents || !geometryInput.biTangents.length) + { + op.setUiError("noBitangents", "Input geometry has no bitangents!", 1); + } + else + { + op.setUiError("noBitangents", null); + points.push(geometryInput.vertices[i + 0] + geometryInput.biTangents[i + 0] * mul.get()); + points.push(geometryInput.vertices[i + 1] + geometryInput.biTangents[i + 1] * mul.get()); + points.push(geometryInput.vertices[i + 2] + geometryInput.biTangents[i + 2] * mul.get()); + } + } + } + + geom.vertices = points; + geom.texCoords = tc; + geom.glPrimitive = cgl.gl.LINES; + + if (mesh) mesh.dispose(); + mesh = new CGL.Mesh(cgl, geom); + + outGeom.set(null); + outGeom.set(geom); + } + else + { + outGeom.set(null); + if (mesh) mesh.dispose(); + mesh = null; + op.setUiError("noVertices", "There is no input geometry or input geometry has no vertices!", 0); + } +} + +render.onTriggered = function () +{ + if (geometry.get() && inDoRender.get()) + { + if (!shader) return; + if (mesh) mesh.render(shader); + } + + trigger.trigger(); +}; + + +}; + +Ops.Gl.ShowNormals_v2.prototype = new CABLES.Op(); +CABLES.OPS["3d68b4d4-2945-48bf-8fc9-30567946deda"]={f:Ops.Gl.ShowNormals_v2,objName:"Ops.Gl.ShowNormals_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.SurfaceScatter_v2 +// +// ************************************************************** + +Ops.Gl.SurfaceScatter_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Render"), + inDraw = op.inValueBool("draw", true), + inNum = op.inValueInt("Num", 100), + inGeomSurface = op.inObject("Geom Surface"), + // inGeom = op.inObject("Geometry"), + inDistribution = op.inValueSelect("Distribution", ["Vertex", "Triangle Center", "Triangle Side", "Random Triangle Point"], "Vertex"), + inVariety = op.inValueSelect("Selection", ["Random", "Sequential"], "Random"), + seed = op.inValueFloat("Random Seed"), + inSizeMin = op.inValueSlider("Size min", 1.0), + inSizeMax = op.inValueSlider("Size max", 1.0), + inDoLimit = op.inValueBool("Limit", false), + inLimit = op.inValueInt("Limit Num", 0), + inRotateRandom = op.inValueBool("Random Rotate", true), + outNext = op.outTrigger("Next"), + outArrPositions = op.outArray("Positions", 3), + outArrScale = op.outArray("Scale", 3), + outArrRotations = op.outArray("Quaternions", 4); +const cgl = op.patch.cgl; +const mod = null; +let recalc = true; + +let matrixArray = new Float32Array(1); +const m = mat4.create(); +const qAxis = vec3.create(); + +op.setPortGroup("Size", [inSizeMin, inSizeMax]); +op.setPortGroup("Distribution", [inDistribution, inVariety, seed]); + +inDistribution.onChange = + seed.onChange = + inNum.onChange = + inRotateRandom.onChange = + inSizeMin.onChange = + inSizeMax.onChange = + inVariety.onChange = + inGeomSurface.onChange = reset; +render.onTriggered = doRender; + +const arrPositions = []; +const arrRotations = []; +const arrScale = []; + +function uniqueIndices(oldCount, newCount, randomize) +{ + function fisherYatesShuffle(array) + { + Math.randomSeed = seed.get(); + let i = 0; + let j = 0; + let temp = null; + + for (i = array.length - 1; i > 0; i -= 1) + { + j = Math.floor(Math.seededRandom() * (i + 1)); + temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } + } + + const arr = []; + arr.length = newCount; + + if (newCount > oldCount) + { + arr.length = newCount; + for (let i = 0; i < newCount; i++) arr[i] = i % (oldCount); + } + else + { + arr.length = oldCount; + for (let i = 0; i < oldCount; i++) arr[i] = i; + } + + if (randomize)fisherYatesShuffle(arr); + return arr; +} + +function getEuler(out, quat) +{ + const x = quat[0], + y = quat[1], + z = quat[2], + w = quat[3], + x2 = x * x, + y2 = y * y, + z2 = z * z, + w2 = w * w; + const unit = x2 + y2 + z2 + w2; + const test = x * w - y * z; + if (test > 0.499995 * unit) + { // TODO: Use glmatrix.EPSILON + // singularity at the north pole + out[0] = Math.PI / 2; + out[1] = 2 * Math.atan2(y, x); + out[2] = 0; + } + else if (test < -0.499995 * unit) + { // TODO: Use glmatrix.EPSILON + // singularity at the south pole + out[0] = -Math.PI / 2; + out[1] = 2 * Math.atan2(y, x); + out[2] = 0; + } + else + { + out[0] = Math.asin(2 * (x * z - w * y)); + out[1] = Math.atan2(2 * (x * w + y * z), 1 - 2 * (z2 + w2)); + out[2] = Math.atan2(2 * (x * y + z * w), 1 - 2 * (y2 + z2)); + } + // TODO: Return them as degrees and not as radians + return out; +} + +function setup() +{ + recalc = false; + + op.toWorkPortsNeedToBeLinkedReset(); + + // if (inDraw.get()) + // { + // op.toWorkPortsNeedToBeLinked(inGeom); + // } + const geom = inGeomSurface.get(); + const num = Math.abs(Math.floor(inNum.get())); + const m = mat4.create(); + const q = quat.create(); + const vm2 = vec3.create(); + const qMat = mat4.create(); + const norm = vec3.create(); + + if (!geom) return; + + Math.randomSeed = seed.get(); + + const DISTMODE_VERTEX = 0; + const DISTMODE_TRIANGLE_CENTER = 1; + const DISTMODE_TRIANGLE_SIDE = 2; + const DISTMODE_TRIANGLE_RANDOM = 3; + + let distMode = 0; + if (inDistribution.get() == "Triangle Center")distMode = DISTMODE_TRIANGLE_CENTER; + else if (inDistribution.get() == "Triangle Side")distMode = DISTMODE_TRIANGLE_SIDE; + else if (inDistribution.get() == "Random Triangle Point")distMode = DISTMODE_TRIANGLE_RANDOM; + + if (matrixArray.length != num * 16) matrixArray = new Float32Array(num * 16); + + let faces = geom.verticesIndices; + if (!geom.isIndexed()) + { + faces = []; + for (let i = 0; i < geom.vertices.length / 3; i++) faces[i] = i; + } + + const indices = uniqueIndices(faces.length / 3, num, inVariety.get() == "Random"); + + arrScale.length = arrPositions.length = num * 3; + arrRotations.length = num * 4; + + for (let i = 0; i < num; i++) + { + const index = indices[i]; + const index3 = index * 3; + + let px = 0; + let py = 0; + let pz = 0; + + mat4.identity(m); + + let nx = geom.vertexNormals[faces[index3] * 3 + 0]; + let ny = geom.vertexNormals[faces[index3] * 3 + 1]; + let nz = geom.vertexNormals[faces[index3] * 3 + 2]; + + if (distMode == DISTMODE_VERTEX) + { + px = geom.vertices[faces[index3] * 3 + 0]; + py = geom.vertices[faces[index3] * 3 + 1]; + pz = geom.vertices[faces[index3] * 3 + 2]; + } + else if (distMode == DISTMODE_TRIANGLE_CENTER) + { + px = (geom.vertices[faces[index3] * 3 + 0] + geom.vertices[faces[index3 + 1] * 3 + 0] + geom.vertices[faces[index3 + 2] * 3 + 0]) / 3; + py = (geom.vertices[faces[index3] * 3 + 1] + geom.vertices[faces[index3 + 1] * 3 + 1] + geom.vertices[faces[index3 + 2] * 3 + 1]) / 3; + pz = (geom.vertices[faces[index3] * 3 + 2] + geom.vertices[faces[index3 + 1] * 3 + 2] + geom.vertices[faces[index3 + 2] * 3 + 2]) / 3; + + nx = (geom.vertexNormals[faces[index3] * 3 + 0] + geom.vertexNormals[faces[index3 + 1] * 3 + 0] + geom.vertexNormals[faces[index3 + 2] * 3 + 0]) / 3; + ny = (geom.vertexNormals[faces[index3] * 3 + 1] + geom.vertexNormals[faces[index3 + 1] * 3 + 1] + geom.vertexNormals[faces[index3 + 2] * 3 + 1]) / 3; + nz = (geom.vertexNormals[faces[index3] * 3 + 2] + geom.vertexNormals[faces[index3 + 1] * 3 + 2] + geom.vertexNormals[faces[index3 + 2] * 3 + 2]) / 3; + } + else if (distMode == DISTMODE_TRIANGLE_SIDE) + { + const which = Math.round(Math.seededRandom() * 3.0); + const whichA = which; + let whichB = which + 1; + if (whichB > 2)whichB = 0; + + px = (geom.vertices[faces[index3 + whichA] * 3 + 0] + geom.vertices[faces[index3 + whichB] * 3 + 0]) / 2; + py = (geom.vertices[faces[index3 + whichA] * 3 + 1] + geom.vertices[faces[index3 + whichB] * 3 + 1]) / 2; + pz = (geom.vertices[faces[index3 + whichA] * 3 + 2] + geom.vertices[faces[index3 + whichB] * 3 + 2]) / 2; + } + else if (distMode == DISTMODE_TRIANGLE_RANDOM) + { + let r = Math.seededRandom(); + const p1x = CABLES.map(r, 0, 1, geom.vertices[(faces[index3 + 0]) * 3 + 0], geom.vertices[(faces[index3 + 1]) * 3 + 0]); + const p1y = CABLES.map(r, 0, 1, geom.vertices[(faces[index3 + 0]) * 3 + 1], geom.vertices[(faces[index3 + 1]) * 3 + 1]); + const p1z = CABLES.map(r, 0, 1, geom.vertices[(faces[index3 + 0]) * 3 + 2], geom.vertices[(faces[index3 + 1]) * 3 + 2]); + + const n1x = CABLES.map(r, 0, 1, geom.vertexNormals[(faces[index3 + 0]) * 3 + 0], geom.vertexNormals[(faces[index3 + 1]) * 3 + 0]); + const n1y = CABLES.map(r, 0, 1, geom.vertexNormals[(faces[index3 + 0]) * 3 + 1], geom.vertexNormals[(faces[index3 + 1]) * 3 + 1]); + const n1z = CABLES.map(r, 0, 1, geom.vertexNormals[(faces[index3 + 0]) * 3 + 2], geom.vertexNormals[(faces[index3 + 1]) * 3 + 2]); + + r = Math.seededRandom(); + const p2x = CABLES.map(r, 0, 1, geom.vertices[(faces[index3 + 1]) * 3 + 0], geom.vertices[(faces[index3 + 2]) * 3 + 0]); + const p2y = CABLES.map(r, 0, 1, geom.vertices[(faces[index3 + 1]) * 3 + 1], geom.vertices[(faces[index3 + 2]) * 3 + 1]); + const p2z = CABLES.map(r, 0, 1, geom.vertices[(faces[index3 + 1]) * 3 + 2], geom.vertices[(faces[index3 + 2]) * 3 + 2]); + + const n2x = CABLES.map(r, 0, 1, geom.vertexNormals[(faces[index3 + 1]) * 3 + 0], geom.vertexNormals[(faces[index3 + 2]) * 3 + 0]); + const n2y = CABLES.map(r, 0, 1, geom.vertexNormals[(faces[index3 + 1]) * 3 + 1], geom.vertexNormals[(faces[index3 + 2]) * 3 + 1]); + const n2z = CABLES.map(r, 0, 1, geom.vertexNormals[(faces[index3 + 1]) * 3 + 2], geom.vertexNormals[(faces[index3 + 2]) * 3 + 2]); + + r = Math.seededRandom(); + const p3x = CABLES.map(r, 0, 1, geom.vertices[(faces[index3 + 2]) * 3 + 0], geom.vertices[(faces[index3 + 0]) * 3 + 0]); + const p3y = CABLES.map(r, 0, 1, geom.vertices[(faces[index3 + 2]) * 3 + 1], geom.vertices[(faces[index3 + 0]) * 3 + 1]); + const p3z = CABLES.map(r, 0, 1, geom.vertices[(faces[index3 + 2]) * 3 + 2], geom.vertices[(faces[index3 + 0]) * 3 + 2]); + + const n3x = CABLES.map(r, 0, 1, geom.vertexNormals[(faces[index3 + 2]) * 3 + 0], geom.vertexNormals[(faces[index3 + 0]) * 3 + 0]); + const n3y = CABLES.map(r, 0, 1, geom.vertexNormals[(faces[index3 + 2]) * 3 + 1], geom.vertexNormals[(faces[index3 + 0]) * 3 + 1]); + const n3z = CABLES.map(r, 0, 1, geom.vertexNormals[(faces[index3 + 2]) * 3 + 2], geom.vertexNormals[(faces[index3 + 0]) * 3 + 2]); + + px = (p1x + p2x + p3x) / 3; + py = (p1y + p2y + p3y) / 3; + pz = (p1z + p2z + p3z) / 3; + + nx = (n1x + n2x + n3x) / 3; + ny = (n1y + n2y + n3y) / 3; + nz = (n1z + n2z + n3z) / 3; + } + + arrPositions[i * 3 + 0] = px; + arrPositions[i * 3 + 1] = py; + arrPositions[i * 3 + 2] = pz; + mat4.translate(m, m, [px, py, pz]); + + // rotate to normal direction + vec3.set(norm, nx, ny, nz); + vec3.set(vm2, 1, 0, 0); + quat.rotationTo(q, vm2, norm); + + // mat4.fromQuat(qMat, q); + // mat4.mul(m,m,qMat); + + // random rotate around up axis + if (inRotateRandom.get()) + { + const mr = mat4.create(); + // let qbase=quat.create(); + quat.rotateX(q, q, Math.seededRandom() * 360 * CGL.DEG2RAD); + // mat4.fromQuat(mr,qbase); + // mat4.mul(m,m,mr); + } + + // rotate -90 degree + const mr2 = mat4.create(); + // let qbase2=quat.create(); + quat.rotateZ(q, q, -90 * CGL.DEG2RAD); + mat4.fromQuat(mr2, q); + mat4.mul(m, m, mr2); + + // scale + if (inSizeMin.get() != 1.0 || inSizeMax != 1.0) + { + const sc = inSizeMin.get() + (Math.seededRandom() * (inSizeMax.get() - inSizeMin.get())); + mat4.scale(m, m, [sc, sc, sc]); + + arrScale[i * 3 + 0] = + arrScale[i * 3 + 1] = + arrScale[i * 3 + 2] = sc; + } + + // //quaternion to euler, KINDA works, but not really :/ + // let finalq=q;// + // let finalq=quat.create(); + // mat4.getRotation(finalq,m); + + // function clamp(v) + // { + // return Math.min(1,Math.max(-1,v) ) ; + // } + + // let yaw = Math.atan2(2.0*(finalq[1]*finalq[2] + finalq[3]*finalq[0]), finalq[3]*finalq[3] - finalq[0]*finalq[0] - finalq[1]*finalq[1] + finalq[2]*finalq[2]); + // let pitch = Math.asin( clamp( -2.0*(finalq[0]*finalq[2] - finalq[3]*finalq[1]))); + // let roll = Math.atan2(2.0*(finalq[0]*finalq[1] + finalq[3]*finalq[2]), finalq[3]*finalq[3] + finalq[0]*finalq[0] - finalq[1]*finalq[1] - finalq[2]*finalq[2]); + + // arrRotations[i*3+0]=360-(pitch*CGL.RAD2DEG); + // arrRotations[i*3+1]=360-(yaw*CGL.RAD2DEG); + // arrRotations[i*3+2]=(roll*CGL.RAD2DEG); + + const rotDeg = vec3.create(); + // quat.getAxisAngle(rotDeg,finalq); + getEuler(rotDeg, q); + + arrRotations[i * 4 + 0] = q[0]; + arrRotations[i * 4 + 1] = q[1]; + arrRotations[i * 4 + 2] = q[2]; + arrRotations[i * 4 + 3] = q[3]; + + // save + for (let a = 0; a < 16; a++) + { + matrixArray[i * 16 + a] = m[a]; + } + } + + outArrScale.set(null); + outArrScale.set(arrScale); + + outArrRotations.set(null); + outArrRotations.set(arrRotations); + + outArrPositions.set(null); + outArrPositions.set(arrPositions); +} + +function reset() +{ + recalc = true; +} + +function doRender() +{ + if (recalc)setup(); + recalc = false; + + outNext.trigger(); +} + + +}; + +Ops.Gl.SurfaceScatter_v2.prototype = new CABLES.Op(); +CABLES.OPS["18eb1e62-80fe-41ce-a57b-15653d00925b"]={f:Ops.Gl.SurfaceScatter_v2,objName:"Ops.Gl.SurfaceScatter_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TesselateGeometry +// +// ************************************************************** + +Ops.Gl.TesselateGeometry = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inGeom = op.inObject("Geometry"); +const inTimes = op.inValueInt("Iterations", 1); +const outGeom = op.outObject("Result"); +const outVertices = op.outNumber("Num Vertices"); + +inGeom.onChange = update; +inTimes.onChange = update; + +function tesselateTC(tc, x1, y1, x2, y2, x3, y3) +{ + tc.push(x1); + tc.push(y1); + + tc.push((x1 + x2) / 2); + tc.push((y1 + y2) / 2); + + tc.push((x1 + x3) / 2); + tc.push((y1 + y3) / 2); + + // -- + + tc.push((x1 + x2) / 2); + tc.push((y1 + y2) / 2); + + tc.push(x2); + tc.push(y2); + + tc.push((x2 + x3) / 2); + tc.push((y2 + y3) / 2); + + // -- + + tc.push((x2 + x3) / 2); + tc.push((y2 + y3) / 2); + + tc.push(x3); + tc.push(y3); + + tc.push((x1 + x3) / 2); + tc.push((y1 + y3) / 2); + + // -- + + tc.push((x1 + x2) / 2); + tc.push((y1 + y2) / 2); + + tc.push((x2 + x3) / 2); + tc.push((y2 + y3) / 2); + + tc.push((x1 + x3) / 2); + tc.push((y1 + y3) / 2); +} + +function tesselate(vertices, x1, y1, z1, x2, y2, z2, x3, y3, z3) +{ + vertices.push(x1); + vertices.push(y1); + vertices.push(z1); + + vertices.push((x1 + x2) / 2); + vertices.push((y1 + y2) / 2); + vertices.push((z1 + z2) / 2); + + vertices.push((x1 + x3) / 2); + vertices.push((y1 + y3) / 2); + vertices.push((z1 + z3) / 2); + + // -- + + vertices.push((x1 + x2) / 2); + vertices.push((y1 + y2) / 2); + vertices.push((z1 + z2) / 2); + + vertices.push(x2); + vertices.push(y2); + vertices.push(z2); + + vertices.push((x2 + x3) / 2); + vertices.push((y2 + y3) / 2); + vertices.push((z2 + z3) / 2); + + // -- + + vertices.push((x2 + x3) / 2); + vertices.push((y2 + y3) / 2); + vertices.push((z2 + z3) / 2); + + vertices.push(x3); + vertices.push(y3); + vertices.push(z3); + + vertices.push((x1 + x3) / 2); + vertices.push((y1 + y3) / 2); + vertices.push((z1 + z3) / 2); + + // -- + + vertices.push((x1 + x2) / 2); + vertices.push((y1 + y2) / 2); + vertices.push((z1 + z2) / 2); + + vertices.push((x2 + x3) / 2); + vertices.push((y2 + y3) / 2); + vertices.push((z2 + z3) / 2); + + vertices.push((x1 + x3) / 2); + vertices.push((y1 + y3) / 2); + vertices.push((z1 + z3) / 2); +} + +function tesselateGeom(oldGeom) +{ + const geom = new CGL.Geometry(op.name); + const vertices = []; + const norms = []; + const biTangents = []; + const tangents = []; + const tc = []; + + let i, j, k; + + if (oldGeom.verticesIndices.length > 0) + { + for (i = 0; i < oldGeom.verticesIndices.length; i += 3) + { + for (j = 0; j < 4; j++) + for (k = 0; k < 3; k++) + { + norms.push( + oldGeom.vertexNormals[oldGeom.verticesIndices[i + k] * 3 + 0], + oldGeom.vertexNormals[oldGeom.verticesIndices[i + k] * 3 + 1], + oldGeom.vertexNormals[oldGeom.verticesIndices[i + k] * 3 + 2] + ); + + if (oldGeom.tangents) + tangents.push( + oldGeom.tangents[oldGeom.verticesIndices[i + k] * 3 + 0], + oldGeom.tangents[oldGeom.verticesIndices[i + k] * 3 + 1], + oldGeom.tangents[oldGeom.verticesIndices[i + k] * 3 + 2] + ); + + if (oldGeom.biTangents) + biTangents.push( + oldGeom.biTangents[oldGeom.verticesIndices[i + k] * 3 + 0], + oldGeom.biTangents[oldGeom.verticesIndices[i + k] * 3 + 1], + oldGeom.biTangents[oldGeom.verticesIndices[i + k] * 3 + 2] + ); + } + + tesselate(vertices, + oldGeom.vertices[oldGeom.verticesIndices[i + 0] * 3 + 0], + oldGeom.vertices[oldGeom.verticesIndices[i + 0] * 3 + 1], + oldGeom.vertices[oldGeom.verticesIndices[i + 0] * 3 + 2], + + oldGeom.vertices[oldGeom.verticesIndices[i + 1] * 3 + 0], + oldGeom.vertices[oldGeom.verticesIndices[i + 1] * 3 + 1], + oldGeom.vertices[oldGeom.verticesIndices[i + 1] * 3 + 2], + + oldGeom.vertices[oldGeom.verticesIndices[i + 2] * 3 + 0], + oldGeom.vertices[oldGeom.verticesIndices[i + 2] * 3 + 1], + oldGeom.vertices[oldGeom.verticesIndices[i + 2] * 3 + 2] + ); + + tesselateTC(tc, + oldGeom.texCoords[oldGeom.verticesIndices[i + 0] * 2 + 0], + oldGeom.texCoords[oldGeom.verticesIndices[i + 0] * 2 + 1], + + oldGeom.texCoords[oldGeom.verticesIndices[i + 1] * 2 + 0], + oldGeom.texCoords[oldGeom.verticesIndices[i + 1] * 2 + 1], + + oldGeom.texCoords[oldGeom.verticesIndices[i + 2] * 2 + 0], + oldGeom.texCoords[oldGeom.verticesIndices[i + 2] * 2 + 1] + ); + } + } + else + { + if (oldGeom.vertices.length > 0) + { + for (i = 0; i < oldGeom.vertices.length; i += 9) + { + for (j = 0; j < 4; j++) + { + for (k = 0; k < 9; k++) + norms.push(oldGeom.vertexNormals[i + k]); + + if (oldGeom.tangents) + for (k = 0; k < 9; k++) + tangents.push(oldGeom.tangents[i + k]); + + if (oldGeom.biTangents) + for (k = 0; k < 9; k++) + biTangents.push(oldGeom.biTangents[i + k]); + } + + tesselate(vertices, + oldGeom.vertices[i + 0], + oldGeom.vertices[i + 1], + oldGeom.vertices[i + 2], + + oldGeom.vertices[i + 3], + oldGeom.vertices[i + 4], + oldGeom.vertices[i + 5], + + oldGeom.vertices[i + 6], + oldGeom.vertices[i + 7], + oldGeom.vertices[i + 8] + ); + + tesselateTC(tc, + oldGeom.texCoords[i / 9 * 6 + 0], + oldGeom.texCoords[i / 9 * 6 + 1], + + oldGeom.texCoords[i / 9 * 6 + 2], + oldGeom.texCoords[i / 9 * 6 + 3], + + oldGeom.texCoords[i / 9 * 6 + 4], + oldGeom.texCoords[i / 9 * 6 + 5] + + ); + } + } + } + + geom.vertexNormals = norms; + geom.setVertices(vertices); + geom.setTexCoords(tc); + geom.tangents = tangents; + geom.biTangents = biTangents; + return geom; +} + +function update() +{ + let geom = inGeom.get(); + if (!geom) return; + const startTime = CABLES.now(); + + for (let i = 0; i < inTimes.get(); i++) + { + geom = tesselateGeom(geom); + } + + outVertices.set(geom.vertices.length / 3); + + outGeom.set(null); + outGeom.set(geom); +} + + +}; + +Ops.Gl.TesselateGeometry.prototype = new CABLES.Op(); +CABLES.OPS["eb3f0bd8-211c-4336-a3ad-fa31c50d705d"]={f:Ops.Gl.TesselateGeometry,objName:"Ops.Gl.TesselateGeometry"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextMeshMSDF_v2 +// +// ************************************************************** + +Ops.Gl.TextMeshMSDF_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"textmeshsdf_frag":"\nUNI sampler2D tex0;\nUNI sampler2D tex1;\nUNI sampler2D tex2;\nUNI sampler2D tex3;\nIN vec2 texCoord;\nUNI vec4 color;\nUNI vec2 texSize;\n\n#ifdef BORDER\n UNI float borderWidth;\n UNI float borderSmooth;\n UNI vec3 colorBorder;\n#endif\n\n#ifdef TEXTURE_COLOR\nUNI sampler2D texMulColor;\n#endif\n#ifdef TEXTURE_MASK\nUNI sampler2D texMulMask;\n#endif\n\nIN float texIndex;\n\n#ifdef SHADOW\n UNI float shadowWidth;\n#endif\n\n\nfloat median(float r, float g, float b)\n{\n return max(min(r, g), min(max(r, g), b));\n}\n\nvoid main()\n{\n vec4 bgColor=vec4(0.0,0.0,0.0,0.0);\n vec4 fgColor=color;\n float opacity=1.0;\n\n #ifndef SDF\n if(int(texIndex)==0) outColor = texture(tex0, texCoord);\n if(int(texIndex)==1) outColor = texture(tex1, texCoord);\n if(int(texIndex)==2) outColor = texture(tex2, texCoord);\n if(int(texIndex)==3) outColor = texture(tex3, texCoord);\n\n return;\n #endif\n\n\n #ifdef TEXTURE_COLOR\n fgColor.rgb *= texture(texMulColor, vec2(0.0,0.0)).rgb; //todo texcoords from char positioning\n #endif\n #ifdef TEXTURE_MASK\n opacity *= texture(texMulMask, vec2(0.0,0.0)).r; //todo texcoords from char positioning\n #endif\n\n\n #ifdef SHADOW\n vec2 msdfUnit1 = texSize;\n vec2 tcv=vec2(texCoord.x-0.002,texCoord.y-0.002);\n vec3 smpl1;\n if(int(texIndex)==0) smpl1 = texture(tex0, tcv).rgb;\n if(int(texIndex)==1) smpl1 = texture(tex1, tcv).rgb;\n if(int(texIndex)==2) smpl1 = texture(tex2, tcv).rgb;\n if(int(texIndex)==3) smpl1 = texture(tex3, tcv).rgb;\n\n float sigDist1 = median(smpl1.r, smpl1.g, smpl1.b) - 0.001;\n float opacity1 = smoothstep(0.0,0.9,sigDist1*sigDist1);\n outColor = mix(bgColor, vec4(0.0,0.0,0.0,1.0), opacity1);\n #endif\n\n vec2 msdfUnit = 8.0/texSize;\n vec3 smpl;\n\n if(int(texIndex)==0) smpl = texture(tex0, texCoord).rgb;\n if(int(texIndex)==1) smpl = texture(tex1, texCoord).rgb;\n if(int(texIndex)==2) smpl = texture(tex2, texCoord).rgb;\n if(int(texIndex)==3) smpl = texture(tex3, texCoord).rgb;\n\n\n float sigDist = median(smpl.r, smpl.g, smpl.b) - 0.5;\n sigDist *= dot(msdfUnit, 0.5/fwidth(texCoord));\n opacity *= clamp(sigDist + 0.5, 0.0, 1.0);\n\n #ifdef BORDER\n float sigDist2 = median(smpl.r, smpl.g, smpl.b) - 0.01;\n float bw=borderWidth*0.6+0.24;\n float opacity2 = smoothstep(bw-borderSmooth,bw+borderSmooth,sigDist2*sigDist2);\n fgColor=mix(fgColor,vec4(colorBorder,1.0),1.0-opacity2);\n #endif\n\n if(color.a==0.0)discard;\n outColor = mix(outColor, fgColor, opacity*color.a);\n\n}\n\n","textmeshsdf_vert":"UNI sampler2D tex1;\nUNI sampler2D tex2;\nUNI sampler2D tex3;\nUNI sampler2D tex4;\n\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\n\nIN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN mat4 instMat;\nIN vec2 attrTexOffsets;\nIN vec2 attrSize;\nIN vec2 attrTcSize;\nIN float attrPage;\n\nOUT vec2 texCoord;\nOUT float texIndex;\n\nconst float mulSize=0.01;\n\nvoid main()\n{\n texCoord=(attrTexOffsets+attrTexCoord*attrTcSize);\n texCoord.y=1.0-texCoord.y;\n\n mat4 instMVMat=instMat;\n vec4 vert=vec4( vPosition, 1. );\n vert.x*=attrSize.x*mulSize;\n vert.y*=attrSize.y*mulSize;\n\n texIndex=attrPage+0.4; // strange ios rounding errors?!\n\n mat4 mvMatrix=viewMatrix * modelMatrix * instMVMat;\n\n gl_Position = projMatrix * mvMatrix * vert;\n}\n",}; +// https://soimy.github.io/msdf-bmfont-xml/ + +// antialiasing: +// https://github.com/Chlumsky/msdfgen/issues/22 + +const + render = op.inTrigger("Render"), + str = op.inString("Text", "cables"), + inFont = op.inDropDown("Font", [], "", true), + scale = op.inFloat("Scale", 0.25), + + letterSpace = op.inFloat("Letter Spacing", 0), + lineHeight = op.inFloat("Line Height", 1), + + align = op.inSwitch("Align", ["Left", "Center", "Right"], "Center"), + valign = op.inSwitch("Vertical Align", ["Zero", "Top", "Middle", "Bottom"], "Middle"), + + r = op.inValueSlider("r", 1), + g = op.inValueSlider("g", 1), + b = op.inValueSlider("b", 1), + a = op.inValueSlider("a", 1), + doSDF = op.inBool("SDF", true), + + inBorder = op.inBool("Border", false), + inBorderWidth = op.inFloatSlider("Border Width", 0.5), + inBorderSmooth = op.inFloatSlider("Smoothness", 0.25), + br = op.inValueSlider("Border r", 1), + bg = op.inValueSlider("Border g", 1), + bb = op.inValueSlider("Border b", 1), + + inShadow = op.inBool("Shadow", false), + + inTexColor = op.inTexture("Texture Color"), + inTexMask = op.inTexture("Texture Mask"), + + inPosArr = op.inArray("Positions"), + inScaleArr = op.inArray("Scalings"), + inRotArr = op.inArray("Rotations"), + + next = op.outTrigger("Next"), + outArr = op.outArray("Positions Original", null, 3), + outLines = op.outNumber("Num Lines"), + + outWidth = op.outNumber("Width"), + outHeight = op.outNumber("Height"), + outStartY = op.outNumber("Start Y"), + outNumChars = op.outNumber("Num Chars"); + +op.setPortGroup("Size", [letterSpace, lineHeight, scale]); +op.setPortGroup("Character Transformations", [inScaleArr, inRotArr, inPosArr]); +op.setPortGroup("Alignment", [align, valign]); +op.setPortGroup("Color", [r, g, b, a, doSDF]); +op.setPortGroup("Border", [br, bg, bb, inBorderSmooth, inBorderWidth, inBorder]); + +r.setUiAttribs({ "colorPick": true }); +br.setUiAttribs({ "colorPick": true }); + +const cgl = op.patch.cgl; +const fontDataVarPrefix = "font_data_"; +const substrLength = fontDataVarPrefix.length; +const alignVec = vec3.create(); +const vScale = vec3.create(); +const shader = new CGL.Shader(cgl, "TextMeshSDF"); + +let fontTexs = null; +let fontData = null; +let fontChars = null; +let needUpdate = true; +let geom = null; +let mesh = null; +let disabled = false; +let valignMode = 1; +let heightAll = 0, widthAll = 0; +let avgHeight = 0; +let minY, maxY, minX, maxX; +let needsUpdateTransmats = true; +let transMats = null; +let offY = 0; + +if (cgl.glVersion == 1) +{ + cgl.gl.getExtension("OES_standard_derivatives"); + shader.enableExtension("GL_OES_standard_derivatives"); +} + +shader.setSource(attachments.textmeshsdf_vert, attachments.textmeshsdf_frag); + +const + uniTex = new CGL.Uniform(shader, "t", "tex0", 0), + uniTex1 = new CGL.Uniform(shader, "t", "tex1", 1), + uniTex2 = new CGL.Uniform(shader, "t", "tex2", 2), + uniTex3 = new CGL.Uniform(shader, "t", "tex3", 3), + uniTexMul = new CGL.Uniform(shader, "t", "texMulColor", 4), + uniTexMulMask = new CGL.Uniform(shader, "t", "texMulMask", 5), + uniColor = new CGL.Uniform(shader, "4f", "color", r, g, b, a), + uniColorBorder = new CGL.Uniform(shader, "3f", "colorBorder", br, bg, bb), + + uniTexSize = new CGL.Uniform(shader, "2f", "texSize", 0, 0), + uniborderSmooth = new CGL.Uniform(shader, "f", "borderSmooth", inBorderSmooth), + uniborderWidth = new CGL.Uniform(shader, "f", "borderWidth", inBorderWidth); + +scale.onChange = updateScale; + +inRotArr.onChange = + inPosArr.onChange = + inScaleArr.onChange = function () { needsUpdateTransmats = true; }; + +inTexColor.onChange = +inTexMask.onChange = +inShadow.onChange = +inBorder.onChange = +doSDF.onChange = + updateDefines; + +updateDefines(); +updateScale(); + +align.onChange = + str.onChange = + letterSpace.onChange = + lineHeight.onChange = + function () + { + needUpdate = true; + }; + +valign.onChange = updateAlign; + +op.patch.addEventListener("variablesChanged", updateFontList); +op.patch.addEventListener("FontLoadedMSDF", updateFontList); + +inFont.onChange = updateFontData; + +updateFontList(); + +function updateDefines() +{ + shader.toggleDefine("SDF", doSDF.get()); + shader.toggleDefine("SHADOW", inShadow.get()); + shader.toggleDefine("BORDER", inBorder.get()); + shader.toggleDefine("TEXTURE_COLOR", inTexColor.isLinked()); + shader.toggleDefine("TEXTURE_MASK", inTexMask.isLinked()); + + br.setUiAttribs({ "greyout": !inBorder.get() }); + bg.setUiAttribs({ "greyout": !inBorder.get() }); + bb.setUiAttribs({ "greyout": !inBorder.get() }); + inBorderSmooth.setUiAttribs({ "greyout": !inBorder.get() }); + inBorderWidth.setUiAttribs({ "greyout": !inBorder.get() }); +} + +function updateFontData() +{ + updateFontList(); + const varname = fontDataVarPrefix + inFont.get(); + + fontData = null; + fontTexs = null; + fontChars = {}; + + const dataVar = op.patch.getVar(varname); + + if (!dataVar || !dataVar.getValue()) + { + fontData = null; + + op.warn("no varname", varname); + return; + } + + fontData = dataVar.getValue().data; + + if (!fontData) + { + return; + } + + const basename = dataVar.getValue().basename; + + const textVar = op.patch.getVar("font_tex_" + basename); + if (!textVar) + { + fontTexs = null; + fontData = null; + return; + } + + fontTexs = textVar.getValue(); + + for (let i = 0; i < fontData.chars.length; i++) fontChars[fontData.chars[i].char] = fontData.chars[i]; + needUpdate = true; +} + +function updateFontList() +{ + const vars = op.patch.getVars(); + const names = ["..."]; + + for (const i in vars) + if (vars[i].type == "fontData") + names.push(i.substr(substrLength)); + + inFont.uiAttribs.values = names; +} + +function updateScale() +{ + const s = scale.get(); + vec3.set(vScale, s, s, s); + + vec3.set(alignVec, 0, offY * s, 0); + + outWidth.set(widthAll * s); + outHeight.set(heightAll * s); + + outStartY.set((maxY + offY) * s); +} + +function updateAlign() +{ + if (minX == undefined) return; + if (valign.get() == "Top") valignMode = 0; + else if (valign.get() == "Middle") valignMode = 1; + else if (valign.get() == "Bottom") valignMode = 2; + else if (valign.get() == "Zero") valignMode = 3; + + offY = 0; + widthAll = (Math.abs(minX - maxX)); + heightAll = (Math.abs(minY - maxY)); + + if (valignMode === 1) offY = heightAll / 2; + else if (valignMode === 2) offY = heightAll; + + if (valignMode != 0)offY -= avgHeight; + + updateScale(); +} + +function buildTransMats() +{ + needsUpdateTransmats = false; + + // if(!( inPosArr.get() || inScaleArr.get() || inRotArr.get())) + // { + // transMats=null; + // return; + // } + + const transformations = []; + const translates = inPosArr.get() || outArr.get(); + const scales = inScaleArr.get(); + const rots = inRotArr.get(); + + for (let i = 0; i < mesh.numInstances; i++) + { + const m = mat4.create(); + mat4.translate(m, m, [translates[i * 3 + 0], translates[i * 3 + 1], translates[i * 3 + 2]]); + + if (scales) mat4.scale(m, m, [scales[i * 3 + 0], scales[i * 3 + 1], scales[i * 3 + 2]]); + + if (rots) + { + mat4.rotateX(m, m, rots[i * 3 + 0] * CGL.DEG2RAD); + mat4.rotateY(m, m, rots[i * 3 + 1] * CGL.DEG2RAD); + mat4.rotateZ(m, m, rots[i * 3 + 2] * CGL.DEG2RAD); + } + + transformations.push(Array.prototype.slice.call(m)); + } + + transMats = [].concat.apply([], transformations); +} + +render.onTriggered = function () +{ + if (!fontData) + { + op.setUiError("nodata", "No font data!"); + op.setUiError("msdfhint", "Use the FontMSDF op to create font and texture.", 0); + updateFontData(); + next.trigger(); + return; + } + if (!fontTexs) + { + op.setUiError("nodata", "No font texture"); + op.setUiError("msdfhint", "Use the FontMSDF op to create font and texture.", 0); + updateFontData(); + next.trigger(); + return; + } + + op.setUiError("nodata", null); + op.setUiError("msdfhint", null); + + if (needUpdate) + { + generateMesh(); + needUpdate = false; + } + + if (mesh && mesh.numInstances > 0) + { + // cgl.pushBlendMode(CGL.BLEND_NORMAL, true); + cgl.pushShader(shader); + + if (fontTexs[0]) uniTexSize.setValue([fontTexs[0].width, fontTexs[0].height]); + + if (fontTexs[0]) cgl.setTexture(0, fontTexs[0].tex); + else cgl.setTexture(0, CGL.Texture.getEmptyTexture(cgl).tex); + + if (fontTexs[1])cgl.setTexture(1, fontTexs[1].tex); + else cgl.setTexture(1, CGL.Texture.getEmptyTexture(cgl).tex); + + if (fontTexs[2])cgl.setTexture(2, fontTexs[2].tex); + else cgl.setTexture(2, CGL.Texture.getEmptyTexture(cgl).tex); + + if (fontTexs[3])cgl.setTexture(3, fontTexs[3].tex); + else cgl.setTexture(3, CGL.Texture.getEmptyTexture(cgl).tex); + + if (inTexColor.get()) cgl.setTexture(4, inTexColor.get().tex); + if (inTexMask.get()) cgl.setTexture(5, inTexMask.get().tex); + + cgl.pushModelMatrix(); + mat4.translate(cgl.mMatrix, cgl.mMatrix, alignVec); + + if (needsUpdateTransmats) buildTransMats(); + if (transMats) mesh.setAttribute("instMat", new Float32Array(transMats), 16, { "instanced": true }); + if (cgl.getShader())cgl.getShader().define("INSTANCING"); + + if (!disabled) + { + mat4.scale(cgl.mMatrix, cgl.mMatrix, vScale); + + mesh.render(cgl.getShader()); + } + + cgl.popModelMatrix(); + + cgl.setTexture(0, null); + cgl.popShader(); + // cgl.popBlendMode(); + } + + next.trigger(); +}; + +function getChar(chStr) +{ + return fontChars[String(chStr)] || fontChars["?"] || fontChars._ || fontChars.X; +} + +function generateMesh() +{ + outArr.set(null); + + if (!fontData || !fontChars) + { + outNumChars.set(0); + return; + } + + const theString = String(str.get() + ""); + + if (!geom) + { + geom = new CGL.Geometry("textmesh"); + + geom.vertices = [ + 0.5, 0.5, 0.0, + -0.5, 0.5, 0.0, + 0.5, -0.5, 0.0, + -0.5, -0.5, 0.0 + ]; + + geom.normals = [ + 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0 + ]; + + geom.texCoords = new Float32Array([ + 1.0, 0.0, + 0.0, 0.0, + 1.0, 1.0, + 0.0, 1.0 + ]); + + geom.verticesIndices = [ + 0, 1, 2, + 3, 1, 2 + ]; + } + + if (mesh)mesh.dispose(); + mesh = new CGL.Mesh(cgl, geom); + + const strings = (theString).split("\n"); + const transformations = []; + const tcOffsets = []; + const sizes = []; + const texPos = []; + const tcSizes = []; + const pages = []; + let charCounter = 0; + const arrPositions = []; + + const mulSize = 0.01; + + outLines.set(strings.length); + minY = 99999; + maxY = -99999; + minX = 99999; + maxX = -99999; + + avgHeight = 0; + + for (let i = 0; i < fontData.chars.length; i++) + { + if (fontData.chars[i].height) avgHeight += fontData.chars[i].height; + } + avgHeight /= fontData.chars.length; + avgHeight *= mulSize; + + for (let s = 0; s < strings.length; s++) + { + const txt = strings[s]; + const numChars = txt.length; + let lineWidth = 0; + + for (let i = 0; i < numChars; i++) + { + const chStr = txt.substring(i, i + 1); + const char = getChar(chStr); + if (char) lineWidth += char.xadvance * mulSize + letterSpace.get(); + } + + let pos = 0; + if (align.get() == "Right") pos -= lineWidth; + else if (align.get() == "Center") pos -= lineWidth / 2; + + for (let i = 0; i < numChars; i++) + { + const m = mat4.create(); + + const chStr = txt.substring(i, i + 1); + const char = getChar(chStr); + + if (!char) continue; + + pages.push(char.page || 0); + sizes.push(char.width, char.height); + + tcOffsets.push(char.x / fontData.common.scaleW, (char.y / fontData.common.scaleH)); + + const charWidth = char.width / fontData.common.scaleW; + const charHeight = char.height / fontData.common.scaleH; + const charOffsetY = (char.yoffset / fontData.common.scaleH); + const charOffsetX = char.xoffset / fontData.common.scaleW; + + if (chStr == " ") tcSizes.push(0, 0); + else tcSizes.push(charWidth, charHeight); + + mat4.identity(m); + + let adv = (char.xadvance / 2) * mulSize; + pos += adv; + + const x = pos + (char.xoffset / 2) * mulSize; + const y = (s * -lineHeight.get()) + (avgHeight) - (mulSize * (char.yoffset + char.height / 2)); + + minX = Math.min(x - charWidth, minX); + maxX = Math.max(x + charWidth, maxX); + minY = Math.min(y - charHeight - avgHeight / 2, minY); + maxY = Math.max(y + charHeight + avgHeight / 2, maxY); + + mat4.translate(m, m, [x, y, 0]); + arrPositions.push(x, y, 0); + + adv = (char.xadvance / 2) * mulSize + letterSpace.get(); + + pos += adv; + + minX = Math.min(pos - charWidth, minX); + maxX = Math.max(pos + charWidth, maxX); + + transformations.push(Array.prototype.slice.call(m)); + + charCounter++; + } + } + + transMats = [].concat.apply([], transformations); + + disabled = false; + if (transMats.length == 0) disabled = true; + + mesh.numInstances = transMats.length / 16; + outNumChars.set(mesh.numInstances); + + if (mesh.numInstances == 0) + { + disabled = true; + return; + } + + mesh.setAttribute("instMat", new Float32Array(transMats), 16, { "instanced": true }); + mesh.setAttribute("attrTexOffsets", new Float32Array(tcOffsets), 2, { "instanced": true }); + mesh.setAttribute("attrTcSize", new Float32Array(tcSizes), 2, { "instanced": true }); + mesh.setAttribute("attrSize", new Float32Array(sizes), 2, { "instanced": true }); + mesh.setAttribute("attrPage", new Float32Array(pages), 1, { "instanced": true }); + + // updateAlign(); + updateAlign(); + needsUpdateTransmats = true; + outArr.set(arrPositions); +} + + +}; + +Ops.Gl.TextMeshMSDF_v2.prototype = new CABLES.Op(); +CABLES.OPS["b5c99363-a749-4040-884b-66f91294bcad"]={f:Ops.Gl.TextMeshMSDF_v2,objName:"Ops.Gl.TextMeshMSDF_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Texture2ColorArray +// +// ************************************************************** + +Ops.Gl.Texture2ColorArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + cgl = op.patch.cgl, + pUpdate = op.inTrigger("update"), + tex = op.inObject("texture"), + inNormalize = op.inSwitch("Normalize", ["0-255", "0-1", "-1-1"], "0-255"), + outTrigger = op.outTrigger("trigger"), + outColors = op.outArray("Colors"), + outIsFloatingPoint = op.outBoolNum("Floating Point"); + +let + fb = null, + pixelData = null, + texChanged = false; +tex.onChange = function () { texChanged = true; }; + +op.toWorkPortsNeedToBeLinked(tex, outColors); + +let isFloatingPoint = false; +let channelType = op.patch.cgl.gl.UNSIGNED_BYTE; + +let convertedPixelData = null; + +let lastFloatingPoint = false; +let lastWidth = 0; +let lastHeight = 0; + +pUpdate.onTriggered = function () +{ + const realTexture = tex.get(), gl = cgl.gl; + + if (!realTexture) return; + if (!fb) fb = gl.createFramebuffer(); + + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + let channels = gl.RGBA; + // channels = gl.R; + + let numChannels = 4; + // numChannels = 1; + + if (texChanged) + { + gl.framebufferTexture2D( + gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, + gl.TEXTURE_2D, realTexture.tex, 0 + ); + + isFloatingPoint = realTexture.textureType == CGL.Texture.TYPE_FLOAT; + + if (isFloatingPoint) channelType = gl.FLOAT; + else channelType = gl.UNSIGNED_BYTE; + + outIsFloatingPoint.set(isFloatingPoint); + + if ( + lastFloatingPoint != isFloatingPoint || + lastWidth != realTexture.width || + lastHeight != realTexture.height) + { + const size = realTexture.width * realTexture.height * numChannels; + if (isFloatingPoint) pixelData = new Float32Array(size); + else pixelData = new Uint8Array(size); + + lastFloatingPoint = isFloatingPoint; + lastWidth = realTexture.width; + lastHeight = realTexture.height; + } + + texChanged = false; + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + gl.readPixels( + 0, 0, + realTexture.width, + realTexture.height, + channels, + channelType, + pixelData + ); + + // if (!convertedPixelData || convertedPixelData.length != pixelData.length) convertedPixelData = new Float32Array(pixelData.length); + // for (let i = 0; i < pixelData.length; i++) + // { + // convertedPixelData[i] = pixelData[i]; + // } + if (inNormalize.get() == "0-1") + { + if (!convertedPixelData || convertedPixelData.length != pixelData.length) convertedPixelData = new Float32Array(pixelData.length); + for (let i = 0; i < pixelData.length; i++) + { + convertedPixelData[i] = pixelData[i] / 255; + } + } + if (inNormalize.get() == "-1-1") + { + if (!convertedPixelData || convertedPixelData.length != pixelData.length) convertedPixelData = new Float32Array(pixelData.length); + + for (let i = 0; i < pixelData.length; i++) + { + convertedPixelData[i] = ((pixelData[i] - 128) * 2.0) / 255; + } + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + outColors.set(null); + outColors.set(convertedPixelData || pixelData); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + outTrigger.trigger(); +}; + + +}; + +Ops.Gl.Texture2ColorArray.prototype = new CABLES.Op(); +CABLES.OPS["51dbc04e-f970-44ca-9cb0-39596ac4d212"]={f:Ops.Gl.Texture2ColorArray,objName:"Ops.Gl.Texture2ColorArray"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureArray +// +// ************************************************************** + +Ops.Gl.TextureArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + outArr = op.outArray("Array"), + outCount = op.outNumber("Count"); + +outArr.ignoreValueSerialize = true; + +const num = 15; +let texturePorts = []; +let arr = []; + +function rebuild() +{ + let i = 0; + let count = 0; + for (i = 0; i < texturePorts.length; i++) if (texturePorts[i].isLinked()) count++; + + arr.length = count; + + count = 0; + for (i = 0; i < texturePorts.length; i++) + { + if (texturePorts[i].isLinked()) + { + arr[count] = texturePorts[i].get(); + count++; + } + } + + outArr.set(null); + outArr.set(arr); + outCount.set(count); +} + +for (let i = 0; i < num; i++) +{ + let p = op.inTexture("Texture " + i); + p.onLinkChanged = rebuild; + p.onChange = rebuild; + texturePorts.push(p); +} + + +}; + +Ops.Gl.TextureArray.prototype = new CABLES.Op(); +CABLES.OPS["fac012e2-43c8-4e21-85ac-189fe85d5723"]={f:Ops.Gl.TextureArray,objName:"Ops.Gl.TextureArray"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureArrayLoaderFromArray +// +// ************************************************************** + +Ops.Gl.TextureArrayLoaderFromArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + filenames = op.inArray("urls"), + tfilter = op.inValueSelect("filter", ["nearest", "linear", "mipmap"]), + wrap = op.inValueSelect("wrap", ["repeat", "mirrored repeat", "clamp to edge"], "clamp to edge"), + flip = op.addInPort(new CABLES.Port(op, "flip", CABLES.OP_PORT_TYPE_VALUE, { "display": "bool" })), + unpackAlpha = op.addInPort(new CABLES.Port(op, "unpackPreMultipliedAlpha", CABLES.OP_PORT_TYPE_VALUE, { "display": "bool" })), + inCaching = op.inBool("Caching", false), + inPatchAsset = op.inBool("Asset in patch", false), + arrOut = op.outArray("TextureArray"), + width = op.outNumber("width"), + height = op.outNumber("height"), + loading = op.outBoolNum("loading"), + ratio = op.outNumber("Aspect Ratio"); + +flip.set(false); +unpackAlpha.set(false); + +const cgl = op.patch.cgl; +let cgl_filter = 0; +let cgl_wrap = 0; +let loadingId = null; +const arr = []; +arrOut.set(arr); + +inPatchAsset.onChange = +flip.onChange = function () { reload(); }; +filenames.onChange = reload; + +tfilter.onChange = onFilterChange; +wrap.onChange = onWrapChange; +unpackAlpha.onChange = function () { reload(); }; + +let timedLoader = 0; + +const setTempTexture = function () +{ + const t = CGL.Texture.getTempTexture(cgl); + // textureOut.set(t); +}; + +function reload(nocache) +{ + clearTimeout(timedLoader); + timedLoader = setTimeout(function () + { + realReload(nocache); + }, 30); +} + +function loadImage(_i, _url, nocache, cb) +{ + let url = _url; + const i = _i; + if (!url) return; + // url=url.replace("XXX",i); + + if (inPatchAsset.get()) + { + let patchId = null; + if (op.storage && op.storage.blueprint && op.storage.blueprint.patchId) + { + patchId = op.storage.blueprint.patchId; + } + url = op.patch.getAssetPath(patchId) + url; + } + + url = op.patch.getFilePath(url); + if (!inCaching.get()) + if (nocache)url += "?rnd=" + CABLES.generateUUID(); + + // if((filename.get() && filename.get().length>1)) + { + loading.set(true); + + let tex = CGL.Texture.load(cgl, url, + function (err) + { + if (err) + { + setTempTexture(); + const errMsg = "could not load texture \"" + url + "\""; + op.uiAttr({ "error": errMsg }); + op.warn("[TextureArrayLoader] " + errMsg); + if (cb)cb(); + return; + } + else op.uiAttr({ "error": null }); + // textureOut.set(tex); + width.set(tex.width); + height.set(tex.height); + ratio.set(tex.width / tex.height); + + arr[i] = tex; + + arrOut.set(null); + arrOut.set(arr); + if (cb)cb(); + }, { + "wrap": cgl_wrap, + "flip": flip.get(), + "unpackAlpha": unpackAlpha.get(), + "filter": cgl_filter + }); + + loading.set(false); + } +} + +function realReload(nocache) +{ + const files = filenames.get(); + + if (!files || files.length == 0) return; + + if (loadingId)cgl.patch.loading.finished(loadingId); + loadingId = cgl.patch.loading.start("texturearray", CABLES.uuid()); + + for (let i = 0; i < files.length; i++) + { + arr[i] = CGL.Texture.getEmptyTexture(cgl); + let cb = null; + if (i == files.length - 1)cb = function () + { + cgl.patch.loading.finished(loadingId); + }; + + if (!files[i]) { if (cb) cb(); } + else loadImage(i, files[i], nocache, cb); + } +} + +function onFilterChange() +{ + if (tfilter.get() == "nearest") cgl_filter = CGL.Texture.FILTER_NEAREST; + if (tfilter.get() == "linear") cgl_filter = CGL.Texture.FILTER_LINEAR; + if (tfilter.get() == "mipmap") cgl_filter = CGL.Texture.FILTER_MIPMAP; + + reload(); +} + +function onWrapChange() +{ + if (wrap.get() == "repeat") cgl_wrap = CGL.Texture.WRAP_REPEAT; + if (wrap.get() == "mirrored repeat") cgl_wrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + if (wrap.get() == "clamp to edge") cgl_wrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + reload(); +} + +op.onFileChanged = function (fn) +{ + +}; + +tfilter.set("linear"); +wrap.set("repeat"); + + +}; + +Ops.Gl.TextureArrayLoaderFromArray.prototype = new CABLES.Op(); +CABLES.OPS["febd6cdf-e049-4aed-be34-d7e370b90e03"]={f:Ops.Gl.TextureArrayLoaderFromArray,objName:"Ops.Gl.TextureArrayLoaderFromArray"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureArrayLoader_v2 +// +// ************************************************************** + +Ops.Gl.TextureArrayLoader_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const USE_LEFT_PAD_DEFAULT = false; + +const filename = op.inString("Url"); +const leftPadFilename = op.inBool("Left Pad", USE_LEFT_PAD_DEFAULT); +const numberLengthPort = op.inInt("Num Digits", 3); +numberLengthPort.setUiAttribs({ "hidePort": !USE_LEFT_PAD_DEFAULT, "greyout": !USE_LEFT_PAD_DEFAULT }); + +const indexStart = op.inInt("Index Start"); +const indexEnd = op.inInt("Index End"); + +const tfilter = op.inValueSelect("filter", ["nearest", "linear", "mipmap"]); +const wrap = op.inValueSelect("wrap", ["repeat", "mirrored repeat", "clamp to edge"], "clamp to edge"); +const flip = op.inBool("Flip", false); +const unpackAlpha = op.inBool("unpackPreMultipliedAlpha", false); + +const arrOut = op.outArray("TextureArray"); + +const width = op.outNumber("Width"); +const height = op.outNumber("Height"); +const loading = op.outBool("Loading"); +const ratio = op.outNumber("Aspect Ratio"); + +indexEnd.set(10); +flip.set(false); +unpackAlpha.set(false); + +const cgl = op.patch.cgl; +let cgl_filter = 0; +let cgl_wrap = 0; + +const arr = []; +arrOut.set(arr); + +flip.onChange = function () { reload(); }; +filename.onChange = reload; + +tfilter.onChange = onFilterChange; +wrap.onChange = onWrapChange; +unpackAlpha.onChange = function () { reload(); }; + +leftPadFilename.onChange = setNumberLengthPortVisibility; + +let timedLoader = 0; + +function setNumberLengthPortVisibility() +{ + const doLeftPad = leftPadFilename.get(); + numberLengthPort.setUiAttribs({ "hidePort": !doLeftPad, "greyout": !doLeftPad }); +} + +const setTempTexture = function () +{ + const t = CGL.Texture.getTempTexture(cgl); + // textureOut.set(t); +}; + +function reload(nocache) +{ + clearTimeout(timedLoader); + timedLoader = setTimeout(function () + { + realReload(nocache); + }, 30); +} + +const REPLACE_CHARACTER = "X"; + +function pad(value, length) +{ + return (value.toString().length < length) ? pad("0" + value, length) : value; +} + +function loadImage(i, nocache) +{ + let url = filename.get(); + if (!url) return; + const firstXIndex = url.indexOf(REPLACE_CHARACTER); + const lastXIndex = url.lastIndexOf(REPLACE_CHARACTER); + if (firstXIndex === -1) { return; } + const replaceString = url.substring(firstXIndex, lastXIndex + 1); + let numberString = i; + if (leftPadFilename.get()) + { + numberString = pad(i, numberLengthPort.get()); + } + url = url.replace(replaceString, numberString); + url = op.patch.getFilePath(url); + + if (nocache)url += "?rnd=" + CABLES.generateUUID(); + + if ((filename.get() && filename.get().length > 1)) + { + loading.set(1); + + var tex = CGL.Texture.load(cgl, url, + function (err) + { + if (err) + { + setTempTexture(); + op.uiAttr({ "error": "could not load texture \"" + filename.get() + "\"" }); + return; + } + else op.uiAttr({ "error": null }); + // textureOut.set(tex); + width.set(tex.width); + height.set(tex.height); + ratio.set(tex.width / tex.height); + + arr[i - parseInt(indexStart.get())] = tex; + if (!tex.isPowerOfTwo()) op.uiAttr( + { + "hint": "texture dimensions not power of two! - texture filtering will not work.", + "warning": null + }); + else op.uiAttr( + { + "hint": null, + "warning": null + }); + + // textureOut.set(null); + // textureOut.set(tex); + + // tex.printInfo(); + arrOut.set(null); + arrOut.set(arr); + }, { + "wrap": cgl_wrap, + "flip": flip.get(), + "unpackAlpha": unpackAlpha.get(), + "filter": cgl_filter + }); + + // textureOut.set(null); + // textureOut.set(tex); + + // if(!textureOut.get() && nocache) + // { + // } + loading.set(0); + } + else + { + setTempTexture(); + } +} + +function realReload(nocache) +{ + for (var i = 0; i < arr.length; i++) + { + if (arr[i]) + { + arr[i].delete(); + } + } + arr.length = 0; + for (var i = Math.floor(indexStart.get()); i <= Math.floor(indexEnd.get()); i++) + { + loadImage(i, nocache); + } +} + +function onFilterChange() +{ + if (tfilter.get() == "nearest") cgl_filter = CGL.Texture.FILTER_NEAREST; + if (tfilter.get() == "linear") cgl_filter = CGL.Texture.FILTER_LINEAR; + if (tfilter.get() == "mipmap") cgl_filter = CGL.Texture.FILTER_MIPMAP; + + reload(); +} + +function onWrapChange() +{ + if (wrap.get() == "repeat") cgl_wrap = CGL.Texture.WRAP_REPEAT; + if (wrap.get() == "mirrored repeat") cgl_wrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + if (wrap.get() == "clamp to edge") cgl_wrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + reload(); +} + +op.onFileChanged = function (fn) +{ + // if(filename.get() && filename.get().indexOf(fn)>-1) + // { + // textureOut.set(null); + // textureOut.set(CGL.Texture.getTempTexture(cgl)); + + // realReload(true); + // } +}; + +tfilter.set("linear"); +wrap.set("repeat"); + + +}; + +Ops.Gl.TextureArrayLoader_v2.prototype = new CABLES.Op(); +CABLES.OPS["4bbb57ce-3c7b-49c1-84fd-2b6a27ff3afa"]={f:Ops.Gl.TextureArrayLoader_v2,objName:"Ops.Gl.TextureArrayLoader_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureColorPick +// +// ************************************************************** + +Ops.Gl.TextureColorPick = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + cgl = op.patch.cgl, + pUpdate = op.inTrigger("update"), + // inNormalize = op.inSwitch("Coordinate", ["Pixel", "Normalized"], "Pixel"), + inX = op.inInt("X", 0), + inY = op.inInt("Y", 0), + tex = op.inObject("texture"), + outTrigger = op.outTrigger("trigger"), + outR = op.outNumber("Red"), + outG = op.outNumber("Green"), + outB = op.outNumber("Blue"), + outA = op.outNumber("Alpha"); + +let + fb = null, + pixelData = null, + texChanged = false; + +tex.onChange = function () { texChanged = true; }; + +let isFloatingPoint = false; +let channelType = op.patch.cgl.gl.UNSIGNED_BYTE; + +pUpdate.onTriggered = function () +{ + const realTexture = tex.get(), gl = cgl.gl; + + if (!realTexture) return; + if (!fb) fb = gl.createFramebuffer(); + + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + if (texChanged) + { + gl.framebufferTexture2D( + gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, + gl.TEXTURE_2D, realTexture.tex, 0 + ); + + isFloatingPoint = realTexture.textureType == CGL.Texture.TYPE_FLOAT; + + if (isFloatingPoint) channelType = gl.FLOAT; + else channelType = gl.UNSIGNED_BYTE; + + const size = 4 * 4; + if (isFloatingPoint) pixelData = new Float32Array(size); + else pixelData = new Uint8Array(size); + + texChanged = false; + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + gl.readPixels( + inX.get(), inY.get(), + 1, 1, + gl.RGBA, + channelType, + pixelData + ); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + if (isFloatingPoint) + { + outR.set(pixelData[0]); + outG.set(pixelData[1]); + outB.set(pixelData[2]); + outA.set(pixelData[3]); + } + else + { + outR.set(pixelData[0] / 255); + outG.set(pixelData[1] / 255); + outB.set(pixelData[2] / 255); + outA.set(pixelData[3] / 255); + } + + outTrigger.trigger(); +}; + + +}; + +Ops.Gl.TextureColorPick.prototype = new CABLES.Op(); +CABLES.OPS["060e740a-2432-4685-a081-5df6ab7418e4"]={f:Ops.Gl.TextureColorPick,objName:"Ops.Gl.TextureColorPick"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffect.RgbeToFloat32Texture +// +// ************************************************************** + +Ops.Gl.TextureEffect.RgbeToFloat32Texture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"rgbe2fp_frag":"UNI sampler2D tex;\nIN vec2 texCoord;\n\n\nvec3 decodeRGBE8(vec4 rgbe)\n{\n vec3 vDecoded = rgbe.rgb * pow(2.0, rgbe.a * 255.0-128.0);\n return vDecoded;\n}\n\nvoid main()\n{\n highp vec4 col=vec4(\n decodeRGBE8(\n texture(tex,texCoord)\n ), 1.0);\n\n\n outColor= col;\n}",}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.rgbe2fp_frag); + +// const highEdgeUniform = new CGL.Uniform(shader, "f", "highEdge", inHighEdge); + +// CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + +// const +// exec = op.inTrigger("Execute"), +// inTex = op.inTexture("RGBE Texture"), +// next = op.outTrigger("Next"), +// outFpTex = op.outTexture("HDR Texture"), +// tfilter = op.inSwitch("Filter", ["nearest", "linear"], "linear"), +// twrap = op.inValueSelect("Wrap", ["clamp to edge", "repeat", "mirrored repeat"], "repeat"); + +// let tc = null; + +// twrap.onChange = +// tfilter.onChange = init; +// init(); + +// function init() +// { +// let wrap = CGL.Texture.WRAP_REPEAT; +// if (twrap.get() == "mirrored repeat") wrap = CGL.Texture.WRAP_MIRRORED_REPEAT; +// if (twrap.get() == "clamp to edge") wrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + +// let filter = CGL.Texture.FILTER_NEAREST; +// if (tfilter.get() == "linear") filter = CGL.Texture.FILTER_LINEAR; + +// if (tc)tc.dispose(); +// tc = new CGL.CopyTexture(op.patch.cgl, "rgbe2hdr", +// { +// "shader": attachments.rgbe2fp_frag, +// "isFloatingPointTexture": true, +// "filter": filter, +// "wrap": wrap +// }); +// } + +// outFpTex.set(CGL.Texture.getEmptyTexture(op.patch.cgl)); + +// exec.onTriggered = () => +// { +// if (!inTex.get()) return; + +// outFpTex.set(CGL.Texture.getEmptyTexture(op.patch.cgl)); +// outFpTex.set(tc.copy(inTex.get())); + +// next.trigger(); +// }; + + +}; + +Ops.Gl.TextureEffect.RgbeToFloat32Texture.prototype = new CABLES.Op(); +CABLES.OPS["35cc1b97-3deb-4cbb-91b5-1658697d4460"]={f:Ops.Gl.TextureEffect.RgbeToFloat32Texture,objName:"Ops.Gl.TextureEffect.RgbeToFloat32Texture"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Alpha +// +// ************************************************************** + +Ops.Gl.TextureEffects.Alpha = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"clearAlpha_frag":"\n// void main()\n// {\n// outColor.a=0.0;\n// }\n\nIN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\n\n\nvoid main()\n{\n vec4 base=texture(tex,texCoord);\n\n outColor=base;\n\n #ifdef METH_NORM\n outColor.a=amount;\n #endif\n #ifdef METH_ADD\n outColor.a+=amount;\n #endif\n #ifdef METH_SUB\n outColor.a-=amount;\n #endif\n #ifdef METH_MUL\n outColor.a*=amount;\n #endif\n\n #ifdef DO_CLAMP\n outColor.a=clamp(0.0,1.0,outColor.a);\n #endif\n\n}\n",}; +const + render = op.inTrigger("Render"), + amount = op.inValueSlider("Amount", 1), + meth = op.inSwitch("Method", ["Set", "Add", "Sub", "Mul"], "Set"), + clamp = op.inBool("Clamp", true), + trigger = op.outTrigger("Next"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "Alpha"); +const TEX_SLOT = 0; + +shader.setSource(shader.getDefaultVertexShader(), attachments.clearAlpha_frag || ""); + +const uniformAmount = new CGL.Uniform(shader, "f", "amount", amount); +const textureUniform = new CGL.Uniform(shader, "t", "tex", TEX_SLOT); + +clamp.onChange = + meth.onChange = updateDefines; +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("METH_NORM", meth.get() == "Set"); + shader.toggleDefine("METH_ADD", meth.get() == "Add"); + shader.toggleDefine("METH_SUB", meth.get() == "Sub"); + shader.toggleDefine("METH_MUL", meth.get() == "Mul"); + shader.toggleDefine("DO_CLAMP", clamp.get()); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(TEX_SLOT, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Alpha.prototype = new CABLES.Op(); +CABLES.OPS["131687e0-77f5-4fd7-be57-864aa6559418"]={f:Ops.Gl.TextureEffects.Alpha,objName:"Ops.Gl.TextureEffects.Alpha"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.AlphaMask_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.AlphaMask_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"alphamask_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D image;\nUNI float amount;\n\nvoid main()\n{\n vec4 col=vec4(0.0,0.0,0.0,1.0);\n col=texture(tex,texCoord);\n\n#ifdef USE_TEXTURE\n float newAlpha=0.0;\n\n #ifdef FROM_RED\n newAlpha=texture(image,texCoord).r;\n #endif\n\n #ifdef FROM_GREEN\n newAlpha=texture(image,texCoord).g;\n #endif\n\n #ifdef FROM_BLUE\n newAlpha=texture(image,texCoord).b;\n #endif\n\n #ifdef FROM_ALPHA\n newAlpha=texture(image,texCoord).a;\n #endif\n\n #ifdef FROM_LUMINANCE\n float gray = dot(vec3(0.2126,0.7152,0.0722), texture(image,texCoord).rgb );\n newAlpha=gray;\n #endif\n\n\n newAlpha*=amount;\n\n #ifdef INVERT\n newAlpha=1.0-newAlpha;\n #endif\n\n #ifdef METH_OVERRIDE\n col.a=newAlpha;\n #endif\n #ifdef METH_ADD\n col.a+=newAlpha;\n #endif\n #ifdef METH_MUL\n col.a*=newAlpha;\n #endif\n\n#endif\n#ifndef USE_TEXTURE\n col.a*=amount;\n // col.g=1.0;\n#endif\n\n outColor= col;\n}",}; +const + render = op.inTrigger("render"), + inAmount = op.inFloatSlider("Amount", 1), + inMethod = op.inSwitch("Method", ["Override", "Mul", "Add"], "Override"), + inInvert = op.inBool("Invert", false), + image = op.inTexture("image"), + next = op.outTrigger("trigger"); + +const cgl = this.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); +shader.setSource(shader.getDefaultVertexShader(), attachments.alphamask_frag); + +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const textureDisplaceUniform = new CGL.Uniform(shader, "t", "image", 1); +const amountUniform = new CGL.Uniform(shader, "f", "amount", inAmount); + +// const method = this.addInPort(new CABLES.Port(this, "method", CABLES.OP_PORT_TYPE_VALUE, { "display": "dropdown", "values": ["luminance", "image alpha", "red", "green", "blue"] })); +const method = op.inDropDown("method", ["luminance", "image alpha", "red", "green", "blue"], "luminance"); + +image.onChange = +inMethod.onChange = +inInvert.onChange = +method.onChange = function () +{ + shader.toggleDefine("FROM_LUMINANCE", method.get() == "luminance"); + shader.toggleDefine("FROM_ALPHA", method.get() == "image alpha"); + shader.toggleDefine("FROM_RED", method.get() == "red"); + shader.toggleDefine("FROM_GREEN", method.get() == "green"); + shader.toggleDefine("FROM_BLUR", method.get() == "blue"); + shader.toggleDefine("USE_TEXTURE", image.get()); + + shader.toggleDefine("INVERT", inInvert.get()); + shader.toggleDefine("METH_MUL", inMethod.get() == "Mul"); + shader.toggleDefine("METH_ADD", inMethod.get() == "Add"); + shader.toggleDefine("METH_OVERRIDE", inMethod.get() == "Override"); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + // if (!image.get()) return next.trigger(); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + if (image.get() && image.get().tex) cgl.setTexture(1, image.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + next.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.AlphaMask_v2.prototype = new CABLES.Op(); +CABLES.OPS["a971aaa4-565f-47cf-8a4f-61a3a4378183"]={f:Ops.Gl.TextureEffects.AlphaMask_v2,objName:"Ops.Gl.TextureEffects.AlphaMask_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.BarrelDistortion_v3 +// +// ************************************************************** + +Ops.Gl.TextureEffects.BarrelDistortion_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"barreldistort_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float intensity;\n\n{{CGL.BLENDMODES3}}\n\n// adapted from https://www.shadertoy.com/view/MlSXR3\n\nvec2 brownConradyDistortion(vec2 uv)\n{\n// positive values of K1 give barrel distortion, negative give pincushion\n float barrelDistortion1 = intensity*10.; // K1 in text books\n float barrelDistortion2 = 0.; // K2 in text books\n float r2 = uv.x*uv.x + uv.y*uv.y;\n uv *= 1.0 + barrelDistortion1 * r2 + barrelDistortion2 * r2 * r2;\n\n // tangential distortion (due to off center lens elements)\n // is not modeled in this function, but if it was, the terms would go here\n return uv;\n}\n\nvoid main()\n{\n vec2 tc=brownConradyDistortion(texCoord-0.5)+0.5;\n vec4 col=texture(tex,texCoord);\n vec4 base=texture(tex,tc);\n\n col.a=0.0;\n outColor=cgl_blendPixel(col,base,amount);\n}",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1.0), + intensity = op.inValue("Intensity", 10.0), + trigger = op.outTrigger("Trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.barreldistort_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uniintensity = new CGL.Uniform(shader, "f", "intensity", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + let texture = cgl.currentTextureEffect.getCurrentSourceTexture(); + + uniintensity.setValue(intensity.get() * (1 / texture.width)); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, texture.tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.BarrelDistortion_v3.prototype = new CABLES.Op(); +CABLES.OPS["d5efa9e4-d552-42f8-a345-d49e5e861602"]={f:Ops.Gl.TextureEffects.BarrelDistortion_v3,objName:"Ops.Gl.TextureEffects.BarrelDistortion_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Blur +// +// ************************************************************** + +Ops.Gl.TextureEffects.Blur = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"blur_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float dirX;\nUNI float dirY;\nUNI float amount;\n\n#ifdef HAS_MASK\n UNI sampler2D imageMask;\n#endif\n\nfloat random(vec3 scale, float seed)\n{\n return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);\n}\n\nvoid main()\n{\n vec4 color = vec4(0.0);\n float total = 0.0;\n\n float am=amount;\n #ifdef HAS_MASK\n am=amount*texture(imageMask,texCoord).r;\n if(am<=0.02)\n {\n outColor=texture(tex, texCoord);\n return;\n }\n #endif\n\n vec2 delta=vec2(dirX*am*0.01,dirY*am*0.01);\n\n\n float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);\n\n #ifdef MOBILE\n offset = 0.1;\n #endif\n\n #if defined(FASTBLUR) && !defined(MOBILE)\n const float range=5.0;\n #else\n const float range=20.0;\n #endif\n\n for (float t = -range; t <= range; t+=1.0)\n {\n float percent = (t + offset - 0.5) / range;\n float weight = 1.0 - abs(percent);\n vec4 smpl = texture(tex, texCoord + delta * percent);\n\n smpl.rgb *= smpl.a;\n\n color += smpl * weight;\n total += weight;\n }\n\n outColor= color / total;\n\n outColor.rgb /= outColor.a + 0.00001;\n\n\n\n}\n",}; +const render = op.inTrigger("render"); +const trigger = op.outTrigger("trigger"); +const amount = op.inValueFloat("amount"); +const direction = op.inSwitch("direction", ["both", "vertical", "horizontal"], "both"); +const fast = op.inValueBool("Fast", true); +const cgl = op.patch.cgl; + +amount.set(10); + +let shader = new CGL.Shader(cgl, "blur"); + +shader.define("FASTBLUR"); + +fast.onChange = function () +{ + if (fast.get()) shader.define("FASTBLUR"); + else shader.removeDefine("FASTBLUR"); +}; + +shader.setSource(shader.getDefaultVertexShader(), attachments.blur_frag); +let textureUniform = new CGL.Uniform(shader, "t", "tex", 0); + +let uniDirX = new CGL.Uniform(shader, "f", "dirX", 0); +let uniDirY = new CGL.Uniform(shader, "f", "dirY", 0); + +let uniWidth = new CGL.Uniform(shader, "f", "width", 0); +let uniHeight = new CGL.Uniform(shader, "f", "height", 0); + +let uniAmount = new CGL.Uniform(shader, "f", "amount", amount.get()); +amount.onChange = function () { uniAmount.setValue(amount.get()); }; + +let textureAlpha = new CGL.Uniform(shader, "t", "imageMask", 1); + +let showingError = false; + +function fullScreenBlurWarning() +{ + if (cgl.currentTextureEffect.getCurrentSourceTexture().width == cgl.canvasWidth && + cgl.currentTextureEffect.getCurrentSourceTexture().height == cgl.canvasHeight) + { + op.setUiError("warning", "Full screen blurs are slow! Try reducing the resolution to 1/2 or a 1/4", 0); + } + else + { + op.setUiError("warning", null); + } +} + +let dir = 0; +direction.onChange = function () +{ + if (direction.get() == "both")dir = 0; + if (direction.get() == "horizontal")dir = 1; + if (direction.get() == "vertical")dir = 2; +}; + +let mask = op.inTexture("mask"); + +mask.onChange = function () +{ + if (mask.get() && mask.get().tex) shader.define("HAS_MASK"); + else shader.removeDefine("HAS_MASK"); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + + uniWidth.setValue(cgl.currentTextureEffect.getCurrentSourceTexture().width); + uniHeight.setValue(cgl.currentTextureEffect.getCurrentSourceTexture().height); + + fullScreenBlurWarning(); + + // first pass + if (dir === 0 || dir == 2) + { + cgl.currentTextureEffect.bind(); + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + if (mask.get() && mask.get().tex) + { + cgl.setTexture(1, mask.get().tex); + // cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, mask.get().tex ); + } + + uniDirX.setValue(0.0); + uniDirY.setValue(1.0); + + cgl.currentTextureEffect.finish(); + } + + // second pass + if (dir === 0 || dir == 1) + { + cgl.currentTextureEffect.bind(); + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + if (mask.get() && mask.get().tex) + { + cgl.setTexture(1, mask.get().tex); + // cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, mask.get().tex ); + } + + uniDirX.setValue(1.0); + uniDirY.setValue(0.0); + + cgl.currentTextureEffect.finish(); + } + + cgl.popShader(); + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Blur.prototype = new CABLES.Op(); +CABLES.OPS["54f26f53-f637-44c1-9bfb-a2f2b722e998"]={f:Ops.Gl.TextureEffects.Blur,objName:"Ops.Gl.TextureEffects.Blur"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Border_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Border_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"border_frag":"IN vec2 texCoord;\nUNI float width;\nUNI sampler2D tex;\nUNI float amount;\nUNI float r;\nUNI float g;\nUNI float b;\nUNI float aspect;\nUNI vec4 mulSides;\nUNI bool smoothed;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n vec4 col= texture(tex,texCoord);\n\n if(!smoothed)\n {\n float border=0.0;\n if(border==0.0 && texCoord.y < width/aspect/3.0) border=mulSides.x;\n if(border==0.0 && texCoord.y > 1.0-width/aspect/3.0) border=mulSides.z;\n if(border==0.0 && texCoord.x > 1.0-width/3.0) border=mulSides.a;\n if(border==0.0 && texCoord.x < width/3.0 ) border=mulSides.y;\n\n col = vec4(r,g,b, border);\n }\n else\n {\n float f=smoothstep(0.0,width,texCoord.x)-smoothstep(1.0-width,1.0,texCoord.x);\n f*=smoothstep(0.0,width/aspect,texCoord.y);\n f*=smoothstep(1.0,1.0-width/aspect,texCoord.y);\n col= mix(col,vec4(r,g,b, 1.0),1.0-f);\n }\n\n vec4 base=texture(tex,texCoord);\n outColor=cgl_blendPixel(base,col,amount*col.a);\n}",}; +const + render = op.inTrigger("render"), + width = op.inValue("width", 0.1), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + + amount = op.inValueSlider("Amount", 1), + trigger = op.outTrigger("trigger"), + smooth = op.inValueBool("Smooth", false), + r = op.inValueSlider("r", Math.random()), + g = op.inValueSlider("g", Math.random()), + b = op.inValueSlider("b", Math.random()), + sideA = op.inFloat("Side A", 1), + sideB = op.inFloat("Side B", 1), + sideC = op.inFloat("Side C", 1), + sideD = op.inFloat("Side D", 1); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "border"); + +shader.setSource(shader.getDefaultVertexShader(), attachments.border_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + aspectUniform = new CGL.Uniform(shader, "f", "aspect", 0), + uniSmooth = new CGL.Uniform(shader, "b", "smoothed", smooth), + uniWidth = new CGL.Uniform(shader, "f", "width", width.get()), + unir = new CGL.Uniform(shader, "f", "r", r), + unig = new CGL.Uniform(shader, "f", "g", g), + unib = new CGL.Uniform(shader, "f", "b", b); + +width.onChange = function () +{ + uniWidth.setValue(width.get() / 2); +}; + +r.setUiAttribs({ "colorPick": true }); +shader.addUniformFrag("4f", "mulSides", sideA, sideB, sideC, sideD); + +op.setPortGroup("Sides", [sideA, sideB, sideC, sideD]); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + let texture = cgl.currentTextureEffect.getCurrentSourceTexture(); + aspectUniform.set(texture.height / texture.width); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, texture.tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Border_v2.prototype = new CABLES.Op(); +CABLES.OPS["ee773dc0-d00c-4d6a-86b7-8fd32f9d72e1"]={f:Ops.Gl.TextureEffects.Border_v2,objName:"Ops.Gl.TextureEffects.Border_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.BrightnessContrast +// +// ************************************************************** + +Ops.Gl.TextureEffects.BrightnessContrast = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"brightness_contrast_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float amountbright;\n\nvoid main()\n{\n vec4 col=vec4(1.0,0.0,0.0,1.0);\n col=texture(tex,texCoord);\n\n // apply contrast\n col.rgb = ((col.rgb - 0.5) * max(amount*2.0, 0.0))+0.5;\n\n // apply brightness\n col.rgb *= amountbright*2.0;\n\n outColor = col;\n}",}; +const + render = op.inTrigger("render"), + amount = op.inValueSlider("contrast", 0.5), + amountBright = op.inValueSlider("brightness", 0.5), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; + +const shader = new CGL.Shader(cgl, "brightnesscontrast"); +shader.setSource(shader.getDefaultVertexShader(), attachments.brightness_contrast_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); +const amountBrightUniform = new CGL.Uniform(shader, "f", "amountbright", amountBright); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + if (!cgl.currentTextureEffect.getCurrentSourceTexture()) return; + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.BrightnessContrast.prototype = new CABLES.Op(); +CABLES.OPS["54b89199-c594-4dff-bc48-82d6c7a55e8a"]={f:Ops.Gl.TextureEffects.BrightnessContrast,objName:"Ops.Gl.TextureEffects.BrightnessContrast"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.BulgePinch +// +// ************************************************************** + +Ops.Gl.TextureEffects.BulgePinch = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"bulgepinch_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\n\nUNI float radius;\nUNI float strength;\nUNI float centerX;\nUNI float centerY;\n\nvoid main()\n{\n vec2 center=vec2(centerX,centerY);\n vec2 coord=texCoord;\n coord -= center;\n float distance = length(coord);\n float percent = distance / radius;\n if (strength > 0.0) coord *= mix(1.0, smoothstep(0.0, radius / distance, percent), strength * 0.75);\n else coord *= mix(1.0, pow(percent, 1.0 + strength * 0.75) * radius / distance, 1.0 - percent);\n coord += center;\n vec4 col=texture(tex,coord);\n outColor= col;\n}",}; +const + render=op.inTrigger('render'), + radius=op.inValueFloat("Radius",0.5), + strength=op.inValueFloat("Strength",1), + centerX=op.inValueFloat("Center X",0.5), + centerY=op.inValueFloat("Center Y",0.5), + trigger=op.outTrigger('trigger'); + +const cgl=op.patch.cgl; +const shader=new CGL.Shader(cgl,'bulgepinch'); +shader.setSource(shader.getDefaultVertexShader(),attachments.bulgepinch_frag); + +const + uniRadius=new CGL.Uniform(shader,'f','radius',radius), + uniStrength=new CGL.Uniform(shader,'f','strength',strength), + uniCenterX=new CGL.Uniform(shader,'f','centerX',centerX), + uniCenterY=new CGL.Uniform(shader,'f','centerY',centerY), + textureUniform=new CGL.Uniform(shader,'t','tex',0); + +render.onTriggered=function() +{ + if(!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex ); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.BulgePinch.prototype = new CABLES.Op(); +CABLES.OPS["25696840-bd64-463e-9301-964a81385bfb"]={f:Ops.Gl.TextureEffects.BulgePinch,objName:"Ops.Gl.TextureEffects.BulgePinch"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.CheckerBoard_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.CheckerBoard_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"checkerboard_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float numX;\nUNI float numY;\nUNI float amount;\nUNI float rotate;\nUNI float aspect;\n\n{{CGL.BLENDMODES3}}\n\n#define PI 3.14159265\n#define TAU (2.0*PI)\n\nvoid pR(inout vec2 p, float a)\n{\n\tp = cos(a)*p + sin(a)*vec2(p.y, -p.x);\n}\n\nvoid main()\n{\n vec2 uv=texCoord-0.5;\n pR(uv.xy,rotate * (TAU));\n // uv = vec2(texCoord.x,texCoord.y*aspect)-0.5;\n\n #ifdef CENTER\n uv+=vec2(0.5,0.5);\n #endif\n\n float asp=1.0;\n float nY=numY;\n #ifdef SQUARE\n asp=aspect;\n nY=numX/aspect;\n\n #endif\n\n float total = floor(uv.x*numX-numX/2.0) +floor(uv.y/asp*nY-nY/2.0);\n float r = mod(total,2.0);\n\n vec4 col=vec4(r,r,r,1.0);\n vec4 base=texture(tex,texCoord);\n outColor=cgl_blendPixel(base,col,amount);\n}",}; +const render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + amount = op.inValueSlider("Amount", 1), + inSquare = op.inBool("Square", true), + numX = op.inValue("Num X", 10), + numY = op.inValue("Num Y", 10), + inRotate = op.inValueSlider("Rotate", 0.0), + inCentered = op.inBool("Centered", true), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "checkerboard"); + +shader.setSource(shader.getDefaultVertexShader(), attachments.checkerboard_frag); + +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + uniNumX = new CGL.Uniform(shader, "f", "numX", numX), + uniNumY = new CGL.Uniform(shader, "f", "numY", numY), + uniAspect = new CGL.Uniform(shader, "f", "aspect", 1), + rotateUniform = new CGL.Uniform(shader, "f", "rotate", inRotate); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +inSquare.onChange = +inCentered.onChange = updateDefines; + +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("CENTER", inCentered.get()); + shader.toggleDefine("SQUARE", inSquare.get()); + + numY.setUiAttribs({ "greyout": inSquare.get() }); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + uniAspect.set(cgl.currentTextureEffect.aspectRatio); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.CheckerBoard_v2.prototype = new CABLES.Op(); +CABLES.OPS["7edfae81-f092-413f-a2a0-b109fdffa61d"]={f:Ops.Gl.TextureEffects.CheckerBoard_v2,objName:"Ops.Gl.TextureEffects.CheckerBoard_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ChromaticAberration_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.ChromaticAberration_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"chromatic_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float pixel;\nUNI float onePixel;\nUNI float amount;\nUNI float lensDistort;\n\n#ifdef MASK\nUNI sampler2D texMask;\n#endif\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n vec4 base=texture(tex,texCoord);\n vec4 col=texture(tex,texCoord);\n\n vec2 tc=texCoord;;\n float pix = pixel;\n if(lensDistort>0.0)\n {\n float dist = distance(texCoord, vec2(0.5,0.5));\n tc-=0.5;\n tc *=smoothstep(-0.9,1.0*lensDistort,1.0-dist);\n tc+=0.5;\n }\n\n #ifdef MASK\n vec4 m=texture(texMask,texCoord);\n pix*=m.r*m.a;\n #endif\n\n #ifdef SMOOTH\n #ifdef WEBGL2\n float numSamples=round(pix/onePixel/4.0+1.0);\n col.r=0.0;\n col.b=0.0;\n\n for(float off=0.0;offinner*sz) v=(smoothstep(0.0,1.0,(dist-(inner*sz))/(fade)));\n }\n\n if(fade>=0.0)\n {\n\n #ifdef FALLOFF_SMOOTHSTEP\n if(dist>inner*sz && distinner*sz && dist(1.0-width) || texCoord.y>(1.0-width) || texCoord.y0.001*amount)outColor= vec4(1.0,0.0,0.0, 1.0);\n #endif\n}\n",}; +const + render = op.inTrigger("Render"), + amount = op.inValueSlider("Amount", 1), + blendMode = CGL.TextureEffect.AddBlendSelect(op), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + inSize = op.inValueSlider("Size", 0.25), + inInner = op.inValueSlider("Inner"), + inStretchX = op.inFloat("Stretch X"), + inStretchY = op.inFloat("Stretch Y"), + inX = op.inValue("Pos X", 0), + inY = op.inValue("Pos Y", 0), + fallOff = op.inValueSelect("fallOff", ["Linear", "SmoothStep"], "Linear"), + inFadeOut = op.inValueSlider("fade Out"), + warnOverflow = op.inValueBool("warn overflow", false), + r = op.inValueSlider("r", 1), + g = op.inValueSlider("g", 1), + b = op.inValueSlider("b", 1), + a = op.inValueSlider("a", 1), + trigger = op.outTrigger("Next"); + +r.setUiAttribs({ "colorPick": true }); + +op.setPortGroup("Size", [inSize, inInner, inStretchX, inStretchY]); +op.setPortGroup("Position", [inX, inY]); +op.setPortGroup("Style", [warnOverflow, fallOff, inFadeOut]); + +let cgl = op.patch.cgl; +let shader = new CGL.Shader(cgl, "textureeffect stripes"); +shader.setSource(shader.getDefaultVertexShader(), attachments.circle_frag); + +updateDefines(); + +let + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + uniStretch = new CGL.Uniform(shader, "2f", "stretch", inStretchX, inStretchY), + uniSize = new CGL.Uniform(shader, "f", "size", inSize), + uniFadeOut = new CGL.Uniform(shader, "f", "fadeOut", inFadeOut), + uniInner = new CGL.Uniform(shader, "f", "inner", inInner), + aspect = new CGL.Uniform(shader, "f", "aspect", 1), + uniformR = new CGL.Uniform(shader, "f", "r", r), + uniformG = new CGL.Uniform(shader, "f", "g", g), + uniformB = new CGL.Uniform(shader, "f", "b", b), + uniformA = new CGL.Uniform(shader, "f", "a", a), + uniformX = new CGL.Uniform(shader, "f", "x", inX), + uniformY = new CGL.Uniform(shader, "f", "y", inY); + +fallOff.onChange = + warnOverflow.onChange = updateDefines; + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +function updateDefines() +{ + shader.toggleDefine("FALLOFF_LINEAR", fallOff.get() == "Linear"); + shader.toggleDefine("FALLOFF_SMOOTHSTEP", fallOff.get() == "SmoothStep"); + shader.toggleDefine("WARN_OVERFLOW", warnOverflow.get()); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + aspect.set(cgl.currentTextureEffect.aspectRatio); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.CircleTexture_v4.prototype = new CABLES.Op(); +CABLES.OPS["9738c421-1ee0-42bf-be0b-f4a481385fbf"]={f:Ops.Gl.TextureEffects.CircleTexture_v4,objName:"Ops.Gl.TextureEffects.CircleTexture_v4"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ClampTexture +// +// ************************************************************** + +Ops.Gl.TextureEffects.ClampTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"clampShader_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float lowEdge;\nUNI float highEdge;\n\n{{CGL.BLENDMODES}}\n\nvoid main()\n{\n vec3 result = vec3(0.);\n vec3 color = texture(tex,texCoord).rgb;\n\n #ifdef CLAMP\n result = clamp(color,vec3(lowEdge),vec3(highEdge));\n #endif\n\n #ifdef REMAP\n result = mix(color*vec3(lowEdge),color*vec3(highEdge),color);\n #endif\n\n #ifdef REMAP_SMOOTH\n result = smoothstep(vec3(lowEdge),vec3(highEdge),color);\n #endif\n\n outColor= mix(vec4(color,1.0),\n vec4(result,1.0),\n amount);\n}",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + modeSelect = op.inValueSelect("Mode", ["Clamp", "Remap", "Remap smooth"], "Clamp"), + inLowEdge = op.inValue("Min", 0.0), + inHighEdge = op.inValue("Max", 1.0), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.clampShader_frag); + +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); +const lowEdgeUniform = new CGL.Uniform(shader, "f", "lowEdge", inLowEdge); +const highEdgeUniform = new CGL.Uniform(shader, "f", "highEdge", inHighEdge); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +op.init = modeSelect.onChange = function () +{ + shader.toggleDefine("CLAMP", modeSelect.get() === "Clamp"); + shader.toggleDefine("REMAP", modeSelect.get() === "Remap"); + shader.toggleDefine("REMAP_SMOOTH", modeSelect.get() === "Remap smooth"); +}; +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.ClampTexture.prototype = new CABLES.Op(); +CABLES.OPS["086ca023-af3c-4e3a-9be7-1972adcf63b5"]={f:Ops.Gl.TextureEffects.ClampTexture,objName:"Ops.Gl.TextureEffects.ClampTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Clarity +// +// ************************************************************** + +Ops.Gl.TextureEffects.Clarity = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"clarity_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float pX,pY;\n\nvec3 desaturate(vec4 color)\n{\n vec3 c= vec3(dot(vec3(0.2126,0.7152,0.0722), color.rgb));\n return c;\n}\n\nvoid main()\n{\n vec4 col=texture(tex,texCoord);\n\n vec3 gray=desaturate(col);\n vec3 m=smoothstep(0.2,0.5,gray)*smoothstep(0.75,0.5,gray);\n vec4 col2=vec4(1.0);\n\n col2.rgb = ((col.rgb - 0.5) * max(( vec3(amount)*m+0.5)*2.0, 0.0))+0.5;\n\n outColor= col2;\n}\n\n\n",}; +const render = op.inTrigger("Render"); +const trigger = op.outTrigger("Trigger"); +const amount = op.inFloat("amount", 0.5); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.clarity_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Clarity.prototype = new CABLES.Op(); +CABLES.OPS["37d66c32-5594-4509-bba0-0ba2cbb706d8"]={f:Ops.Gl.TextureEffects.Clarity,objName:"Ops.Gl.TextureEffects.Clarity"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ColorBalance_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.ColorBalance_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"colorbalance_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float r;\nUNI float g;\nUNI float b;\n\nfloat lumi(vec3 color)\n{\n return vec3(dot(vec3(0.2126,0.7152,0.0722), color)).r;\n}\n\nvoid main()\n{\n vec4 base=texture(tex,texCoord);\n float l=lumi(base.rgb);\n\n #ifdef TONE_MID\n l=smoothstep(0.33,0.66,l);\n #endif\n\n #ifdef TONE_LOW\n l=1.0-l;\n #endif\n\n l=l*l;\n vec3 color=base.rgb+vec3(l*r*0.1,l*g*0.1,l*b*0.1);\n outColor= vec4(color,base.a);\n}\n",}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + tone = op.inValueSelect("Tone", ["Highlights", "Midtones", "Shadows"], "Highlights"), + r = op.inValue("r"), + g = op.inValue("g"), + b = op.inValue("b"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.colorbalance_frag); +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uniR = new CGL.Uniform(shader, "f", "r", r), + uniG = new CGL.Uniform(shader, "f", "g", g), + uniB = new CGL.Uniform(shader, "f", "b", b); + +tone.onChange = function () +{ + shader.toggleDefine("TONE_HIGH", tone.get() == "Highlights"); + shader.toggleDefine("TONE_MID", tone.get() == "Midtones"); + shader.toggleDefine("TONE_LOW", tone.get() == "Shadows"); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.ColorBalance_v2.prototype = new CABLES.Op(); +CABLES.OPS["5af81475-2aa6-451b-a1f3-0980f641a72e"]={f:Ops.Gl.TextureEffects.ColorBalance_v2,objName:"Ops.Gl.TextureEffects.ColorBalance_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ColorChannel_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.ColorChannel_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"colorchannel_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\n\nvoid main()\n{\n vec4 color=texture(tex,texCoord);\n vec4 col=vec4(0.0,0.0,0.0,color.a);\n\n #ifdef CHANNEL_R\n col.r=color.r;\n #ifdef MONO\n col.g=col.b=col.r;\n #endif\n #endif\n\n #ifdef CHANNEL_G\n col.g=color.g;\n #ifdef MONO\n col.r=col.b=col.g;\n #endif\n #endif\n\n #ifdef CHANNEL_B\n col.b=color.b;\n #ifdef MONO\n col.g=col.r=col.b;\n #endif\n #endif\n\n #ifdef CHANNEL_A\n col.r=col.g=col.b=color.a;\n #endif\n\n outColor = col;\n}",}; +const + render = op.inTrigger("render"), + channelR = op.inValueBool("channelR", true), + channelG = op.inValueBool("channelG", false), + channelB = op.inValueBool("channelB", false), + channelA = op.inValueBool("channelA", false), + mono = op.inValueBool("mono", false), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.colorchannel_frag || ""); +let textureUniform = new CGL.Uniform(shader, "t", "tex", 0); + +mono.onChange = + channelA.onChange = + channelR.onChange = + channelG.onChange = + channelB.onChange = updateChannels; +updateChannels(); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + +function updateChannels() +{ + shader.toggleDefine("CHANNEL_R",channelR.get()); + shader.toggleDefine("CHANNEL_G",channelG.get()); + shader.toggleDefine("CHANNEL_B",channelB.get()); + shader.toggleDefine("CHANNEL_A",channelA.get()); + shader.toggleDefine("MONO",mono.get()); +} + + +}; + +Ops.Gl.TextureEffects.ColorChannel_v2.prototype = new CABLES.Op(); +CABLES.OPS["0a512974-0920-4aa8-89dc-4dda184c0d46"]={f:Ops.Gl.TextureEffects.ColorChannel_v2,objName:"Ops.Gl.TextureEffects.ColorChannel_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ColorMapRange +// +// ************************************************************** + +Ops.Gl.TextureEffects.ColorMapRange = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"maprange_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\n\nUNI float min1,min2,max1,max2;\n\nfloat map(float value)\n{\n return min2 + (value - min1) * (max2 - min2) / (max1 - min1);\n}\n\nvoid main()\n{\n vec4 col=texture(tex,texCoord);\n\n #ifdef CH_R\n col.r=map(col.r);\n #endif\n #ifdef CH_G\n col.g=map(col.g);\n #endif\n #ifdef CH_B\n col.b=map(col.b);\n #endif\n #ifdef CH_A\n col.a=map(col.a);\n #endif\n\n outColor = col;\n}",}; +const + render = op.inTrigger("render"), + min1 = op.inValueSlider("Old Min", 0), + max1 = op.inValueSlider("Old Max", 1), + min2 = op.inValueSlider("New Min", 0), + max2 = op.inValueSlider("New Max", 1), + + inR = op.inBool("R", true), + inG = op.inBool("G", true), + inB = op.inBool("B", true), + inA = op.inBool("A", false), + + trigger = op.outTrigger("trigger"); + +op.setPortGroup("Input Range", [min1, max1]); +op.setPortGroup("Output Range", [min2, max2]); + +const cgl = op.patch.cgl; + +const shader = new CGL.Shader(cgl, "colorMaprange"); +shader.setSource(shader.getDefaultVertexShader(), attachments.maprange_frag); +toggleChannels(shader); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uniMin1 = new CGL.Uniform(shader, "f", "min1", min1), + uniMin2 = new CGL.Uniform(shader, "f", "min2", min2), + unimax1 = new CGL.Uniform(shader, "f", "max1", max1), + unimax2 = new CGL.Uniform(shader, "f", "max2", max2); + +inR.onChange = + inG.onChange = + inB.onChange = + inA.onChange = () => + { + toggleChannels(shader); + }; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + if (!cgl.currentTextureEffect.getCurrentSourceTexture()) return; + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + +function toggleChannels(shader) +{ + shader.toggleDefine("CH_R", inR.get()); + shader.toggleDefine("CH_G", inG.get()); + shader.toggleDefine("CH_B", inB.get()); + shader.toggleDefine("CH_A", inA.get()); +} + + +}; + +Ops.Gl.TextureEffects.ColorMapRange.prototype = new CABLES.Op(); +CABLES.OPS["a1452720-dc08-4195-983b-7949aac33055"]={f:Ops.Gl.TextureEffects.ColorMapRange,objName:"Ops.Gl.TextureEffects.ColorMapRange"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ColorMap_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.ColorMap_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"colormap_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D gradient;\nUNI float pos;\nUNI float amount;\nUNI float vmin;\nUNI float vmax;\n\n{{CGL.BLENDMODES3}}\n\n\nfloat lumi(vec3 color)\n{\n return vec3(dot(vec3(0.2126,0.7152,0.0722), color)).r;\n}\n\nvoid main()\n{\n vec4 base=texture(tex,texCoord);\n float a=base.a;\n\n base=clamp(base,vmin,vmax);\n\n #ifdef METH_LUMI\n vec4 color=texture(gradient,vec2(lumi(base.rgb),pos));\n #endif\n\n #ifdef METH_CHANNELS\n vec4 color=vec4(1.0);\n color.r=texture(gradient,vec2(base.r,pos)).r;\n color.g=texture(gradient,vec2(base.g,pos)).g;\n color.b=texture(gradient,vec2(base.b,pos)).b;\n #endif\n\n base.a=color.a=a;\n\n\n outColor=cgl_blendPixel(base,color,amount);\n\n}\n",}; +let render = op.inTrigger("render"); +let trigger = op.outTrigger("trigger"); + +const blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"); +const amount = op.inValueSlider("Amount", 1); + +let inGradient = op.inTexture("Gradient"); +let inMethod = op.inSwitch("Method", ["Luminance", "Channels"], "Luminance"); + +let inMin = op.inFloatSlider("Min", 0); +let inMax = op.inFloatSlider("Max", 1); + +let inPos = op.inValueSlider("Position", 0.5); + +op.setPortGroup("Vertical Position", [inMin, inMax, inPos]); + +let cgl = op.patch.cgl; +let shader = new CGL.Shader(cgl, op.name); +shader.define("METH_LUMI"); + +shader.setSource(shader.getDefaultVertexShader(), attachments.colormap_frag); +let textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +let textureUniform2 = new CGL.Uniform(shader, "t", "gradient", 1); +let uniPos = new CGL.Uniform(shader, "f", "pos", inPos); +let uniMin = new CGL.Uniform(shader, "f", "vmin", inMin); +let uniMax = new CGL.Uniform(shader, "f", "vmax", inMax); +let uniAmount = new CGL.Uniform(shader, "f", "amount", amount); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +inMethod.onChange = () => +{ + shader.toggleDefine("METH_LUMI", inMethod.get() == "Luminance"); + shader.toggleDefine("METH_CHANNELS", inMethod.get() == "Channels"); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + if (!inGradient.get()) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.setTexture(1, inGradient.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.ColorMap_v2.prototype = new CABLES.Op(); +CABLES.OPS["440c1675-122d-411f-b848-16c60b677120"]={f:Ops.Gl.TextureEffects.ColorMap_v2,objName:"Ops.Gl.TextureEffects.ColorMap_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Color_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Color_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"color_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float r;\nUNI float g;\nUNI float b;\nUNI float amount;\n\n#ifdef MASK\n UNI sampler2D mask;\n#endif\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n vec4 col=vec4(r,g,b,1.0);\n vec4 base=texture(tex,texCoord);\n\n float am=amount;\n #ifdef MASK\n float msk=texture(mask,texCoord).r;\n #ifdef INVERTMASK\n msk=1.0-msk;\n #endif\n am*=1.0-msk;\n #endif\n\n outColor=cgl_blendPixel(base,col,am);\n}\n",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op), + amount = op.inValueSlider("Amount", 1), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + + inMask = op.inTexture("Mask"), + inMaskInvert = op.inValueBool("Mask Invert"), + r = op.inValueSlider("r", Math.random()), + g = op.inValueSlider("g", Math.random()), + b = op.inValueSlider("b", Math.random()), + trigger = op.outTrigger("trigger"); + +r.setUiAttribs({ "colorPick": true }); +op.setPortGroup("Color", [r, g, b]); + +const TEX_SLOT = 0; +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "textureeffect color"); +const srcFrag = attachments.color_frag || ""; +shader.setSource(shader.getDefaultVertexShader(), srcFrag); +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", TEX_SLOT), + makstextureUniform = new CGL.Uniform(shader, "t", "mask", 1), + uniformR = new CGL.Uniform(shader, "f", "r", r), + uniformG = new CGL.Uniform(shader, "f", "g", g), + uniformB = new CGL.Uniform(shader, "f", "b", b), + uniformAmount = new CGL.Uniform(shader, "f", "amount", amount); + +inMask.onChange = function () +{ + if (inMask.isLinked())shader.define("MASK"); + else shader.removeDefine("MASK"); +}; + +inMaskInvert.onChange = function () +{ + if (inMaskInvert.get())shader.define("INVERTMASK"); + else shader.removeDefine("INVERTMASK"); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(TEX_SLOT, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + if (inMask.get()) cgl.setTexture(1, inMask.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Color_v2.prototype = new CABLES.Op(); +CABLES.OPS["6dada2b7-da7c-47ee-87a9-a12e87055208"]={f:Ops.Gl.TextureEffects.Color_v2,objName:"Ops.Gl.TextureEffects.Color_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Denoise +// +// ************************************************************** + +Ops.Gl.TextureEffects.Denoise = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"denoise_frag":"UNI sampler2D tex;\nUNI float exponent;\nUNI float strength;\nUNI vec2 texSize;\nIN vec2 texCoord;\n\nvoid main()\n{\n vec4 center = texture(tex, texCoord);\n vec4 color = vec4(0.0);\n float total = 0.0;\n const float pixels=4.0;\n for (float x = -pixels; x <= pixels; x += 1.0) {\n for (float y = -pixels; y <= pixels; y += 1.0) {\n vec4 smpl = texture(tex, texCoord + vec2(x, y) / texSize);\n float weight = 1.0 - abs(dot(smpl.rgb - center.rgb, vec3(0.25)));\n weight = pow(weight, (1.0-exponent)*50.0);\n color += smpl * weight;\n total += weight;\n }\n }\n outColor = color / total;\n}\n",}; +let render = op.inTrigger("render"); +let strength = op.inValueSlider("Exponent", 0.6); + +let trigger = op.outTrigger("trigger"); + +let cgl = op.patch.cgl; +let shader = new CGL.Shader(cgl, op.name); +let tsize = [128, 128]; +let srcFrag = attachments.denoise_frag; + +shader.setSource(shader.getDefaultVertexShader(), srcFrag); +let textureUniform = new CGL.Uniform(shader, "t", "tex", 0); + +let strengthUniform = new CGL.Uniform(shader, "f", "exponent", strength); +let texSizeUniform = new CGL.Uniform(shader, "2f", "texSize", tsize); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + tsize[0] = cgl.currentTextureEffect.getCurrentSourceTexture().width; + tsize[1] = cgl.currentTextureEffect.getCurrentSourceTexture().height; + texSizeUniform.setValue(tsize); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Denoise.prototype = new CABLES.Op(); +CABLES.OPS["0abfea0f-1aa9-47bf-b540-f54f89a60a6c"]={f:Ops.Gl.TextureEffects.Denoise,objName:"Ops.Gl.TextureEffects.Denoise"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.DepthTextureFocus_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.DepthTextureFocus_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"depth_focus_frag":"IN vec2 texCoord;\nUNI sampler2D image;\nUNI float nearPlane;\nUNI float farPlane;\nUNI float focus; // center\nUNI float width;\n\n\nvoid main()\n{\n float depthFromTexture = texture(image,texCoord).r;\n\n float z_viewSpace = (nearPlane * farPlane) / (farPlane - depthFromTexture * (farPlane - nearPlane));\n z_viewSpace = abs(z_viewSpace - (focus));\n z_viewSpace = smoothstep(0.0, width, z_viewSpace);\n\n #ifndef INVERT\n z_viewSpace = 1. - z_viewSpace;\n #endif\n\n outColor = vec4(vec3(z_viewSpace), 1.);\n}",}; +const render = op.inTrigger("render"); +const depthTexture = op.inTexture("Depth Texture"); + +const inFocus = op.inFloat("Focus", 0.5); +const inWidth = op.inFloat("Width", 0.2); +const inInv = op.inBool("Invert", false); +const nearPlane = op.inFloat("nearplane", 0.1); +const farPlane = op.inFloat("farplane", 100); + +const trigger = op.outTrigger("trigger"); + +op.setPortGroup("Frustum", [farPlane, nearPlane]); +op.setPortGroup("Focus Settings", [inInv, inFocus, inWidth]); + + +const cgl = op.patch.cgl; + +const shader = new CGL.Shader(cgl, op.name); +const srcFrag = attachments.depth_focus_frag || ""; +shader.setSource(shader.getDefaultVertexShader(), srcFrag); + +const textureUniform = new CGL.Uniform(shader, "t", "depthTexture", 0); +const uniFarplane = new CGL.Uniform(shader, "f", "farPlane", farPlane); +const uniNearplane = new CGL.Uniform(shader, "f", "nearPlane", nearPlane); +const uniFocus = new CGL.Uniform(shader, "f", "focus", inFocus); +const uniwidth = new CGL.Uniform(shader, "f", "width", inWidth); +const uniAspect = new CGL.Uniform(shader, "f", "aspectRatio", 0); + +inInv.onChange = function () +{ + if (inInv.get())shader.define("INVERT"); + else shader.removeDefine("INVERT"); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + if (depthTexture.get() && depthTexture.get().tex) + { + const a = + cgl.currentTextureEffect.getCurrentSourceTexture().height + / cgl.currentTextureEffect.getCurrentSourceTexture().width; + + uniAspect.set(a); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + + cgl.setTexture(0, depthTexture.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + } + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.DepthTextureFocus_v2.prototype = new CABLES.Op(); +CABLES.OPS["f84ac22e-664e-4ff1-b23f-539ac1f5c67e"]={f:Ops.Gl.TextureEffects.DepthTextureFocus_v2,objName:"Ops.Gl.TextureEffects.DepthTextureFocus_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.DepthTexture_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.DepthTexture_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"depthtexture_frag":"IN vec2 texCoord;\nUNI float amount;\nUNI sampler2D texDepth;\nUNI sampler2D texBase;\nUNI float n;\nUNI float f;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n vec4 col=texture(texDepth,texCoord);\n float z=col.r;\n float c=(2.0*n)/(f+n-z*(f-n));\n\n #ifdef INVERT\n c=1.0-c;\n #endif\n\n col=vec4(c,c,c,1.0);\n vec4 base=texture(texBase,texCoord);\n\n outColor=cgl_blendPixel(base,col,amount);\n\n}",}; +const + render = op.inTrigger("render"), + inDepthTex = op.inTexture("image"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + farPlane = op.inValue("farplane", 50.0), + nearPlane = op.inValue("nearplane", 0.1), + inInv = op.inValueBool("Invert", false), + trigger = op.outTrigger("trigger"); + +op.setPortGroup("Frustum", [farPlane, nearPlane]); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.depthtexture_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "texDepth", 0), + textureBaseUniform = new CGL.Uniform(shader, "t", "texBase", 1), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + uniFarplane = new CGL.Uniform(shader, "f", "f", farPlane), + uniNearplane = new CGL.Uniform(shader, "f", "n", nearPlane); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +inInv.onChange = function () +{ + if (inInv.get())shader.define("INVERT"); + else shader.removeDefine("INVERT"); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + if (inDepthTex.get() && inDepthTex.get().tex) + { + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, inDepthTex.get().tex); + cgl.setTexture(1, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + cgl.currentTextureEffect.finish(); + cgl.popShader(); + } + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.DepthTexture_v2.prototype = new CABLES.Op(); +CABLES.OPS["5958fbb8-fb78-4de2-85dc-5eb289f652cb"]={f:Ops.Gl.TextureEffects.DepthTexture_v2,objName:"Ops.Gl.TextureEffects.DepthTexture_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Desaturate +// +// ************************************************************** + +Ops.Gl.TextureEffects.Desaturate = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"desaturate_frag":"\nIN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\n\n#ifdef MASK\n UNI sampler2D mask;\n#endif\n\nvec3 desaturate(vec3 color, float amount)\n{\n vec3 gray = vec3(dot(vec3(0.2126,0.7152,0.0722), color));\n return vec3(mix(color, gray, amount));\n}\n\nvoid main()\n{\n vec4 col=texture(tex,texCoord);\n\n float am=amount;\n #ifdef MASK\n am*=1.0-texture(mask,texCoord).r;\n #ifdef INVERTMASK\n am=1.0-am;\n #endif\n #endif\n\n col.rgb=desaturate(col.rgb,am);\n outColor= col;\n}",}; +const render = op.inTrigger("render"); +const trigger = op.outTrigger("trigger"); +const amount = op.inValueSlider("amount", 1); +const inMask = op.inTexture("Mask"); +const invertMask = op.inValueBool("Invert Mask"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.desaturate_frag); +let textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +let masktextureUniform = new CGL.Uniform(shader, "t", "mask", 1); +let amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + + +invertMask.onChange = function () +{ + if (invertMask.get())shader.define("INVERTMASK"); + else shader.removeDefine("INVERTMASK"); +}; + +inMask.onChange = function () +{ + if (inMask.get())shader.define("MASK"); + else shader.removeDefine("MASK"); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + if (inMask.get()) cgl.setTexture(1, inMask.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Desaturate.prototype = new CABLES.Op(); +CABLES.OPS["340efbd5-be53-4bd5-92ad-8f38d8eeecf1"]={f:Ops.Gl.TextureEffects.Desaturate,objName:"Ops.Gl.TextureEffects.Desaturate"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Dither_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Dither_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"dither_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float strength;\nUNI float amount;\nUNI float width;\nUNI float height;\nUNI float threshold;\n\nfloat lumi( vec4 col ) {\n return (0.2126*col.r + 0.7152*col.g + 0.0722*col.b);\n}\n\n{{CGL.BLENDMODES3}}\n\nfloat adjustFrag( mat4 adjustments,float val, vec2 coord )\n{\n vec2 coordMod = mod(vec2(coord.x*width,coord.y*height), 4.0);\n int xMod = int(coordMod.x);\n int yMod = int(coordMod.y);\n\n vec4 col;\n if (xMod == 0) col = adjustments[0];\n else if (xMod == 1) col = adjustments[1];\n else if (xMod == 2) col = adjustments[2];\n else if (xMod == 3) col = adjustments[3];\n\n float adjustment;\n if (yMod == 0) adjustment = col.x;\n else if (yMod == 1) adjustment = col.y;\n else if (yMod == 2) adjustment = col.z;\n else if (yMod == 3) adjustment = col.w;\n\n return val + (val * adjustment);\n}\n\nvoid main()\n{\n mat4 adjustments = ((mat4(\n 1, 13, 4, 16,\n 9, 5, 12, 8,\n 3, 15, 2, 14,\n 11, 7, 10, 6\n ) - 8.) * 1.0 / strength);\n\n vec4 base=texture(tex,texCoord);\n vec4 color;\n\n float lum = lumi(base);\n lum = adjustFrag(adjustments,lum, texCoord.xy);\n\n if (lum > threshold) color = vec4(1, 1, 1, base.a);\n else color = vec4(0, 0, 0, base.a);\n\n outColor=cgl_blendPixel(base,color,amount);\n}",}; +const + render = op.inTrigger("Render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + trigger = op.outTrigger("Trigger"), + strength = op.inValue("strength", 2), + threshold = op.inValueSlider("threshold", 0.35); + +const + cgl = op.patch.cgl, + shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.dither_frag); + +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + strengthUniform = new CGL.Uniform(shader, "f", "strength", strength), + uniWidth = new CGL.Uniform(shader, "f", "width", 0), + uniHeight = new CGL.Uniform(shader, "f", "height", 0), + unithreshold = new CGL.Uniform(shader, "f", "threshold", threshold); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op,3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + uniWidth.setValue(cgl.currentTextureEffect.getCurrentSourceTexture().width); + uniHeight.setValue(cgl.currentTextureEffect.getCurrentSourceTexture().height); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Dither_v2.prototype = new CABLES.Op(); +CABLES.OPS["686ae373-2d2d-44cc-b45f-2ccb782dea26"]={f:Ops.Gl.TextureEffects.Dither_v2,objName:"Ops.Gl.TextureEffects.Dither_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.DrawImage_v3 +// +// ************************************************************** + +Ops.Gl.TextureEffects.DrawImage_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"drawimage_frag":"#ifdef HAS_TEXTURES\n IN vec2 texCoord;\n UNI sampler2D tex;\n UNI sampler2D image;\n#endif\n\n#ifdef TEX_TRANSFORM\n IN mat3 transform;\n#endif\n// UNI float rotate;\n\n{{CGL.BLENDMODES}}\n\n#ifdef HAS_TEXTUREALPHA\n UNI sampler2D imageAlpha;\n#endif\n\nUNI float amount;\n\n#ifdef ASPECT_RATIO\n UNI float aspectTex;\n UNI float aspectPos;\n#endif\n\nvoid main()\n{\n vec4 blendRGBA=vec4(0.0,0.0,0.0,1.0);\n\n #ifdef HAS_TEXTURES\n vec2 tc=texCoord;\n\n #ifdef TEX_FLIP_X\n tc.x=1.0-tc.x;\n #endif\n #ifdef TEX_FLIP_Y\n tc.y=1.0-tc.y;\n #endif\n\n #ifdef ASPECT_RATIO\n #ifdef ASPECT_AXIS_X\n tc.y=(1.0-aspectPos)-(((1.0-aspectPos)-tc.y)*aspectTex);\n #endif\n #ifdef ASPECT_AXIS_Y\n tc.x=(1.0-aspectPos)-(((1.0-aspectPos)-tc.x)/aspectTex);\n #endif\n #endif\n\n #ifdef TEX_TRANSFORM\n vec3 coordinates=vec3(tc.x, tc.y,1.0);\n tc=(transform * coordinates ).xy;\n #endif\n\n blendRGBA=texture(image,tc);\n\n vec3 blend=blendRGBA.rgb;\n vec4 baseRGBA=texture(tex,texCoord);\n vec3 base=baseRGBA.rgb;\n\n\n #ifdef PREMUL\n blend.rgb = (blend.rgb) + (base.rgb * (1.0 - blendRGBA.a));\n #endif\n\n vec3 colNew=_blend(base,blend);\n\n\n\n\n #ifdef REMOVE_ALPHA_SRC\n blendRGBA.a=1.0;\n #endif\n\n #ifdef HAS_TEXTUREALPHA\n vec4 colImgAlpha=texture(imageAlpha,tc);\n float colImgAlphaAlpha=colImgAlpha.a;\n\n #ifdef ALPHA_FROM_LUMINANCE\n vec3 gray = vec3(dot(vec3(0.2126,0.7152,0.0722), colImgAlpha.rgb ));\n colImgAlphaAlpha=(gray.r+gray.g+gray.b)/3.0;\n #endif\n\n #ifdef ALPHA_FROM_INV_UMINANCE\n vec3 gray = vec3(dot(vec3(0.2126,0.7152,0.0722), colImgAlpha.rgb ));\n colImgAlphaAlpha=1.0-(gray.r+gray.g+gray.b)/3.0;\n #endif\n\n #ifdef INVERT_ALPHA\n colImgAlphaAlpha=clamp(colImgAlphaAlpha,0.0,1.0);\n colImgAlphaAlpha=1.0-colImgAlphaAlpha;\n #endif\n\n blendRGBA.a=colImgAlphaAlpha*blendRGBA.a;\n #endif\n #endif\n\n float am=amount;\n\n #ifdef CLIP_REPEAT\n if(tc.y>1.0 || tc.y<0.0 || tc.x>1.0 || tc.x<0.0)\n {\n // colNew.rgb=vec3(0.0);\n am=0.0;\n }\n #endif\n\n #ifdef ASPECT_RATIO\n #ifdef ASPECT_CROP\n if(tc.y>1.0 || tc.y<0.0 || tc.x>1.0 || tc.x<0.0)\n {\n colNew.rgb=base.rgb;\n am=0.0;\n }\n\n #endif\n #endif\n\n\n\n #ifndef PREMUL\n blendRGBA.rgb=mix(colNew,base,1.0-(am*blendRGBA.a));\n blendRGBA.a=clamp(baseRGBA.a+(blendRGBA.a*am),0.,1.);\n #endif\n\n #ifdef PREMUL\n // premultiply\n // blendRGBA.rgb = (blendRGBA.rgb) + (baseRGBA.rgb * (1.0 - blendRGBA.a));\n blendRGBA=vec4(\n mix(colNew.rgb,base,1.0-(am*blendRGBA.a)),\n blendRGBA.a*am+baseRGBA.a\n );\n #endif\n\n #ifdef ALPHA_MASK\n blendRGBA.a=baseRGBA.a;\n #endif\n\n outColor=blendRGBA;\n}\n\n\n\n\n\n\n\n","drawimage_vert":"IN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\n\nUNI mat4 projMatrix;\nUNI mat4 mvMatrix;\n\nOUT vec2 texCoord;\n// OUT vec3 norm;\n\n#ifdef TEX_TRANSFORM\n UNI float posX;\n UNI float posY;\n UNI float scaleX;\n UNI float scaleY;\n UNI float rotate;\n OUT mat3 transform;\n#endif\n\nvoid main()\n{\n texCoord=attrTexCoord;\n// norm=attrVertNormal;\n\n #ifdef TEX_TRANSFORM\n vec3 coordinates=vec3(attrTexCoord.x, attrTexCoord.y,1.0);\n float angle = radians( rotate );\n vec2 scale= vec2(scaleX,scaleY);\n vec2 translate= vec2(posX,posY);\n\n transform = mat3( scale.x * cos( angle ), scale.x * sin( angle ), 0.0,\n - scale.y * sin( angle ), scale.y * cos( angle ), 0.0,\n - 0.5 * scale.x * cos( angle ) + 0.5 * scale.y * sin( angle ) - 0.5 * translate.x*2.0 + 0.5, - 0.5 * scale.x * sin( angle ) - 0.5 * scale.y * cos( angle ) - 0.5 * translate.y*2.0 + 0.5, 1.0);\n #endif\n\n gl_Position = projMatrix * mvMatrix * vec4(vPosition, 1.0);\n}\n",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "blendMode"), + amount = op.inValueSlider("amount", 1), + + image = op.inTexture("Image"), + inAlphaPremul = op.inValueBool("Premultiplied", false), + inAlphaMask = op.inValueBool("Alpha Mask", false), + removeAlphaSrc = op.inValueBool("removeAlphaSrc", false), + + imageAlpha = op.inTexture("Mask"), + alphaSrc = op.inValueSelect("Mask Src", ["alpha channel", "luminance", "luminance inv"], "luminance"), + invAlphaChannel = op.inValueBool("Invert alpha channel"), + + inAspect = op.inValueBool("Aspect Ratio", false), + inAspectAxis = op.inValueSelect("Stretch Axis", ["X", "Y"], "X"), + inAspectPos = op.inValueSlider("Position", 0.0), + inAspectCrop = op.inValueBool("Crop", false), + + trigger = op.outTrigger("trigger"); + +blendMode.set("normal"); +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "drawimage"); + +imageAlpha.onLinkChanged = updateAlphaPorts; + +op.setPortGroup("Mask", [imageAlpha, alphaSrc, invAlphaChannel]); +op.setPortGroup("Aspect Ratio", [inAspect, inAspectPos, inAspectCrop, inAspectAxis]); + +function updateAlphaPorts() +{ + if (imageAlpha.isLinked()) + { + removeAlphaSrc.setUiAttribs({ "greyout": true }); + alphaSrc.setUiAttribs({ "greyout": false }); + invAlphaChannel.setUiAttribs({ "greyout": false }); + } + else + { + removeAlphaSrc.setUiAttribs({ "greyout": false }); + alphaSrc.setUiAttribs({ "greyout": true }); + invAlphaChannel.setUiAttribs({ "greyout": true }); + } +} + +op.toWorkPortsNeedToBeLinked(image); + +shader.setSource(attachments.drawimage_vert, attachments.drawimage_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + textureImaghe = new CGL.Uniform(shader, "t", "image", 1), + textureAlpha = new CGL.Uniform(shader, "t", "imageAlpha", 2), + uniTexAspect = new CGL.Uniform(shader, "f", "aspectTex", 1), + uniAspectPos = new CGL.Uniform(shader, "f", "aspectPos", inAspectPos); + +inAspect.onChange = + inAspectCrop.onChange = + inAspectAxis.onChange = updateAspectRatio; + +function updateAspectRatio() +{ + shader.removeDefine("ASPECT_AXIS_X"); + shader.removeDefine("ASPECT_AXIS_Y"); + shader.removeDefine("ASPECT_CROP"); + + inAspectPos.setUiAttribs({ "greyout": !inAspect.get() }); + inAspectCrop.setUiAttribs({ "greyout": !inAspect.get() }); + inAspectAxis.setUiAttribs({ "greyout": !inAspect.get() }); + + if (inAspect.get()) + { + shader.define("ASPECT_RATIO"); + + if (inAspectCrop.get()) shader.define("ASPECT_CROP"); + + if (inAspectAxis.get() == "X") shader.define("ASPECT_AXIS_X"); + if (inAspectAxis.get() == "Y") shader.define("ASPECT_AXIS_Y"); + } + else + { + shader.removeDefine("ASPECT_RATIO"); + if (inAspectCrop.get()) shader.define("ASPECT_CROP"); + + if (inAspectAxis.get() == "X") shader.define("ASPECT_AXIS_X"); + if (inAspectAxis.get() == "Y") shader.define("ASPECT_AXIS_Y"); + } +} + +alphaSrc.set("alpha channel"); + +// +// texture flip +// +const flipX = op.inValueBool("flip x"); +const flipY = op.inValueBool("flip y"); + +// +// texture transform +// + +let doTransform = op.inValueBool("Transform"); + +let scaleX = op.inValueSlider("Scale X", 1); +let scaleY = op.inValueSlider("Scale Y", 1); + +let posX = op.inValue("Position X", 0); +let posY = op.inValue("Position Y", 0); + +let rotate = op.inValue("Rotation", 0); + +const inClipRepeat = op.inValueBool("Clip Repeat", false); + +const uniScaleX = new CGL.Uniform(shader, "f", "scaleX", scaleX); +const uniScaleY = new CGL.Uniform(shader, "f", "scaleY", scaleY); +const uniPosX = new CGL.Uniform(shader, "f", "posX", posX); +const uniPosY = new CGL.Uniform(shader, "f", "posY", posY); +const uniRotate = new CGL.Uniform(shader, "f", "rotate", rotate); + +doTransform.onChange = updateTransformPorts; + +function updateTransformPorts() +{ + shader.toggleDefine("TEX_TRANSFORM", doTransform.get()); + + scaleX.setUiAttribs({ "greyout": !doTransform.get() }); + scaleY.setUiAttribs({ "greyout": !doTransform.get() }); + posX.setUiAttribs({ "greyout": !doTransform.get() }); + posY.setUiAttribs({ "greyout": !doTransform.get() }); + rotate.setUiAttribs({ "greyout": !doTransform.get() }); +} + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +render.onTriggered = doRender; + +inClipRepeat.onChange = + imageAlpha.onChange = + inAlphaPremul.onChange = + inAlphaMask.onChange = + invAlphaChannel.onChange = + flipY.onChange = + flipX.onChange = + removeAlphaSrc.onChange = + alphaSrc.onChange = updateDefines; + +updateTransformPorts(); +updateAlphaPorts(); +updateAspectRatio(); +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("REMOVE_ALPHA_SRC", removeAlphaSrc.get()); + shader.toggleDefine("ALPHA_MASK", inAlphaMask.get()); + + shader.toggleDefine("CLIP_REPEAT", inClipRepeat.get()); + + shader.toggleDefine("HAS_TEXTUREALPHA", imageAlpha.get() && imageAlpha.get().tex); + + shader.toggleDefine("TEX_FLIP_X", flipX.get()); + shader.toggleDefine("TEX_FLIP_Y", flipY.get()); + + shader.toggleDefine("INVERT_ALPHA", invAlphaChannel.get()); + + shader.toggleDefine("ALPHA_FROM_LUMINANCE", alphaSrc.get() == "luminance"); + shader.toggleDefine("ALPHA_FROM_INV_UMINANCE", alphaSrc.get() == "luminance_inv"); + shader.toggleDefine("PREMUL", inAlphaPremul.get()); +} + +function doRender() +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + const tex = image.get(); + if (tex && tex.tex && amount.get() > 0.0) + { + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + const imgTex = cgl.currentTextureEffect.getCurrentSourceTexture(); + cgl.setTexture(0, imgTex.tex); + + if (imgTex && tex) + { + if (tex.textureType != imgTex.textureType && (tex.textureType != CGL.Texture.TYPE_FLOAT || imgTex.textureType != CGL.Texture.TYPE_FLOAT)) + op.setUiError("textypediff", "Drawing 32bit texture into an 8 bit can result in data/precision loss", 1); + else + op.setUiError("textypediff", null); + } + + const asp = 1 / (cgl.currentTextureEffect.getWidth() / cgl.currentTextureEffect.getHeight()) * (tex.width / tex.height); + // uniTexAspect.setValue(1 / (tex.height / tex.width * imgTex.width / imgTex.height)); + + uniTexAspect.setValue(asp); + + cgl.setTexture(1, tex.tex); + // cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, image.get().tex ); + + if (imageAlpha.get() && imageAlpha.get().tex) + { + cgl.setTexture(2, imageAlpha.get().tex); + // cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, imageAlpha.get().tex ); + } + + // cgl.pushBlend(false); + + cgl.pushBlendMode(CGL.BLEND_NONE, true); + + cgl.currentTextureEffect.finish(); + cgl.popBlendMode(); + + // cgl.popBlend(); + + cgl.popShader(); + } + + trigger.trigger(); +} + + +}; + +Ops.Gl.TextureEffects.DrawImage_v3.prototype = new CABLES.Op(); +CABLES.OPS["8f6b2f15-fcb0-4597-90c0-e5173f2969fe"]={f:Ops.Gl.TextureEffects.DrawImage_v3,objName:"Ops.Gl.TextureEffects.DrawImage_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.EdgeDetection_v4 +// +// ************************************************************** + +Ops.Gl.TextureEffects.EdgeDetection_v4 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"edgedetect_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float width;\nUNI float strength;\nUNI float texWidth;\nUNI float texHeight;\nUNI float mulColor;\n\nconst vec4 lumcoeff = vec4(0.299,0.587,0.114, 0.);\n\nvec3 desaturate(vec3 color)\n{\n return vec3(dot(vec3(0.2126,0.7152,0.0722), color));\n}\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n // vec4 col=vec4(1.0,0.0,0.0,1.0);\n\n // float pixelX=0.27/texWidth;\n // float pixelY=0.27/texHeight;\n float pixelX=(width+0.01)*4.0/texWidth;\n float pixelY=(width+0.01)*4.0/texHeight;\n\nvec2 tc=texCoord;\n// #ifdef OFFSETPIXEL\n tc.x+=1.0/texWidth*0.5;\n tc.y+=1.0/texHeight*0.5;\n// #endif\n // col=texture(tex,texCoord);\n\n float count=1.0;\n vec4 base=texture(tex,texCoord);\n\n\tvec4 horizEdge = vec4( 0.0 );\n\thorizEdge -= texture( tex, vec2( tc.x - pixelX, tc.y - pixelY ) ) * 1.0;\n\thorizEdge -= texture( tex, vec2( tc.x - pixelX, tc.y ) ) * 2.0;\n\thorizEdge -= texture( tex, vec2( tc.x - pixelX, tc.y + pixelY ) ) * 1.0;\n\thorizEdge += texture( tex, vec2( tc.x + pixelX, tc.y - pixelY ) ) * 1.0;\n\thorizEdge += texture( tex, vec2( tc.x + pixelX, tc.y ) ) * 2.0;\n\thorizEdge += texture( tex, vec2( tc.x + pixelX, tc.y + pixelY ) ) * 1.0;\n\tvec4 vertEdge = vec4( 0.0 );\n\tvertEdge -= texture( tex, vec2( tc.x - pixelX, tc.y - pixelY ) ) * 1.0;\n\tvertEdge -= texture( tex, vec2( tc.x , tc.y - pixelY ) ) * 2.0;\n\tvertEdge -= texture( tex, vec2( tc.x + pixelX, tc.y - pixelY ) ) * 1.0;\n\tvertEdge += texture( tex, vec2( tc.x - pixelX, tc.y + pixelY ) ) * 1.0;\n\tvertEdge += texture( tex, vec2( tc.x , tc.y + pixelY ) ) * 2.0;\n\tvertEdge += texture( tex, vec2( tc.x + pixelX, tc.y + pixelY ) ) * 1.0;\n\n\thorizEdge*=base.a;\n\tvertEdge*=base.a;\n\n\n\tvec3 edge = sqrt((horizEdge.rgb/count * horizEdge.rgb/count) + (vertEdge.rgb/count * vertEdge.rgb/count));\n\n edge=desaturate(edge);\n edge*=strength;\n\n if(mulColor>0.0) edge*=texture( tex, texCoord ).rgb*mulColor*4.0;\n edge=max(min(edge,1.0),0.0);\n\n //blend section\n vec4 col=vec4(edge,base.a);\n\n outColor=cgl_blendPixel(base,col,amount*base.a);\n}\n\n",}; +const + render = op.inTrigger("Render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + strength = op.inFloat("Strength", 4.0), + width = op.inValueSlider("Width", 0.1), + mulColor = op.inValueSlider("Mul Color", 0), + trigger = op.outTrigger("Trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.edgedetect_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + strengthUniform = new CGL.Uniform(shader, "f", "strength", strength), + widthUniform = new CGL.Uniform(shader, "f", "width", width), + uniWidth = new CGL.Uniform(shader, "f", "texWidth", 128), + uniHeight = new CGL.Uniform(shader, "f", "texHeight", 128), + uniMulColor = new CGL.Uniform(shader, "f", "mulColor", mulColor); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op,3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + uniWidth.setValue(cgl.currentTextureEffect.getCurrentSourceTexture().width); + uniHeight.setValue(cgl.currentTextureEffect.getCurrentSourceTexture().height); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.EdgeDetection_v4.prototype = new CABLES.Op(); +CABLES.OPS["0240e26e-b86d-43b2-8c72-6795bb86dc76"]={f:Ops.Gl.TextureEffects.EdgeDetection_v4,objName:"Ops.Gl.TextureEffects.EdgeDetection_v4"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Emboss +// +// ************************************************************** + +Ops.Gl.TextureEffects.Emboss = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"emboss_frag":"#ifdef HAS_TEXTURES\n IN vec2 texCoord;\n UNI sampler2D tex;\n UNI float texSizeX;\n UNI float texSizeY;\n#endif\n\nUNI float strength;\n\nvoid main()\n{\n vec4 orig=texture(tex, texCoord);\n vec2 texelSize=vec2(texSizeX,texSizeY);\n\n float tl = abs(texture(tex, texCoord + texelSize * vec2(-1.0, -1.0)).x); // top left\n float l = abs(texture(tex, texCoord + texelSize * vec2(-1.0, 0.0)).x); // left\n float bl = abs(texture(tex, texCoord + texelSize * vec2(-1.0, 1.0)).x); // bottom left\n float t = abs(texture(tex, texCoord + texelSize * vec2( 0.0, -1.0)).x); // top\n float b = abs(texture(tex, texCoord + texelSize * vec2( 0.0, 1.0)).x); // bottom\n float tr = abs(texture(tex, texCoord + texelSize * vec2( 1.0, -1.0)).x); // top right\n float r = abs(texture(tex, texCoord + texelSize * vec2( 1.0, 0.0)).x); // right\n float br = abs(texture(tex, texCoord + texelSize * vec2( 1.0, 1.0)).x); // bottom right\n\n float dX = tr + 2.0*r + br -tl - 2.0*l - bl;\n float dY = bl + 2.0*b + br -tl - 2.0*t - tr;\n\n vec4 N=vec4(1.0);\n\n N.rgb=orig.rgb;\n\n #ifdef CLEAR\n N.rgb=vec3(0.5,0.5,0.5);\n #endif\n\n N.rgb-=vec3(dY)*strength;\n N.rgb+=vec3(dX)*strength;\n\n outColor= N;\n}",}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + strength = op.inValue("Strength", 4), + clear = op.inValueBool("Clear", true), + cgl = op.patch.cgl, + shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.emboss_frag || ""); +let textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +let uniStrength = new CGL.Uniform(shader, "f", "strength", strength); +let unitexSizeX = new CGL.Uniform(shader, "f", "texSizeX", 1024); +let unitexSizeY = new CGL.Uniform(shader, "f", "texSizeY", 1024); + +clear.onChange = updateClear; +updateClear(); + +function updateClear() +{ + if (clear.get())shader.define("CLEAR"); + else shader.removeDefine("CLEAR"); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + unitexSizeX.set(1.0 / cgl.currentTextureEffect.getCurrentSourceTexture().width); + unitexSizeY.set(1.0 / cgl.currentTextureEffect.getCurrentSourceTexture().height); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Emboss.prototype = new CABLES.Op(); +CABLES.OPS["e973e104-392a-44f0-bbc5-c382a08c15df"]={f:Ops.Gl.TextureEffects.Emboss,objName:"Ops.Gl.TextureEffects.Emboss"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.FXAA +// +// ************************************************************** + +Ops.Gl.TextureEffects.FXAA = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"fxaa_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float FXAA_SPAN_MAX;\nUNI float FXAA_REDUCE_MUL;\nUNI float FXAA_REDUCE_MIN;\nUNI float width;\nUNI float height;\n\nvec4 getColorFXAA(vec2 coord)\n{\n vec2 invtexsize=vec2(1.0/width,1.0/height);\n\n float step=1.0;\n\n vec3 rgbNW = texture(tex, coord.xy + (vec2(-step, -step)*invtexsize )).xyz;\n vec3 rgbNE = texture(tex, coord.xy + (vec2(+step, -step)*invtexsize )).xyz;\n vec3 rgbSW = texture(tex, coord.xy + (vec2(-step, +step)*invtexsize )).xyz;\n vec3 rgbSE = texture(tex, coord.xy + (vec2(+step, +step)*invtexsize )).xyz;\n vec3 rgbM = texture(tex, coord.xy).xyz;\n\n vec3 luma = vec3(0.299, 0.587, 0.114);\n float lumaNW = dot(rgbNW, luma);\n float lumaNE = dot(rgbNE, luma);\n float lumaSW = dot(rgbSW, luma);\n float lumaSE = dot(rgbSE, luma);\n float lumaM = dot( rgbM, luma);\n\n float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n\n vec2 dir;\n dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\n dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));\n\n float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\n\n float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);\n\n dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),\n max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin))*invtexsize ;\n\n vec3 rgbA = (1.0/2.0) * (\n texture(tex, coord.xy + dir * (1.0/3.0 - 0.5)).xyz +\n texture(tex, coord.xy + dir * (2.0/3.0 - 0.5)).xyz);\n vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (\n texture(tex, coord.xy + dir * (0.0/3.0 - 0.5)).xyz +\n texture(tex, coord.xy + dir * (3.0/3.0 - 0.5)).xyz);\n float lumaB = dot(rgbB, luma);\n\n vec4 color=texture(tex,coord).rgba;\n\n if((lumaB < lumaMin) || (lumaB > lumaMax)){\n color.xyz=rgbA;\n } else {\n color.xyz=rgbB;\n }\n return color;\n}\n\nvoid main()\n{\n vec4 col=vec4(1.0,0.0,0.0,1.0);\n outColor= getColorFXAA(texCoord);\n}",}; +// shader from: https://github.com/mattdesl/glsl-fxaa + +let render = op.inTrigger("render"); +let trigger = op.outTrigger("trigger"); +let fxaa_span = op.inValueSelect("span", [0, 2, 4, 8, 16, 32, 64]); +let fxaa_reduceMin = op.inValueFloat("reduceMin"); +let fxaa_reduceMul = op.inValueFloat("reduceMul"); +let useVPSize = op.inValueBool("use viewport size", true); +let texWidth = op.inValueInt("width"); +let texHeight = op.inValueInt("height"); + +let cgl = op.patch.cgl; +let shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.fxaa_frag); +let textureUniform = new CGL.Uniform(shader, "t", "tex", 0); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + cgl.pushShader(shader); + + if (cgl.getViewPort()[2] != texWidth.get() || cgl.getViewPort()[3] != texHeight.get()) + { + changeRes(); + } + + cgl.currentTextureEffect.bind(); + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + + cgl.currentTextureEffect.finish(); + + cgl.popShader(); + + trigger.trigger(); +}; + + +let uniformSpan = new CGL.Uniform(shader, "f", "FXAA_SPAN_MAX", 0); +let uniformMul = new CGL.Uniform(shader, "f", "FXAA_REDUCE_MUL", 0); +let uniformMin = new CGL.Uniform(shader, "f", "FXAA_REDUCE_MIN", 0); + +fxaa_span.onChange = function () +{ + uniformSpan.setValue(parseInt(fxaa_span.get(), 10)); +}; + +let uWidth = new CGL.Uniform(shader, "f", "width", 0); +let uHeight = new CGL.Uniform(shader, "f", "height", 0); + +function changeRes() +{ + if (useVPSize.get()) + { + let w = cgl.getViewPort()[2]; + let h = cgl.getViewPort()[3]; + uWidth.setValue(w); + uHeight.setValue(h); + // texWidth.set(w); + // texHeight.set(h); + } + else + { + uWidth.setValue(texWidth.get()); + uHeight.setValue(texHeight.get()); + } +} + +texWidth.onChange = changeRes; +texHeight.onChange = changeRes; +useVPSize.onChange = changeRes; +op.onResize = changeRes; + +fxaa_span.set(8); +// texWidth.set(1920); +// texHeight.set(1080); + +fxaa_reduceMul.onChange = function () +{ + uniformMul.setValue(1.0 / fxaa_reduceMul.get()); +}; + +fxaa_reduceMin.onChange = function () +{ + uniformMin.setValue(1.0 / fxaa_reduceMin.get()); +}; + +fxaa_reduceMul.set(8); +fxaa_reduceMin.set(128); + + +}; + +Ops.Gl.TextureEffects.FXAA.prototype = new CABLES.Op(); +CABLES.OPS["3e679c17-f050-4bc8-bfe5-5b9190e7ce40"]={f:Ops.Gl.TextureEffects.FXAA,objName:"Ops.Gl.TextureEffects.FXAA"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.FastBlur_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.FastBlur_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"blur_frag":"\nUNI sampler2D tex;\n#ifdef USE_MASK\n UNI sampler2D texMask;\n#endif\nUNI float amount;\nUNI float pass;\n\nIN vec2 texCoord;\n\nUNI float dirX;\nUNI float dirY;\nUNI float width;\nUNI float height;\n\nIN vec2 coord0;\nIN vec2 coord1;\nIN vec2 coord2;\nIN vec2 coord3;\nIN vec2 coord4;\nIN vec2 coord5;\nIN vec2 coord6;\n\n#ifdef HAS_MASK\n UNI sampler2D imageMask;\n#endif\n\nvoid main()\n{\n vec4 color = vec4(0.0);\n\n #ifdef USE_MASK\n #ifdef MASK_INVERT\n if(texture(texMask,texCoord).r<0.5)\n {\n outColor= texture(tex, texCoord);\n return;\n }\n #endif\n\n #ifndef MASK_INVERT\n if(texture(texMask,texCoord).r>0.5)\n {\n outColor= texture(tex, texCoord);\n return;\n }\n #endif\n #endif\n\n color += texture(tex, coord0) * 0.06927096443792478;\n color += texture(tex, coord1) * 0.1383328848652136;\n color += texture(tex, coord2) * 0.21920904690397863;\n color += texture(tex, coord3) * 0.14637421;\n color += texture(tex, coord4) * 0.21920904690397863;\n color += texture(tex, coord5) * 0.1383328848652136;\n color += texture(tex, coord6) * 0.06927096443795711;\n\n outColor= color;\n}","blur_vert":"\nIN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\nOUT vec2 texCoord;\nOUT vec3 norm;\nUNI mat4 projMatrix;\nUNI mat4 mvMatrix;\nUNI mat4 modelMatrix;\n\nUNI float pass;\nUNI float dirX;\nUNI float dirY;\nUNI float width;\nUNI float height;\n\nOUT vec2 coord0;\nOUT vec2 coord1;\nOUT vec2 coord2;\nOUT vec2 coord3;\nOUT vec2 coord4;\nOUT vec2 coord5;\nOUT vec2 coord6;\n\nvoid main()\n{\n texCoord=attrTexCoord;\n norm=attrVertNormal;\n vec4 pos=vec4(vPosition, 1.0);\n {{MODULE_VERTEX_POSITION}}\n\n vec2 dir=vec2(dirX,dirY);\n vec2 res=vec2( (1.) / width , (1.) / height )*dir;\n\n coord3= attrTexCoord;\n\n coord0= attrTexCoord + (-3.0368997744118595 * res);\n coord1= attrTexCoord + (-2.089778445362373 * res);\n coord2= attrTexCoord + (-1.2004366090034069 * res);\n coord4= attrTexCoord + (1.2004366090034069 * res);\n coord5= attrTexCoord + (2.089778445362373* res);\n coord6= attrTexCoord + (3.0368997744118595 * res);\n\n #ifdef CLAMP\n coord0=clamp(coord0,0.0,1.0);\n coord1=clamp(coord1,0.0,1.0);\n coord2=clamp(coord2,0.0,1.0);\n coord3=clamp(coord3,0.0,1.0);\n coord4=clamp(coord4,0.0,1.0);\n coord5=clamp(coord5,0.0,1.0);\n coord6=clamp(coord6,0.0,1.0);\n #endif\n\n gl_Position = projMatrix * mvMatrix * pos;\n}\n",}; +// http://dev.theomader.com/gaussian-kernel-calculator/ +// http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/ + +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + inPasses = op.inFloat("Passes", 3), + clamp = op.inBool("Clamp", false), + direction = op.inDropDown("direction", ["both", "vertical", "horizontal"], "both"), + mask = op.inTexture("Mask"), + maskInvert = op.inBool("Mask Invert", false); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "fastblur"); + +op.setPortGroup("Mask", [mask, maskInvert]); + +shader.setSource(attachments.blur_vert, attachments.blur_frag); +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uniDirX = new CGL.Uniform(shader, "f", "dirX", 0), + uniDirY = new CGL.Uniform(shader, "f", "dirY", 0), + uniWidth = new CGL.Uniform(shader, "f", "width", 0), + uniHeight = new CGL.Uniform(shader, "f", "height", 0), + uniPass = new CGL.Uniform(shader, "f", "pass", 0), + uniAmount = new CGL.Uniform(shader, "f", "amount", inPasses.get()), + textureAlpha = new CGL.Uniform(shader, "t", "texMask", 1); + +inPasses.onChange = () => { uniAmount.setValue(inPasses.get()); }; + +let dir = 0; +direction.onChange = () => +{ + if (direction.get() == "both") dir = 0; + if (direction.get() == "horizontal") dir = 1; + if (direction.get() == "vertical") dir = 2; +}; + +clamp.onChange = () => { shader.toggleDefine("CLAMP", clamp.get()); }; + +maskInvert.onChange = + mask.onChange = updateDefines; +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("USE_MASK", mask.isLinked()); + shader.toggleDefine("MASK_INVERT", maskInvert.get()); + + maskInvert.setUiAttribs({ "greyout": !mask.isLinked() }); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + uniWidth.setValue(cgl.currentTextureEffect.getCurrentSourceTexture().width); + uniHeight.setValue(cgl.currentTextureEffect.getCurrentSourceTexture().height); + const numPasses = inPasses.get(); + + if (mask.get())cgl.setTexture(1, mask.get().tex); + + for (let i = 0; i < numPasses; i++) + { + cgl.pushShader(shader); + + uniPass.setValue(i / numPasses); + + // first pass + if (dir === 0 || dir == 2) + { + cgl.currentTextureEffect.bind(); + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + uniDirX.setValue(0.0); + uniDirY.setValue(1.0 + (i * i)); + + cgl.currentTextureEffect.finish(); + } + + // second pass + if (dir === 0 || dir == 1) + { + cgl.currentTextureEffect.bind(); + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + uniDirX.setValue(1.0 + (i * i)); + uniDirY.setValue(0.0); + + cgl.currentTextureEffect.finish(); + } + + cgl.popShader(); + } + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.FastBlur_v2.prototype = new CABLES.Op(); +CABLES.OPS["61ed277f-d096-43b2-9de8-dc87fb3a9169"]={f:Ops.Gl.TextureEffects.FastBlur_v2,objName:"Ops.Gl.TextureEffects.FastBlur_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Flip +// +// ************************************************************** + +Ops.Gl.TextureEffects.Flip = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"flip_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float x;\nUNI float y;\n\nvoid main()\n{\n vec4 col=vec4(1.0,0.0,0.0,1.0);\n col=texture(tex,vec2(abs(x-texCoord.x),abs(y-texCoord.y)));\n outColor= col;\n}",}; +const render = op.inTrigger("render"); +const x = op.inValueBool("X"); +const y = op.inValueBool("Y"); +const trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.flip_frag); + +const uniTexture = new CGL.Uniform(shader, "t", "tex", 0); +const uniX = new CGL.Uniform(shader, "f", "x", x); +const uniY = new CGL.Uniform(shader, "f", "y", y); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Flip.prototype = new CABLES.Op(); +CABLES.OPS["ce36ad01-411a-412f-affa-1959aa23f93b"]={f:Ops.Gl.TextureEffects.Flip,objName:"Ops.Gl.TextureEffects.Flip"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Float32ToRgbeTexture +// +// ************************************************************** + +Ops.Gl.TextureEffects.Float32ToRgbeTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"rgbe2fp_frag":"UNI sampler2D tex;\nIN vec2 texCoord;\n\n\n// highp vec3 decodeRGBE8(highp vec4 rgbe)\n// {\n// highp vec3 vDecoded = rgbe.rgb * pow(2.0, rgbe.a * 255.0-128.0);\n// return vDecoded;\n// }\nvec4 encodeRGBE8( vec3 rgb )\n{\n vec4 vEncoded;\n float maxComponent = max(max(rgb.r, rgb.g), rgb.b );\n float fExp = ceil( log2(maxComponent) );\n vEncoded.rgb = rgb / exp2(fExp);\n vEncoded.a = (fExp + 128.0) / 255.0;\n return vEncoded;\n}\n\n\nvoid main()\n{\n vec4 col=vec4( encodeRGBE8(texture(tex,texCoord).rgb));\n\n outColor= col;\n}",}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.rgbe2fp_frag); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Float32ToRgbeTexture.prototype = new CABLES.Op(); +CABLES.OPS["ae3585c4-b49a-4dd5-b7be-1f53a90bb060"]={f:Ops.Gl.TextureEffects.Float32ToRgbeTexture,objName:"Ops.Gl.TextureEffects.Float32ToRgbeTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Fog_v4 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Fog_v4 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"fog_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D texDepth;\n\n#ifdef HAS_GRADIENT_TEX\n UNI sampler2D texGradient;\n#endif\n\n#ifdef HAS_BG_TEX\n UNI sampler2D texBg;\n#endif\n\nUNI float nearPlane;\nUNI float farPlane;\nUNI float inAmount;\nUNI vec4 inFogColor;\nUNI float inFogDensity;\nUNI float inFogStart;\nUNI float inFogEnd;\n\n{{CGL.BLENDMODES3}}\n\nfloat map(float value, float min1, float max1, float min2, float max2) {\n return min2 + (value - min1) * (max2 - min2) / (max1 - min1);\n}\n\nfloat CalcFogDensity(float depth) {\n float newDepth = map(depth, nearPlane, farPlane, 0., 1.);\n float fogAmount = 1.0 - clamp((inFogEnd - depth) / (inFogEnd - inFogStart), 0.0, 1.0);\n\n // EXPONENTIAL: fogAmount = 1. - exp(MAGIC_NUMBER * -inFogDensity * newDepth); // smoothstep(fogStart, fogEnd, newDepth));\n // EXP2: fogAmount = 1. - exp(-pow(MAGIC_NUMBER * inFogDensity * smoothstep(fogStart, fogEnd, newDepth), 2.0));\n\n fogAmount *= inFogDensity;\n\n return fogAmount;\n}\n\nvoid main()\n{\n vec4 color = texture(tex, texCoord);\n\n float depthFromTexture = texture(texDepth,texCoord).r;\n\n float distanceToCamera_viewSpace = (nearPlane * farPlane) / (farPlane - depthFromTexture * (farPlane - nearPlane));\n\n float fogAmount = CalcFogDensity(distanceToCamera_viewSpace);\n\n vec4 fogColor = inFogColor;\n\n #ifdef HAS_GRADIENT_TEX\n vec4 fogColTex = texture(texGradient, vec2(clamp(distanceToCamera_viewSpace / (farPlane - nearPlane), 0.0, 0.9999),0.5));\n fogColor *= fogColTex;\n #endif\n\n #ifdef HAS_BG_TEX\n vec4 fogColTexBg = texture(texBg, texCoord);\n fogColor *= fogColTexBg;\n\n #endif\n\n fogColor = color * (1.0 - fogAmount) + fogColor * fogAmount;\n // fogColor = mix(color, fogColor, fogAmount);\n\n\n outColor = cgl_blendPixel(color, fogColor, inAmount);\n\n}\n","fog_vert":"IN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\n\nOUT vec2 texCoord;\nOUT vec3 norm;\n\nUNI mat4 projMatrix;\nUNI mat4 mvMatrix;\nUNI mat4 modelMatrix;\n\nvoid main()\n{\n texCoord = attrTexCoord;\n norm = attrVertNormal;\n vec4 pos = vec4(vPosition, 1.0);\n\n {{MODULE_VERTEX_POSITION}}\n\n gl_Position = projMatrix * mvMatrix * pos;\n\n}\n",}; +const cgl = op.patch.cgl; + +const render = op.inTrigger("render"); +const blendMode = CGL.TextureEffect.AddBlendSelect(op, "blendMode"); +const inAmount = op.inFloatSlider("Amount", 1); +const image = op.inTexture("Depth Texture"); +const inGradientTexture = op.inTexture("Gradient Texture"); +const inBgTex = op.inTexture("Background Texture"); +const inFogStart = op.inFloat("Fog Start", 1); +const inFogEnd = op.inFloat("Fog End", 8); +const inFogDensity = op.inFloatSlider("Fog Density", 1); +const nearPlane = op.inFloat("nearplane", 0.1); +const farPlane = op.inFloat("farplane", 20); +const inFogR = op.inFloatSlider("Fog R", 0.6); +const inFogG = op.inFloatSlider("Fog G", 0.6); +const inFogB = op.inFloatSlider("Fog B", 0.6); +const inFogA = op.inFloatSlider("Fog A", 1); +inFogR.setUiAttribs({ "colorPick": true }); + +const trigger = op.outTrigger("trigger"); + +op.setPortGroup("Textures", [image, inGradientTexture, inBgTex]); +op.setPortGroup("Frustum", [farPlane, nearPlane]); +op.setPortGroup("Fog Options", [inFogStart, inFogEnd, inFogDensity]); +op.setPortGroup("Fog Color", [inFogR, inFogG, inFogB, inFogA]); + +const shader = new CGL.Shader(cgl, "Fog"); +const srcFrag = attachments.fog_frag; +const srcVert = attachments.fog_vert; +shader.setSource(srcVert, srcFrag); + +const uniAmount = new CGL.Uniform(shader, "f", "inAmount", inAmount); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const depthTextureUniform = new CGL.Uniform(shader, "t", "texDepth", 1); +const uniGradientTexture = new CGL.Uniform(shader, "t", "texGradient", 2); +const uniBgTexture = new CGL.Uniform(shader, "t", "texBg", 3); + +const uniFarplane = new CGL.Uniform(shader, "f", "farPlane", farPlane); +const uniNearplane = new CGL.Uniform(shader, "f", "nearPlane", nearPlane); + +const uniAspect = new CGL.Uniform(shader, "f", "aspectRatio", 0); +const uniFogColor = new CGL.Uniform(shader, "4f", "inFogColor", inFogR, inFogG, inFogB, inFogA); +const uniFogDensity = new CGL.Uniform(shader, "f", "inFogDensity", inFogDensity); +const uniFogStart = new CGL.Uniform(shader, "f", "inFogStart", inFogStart); +const uniFogEnd = new CGL.Uniform(shader, "f", "inFogEnd", inFogEnd); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, inAmount); + +let texturesChanged = false; +inGradientTexture.onChange = +inBgTex.onChange = () => +{ + texturesChanged = true; +}; + +function updateDefines() +{ + shader.toggleDefine("HAS_BG_TEX", inBgTex.get() && inBgTex.get().tex); + + if (inGradientTexture.get() && inGradientTexture.get().tex) shader.define("HAS_GRADIENT_TEX"); + else shader.removeDefine("HAS_GRADIENT_TEX"); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op,3)) return; + if (!image.get()) + { + op.setUiError("noDepthTex", "This op needs a depth texture to work properly!", 0); + } + else + { + op.setUiError("noDepthTex", null); + } + + if (texturesChanged)updateDefines(); + + if (image.get() && image.get().tex) + { + const a = + cgl.currentTextureEffect.getCurrentSourceTexture().height + / cgl.currentTextureEffect.getCurrentSourceTexture().width; + + uniAspect.set(a); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + if (image.get()) cgl.setTexture(1, image.get().tex); + if (inGradientTexture.get()) cgl.setTexture(2, inGradientTexture.get().tex); + if (inBgTex.get()) cgl.setTexture(3, inBgTex.get().tex); + cgl.currentTextureEffect.finish(); + cgl.popShader(); + } + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Fog_v4.prototype = new CABLES.Op(); +CABLES.OPS["9d52bb1d-cf80-4f75-a80b-bdca16421d65"]={f:Ops.Gl.TextureEffects.Fog_v4,objName:"Ops.Gl.TextureEffects.Fog_v4"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.GammaCorrection_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.GammaCorrection_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"gamma_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float multiplyAmount;\nUNI float gammaAmount;\n\n{{CGL.BLENDMODES}}\n\nvoid main()\n{\n vec4 base4=texture(tex,texCoord);\n vec3 color = base4.rgb * multiplyAmount;\n\n outColor= vec4(\n mix(\n color,\n vec3(pow(color,vec3(1.0 / gammaAmount))\n ),amount),\n base4.a);\n}",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + inMultiply = op.inValue("Multiply texture", 1.0), + inGamma = op.inValue("Gamma correction", 2.2), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.gamma_frag); + +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); +const multiplyUniform = new CGL.Uniform(shader, "f", "multiplyAmount", inMultiply); +const gammaUniform = new CGL.Uniform(shader, "f", "gammaAmount", inGamma); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op,3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.GammaCorrection_v2.prototype = new CABLES.Op(); +CABLES.OPS["18da81c9-bcae-4446-ac58-d3ba31808013"]={f:Ops.Gl.TextureEffects.GammaCorrection_v2,objName:"Ops.Gl.TextureEffects.GammaCorrection_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Gradient_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Gradient_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"gradient_frag":"IN vec2 texCoord;\nUNI float amount;\nUNI float pos;\nUNI float width;\n\nUNI vec3 colA;\nUNI vec3 colB;\nUNI vec3 colC;\nUNI sampler2D tex;\n\n{{CGL.BLENDMODES3}}\n\n\n\n\nvec3 lin2srgb( vec3 cl )\n{\n\tcl = clamp( cl, 0.0, 1.0 );\n\tvec3 c_lo = 12.92 * cl;\n\tvec3 c_hi = 1.055 * pow(cl,vec3(0.41666,0.41666,0.41666)) - 0.055;\n\treturn vec3( (cl.r<0.0031308) ? c_lo.r : c_hi.r,\n (cl.g<0.0031308) ? c_lo.g : c_hi.g,\n (cl.b<0.0031308) ? c_lo.b : c_hi.b );\n}\n\nvec3 oklab_mix( vec3 colA, vec3 colB, float h )\n{\n // https://www.shadertoy.com/view/ttcyRS\n // https://bottosson.github.io/posts/oklab\n const mat3 kCONEtoLMS = mat3(\n 0.4121656120, 0.2118591070, 0.0883097947,\n 0.5362752080, 0.6807189584, 0.2818474174,\n 0.0514575653, 0.1074065790, 0.6302613616);\n const mat3 kLMStoCONE = mat3(\n 4.0767245293, -1.2681437731, -0.0041119885,\n -3.3072168827, 2.6093323231, -0.7034763098,\n 0.2307590544, -0.3411344290, 1.7068625689);\n\n // rgb to cone (arg of pow can't be negative)\n vec3 lmsA = pow( kCONEtoLMS*colA, vec3(1.0/3.0) );\n vec3 lmsB = pow( kCONEtoLMS*colB, vec3(1.0/3.0) );\n // lerp\n vec3 lms = mix( lmsA, lmsB, h );\n // gain in the middle (no oaklab anymore, but looks better?)\n #ifdef OKLABGAIN\n lms *= 1.0+0.2*h*(1.0-h);\n #endif\n // cone to rgb\n return kLMStoCONE*(lms*lms*lms);\n}\n\n\nvoid main()\n{\n vec4 base=texture(tex,texCoord);\n vec4 col;\n float ax=texCoord.x;\n\n #ifdef GRAD_Y\n ax=texCoord.y;\n #endif\n #ifdef GRAD_XY\n ax=(texCoord.x+texCoord.y)/2.0;\n #endif\n #ifdef GRAD_RADIAL\n ax=distance(texCoord,vec2(0.5,0.5))*2.0;\n #endif\n\n ax=((ax-0.5)*width)+0.5;\nax=clamp(ax,0.0,1.0);\n\n #ifndef GRAD_SMOOTHSTEP\n if(ax<=pos) col = vec4(MIXER(colA, colB, ax*1.0/pos),1.0);\n else col = vec4(MIXER(colB, colC, min(1.0,(ax-pos)*1.0/(1.0-pos))),1.0);\n #endif\n\n #ifdef GRAD_SMOOTHSTEP\n if(ax<=pos) col = vec4(MIXER(colA, colB, smoothstep(0.0,1.0,ax*1.0/pos)),1.0);\n else col = vec4(MIXER(colB, colC, smoothstep(0.0,1.0,min(1.0,(ax-pos)*1.0/(1.0-pos)))),1.0);\n #endif\n\n #ifdef SRGB\n col.rgb=lin2srgb(col.rgb);\n #endif\n\n outColor=cgl_blendPixel(base,col,amount);\n}",}; +const + render = op.inTrigger("Render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + amount = op.inValueSlider("Amount", 1), + width = op.inValue("Width", 1), + gType = op.inSwitch("Type", ["X", "Y", "XY", "Radial"], "X"), + pos1 = op.inValueSlider("Pos", 0.5), + smoothStep = op.inValueBool("Smoothstep", true), + inSrgb = op.inValueBool("sRGB", false), + inColSpace = op.inSwitch("color space", ["RGB", "Oklab", "OklabG"], "RGB"), + + r = op.inValueSlider("r", Math.random()), + g = op.inValueSlider("g", Math.random()), + b = op.inValueSlider("b", Math.random()), + + r2 = op.inValueSlider("r2", Math.random()), + g2 = op.inValueSlider("g2", Math.random()), + b2 = op.inValueSlider("b2", Math.random()), + + r3 = op.inValueSlider("r3", Math.random()), + g3 = op.inValueSlider("g3", Math.random()), + b3 = op.inValueSlider("b3", Math.random()), + + randomize = op.inTriggerButton("Randomize"), + next = op.outTrigger("Next"); + +r.setUiAttribs({ "colorPick": true }); +r2.setUiAttribs({ "colorPick": true }); +r3.setUiAttribs({ "colorPick": true }); + +op.setPortGroup("Blending", [blendMode, amount]); +op.setPortGroup("Color A", [r, g, b]); +op.setPortGroup("Color B", [r2, g2, b2]); +op.setPortGroup("Color C", [r3, g3, b3]); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "gradient"); + +shader.setSource(shader.getDefaultVertexShader(), attachments.gradient_frag); +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); +const uniPos = new CGL.Uniform(shader, "f", "pos", pos1); +const uniWidth = new CGL.Uniform(shader, "f", "width", width); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +let r3uniform, r2uniform, runiform; + +r2.onChange = g2.onChange = b2.onChange = updateCol2; +r3.onChange = g3.onChange = b3.onChange = updateCol3; +r.onChange = g.onChange = b.onChange = updateCol; + +r2.onLinkChanged = g2.onLinkChanged = b2.onLinkChanged = +r3.onLinkChanged = g3.onLinkChanged = b3.onLinkChanged = +r.onLinkChanged = g.onLinkChanged = b.onLinkChanged = updateUi; + +updateCol(); +updateCol2(); +updateCol3(); +updateDefines(); + +inSrgb.onChange = +inColSpace.onChange = +smoothStep.onChange = + gType.onChange = updateDefines; + +function updateUi() +{ + randomize.setUiAttribs({ "greyout": r2.isLinked() || g2.isLinked() || b2.isLinked() || r3.isLinked() || g3.isLinked() || b3.isLinked() || r.isLinked() || g.isLinked() || b.isLinked() }); +} + +function updateDefines() +{ + // shader.toggleDefine("OKLABGAIN", inoklabGain.get()); + shader.toggleDefine("SRGB", inSrgb.get()); + + shader.define("MIXER", (inColSpace.get() + "").indexOf("Oklab") > -1 ? "oklab_mix" : "mix"); + shader.toggleDefine("OKLABGAIN", (inColSpace.get() + "").indexOf("OklabG") > -1); + + shader.toggleDefine("GRAD_SMOOTHSTEP", smoothStep.get()); + shader.toggleDefine("GRAD_X", gType.get() == "X"); + shader.toggleDefine("GRAD_XY", gType.get() == "XY"); + shader.toggleDefine("GRAD_Y", gType.get() == "Y"); + shader.toggleDefine("GRAD_RADIAL", gType.get() == "Radial"); +} + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +randomize.onTriggered = function () +{ + r.set(Math.random()); + g.set(Math.random()); + b.set(Math.random()); + + r2.set(Math.random()); + g2.set(Math.random()); + b2.set(Math.random()); + + r3.set(Math.random()); + g3.set(Math.random()); + b3.set(Math.random()); + + op.refreshParams(); +}; + +function updateCol() +{ + const colA = [r.get(), g.get(), b.get()]; + if (!runiform) runiform = new CGL.Uniform(shader, "3f", "colA", colA); + else runiform.setValue(colA); +} + +function updateCol2() +{ + const colB = [r2.get(), g2.get(), b2.get()]; + if (!r2uniform) r2uniform = new CGL.Uniform(shader, "3f", "colB", colB); + else r2uniform.setValue(colB); +} + +function updateCol3() +{ + const colC = [r3.get(), g3.get(), b3.get()]; + if (!r3uniform) r3uniform = new CGL.Uniform(shader, "3f", "colC", colC); + else r3uniform.setValue(colC); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + next.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Gradient_v2.prototype = new CABLES.Op(); +CABLES.OPS["c8a9408a-75e5-481f-99a7-6aa7ca88bebc"]={f:Ops.Gl.TextureEffects.Gradient_v2,objName:"Ops.Gl.TextureEffects.Gradient_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.GridTexture_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.GridTexture_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"grid_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI bool invertColor;\nUNI float lineThicknessX;\nUNI float lineThicknessY;\nUNI float cellsX;\nUNI float cellsY;\nUNI float offsetX;\nUNI float offsetY;\nUNI float rotate;\n\nUNI float lineR;\nUNI float lineG;\nUNI float lineB;\n\n{{CGL.BLENDMODES3}}\n\n#define PI 3.14159265\n#define TAU (2.0*PI)\n\nvoid pR(inout vec2 p, float a)\n{\n\tp = cos(a)*p + sin(a)*vec2(p.y, -p.x);\n}\n\nfloat vmax(vec2 v)\n{\n\treturn max(v.x, v.y);\n}\nfloat fBox2(vec2 p, vec2 b)\n{\n\tvec2 d = abs(p) - b;\n\treturn length(max(d, vec2(0.0))) + vmax(min(d, vec2(0.0)));\n}\n\nvec2 pMod2(inout vec2 p, vec2 size)\n{\n\tvec2 c = floor((p + size*0.5)/size);\n\tp = mod(p + size*0.5,size) - size*0.5;\n\treturn c;\n}\nvoid main()\n{\n vec2 uv = texCoord;\n uv -= 0.5;\n pR(uv.xy,rotate * (TAU));\n uv += 0.5;\n uv *= vec2(cellsX,cellsY);\n uv -= 0.5;\n uv -= vec2(offsetX,offsetY);\n pMod2(uv,vec2(1.));\n\n float box = 0.0;\n\n if(invertColor) box = 1.0 - sign(fBox2(uv,vec2(lineThicknessX,lineThicknessY)));\n else box = sign(fBox2(uv,vec2(lineThicknessX,lineThicknessY)));\n vec4 color = vec4(vec3(box) * vec3(lineR,lineG,lineB),1.0);\n\n vec4 col=vec4(color);\n vec4 base=texture(tex,texCoord);\n\n outColor=cgl_blendPixel(base,col,amount);\n}",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + + amount = op.inValueSlider("Amount", 1), + + lineThicknessX = op.inValueSlider("Line thickness X", 0.4), + lineThicknessY = op.inValueSlider("Line thickness Y", 0.4), + cellsX = op.inValueFloat("Cells X", 10), + cellsY = op.inValueFloat("Cells Y", 10), + inRotate = op.inValueSlider("Rotate", 0.0), + offsetX = op.inValue("Offset X", 0.0), + offsetY = op.inValue("Offset Y", 0.0), + + invertColor = op.inValueBool("Invert color", false), + r = op.inValueSlider("Line red", Math.random()), + g = op.inValueSlider("Line green", Math.random()), + b = op.inValueSlider("Line Blue", Math.random()); + +r.setUiAttribs({ "colorPick": true }); + +op.setPortGroup("LineThickness", [lineThicknessX, lineThicknessY]); +op.setPortGroup("Cells", [cellsX, cellsY]); +op.setPortGroup("Position", [inRotate, offsetX, offsetY]); + +const trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.grid_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + uniInvertColor = new CGL.Uniform(shader, "b", "invertColor", invertColor), + unilineThicknessX = new CGL.Uniform(shader, "f", "lineThicknessX", lineThicknessX), + unilineThicknessY = new CGL.Uniform(shader, "f", "lineThicknessY", lineThicknessY), + unicellsX = new CGL.Uniform(shader, "f", "cellsX", cellsX), + unicellsY = new CGL.Uniform(shader, "f", "cellsY", cellsY), + rotateUniform = new CGL.Uniform(shader, "f", "rotate", inRotate), + offsetXUniform = new CGL.Uniform(shader, "f", "offsetX", offsetX), + offsetYUniform = new CGL.Uniform(shader, "f", "offsetY", offsetY), + uniformLineR = new CGL.Uniform(shader, "f", "lineR", r), + uniformLineG = new CGL.Uniform(shader, "f", "lineG", g), + uniformLineB = new CGL.Uniform(shader, "f", "lineB", b); + + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount,maskAlpha); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.GridTexture_v2.prototype = new CABLES.Op(); +CABLES.OPS["4e3c7990-9434-4f41-ad79-dfed8395c460"]={f:Ops.Gl.TextureEffects.GridTexture_v2,objName:"Ops.Gl.TextureEffects.GridTexture_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.GrowPixels_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.GrowPixels_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"outline_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float strength;\nUNI float texWidth,texHeight;\nUNI float r,g,b;\nconst vec4 lumcoeff = vec4(0.299,0.587,0.114, 0.);\n\n{{CGL.BLENDMODES3}}\n\nvec3 desaturate(vec3 color)\n{\n return vec3(dot(vec3(0.2126,0.7152,0.0722), color));\n}\n\nvoid main()\n{\n float pixelX=1.0/texWidth*0.5;\n float pixelY=1.0/texHeight*0.5;\n\n vec4 co = texture(tex, vec2(texCoord.x, texCoord.y - pixelY ));\n float n=co.r*co.a;\n co = texture(tex, vec2(texCoord.x, texCoord.y + pixelY ));\n float s=co.r*co.a;\n\n co = texture(tex, vec2(texCoord.x+pixelX, texCoord.y ));\n float e=co.r*co.a;\n co = texture(tex, vec2(texCoord.x-pixelX, texCoord.y ));\n float w=co.r*co.a;\n\n float c=0.0;\n if(n+s+e+w/4.0>((1.0-strength)*0.4)) c=1.0;\n\n vec4 base=texture(tex,texCoord);\n vec4 col=vec4(r*c,g*c,b*c,base.a+c);\n\n outColor=cgl_blendPixel(base,col,amount);\n}\n\n",}; +const + render = op.inTrigger("Render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + strength = op.inValueSlider("strength", 1), + iter = op.inInt("iterations", 1), + r = op.inValueSlider("r", 1), + g = op.inValueSlider("g", 1), + b = op.inValueSlider("b", 1), + trigger = op.outTrigger("Trigger"); + +op.setPortGroup("Look", strength); +r.setUiAttribs({ "colorPick": true }); +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.outline_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + strengthUniform = new CGL.Uniform(shader, "f", "strength", strength), + uniWidth = new CGL.Uniform(shader, "f", "texWidth", 128), + uniHeight = new CGL.Uniform(shader, "f", "texHeight", 128), + unir = new CGL.Uniform(shader, "f", "r", r), + unig = new CGL.Uniform(shader, "f", "g", g), + unib = new CGL.Uniform(shader, "f", "b", b); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op,3)) return; + + + for (let i = 0; i < Math.floor(iter.get()); i++) + if (strength.get() > 0.0) + { + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + uniWidth.setValue(cgl.currentTextureEffect.getCurrentSourceTexture().width); + uniHeight.setValue(cgl.currentTextureEffect.getCurrentSourceTexture().height); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + } + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.GrowPixels_v2.prototype = new CABLES.Op(); +CABLES.OPS["f81a7074-7a97-4d1e-bcb8-98f5874a64fc"]={f:Ops.Gl.TextureEffects.GrowPixels_v2,objName:"Ops.Gl.TextureEffects.GrowPixels_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Hue +// +// ************************************************************** + +Ops.Gl.TextureEffects.Hue = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"hue_frag":"UNI float hue;\n\n#ifdef HAS_TEXTURES\n IN vec2 texCoord;\n UNI sampler2D tex;\n#endif\n\n#ifdef TEX_MASK\n UNI sampler2D texMask;\n#endif\n#ifdef TEX_OFFSET\n UNI sampler2D texOffset;\n#endif\n\nvec3 rgb2hsv(vec3 c)\n{\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n\n float d = q.x - min(q.w, q.y);\n float e = 1.0e-10;\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n}\n\nvec3 hsv2rgb(vec3 c)\n{\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\nvoid main()\n{\n vec4 col=vec4(1.0,0.0,0.0,1.0);\n #ifdef HAS_TEXTURES\n col=texture(tex,texCoord);\n float h=hue;\n\n #ifdef TEX_OFFSET\n h += texture(texOffset,texCoord).r;\n #endif\n\n\n vec3 hsv = rgb2hsv(col.rgb);\n hsv.x=hsv.x+h;\n\n #ifndef TEX_MASK\n col.rgb = hsv2rgb(hsv);\n #endif\n\n #ifdef TEX_MASK\n col.rgb = mix(col.rgb,hsv2rgb(hsv),texture(texMask,texCoord).r);\n #endif\n\n #endif\n outColor= col;\n}",}; +const + render = op.inTrigger("render"), + hue = op.inValueSlider("hue", 1), + texMask = op.inTexture("Mask"), + texOffset = op.inTexture("Offset"), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.hue_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); + +const textureMaskUniform = new CGL.Uniform(shader, "t", "texMask", 1); +const textureOffsetUniform = new CGL.Uniform(shader, "t", "texOffset", 2); + +const uniformHue = new CGL.Uniform(shader, "f", "hue", 1.0); + +hue.onChange = function () { uniformHue.setValue(hue.get()); }; + +texMask.onChange = +texOffset.onChange = () => +{ + shader.toggleDefine("TEX_MASK", texMask.get()); + shader.toggleDefine("TEX_OFFSET", texOffset.get()); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + if (texMask.get()) cgl.setTexture(1, texMask.get().tex); + if (texOffset.get()) cgl.setTexture(2, texOffset.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Hue.prototype = new CABLES.Op(); +CABLES.OPS["94ef0da0-c920-415c-81b0-fecbd437991d"]={f:Ops.Gl.TextureEffects.Hue,objName:"Ops.Gl.TextureEffects.Hue"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ImageComposeAspectRatio +// +// ************************************************************** + +Ops.Gl.TextureEffects.ImageComposeAspectRatio = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inUpdate=op.inTrigger("Update"), + inAspect=op.inFloat("Aspect",1), + next=op.outTrigger("Next"); + +const cgl=op.patch.cgl; +let prev=1; + +inUpdate.onTriggered=()=> +{ + if (!CGL.TextureEffect.checkOpInEffect(op,3)) return; + + if(cgl.currentTextureEffect) + { + prev=cgl.currentTextureEffect.aspectRatio; + cgl.currentTextureEffect.aspectRatio=inAspect.get(); + + next.trigger(); + + cgl.currentTextureEffect.aspectRatio=prev; + } + +}; + + +}; + +Ops.Gl.TextureEffects.ImageComposeAspectRatio.prototype = new CABLES.Op(); +CABLES.OPS["b346b8cf-b63d-4e1d-b95f-19edf04ae07d"]={f:Ops.Gl.TextureEffects.ImageComposeAspectRatio,objName:"Ops.Gl.TextureEffects.ImageComposeAspectRatio"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ImageComposeSnapshot +// +// ************************************************************** + +Ops.Gl.TextureEffects.ImageComposeSnapshot = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("Update"), + trigger = op.outTrigger("trigger"), + outTex = op.outTexture("Texture"); + +const cgl = op.patch.cgl; +let tc = new CGL.CopyTexture(cgl, "textureThief", {}); +let fp = false; + +render.onTriggered = () => +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + const effect = cgl.currentTextureEffect; + effect.endEffect(); + + const shouldFp = cgl.currentTextureEffect.getCurrentSourceTexture().isFloatingPoint(); + + if (fp != shouldFp) + { + tc = new CGL.CopyTexture(cgl, "textureThief", + { + "isFloatingPointTexture": shouldFp, + }); + fp = shouldFp; + } + + const vp = cgl.getViewPort(); + outTex.set(CGL.Texture.getEmptyTexture(cgl)); + + const tx = cgl.currentTextureEffect.getCurrentSourceTexture(); + outTex.set(tc.copy(tx)); + + effect.continueEffect(tx); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.ImageComposeSnapshot.prototype = new CABLES.Op(); +CABLES.OPS["e15c0803-02bb-4783-9d75-e75abd70d910"]={f:Ops.Gl.TextureEffects.ImageComposeSnapshot,objName:"Ops.Gl.TextureEffects.ImageComposeSnapshot"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ImageCompose_v3 +// +// ************************************************************** + +Ops.Gl.TextureEffects.ImageCompose_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"imgcomp_frag":"IN vec2 texCoord;\nUNI vec4 bgColor;\nUNI sampler2D tex;\n\nvoid main()\n{\n\n #ifndef USE_TEX\n outColor=bgColor;\n #endif\n #ifdef USE_TEX\n outColor=texture(tex,texCoord);\n #endif\n\n\n\n}\n",}; +const + cgl = op.patch.cgl, + render = op.inTrigger("Render"), + inTex = op.inTexture("Base Texture"), + inSize = op.inSwitch("Size", ["Auto", "Manual"], "Auto"), + width = op.inValueInt("Width", 640), + height = op.inValueInt("Height", 480), + inFilter = op.inSwitch("Filter", ["nearest", "linear", "mipmap"], "linear"), + inWrap = op.inValueSelect("Wrap", ["clamp to edge", "repeat", "mirrored repeat"], "repeat"), + inPixel = op.inDropDown("Pixel Format", CGL.Texture.PIXELFORMATS, CGL.Texture.PFORMATSTR_RGBA8UB), + + r = op.inValueSlider("R", 0), + g = op.inValueSlider("G", 0), + b = op.inValueSlider("B", 0), + a = op.inValueSlider("A", 0), + + trigger = op.outTrigger("Next"), + texOut = op.outTexture("texture_out", CGL.Texture.getEmptyTexture(cgl)), + outRatio = op.outNumber("Aspect Ratio"), + outWidth = op.outNumber("Texture Width"), + outHeight = op.outNumber("Texture Height"); + +op.setPortGroup("Texture Size", [inSize, width, height]); +op.setPortGroup("Texture Parameters", [inWrap, inFilter, inPixel]); + +r.setUiAttribs({ "colorPick": true }); +op.setPortGroup("Color", [r, g, b, a]); + +const prevViewPort = [0, 0, 0, 0]; +let effect = null; +let tex = null; +let reInitEffect = true; +let isFloatTex = false; +let copyShader = null; +let copyShaderTexUni = null; +let copyShaderRGBAUni = null; + +inWrap.onChange = + inFilter.onChange = + inPixel.onChange = reInitLater; + +inTex.onLinkChanged = +inSize.onChange = updateUi; + +render.onTriggered = + op.preRender = doRender; + +updateUi(); + +function initEffect() +{ + if (effect)effect.delete(); + if (tex)tex.delete(); + + effect = new CGL.TextureEffect(cgl, { "isFloatingPointTexture": getFloatingPoint() }); + + tex = new CGL.Texture(cgl, + { + "name": "image_compose_v2_" + op.id, + "isFloatingPointTexture": getFloatingPoint(), + "filter": getFilter(), + "wrap": getWrap(), + "width": getWidth(), + "height": getHeight() + }); + + effect.setSourceTexture(tex); + + outWidth.set(getWidth()); + outHeight.set(getHeight()); + outRatio.set(getWidth() / getHeight()); + + texOut.set(CGL.Texture.getEmptyTexture(cgl)); + + reInitEffect = false; + updateUi(); +} + +function getFilter() +{ + if (inFilter.get() == "nearest") return CGL.Texture.FILTER_NEAREST; + else if (inFilter.get() == "linear") return CGL.Texture.FILTER_LINEAR; + else if (inFilter.get() == "mipmap") return CGL.Texture.FILTER_MIPMAP; +} + +function getWrap() +{ + if (inWrap.get() == "repeat") return CGL.Texture.WRAP_REPEAT; + else if (inWrap.get() == "mirrored repeat") return CGL.Texture.WRAP_MIRRORED_REPEAT; + else if (inWrap.get() == "clamp to edge") return CGL.Texture.WRAP_CLAMP_TO_EDGE; +} + +function getFloatingPoint() +{ + isFloatTex = inPixel.get() == CGL.Texture.PFORMATSTR_RGBA32F; + return isFloatTex; +} + +function getWidth() +{ + if (inTex.get() && inSize.get() == "Auto") return inTex.get().width; + if (inSize.get() == "Auto") return cgl.getViewPort()[2]; + return Math.ceil(width.get()); +} + +function getHeight() +{ + if (inTex.get() && inSize.get() == "Auto") return inTex.get().height; + else if (inSize.get() == "Auto") return cgl.getViewPort()[3]; + else return Math.ceil(height.get()); +} + +function reInitLater() +{ + reInitEffect = true; +} + +function updateResolution() +{ + if (( + getWidth() != tex.width || + getHeight() != tex.height || + tex.isFloatingPoint() != getFloatingPoint() || + tex.filter != getFilter() || + tex.wrap != getWrap() + ) && (getWidth() !== 0 && getHeight() !== 0)) + { + initEffect(); + effect.setSourceTexture(tex); + texOut.set(CGL.Texture.getEmptyTexture(cgl)); + texOut.set(tex); + updateResolutionInfo(); + } +} + +function updateResolutionInfo() +{ + let info = null; + + if (inSize.get() == "Manual") + { + info = null; + } + else if (inSize.get() == "Auto") + { + if (inTex.get()) info = "Input Texture"; + else info = "Canvas Size"; + + info += ": " + getWidth() + " x " + getHeight(); + } + + let changed = false; + changed = inSize.uiAttribs.info != info; + inSize.setUiAttribs({ "info": info }); + if (changed)op.refreshParams(); +} + +function updateDefines() +{ + if (copyShader)copyShader.toggleDefine("USE_TEX", inTex.isLinked()); +} + +function updateUi() +{ + r.setUiAttribs({ "greyout": inTex.isLinked() }); + b.setUiAttribs({ "greyout": inTex.isLinked() }); + g.setUiAttribs({ "greyout": inTex.isLinked() }); + a.setUiAttribs({ "greyout": inTex.isLinked() }); + + width.setUiAttribs({ "greyout": inSize.get() == "Auto" }); + height.setUiAttribs({ "greyout": inSize.get() == "Auto" }); + + width.setUiAttribs({ "hideParam": inSize.get() != "Manual" }); + height.setUiAttribs({ "hideParam": inSize.get() != "Manual" }); + + if (tex) + if (getFloatingPoint() && getFilter() == CGL.Texture.FILTER_MIPMAP) op.setUiError("fpmipmap", "Don't use mipmap and 32bit at the same time, many systems do not support this."); + else op.setUiError("fpmipmap", null); + + updateResolutionInfo(); + updateDefines(); +} + +op.preRender = () => +{ + doRender(); +}; + +function copyTexture() +{ + if (!copyShader) + { + copyShader = new CGL.Shader(cgl, "copytextureshader"); + copyShader.setSource(copyShader.getDefaultVertexShader(), attachments.imgcomp_frag); + copyShaderTexUni = new CGL.Uniform(copyShader, "t", "tex", 0); + copyShaderRGBAUni = new CGL.Uniform(copyShader, "4f", "bgColor", r, g, b, a); + updateDefines(); + } + + cgl.pushShader(copyShader); + cgl.currentTextureEffect.bind(); + + if (inTex.get()) cgl.setTexture(0, inTex.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); +} + +function doRender() +{ + if (!effect || reInitEffect) initEffect(); + + const vp = cgl.getViewPort(); + prevViewPort[0] = vp[0]; + prevViewPort[1] = vp[1]; + prevViewPort[2] = vp[2]; + prevViewPort[3] = vp[3]; + + cgl.pushBlend(false); + + updateResolution(); + + const oldEffect = cgl.currentTextureEffect; + cgl.currentTextureEffect = effect; + cgl.currentTextureEffect.imgCompVer = 3; + cgl.currentTextureEffect.width = width.get(); + cgl.currentTextureEffect.height = height.get(); + effect.setSourceTexture(tex); + + effect.startEffect(inTex.get() || CGL.Texture.getEmptyTexture(cgl, isFloatTex), true); + copyTexture(); + + trigger.trigger(); + + texOut.set(CGL.Texture.getEmptyTexture(cgl)); + + texOut.set(effect.getCurrentSourceTexture()); + + effect.endEffect(); + + cgl.setViewPort(prevViewPort[0], prevViewPort[1], prevViewPort[2], prevViewPort[3]); + + cgl.popBlend(false); + cgl.currentTextureEffect = oldEffect; +} + + +}; + +Ops.Gl.TextureEffects.ImageCompose_v3.prototype = new CABLES.Op(); +CABLES.OPS["e890a050-11b7-456e-b09b-d08cd9c1ee41"]={f:Ops.Gl.TextureEffects.ImageCompose_v3,objName:"Ops.Gl.TextureEffects.ImageCompose_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Interlace +// +// ************************************************************** + +Ops.Gl.TextureEffects.Interlace = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"interlace_frag":"\n#ifdef HAS_TEXTURES\n IN vec2 texCoord;\n UNI sampler2D tex;\n#endif\nUNI float amount;\nUNI float lum;\nUNI float add;\nUNI float lineSize;\nUNI float scroll;\nUNI float displace;\n\n\nvoid main()\n{\n vec4 col=vec4(1.0,0.0,0.0,1.0);\n\n col=texture(tex,texCoord);\n // .endl()+' col=clamp(col,0.0,1.0);'\n\n float dir;\n #ifdef DIRECTION\n dir = gl_FragCoord.x;\n #endif\n\n #ifndef DIRECTION\n dir = gl_FragCoord.y;\n #endif\n\n if( mod(dir+scroll,lineSize)>=lineSize*0.5)\n {\n col=texture(tex,vec2(texCoord.x+displace*0.05,texCoord.y));\n float gray = vec3(dot(vec3(0.2126,0.7152,0.0722), col.rgb)).r;\n col.rgb=col.rgb*(1.0-amount) + (col.rgb*gray*gray*lum)*amount;\n }\n else col+=add;\n\n\n outColor= col;\n}",}; +let render = op.inTrigger("render"); +let amount = op.inValueSlider("amount", 0.5); +let lum = op.inValueSlider("Lumi Scale", 0.9); +let direction = op.inBool("X or Y", false); +let lineSize = op.inValue("Line Size", 4); +let displace = op.inValueSlider("Displacement", 0); + +let add = op.inValue("Add", 0.02); +let inScroll = op.inValue("scroll", 0); + +let trigger = op.outTrigger("trigger"); + +let cgl = op.patch.cgl; +let shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.interlace_frag); +let textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +let uniAmount = new CGL.Uniform(shader, "f", "amount", amount); + +let uniLum = new CGL.Uniform(shader, "f", "lum", lum); +let uniLineSize = new CGL.Uniform(shader, "f", "lineSize", lineSize); +let uniAdd = new CGL.Uniform(shader, "f", "add", add); +let uniDisplace = new CGL.Uniform(shader, "f", "displace", displace); +let uniScroll = new CGL.Uniform(shader, "f", "scroll", inScroll); + +direction.onChange = function () +{ + shader.toggleDefine("DIRECTION", direction.get()); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Interlace.prototype = new CABLES.Op(); +CABLES.OPS["3cd69d5b-6c05-4522-9551-52458f99421a"]={f:Ops.Gl.TextureEffects.Interlace,objName:"Ops.Gl.TextureEffects.Interlace"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Invert_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Invert_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"invert_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D texMask;\nUNI float amount;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n vec4 col=texture(tex,texCoord);\n\n #ifdef USE_MASK\n #ifdef MASK_INVERT\n if(texture(texMask,texCoord).r>0.5)\n {\n outColor= col;\n return;\n }\n #endif\n\n #ifndef MASK_INVERT\n if(texture(texMask,texCoord).r<0.5)\n {\n outColor= col;\n return;\n }\n #endif\n #endif\n\n\n vec3 m=vec3( INVR , INVG , INVB );\n vec4 invert = vec4(clamp(m-col.rgb,0.0,1.0),col.a);\n\n outColor=cgl_blendPixel(col,invert,amount);\n\n // outColor.rgb=m;\n}\n",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + maskInvert = op.inBool("Mask Invert", false), + mask = op.inTexture("Mask"), + invertR = op.inBool("Invert R", true), + invertG = op.inBool("Invert G", true), + invertB = op.inBool("Invert B", true), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.invert_frag); +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + textureMaskUniform = new CGL.Uniform(shader, "t", "texMask", 1); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +maskInvert.onChange = + invertR.onChange = + invertG.onChange = + invertB.onChange = + mask.onLinkChanged = updateDefines; +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("USE_MASK", mask.isLinked()); + shader.toggleDefine("MASK_INVERT", maskInvert.get()); + + shader.define("INVR", invertR.get() ? "1.0" : "0.0"); + shader.define("INVG", invertG.get() ? "1.0" : "0.0"); + shader.define("INVB", invertB.get() ? "1.0" : "0.0"); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + if (mask.get())cgl.setTexture(1, mask.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Invert_v2.prototype = new CABLES.Op(); +CABLES.OPS["56e8c95b-da89-423b-9d31-23351c263bb6"]={f:Ops.Gl.TextureEffects.Invert_v2,objName:"Ops.Gl.TextureEffects.Invert_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Kaleidoscope_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Kaleidoscope_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"kaleidoscope_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\n\nUNI float sides;\nUNI float angle;\nUNI float amount;\n\nUNI float slidex;\nUNI float slidey;\nUNI float centerX;\nUNI float centerY;\nUNI float aspect;\n\nconst float tau = 6.28318530718;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n vec2 center=vec2(centerX,centerY/aspect);\n\n\tvec2 loc = texCoord;\n\tloc.y/=aspect;\n\n\tfloat r = distance(center, loc);\n\tfloat a = atan ((loc.y-center.y),(loc.x-center.x));\n\n\t// kaleidoscope\n\ta = mod(a, tau/sides);\n\ta = abs(a - tau/sides/2.);\n\n\tloc.x = r * cos(a + tau * angle);\n\tloc.y = r * sin(a + tau * angle);\n\n\tloc = (center + loc) *2.1;\n\n\tloc.x = mod(loc.x + slidex, 1.0);\n\tloc.y = mod(loc.y + slidey, 1.0);\n\n\tif(loc.x < 0.0)loc.x = mod(abs(loc.x),1.0);\n\tif(loc.y < 0.0)loc.y = mod(abs(loc.y),1.0);\n\n\tif(loc.x > 1.0) loc.x = mod(abs(1.0-loc.x),1.0);\n\tif(loc.y > 1.0) loc.y = mod(abs(1.0-loc.y),1.0);\n\n\tvec4 col=texture(tex,loc);\n\tvec4 base=texture(tex,texCoord);\n\tbase.a=0.0;\n outColor= cgl_blendPixel(base,col,amount);\n\n}\n",}; +const + render = op.inTrigger("Render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + sides = op.inValue("Sides", 10), + angle = op.inValueSlider("Angle", 0), + slidex = op.inValueSlider("Slide X", 0), + slidey = op.inValueSlider("Slide Y", 0), + centerX = op.inValueSlider("Center X", 0.5), + centerY = op.inValueSlider("Center Y", 0.5), + inAspect=op.inBool("Aspect Ratio",true), + trigger = op.outTrigger("Next"); + +let cgl = op.patch.cgl; +let shader = new CGL.Shader(cgl, op.name); + +const + unisides = new CGL.Uniform(shader, "f", "sides", sides), + uniangle = new CGL.Uniform(shader, "f", "angle", angle), + unislidex = new CGL.Uniform(shader, "f", "slidex", slidex), + unislidey = new CGL.Uniform(shader, "f", "slidey", slidey), + uniCenterX = new CGL.Uniform(shader, "f", "centerX", centerX), + uniCenterY = new CGL.Uniform(shader, "f", "centerY", centerY), + uniAmount = new CGL.Uniform(shader, "f", "amount", amount), + uniAspect = new CGL.Uniform(shader, "f", "aspect", 1); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +shader.setSource(shader.getDefaultVertexShader(), attachments.kaleidoscope_frag); +let textureUniform = new CGL.Uniform(shader, "t", "tex", 0); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + if(inAspect.get()) uniAspect.setValue(cgl.currentTextureEffect.aspectRatio); + else uniAspect.setValue(1); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Kaleidoscope_v2.prototype = new CABLES.Op(); +CABLES.OPS["3c900fc2-8508-4531-a365-43224f7751c8"]={f:Ops.Gl.TextureEffects.Kaleidoscope_v2,objName:"Ops.Gl.TextureEffects.Kaleidoscope_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.LUTMap +// +// ************************************************************** + +Ops.Gl.TextureEffects.LUTMap = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"lut_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D texLut;\nUNI float amount;\n\nvoid main()\n{\n vec4 textureColor = texture(tex, texCoord);\n float blueColor = textureColor.b * 63.0;\n \n vec2 quad1;\n quad1.y = floor(floor(blueColor) / 8.0);\n quad1.x = floor(blueColor) - (quad1.y * 8.0);\n \n vec2 quad2;\n quad2.y = floor(ceil(blueColor) / 8.0);\n quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n \n highp vec2 texPos1;\n texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);\n \n highp vec2 texPos2;\n texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);\n \n vec4 newColor1 = texture(texLut, texPos1);\n vec4 newColor2 = texture(texLut, texPos2);\n \n vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n outColor= mix(textureColor,vec4(newColor.rgb, textureColor.w),amount);\n}\n",}; +let render = op.inTrigger("render"); +let trigger = op.outTrigger("trigger"); +let inLut = op.inTexture("LUT Image"); +let inAmount = op.inValueSlider("Amount", 1.0); + +let cgl = op.patch.cgl; +let shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.lut_frag); +let textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +let textureUniform2 = new CGL.Uniform(shader, "t", "texLut", 1); +let uniPos = new CGL.Uniform(shader, "f", "amount", inAmount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + if (!inLut.get()) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.setTexture(1, inLut.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.LUTMap.prototype = new CABLES.Op(); +CABLES.OPS["baba13d7-1cc2-4ba8-b66d-05425b0e5a75"]={f:Ops.Gl.TextureEffects.LUTMap,objName:"Ops.Gl.TextureEffects.LUTMap"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.LensDirt_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.LensDirt_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"lensDirt_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float uOffsetX;\nUNI float uOffsetY;\nUNI float uZoom;\n// UNI int uIterations;\nUNI int uRandomSeed;\nUNI float uSpotEdge;\nUNI float uGamma;\nUNI float uAspect;\nUNI float amount;\n\n{{CGL.BLENDMODES3}}\n\n// https://www.shadertoy.com/view/MdfBRX\nfloat Bokeh(vec2 p, vec2 sp, float size, float mi, float blur)\n{\n float d = length(p - sp);\n float c = smoothstep(size, size*(1.-blur), d);\n c *= mix(mi, 1., smoothstep(size*.8, size, d));\n return c;\n}\n/// 2 out, 2 in... from https://www.shadertoy.com/view/4djSRW\n//stable\nvec2 hash22(vec2 p)\n{\n\tvec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));\n p3 += dot(p3, p3.yzx+33.33);\n return fract((p3.xx+p3.yz)*p3.zy)*2.0-1.0;\n\n}\nvec3 dirt(vec2 uv, float n,float density,float hardness)\n{\n n *= density;\n vec2 p = fract(uv * n);\n vec2 st = (floor(uv * n) + 0.5) / n;\n vec2 rnd = hash22(st);\n float c = Bokeh(p, vec2(0.5, 0.5) + vec2(0.3) * rnd, 0.2,\n abs(rnd.y * 0.35) + 0.3, 0.25 + rnd.x * rnd.y * hardness);\n\n return vec3(c) * exp(rnd.x * 4.0);\n}\n\nvoid main()\n{\n\tvec3 di = vec3(1.0);\n float edgeHardness = 0.1;\n edgeHardness = clamp(uSpotEdge*0.25,0.0,0.2);\n\n vec2 uv = (texCoord-0.5);\n\n uv.y/=uAspect;\n uv *= uZoom;\n uv -= vec2(uOffsetX,uOffsetY);\n\n float q = 0.0;\n for (int i = 1; i < ITERATIONS ; i++)\n {\n q = float(i);\n vec2 h=hash22(vec2(q)+vec2(uRandomSeed));\n di += dirt(uv-h, h.x, 1.0, edgeHardness);\n }\n\n di = pow(di* 0.01,vec3(uGamma));\n vec4 col = vec4(di,1.0);\n vec4 base = texture(tex,texCoord);\n\n outColor = cgl_blendPixel(base,col,amount);\n}",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + offsetX = op.inFloat("Offset X", 0), + offsetY = op.inFloat("Offset Y", 0), + zoom = op.inFloat("Zoom", 5), + iterations = op.inInt("Iterations", 50), + randomSeed = op.inInt("Seed", 1), + spotEdge = op.inFloatSlider("Spot edge", 0.5), + gamma = op.inFloat("Gamma", 0.75), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.lensDirt_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + offsetXUniformX = new CGL.Uniform(shader, "f", "uOffsetX", offsetX), + offsetXUniformY = new CGL.Uniform(shader, "f", "uOffsetY", offsetY), + zoomUniform = new CGL.Uniform(shader, "f", "uZoom", zoom), + // iterationsUniform=new CGL.Uniform(shader,'i','uIterations',iterations), + randomSeedUniform = new CGL.Uniform(shader, "i", "uRandomSeed", randomSeed), + spotEdgeUniform = new CGL.Uniform(shader, "f", "uSpotEdge", spotEdge), + gammaUniform = new CGL.Uniform(shader, "f", "uGamma", gamma), + uniformAspect = new CGL.Uniform(shader, "f", "uAspect", 1.0), + + amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +iterations.onChange = updateIterations; +updateIterations(); + +function updateIterations() +{ + let its = iterations.get(); + its = Math.min(300, Math.max(1, its)); + shader.define("ITERATIONS", its); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + uniformAspect.setValue(cgl.currentTextureEffect.getCurrentSourceTexture().width / cgl.currentTextureEffect.getCurrentSourceTexture().height); + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.LensDirt_v2.prototype = new CABLES.Op(); +CABLES.OPS["a04156f6-f636-430f-810e-9cb27199ceeb"]={f:Ops.Gl.TextureEffects.LensDirt_v2,objName:"Ops.Gl.TextureEffects.LensDirt_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.LensScratches_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.LensScratches_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"lensScratches_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float uOffsetX;\nUNI float uOffsetY;\nUNI float uWavyness;\nUNI float uScale;\nUNI int uLayers;\nUNI float uAntiAliasIterations;\nUNI float uFrequency;\nUNI float uFrequencyStep;\nUNI float uResWidth;\nUNI float uResHeight;\nUNI float uAspect;\nUNI float amount;\n\n{{CGL.BLENDMODES3}}\n//Shader kindly used with the permission of Tropical trevor\n//shadertoy user Daedelus\n//https://www.shadertoy.com/view/4syXRD\n\nvoid pR(inout vec2 p, float a)\n{\n float sa = sin(a);\n float ca = cos(a);\n p *= mat2(ca, sa, -sa, ca);\n}\n\nfloat scratch(vec2 uv, vec2 seed)\n{\n seed.x = floor(sin(seed.x * 51024.0) * 3104.0);\n seed.y = floor(sin(seed.y * 1324.0) * 554.0);\n\n uv = uv * 2.0 - 1.0;\n pR(uv, seed.x + seed.y);\n uv += sin(seed.x - seed.y);\n uv = clamp(uv * 0.5 + 0.5, 0.0, 1.0);\n\n float s1 = sin(seed.x + uv.y * 3.1415) * uWavyness;\n float s2 = sin(seed.y + uv.y * 3.1415) * uWavyness;\n\n float x = sign(0.01 - abs(uv.x - 0.5 + s2 + s1));\n return clamp(((1.0 - pow(uv.y, 2.0)) * uv.y) * 2.5 * x, 0.0, 1.0);\n}\n\nfloat layer(vec2 uv, vec2 frequency, vec2 offset, float angle)\n{\n pR(uv, angle);\n uv = uv * frequency + offset;\n return scratch(fract(uv), floor(uv));\n}\n\nfloat scratches(vec2 uv)\n{\n uv *= uScale;\n uv -= vec2(uOffsetX,uOffsetY);\n vec2 frequency = vec2(uFrequency);\n float scratches = 0.0;\n int iterations = clamp(uLayers,1,20);\n for(int i = 0; i < iterations; ++i)\n {\n float fi = float(i);\n \tscratches += layer(uv, frequency, vec2(fi, fi), fi * 3145.0);\n frequency += uFrequencyStep;\n }\n return scratches;\n}\nvoid main()\n{\n vec2 uv = texCoord.xy-0.5;\n uv.y/=uAspect;\n\n // using AA by Shane:\n // https://www.shadertoy.com/view/4d3SWf\n // Antialias level. Set to 1 for a standard, aliased scene\n float AA = clamp(uAntiAliasIterations,1.,4.);\n int AA2 = int(AA*AA);\n float color = 0.0;\n vec2 pix = 2.0/vec2(uResWidth,uResHeight)/AA; // or iResolution.xy\n for (int i=0; i threshholdHigh) col.r=col.g=col.b=col.a=0.0;\n #ifdef BLACKWHITE\n else col.r=col.g=col.b=col.a=1.0;\n #endif\n #endif\n\n #ifdef INVERT\n if(gray > threshholdLow && gray < threshholdHigh) col.r=col.g=col.b=col.a=0.0;\n #ifdef BLACKWHITE\n else col.r=col.g=col.b=col.a=1.0;\n #endif\n #endif\n\n outColor= col;\n}",}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + inInvert = op.inValueBool("Invert"), + inBlackWhite = op.inValueBool("Black White"), + thresholdLow = op.inValueSlider("Threshold low ", 0.5), + thresholdHigh = op.inValueSlider("Threshold high", 1.0); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "lumakey"); + +shader.setSource(shader.getDefaultVertexShader(), attachments.lumakeyV2_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const uniThresholdLow = new CGL.Uniform(shader, "f", "threshholdLow", thresholdLow); +const uniThresholdHigh = new CGL.Uniform(shader, "f", "threshholdHigh", thresholdHigh); + +inBlackWhite.onChange = function () +{ + if (inBlackWhite.get()) shader.define("BLACKWHITE"); + else shader.removeDefine("BLACKWHITE"); +}; + +inInvert.onChange = function () +{ + if (inInvert.get()) shader.define("INVERT"); + else shader.removeDefine("INVERT"); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + + cgl.currentTextureEffect.bind(); + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + + cgl.popShader(); + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.LumaKey_v2.prototype = new CABLES.Op(); +CABLES.OPS["1699f3fc-355b-4497-a23c-1620a04a9cd4"]={f:Ops.Gl.TextureEffects.LumaKey_v2,objName:"Ops.Gl.TextureEffects.LumaKey_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Math.RgbMath +// +// ************************************************************** + +Ops.Gl.TextureEffects.Math.RgbMath = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"rgbmul_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\n#ifdef MOD_MASK\n UNI sampler2D texMask;\n#endif\nUNI float r;\nUNI float g;\nUNI float b;\nUNI float a;\n\n\n\nvoid main()\n{\n vec4 col=texture(tex,texCoord);\n vec4 v=vec4(r,g,b,a);\n\n #ifdef MOD_MASK\n v*=texture(texMask,texCoord);\n #endif\n\n #ifdef MOD_OP_SUB_CX\n #ifdef MOD_CHAN_R\n col.r=col.r-v.r;\n #endif\n #ifdef MOD_CHAN_G\n col.g=col.g-v.g;\n #endif\n #ifdef MOD_CHAN_B\n col.b=col.b-v.b;\n #endif\n #ifdef MOD_CHAN_A\n col.a=col.a-v.a;\n #endif\n #endif\n\n #ifdef MOD_OP_SUB_XC\n #ifdef MOD_CHAN_R\n col.r=v.r-col.r;\n #endif\n #ifdef MOD_CHAN_G\n col.g=v.g-col.g;\n #endif\n #ifdef MOD_CHAN_B\n col.b=v.b-col.b;\n #endif\n #ifdef MOD_CHAN_A\n col.a=v.a-col.a;\n #endif\n #endif\n\n #ifdef MOD_OP_ADD\n #ifdef MOD_CHAN_R\n col.r+=v.r;\n #endif\n #ifdef MOD_CHAN_G\n col.g+=v.g;\n #endif\n #ifdef MOD_CHAN_B\n col.b+=v.b;\n #endif\n #ifdef MOD_CHAN_A\n col.a+=v.a;\n #endif\n #endif\n\n #ifdef MOD_OP_MUL\n #ifdef MOD_CHAN_R\n col.r*=v.r;\n #endif\n #ifdef MOD_CHAN_G\n col.g*=v.g;\n #endif\n #ifdef MOD_CHAN_B\n col.b*=v.b;\n #endif\n #ifdef MOD_CHAN_A\n col.a*=v.a;\n #endif\n #endif\n\n #ifdef MOD_OP_DIV_XC\n #ifdef MOD_CHAN_R\n col.r=v.r/col.r;\n #endif\n #ifdef MOD_CHAN_G\n col.g=v.g/col.g;\n #endif\n #ifdef MOD_CHAN_B\n col.b=v.b/col.b;\n #endif\n #ifdef MOD_CHAN_A\n col.a=v.a/col.a;\n #endif\n #endif\n\n #ifdef MOD_OP_DIV_CX\n #ifdef MOD_CHAN_R\n col.r=col.r/v.r;\n #endif\n #ifdef MOD_CHAN_G\n col.g=col.g/v.g;\n #endif\n #ifdef MOD_CHAN_B\n col.b=col.b/v.b;\n #endif\n #ifdef MOD_CHAN_A\n col.a=col.a/v.a;\n #endif\n #endif\n\n #ifdef MOD_OP_MODULO\n col=mod(col,v);\n #endif\n\n// csdcsd\n outColor= col;\n}\n",}; +const + render = op.inTrigger("Render"), + inOp = op.inSwitch("Operation", ["c-x", "x-c", "c+x", "c*x", "x/c", "c/x", "c%x"], "c*x"), + chanR = op.inBool("R Active", true), + chanG = op.inBool("G Active", true), + chanB = op.inBool("B Active", true), + chanA = op.inBool("A Active", false), + r = op.inValue("r", 1), + g = op.inValue("g", 1), + b = op.inValue("b", 1), + a = op.inValue("a", 1), + inTexMask = op.inTexture("Mask"), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.rgbmul_frag); +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + textureMaskUniform = new CGL.Uniform(shader, "t", "texMask", 1), + uniformR = new CGL.Uniform(shader, "f", "r", r), + uniformG = new CGL.Uniform(shader, "f", "g", g), + uniformB = new CGL.Uniform(shader, "f", "b", b), + uniformA = new CGL.Uniform(shader, "f", "a", a); + +chanR.onChange = + inTexMask.onChange = + chanG.onChange = + chanB.onChange = + chanA.onChange = + inOp.onChange = updateDefines; + +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("MOD_MASK", inTexMask.get()); + + shader.toggleDefine("MOD_OP_SUB_CX", inOp.get() === "c-x"); + shader.toggleDefine("MOD_OP_SUB_XC", inOp.get() === "x-c"); + + shader.toggleDefine("MOD_OP_ADD", inOp.get() === "c+x"); + shader.toggleDefine("MOD_OP_MUL", inOp.get() === "c*x"); + + shader.toggleDefine("MOD_OP_DIV_XC", inOp.get() === "x/c"); + shader.toggleDefine("MOD_OP_DIV_CX", inOp.get() === "c/x"); + + shader.toggleDefine("MOD_OP_MODULO", inOp.get() === "c%x"); + + shader.toggleDefine("MOD_CHAN_R", chanR.get()); + r.setUiAttribs({ "greyout": !chanR.get() }); + + shader.toggleDefine("MOD_CHAN_G", chanG.get()); + g.setUiAttribs({ "greyout": !chanG.get() }); + + shader.toggleDefine("MOD_CHAN_B", chanB.get()); + b.setUiAttribs({ "greyout": !chanB.get() }); + + shader.toggleDefine("MOD_CHAN_A", chanA.get()); + a.setUiAttribs({ "greyout": !chanA.get() }); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + if (inTexMask.get())cgl.setTexture(1, inTexMask.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Math.RgbMath.prototype = new CABLES.Op(); +CABLES.OPS["dc858e71-1f12-4de5-89f5-67fb41ebfa39"]={f:Ops.Gl.TextureEffects.Math.RgbMath,objName:"Ops.Gl.TextureEffects.Math.RgbMath"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Math.RgbTransform +// +// ************************************************************** + +Ops.Gl.TextureEffects.Math.RgbTransform = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"rgbmul_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\n#ifdef MOD_MASK\n UNI sampler2D texMask;\n#endif\n\nUNI vec3 translate;\nUNI vec3 scale;\nUNI vec3 rot;\n\n\n\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n axis = normalize(axis);\n float s = sin(angle);\n float c = cos(angle);\n float oc = 1.0 - c;\n\n return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0,\n oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0,\n oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0,\n 0.0, 0.0, 0.0, 1.0);\n}\n\n\nvoid main()\n{\n vec4 col=texture(tex,texCoord);\n\n float mul=1.0;\n\n\n #ifdef MOD_MASK\n mul=texture(texMask,texCoord).r;\n #endif\n\n #ifdef DO_ROT\n col*=rotationMatrix(vec3(1.0,0.0,0.0), mul*rot.x/57.29577951308232);\n col*=rotationMatrix(vec3(0.0,1.0,0.0), mul*rot.y/57.29577951308232);\n col*=rotationMatrix(vec3(0.0,0.0,1.0), mul*rot.z/57.29577951308232);\n #endif\n\n #ifdef DO_SCALE\n col.xyz*=scale*mul;\n #endif\n\n #ifdef DO_TRANS\n col.xyz+=translate*mul;\n #endif\n\n outColor=col;\n}\n",}; +const + render = op.inTrigger("Render"), + + inDoTrans = op.inBool("Translate", true), + posx = op.inValue("Pos X", 0), + posy = op.inValue("Pos Y", 0), + posz = op.inValue("Pos Z", 0), + + inDoScale = op.inBool("Scale", true), + scalex = op.inValue("Scale X", 1), + scaley = op.inValue("Scale Y", 1), + scalez = op.inValue("Scale Z", 1), + + inDoRot = op.inBool("Rotate", true), + rotx = op.inValue("Rotation X", 1), + roty = op.inValue("Rotation Y", 1), + rotz = op.inValue("Rotation Z", 1), + + inTexMask = op.inTexture("Mask"), + trigger = op.outTrigger("trigger"); + +op.setPortGroup("Rotation", [inDoRot, rotx, roty, rotz]); +op.setPortGroup("Position", [inDoTrans, posx, posy, posz]); +op.setPortGroup("Scale", [inDoScale, scalex, scaley, scalez]); +op.setUiAxisPorts(posx, posz, posy); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.rgbmul_frag); +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + textureMaskUniform = new CGL.Uniform(shader, "t", "texMask", 1), + uniformTransl = new CGL.Uniform(shader, "3f", "translate", posx, posy, posz), + uniformScale = new CGL.Uniform(shader, "3f", "scale", scalex, scaley, scalez), + uniformRot = new CGL.Uniform(shader, "3f", "rot", rotx, roty, rotz); + +inTexMask.onChange = + inDoTrans.onChange = + inDoRot.onChange = + inDoScale.onChange = updateDefines; + +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("MOD_MASK", inTexMask.get()); + + shader.toggleDefine("DO_TRANS", inDoTrans.get()); + shader.toggleDefine("DO_ROT", inDoRot.get()); + shader.toggleDefine("DO_SCALE", inDoScale.get()); + + posx.setUiAttribs({ "greyout": !inDoTrans.get() }); + posy.setUiAttribs({ "greyout": !inDoTrans.get() }); + posz.setUiAttribs({ "greyout": !inDoTrans.get() }); + + rotx.setUiAttribs({ "greyout": !inDoRot.get() }); + roty.setUiAttribs({ "greyout": !inDoRot.get() }); + rotz.setUiAttribs({ "greyout": !inDoRot.get() }); + + scalex.setUiAttribs({ "greyout": !inDoScale.get() }); + scaley.setUiAttribs({ "greyout": !inDoScale.get() }); + scalez.setUiAttribs({ "greyout": !inDoScale.get() }); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + if (inTexMask.get())cgl.setTexture(1, inTexMask.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Math.RgbTransform.prototype = new CABLES.Op(); +CABLES.OPS["0a069281-e7a1-43a4-a74a-101026df6a29"]={f:Ops.Gl.TextureEffects.Math.RgbTransform,objName:"Ops.Gl.TextureEffects.Math.RgbTransform"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Mirror +// +// ************************************************************** + +Ops.Gl.TextureEffects.Mirror = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"mirror_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float axis;\nUNI float width;\nUNI float flip;\nUNI float offset;\n\nvoid main()\n{\n vec4 col=vec4(1.0,0.0,0.0,1.0);\n\n float tc=texCoord.x;\n if(axis==1.0) tc=(texCoord.y);\n\n float x=(tc);\n if(tc>=0.5)x=1.0-tc;\n\n x*=width*2.0;\n if(flip==1.0)x=1.0-x;\n x*=1.0-offset;\n\n if(axis==1.0) col=texture(tex,vec2(texCoord.x,x) );\n else col=texture(tex,vec2(x,texCoord.y) );\n\n outColor= col;\n}",}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + axis = op.inSwitch("axis", ["X", "Y"], "X"), + width = op.inValueFloat("width", 0.5), + offset = op.inValueFloat("offset"), + flip = op.inValueBool("flip"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.mirror_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uniAxis = new CGL.Uniform(shader, "f", "axis", 0), + uniWidth = new CGL.Uniform(shader, "f", "width", width), + uniOffset = new CGL.Uniform(shader, "f", "offset", offset), + uniFlip = new CGL.Uniform(shader, "f", "flip", 0); + +flip.onChange = function () +{ + if (flip.get())uniFlip.setValue(1); + else uniFlip.setValue(0); +}; + +axis.onChange = function () +{ + if (axis.get() == "X")uniAxis.setValue(0); + else if (axis.get() == "Y")uniAxis.setValue(1); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Mirror.prototype = new CABLES.Op(); +CABLES.OPS["10d3c769-9a7f-4bd3-a849-7354d3e5f7f0"]={f:Ops.Gl.TextureEffects.Mirror,objName:"Ops.Gl.TextureEffects.Mirror"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.MultiDrawImage +// +// ************************************************************** + +Ops.Gl.TextureEffects.MultiDrawImage = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"invert_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D tex1;\nUNI sampler2D tex2;\nUNI sampler2D tex3;\nUNI sampler2D tex4;\nUNI sampler2D tex5;\nUNI sampler2D tex6;\nUNI sampler2D tex7;\nUNI sampler2D tex8;\n\n\nUNI sampler2D texMask1;\nUNI sampler2D texMask2;\nUNI sampler2D texMask3;\nUNI sampler2D texMask4;\nUNI sampler2D texMask5;\nUNI sampler2D texMask6;\nUNI sampler2D texMask7;\nUNI sampler2D texMask8;\n\nUNI float amount1;\nUNI float amount2;\nUNI float amount3;\nUNI float amount4;\nUNI float amount5;\nUNI float amount6;\nUNI float amount7;\nUNI float amount8;\n\n{{BLENDCODE}}\n\nvoid main()\n{\n vec4 col=texture(tex,texCoord);\n\n\n #ifdef USE_TEX_1\n vec4 col1=texture(tex1,texCoord);\n col=cgl_blend1(col,col1,amount1);\n #endif\n #ifdef USE_TEX_2\n vec4 col2=texture(tex2,texCoord);\n col=cgl_blend2(col,col2,amount2);\n #endif\n #ifdef USE_TEX_3\n vec4 col3=texture(tex3,texCoord);\n col=cgl_blend3(col,col3,amount3);\n #endif\n #ifdef USE_TEX_4\n vec4 col4=texture(tex4,texCoord);\n col=cgl_blend4(col,col4,amount4);\n #endif\n #ifdef USE_TEX_5\n vec4 col5=texture(tex5,texCoord);\n col=cgl_blend5(col,col5,amount5);\n #endif\n #ifdef USE_TEX_6\n vec4 col6=texture(tex6,texCoord);\n col=cgl_blend6(col,col6,amount6);\n #endif\n #ifdef USE_TEX_7\n vec4 col7=texture(tex7,texCoord);\n col=cgl_blend7(col,col7,amount7);\n #endif\n #ifdef USE_TEX_8\n vec4 col8=texture(tex8,texCoord);\n col=cgl_blend8(col,col8,amount8);\n #endif\n\n outColor=col;\n\n}\n",}; +const blendmodes = ["normal", "lighten", "darken", "multiply", "multiply invert", "average", "add", "substract", "difference", "negation", "exclusion", "overlay", "screen", "color dodge", "color burn", "softlight", "hardlight"]; +const + render = op.inTrigger("render"), + maskInvert = op.inBool("Mask Invert", false), + trigger = op.outTrigger("trigger"); +const + NUM = 8, + cgl = op.patch.cgl, + shader = new CGL.Shader(cgl, op.name), + amounts = [], + blends = [], + alphas = [], + texMasks = [], + maskModes = [], + texs = []; + +let needsUpdate = true; + +for (let i = 0; i < NUM; i++) +{ + const tex = op.inTexture("Texture " + (i + 1)); + const blend = op.inDropDown("Blendmode " + (i + 1), blendmodes, "normal"); + const texMask = op.inTexture("Mask " + (i + 1)); + const maskMode = op.inSwitch("Mask Source " + (i + 1), ["R", "R inv", "A", "A inv"], "R"); + const alpha = op.inSwitch("Opacity " + (i + 1), ["Normal", "Prev A", "Prev R"], "Normal"); + const amount = op.inValueSlider("Amount " + (i + 1), 1); + + blend.onChange = + alpha.onChange = + maskMode.onChange = + texMask.onLinkChanged = + tex.onLinkChanged = () => { needsUpdate = true; }; + + texs.push(tex); + texMasks.push(texMask); + alphas.push(alpha); + blends.push(blend); + amounts.push(amount); + maskModes.push(maskMode); + + op.setPortGroup("Image " + (i + 1), [tex, blend, amount, alpha, texMask, maskMode]); + + new CGL.Uniform(shader, "t", "tex" + (i + 1), i * 2 + 1); + new CGL.Uniform(shader, "t", "texMask" + (i + 1), i * 2 + 2); + new CGL.Uniform(shader, "f", "amount" + (i + 1), amount); +} + +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); + +function setBlendCode() +{ + let defines = ""; + let blendcode = ""; + for (let i = 0; i < NUM; i++) + { + let active = texs[i].isLinked(); + amounts[i].setUiAttribs({ "greyout": !active }); + blends[i].setUiAttribs({ "greyout": !active }); + alphas[i].setUiAttribs({ "greyout": !active }); + + if (active) + { + defines += "#define USE_TEX_" + (i + 1) + "".endl(); + blendcode += getBlendCode(i + 1, + blends[i].get(), + alphas[i].get(), + texMasks[i].get(), + maskModes[i].get()); + } + } + + let src = defines.endl() + attachments.invert_frag; + src = src.replace("{{BLENDCODE}}", blendcode); + + shader.setSource(shader.getDefaultVertexShader(), src); + + needsUpdate = false; +} + +function getBlendCode(idx, name, alpha, hasMask, maskMode) +{ + let src = "" + + "vec3 _blend" + idx + "(vec3 base,vec3 blend)".endl() + + "{".endl() + + " vec3 colNew=blend;".endl(); + + if (name == "multiply") src += " colNew=base*blend;".endl(); + else if (name == "multiply invert") src += " colNew=base* vec3(1.0)-blend;".endl(); + else if (name == "average") src += " colNew=((base + blend) / 2.0);".endl(); + else if (name == "add") src += " colNew=min(base + blend, vec3(1.0));".endl(); + else if (name == "substract") src += " colNew=max(base + blend - vec3(1.0), vec3(0.0));".endl(); + else if (name == "difference") src += " colNew=abs(base - blend);".endl(); + else if (name == "negation") src += " colNew=(vec3(1.0) - abs(vec3(1.0) - base - blend));".endl(); + else if (name == "exclusion") src += " colNew=(base + blend - 2.0 * base * blend);".endl(); + else if (name == "lighten") src += " colNew=max(blend, base);".endl(); + else if (name == "darken") src += " colNew=min(blend, base);".endl(); + else if (name == "overlay") + { + src += "" + + " #define BlendOverlayf(base, blend) (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))".endl() + + " colNew=vec3(BlendOverlayf(base.r, blend.r),BlendOverlayf(base.g, blend.g),BlendOverlayf(base.b, blend.b));".endl(); + } + else if (name == "screen") + { + src += "" + + " #define BlendScreenf(base, blend) (1.0 - ((1.0 - base) * (1.0 - blend)))".endl() + + " colNew=vec3(BlendScreenf(base.r, blend.r),BlendScreenf(base.g, blend.g),BlendScreenf(base.b, blend.b));".endl(); + } + else if (name == "softlight") + { + src += "" + + " #define BlendSoftLightf(base, blend) ((blend < 0.5) ? (2.0 * base * blend + base * base * (1.0 - 2.0 * blend)) : (sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend)))".endl() + + " colNew=vec3(BlendSoftLightf(base.r, blend.r),BlendSoftLightf(base.g, blend.g),BlendSoftLightf(base.b, blend.b));".endl(); + } + else if (name == "hardlight") + { + src += "" + + " #define BlendOverlayf(base, blend) (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))".endl() + + " colNew=vec3(BlendOverlayf(base.r, blend.r),BlendOverlayf(base.g, blend.g),BlendOverlayf(base.b, blend.b));".endl(); + } + else if (name == "color dodge") + { + src += "" + + " #define BlendColorDodgef(base, blend) ((blend == 1.0) ? blend : min(base / (1.0 - blend), 1.0))".endl() + + " colNew=vec3(BlendColorDodgef(base.r, blend.r),BlendColorDodgef(base.g, blend.g),BlendColorDodgef(base.b, blend.b));".endl(); + } + else if (name == "color burn") + { + src += "" + + " #define BlendColorBurnf(base, blend) ((blend == 0.0) ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0))".endl() + + " colNew=vec3(BlendColorBurnf(base.r, blend.r),BlendColorBurnf(base.g, blend.g),BlendColorBurnf(base.b, blend.b));".endl(); + } + + src += "" + + " return colNew;".endl() + + "}".endl() + + + "vec4 cgl_blend" + idx + "(vec4 oldColor,vec4 newColor,float amount)".endl() + + "{".endl() + // +"vec4 col=vec4(0.0,0.0,0.0,1.0);" + + // +"if(newColor.a==0.0)return vec4(0.0);".endl() + + "float a=(amount*newColor.a);".endl(); + + if (alpha === "Prev A") src += "a*=oldColor.a;"; + if (alpha === "Prev R") src += "a*=oldColor.r;"; + + src = src + + + "vec4 col = vec4( _blend" + idx + "(oldColor.rgb, newColor.rgb), 1.0);".endl() + + "col = vec4( mix( col.rgb,oldColor.rgb, col.a * 1.0-amount), 1.0);".endl(); + + if (hasMask) + if (maskMode === "R")src = src + "newColor.a *= texture(texMask" + idx + ",texCoord).r;".endl(); + else if (maskMode === "R inv")src = src + "newColor.a *= 1.0-texture(texMask" + idx + ",texCoord).r;".endl(); + else if (maskMode === "A")src = src + "newColor.a *= texture(texMask" + idx + ",texCoord).a;".endl(); + else if (maskMode === "A inv")src = src + "newColor.a *= 1.0-texture(texMask" + idx + ",texCoord).a;".endl(); + + src = src + "col = vec4( mix( oldColor,col, newColor.a));".endl() + + // + "vec3 blendedCol=_blend"+idx+"(newColor.rgb,newColor.rgb);".endl() + // + "col.rgb=mix(oldColor.rgb,newColor.rgb,a);".endl() + + // + "col.a=clamp(oldColor.a+a,0.0,1.0);".endl() + + + "return col;".endl() + + "}".endl().endl(); + return src; +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + if (needsUpdate)setBlendCode(); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + let count = 1; + for (let i = 0; i < texs.length; i++) + { + if (texs[i].get()) + { + cgl.setTexture(i * 2 + 1, texs[i].get().tex); + count++; + } + if (texMasks[i].get()) + { + cgl.setTexture(i * 2 + 2, texMasks[i].get().tex); + count++; + } + } + if (count > cgl.maxTextureUnits) op.setUiError("manytex", "Too many textures bound"); + else op.setUiError("manytex", null); + + cgl.pushBlendMode(CGL.BLEND_NONE, true); + cgl.currentTextureEffect.finish(); + cgl.popBlendMode(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.MultiDrawImage.prototype = new CABLES.Op(); +CABLES.OPS["4df51ead-c46c-471d-ac5e-1872219a3174"]={f:Ops.Gl.TextureEffects.MultiDrawImage,objName:"Ops.Gl.TextureEffects.MultiDrawImage"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Noise.CellularNoise_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Noise.CellularNoise_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"cellularnoise3d_frag":"UNI float z;\nUNI float x;\nUNI float y;\nUNI float scale;\nIN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float harmonics;\nUNI float aspect;\n\n#ifdef HAS_TEX_OFFSETMAP\n UNI sampler2D texOffsetZ;\n UNI float offMul;\n#endif\n\n#ifdef HAS_TEX_MASK\n UNI sampler2D texMask;\n#endif\n\n{{CGL.BLENDMODES3}}\n\nvoid FAST32_hash_3D( \tvec3 gridcell,\n out vec4 lowz_hash_0,\n out vec4 lowz_hash_1,\n out vec4 lowz_hash_2,\n out vec4 highz_hash_0,\n out vec4 highz_hash_1,\n out vec4 highz_hash_2\t)\t\t//\tgenerates 3 random numbers for each of the 8 cell corners\n{\n // gridcell is assumed to be an integer coordinate\n\n //\tTODO: \tthese constants need tweaked to find the best possible noise.\n //\t\t\tprobably requires some kind of brute force computational searching or something....\n const vec2 OFFSET = vec2( 50.0, 161.0 );\n const float DOMAIN = 69.0;\n const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );\n const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );\n\n //\ttruncate the domain\n gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;\n vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );\n\n //\tcalculate the noise\n vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;\n P *= P;\n P = P.xzxz * P.yyww;\n vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );\n vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );\n lowz_hash_0 = fract( P * lowz_mod.xxxx );\n highz_hash_0 = fract( P * highz_mod.xxxx );\n lowz_hash_1 = fract( P * lowz_mod.yyyy );\n highz_hash_1 = fract( P * highz_mod.yyyy );\n lowz_hash_2 = fract( P * lowz_mod.zzzz );\n highz_hash_2 = fract( P * highz_mod.zzzz );\n}\n\n\n\n\nvec4 Cellular_weight_samples( vec4 samples )\n{\n samples = samples * 2.0 - 1.0;\n //return (1.0 - samples * samples) * sign(samples);\t// square\n return (samples * samples * samples) - sign(samples);\t// cubic (even more variance)\n}\n\n\n//\n//\tCellular Noise 3D\n//\tBased off Stefan Gustavson's work at http://www.itn.liu.se/~stegu/GLSL-cellular\n//\thttp://briansharpe.files.wordpress.com/2011/12/cellularsample.jpg\n//\n//\tSpeed up by using 2x2x2 search window instead of 3x3x3\n//\tproduces range of 0.0->1.0\n//\nfloat Cellular3D(vec3 P)\n{\n //\testablish our grid cell and unit position\n vec3 Pi = floor(P);\n vec3 Pf = P - Pi;\n\n //\tcalculate the hash.\n //\t( various hashing methods listed in order of speed )\n vec4 hash_x0, hash_y0, hash_z0, hash_x1, hash_y1, hash_z1;\n FAST32_hash_3D( Pi, hash_x0, hash_y0, hash_z0, hash_x1, hash_y1, hash_z1 );\n //SGPP_hash_3D( Pi, hash_x0, hash_y0, hash_z0, hash_x1, hash_y1, hash_z1 );\n\n //\tgenerate the 8 random points\n#if 1\n //\trestrict the random point offset to eliminate artifacts\n //\twe'll improve the variance of the noise by pushing the points to the extremes of the jitter window\n const float JITTER_WINDOW = 0.166666666;\t// 0.166666666 will guarentee no artifacts. It is the intersection on x of graphs f(x)=( (0.5 + (0.5-x))^2 + 2*((0.5-x)^2) ) and f(x)=( 2 * (( 0.5 + x )^2) + x * x )\n hash_x0 = Cellular_weight_samples( hash_x0 ) * JITTER_WINDOW + vec4(0.0, 1.0, 0.0, 1.0);\n hash_y0 = Cellular_weight_samples( hash_y0 ) * JITTER_WINDOW + vec4(0.0, 0.0, 1.0, 1.0);\n hash_x1 = Cellular_weight_samples( hash_x1 ) * JITTER_WINDOW + vec4(0.0, 1.0, 0.0, 1.0);\n hash_y1 = Cellular_weight_samples( hash_y1 ) * JITTER_WINDOW + vec4(0.0, 0.0, 1.0, 1.0);\n hash_z0 = Cellular_weight_samples( hash_z0 ) * JITTER_WINDOW + vec4(0.0, 0.0, 0.0, 0.0);\n hash_z1 = Cellular_weight_samples( hash_z1 ) * JITTER_WINDOW + vec4(1.0, 1.0, 1.0, 1.0);\n#else\n //\tnon-weighted jitter window. jitter window of 0.4 will give results similar to Stefans original implementation\n //\tnicer looking, faster, but has minor artifacts. ( discontinuities in signal )\n const float JITTER_WINDOW = 0.4;\n hash_x0 = hash_x0 * JITTER_WINDOW * 2.0 + vec4(-JITTER_WINDOW, 1.0-JITTER_WINDOW, -JITTER_WINDOW, 1.0-JITTER_WINDOW);\n hash_y0 = hash_y0 * JITTER_WINDOW * 2.0 + vec4(-JITTER_WINDOW, -JITTER_WINDOW, 1.0-JITTER_WINDOW, 1.0-JITTER_WINDOW);\n hash_x1 = hash_x1 * JITTER_WINDOW * 2.0 + vec4(-JITTER_WINDOW, 1.0-JITTER_WINDOW, -JITTER_WINDOW, 1.0-JITTER_WINDOW);\n hash_y1 = hash_y1 * JITTER_WINDOW * 2.0 + vec4(-JITTER_WINDOW, -JITTER_WINDOW, 1.0-JITTER_WINDOW, 1.0-JITTER_WINDOW);\n hash_z0 = hash_z0 * JITTER_WINDOW * 2.0 + vec4(-JITTER_WINDOW, -JITTER_WINDOW, -JITTER_WINDOW, -JITTER_WINDOW);\n hash_z1 = hash_z1 * JITTER_WINDOW * 2.0 + vec4(1.0-JITTER_WINDOW, 1.0-JITTER_WINDOW, 1.0-JITTER_WINDOW, 1.0-JITTER_WINDOW);\n#endif\n\n //\treturn the closest squared distance\n vec4 dx1 = Pf.xxxx - hash_x0;\n vec4 dy1 = Pf.yyyy - hash_y0;\n vec4 dz1 = Pf.zzzz - hash_z0;\n vec4 dx2 = Pf.xxxx - hash_x1;\n vec4 dy2 = Pf.yyyy - hash_y1;\n vec4 dz2 = Pf.zzzz - hash_z1;\n vec4 d1 = dx1 * dx1 + dy1 * dy1 + dz1 * dz1;\n vec4 d2 = dx2 * dx2 + dy2 * dy2 + dz2 * dz2;\n d1 = min(d1, d2);\n d1.xy = min(d1.xy, d1.wz);\n return min(d1.x, d1.y) * ( 9.0 / 12.0 );\t//\tscale return value from 0.0->1.333333 to 0.0->1.0 \t(2/3)^2 * 3 == (12/9) == 1.333333\n}\n\n\nvoid main()\n{\n\n\n vec2 p=vec2(texCoord.x-0.5,texCoord.y-0.5);\n\n #ifdef DO_TILEABLE\n p=abs(texCoord-0.5);\n #endif\n\n p.x*=aspect;\n\n p=p*scale;\n\n p=vec2(p.x+0.5-x,p.y+0.5-y);\n\n vec3 offset;\n #ifdef HAS_TEX_OFFSETMAP\n vec4 offMap=texture(texOffsetZ,texCoord);\n\n #ifdef OFFSET_X_R\n offset.x=offMap.r;\n #endif\n #ifdef OFFSET_X_G\n offset.x=offMap.g;\n #endif\n #ifdef OFFSET_X_B\n offset.x=offMap.b;\n #endif\n\n #ifdef OFFSET_Y_R\n offset.y=offMap.r;\n #endif\n #ifdef OFFSET_Y_G\n offset.y=offMap.g;\n #endif\n #ifdef OFFSET_Y_B\n offset.y=offMap.b;\n #endif\n\n #ifdef OFFSET_Z_R\n offset.z=offMap.r;\n #endif\n #ifdef OFFSET_Z_G\n offset.z=offMap.g;\n #endif\n #ifdef OFFSET_Z_B\n offset.z=offMap.b;\n #endif\n\n offset*=offMul;\n\n #endif\n\n float v=Cellular3D(vec3(p.x,p.y,z)+offset);\n\n\n if (harmonics >= 2.0) v += Cellular3D(vec3(p.x,p.y,z)*2.3+offset) * 0.5;\n if (harmonics >= 3.0) v += Cellular3D(vec3(p.x,p.y,z)*4.2+offset) * 0.25;\n if (harmonics >= 4.0) v += Cellular3D(vec3(p.x,p.y,z)*8.1+offset) * 0.125;\n if (harmonics >= 5.0) v += Cellular3D(vec3(p.x,p.y,z)*16.7+offset) * 0.0625;\n\n\n vec4 col=vec4(v,v,v,1.0);\n\n vec4 base=texture(tex,texCoord);\n\n\n float str=1.0;\n #ifdef HAS_TEX_MASK\n str=texture(texMask,texCoord).r;\n #endif\n\n outColor=cgl_blendPixel(base,col,amount*str);\n\n}\n",}; +const + render = op.inTrigger("render"), + inTexMask = op.inTexture("Mask"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + + amount = op.inValueSlider("Amount", 1), + x = op.inValue("X", 0), + y = op.inValue("Y", 0), + z = op.inValue("Z", 0), + scale = op.inValue("Scale", 5), + + inHarmonics = op.inSwitch("Harmonics", ["1", "2", "3", "4", "5"], "1"), + tile = op.inValueBool("Tileable", false), + + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.cellularnoise3d_frag); + +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uniOffset = new CGL.Uniform(shader, "t", "texOffsetZ", 1), + uniMask = new CGL.Uniform(shader, "t", "texMask", 2), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + uniZ = new CGL.Uniform(shader, "f", "z", z), + uniX = new CGL.Uniform(shader, "f", "x", x), + uniY = new CGL.Uniform(shader, "f", "y", y), + uniScale = new CGL.Uniform(shader, "f", "scale", scale); + +tile.onChange = updateTileable; +function updateTileable() +{ + if (tile.get())shader.define("DO_TILEABLE"); + else shader.removeDefine("DO_TILEABLE"); +} + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount,maskAlpha); + +// offsetMap + +const + inTexOffsetTex = op.inTexture("Offset"), + inOffsetMul = op.inFloat("Offset Multiply", 1), + + offsetX = op.inSwitch("Offset X", ["None", "R", "G", "B"], "None"), + offsetY = op.inSwitch("Offset Y", ["None", "R", "G", "B"], "None"), + offsetZ = op.inSwitch("Offset Z", ["None", "R", "G", "B"], "R"); + +const uniOffMul = new CGL.Uniform(shader, "f", "offMul", inOffsetMul); + +op.setPortGroup("Offset Map", [inTexOffsetTex, offsetZ, offsetY, offsetX, inOffsetMul]); + +const uniAspect = new CGL.Uniform(shader, "f", "aspect", 1); +const uniHarmonics = new CGL.Uniform(shader, "f", "harmonics", 0); +inHarmonics.onChange = () => +{ + uniHarmonics.setValue(parseFloat(inHarmonics.get())); +}; + +offsetX.onChange = +offsetY.onChange = +offsetZ.onChange = +inTexMask.onChange = +inTexOffsetTex.onChange = updateDefines; +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("HAS_TEX_OFFSETMAP", inTexOffsetTex.get()); + shader.toggleDefine("HAS_TEX_MASK", inTexMask.get()); + + shader.toggleDefine("OFFSET_X_R", offsetX.get() == "R"); + shader.toggleDefine("OFFSET_X_G", offsetX.get() == "G"); + shader.toggleDefine("OFFSET_X_B", offsetX.get() == "B"); + + shader.toggleDefine("OFFSET_Y_R", offsetY.get() == "R"); + shader.toggleDefine("OFFSET_Y_G", offsetY.get() == "G"); + shader.toggleDefine("OFFSET_Y_B", offsetY.get() == "B"); + + shader.toggleDefine("OFFSET_Z_R", offsetZ.get() == "R"); + shader.toggleDefine("OFFSET_Z_G", offsetZ.get() == "G"); + shader.toggleDefine("OFFSET_Z_B", offsetZ.get() == "B"); + + offsetX.setUiAttribs({ "greyout": !inTexOffsetTex.isLinked() }); + offsetY.setUiAttribs({ "greyout": !inTexOffsetTex.isLinked() }); + offsetZ.setUiAttribs({ "greyout": !inTexOffsetTex.isLinked() }); +} + +// end offsetmap + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op,3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + uniAspect.setValue(cgl.currentTextureEffect.aspectRatio); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + if (inTexOffsetTex.get()) cgl.setTexture(1, inTexOffsetTex.get().tex); + if (inTexMask.get()) cgl.setTexture(2, inTexMask.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Noise.CellularNoise_v2.prototype = new CABLES.Op(); +CABLES.OPS["e0ce24fe-4ddb-4df4-a087-623cf4c711a7"]={f:Ops.Gl.TextureEffects.Noise.CellularNoise_v2,objName:"Ops.Gl.TextureEffects.Noise.CellularNoise_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Noise.FBMNoise_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Noise.FBMNoise_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"fbmnoise_frag":"UNI sampler2D tex;\nUNI float anim;\n\nUNI float scale;\nUNI float repeat;\n\nUNI float scrollX;\nUNI float scrollY;\n\nUNI float amount;\n\nUNI bool layer1;\nUNI bool layer2;\nUNI bool layer3;\nUNI bool layer4;\nUNI vec3 color;\nUNI float aspect;\n\nIN vec2 texCoord;\n\n\n{{CGL.BLENDMODES3}}\n\n// csdcsdcds\n// adapted from warp shader by inigo quilez/iq\n// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.\n\n// See here for a tutorial on how to make this: http://www.iquilezles.org/www/articles/warp/warp.htm\n\nconst mat2 m = mat2( 0.80, 0.60, -0.60, 0.80 );\n\nfloat noise( in vec2 x )\n{\n\treturn sin(1.5*x.x)*sin(1.5*x.y);\n}\n\nfloat fbm4( vec2 p )\n{\n float f = 0.0;\n f += 0.5000*noise( p ); p = m*p*2.02;\n f += 0.2500*noise( p ); p = m*p*2.03;\n f += 0.1250*noise( p ); p = m*p*2.01;\n f += 0.0625*noise( p );\n return f/0.9375;\n}\n\nfloat fbm6( vec2 p )\n{\n float f = 0.0;\n f += 0.500000*(0.5+0.5*noise( p )); p = m*p*2.02;\n f += 0.250000*(0.5+0.5*noise( p )); p = m*p*2.03;\n f += 0.125000*(0.5+0.5*noise( p )); p = m*p*2.01;\n f += 0.062500*(0.5+0.5*noise( p )); p = m*p*2.04;\n f += 0.031250*(0.5+0.5*noise( p )); p = m*p*2.01;\n f += 0.015625*(0.5+0.5*noise( p ));\n return f/0.96875;\n}\n\nvoid main()\n{\n vec2 tc=texCoord;\n\t#ifdef DO_TILEABLE\n\t tc=abs(texCoord-0.5);\n\t#endif\n\n vec2 p=(tc-0.5)*scale;\n\n p.y/=aspect;\n vec2 q = vec2( fbm4( p + vec2(0.3+scrollX,0.20+scrollY) ),\n fbm4( p + vec2(3.1+scrollX,1.3+scrollY) ) );\n\n vec2 q2 = vec2( fbm4( p + vec2(2.0+scrollX,1.0+scrollY) ),\n fbm4( p + vec2(3.1+scrollX,1.3+scrollY) ) );\n\n vec2 q3 = vec2( fbm4( p + vec2(9.0+scrollX,4.0+scrollY) ),\n fbm4( p + vec2(3.1+scrollX,4.3+scrollY) ) );\n\n float v= fbm4( ( p + 4.0*q +anim*0.1)*repeat);\n float v2= fbm4( (p + 4.0*q2 +anim*0.1)*repeat );\n\n float v3= fbm6( (p + 4.0*q3 +anim*0.1)*repeat );\n float v4= fbm6( (p + 4.0*q2 +anim*0.1)*repeat );\n\n vec4 base=texture(tex,texCoord);\n\n vec4 finalColor;\n float colVal=0.0;\n float numLayers=0.0;\n\n if(layer1)\n {\n colVal+=v;\n numLayers++;\n }\n\n if(layer2)\n {\n colVal+=v2;\n numLayers++;\n }\n\n if(layer3)\n {\n colVal+=v3;\n numLayers++;\n }\n\n if(layer4)\n {\n colVal+=v4;\n numLayers++;\n }\n\n finalColor=vec4( color*vec3(colVal/numLayers),1.0);\n\n outColor = cgl_blendPixel(base,finalColor,amount);\n}\n",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + r = op.inValueSlider("r", 1.0), + g = op.inValueSlider("g", 1.0), + b = op.inValueSlider("b", 1.0), + trigger = op.outTrigger("trigger"); + +r.setUiAttribs({ "colorPick": true }); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "fbmnoise"); + +shader.setSource(shader.getDefaultVertexShader(), attachments.fbmnoise_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uniScale = new CGL.Uniform(shader, "f", "scale", op.inValue("scale", 2)), + uniAnim = new CGL.Uniform(shader, "f", "anim", op.inValue("anim", 0)), + uniScrollX = new CGL.Uniform(shader, "f", "scrollX", op.inValue("scrollX", 9)), + uniScrollY = new CGL.Uniform(shader, "f", "scrollY", op.inValue("scrollY", 0)), + uniRepeat = new CGL.Uniform(shader, "f", "repeat", op.inValue("repeat", 1)), + uniAspect = new CGL.Uniform(shader, "f", "aspect", op.inValue("aspect", 1)), + uniLayer1 = new CGL.Uniform(shader, "b", "layer1", op.inValueBool("Layer 1", true)), + uniLayer2 = new CGL.Uniform(shader, "b", "layer2", op.inValueBool("Layer 2", true)), + uniLayer3 = new CGL.Uniform(shader, "b", "layer3", op.inValueBool("Layer 3", true)), + uniLayer4 = new CGL.Uniform(shader, "b", "layer4", op.inValueBool("Layer 4", true)), + uniColor = new CGL.Uniform(shader, "3f", "color", r, g, b), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +const tile = op.inValueBool("Tileable", false); +tile.onChange = updateTileable; + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +function updateTileable() +{ + shader.toggleDefine("DO_TILEABLE", tile.get()); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + uniAspect.set(cgl.currentTextureEffect.getCurrentSourceTexture().width / cgl.currentTextureEffect.getCurrentSourceTexture().height); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Noise.FBMNoise_v2.prototype = new CABLES.Op(); +CABLES.OPS["9422eeab-b6c5-47d1-8737-d5c43dc137a3"]={f:Ops.Gl.TextureEffects.Noise.FBMNoise_v2,objName:"Ops.Gl.TextureEffects.Noise.FBMNoise_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Noise.GlitchNoise_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Noise.GlitchNoise_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"glitchnoise_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\n\n{{CGL.BLENDMODES3}}\n\nUNI float amount;\nUNI float time;\nUNI float frequency;\nUNI float strength;\nUNI float blockSizeA;\nUNI float blockSizeB;\nUNI float blockSizeC;\nUNI float blockSizeD;\nUNI float scrollX;\nUNI float scrollY;\n\nfloat rng2(vec2 seed)\n{\n return fract(sin(dot(seed * floor(time * (frequency * 10.0)), vec2(127.1,311.7))) * 43758.5453123);//43758.5453123\n}\n\nfloat rng(float seed)\n{\n return rng2(vec2(seed, 1.0));\n}\n\nvoid main( )\n{\n //add scroll for x and y\n vec2 scrollXY = vec2(scrollX,scrollY);\n vec2 blockS = floor((texCoord + scrollXY ) * vec2(blockSizeA,blockSizeB));\n vec2 blockL = floor((texCoord ) * vec2(blockSizeC,blockSizeD));\n\n float r = rng2(texCoord);\n vec3 noise = (vec3(r, 1. - r, r / 2. + 0.5) * 1.0 - 2.0) * 0.08;\n\n float lineNoise = pow(rng2(blockS), 8.0) * pow(rng2(blockL), 3.0) - pow(rng(7.2341), 17.0) * 2.;\n\n vec4 col1 = texture(tex, texCoord);\n vec4 col2 = texture(tex, texCoord + vec2(lineNoise * (0.05 * strength) * rng(5.0), 1));\n vec4 col3 = texture(tex, texCoord - vec2(lineNoise * (0.05 * strength) * rng(31.0), 1));\n\n float glitch = (lineNoise * strength * rng(5.0)) + (lineNoise * strength * rng(31.));\n float glitch2 = lineNoise * strength * rng(31.);\n\n //blend section\n vec4 col=vec4(vec3(glitch),1.0);\n //original texture\n vec4 base=texture(tex,texCoord);\n\n outColor=cgl_blendPixel(base,col,amount);\n\n}",}; +const + render = op.inTrigger("render"), + amount = op.inValueSlider("Amount", 1), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + + time = op.inValue("Seed", 0), + inFrequency = op.inValue("frequency", 1), + inStrength = op.inValue("strength", 8.0), + inBlockSizeA = op.inValue("Block size small x", 24.0), + inBlockSizeB = op.inValue("Block size small y", 9.0), + inBlockSizeC = op.inValue("Block size large x", 8.0), + inBlockSizeD = op.inValue("Block size large y", 4.0), + inScrollX = op.inValue("Scroll X", 0.0), + inScrollY = op.inValue("Scroll Y", 0.0), + trigger = op.outTrigger("trigger"); + +const TEX_SLOT = 0; +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); +shader.setSource(shader.getDefaultVertexShader(), attachments.glitchnoise_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", TEX_SLOT), + uniformAmount = new CGL.Uniform(shader, "f", "amount", amount), + timeUniform = new CGL.Uniform(shader, "f", "time", time), + frequencyUniform = new CGL.Uniform(shader, "f", "frequency", inFrequency), + strengthUniform = new CGL.Uniform(shader, "f", "strength", inStrength), + sizeAUniform = new CGL.Uniform(shader, "f", "blockSizeA", inBlockSizeA), + sizeBUniform = new CGL.Uniform(shader, "f", "blockSizeB", inBlockSizeB), + sizeCUniform = new CGL.Uniform(shader, "f", "blockSizeC", inBlockSizeC), + sizeDUniform = new CGL.Uniform(shader, "f", "blockSizeD", inBlockSizeD), + scrollXUniform = new CGL.Uniform(shader, "f", "scrollX", inScrollX), + scrollYUniform = new CGL.Uniform(shader, "f", "scrollY", inScrollY); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(TEX_SLOT, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Noise.GlitchNoise_v2.prototype = new CABLES.Op(); +CABLES.OPS["87de572e-644a-4613-b0f3-68b9ec74f489"]={f:Ops.Gl.TextureEffects.Noise.GlitchNoise_v2,objName:"Ops.Gl.TextureEffects.Noise.GlitchNoise_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Noise.HexagonNoise_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Noise.HexagonNoise_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"hexnoise_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float scale;\nUNI float addX;\nUNI float addY;\nUNI float addZ;\nUNI float seed2;\nUNI float minIn;\nUNI float maxIn;\n\nUNI float aspect;\n{{CGL.BLENDMODES3}}\n\n\n#define PI 3.14159265\n#define TAU (2.0*PI)\n\nvoid pR(inout vec2 p, float a)\n{\n\tp = cos(a)*p + sin(a)*vec2(p.y, -p.x);\n}\n\n//cell code from https://www.shadertoy.com/view/lldfWH\nvec4 hex(vec2 uv, out vec2 id)\n{\n // #ifdef ASPECT\n uv.x*=aspect;\n // #endif\n\n uv *= mat2(1.1547,0.0,-0.5773503,1.0);\n vec2 f = fract(uv);\n float triid = 1.0;\n\tif((f.x+f.y) > 1.0) { f = 1.0 - f; triid = -1.0; }\n\n vec2 co = step(f.yx,f) * step(1.0-f.x-f.y,max(f.x,f.y));\n id = floor(uv) + (triid < 0.0 ? 1.0 - co : co);\n co = (f - co) * triid * mat2(0.866026,0.0,0.5,1.0);\n\n uv = abs(co);\n return vec4(0.5-max(uv.y,abs(dot(vec2(0.866026,0.5),uv))),length(co),co);\n}\n\nfloat random(vec2 co)\n{\n float r=fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * (5.711+(mod(addZ+5711.210,57.0))));\n\n #ifdef LOOP\n r=abs(r-0.5)*2.0;\n #endif\n\n return r;\n}\n\n\nvoid main()\n{\n vec2 uv = texCoord;\n uv -= 0.5;\n uv -= vec2(addX,addY);\n uv*=scale;\n\n #ifdef FLIP\n pR(uv.xy,0.25*TAU);\n #endif\n\n float r,g,b;\n vec4 rnd = vec4(0.0);\n\n // get hexagon cell id\n vec2 id0;\n vec4 h = hex(uv*4.0, id0);\n\n #ifndef RGB\n r=g=b= random(id0.xy*id0.xy+seed2);\n #endif\n\n #ifdef RGB\n r = random(((id0.xy*id0.xy)*0.234)+seed2);\n g = random(((id0.xy*id0.xy)*0.234)+seed2+0.9812);\n b = random(((id0.xy*id0.xy)*0.234)+seed2+57.101);\n #endif\n\n rnd = clamp( vec4( r,g,b,1.0 ),vec4(minIn), vec4(maxIn) );\n vec4 base=texture(tex,texCoord);\n\n outColor=cgl_blendPixel(base,rnd,amount);\n}\n\n//",}; +const + render = op.inTrigger("Render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + inLoop = op.inValueBool("Loop", false), + inRGB = op.inValueBool("RGB", false), + minValue = op.inValue("Minimum value", 0), + maxValue = op.inValue("Maximum value", 1), + scale = op.inValue("Scale", 3), + orientation = op.inBool("Orientation", false), + addX = op.inValue("X", 0), + addY = op.inValue("Y", 0), + addZ = op.inValue("Z", 0), + seed2 = op.inValue("Seed", 0), + trigger = op.outTrigger("Next"); + +op.setPortGroup("Look", [inRGB, inLoop, minValue, maxValue]); +op.setPortGroup("Position", [addX, addY, addZ]); +op.setPortGroup("Position", [addX, addY, addZ]); +op.setPortGroup("", [scale, orientation]); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); +shader.setSource(shader.getDefaultVertexShader(), attachments.hexnoise_frag); + +const + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + timeUniform = new CGL.Uniform(shader, "f", "time", 1.0), + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uni_scale = new CGL.Uniform(shader, "f", "scale", scale), + uni_addX = new CGL.Uniform(shader, "f", "addX", addX), + uni_addY = new CGL.Uniform(shader, "f", "addY", addY), + uni_addZ = new CGL.Uniform(shader, "f", "addZ", addZ), + uni_seed = new CGL.Uniform(shader, "f", "seed2", seed2), + uni_minValue = new CGL.Uniform(shader, "f", "minIn", minValue), + uni_maxValue = new CGL.Uniform(shader, "f", "maxIn", maxValue), + uni_asp = new CGL.Uniform(shader, "f", "aspect", 1); + +inLoop.onChange = +inRGB.onChange = +orientation.onChange = updateDefines; + +function updateDefines() +{ + shader.toggleDefine("FLIP", orientation.get()); + shader.toggleDefine("RGB", inRGB.get()); + shader.toggleDefine("LOOP", inLoop.get()); +} + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + uni_asp.setValue(cgl.currentTextureEffect.aspectRatio); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Noise.HexagonNoise_v2.prototype = new CABLES.Op(); +CABLES.OPS["1c4def10-3574-4ef7-8abc-de28d2293095"]={f:Ops.Gl.TextureEffects.Noise.HexagonNoise_v2,objName:"Ops.Gl.TextureEffects.Noise.HexagonNoise_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Noise.LayerNoise_v3 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Noise.LayerNoise_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"layernoise_frag":"// @author Jan Scheurer - Xe-Development UG\n// @copyright undefined development UG\n\n{{MODULES_HEAD}}\n\nUNI int mode;\nUNI vec4 attribs;\nUNI vec3 scroll;\nUNI bool rgba;\nUNI float amount;\nIN vec2 texCoord;\nUNI sampler2D tex;\nUNI float aspect;\n\n{{CGL.BLENDMODES3}}\n\n#define LINEAR 0\n#define EXPONENTIAL 1\n#define LOGARITHMIC 2\n\nfloat rand (vec3 p) {\n return fract(sin(dot(p,vec3(12.4085,48.512313,32.6143)))*42754.71415);\n}\n\nconst vec2 O = vec2(0,1);\n\nfloat noise (vec3 p) {\n vec3 b=floor(p),f=fract(p);\n return mix(\n mix(mix(rand(b+O.xxx),rand(b+O.yxx),f.x),mix(rand(b+O.xyx),rand(b+O.yyx),f.x),f.y),\n mix(mix(rand(b+O.xxy),rand(b+O.yxy),f.x),mix(rand(b+O.xyy),rand(b+O.yyy),f.x),f.y),\n f.z\n );\n}\n\nfloat gn(vec3 p){\n float n = 0., fi;\n int numLayers = int(attribs.g);\n for (int i = 1; i < 100; i++) {\n if (i > numLayers) break;\n if (mode == LINEAR)\n fi = float(i),p+=attribs.r;\n else if (mode == EXPONENTIAL)\n fi = float(pow(float(i),attribs.a));\n else if (mode == LOGARITHMIC)\n fi = log(float(i+1)),p+=attribs.r;\n n += noise(p*fi) / fi;\n }\n return n*attribs.b;\n}\n\nvoid main()\n{\n vec4 base=texture(tex,texCoord);\n vec2 tc=texCoord;\n tc.y/=aspect;\n\n\t#ifdef DO_TILEABLE\n\t tc=abs(texCoord-0.5);\n\t#endif\n vec3 p = vec3(tc * 2. - 1.,0) + scroll;\n vec4 col;\n if (rgba)\n {\n for(int i = 0; i < 4; i++)\n {\n col[i] = gn(p*attribs.r);\n p += attribs.r;\n }\n } else col = vec4(vec3(gn(p*attribs.r)),1);\n\n outColor=cgl_blendPixel(base,col,amount);\n}",}; +const cgl = op.patch.cgl; + +// inputs +const + inTrigger = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inFloatSlider("Amount", 1), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + inLayerMode = op.inValueSelect("mode", [ + "exponential", + "logarithmic", + "linear" + ], "exponential"), + inRGBA = op.inValueBool("RGBA"), + inScale = op.inValue("scale", 7), + inNumLayers = op.inValueInt("layers", 3), + inFactor = op.inFloat("factor", 1), + inExponent = op.inFloat("exponent", 2), + inScrollX = op.inFloat("scrollX"), + inScrollY = op.inFloat("scrollY"), + inScrollZ = op.inFloat("scrollZ"), + tile = op.inValueBool("Tileable", false), + outTrigger = op.outTrigger("trigger"); + +// locals +const TEX_SLOT = 0; +const shader = new CGL.Shader(cgl, "layernoise"); +const attribs = [inScale.get(), inNumLayers.get(), inFactor.get(), 0]; +shader.setSource(shader.getDefaultVertexShader(), attachments.layernoise_frag); +const attributes = new CGL.Uniform(shader, "4f", "attribs", attribs); + +const uniMode = new CGL.Uniform(shader, "i", "mode", 2); +shader._addUniform(uniMode); +const uniRGBA = new CGL.Uniform(shader, "b", "rgba", false); +const scrollArr = [inScrollX.get(), inScrollY.get(), inScrollZ.get()]; +const uniScroll = new CGL.Uniform(shader, "3f", "scroll", scrollArr); +const uniformAmount = new CGL.Uniform(shader, "f", "amount", amount); +const uniAspect = new CGL.Uniform(shader, "f", "aspect", 1); +const textureUniform = new CGL.Uniform(shader, "t", "tex", TEX_SLOT); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +let needsUpdate = false; +// events + +tile.onChange = updateTileable; + +inTrigger.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + if (needsUpdate) + { + attribs[0] = inScale.get(); + attribs[1] = inNumLayers.get(); + + const layerMode = inLayerMode.get(); + if (layerMode == "linear") + uniMode.set(0); + else if (layerMode == "exponential") + uniMode.set(1); + else + uniMode.set(2); + + attribs[2] = inFactor.get(); + attribs[3] = inExponent.get(); + attributes.set(attribs); + + uniRGBA.set(inRGBA.get()); + scroll[0] = inScrollX.get(); + scroll[1] = inScrollY.get(); + scroll[2] = inScrollZ.get(); + uniScroll.set(scroll); + + needsUpdate = false; + } + + uniAspect.setValue(cgl.currentTextureEffect.aspectRatio); + + cgl.setTexture(TEX_SLOT, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + cgl.currentTextureEffect.finish(); + cgl.popShader(); + outTrigger.trigger(); +}; + +function updateTileable() +{ + shader.toggleDefine("DO_TILEABLE", tile.get()); +} + +inScale.onChange = + inNumLayers.onChange = + inLayerMode.onChange = + inExponent.onChange = + inFactor.onChange = + inRGBA.onChange = + inScrollX.onChange = + inScrollY.onChange = + inScrollZ.onChange = update; +function update() +{ + needsUpdate = true; +} +update(); + + +}; + +Ops.Gl.TextureEffects.Noise.LayerNoise_v3.prototype = new CABLES.Op(); +CABLES.OPS["b918b3f1-53ee-4d32-92b7-73a1d00e0d69"]={f:Ops.Gl.TextureEffects.Noise.LayerNoise_v3,objName:"Ops.Gl.TextureEffects.Noise.LayerNoise_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Noise.Noise_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Noise.Noise_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"noise_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float time;\n\n#ifdef HAS_MULMASK\n UNI sampler2D texMul;\n#endif\n\n{{CGL.BLENDMODES3}}\n{{MODULES_HEAD}}\n\n{{CGL.RANDOM_TEX}}\n\nvoid main()\n{\n vec4 rnd;\n\n #ifdef RGB\n rnd=vec4(cgl_random3(texCoord.xy+vec2(time)),1.0);\n #else\n float r=cgl_random(texCoord.xy+vec2(time));\n rnd=vec4( r,r,r,1.0 );\n #endif\n\n vec4 base=texture(tex,texCoord);\n vec4 col=rnd;//( _blend(base.rgb,rnd.rgb) ,1.0);\n\n #ifdef NORMALIZE\n col.rgb=(col.rgb-0.5)*2.0;\n #endif\n\n #ifdef HAS_MULMASK\n col.rgb*=texture(texMul,texCoord).rgb;\n #endif\n\n outColor=cgl_blendPixel(base,col,amount);\n // outColor=vec4( mix( col.rgb, base.rgb ,1.0-base.a*amount),1.0);\n}",}; +const + render = op.inTrigger("Render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + amount = op.inValueSlider("Amount", 1), + animated = op.inValueBool("Animated", true), + inRGB = op.inValueBool("RGB", false), + normalize = op.inValueBool("Normalize", false), + inTexMul = op.inTexture("Multiply"), + trigger = op.outTrigger("Next"); + +const + cgl = op.patch.cgl, + shader = new CGL.Shader(cgl, op.name), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + timeUniform = new CGL.Uniform(shader, "f", "time", 1.0), + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + mulUniform = new CGL.Uniform(shader, "t", "texMul", 1); + +shader.setSource(shader.getDefaultVertexShader(), attachments.noise_frag); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount,maskAlpha); + +op.toWorkPortsNeedToBeLinked(render); + +inTexMul.onChange = +normalize.onChange = +inRGB.onChange = function () +{ + shader.toggleDefine("HAS_MULMASK", inTexMul.get()); + shader.toggleDefine("RGB", inRGB.get()); + shader.toggleDefine("NORMALIZE", normalize.get()); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op,3)) return; + + if (animated.get()) timeUniform.setValue(op.patch.freeTimer.get() / 1000 % 100); + else timeUniform.setValue(0); + + cgl.pushShader(shader); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + if (inTexMul.get())cgl.setTexture(1, inTexMul.get().tex); + + cgl.currentTextureEffect.bind(); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Noise.Noise_v2.prototype = new CABLES.Op(); +CABLES.OPS["b1d9aacc-dc52-43a6-a00f-414f08768800"]={f:Ops.Gl.TextureEffects.Noise.Noise_v2,objName:"Ops.Gl.TextureEffects.Noise.Noise_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Noise.PerlinNoise_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Noise.PerlinNoise_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"perlinnoise3d_frag":"UNI float z;\nUNI float x;\nUNI float y;\nUNI float scale;\nUNI float rangeMul;\nUNI float harmonics;\nUNI float aspect;\n\nIN vec2 texCoord;\nUNI sampler2D tex;\n\n#ifdef HAS_TEX_OFFSETMAP\n UNI sampler2D texOffsetZ;\n UNI float offMul;\n#endif\n\n#ifdef HAS_TEX_MASK\n UNI sampler2D texMask;\n#endif\n\nUNI float amount;\n\n{{CGL.BLENDMODES3}}\n\n\nfloat Interpolation_C2( float x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); } // 6x^5-15x^4+10x^3\t( Quintic Curve. As used by Perlin in Improved Noise. http://mrl.nyu.edu/~perlin/paper445.pdf )\nvec2 Interpolation_C2( vec2 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec3 Interpolation_C2( vec3 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2( vec4 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2_InterpAndDeriv( vec2 x ) { return x.xyxy * x.xyxy * ( x.xyxy * ( x.xyxy * ( x.xyxy * vec2( 6.0, 0.0 ).xxyy + vec2( -15.0, 30.0 ).xxyy ) + vec2( 10.0, -60.0 ).xxyy ) + vec2( 0.0, 30.0 ).xxyy ); }\nvec3 Interpolation_C2_Deriv( vec3 x ) { return x * x * (x * (x * 30.0 - 60.0) + 30.0); }\n\n\nvoid FAST32_hash_3D( vec3 gridcell, out vec4 lowz_hash, out vec4 highz_hash )\t//\tgenerates a random number for each of the 8 cell corners\n{\n // gridcell is assumed to be an integer coordinate\n\n //\tTODO: \tthese constants need tweaked to find the best possible noise.\n //\t\t\tprobably requires some kind of brute force computational searching or something....\n const vec2 OFFSET = vec2( 50.0, 161.0 );\n const float DOMAIN = 69.0;\n const float SOMELARGEFLOAT = 635.298681;\n const float ZINC = 48.500388;\n\n //\ttruncate the domain\n gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;\n vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );\n\n //\tcalculate the noise\n vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;\n P *= P;\n P = P.xzxz * P.yyww;\n highz_hash.xy = vec2( 1.0 / ( SOMELARGEFLOAT + vec2( gridcell.z, gridcell_inc1.z ) * ZINC ) );\n lowz_hash = fract( P * highz_hash.xxxx );\n highz_hash = fract( P * highz_hash.yyyy );\n}\n\n\n\n\nvoid FAST32_hash_3D( \tvec3 gridcell,\n out vec4 lowz_hash_0,\n out vec4 lowz_hash_1,\n out vec4 lowz_hash_2,\n out vec4 highz_hash_0,\n out vec4 highz_hash_1,\n out vec4 highz_hash_2\t)\t\t//\tgenerates 3 random numbers for each of the 8 cell corners\n{\n // gridcell is assumed to be an integer coordinate\n\n //\tTODO: \tthese constants need tweaked to find the best possible noise.\n //\t\t\tprobably requires some kind of brute force computational searching or something....\n const vec2 OFFSET = vec2( 50.0, 161.0 );\n const float DOMAIN = 69.0;\n const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );\n const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );\n\n //\ttruncate the domain\n gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;\n vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );\n\n //\tcalculate the noise\n vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;\n P *= P;\n P = P.xzxz * P.yyww;\n vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );\n vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );\n lowz_hash_0 = fract( P * lowz_mod.xxxx );\n highz_hash_0 = fract( P * highz_mod.xxxx );\n lowz_hash_1 = fract( P * lowz_mod.yyyy );\n highz_hash_1 = fract( P * highz_mod.yyyy );\n lowz_hash_2 = fract( P * lowz_mod.zzzz );\n highz_hash_2 = fract( P * highz_mod.zzzz );\n}\nfloat Falloff_Xsq_C1( float xsq ) { xsq = 1.0 - xsq; return xsq*xsq; }\t// ( 1.0 - x*x )^2 ( Used by Humus for lighting falloff in Just Cause 2. GPUPro 1 )\nfloat Falloff_Xsq_C2( float xsq ) { xsq = 1.0 - xsq; return xsq*xsq*xsq; }\t// ( 1.0 - x*x )^3. NOTE: 2nd derivative is 0.0 at x=1.0, but non-zero at x=0.0\nvec4 Falloff_Xsq_C2( vec4 xsq ) { xsq = 1.0 - xsq; return xsq*xsq*xsq; }\n\n\n//\n//\tPerlin Noise 3D ( gradient noise )\n//\tReturn value range of -1.0->1.0\n//\thttp://briansharpe.files.wordpress.com/2011/11/perlinsample.jpg\n//\nfloat Perlin3D( vec3 P )\n{\n //\testablish our grid cell and unit position\n vec3 Pi = floor(P);\n vec3 Pf = P - Pi;\n vec3 Pf_min1 = Pf - 1.0;\n\n#if 1\n //\n //\tclassic noise.\n //\trequires 3 random values per point. with an efficent hash function will run faster than improved noise\n //\n\n //\tcalculate the hash.\n //\t( various hashing methods listed in order of speed )\n vec4 hashx0, hashy0, hashz0, hashx1, hashy1, hashz1;\n FAST32_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n //SGPP_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );\n\n //\tcalculate the gradients\n vec4 grad_x0 = hashx0 - 0.49999;\n vec4 grad_y0 = hashy0 - 0.49999;\n vec4 grad_z0 = hashz0 - 0.49999;\n vec4 grad_x1 = hashx1 - 0.49999;\n vec4 grad_y1 = hashy1 - 0.49999;\n vec4 grad_z1 = hashz1 - 0.49999;\n vec4 grad_results_0 = inversesqrt( grad_x0 * grad_x0 + grad_y0 * grad_y0 + grad_z0 * grad_z0 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x0 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y0 + Pf.zzzz * grad_z0 );\n vec4 grad_results_1 = inversesqrt( grad_x1 * grad_x1 + grad_y1 * grad_y1 + grad_z1 * grad_z1 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x1 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y1 + Pf_min1.zzzz * grad_z1 );\n\n#if 1\n //\tClassic Perlin Interpolation\n vec3 blend = Interpolation_C2( Pf );\n vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n float final = dot( res0, blend2.zxzx * blend2.wwyy );\n final *= 1.1547005383792515290182975610039;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range *= 1.0/sqrt(0.75)\n return final;\n#else\n //\tClassic Perlin Surflet\n //\thttp://briansharpe.wordpress.com/2012/03/09/modifications-to-classic-perlin-noise/\n Pf *= Pf;\n Pf_min1 *= Pf_min1;\n vec4 vecs_len_sq = vec4( Pf.x, Pf_min1.x, Pf.x, Pf_min1.x ) + vec4( Pf.yy, Pf_min1.yy );\n float final = dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf.zzzz ) ), grad_results_0 ) + dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf_min1.zzzz ) ), grad_results_1 );\n final *= 2.3703703703703703703703703703704;\t\t//\t(optionally) scale things to a strict -1.0->1.0 range *= 1.0/cube(0.75)\n return final;\n#endif\n\n#else\n //\n //\timproved noise.\n //\trequires 1 random value per point. Will run faster than classic noise if a slow hashing function is used\n //\n\n //\tcalculate the hash.\n //\t( various hashing methods listed in order of speed )\n vec4 hash_lowz, hash_highz;\n FAST32_hash_3D( Pi, hash_lowz, hash_highz );\n //BBS_hash_3D( Pi, hash_lowz, hash_highz );\n //SGPP_hash_3D( Pi, hash_lowz, hash_highz );\n\n //\n //\t\"improved\" noise using 8 corner gradients. Faster than the 12 mid-edge point method.\n //\tKen mentions using diagonals like this can cause \"clumping\", but we'll live with that.\n //\t[1,1,1] [-1,1,1] [1,-1,1] [-1,-1,1]\n //\t[1,1,-1] [-1,1,-1] [1,-1,-1] [-1,-1,-1]\n //\n hash_lowz -= 0.5;\n vec4 grad_results_0_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_lowz );\n hash_lowz = abs( hash_lowz ) - 0.25;\n vec4 grad_results_0_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_lowz );\n vec4 grad_results_0_2 = Pf.zzzz * sign( abs( hash_lowz ) - 0.125 );\n vec4 grad_results_0 = grad_results_0_0 + grad_results_0_1 + grad_results_0_2;\n\n hash_highz -= 0.5;\n vec4 grad_results_1_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_highz );\n hash_highz = abs( hash_highz ) - 0.25;\n vec4 grad_results_1_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_highz );\n vec4 grad_results_1_2 = Pf_min1.zzzz * sign( abs( hash_highz ) - 0.125 );\n vec4 grad_results_1 = grad_results_1_0 + grad_results_1_1 + grad_results_1_2;\n\n //\tblend the gradients and return\n vec3 blend = Interpolation_C2( Pf );\n vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );\n vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n return dot( res0, blend2.zxzx * blend2.wwyy ) * (2.0 / 3.0);\t//\t(optionally) mult by (2.0/3.0) to scale to a strict -1.0->1.0 range\n#endif\n}\n\nvoid main()\n{\n vec4 base=texture(tex,texCoord);\n vec2 p=vec2(texCoord.x-0.5,texCoord.y-0.5);\n\n p=p*scale;\n p=vec2(p.x+0.5-x,p.y+0.5-y);\n\n\n\n vec3 offset;\n #ifdef HAS_TEX_OFFSETMAP\n vec4 offMap=texture(texOffsetZ,texCoord);\n\n #ifdef OFFSET_X_R\n offset.x=offMap.r;\n #endif\n #ifdef OFFSET_X_G\n offset.x=offMap.g;\n #endif\n #ifdef OFFSET_X_B\n offset.x=offMap.b;\n #endif\n\n #ifdef OFFSET_Y_R\n offset.y=offMap.r;\n #endif\n #ifdef OFFSET_Y_G\n offset.y=offMap.g;\n #endif\n #ifdef OFFSET_Y_B\n offset.y=offMap.b;\n #endif\n\n #ifdef OFFSET_Z_R\n offset.z=offMap.r;\n #endif\n #ifdef OFFSET_Z_G\n offset.z=offMap.g;\n #endif\n #ifdef OFFSET_Z_B\n offset.z=offMap.b;\n #endif\n offset*=offMul;\n #endif\n\n float aa=texture(tex,texCoord).r;\n\n float v = 0.0;\n p.x*=aspect;\n\n v+=Perlin3D(vec3(p.x,p.y,z)+offset);\n\n #ifdef HARMONICS\n if (harmonics >= 2.0) v += Perlin3D(vec3(p.x,p.y,z)*2.2+offset) * 0.5;\n if (harmonics >= 3.0) v += Perlin3D(vec3(p.x,p.y,z)*4.3+offset) * 0.25;\n if (harmonics >= 4.0) v += Perlin3D(vec3(p.x,p.y,z)*8.4+offset) * 0.125;\n if (harmonics >= 5.0) v += Perlin3D(vec3(p.x,p.y,z)*16.5+offset) * 0.0625;\n #endif\n\n\n v*=rangeMul;\n v=v*0.5+0.5;\n float v2=v;\n float v3=v;\n\n #ifdef RGB\n v2=Perlin3D(vec3(p.x+2.0,p.y+2.0,z))*0.5+0.5;\n\n #ifdef HARMONICS\n if (harmonics >= 2.0) v2 += Perlin3D(vec3(p.x,p.y,z)*2.2+offset) * 0.5;\n if (harmonics >= 3.0) v2 += Perlin3D(vec3(p.x,p.y,z)*4.3+offset) * 0.25;\n if (harmonics >= 4.0) v2 += Perlin3D(vec3(p.x,p.y,z)*8.4+offset) * 0.125;\n if (harmonics >= 5.0) v2 += Perlin3D(vec3(p.x,p.y,z)*16.5+offset) * 0.0625;\n #endif\n\n v3=Perlin3D(vec3(p.x+3.0,p.y+3.0,z))*0.5+0.5;\n\n #ifdef HARMONICS\n if (harmonics >= 2.0) v3 += Perlin3D(vec3(p.x,p.y,z)*2.2+offset) * 0.5;\n if (harmonics >= 3.0) v3 += Perlin3D(vec3(p.x,p.y,z)*4.3+offset) * 0.25;\n if (harmonics >= 4.0) v3 += Perlin3D(vec3(p.x,p.y,z)*8.4+offset) * 0.125;\n if (harmonics >= 5.0) v3 += Perlin3D(vec3(p.x,p.y,z)*16.5+offset) * 0.0625;\n #endif\n\n #endif\n\n vec4 col=vec4(v,v2,v3,1.0);\n\n float str=1.0;\n #ifdef HAS_TEX_MASK\n str=texture(texMask,texCoord).r;\n #endif\n\n col=cgl_blendPixel(base,col,amount*str);\n\n\n #ifdef NO_CHANNEL_R\n col.r=base.r;\n #endif\n #ifdef NO_CHANNEL_G\n col.g=base.g;\n #endif\n #ifdef NO_CHANNEL_B\n col.b=base.b;\n #endif\n\n\n\n outColor=col;\n}\n",}; +const + render = op.inTrigger("render"), + inTexMask = op.inTexture("Mask"), + blendMode = CGL.TextureEffect.AddBlendSelect(op), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + amount = op.inValueSlider("Amount", 1), + inMode = op.inSwitch("Color", ["Mono", "RGB", "R", "G", "B"], "Mono"), + scale = op.inValue("Scale", 8), + rangeMul = op.inValue("Multiply", 1), + inHarmonics = op.inSwitch("Harmonics", ["1", "2", "3", "4", "5"], "1"), + x = op.inValue("X", 0), + y = op.inValue("Y", 0), + z = op.inValue("Z", 0), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "perlinnoise"); + +op.setPortGroup("Position", [x, y, z]); + +shader.setSource(shader.getDefaultVertexShader(), attachments.perlinnoise3d_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + textureUniformOffZ = new CGL.Uniform(shader, "t", "texOffsetZ", 1), + textureUniformMask = new CGL.Uniform(shader, "t", "texMask", 2), + + uniZ = new CGL.Uniform(shader, "f", "z", z), + uniX = new CGL.Uniform(shader, "f", "x", x), + uniY = new CGL.Uniform(shader, "f", "y", y), + uniScale = new CGL.Uniform(shader, "f", "scale", scale), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + rangeMulUniform = new CGL.Uniform(shader, "f", "rangeMul", rangeMul); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +// offsetMap + +const + inTexOffsetZ = op.inTexture("Offset"), + inOffsetMul = op.inFloat("Offset Multiply", 1), + offsetX = op.inSwitch("Offset X", ["None", "R", "G", "B"], "None"), + offsetY = op.inSwitch("Offset Y", ["None", "R", "G", "B"], "None"), + offsetZ = op.inSwitch("Offset Z", ["None", "R", "G", "B"], "R"); + +op.setPortGroup("Offset Map", [inTexOffsetZ, offsetZ, offsetY, offsetX, inOffsetMul]); + +const uniOffMul = new CGL.Uniform(shader, "f", "offMul", inOffsetMul); + +const uniAspect = new CGL.Uniform(shader, "f", "aspect", 1); +const uniHarmonics = new CGL.Uniform(shader, "f", "harmonics", 0); + +inHarmonics.onChange = () => +{ + uniHarmonics.setValue(parseFloat(inHarmonics.get())); + shader.toggleDefine("HARMONICS", inHarmonics.get() > 1); +}; + +offsetX.onChange = +offsetY.onChange = +offsetZ.onChange = +inTexMask.onChange = +inMode.onChange = +inTexOffsetZ.onChange = updateDefines; +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("NO_CHANNEL_R", inMode.get() == "G" || inMode.get() == "B"); + shader.toggleDefine("NO_CHANNEL_G", inMode.get() == "R" || inMode.get() == "B"); + shader.toggleDefine("NO_CHANNEL_B", inMode.get() == "R" || inMode.get() == "G"); + + shader.toggleDefine("HAS_TEX_OFFSETMAP", inTexOffsetZ.get()); + shader.toggleDefine("HAS_TEX_MASK", inTexMask.get()); + + shader.toggleDefine("OFFSET_X_R", offsetX.get() == "R"); + shader.toggleDefine("OFFSET_X_G", offsetX.get() == "G"); + shader.toggleDefine("OFFSET_X_B", offsetX.get() == "B"); + + shader.toggleDefine("OFFSET_Y_R", offsetY.get() == "R"); + shader.toggleDefine("OFFSET_Y_G", offsetY.get() == "G"); + shader.toggleDefine("OFFSET_Y_B", offsetY.get() == "B"); + + shader.toggleDefine("OFFSET_Z_R", offsetZ.get() == "R"); + shader.toggleDefine("OFFSET_Z_G", offsetZ.get() == "G"); + shader.toggleDefine("OFFSET_Z_B", offsetZ.get() == "B"); + + offsetX.setUiAttribs({ "greyout": !inTexOffsetZ.isLinked() }); + offsetY.setUiAttribs({ "greyout": !inTexOffsetZ.isLinked() }); + offsetZ.setUiAttribs({ "greyout": !inTexOffsetZ.isLinked() }); + inOffsetMul.setUiAttribs({ "greyout": !inTexOffsetZ.isLinked() }); + + shader.toggleDefine("RGB", inMode.get() == "RGB"); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + uniAspect.setValue(cgl.currentTextureEffect.aspectRatio); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + if (inTexOffsetZ.get()) cgl.setTexture(1, inTexOffsetZ.get().tex); + if (inTexMask.get()) cgl.setTexture(2, inTexMask.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Noise.PerlinNoise_v2.prototype = new CABLES.Op(); +CABLES.OPS["b4b238d3-db68-4206-8dc7-4b52433fc932"]={f:Ops.Gl.TextureEffects.Noise.PerlinNoise_v2,objName:"Ops.Gl.TextureEffects.Noise.PerlinNoise_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Noise.PixelNoise_v3 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Noise.PixelNoise_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"pixelnoise2_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float numX;\nUNI float numY;\nUNI float addX;\nUNI float addY;\nUNI float addZ;\nUNI float seed2;\nUNI float minIn;\nUNI float maxIn;\n\nfloat random(vec2 co)\n{\n float r=fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * (5.711+(mod(addZ+5711.210,57111.0))));\n\n #ifdef LOOP\n r=abs(r-0.5)*2.0;\n #endif\n\n return r;\n}\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n vec2 seed=vec2(0.0);\n\n #ifndef CENTER\n seed=vec2(floor( texCoord.x*numX+addX),floor( texCoord.y*numY+addY));\n #endif\n #ifdef CENTER\n seed=vec2(floor( (texCoord.x-0.5)*numX+addX),floor( (texCoord.y-0.5)*numY+addY));\n #endif\n\n float r,g,b;\n\n #ifndef RGB\n r=g=b=random( seed + 0.5711 + seed2 );\n #endif\n\n #ifdef RGB\n r=random( seed+0.5711 + seed2);\n g=random( seed+0.5712 + seed2);\n b=random( seed+0.5713 + seed2);\n #endif\n\n vec4 rnd = clamp( vec4( r,g,b,1.0 ),vec4(minIn), vec4(maxIn) );\n\n vec4 base=texture(tex,texCoord);\n\n outColor=cgl_blendPixel(base,rnd,amount);\n\n}",}; +const + render = op.inTrigger("Render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + amount = op.inValueSlider("Amount", 1), + inLoop = op.inValueBool("Loop", false), + inRGB = op.inValueBool("RGB", false), + minValue = op.inValue("Minimum value", 0), + maxValue = op.inValue("Maximum value", 1), + numX = op.inValue("Num X", 10), + numY = op.inValue("Num Y", 10), + addX = op.inValue("X", 0), + addY = op.inValue("Y", 0), + addZ = op.inValue("Z", 0), + seed2 = op.inValue("Seed", 0), + inCentered = op.inBool("Centered", false), + trigger = op.outTrigger("Next"); + +op.setPortGroup("Look", [inRGB, inLoop, minValue, maxValue]); +op.setPortGroup("Position", [addX, addY, addZ]); +op.setPortGroup("Scaling", [numX, numY]); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); +shader.setSource(shader.getDefaultVertexShader(), attachments.pixelnoise2_frag); + +const + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + timeUniform = new CGL.Uniform(shader, "f", "time", 1.0), + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uni_numX = new CGL.Uniform(shader, "f", "numX", numX), + uni_numY = new CGL.Uniform(shader, "f", "numY", numY), + uni_addX = new CGL.Uniform(shader, "f", "addX", addX), + uni_addY = new CGL.Uniform(shader, "f", "addY", addY), + uni_addZ = new CGL.Uniform(shader, "f", "addZ", addZ), + uni_seed = new CGL.Uniform(shader, "f", "seed2", seed2), + uni_minValue = new CGL.Uniform(shader, "f", "minIn", minValue), + uni_maxValue = new CGL.Uniform(shader, "f", "maxIn", maxValue); + +inLoop.onChange = function () +{ + if (inLoop.get())shader.define("LOOP"); + else shader.removeDefine("LOOP"); +}; + +inRGB.onChange = function () +{ + if (inRGB.get())shader.define("RGB"); + else shader.removeDefine("RGB"); +}; + +inCentered.onChange = function () +{ + shader.toggleDefine("CENTER", inCentered.get()); +}; + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Noise.PixelNoise_v3.prototype = new CABLES.Op(); +CABLES.OPS["01ad08b6-dea4-4765-984c-3885c9c6520f"]={f:Ops.Gl.TextureEffects.Noise.PixelNoise_v3,objName:"Ops.Gl.TextureEffects.Noise.PixelNoise_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Noise.PolkaDotNoise_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Noise.PolkaDotNoise_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"polkadotnoise_frag":"#ifdef HAS_TEXTURES\n IN vec2 texCoord;\n UNI sampler2D tex;\n#endif\n\nUNI float amount;\nUNI float radius_low;\nUNI float radius_high;\nUNI float X,Y,Z;\nUNI float scale;\nUNI float threshhold;\nUNI float aspect;\n\n{{CGL.BLENDMODES3}}\n\nfloat random(vec2 co)\n{\n return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * (437511.5453));\n}\n\n\n//\n//\tFalloff defined in XSquared\n//\t( smoothly decrease from 1.0 to 0.0 as xsq increases from 0.0 to 1.0 )\n//\thttp://briansharpe.wordpress.com/2011/11/14/two-useful-interpolation-functions-for-noise-development/\n//\nfloat Falloff_Xsq_C1( float xsq ) { xsq = 1.0 - xsq; return xsq*xsq; }\t// ( 1.0 - x*x )^2 ( Used by Humus for lighting falloff in Just Cause 2. GPUPro 1 )\nfloat Falloff_Xsq_C2( float xsq ) { xsq = 1.0 - xsq; return xsq*xsq*xsq; }\t// ( 1.0 - x*x )^3. NOTE: 2nd derivative is 0.0 at x=1.0, but non-zero at x=0.0\nvec4 Falloff_Xsq_C2( vec4 xsq ) { xsq = 1.0 - xsq; return xsq*xsq*xsq; }\n\n\nvec4 FAST32_hash_3D_Cell( vec3 gridcell )\t//\tgenerates 4 different random numbers for the single given cell point\n{\n // gridcell is assumed to be an integer coordinate\n\n //\tTODO: \tthese constants need tweaked to find the best possible noise.\n //\t\t\tprobably requires some kind of brute force computational searching or something....\n const vec2 OFFSET = vec2( 50.0, 161.0 );\n const float DOMAIN = 69.0;\n const vec4 SOMELARGEFLOATS = vec4( 635.298681, 682.357502, 668.926525, 588.255119 );\n const vec4 ZINC = vec4( 48.500388, 65.294118, 63.934599, 63.279683 );\n\n //\ttruncate the domain\n gridcell.xyz = gridcell - floor(gridcell * ( 1.0 / DOMAIN )) * DOMAIN;\n gridcell.xy += OFFSET.xy;\n gridcell.xy *= gridcell.xy;\n return fract( ( gridcell.x * gridcell.y ) * ( 1.0 / ( SOMELARGEFLOATS + gridcell.zzzz * ZINC ) ) );\n}\n\n\n//\tPolkaDot Noise 3D\n//\thttp://briansharpe.files.wordpress.com/2011/12/polkadotsample.jpg\n//\thttp://briansharpe.files.wordpress.com/2012/01/polkaboxsample.jpg\n//\tTODO, these images have random intensity and random radius. This noise now has intensity as proportion to radius. Images need updated. TODO\n//\n//\tGenerates a noise of smooth falloff polka dots.\n//\tAllow for control on radius. Intensity is proportional to radius\n//\tReturn value range of 0.0->1.0\n//\nfloat PolkaDot3D( \tvec3 P,\n float radius_low,\t\t//\tradius range is 0.0->1.0\n float radius_high\t)\n{\n //\testablish our grid cell and unit position\n vec3 Pi = floor(P);\n vec3 Pf = P - Pi;\n\n //\tcalculate the hash.\n vec4 hash = FAST32_hash_3D_Cell( Pi );\n\n hash.w=step(hash.w,threshhold);\n\n //\tuser variables\n float RADIUS = max( 0.0, radius_low + hash.w * ( radius_high - radius_low ) );\n float VALUE = RADIUS / max( radius_high, radius_low );\t//\tnew keep value in proportion to radius. Behaves better when used for bumpmapping, distortion and displacement\n\n //\tcalc the noise and return\n RADIUS = 2.0/RADIUS;\n Pf *= RADIUS;\n Pf -= ( RADIUS - 1.0 );\n Pf += hash.xyz * ( RADIUS - 2.0 );\n #ifdef BOX\n Pf *= Pf;\t\t//\tthis gives us a cool box looking effect\n #endif\n return Falloff_Xsq_C2( min( dot( Pf, Pf ), 1.0 ) ) * VALUE;\n}\n\n\n\nvoid main()\n{\n vec3 pos=vec3(texCoord.x,texCoord.y,0);\n\n pos.xy-=0.5;\n pos.y/=aspect;\n pos.xy*=scale;\n pos.xy-=vec2(X,Y);\n\n vec3 Pi = floor(pos);\n vec4 hash = FAST32_hash_3D_Cell( Pi );\n pos.z=Z+random(hash.zz);\n\n vec4 rnd=vec4(PolkaDot3D(pos,radius_low,radius_high));\n rnd.a=1.0;\n\n vec4 base=texture(tex,texCoord);\n\n outColor=cgl_blendPixel(base,rnd,amount);\n\n}",}; +const + render = op.inTrigger("Render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + inBox = op.inValueBool("Square Look", false), + threshhold = op.inValueSlider("Threshold", 0.25), + radius_low = op.inValueSlider("Radius Low", 0), + radius_high = op.inValueSlider("Radius High", 1), + scale = op.inValue("Scale", 14), + X = op.inValue("X", 0), + Y = op.inValue("Y", 0), + Z = op.inValue("Z", 0), + trigger = op.outTrigger("Next"); + +let cgl = op.patch.cgl; +let shader = new CGL.Shader(cgl, op.name); + +let amountUniform = new CGL.Uniform(shader, "f", "amount", amount); +let timeUniform = new CGL.Uniform(shader, "f", "time", 1.0); + +shader.setSource(CGL.Shader.getDefaultVertexShader(), attachments.polkadotnoise_frag); +let textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +radius_low.uniform = new CGL.Uniform(shader, "f", "radius_low", radius_low); +radius_high.uniform = new CGL.Uniform(shader, "f", "radius_high", radius_high); +X.uniform = new CGL.Uniform(shader, "f", "X", X); +Y.uniform = new CGL.Uniform(shader, "f", "Y", Y); +Z.uniform = new CGL.Uniform(shader, "f", "Z", Z); +scale.uniform = new CGL.Uniform(shader, "f", "scale", scale); +const uniaspect = new CGL.Uniform(shader, "f", "aspect", 1); +const uniThreshhold = new CGL.Uniform(shader, "f", "threshhold", threshhold); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +inBox.onChange = function () +{ + if (inBox.get())shader.define("BOX"); + else shader.removeDefine("BOX"); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + uniaspect.setValue(cgl.currentTextureEffect.aspectRatio); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Noise.PolkaDotNoise_v2.prototype = new CABLES.Op(); +CABLES.OPS["2f128bcc-0846-4565-89ad-eda22e41ca4f"]={f:Ops.Gl.TextureEffects.Noise.PolkaDotNoise_v2,objName:"Ops.Gl.TextureEffects.Noise.PolkaDotNoise_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Noise.SimplexNoise_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Noise.SimplexNoise_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"simplexnoise_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float smoothness;\nUNI float scale;\nUNI float seed;\nUNI float x;\nUNI float y;\nUNI float time;\nUNI float aspect;\nUNI float harmonics;\n\n#ifdef HAS_TEX_OFFSETMAP\n UNI sampler2D texOffsetZ;\n UNI float offMul;\n#endif\n\n\n#ifdef HAS_TEX_MASK\n UNI sampler2D texMask;\n#endif\n\n\n\n{{CGL.BLENDMODES3}}\n\nvoid FAST32_hash_3D( vec3 gridcell,\n vec3 v1_mask, // user definable v1 and v2. ( 0s and 1s )\n vec3 v2_mask,\n out vec4 hash_0,\n out vec4 hash_1,\n out vec4 hash_2 ) // generates 3 random numbers for each of the 4 3D cell corners. cell corners: v0=0,0,0 v3=1,1,1 the other two are user definable\n{\n // gridcell is assumed to be an integer coordinate\n\n // TODO: these constants need tweaked to find the best possible noise.\n // probably requires some kind of brute force computational searching or something....\n const vec2 OFFSET = vec2( 50.0, 161.0 );\n const float DOMAIN = 69.0;\n const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );\n const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );\n\n // truncate the domain\n gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;\n vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );\n\n // compute x*x*y*y for the 4 corners\n vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;\n P *= P;\n vec4 V1xy_V2xy = mix( P.xyxy, P.zwzw, vec4( v1_mask.xy, v2_mask.xy ) ); // appl y mask for v1 and v2\n P = vec4( P.x, V1xy_V2xy.xz, P.z ) * vec4( P.y, V1xy_V2xy.yw, P.w );\n\n // get the lowz and highz mods\n vec3 lowz_mods = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );\n vec3 highz_mods = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );\n\n // appl mask for v1 and v2 mod values\n v1_mask = ( v1_mask.z < 0.5 ) ? lowz_mods : highz_mods;\n v2_mask = ( v2_mask.z < 0.5 ) ? lowz_mods : highz_mods;\n\n // compute the final hash\n hash_0 = fract( P * vec4( lowz_mods.x, v1_mask.x, v2_mask.x, highz_mods.x ) );\n hash_1 = fract( P * vec4( lowz_mods.y, v1_mask.y, v2_mask.y, highz_mods.y ) );\n hash_2 = fract( P * vec4( lowz_mods.z, v1_mask.z, v2_mask.z, highz_mods.z ) );\n}\n\n\n//\n// Given an arbitrary 3D point this calculates the 4 vectors from the corners of the simplex pyramid to the point\n// It also returns the integer grid index information for the corners\n//\nvoid Simplex3D_GetCornerVectors( vec3 P, // input point\n out vec3 Pi, // integer grid index for the origin\n out vec3 Pi_1, // offsets for the 2nd and 3rd corners. ( the 4th = Pi + 1.0 )\n out vec3 Pi_2,\n out vec4 v1234_x, // vectors from the 4 corners to the intput point\n out vec4 v1234_y,\n out vec4 v1234_z )\n{\n //\n // Simplex math from Stefan Gustavsons and Ian McEwans work at...\n // http://github.com/ashima/webgl-noise\n //\n\n // simplex math constants\n const float SKEWFACTOR = 1.0/3.0;\n const float UNSKEWFACTOR = 1.0/6.0;\n const float SIMPLEX_CORNER_POS = 0.5;\n const float SIMPLEX_PYRAMID_HEIGHT = 0.70710678118654752440084436210485; // sqrt( 0.5 ) height of simplex pyramid.\n\n P *= SIMPLEX_PYRAMID_HEIGHT; // scale space so we can have an approx feature size of 1.0 ( optional )\n\n // Find the vectors to the corners of our simplex pyramid\n Pi = floor( P + dot( P, vec3( SKEWFACTOR) ) );\n vec3 x0 = P - Pi + dot(Pi, vec3( UNSKEWFACTOR ) );\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n Pi_1 = min( g.xyz, l.zxy );\n Pi_2 = max( g.xyz, l.zxy );\n vec3 x1 = x0 - Pi_1 + UNSKEWFACTOR;\n vec3 x2 = x0 - Pi_2 + SKEWFACTOR;\n vec3 x3 = x0 - SIMPLEX_CORNER_POS;\n\n // pack them into a parallel-friendly arrangement\n v1234_x = vec4( x0.x, x1.x, x2.x, x3.x );\n v1234_y = vec4( x0.y, x1.y, x2.y, x3.y );\n v1234_z = vec4( x0.z, x1.z, x2.z, x3.z );\n}\n\n//\n// Calculate the weights for the 3D simplex surflet\n//\nvec4 Simplex3D_GetSurfletWeights( vec4 v1234_x,\n vec4 v1234_y,\n vec4 v1234_z )\n{\n // perlins original implementation uses the surlet falloff formula of (0.6-x*x)^4.\n // This is buggy as it can cause discontinuities along simplex faces. (0.5-x*x)^3 solves this and gives an almost identical curve\n\n // evaluate surflet. f(x)=(0.5-x*x)^3\n vec4 surflet_weights = v1234_x * v1234_x + v1234_y * v1234_y + v1234_z * v1234_z;\n surflet_weights = max(0.5 - surflet_weights, 0.0); // 0.5 here represents the closest distance (squared) of any simplex pyramid corner to any of its planes. ie, SIMPLEX_PYRAMID_HEIGHT^2\n return surflet_weights*surflet_weights*surflet_weights;\n}\n\n\n\n//\n// SimplexPerlin3D ( simplex gradient noise )\n// Perlin noise over a simplex (tetrahedron) grid\n// Return value range of -1.0->1.0\n// http://briansharpe.files.wordpress.com/2012/01/simplexperlinsample.jpg\n//\n// Implementation originally based off Stefan Gustavsons and Ian McEwans work at...\n// http://github.com/ashima/webgl-noise\n//\nfloat SimplexPerlin3D(vec3 P)\n{\n // calculate the simplex vector and index math\n vec3 Pi;\n vec3 Pi_1;\n vec3 Pi_2;\n vec4 v1234_x;\n vec4 v1234_y;\n vec4 v1234_z;\n Simplex3D_GetCornerVectors( P, Pi, Pi_1, Pi_2, v1234_x, v1234_y, v1234_z );\n\n // generate the random vectors\n // ( various hashing methods listed in order of speed )\n vec4 hash_0;\n vec4 hash_1;\n vec4 hash_2;\n FAST32_hash_3D( Pi, Pi_1, Pi_2, hash_0, hash_1, hash_2 );\n //SGPP_hash_3D( Pi, Pi_1, Pi_2, hash_0, hash_1, hash_2 );\n hash_0 -= 0.49999;\n hash_1 -= 0.49999;\n hash_2 -= 0.49999;\n\n // evaluate gradients\n vec4 grad_results = inversesqrt( hash_0 * hash_0 + hash_1 * hash_1 + hash_2 * hash_2 ) * ( hash_0 * v1234_x + hash_1 * v1234_y + hash_2 * v1234_z );\n\n // Normalization factor to scale the final result to a strict 1.0->-1.0 range\n // x = sqrt( 0.75 ) * 0.5\n // NF = 1.0 / ( x * ( ( 0.5 * x*x ) ^ 3 ) * 2.0 )\n // http://briansharpe.wordpress.com/2012/01/13/simplex-noise/#comment-36\n float FINAL_NORMALIZATION = 37.837227241611314102871574478976*smoothness;\n\n // sum with the surflet and return\n return dot( Simplex3D_GetSurfletWeights( v1234_x, v1234_y, v1234_z ), grad_results ) * FINAL_NORMALIZATION;\n}\n\nvoid main()\n{\n vec2 p=vec2(texCoord.x-0.5,texCoord.y-0.5);\n\n p.x*=aspect;\n p=p*scale;\n\n p=vec2(p.x+0.5-x,p.y+0.5-y);\n\n vec3 offset;\n #ifdef HAS_TEX_OFFSETMAP\n vec4 offMap=texture(texOffsetZ,texCoord);\n\n #ifdef OFFSET_X_R\n offset.x=offMap.r;\n #endif\n #ifdef OFFSET_X_G\n offset.x=offMap.g;\n #endif\n #ifdef OFFSET_X_B\n offset.x=offMap.b;\n #endif\n\n #ifdef OFFSET_Y_R\n offset.y=offMap.r;\n #endif\n #ifdef OFFSET_Y_G\n offset.y=offMap.g;\n #endif\n #ifdef OFFSET_Y_B\n offset.y=offMap.b;\n #endif\n\n #ifdef OFFSET_Z_R\n offset.z=offMap.r;\n #endif\n #ifdef OFFSET_Z_G\n offset.z=offMap.g;\n #endif\n #ifdef OFFSET_Z_B\n offset.z=offMap.b;\n #endif\n\n offset*=offMul;\n #endif\n\n float v=SimplexPerlin3D(vec3(p.x,p.y,time)+offset)*0.5+0.5;\n\n\n if (harmonics >= 2.0) v += SimplexPerlin3D(vec3(p.x,p.y,time)*2.3+offset) * 0.5;\n if (harmonics >= 3.0) v += SimplexPerlin3D(vec3(p.x,p.y,time)*4.2+offset) * 0.25;\n if (harmonics >= 4.0) v += SimplexPerlin3D(vec3(p.x,p.y,time)*8.1+offset) * 0.125;\n if (harmonics >= 5.0) v += SimplexPerlin3D(vec3(p.x,p.y,time)*16.7+offset) * 0.0625;\n\n\n\n //blend section\n vec4 col=vec4(v,v,v,1.0);\n\n vec4 base=texture(tex,texCoord);\n\n // outColor=cgl_blend(base,col,amount);\n\n\n float str=1.0;\n #ifdef HAS_TEX_MASK\n str=texture(texMask,texCoord).r;\n #endif\n\n outColor=cgl_blendPixel(base,col,amount*str);\n\n}",}; +const + render = op.inTrigger("render"), + inTexMask = op.inTexture("Mask"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + smoothness = op.inValue("smoothness", 1.0), + inHarmonics = op.inSwitch("Harmonics", ["1", "2", "3", "4", "5"], "1"), + scale = op.inValue("scale", 7), + trigger = op.outTrigger("trigger"), + x = op.inValue("x"), + y = op.inValue("y"), + time = op.inValue("time", 0); + +const + inTexOffsetZ = op.inTexture("Offset"), + inOffsetMul = op.inFloat("Offset Multiply", 1), + offsetX = op.inSwitch("Offset X", ["None", "R", "G", "B"], "None"), + offsetY = op.inSwitch("Offset Y", ["None", "R", "G", "B"], "None"), + offsetZ = op.inSwitch("Offset Z", ["None", "R", "G", "B"], "R"); + +op.setPortGroup("Offset Map", [inTexOffsetZ, offsetZ, offsetY, offsetX, inOffsetMul]); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.simplexnoise_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + textureUniformOffZ = new CGL.Uniform(shader, "t", "texOffsetZ", 1), + uniTexMask = new CGL.Uniform(shader, "t", "texMask", 2), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + uniSmoothness = new CGL.Uniform(shader, "f", "smoothness", smoothness), + uniScale = new CGL.Uniform(shader, "f", "scale", scale), + uniX = new CGL.Uniform(shader, "f", "x", x), + uniY = new CGL.Uniform(shader, "f", "y", y), + uniAspect = new CGL.Uniform(shader, "f", "aspect", 1), + uniTime = new CGL.Uniform(shader, "f", "time", time), + uniOffMul = new CGL.Uniform(shader, "f", "offMul", inOffsetMul), + uniHarmonics = new CGL.Uniform(shader, "f", "harmonics", 0); + +inHarmonics.onChange = () => +{ + uniHarmonics.setValue(parseFloat(inHarmonics.get())); +}; + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount,maskAlpha); + +offsetX.onChange = +offsetY.onChange = +offsetZ.onChange = +inTexMask.onChange = +inTexOffsetZ.onChange = updateDefines; +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("HAS_TEX_OFFSETMAP", inTexOffsetZ.get()); + shader.toggleDefine("HAS_TEX_MASK", inTexMask.get()); + + shader.toggleDefine("OFFSET_X_R", offsetX.get() == "R"); + shader.toggleDefine("OFFSET_X_G", offsetX.get() == "G"); + shader.toggleDefine("OFFSET_X_B", offsetX.get() == "B"); + + shader.toggleDefine("OFFSET_Y_R", offsetY.get() == "R"); + shader.toggleDefine("OFFSET_Y_G", offsetY.get() == "G"); + shader.toggleDefine("OFFSET_Y_B", offsetY.get() == "B"); + + shader.toggleDefine("OFFSET_Z_R", offsetZ.get() == "R"); + shader.toggleDefine("OFFSET_Z_G", offsetZ.get() == "G"); + shader.toggleDefine("OFFSET_Z_B", offsetZ.get() == "B"); + + offsetX.setUiAttribs({ "greyout": !inTexOffsetZ.isLinked() }); + offsetY.setUiAttribs({ "greyout": !inTexOffsetZ.isLinked() }); + offsetZ.setUiAttribs({ "greyout": !inTexOffsetZ.isLinked() }); + inOffsetMul.setUiAttribs({ "greyout": !inTexOffsetZ.isLinked() }); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op,3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + uniAspect.setValue(cgl.currentTextureEffect.aspectRatio); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + if (inTexOffsetZ.get()) cgl.setTexture(1, inTexOffsetZ.get().tex); + if (inTexMask.get()) cgl.setTexture(2, inTexMask.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Noise.SimplexNoise_v2.prototype = new CABLES.Op(); +CABLES.OPS["0f4a8d04-89b0-437a-9da8-b4098772d250"]={f:Ops.Gl.TextureEffects.Noise.SimplexNoise_v2,objName:"Ops.Gl.TextureEffects.Noise.SimplexNoise_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Noise.TriangleNoise_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Noise.TriangleNoise_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"trianglenoise_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float scale;\nUNI float angle;\nUNI float ratio;\nUNI float add;\nUNI float amount;\n\n{{CGL.BLENDMODES3}}\n\nfloat rand(vec2 co)\n{\n return fract(sin(dot(co.xy ,vec2(13.98987,28.533))) * 4758.6453+add*0.1);\n}\n\nfloat GetLocation(vec2 s, float d)\n{\n vec2 f = s*d;\n f = f + vec2(0,0.5)*floor(f).x;\n s = fract(f);\n f = floor(f);\n\n d = s.y - 0.5;\n float l = abs(d) + 0.5 * s.x;\n float ff = f.x+f.y;\n f = mix(f, f+sign(d)*vec2(0,0.5), step(0.5, l));\n l = mix(ff, ff+sign(d)*0.5, step(0.5, l));\n\n float r=mod(rand(f)*2.0,2.0);\n if(r>1.0)r=2.0-r;\n\n return r;\n}\n\nvoid main()\n{\n vec2 coord=texCoord;\n coord-=0.5;\n coord.y/=ratio;\n coord*=scale;\n coord+=0.5;\n\n float sin_factor = sin(angle*0.01745329251);\n float cos_factor = cos(angle*0.01745329251);\n coord = vec2((coord.x - 0.5), coord.y - ratio/2.0) * mat2(cos_factor, sin_factor, -sin_factor, cos_factor);\n\n float a=GetLocation(coord,1.0);\n\n vec4 base=texture(tex,texCoord);\n vec4 col=vec4(a,a,a,1.0);\n\n outColor=cgl_blendPixel(base,col,amount);\n}",}; +const + render = op.inTrigger("Render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + scale = op.inValue("scale", 10), + angle = op.inValue("angle", 0), + add = op.inValue("Add", 0), + trigger = op.outTrigger("Next"); + +const + cgl = op.patch.cgl, + shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.trianglenoise_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + addUniform = new CGL.Uniform(shader, "f", "add", add), + scaleUniform = new CGL.Uniform(shader, "f", "scale", scale), + angleUniform = new CGL.Uniform(shader, "f", "angle", angle), + ratioUniform = new CGL.Uniform(shader, "f", "ratio", 1); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + ratioUniform.setValue(cgl.currentTextureEffect.aspectRatio); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Noise.TriangleNoise_v2.prototype = new CABLES.Op(); +CABLES.OPS["9e634336-cb44-40ca-b06b-90063e4324a2"]={f:Ops.Gl.TextureEffects.Noise.TriangleNoise_v2,objName:"Ops.Gl.TextureEffects.Noise.TriangleNoise_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Noise.ValueNoise_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Noise.ValueNoise_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"valuenoise3d_frag":"UNI float z;\nUNI float x;\nUNI float y;\nUNI float scale;\nUNI float amount;\nIN vec2 texCoord;\nUNI sampler2D tex;\nUNI float aspect;\n\n{{CGL.BLENDMODES3}}\n\n//\n//\tValue Noise 3D\n//\tReturn value range of 0.0->1.0\n//\thttp://briansharpe.files.wordpress.com/2011/11/valuesample1.jpg\n//\n\nfloat Interpolation_C2( float x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); } // 6x^5-15x^4+10x^3\t( Quintic Curve. As used by Perlin in Improved Noise. http://mrl.nyu.edu/~perlin/paper445.pdf )\nvec2 Interpolation_C2( vec2 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec3 Interpolation_C2( vec3 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2( vec4 x ) { return x * x * x * (x * (x * 6.0 - 15.0) + 10.0); }\nvec4 Interpolation_C2_InterpAndDeriv( vec2 x ) { return x.xyxy * x.xyxy * ( x.xyxy * ( x.xyxy * ( x.xyxy * vec2( 6.0, 0.0 ).xxyy + vec2( -15.0, 30.0 ).xxyy ) + vec2( 10.0, -60.0 ).xxyy ) + vec2( 0.0, 30.0 ).xxyy ); }\nvec3 Interpolation_C2_Deriv( vec3 x ) { return x * x * (x * (x * 30.0 - 60.0) + 30.0); }\n\nvoid FAST32_hash_3D( vec3 gridcell, out vec4 lowz_hash, out vec4 highz_hash )\t//\tgenerates a random number for each of the 8 cell corners\n{\n // gridcell is assumed to be an integer coordinate\n\n //\tTODO: \tthese constants need tweaked to find the best possible noise.\n //\t\t\tprobably requires some kind of brute force computational searching or something....\n const vec2 OFFSET = vec2( 50.0, 161.0 );\n const float DOMAIN = 69.0;\n const float SOMELARGEFLOAT = 635.298681;\n const float ZINC = 48.500388;\n\n //\ttruncate the domain\n gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;\n vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );\n\n //\tcalculate the noise\n vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;\n P *= P;\n P = P.xzxz * P.yyww;\n highz_hash.xy = vec2( 1.0 / ( SOMELARGEFLOAT + vec2( gridcell.z, gridcell_inc1.z ) * ZINC ) );\n lowz_hash = fract( P * highz_hash.xxxx );\n highz_hash = fract( P * highz_hash.yyyy );\n}\n\n\nfloat Value3D( vec3 P )\n{\n //\testablish our grid cell and unit position\n vec3 Pi = floor(P);\n vec3 Pf = P - Pi;\n\n //\tcalculate the hash.\n //\t( various hashing methods listed in order of speed )\n vec4 hash_lowz, hash_highz;\n FAST32_hash_3D( Pi, hash_lowz, hash_highz );\n //FAST32_2_hash_3D( Pi, hash_lowz, hash_highz );\n //BBS_hash_3D( Pi, hash_lowz, hash_highz );\n //SGPP_hash_3D( Pi, hash_lowz, hash_highz );\n\n //\tblend the results and return\n vec3 blend = Interpolation_C2( Pf );\n vec4 res0 = mix( hash_lowz, hash_highz, blend.z );\n vec4 blend2 = vec4( blend.xy, vec2( 1.0 - blend.xy ) );\n return dot( res0, blend2.zxzx * blend2.wwyy );\n}\n\nvoid main()\n{\n vec2 tc=texCoord;\n tc.y/=aspect;\n vec4 base=texture(tex,tc);\n\n vec2 p=vec2(tc.x-0.5,tc.y-0.5);\n p=p*scale;\n\n p=vec2(p.x+0.5-x,p.y+0.5-y);\n\n float v=Value3D(vec3(p.x,p.y,z));\n vec4 col=vec4(v,v,v,1.0);\n\n outColor=cgl_blendPixel(base,col,amount);\n\n}\n",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + scale = op.inValue("Scale", 25), + x = op.inValue("X", 0), + y = op.inValue("Y", 0), + z = op.inValue("Z", 0), + trigger = op.outTrigger("trigger"); + +op.setPortGroup("Position", [x, y, z]); +op.setPortGroup("Look", [scale]); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(CGL.Shader.getDefaultVertexShader(), attachments.valuenoise3d_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uniZ = new CGL.Uniform(shader, "f", "z", z), + uniX = new CGL.Uniform(shader, "f", "x", x), + uniY = new CGL.Uniform(shader, "f", "y", y), + uniScale = new CGL.Uniform(shader, "f", "scale", scale), + uniAspect = new CGL.Uniform(shader, "f", "aspect", 1), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + uniAspect.setValue(cgl.currentTextureEffect.aspectRatio); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Noise.ValueNoise_v2.prototype = new CABLES.Op(); +CABLES.OPS["d2748c53-9ac1-4cd7-8176-66d3eb5d1bb6"]={f:Ops.Gl.TextureEffects.Noise.ValueNoise_v2,objName:"Ops.Gl.TextureEffects.Noise.ValueNoise_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Noise.Voronoise_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Noise.Voronoise_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"voronoise_frag":"// adapted from https://thebookofshaders.com/12/\n\nIN vec2 texCoord;\n\nUNI bool drawIsoLines;\nUNI bool drawDistance;\nUNI int fill;\nUNI float seed;\n\nUNI float time;\nUNI float movement;\nUNI float amount;\nUNI float centerSize;\nUNI sampler2D tex;\nUNI float aspect;\n\n{{CGL.BLENDMODES3}}\n{{CGL.RANDOM_OLD}}\n\nfloat rand(float n){return fract(sin(n) * 43.5453123);}\nvec2 random2( vec2 p )\n{\n return vec2(rand(p.x),rand(p.x+p.y));\n}\n\nvoid main() {\n\n vec3 color = vec3(.0);\n float m_dist = 1.; // minimun distance\n vec2 m_point; // minimum position\n float indexColor=0.0;\n\n vec2 coord=texCoord;\n\n coord.y/=aspect;\n\n // const float NUM=21.0;\n\n // Iterate through the points positions\n for (float i = 0.0; i < NUM; i++)\n {\n vec2 pos= random2(vec2(i+seed,i+seed));\n\n pos.x+=sin(time+i)*movement;\n pos.y+=cos(time+i)*movement;\n\n if(i==0.0)\n {\n // pos=vec2(mouseX,mouseY);\n }\n\n float dist = distance(coord, pos);\n if( dist < m_dist )\n {\n // Keep the closer distance\n m_dist = dist;\n\n // Kepp the position of the closer point\n m_point = pos;\n indexColor=(i)/NUM;\n }\n }\n\n // tint acording the closest point position\n if(fill==1) color.rgb = vec3( indexColor );\n if(fill==2) color.rgb = vec3( m_point.x );\n if(fill==3) color.rgb = vec3( 0.5 );\n\n // Add distance field to closest point center\n if(drawDistance) color += m_dist*2.;\n\n // Show isolines\n if(drawIsoLines) color -= abs(sin(120.0*m_dist))*0.07;\n\n // Draw point center\n if(centerSize>0.0)\n color += 1.-step(centerSize/30.0, m_dist);\n\n vec4 base=texture(tex,coord);\n\n outColor= cgl_blendPixel(base,vec4(color,1.0),amount);\n}",}; +const + render = op.inTrigger("Render"), + trigger = op.outTrigger("Trigger"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + time = op.inValue("Time", 0), + movement = op.inValueSlider("Movement", 0), + num = op.inValue("Num", 20), + seed = op.inValue("seed", 0), + fill = op.inValueSelect("Fill", ["None", "Random", "Gradient", "Gray"], "Random"), + drawIsoLines = op.inValueBool("Draw Isolines", false), + drawDistance = op.inValueBool("Draw Distance", false), + centerSize = op.inValueSlider("Draw Center", 0); + +const cgl = op.patch.cgl; +let shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.voronoise_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + uniPx = new CGL.Uniform(shader, "f", "pX", 1 / 1024), + uniPy = new CGL.Uniform(shader, "f", "pY", 1 / 1024), + uniFill = new CGL.Uniform(shader, "i", "fill", 1), + uniSeed = new CGL.Uniform(shader, "f", "seed", seed), + uniTime = new CGL.Uniform(shader, "f", "time", time), + uniMovement = new CGL.Uniform(shader, "f", "movement", movement), + uniAspect = new CGL.Uniform(shader, "f", "aspect", 1), + uniIsoLines = new CGL.Uniform(shader, "b", "drawIsoLines", drawIsoLines), + uniDrawDistance = new CGL.Uniform(shader, "b", "drawDistance", drawDistance), + uniCenterSize = new CGL.Uniform(shader, "f", "centerSize", centerSize); + +shader.define("NUM", 20.001); + +num.onChange = function () +{ + shader.define("NUM", num.get() + 0.001); +}; + +fill.onChange = function () +{ + if (fill.get() == "Random") uniFill.setValue(1); + else if (fill.get() == "Gradient") uniFill.setValue(2); + else if (fill.get() == "Gray") uniFill.setValue(3); + else uniFill.setValue(0); +}; + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + uniPx.setValue(1 / cgl.currentTextureEffect.getCurrentSourceTexture().width); + uniPy.setValue(1 / cgl.currentTextureEffect.getCurrentSourceTexture().height); + + uniAspect.setValue(cgl.currentTextureEffect.aspectRatio); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Noise.Voronoise_v2.prototype = new CABLES.Op(); +CABLES.OPS["0e68dbf4-dc3e-448d-b1e1-256dde99802a"]={f:Ops.Gl.TextureEffects.Noise.Voronoise_v2,objName:"Ops.Gl.TextureEffects.Noise.Voronoise_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Noise.WorleyNoise_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Noise.WorleyNoise_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"worleynoise_frag":"// Author: Stefan Gustavson\n// Title: Worley noise 2x2x2\n\nIN vec2 texCoord;\n\nUNI float amount;\nUNI float x;\nUNI float y;\nUNI float z;\nUNI float scale;\nUNI sampler2D tex;\nUNI float rangeA;\nUNI float rangeB;\nUNI float aspect;\nUNI float harmonics;\n\n#ifdef HAS_MASK\n UNI sampler2D texMask;\n#endif\n\n#ifdef HAS_TEX_OFFSETMAP\n UNI sampler2D texOffsetZ;\n UNI float offMul;\n#endif\n\n{{CGL.BLENDMODES3}}\n{{CGL.LUMINANCE}}\n\n// Cellular noise (\"Worley noise\") in 3D in GLSL.\n// Copyright (c) Stefan Gustavson 2011-04-19. All rights reserved.\n// This code is released under the conditions of the MIT license.\n// See LICENSE file for details.\n\n// Permutation polynomial: (34x^2 + x) mod 289\nvec4 permute(vec4 x) {\n return mod((34.0 * x + 1.0) * x, 289.0);\n}\nvec3 permute(vec3 x) {\n return mod((34.0 * x + 1.0) * x, 289.0);\n}\n\n// Cellular noise, returning F1 and F2 in a vec2.\n// Speeded up by using 2x2x2 search window instead of 3x3x3,\n// at the expense of some pattern artifacts.\n// F2 is often wrong and has sharp discontinuities.\n// If you need a good F2, use the slower 3x3x3 version.\nvec2 cellular2x2x2(vec3 P) {\n\t#define K 0.142857142857 // 1/7\n\t#define Ko 0.428571428571 // 1/2-K/2\n\t#define K2 0.020408163265306 // 1/(7*7)\n\t#define Kz 0.166666666667 // 1/6\n\t#define Kzo 0.416666666667 // 1/2-1/6*2\n\t#define jitter 0.8 // smaller jitter gives less errors in F2\n\tvec3 Pi = mod(floor(P), 289.0);\n \tvec3 Pf = fract(P);\n\tvec4 Pfx = Pf.x + vec4(0.0, -1.0, 0.0, -1.0);\n\tvec4 Pfy = Pf.y + vec4(0.0, 0.0, -1.0, -1.0);\n\tvec4 p = permute(Pi.x + vec4(0.0, 1.0, 0.0, 1.0));\n\tp = permute(p + Pi.y + vec4(0.0, 0.0, 1.0, 1.0));\n\tvec4 p1 = permute(p + Pi.z); // z+0\n\tvec4 p2 = permute(p + Pi.z + vec4(1.0)); // z+1\n\tvec4 ox1 = fract(p1*K) - Ko;\n\tvec4 oy1 = mod(floor(p1*K), 7.0)*K - Ko;\n\tvec4 oz1 = floor(p1*K2)*Kz - Kzo; // p1 < 289 guaranteed\n\tvec4 ox2 = fract(p2*K) - Ko;\n\tvec4 oy2 = mod(floor(p2*K), 7.0)*K - Ko;\n\tvec4 oz2 = floor(p2*K2)*Kz - Kzo;\n\tvec4 dx1 = Pfx + jitter*ox1;\n\tvec4 dy1 = Pfy + jitter*oy1;\n\tvec4 dz1 = Pf.z + jitter*oz1;\n\tvec4 dx2 = Pfx + jitter*ox2;\n\tvec4 dy2 = Pfy + jitter*oy2;\n\tvec4 dz2 = Pf.z - 1.0 + jitter*oz2;\n\tvec4 d1 = dx1 * dx1 + dy1 * dy1 + dz1 * dz1; // z+0\n\tvec4 d2 = dx2 * dx2 + dy2 * dy2 + dz2 * dz2; // z+1\n\n\t// Sort out the two smallest distances (F1, F2)\n#if 0\n\t// Cheat and sort out only F1\n\td1 = min(d1, d2);\n\td1.xy = min(d1.xy, d1.wz);\n\td1.x = min(d1.x, d1.y);\n\treturn sqrt(d1.xx);\n#else\n\t// Do it right and sort out both F1 and F2\n\tvec4 d = min(d1,d2); // F1 is now in d\n\td2 = max(d1,d2); // Make sure we keep all candidates for F2\n\td.xy = (d.x < d.y) ? d.xy : d.yx; // Swap smallest to d.x\n\td.xz = (d.x < d.z) ? d.xz : d.zx;\n\td.xw = (d.x < d.w) ? d.xw : d.wx; // F1 is now in d.x\n\td.yzw = min(d.yzw, d2.yzw); // F2 now not in d2.yzw\n\td.y = min(d.y, d.z); // nor in d.z\n\td.y = min(d.y, d.w); // nor in d.w\n\td.y = min(d.y, d2.x); // F2 is now in d.y\n\treturn sqrt(d.xy); // F1 and F2\n#endif\n}\n\nvoid main(void) {\n\tvec2 st = texCoord;//gl_FragCoord.xy/u_resolution.xy;\n\n\t#ifdef DO_TILEABLE\n\t st=abs(texCoord-0.5);\n\t#endif\n\n vec3 offset;\n #ifdef HAS_TEX_OFFSETMAP\n vec4 offMap=texture(texOffsetZ,texCoord);\n\n #ifdef OFFSET_X_R\n offset.x=offMap.r;\n #endif\n #ifdef OFFSET_X_G\n offset.x=offMap.g;\n #endif\n #ifdef OFFSET_X_B\n offset.x=offMap.b;\n #endif\n\n #ifdef OFFSET_Y_R\n offset.y=offMap.r;\n #endif\n #ifdef OFFSET_Y_G\n offset.y=offMap.g;\n #endif\n #ifdef OFFSET_Y_B\n offset.y=offMap.b;\n #endif\n\n #ifdef OFFSET_Z_R\n offset.z=offMap.r;\n #endif\n #ifdef OFFSET_Z_G\n offset.z=offMap.g;\n #endif\n #ifdef OFFSET_Z_B\n offset.z=offMap.b;\n #endif\n offset*=offMul;\n #endif\n\n st.x-=0.5;\n st.y-=0.5;\n\tst *= scale;\n st.x+=0.5;\n st.y+=0.5;\n\n st.y/=aspect;\n\n\tst.x+=x;\n\tst.y+=y;\n\n\tvec2 F = cellular2x2x2(vec3(st,z)+offset);\n\n if (harmonics >= 2.0) F.x += cellular2x2x2(vec3(st,z)*2.2+offset).x * 0.5;\n if (harmonics >= 3.0) F.x += cellular2x2x2(vec3(st,z)*4.3+offset).x * 0.25;\n if (harmonics >= 4.0) F.x += cellular2x2x2(vec3(st,z)*8.4+offset).x * 0.125;\n if (harmonics >= 5.0) F.x += cellular2x2x2(vec3(st,z)*16.5+offset).x * 0.0625;\n\n\tfloat n = smoothstep(rangeA,rangeB, F.x);\n\n #ifdef DO_INVERT\n n=1.0-n;\n #endif\n\n vec4 col=vec4(n,n,n,1.0);\n vec4 base=texture(tex,texCoord);\n\n float am=amount;\n #ifdef HAS_MASK\n #ifdef MASK_SRC_R\n float mul=texture(texMask,texCoord).r;\n #endif\n #ifdef MASK_SRC_G\n float mul=texture(texMask,texCoord).g;\n #endif\n #ifdef MASK_SRC_B\n float mul=texture(texMask,texCoord).b;\n #endif\n #ifdef MASK_SRC_A\n float mul=texture(texMask,texCoord).a;\n #endif\n #ifdef MASK_SRC_LUM\n float mul=cgl_luminance(texture(texMask,texCoord).rgb);\n #endif\n #ifdef MASK_INV\n mul=1.0-mul;\n #endif\n am*=mul;\n #endif\n\n outColor=cgl_blendPixel(base,col,am);\n\n}\n",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + amount = op.inValueSlider("Amount", 1), + x = op.inValue("X", 0), + y = op.inValue("Y", 0), + z = op.inValue("Z", 0), + scale = op.inValue("Scale", 6), + inHarmonics = op.inSwitch("Harmonics", ["1", "2", "3", "4", "5"], "1"), + inv = op.inValueBool("Invert", true), + rangeA = op.inValueSlider("RangeA", 0.4), + rangeB = op.inValueSlider("RangeB", 0.5), + tile = op.inValueBool("Tileable", false), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.worleynoise_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + textureUniformOffZ = new CGL.Uniform(shader, "t", "texOffsetZ", 1), + textureUniformMask = new CGL.Uniform(shader, "t", "texMask", 2), + uniZ = new CGL.Uniform(shader, "f", "z", z), + uniX = new CGL.Uniform(shader, "f", "x", x), + uniY = new CGL.Uniform(shader, "f", "y", y), + uniScale = new CGL.Uniform(shader, "f", "scale", scale), + uniAspect = new CGL.Uniform(shader, "f", "aspect", 1), + uniharmonics = new CGL.Uniform(shader, "f", "harmonics", inHarmonics), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + rangeAUniform = new CGL.Uniform(shader, "f", "rangeA", rangeA), + rangeBUniform = new CGL.Uniform(shader, "f", "rangeB", rangeB); + +// amount Map + +const + inMaskTex = op.inTexture("Amount Map"), + inMaskSource = op.inSwitch("Source Strength Map", ["R", "G", "B", "A", "Lum"], "R"), + inMaskInv = op.inBool("Invert Strength Map", false); + +inMaskSource.setUiAttribs({ "title": "Source Amount Map" }); +inMaskInv.setUiAttribs({ "title": "Invert Amount Map" }); + +op.setPortGroup("Amount Map", [inMaskTex, inMaskSource, inMaskInv]); + +// offsetMap + +const + inTexOffsetZ = op.inTexture("Offset"), + inOffsetMul = op.inFloat("Offset Multiply", 1), + offsetX = op.inSwitch("Offset X", ["None", "R", "G", "B"], "None"), + offsetY = op.inSwitch("Offset Y", ["None", "R", "G", "B"], "None"), + offsetZ = op.inSwitch("Offset Z", ["None", "R", "G", "B"], "R"); + +op.setPortGroup("Offset Map", [inTexOffsetZ, offsetZ, offsetY, offsetX, inOffsetMul]); + +const uniOffMul = new CGL.Uniform(shader, "f", "offMul", inOffsetMul); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +inMaskTex.onChange = + inMaskSource.onChange = + inMaskInv.onChange = + inv.onChange = + offsetX.onChange = + offsetY.onChange = + offsetZ.onChange = + inMaskTex.onLinkChanged = + inTexOffsetZ.onLinkChanged = + tile.onChange = updateDefines; + +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("DO_INVERT", inv.get()); + shader.toggleDefine("DO_TILEABLE", tile.get()); + + shader.toggleDefine("HAS_TEX_OFFSETMAP", inTexOffsetZ.isLinked()); + shader.toggleDefine("HAS_TEX_MASK", inMaskTex.isLinked()); + + shader.toggleDefine("OFFSET_X_R", offsetX.get() == "R"); + shader.toggleDefine("OFFSET_X_G", offsetX.get() == "G"); + shader.toggleDefine("OFFSET_X_B", offsetX.get() == "B"); + + shader.toggleDefine("OFFSET_Y_R", offsetY.get() == "R"); + shader.toggleDefine("OFFSET_Y_G", offsetY.get() == "G"); + shader.toggleDefine("OFFSET_Y_B", offsetY.get() == "B"); + + shader.toggleDefine("OFFSET_Z_R", offsetZ.get() == "R"); + shader.toggleDefine("OFFSET_Z_G", offsetZ.get() == "G"); + shader.toggleDefine("OFFSET_Z_B", offsetZ.get() == "B"); + + offsetX.setUiAttribs({ "greyout": !inTexOffsetZ.isLinked() }); + offsetY.setUiAttribs({ "greyout": !inTexOffsetZ.isLinked() }); + offsetZ.setUiAttribs({ "greyout": !inTexOffsetZ.isLinked() }); + inOffsetMul.setUiAttribs({ "greyout": !inTexOffsetZ.isLinked() }); + + shader.toggleDefine("HAS_MASK", inMaskTex.isLinked()); + shader.toggleDefine("MASK_SRC_R", inMaskSource.get() == "R"); + shader.toggleDefine("MASK_SRC_G", inMaskSource.get() == "G"); + shader.toggleDefine("MASK_SRC_B", inMaskSource.get() == "B"); + shader.toggleDefine("MASK_SRC_A", inMaskSource.get() == "A"); + shader.toggleDefine("MASK_SRC_LUM", inMaskSource.get() == "Lum"); + shader.toggleDefine("MASK_INV", inMaskInv.get()); + inMaskSource.setUiAttribs({ "greyout": !inMaskTex.isLinked() }); + inMaskInv.setUiAttribs({ "greyout": !inMaskTex.isLinked() }); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + if (inTexOffsetZ.get()) cgl.setTexture(1, inTexOffsetZ.get().tex); + if (inMaskTex.get()) cgl.setTexture(2, inMaskTex.get().tex); + + uniAspect.setValue(cgl.currentTextureEffect.aspectRatio); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Noise.WorleyNoise_v2.prototype = new CABLES.Op(); +CABLES.OPS["fc6fbe7c-4bf8-4fdc-bd37-95b9f50a5bf2"]={f:Ops.Gl.TextureEffects.Noise.WorleyNoise_v2,objName:"Ops.Gl.TextureEffects.Noise.WorleyNoise_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.PatternLookup +// +// ************************************************************** + +Ops.Gl.TextureEffects.PatternLookup = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"patternlookup_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D patternTex;\nUNI float amount;\nUNI float patternWidth;\nUNI float patternHeight;\n\n{{CGL.BLENDMODES}}\n\nfloat desaturate(vec3 color)\n{\n vec3 gray = vec3(dot(vec3(0.2126,0.7152,0.0722), color));\n return gray.g;\n}\n\nvoid main()\n{\n vec4 col=vec4(1.0,0.0,0.0,1.0);\n vec4 base=texture(tex,texCoord);\n\n vec2 nc=vec2(0.5,desaturate(base.rgb));\n nc.x=mod(texCoord.x,patternWidth*0.1);\n nc.y=nc.y+mod(texCoord.y,patternHeight*0.1);\n\n // maybe should have a ping pong modulo option...\n\n nc.x=clamp(nc.x,0.0,1.0);\n nc.y=clamp(nc.y,0.0,1.0);\n\n vec4 newCol=texture(patternTex,nc);\n\n outColor=cgl_blend(base,newCol,amount);\n}",}; +const render = op.inTrigger("render"); +const multiplierTex = op.inTexture("Multiplier"); +const blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"); +const amount = op.inValueSlider("Amount", 1); +const trigger = op.outTrigger("trigger"); + +const patternWidth = op.inValueSlider("Width", 0.1); +const patternHeight = op.inValueSlider("Height", 0.1); + + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +op.toWorkPortsNeedToBeLinked(multiplierTex); + + +shader.setSource(shader.getDefaultVertexShader(), attachments.patternlookup_frag); + +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const textureMultiplierUniform = new CGL.Uniform(shader, "t", "patternTex", 1); +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); +const ptrnWidthUniform = new CGL.Uniform(shader, "f", "patternWidth", patternWidth); +const patternHeightUniform = new CGL.Uniform(shader, "f", "patternHeight", patternHeight); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + let multex = multiplierTex.get(); + if (multex) + { + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + if (multex) cgl.setTexture(1, multex.tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + } + + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.PatternLookup.prototype = new CABLES.Op(); +CABLES.OPS["f05f45fe-f3d2-4d99-b1b7-dfae7005382a"]={f:Ops.Gl.TextureEffects.PatternLookup,objName:"Ops.Gl.TextureEffects.PatternLookup"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.PixelColor +// +// ************************************************************** + +Ops.Gl.TextureEffects.PixelColor = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"pixelate_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D srcTex;\nUNI float amount;\n\nUNI vec2 pixelPos;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n\n vec4 base=texture(tex,texCoord);\n vec4 col=texture(srcTex,pixelPos);\n\n outColor=cgl_blendPixel(base,col,amount);\n outColor=col;\n}",}; +const render = op.inTrigger("render"), + srcTex = op.inTexture("Source Texture"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + posX = op.inFloatSlider("Pos X", 0), + posY = op.inFloatSlider("Pos Y", 0), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.pixelate_frag); + +const textureMultiplierUniform = new CGL.Uniform(shader, "t", "srcTex", 1); +const unipos = new CGL.Uniform(shader, "2f", "pixelPos", posX, posY); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); + +// srcTex.onChange = function () +// { +// shader.toggleDefine("PI XELATE_TEXTURE", srcTex.isLinked()); +// }; + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + if (srcTex.get()) cgl.setTexture(1, srcTex.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.PixelColor.prototype = new CABLES.Op(); +CABLES.OPS["114e250c-f569-4963-a3b3-fcdce816406f"]={f:Ops.Gl.TextureEffects.PixelColor,objName:"Ops.Gl.TextureEffects.PixelColor"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.PixelDifference +// +// ************************************************************** + +Ops.Gl.TextureEffects.PixelDifference = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"slope_frag":"\nIN vec2 texCoord;\nUNI sampler2D tex;\nUNI vec2 pixel;\nUNI float strength;\nUNI float sstep;\n\nfloat lum(vec3 c)\n{\n return dot(vec3(0.2126,0.7152,0.0722),c);\n}\n\nvoid main()\n{\n vec4 a,b;\n // vec4 px=texture(tex, texCoord);\n vec4 pxl=texture(tex, texCoord + vec2(-sstep*pixel.x, 0.0));\n vec4 pxr=texture(tex, texCoord + vec2( sstep*pixel.x, 0.0));\n vec4 pxt=texture(tex, texCoord + vec2(0.0, -sstep*pixel.y));\n vec4 pxb=texture(tex, texCoord + vec2(0.0, sstep*pixel.y));\n\n vec4 col=vec4(0.5);\n\n #ifdef DIR_R_HORIZONTAL\n a=pxl;\n b=pxr;\n #endif\n #ifndef DIR_R_HORIZONTAL // VERTICAL\n a=pxt;\n b=pxb;\n #endif\n #ifdef FLIP_R\n vec4 c=a;\n a=b;\n b=c;\n #endif\n #ifdef METH_R_DIFF\n #ifdef METH_R_R\n col.r+=(b.r-a.r)*strength;\n #endif\n #ifdef METH_R_G\n col.r+=(b.g-a.g)*strength;\n #endif\n #ifdef METH_R_B\n col.r+=(b.b-a.b)*strength;\n #endif\n #endif\n #ifdef METH_R_AVG\n #ifdef METH_R_R\n col.r+=(((b.r+a.r-0.5)/2.0))*strength;\n #endif\n #ifdef METH_R_G\n col.r+=(((b.g+a.g-0.5)/2.0))*strength;\n #endif\n #ifdef METH_R_B\n col.r+=(((b.b+a.b-0.5)/2.0))*strength;\n #endif\n #endif\n #ifdef METH_R_LUMI\n col.r+=(lum(b.rgb)-lum(a.rgb))*strength;\n #endif\n #ifdef METH_R_ONE\n col.r=1.0;\n #endif\n #ifdef METH_R_ZERO\n col.r=0.0;\n #endif\n\n\n ////////////////////////\n\n #ifdef DIR_G_HORIZONTAL\n a=pxl;\n b=pxr;\n #endif\n #ifndef DIR_G_HORIZONTAL // VERTICAL\n a=pxt;\n b=pxb;\n #endif\n #ifdef FLIP_G\n vec4 c3=a;\n a=b;\n b=c3;\n #endif\n #ifdef METH_G_DIFF\n #ifdef METH_G_R\n col.g+=(b.r-a.r)*strength;\n #endif\n #ifdef METH_G_G\n col.g+=(b.g-a.g)*strength;\n #endif\n #ifdef METH_G_B\n col.g+=(b.b-a.b)*strength;\n #endif\n #endif\n #ifdef METH_G_AVG\n #ifdef METH_G_R\n col.g+=(((b.r+a.r-0.5)/2.0))*strength;\n #endif\n #ifdef METH_G_G\n col.g+=(((b.g+a.g-0.5)/2.0))*strength;\n #endif\n #ifdef METH_G_B\n col.g+=(((b.b+a.b-0.5)/2.0))*strength;\n #endif\n #endif\n #ifdef METH_G_LUMI\n col.g+=(lum(b.rgb)-lum(a.rgb))*strength;\n #endif\n #ifdef METH_G_ONE\n col.g=1.0;\n #endif\n #ifdef METH_G_ZERO\n col.g=0.0;\n #endif\n\n\n ////////////////////////\n\n #ifdef DIR_B_HORIZONTAL\n a=pxl;\n b=pxr;\n #endif\n #ifndef DIR_B_HORIZONTAL // VERTICAL\n a=pxt;\n b=pxb;\n #endif\n #ifdef FLIP_B\n vec4 c2=a;\n a=b;\n b=c2;\n #endif\n #ifdef METH_B_DIFF\n #ifdef METH_B_R\n col.b+=(b.r-a.r)*strength;\n #endif\n #ifdef METH_B_G\n col.b+=(b.g-a.g)*strength;\n #endif\n #ifdef METH_B_B\n col.b+=(b.b-a.b)*strength;\n #endif\n #endif\n #ifdef METH_B_AVG\n #ifdef METH_B_R\n col.b+=(((b.r+a.r-0.5)/2.0))*strength;\n #endif\n #ifdef METH_B_G\n col.b+=(((b.g+a.g-0.5)/2.0))*strength;\n #endif\n #ifdef METH_B_B\n col.b+=(((b.b+a.b-0.5)/2.0))*strength;\n #endif\n #endif\n #ifdef METH_B_LUMI\n col.b+=(lum(b.rgb)-lum(a.rgb))*strength;\n #endif\n #ifdef METH_B_ONE\n col.b=1.0;\n #endif\n #ifdef METH_B_ZERO\n col.b=0.0;\n #endif\n\n\n\n col.a=1.0;\n\n outColor= col;\n\n}\n",}; +const options = [ + "Vertical Difference Red", "Vertical Difference Green", "Vertical Difference Blue", + "Vertical Average Red", "Vertical Average Green", "Vertical Average Blue", + "Vertical Luminance", + "Horizontal Difference Red", "Horizontal Difference Green", "Horizontal Difference Blue", + "Horizontal Average Red", "Horizontal Average Green", "Horizontal Average Blue", + "Horizontal Luminance", + "Midpoint", "Zero", "One" +]; + +const + render = op.inTrigger("render"), + strength = op.inValue("Strength", 4), + step = op.inValue("Step", 1), + rMeth = op.inDropDown("Red", options, "Horizontal Difference Red"), + rFlip = op.inBool("Red Flip", false), + gMeth = op.inDropDown("Green", options, "Vertical Difference Green"), + gFlip = op.inBool("Green Flip", false), + bMeth = op.inDropDown("Blue", options, "Midpoint"), + bFlip = op.inBool("Blue Flip", false), + trigger = op.outTrigger("trigger"); +op.setPortGroup("Method", [rFlip, gFlip, bFlip, rMeth, gMeth, bMeth]); + +rFlip.onChange = +gFlip.onChange = +bFlip.onChange = +rMeth.onChange = + gMeth.onChange = + bMeth.onChange = updateDefines; + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.slope_frag); +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uniStrength = new CGL.Uniform(shader, "f", "strength", strength), + uniStep = new CGL.Uniform(shader, "f", "sstep", step), + uniRes = new CGL.Uniform(shader, "2f", "pixel"); + +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("DIR_R_HORIZONTAL", (rMeth.get() + "").indexOf("Horizontal") != -1); + shader.toggleDefine("DIR_G_HORIZONTAL", (gMeth.get() + "").indexOf("Horizontal") != -1); + shader.toggleDefine("DIR_B_HORIZONTAL", (bMeth.get() + "").indexOf("Horizontal") != -1); + + shader.toggleDefine("METH_R_DIFF", (rMeth.get() + "").indexOf("Difference") != -1); + shader.toggleDefine("METH_G_DIFF", (gMeth.get() + "").indexOf("Difference") != -1); + shader.toggleDefine("METH_B_DIFF", (bMeth.get() + "").indexOf("Difference") != -1); + + shader.toggleDefine("METH_R_AVG", (rMeth.get() + "").indexOf("Average") != -1); + shader.toggleDefine("METH_G_AVG", (gMeth.get() + "").indexOf("Average") != -1); + shader.toggleDefine("METH_B_AVG", (bMeth.get() + "").indexOf("Average") != -1); + + shader.toggleDefine("METH_R_R", (rMeth.get() + "").indexOf("Red") != -1); + shader.toggleDefine("METH_G_R", (gMeth.get() + "").indexOf("Red") != -1); + shader.toggleDefine("METH_B_R", (bMeth.get() + "").indexOf("Red") != -1); + + shader.toggleDefine("METH_R_G", (rMeth.get() + "").indexOf("Green") != -1); + shader.toggleDefine("METH_G_G", (gMeth.get() + "").indexOf("Green") != -1); + shader.toggleDefine("METH_B_G", (bMeth.get() + "").indexOf("Green") != -1); + + shader.toggleDefine("METH_R_B", (rMeth.get() + "").indexOf("Blue") != -1); + shader.toggleDefine("METH_G_B", (gMeth.get() + "").indexOf("Blue") != -1); + shader.toggleDefine("METH_B_B", (bMeth.get() + "").indexOf("Blue") != -1); + + shader.toggleDefine("METH_R_LUMI", (rMeth.get() + "").indexOf("Luminance") != -1); + shader.toggleDefine("METH_G_LUMI", (gMeth.get() + "").indexOf("Luminance") != -1); + shader.toggleDefine("METH_B_LUMI", (bMeth.get() + "").indexOf("Luminance") != -1); + + shader.toggleDefine("METH_R_MID", (rMeth.get() + "").indexOf("Midpoint") != -1); + shader.toggleDefine("METH_G_MID", (gMeth.get() + "").indexOf("Midpoint") != -1); + shader.toggleDefine("METH_B_MID", (bMeth.get() + "").indexOf("Midpoint") != -1); + + shader.toggleDefine("METH_R_ZERO", (rMeth.get() + "").indexOf("Zero") != -1); + shader.toggleDefine("METH_G_ZERO", (gMeth.get() + "").indexOf("Zero") != -1); + shader.toggleDefine("METH_B_ZERO", (bMeth.get() + "").indexOf("Zero") != -1); + + shader.toggleDefine("METH_R_ONE", (rMeth.get() + "").indexOf("One") != -1); + shader.toggleDefine("METH_G_ONE", (gMeth.get() + "").indexOf("One") != -1); + shader.toggleDefine("METH_B_ONE", (bMeth.get() + "").indexOf("One") != -1); + + shader.toggleDefine("FLIP_R", rFlip.get()); + shader.toggleDefine("FLIP_G", gFlip.get()); + shader.toggleDefine("FLIP_B", bFlip.get()); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + const tex = cgl.currentTextureEffect.getCurrentSourceTexture(); + uniRes.set([1 / tex.width, 1 / tex.height]); + + cgl.setTexture(0, tex.tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.PixelDifference.prototype = new CABLES.Op(); +CABLES.OPS["f4e53fd9-d4c3-4d0e-839a-78543c38b8db"]={f:Ops.Gl.TextureEffects.PixelDifference,objName:"Ops.Gl.TextureEffects.PixelDifference"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.PixelDisplacement_v4 +// +// ************************************************************** + +Ops.Gl.TextureEffects.PixelDisplacement_v4 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"pixeldisplace3_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D displaceTex;\nUNI float amountX;\nUNI float amountY;\nUNI float amount;\n\n{{CGL.BLENDMODES3}}\n\nvec3 getOffset(vec3 offset)\n{\n #ifdef ZERO_BLACK\n return offset;\n #endif\n\n #ifdef ZERO_GREY\n return offset*2.0-1.0;\n #endif\n}\n\nfloat getOffset(float offset)\n{\n #ifdef ZERO_BLACK\n return offset;\n #endif\n\n #ifdef ZERO_GREY\n return offset*2.0-1.0;\n #endif\n}\n\nvoid main()\n{\n vec4 rgba=texture(displaceTex,texCoord);\n vec3 offset=rgba.rgb*rgba.a;\n float x,y;\n\n #ifdef INPUT_REDGREEN\n offset=getOffset(offset);\n x=offset.r*amountX+texCoord.x;\n y=offset.g*amountY+texCoord.y;\n #endif\n #ifdef INPUT_RED\n offset=getOffset(offset);\n x=offset.r*amountX+texCoord.x;\n y=offset.r*amountY+texCoord.y;\n #endif\n #ifdef INPUT_GREEN\n offset=getOffset(offset);\n x=offset.g*amountX+texCoord.x;\n y=offset.g*amountY+texCoord.y;\n #endif\n #ifdef INPUT_BLUE\n offset=getOffset(offset);\n x=offset.b*amountX+texCoord.x;\n y=offset.b*amountY+texCoord.y;\n #endif\n #ifdef INPUT_LUMINANCE\n float o=dot(vec3(0.2126,0.7152,0.0722), offset);\n o=getOffset(o);\n x=o*amountX+texCoord.x;\n y=o*amountY+texCoord.y;\n #endif\n #ifdef WRAP_CLAMP\n x=clamp(x,0.0,1.0);\n y=clamp(y,0.0,1.0);\n #endif\n #ifdef WRAP_REPEAT\n x=mod(x,1.0);\n y=mod(y,1.0);\n #endif\n #ifdef WRAP_MIRROR\n float mx=mod(x,2.0);\n float my=mod(y,2.0);\n x=abs((floor(mx)-fract(mx)));\n y=abs((floor(my)-fract(my)));\n #endif\n\n\n\n vec4 col=texture(tex,vec2(x,y));\n vec4 base=texture(tex,texCoord);\n\n base.a=0.0;\n\n outColor=cgl_blendPixel(base,col,amount);\n}\n",}; +const + render = op.inTrigger("render"), + displaceTex = op.inTexture("displaceTex"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + amountX = op.inValueSlider("amount X", 0.2), + amountY = op.inValueSlider("amount Y", 0.2), + inWrap = op.inSwitch("Wrap", ["Mirror", "Clamp", "Repeat"], "Mirror"), + inInput = op.inValueSelect("Input", ["Luminance", "RedGreen", "Red", "Green", "Blue"], "Luminance"), + inZero = op.inSwitch("Zero Displace", ["Grey", "Black"], "Grey"), + // displaceTex=op.inTexture("displaceTex"), + trigger = op.outTrigger("trigger"); + +op.setPortGroup("Axis Displacement Strength", [amountX, amountY]); +op.setPortGroup("Modes", [inWrap, inInput]); +op.toWorkPortsNeedToBeLinked(displaceTex); + +const + cgl = op.patch.cgl, + shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.pixeldisplace3_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + textureDisplaceUniform = new CGL.Uniform(shader, "t", "displaceTex", 1), + amountXUniform = new CGL.Uniform(shader, "f", "amountX", amountX), + amountYUniform = new CGL.Uniform(shader, "f", "amountY", amountY), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +inZero.onChange = updateZero; +inWrap.onChange = updateWrap; +inInput.onChange = updateInput; + +updateWrap(); +updateInput(); +updateZero(); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +function updateZero() +{ + shader.removeDefine("ZERO_BLACK"); + shader.removeDefine("ZERO_GREY"); + shader.define("ZERO_" + (inZero.get() + "").toUpperCase()); +} + +function updateWrap() +{ + shader.removeDefine("WRAP_CLAMP"); + shader.removeDefine("WRAP_REPEAT"); + shader.removeDefine("WRAP_MIRROR"); + shader.define("WRAP_" + (inWrap.get() + "").toUpperCase()); +} + +function updateInput() +{ + shader.removeDefine("INPUT_LUMINANCE"); + shader.removeDefine("INPUT_REDGREEN"); + shader.removeDefine("INPUT_RED"); + shader.define("INPUT_" + (inInput.get() + "").toUpperCase()); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op,3)) return; + + if(displaceTex.get()) + { + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + if (displaceTex.get()) cgl.setTexture(1, displaceTex.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + } + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.PixelDisplacement_v4.prototype = new CABLES.Op(); +CABLES.OPS["c00f79f2-0505-4b4f-b0bf-10ef7875dd87"]={f:Ops.Gl.TextureEffects.PixelDisplacement_v4,objName:"Ops.Gl.TextureEffects.PixelDisplacement_v4"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Pixelate_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Pixelate_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"pixelate_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D multiplierTex;\nUNI float amount;\nUNI float amountX;\nUNI float amountY;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n vec4 col=vec4(1.0,0.0,0.0,1.0);\n\n float x=1.0/amountX;\n float y=1.0/amountY;\n\n #ifdef PIXELATE_TEXTURE\n x += texture(multiplierTex,texCoord).r*0.1;//*0.1\n y += texture(multiplierTex,texCoord).r*0.1;//*0.1\n #endif\n\n vec2 coord = vec2(x*floor(texCoord.x/x), y*floor(texCoord.y/y));\n\n col=texture(tex,coord);\n vec4 base=texture(tex,texCoord);\n\n outColor=cgl_blendPixel(base,col,amount);\n}",}; +const render = op.inTrigger("render"), + multiplierTex = op.inTexture("Multiplier"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + amountX = op.inValue("width", 100), + amountY = op.inValue("height", 100), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.pixelate_frag); + +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const textureMultiplierUniform = new CGL.Uniform(shader, "t", "multiplierTex", 1); +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); +const amountXUniform = new CGL.Uniform(shader, "f", "amountX", amountX); +const amountYUniform = new CGL.Uniform(shader, "f", "amountY", amountY); + +multiplierTex.onChange = function () +{ + shader.toggleDefine("PIXELATE_TEXTURE", multiplierTex.isLinked()); +}; + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + if (multiplierTex.get()) cgl.setTexture(1, multiplierTex.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Pixelate_v2.prototype = new CABLES.Op(); +CABLES.OPS["c06ae168-ff4f-4ae6-b4d0-06c3b24203bc"]={f:Ops.Gl.TextureEffects.Pixelate_v2,objName:"Ops.Gl.TextureEffects.Pixelate_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Plasma_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Plasma_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"plasma_frag":"#define PI 3.1415926535897932384626433832795\n\nIN vec2 texCoord;\n\nUNI sampler2D tex;\nUNI vec2 size;\nUNI vec2 pos;\nUNI float mul;\nUNI float amount;\nUNI float time;\nUNI float aspect;\n\n#ifdef HAS_TEX_OFFSETMAP\n UNI sampler2D texOffsetZ;\n UNI float offMul;\n#endif\n\n#ifdef HAS_TEX_MASK\n UNI sampler2D texMask;\n#endif\n\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n float v = 0.0;\n\n vec2 s=size;\n #ifdef FIXASPECT\n s.y=size.x/aspect;\n #endif\n\n vec2 c = texCoord * s - s/2.0;\n\n c+=pos;\n\n vec3 offset;\n #ifdef HAS_TEX_OFFSETMAP\n vec4 offMap=texture(texOffsetZ,texCoord);\n\n #ifdef OFFSET_X_R\n offset.x=offMap.r;\n #endif\n #ifdef OFFSET_X_G\n offset.x=offMap.g;\n #endif\n #ifdef OFFSET_X_B\n offset.x=offMap.b;\n #endif\n\n #ifdef OFFSET_Y_R\n offset.y=offMap.r;\n #endif\n #ifdef OFFSET_Y_G\n offset.y=offMap.g;\n #endif\n #ifdef OFFSET_Y_B\n offset.y=offMap.b;\n #endif\n\n #ifdef OFFSET_Z_R\n offset.z=offMap.r;\n #endif\n #ifdef OFFSET_Z_G\n offset.z=offMap.g;\n #endif\n #ifdef OFFSET_Z_B\n offset.z=offMap.b;\n #endif\n offset*=offMul;\n #endif\n\n c+=offset.xy;\n float t=time+offset.z;\n\n v += sin((c.x+t));\n v += sin((c.y+t)/2.0);\n v += sin((c.x+c.y+t)/2.0);\n c += size/2.0 * vec2(sin(t/3.0), cos(t/2.0));\n\n v += sin(sqrt(c.x*c.x+c.y*c.y+1.0)+t);\n v = v/2.0;\n\n vec3 newColor = vec3(sin(PI*v*mul/4.0), sin(PI*v*mul), cos(PI*v*mul))*.5 + .5;\n vec4 base=texture(tex,texCoord);\n\n #ifndef GREY\n vec4 col=vec4( _blend(base.rgb,newColor) ,1.0);\n #endif\n #ifdef GREY\n vec4 col=vec4( _blend(base.rgb,vec3(newColor.g)) ,1.0);\n #endif\n\n float str=1.0;\n #ifdef HAS_TEX_MASK\n str=texture(texMask,texCoord).r;\n #endif\n\n outColor=cgl_blendPixel(base,col,amount*str);\n}\n\n",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + amount = op.inValueSlider("Amount", 1), + w = op.inValue("Width", 20), + h = op.inValue("Height", 20), + inAspect = op.inBool("Aspect", true), + mul = op.inValue("Mul", 1), + x = op.inValue("X", 0), + y = op.inValue("Y", 0), + time = op.inValue("Time", 1), + greyscale = op.inValueBool("Greyscale", true), + + inTexOffsetZ = op.inTexture("Offset"), + inOffsetMul = op.inFloat("Offset Multiply", 1), + offsetX = op.inSwitch("Offset X", ["None", "R", "G", "B"], "None"), + offsetY = op.inSwitch("Offset Y", ["None", "R", "G", "B"], "None"), + offsetZ = op.inSwitch("Offset Time", ["None", "R", "G", "B"], "R"), + + inTexMask = op.inTexture("Mask"), + + trigger = op.outTrigger("trigger"); + +op.setPortGroup("Offset Map", [inTexOffsetZ, offsetZ, offsetY, offsetX, inOffsetMul]); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.plasma_frag); +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +const + uniPos = new CGL.Uniform(shader, "2f", "pos", x, y), + uniSize = new CGL.Uniform(shader, "2f", "size", w, h), + uniTime = new CGL.Uniform(shader, "f", "time", time), + uniMul = new CGL.Uniform(shader, "f", "mul", mul), + uniAspect = new CGL.Uniform(shader, "f", "aspect", 1), + uniOffMul = new CGL.Uniform(shader, "f", "offMul", inOffsetMul), + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + textureUniformOffZ = new CGL.Uniform(shader, "t", "texOffsetZ", 1), + textureUniformMask = new CGL.Uniform(shader, "t", "texMask", 2), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +offsetX.onChange = + inAspect.onChange = + offsetY.onChange = + offsetZ.onChange = + inTexMask.onChange = + greyscale.onChange = + inTexOffsetZ.onLinkChanged = updateDefines; + +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("GREY", greyscale.get()); + + shader.toggleDefine("HAS_TEX_OFFSETMAP", inTexOffsetZ.isLinked()); + shader.toggleDefine("HAS_TEX_MASK", inTexMask.isLinked()); + + shader.toggleDefine("OFFSET_X_R", offsetX.get() == "R"); + shader.toggleDefine("OFFSET_X_G", offsetX.get() == "G"); + shader.toggleDefine("OFFSET_X_B", offsetX.get() == "B"); + + shader.toggleDefine("OFFSET_Y_R", offsetY.get() == "R"); + shader.toggleDefine("OFFSET_Y_G", offsetY.get() == "G"); + shader.toggleDefine("OFFSET_Y_B", offsetY.get() == "B"); + + shader.toggleDefine("OFFSET_Z_R", offsetZ.get() == "R"); + shader.toggleDefine("OFFSET_Z_G", offsetZ.get() == "G"); + shader.toggleDefine("OFFSET_Z_B", offsetZ.get() == "B"); + + offsetX.setUiAttribs({ "greyout": !inTexOffsetZ.isLinked() }); + offsetY.setUiAttribs({ "greyout": !inTexOffsetZ.isLinked() }); + offsetZ.setUiAttribs({ "greyout": !inTexOffsetZ.isLinked() }); + inOffsetMul.setUiAttribs({ "greyout": !inTexOffsetZ.isLinked() }); + + h.setUiAttribs({ "greyout": inAspect.get() }); + shader.toggleDefine("FIXASPECT", inAspect.get()); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + if (inAspect.get()) uniAspect.setValue(cgl.currentTextureEffect.aspectRatio); + else uniAspect.setValue(1); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + if (inTexOffsetZ.get()) cgl.setTexture(1, inTexOffsetZ.get().tex); + if (inTexMask.get()) cgl.setTexture(2, inTexMask.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Plasma_v2.prototype = new CABLES.Op(); +CABLES.OPS["89b3bf34-a9a8-4dcf-a304-9dee597fcf48"]={f:Ops.Gl.TextureEffects.Plasma_v2,objName:"Ops.Gl.TextureEffects.Plasma_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.PolarCoords +// +// ************************************************************** + +Ops.Gl.TextureEffects.PolarCoords = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"polarcoords_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float inner;\nUNI float outer;\n\nvoid main()\n{\n vec4 col=vec4(1.0,0.0,0.0,1.0);\n vec2 x = texCoord - vec2(0.5);\n float radius = length(x);\n float angle = atan(x.y, x.x);\n\n vec2 tc;\n tc.s = ( radius - inner) / (outer - inner);\n tc.t = angle * 0.5 / 3.141592653589793 + 0.5;\n\n #ifdef CROP_IMAGE\n if(tc.s<0.0 || tc.t<0.0 || tc.s>1.0 || tc.t>1.0) discard;\n #endif\n\n col=texture(tex,tc);\n outColor= col;\n}\n",}; +const + render = op.inTrigger("render"), + inner = op.inValueSlider("Radius Inner", 0), + outer = op.inValueSlider("Radius Outer", 1), + crop = op.inValueBool("Crop", false), + trigger = op.outTrigger("trigger"), + cgl = op.patch.cgl; + +const shader = new CGL.Shader(cgl, op.name); +shader.setSource(shader.getDefaultVertexShader(), attachments.polarcoords_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uniinner = new CGL.Uniform(shader, "f", "inner", inner), + uniouter = new CGL.Uniform(shader, "f", "outer", outer); + +crop.onChange = updateCrop; + +function updateCrop() +{ + if (crop.get()) shader.define("CROP_IMAGE"); + else shader.removeDefine("CROP_IMAGE"); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.PolarCoords.prototype = new CABLES.Op(); +CABLES.OPS["1555fefe-4eb4-4aed-84c0-ad54e0dae1c1"]={f:Ops.Gl.TextureEffects.PolarCoords,objName:"Ops.Gl.TextureEffects.PolarCoords"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Posterize_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Posterize_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"posterize_frag":"UNI sampler2D tex;\nIN vec2 texCoord;\nUNI float levels;\nUNI float amount;\n\n{{CGL.BLENDMODES3}}\n\nvoid main(void)\n{\n vec3 srcPixel = texture(tex, texCoord ).rgb;\n vec3 amountPerLevel = vec3(1.0/levels);\n vec3 numOfLevels = floor(srcPixel/amountPerLevel);\n vec3 col = numOfLevels * (vec3(1.0) / (vec3(levels) - vec3(1.0)));\n\n vec4 base=texture(tex,texCoord);\n outColor= cgl_blendPixel(base,vec4(col,base.a),amount);\n}\n\n",}; +const + render = op.inTrigger("Render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + levels = op.inValue("levels", 2), + trigger = op.outTrigger("Trigger"); + +const + cgl = op.patch.cgl, + shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.posterize_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + levelsUniform = new CGL.Uniform(shader, "f", "levels", levels), + uniWidth = new CGL.Uniform(shader, "f", "texWidth", 128), + uniHeight = new CGL.Uniform(shader, "f", "texHeight", 128), + uniAmount = new CGL.Uniform(shader, "f", "amount", amount); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + uniWidth.setValue(cgl.currentTextureEffect.getCurrentSourceTexture().width); + uniHeight.setValue(cgl.currentTextureEffect.getCurrentSourceTexture().height); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Posterize_v2.prototype = new CABLES.Op(); +CABLES.OPS["19703953-7984-4334-af72-0991425b4850"]={f:Ops.Gl.TextureEffects.Posterize_v2,objName:"Ops.Gl.TextureEffects.Posterize_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.PseudoLensFlares +// +// ************************************************************** + +Ops.Gl.TextureEffects.PseudoLensFlares = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"lensflares_frag":"UNI sampler2D tex;\n// UNI sampler2D texInput;\nUNI float haloWidth;\nUNI int numGhosts;\nUNI float dispersal;\nUNI float amountGhosts;\nUNI float amountHalo;\nUNI sampler2D texLookup;\n\nIN vec2 texCoord;\n\nvec3 lumi(vec3 c)\n{\n return vec3(sqrt(c.r*c.r*0.241+c.g*c.g*0.691+c.b*c.b*0.068));\n}\n\nvec4 myTexture(sampler2D tex,vec2 coords)\n{\n vec4 c=texture(tex, coords);\n c.rgb=lumi(c.rgb);\n return c;\n}\n\nvoid main()\n{\n vec2 texcoord = -texCoord + vec2(1.0);\n // vec2 texelSize = 1.0 / vec2(textureSize(texInput, 0));\n vec2 ghostVec = (vec2(0.5) - texcoord) * (0.5*dispersal);\n vec4 result = vec4(0.0,0.0,0.0,1.0);//texture(tex,texCoord);\n\n\n\n // ghosts\n for (int i = 0; i < numGhosts; ++i)\n {\n vec2 offset = fract(texcoord + ghostVec * float(i));\n float weightA = length(vec2(0.5) - offset) / length(vec2(0.5));\n weightA = pow(1. - weightA, 10.0);\n result += myTexture(tex, offset)*weightA*amountGhosts;\n }\n\n // halo\n vec2 haloVec = normalize(ghostVec) * haloWidth;\n float weight = length(vec2(0.5) - fract(texcoord + haloVec)) / length(vec2(0.5));\n\n weight = pow(1.0 - weight, 5.0);\n result += myTexture(tex, texcoord + haloVec) * weight * amountHalo;\n\n #ifdef TEX_LOOPUP\n result *= texture(texLookup, vec2(length(vec2(0.5) - texcoord) / length(vec2(0.5)),0.5));\n #endif\n\n outColor=result;\n}\n\n",}; +// http://john-chapman-graphics.blogspot.com/2013/02/pseudo-lens-flare.html + +const render = op.inTrigger("render"), + inAmountGhosts = op.inValueSlider("Ghosts", 1.0), + inNumGhosts = op.inValueInt("Num Ghosts", 3), + inDispersal = op.inValueSlider("Dispersal", 0.5), + inAmountHalo = op.inValueSlider("Halo", 1.0), + inHaloWidth = op.inValueSlider("Halo Width", 0.5), + textureLookup = op.inTexture("Color Lookup"), + trigger = op.outTrigger("trigger"); + +const + cgl = op.patch.cgl, + shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.lensflares_frag || ""); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + textureLookupUni = new CGL.Uniform(shader, "t", "texLookup", 1), + uniHaloWidth = new CGL.Uniform(shader, "f", "haloWidth", inHaloWidth), + uniNumGhosts = new CGL.Uniform(shader, "i", "numGhosts", inNumGhosts), + uniDispersal = new CGL.Uniform(shader, "f", "dispersal", inDispersal), + uniAmountGhosts = new CGL.Uniform(shader, "f", "amountGhosts", inAmountGhosts), + uniAmounthalo = new CGL.Uniform(shader, "f", "amountHalo", inAmountHalo); + +textureLookup.onChange = function () +{ + if (textureLookup.get())shader.define("TEX_LOOPUP"); + else shader.removeDefine("TEX_LOOPUP"); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + let texture = cgl.currentTextureEffect.getCurrentSourceTexture(); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, texture.tex); + if (textureLookup.get()) cgl.setTexture(1, textureLookup.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.PseudoLensFlares.prototype = new CABLES.Op(); +CABLES.OPS["9e4a5694-ed59-4401-9f7b-123a627924c5"]={f:Ops.Gl.TextureEffects.PseudoLensFlares,objName:"Ops.Gl.TextureEffects.PseudoLensFlares"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.RGBOffset_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.RGBOffset_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"offsetrgb_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float offsetRedX,offsetRedY,offsetGreenX,offsetGreenY,offsetBlueX,offsetBlueY;\nUNI float redAmount,greenAmount,blueAmount;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n vec3 rgb = vec3(texture(tex,texCoord+vec2(offsetRedX,offsetRedY)).r,\n texture(tex,texCoord+vec2(offsetGreenX,offsetGreenY)).g,\n texture(tex,texCoord+vec2(offsetBlueX,offsetBlueY)).b);\n\n vec4 base = texture(tex,texCoord);\n vec4 col = vec4(rgb*vec3(redAmount,greenAmount,blueAmount),base.a);\n\n outColor=cgl_blendPixel(base,col,amount);\n}\n",}; +const + render = op.inTrigger("Render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + offsetRedX = op.inFloat("Red offset X", 0.05), + offsetRedY = op.inFloat("Red offset Y", 0.1), + redAmount = op.inFloat("Red amount", 1.0), + offsetGreenX = op.inFloat("Green offset X", 0.0), + offsetGreenY = op.inFloat("Green offset Y", 0.0), + greenAmount = op.inFloat("Green amount", 1.0), + offsetBlueX = op.inFloat("Blue offset X", 0), + offsetBlueY = op.inFloat("Blue offset Y", 0), + blueAmount = op.inFloat("Blue amount", 1.0), + trigger = op.outTrigger("trigger"); + +op.setPortGroup("Red", [offsetRedX, offsetRedY, redAmount]); +op.setPortGroup("Green", [offsetGreenX, offsetGreenY, greenAmount]); +op.setPortGroup("Blue", [offsetBlueX, offsetBlueY, blueAmount]); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "RGB offset"); + +shader.setSource(shader.getDefaultVertexShader(), attachments.offsetrgb_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + offsetRedUniX = new CGL.Uniform(shader, "f", "offsetRedX", offsetRedX), + offsetRedUniY = new CGL.Uniform(shader, "f", "offsetRedY", offsetRedY), + redUniAmount = new CGL.Uniform(shader, "f", "redAmount", redAmount), + + offsetGreenUniX = new CGL.Uniform(shader, "f", "offsetGreenX", offsetGreenX), + offsetGreenUniY = new CGL.Uniform(shader, "f", "offsetGreenY", offsetGreenY), + greenUniAmount = new CGL.Uniform(shader, "f", "greenAmount", greenAmount), + + offsetBlueUniX = new CGL.Uniform(shader, "f", "offsetBlueX", offsetBlueX), + offsetBlueUniY = new CGL.Uniform(shader, "f", "offsetBlueY", offsetBlueY), + blueUniAmount = new CGL.Uniform(shader, "f", "blueAmount", blueAmount); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op,3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.RGBOffset_v2.prototype = new CABLES.Op(); +CABLES.OPS["41a9655a-6e05-47ee-82b9-f19a33a5cfd4"]={f:Ops.Gl.TextureEffects.RGBOffset_v2,objName:"Ops.Gl.TextureEffects.RGBOffset_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.RectangleTexture_v4 +// +// ************************************************************** + +Ops.Gl.TextureEffects.RectangleTexture_v4 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"rectangle_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\n\nUNI float width;\nUNI float height;\nUNI float x;\nUNI float y;\n\nUNI float r;\nUNI float g;\nUNI float b;\nUNI float a;\n\nUNI float aspect;\nUNI float amount;\nUNI float rotate;\nUNI float roundness;\n\n#define DEG2RAD 0.785398163397\n\n{{CGL.BLENDMODES3}}\n\nmat2 rot(float angle)\n{\n float s=sin(angle);\n float c=cos(angle);\n\n return mat2(c,-s,s,c);\n}\n\nvoid main()\n{\n vec4 base=texture(tex,texCoord);\n vec4 col=vec4(r,g,b,a);\n vec2 p=texCoord;\n\n // p.y*=aspect;\n float d=1.0;\n\n vec2 pos=vec2(x,y);\n pos=pos/2.0+0.5;\n\n\n vec2 pp=p-pos;\n #ifndef CENTER\n pp-=vec2(width,height*aspect);\n #endif\n\n pp=pp*rot(rotate*DEG2RAD/45.0);\n\n float roundn=roundness*min(width,height);\n\n vec2 size=max(vec2(width,height*aspect)-roundn,0.0);\n vec2 absPos=abs(pp)-size;\n\n d=max(absPos.x,absPos.y);\n d=min(d,length(max(absPos,0.0))-roundn);\n d=step(0.0,d);\n\n\n // col=vec4( _blend(base.rgb,vec3(r,g,b)) ,1.0);\n // col=vec4( mix( col.rgb, base.rgb ,1.0-base.a*a*(1.0-d)*amount),1.0);\n // outColor=col;\n\n outColor=cgl_blendPixel(base,col,amount*(1.0-d));\n // outColor=vec4(1.0,1.0,1.0,1.0-d);\n\n\n}\n\n\n\n",}; +const render = op.inTrigger("render"), + amount = op.inValueSlider("Amount", 1), + blendMode = CGL.TextureEffect.AddBlendSelect(op), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + inCenterMode = op.inBool("Center", true), + inWidth = op.inValueSlider("Width", 0.25), + inHeight = op.inValueSlider("Height", 0.25), + inPosX = op.inValueSlider("X", 0), + inPosY = op.inValueSlider("Y", 0), + inRot = op.inValue("Rotate", 0), + inRoundness = op.inValueSlider("roundness", 0), + r = op.inValueSlider("r", 1.0), + g = op.inValueSlider("g", 1.0), + b = op.inValueSlider("b", 1.0), + a = op.inValueSlider("a", 1.0), + trigger = op.outTrigger("trigger"); + +r.setUiAttribs({ "colorPick": true }); + +op.setPortGroup("Size", [inWidth, inHeight]); +op.setPortGroup("Position", [inPosX, inPosY]); +op.setPortGroup("Color", [r, g, b, a]); + +let cgl = op.patch.cgl; +let shader = new CGL.Shader(cgl, "textureeffect rectangle"); +shader.setSource(shader.getDefaultVertexShader(), attachments.rectangle_frag || ""); + +let textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uniHeight = new CGL.Uniform(shader, "f", "height", inHeight), + unWidth = new CGL.Uniform(shader, "f", "width", inWidth), + uniX = new CGL.Uniform(shader, "f", "x", inPosX), + uniY = new CGL.Uniform(shader, "f", "y", inPosY), + uniRot = new CGL.Uniform(shader, "f", "rotate", inRot), + uniRoundness = new CGL.Uniform(shader, "f", "roundness", inRoundness), + uniformR = new CGL.Uniform(shader, "f", "r", r), + uniformG = new CGL.Uniform(shader, "f", "g", g), + uniformB = new CGL.Uniform(shader, "f", "b", b), + uniformA = new CGL.Uniform(shader, "f", "a", a), + uniformAmount = new CGL.Uniform(shader, "f", "amount", amount), + uniformAspect = new CGL.Uniform(shader, "f", "aspect", 1); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +inCenterMode.onChange = updateDefines; +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("CENTER", inCenterMode.get()); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + const texture = cgl.currentTextureEffect.getCurrentSourceTexture(); + uniformAspect.set(cgl.currentTextureEffect.aspectRatio); + + cgl.setTexture(0, texture.tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.RectangleTexture_v4.prototype = new CABLES.Op(); +CABLES.OPS["268ad86e-1f6d-4099-b5c0-e1e0150adbfb"]={f:Ops.Gl.TextureEffects.RectangleTexture_v4,objName:"Ops.Gl.TextureEffects.RectangleTexture_v4"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.RemoveAlpha +// +// ************************************************************** + +Ops.Gl.TextureEffects.RemoveAlpha = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const render = op.inTrigger("render"); +const trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +const srcFrag = "" + + .endl() + "#ifdef HAS_TEXTURES" + .endl() + " IN vec2 texCoord;" + .endl() + " uniform sampler2D tex;" + .endl() + "#endif" + .endl() + "" + .endl() + "" + .endl() + "void main()" + .endl() + "{" + .endl() + " vec4 col=vec4(1.0,0.0,0.0,1.0);" + .endl() + " #ifdef HAS_TEXTURES" + .endl() + " col=texture2D(tex,texCoord);" + .endl() + " col.a=1.0;" + .endl() + " #endif" + .endl() + " outColor= col;" + .endl() + "}"; + +shader.setSource(shader.getDefaultVertexShader(), srcFrag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.RemoveAlpha.prototype = new CABLES.Op(); +CABLES.OPS["98875f07-5dfa-4dfa-921c-de317cdc357e"]={f:Ops.Gl.TextureEffects.RemoveAlpha,objName:"Ops.Gl.TextureEffects.RemoveAlpha"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.RepeatTexture_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.RepeatTexture_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"repeat_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D mulTex;\nUNI float amount;\nUNI float amountX;\nUNI float amountY;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n float am=amount;\n\n float mul=1.0;\n\n #ifdef HAS_MASK\n mul=texture(mulTex,texCoord).r;\n #endif\n\n vec2 coord = vec2(\n mod(texCoord.x*amountX*mul,1.0),\n mod(texCoord.y*amountY*mul,1.0));\n\n vec4 col=texture(tex,coord);\n vec4 base=texture(tex,texCoord);\n\n\n #ifdef CLEAR\n base.a=0.0;\n #endif\n\n outColor=cgl_blendPixel(base,col,am);\n}",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + amountX = op.inValue("x", 3), + amountY = op.inValue("y", 3), + trigger = op.outTrigger("trigger"), + inClear=op.inBool("Clear",true), + mulTex = op.inTexture("Multiply"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.repeat_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + textureMulUniform = new CGL.Uniform(shader, "t", "mulTex", 2), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + amountXUniform = new CGL.Uniform(shader, "f", "amountX", amountX), + amountYUniform = new CGL.Uniform(shader, "f", "amountY", amountY); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +inClear.onChange = +mulTex.onChange =updateDefines; + +function updateDefines() +{ + + shader.toggleDefine("CLEAR", inClear.get()); + shader.toggleDefine("HAS_MASK", mulTex.get()); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op,3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + if (mulTex.get())cgl.setTexture(2, mulTex.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.RepeatTexture_v2.prototype = new CABLES.Op(); +CABLES.OPS["ff9aa796-d781-444c-a9d4-a62157f82dd5"]={f:Ops.Gl.TextureEffects.RepeatTexture_v2,objName:"Ops.Gl.TextureEffects.RepeatTexture_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.RgbMultiply +// +// ************************************************************** + +Ops.Gl.TextureEffects.RgbMultiply = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"rgbmul_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float r;\nUNI float g;\nUNI float b;\n\nvoid main()\n{\n vec4 col=vec4(1.0,0.0,0.0,1.0);\n col=texture(tex,texCoord);\n col.r*=r;\n col.g*=g;\n col.b*=b;\n outColor= col;\n}\n",}; +const render = op.inTrigger("render"); +const r = op.inValue("r", 1); +const g = op.inValue("g", 1); +const b = op.inValue("b", 1); +const trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.rgbmul_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const uniformR = new CGL.Uniform(shader, "f", "r", r); +const uniformG = new CGL.Uniform(shader, "f", "g", g); +const uniformB = new CGL.Uniform(shader, "f", "b", b); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.RgbMultiply.prototype = new CABLES.Op(); +CABLES.OPS["00f30153-f656-4701-9b93-244b033b2eaa"]={f:Ops.Gl.TextureEffects.RgbMultiply,objName:"Ops.Gl.TextureEffects.RgbMultiply"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.RgbToHsvTexture +// +// ************************************************************** + +Ops.Gl.TextureEffects.RgbToHsvTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"tonormal_frag":"#ifdef HAS_TEXTURES\n IN vec2 texCoord;\n UNI sampler2D tex;\n#endif\n\nUNI float strength;\n\n\nvec3 rgb2hsv(vec3 c)\n{\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n\n float d = q.x - min(q.w, q.y);\n float e = 1.0e-10;\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n}\n\nvec3 hsv2rgb(vec3 c)\n{\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\nvoid main()\n{\n vec4 col=texture(tex, texCoord);\n\n\n\n #ifdef OUT_HSB\n col.rgb=rgb2hsv(col.rgb).rgb;\n #endif\n #ifdef OUT_H\n col.rgb=rgb2hsv(col.rgb).rrr;\n #endif\n #ifdef OUT_S\n col.rgb=rgb2hsv(col.rgb).ggg;\n #endif\n #ifdef OUT_B\n col.rgb=rgb2hsv(col.rgb).bbb;\n #endif\n #ifdef OUT_SB\n col.rgb=rgb2hsv(col.rgb).ggg*rgb2hsv(col.rgb).bbb;\n #endif\n\n\n outColor=col;\n}",}; +const + render = op.inTrigger("render"), + inMeth = op.inSwitch("Output RGB", ["HSB", "Hue", "Sat", "Bright", "Sat*Bright"], "HSB"), + trigger = op.outTrigger("trigger"), + cgl = op.patch.cgl, + shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.tonormal_frag); +let textureUniform = new CGL.Uniform(shader, "t", "tex", 0); + +inMeth.onChange = updateDefines; +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("OUT_HSB", inMeth.get() == "HSB"); + shader.toggleDefine("OUT_H", inMeth.get() == "Hue"); + shader.toggleDefine("OUT_S", inMeth.get() == "Sat"); + shader.toggleDefine("OUT_B", inMeth.get() == "Bright"); + shader.toggleDefine("OUT_SB", inMeth.get() == "Sat*Bright"); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.RgbToHsvTexture.prototype = new CABLES.Op(); +CABLES.OPS["147ed29e-f04e-4f7c-b9d7-133d7c6cbef9"]={f:Ops.Gl.TextureEffects.RgbToHsvTexture,objName:"Ops.Gl.TextureEffects.RgbToHsvTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.RotateTexture_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.RotateTexture_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"rotate_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D multiplierTex;\nUNI float amount;\nUNI float resX;\nUNI float resY;\nUNI float rotate;\n\n{{CGL.BLENDMODES3}}\n\n#define PI 3.14159265\n#define TAU (2.0*PI)\n\nvoid pR(inout vec2 p, float a)\n{\n\tp = cos(a)*p + sin(a)*vec2(p.y, -p.x);\n}\n\nvoid main()\n{\n float multiplier = 0.0;\n\n #ifdef ROTATE_TEXTURE\n multiplier = dot(vec3(0.2126,0.7152,0.0722), texture(multiplierTex,texCoord).rgb);\n #endif\n\n vec2 uv = texCoord;\n vec2 res = vec2(resX,resY);\n uv -= 0.5;\n pR(uv.xy,(rotate + multiplier) * (TAU) );\n uv += 0.5;\n\n\n\n vec4 col=texture(tex,uv);\n vec4 base=texture(tex,texCoord);\n\n #ifdef CLEAR\n base.a=0.0;\n #endif\n\n\n #ifdef CROP_IMAGE\n if(uv.x>1.0 ||uv.x<0.0 || uv.y>1.0 ||uv.y<0.0 )\n {\n base.a=0.0;\n col.a=0.0;\n // discard;\n // return;\n }\n #endif\n\n outColor=cgl_blendPixel(base,col,amount);\n}",}; +const render = op.inTrigger("render"), + multiplierTex = op.inTexture("Multiplier"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + inRotate = op.inValueSlider("Rotate", 0.125), + crop = op.inValueBool("Crop", true), + inClear=op.inBool("Clear",true), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "rotatetexture"); + +shader.setSource(shader.getDefaultVertexShader(), attachments.rotate_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + textureMultiplierUniform = new CGL.Uniform(shader, "t", "multiplierTex", 1), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + rotateUniform = new CGL.Uniform(shader, "f", "rotate", inRotate); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +crop.onChange = + multiplierTex.onChange = updateDefines; + +updateDefines(); + + +function updateDefines() +{ + shader.toggleDefine("CLEAR", inClear.get()); + shader.toggleDefine("CROP_IMAGE", crop.get()); + shader.toggleDefine("ROTATE_TEXTURE", multiplierTex.isLinked()); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op,3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + if (multiplierTex.get()) cgl.setTexture(1, multiplierTex.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.RotateTexture_v2.prototype = new CABLES.Op(); +CABLES.OPS["20b8a2e6-2419-474b-98a4-71a5e3178631"]={f:Ops.Gl.TextureEffects.RotateTexture_v2,objName:"Ops.Gl.TextureEffects.RotateTexture_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.RoundCorners +// +// ************************************************************** + +Ops.Gl.TextureEffects.RoundCorners = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"roundcorners_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float radius;\nUNI float r;\nUNI float g;\nUNI float b;\nUNI float a;\n\nUNI float width;\nUNI float height;\n\nfloat roundRect(in vec2 distFromCenter)\n{\n float r=radius*0.25*width+0.01;\n float t = length(max(abs(distFromCenter) - (vec2(0.5*width,0.5*height) - vec2(r,r)), vec2(0.0))) - r;\n return smoothstep(-0.001, 0.9,t);\n}\n\nvoid main()\n{\n vec2 tc=texCoord;\n vec4 col=texture(tex,tc);\n float c=0.0;\n\n c=roundRect(vec2(0.5*width,0.5*height)-vec2(gl_FragCoord));\n outColor=mix(col,vec4(r,g,b,a),c);\n\n}",}; +const + render = op.inTrigger("render"), + radius = op.inValueSlider("radius", 0.25), + r = op.inValueSlider("r"), + g = op.inValueSlider("g"), + b = op.inValueSlider("b"), + a = op.inValueSlider("a", 1), + next = op.outTrigger("next"); + +let cgl = op.patch.cgl; +let shader = new CGL.Shader(cgl, op.name); +shader.setSource(shader.getDefaultVertexShader(), attachments.roundcorners_frag); +let textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +radius.uniform = new CGL.Uniform(shader, "f", "radius", radius); +r.uniform = new CGL.Uniform(shader, "f", "r", r); +g.uniform = new CGL.Uniform(shader, "f", "g", g); +b.uniform = new CGL.Uniform(shader, "f", "b", b); +a.uniform = new CGL.Uniform(shader, "f", "a", a); +r.setUiAttribs({ "colorPick": true }); + +let uniWidth = new CGL.Uniform(shader, "f", "width", 512); +let uniHeight = new CGL.Uniform(shader, "f", "height", 512); +let uniAspect = new CGL.Uniform(shader, "f", "aspect", 1); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + uniWidth.setValue(cgl.currentTextureEffect.getCurrentSourceTexture().width); + uniHeight.setValue(cgl.currentTextureEffect.getCurrentSourceTexture().height); + + let texture = cgl.currentTextureEffect.getCurrentSourceTexture(); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, texture.tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + next.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.RoundCorners.prototype = new CABLES.Op(); +CABLES.OPS["f7e5d8c3-6f49-4769-a863-fbff2c466ce8"]={f:Ops.Gl.TextureEffects.RoundCorners,objName:"Ops.Gl.TextureEffects.RoundCorners"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.SSAO_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.SSAO_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"ssao_frag":"/*\nSSAO GLSL shader v1.2\nassembled by Martins Upitis (martinsh) (devlog-martinsh.blogspot.com)\noriginal technique is made by Arkano22 (www.gamedev.net/topic/550699-ssao-no-halo-artifacts/)\n\nchangelog:\n1.2 - added fog calculation to mask AO. Minor fixes.\n1.1 - added spiral sampling method from here:\n(http://www.cgafaq.info/wiki/Evenly_distributed_points_on_sphere)\n\n*/\n\n{{CGL.BLENDMODES}}\n\nIN vec2 texCoord;\n\nUNI float amount;\n\nUNI sampler2D texDepth;\nUNI sampler2D tex;\n// const float bgl_RenderedTextureWidth=800.0;\n// const float bgl_RenderedTextureHeight=600.0;\n\n#define PI 3.14159265\n\nUNI float width;\nUNI float height;\n// float width = 800.0; //texture width\n// float height = 600.0; //texture height\n\n// vec2 texCoord = texCoord.st;\n\n//------------------------------------------\n//general stuff\n\n//make sure that these two values are the same for your camera, otherwise distances will be wrong.\n\n// const float znear = 0.01; //Z-near\n// const float zfar = 20.0; //Z-far\nUNI float znear;\nUNI float zfar;\n\n//user variables\n// const int SAMPLES = 16; //ao sample count\n// UNI int SAMPLES;\n\n// const float radius = 3.0; //ao radius\n// const float aoclamp = 0.25; //depth clamp - reduces haloing at screen edges\n\nUNI float radius;\nUNI float aoclamp;\nUNI bool noise ; //use noise instead of pattern for sample dithering//*****\nUNI float noiseamount; //dithering amount//********\n\nconst float diffarea = 0.4; //self-shadowing reduction\nconst float gdisplace = 0.4; //gauss bell center\n\n// const bool mist = false; //use mist?\n// const float miststart = 0.0; //mist start\n// const float mistend = 16.0; //mist end\n\n// const bool onlyAO = false; //use only ambient occlusion pass?\n// const float lumInfluence = 0.7; //how much luminance affects occlusion\nUNI float lumInfluence;\n\n\n\n\n//--------------------------------------------------------\n\nvec2 rand(vec2 coord) //generating noise/pattern texture for dithering\n{\n\n #ifndef NOISE\n \treturn vec2(0.0,0.0);\n\t#endif\n\n #ifdef NOISE\n\t\tfloat noiseX = clamp(fract(sin(dot(coord ,vec2(12.9898,78.233))) * 43758.5453),0.0,1.0)*2.0-1.0;\n\t\tfloat noiseY = clamp(fract(sin(dot(coord ,vec2(12.9898,78.233)*2.0)) * 43758.5453),0.0,1.0)*2.0-1.0;\n \treturn vec2(noiseX,noiseY)*noiseamount/100.0;\n #endif\n}\n\n// float doMist()\n// {\n// \tfloat zdepth = texture(texDepth,texCoord.xy).x;\n// \tfloat depth = -zfar * znear / (zdepth * (zfar - znear) - zfar);\n// \treturn clamp((depth-miststart)/mistend,0.0,1.0);\n// }\n\nfloat readDepth(in vec2 coord)\n{\n\tif (texCoord.x<0.0||texCoord.y<0.0) return 1.0;\n\treturn (2.0 * znear) / (zfar + znear - texture(texDepth, coord ).x * (zfar-znear));\n}\n\nfloat compareDepths(in float depth1, in float depth2,inout int far)\n{\n\tfloat garea = 2.0; //gauss bell width\n\tfloat diff = (depth1 - depth2)*100.0; //depth difference (0-100)\n\t//reduce left bell width to avoid self-shadowing\n\tif (diff 0)\n\t{\n\t\ttemp2 = compareDepths(readDepth(coord2),depth,far);\n\t\ttemp += (1.0-temp)*temp2;\n\t}\n\n\treturn temp;\n}\n\nvoid main(void)\n{\n\tvec2 noise = rand(texCoord);\n\tfloat depth = readDepth(texCoord);\n\n\tfloat w = (1.0 / width)/clamp(depth,aoclamp,1.0)+(noise.x*(1.0-noise.x));\n\tfloat h = (1.0 / height)/clamp(depth,aoclamp,1.0)+(noise.y*(1.0-noise.y));\n\n\tfloat pw;\n\tfloat ph;\n\n\tfloat ao;\n\n\tfloat dl = PI*(3.0-sqrt(5.0));\n\tfloat dz = 1.0/float(SAMPLES);\n\tfloat l = 0.0;\n\tfloat z = 1.0 - dz/2.0;\n\n\tfor (int i = 0; i <= SAMPLES; i ++)\n\t{\n\t\tfloat r = sqrt(1.0-z);\n\n\t\tpw = cos(l)*r;\n\t\tph = sin(l)*r;\n\t\tao += calAO(depth,pw*w,ph*h);\n\t\tz = z - dz;\n\t\tl = l + dl;\n\t}\n\n\tao /= float(SAMPLES);\n\tao = 1.0-ao;\n\tvec4 color = texture(tex,texCoord);\n\n\tvec3 lumcoeff = vec3(0.299,0.587,0.114);\n\tfloat lum = dot(color.rgb, lumcoeff);\n\tvec3 luminance = vec3(lum, lum, lum);\n\tvec3 final = vec3(mix( clamp(vec3(ao),0.0,1.0),vec3(1.0),luminance*(1.0-amount)));//mix(color*ao, white, luminance)\n\n vec4 col=vec4( _blend(color.rgb,final) ,1.0);\n\n outColor=vec4( mix( col.rgb, color.rgb ,1.0-color.a*amount),1.0);\n}",}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "multiply"), + amount = op.inValueSlider("Amount", 1), + + depth = op.inTexture("depth texture"), + zNear = op.inValue("Frustum Near", 0.1), + zFar = op.inValue("Frustum Far", 20), + samples = op.inValueInt("Samples", 4), + aoRadius = op.inValue("Ao Radius", 3), + aoClamp = op.inValueSlider("Ao Clamp", 0.25), + lumInfluence = op.inValueSlider("Luminance Influence", 0.7), + noise = op.inValueBool("Enable noise", false), + noiseamount = op.inValueFloat("Noise amount", 0.0008); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +op.toWorkPortsNeedToBeLinked(depth, render); +op.setPortGroup("Noise", [noise, noiseamount]); + +shader.setSource(shader.getDefaultVertexShader(), attachments.ssao_frag); +let textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +let textureAlpha = new CGL.Uniform(shader, "t", "texDepth", 1); +aoRadius.uniform = new CGL.Uniform(shader, "f", "radius", aoRadius); +aoClamp.uniform = new CGL.Uniform(shader, "f", "aoclamp", aoClamp); +lumInfluence.uniform = new CGL.Uniform(shader, "f", "lumInfluence", lumInfluence); +zNear.uniform = new CGL.Uniform(shader, "f", "znear", zNear); +zFar.uniform = new CGL.Uniform(shader, "f", "zfar", zFar); +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); +noiseamount.uniform = new CGL.Uniform(shader, "f", "noiseamount", noiseamount); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +noise.onChange = function () +{ + shader.toggleDefine("NOISE", noise.get()); +}; + +samples.onChange = function () +{ + shader.define("SAMPLES", samples.get()); +}; + +let uniWidth = new CGL.Uniform(shader, "f", "width", 1024), + uniHeight = new CGL.Uniform(shader, "f", "height", 512); + +shader.define("SAMPLES", samples.get()); +aoClamp.uniform = new CGL.Uniform(shader, "f", "aoclamp", aoClamp); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + if (!depth.get()) return; + + uniWidth.setValue(depth.get().width); + uniHeight.setValue(depth.get().height); + + cgl.pushShader(shader); + + cgl.currentTextureEffect.bind(); + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + if (depth.get() && depth.get().tex) + { + cgl.setTexture(1, depth.get().tex); + // cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, depth.get().tex ); + } + + cgl.currentTextureEffect.finish(); + + cgl.popShader(); + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.SSAO_v2.prototype = new CABLES.Op(); +CABLES.OPS["049ad504-09a2-4bc0-bbf1-dad67608a3d2"]={f:Ops.Gl.TextureEffects.SSAO_v2,objName:"Ops.Gl.TextureEffects.SSAO_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ScaleTexture_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.ScaleTexture_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"scale_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D multiplierTex;\nUNI float amount;\nUNI float uScaleX,uScaleY;\nUNI float offsetX,offsetY;\nUNI float centerX,centerY;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n float multiplier = 1.0;\n vec2 uv = texCoord;\n\n #ifdef MASK_SCALE\n multiplier = dot(vec3(0.2126,0.7152,0.0722), texture(multiplierTex,texCoord).rgb);\n #endif\n\n uv.x = (uv.x - centerX) / (uScaleX * multiplier) + centerX+offsetX ;\n uv.y = (uv.y - centerY) / (uScaleY * multiplier) + centerY+offsetY ;\n\n vec4 col = texture(tex,uv);\n vec4 base = texture(tex,texCoord);\n float a=amount;\n\n #ifdef CLEAR\n base=vec4(0.0,0.0,0.0,0.0);\n #endif\n\n outColor=cgl_blendPixel(base,col,a);\n\n if(uv.x>1.0||uv.y>1.0||uv.x<0.0||uv.y<0.0)\n outColor.a=0.0;\n\n}\n",}; +const + render = op.inTrigger("render"), + multiplierTex = op.inTexture("Multiplier"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + scaleX = op.inValue("Scale X", 1.5), + scaleY = op.inValue("Scale Y", 1.5), + offsetX = op.inFloat("offset X", 0), + offsetY = op.inFloat("offset Y", 0), + centerX = op.inFloat("center X", 0.5), + centerY = op.inFloat("center Y", 0.5), + inClear = op.inBool("Clear", true), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.scale_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + textureMultiplierUniform = new CGL.Uniform(shader, "t", "multiplierTex", 1), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + scaleXUniform = new CGL.Uniform(shader, "f", "uScaleX", scaleX), + scaleYUniform = new CGL.Uniform(shader, "f", "uScaleY", scaleY), + centerXUniform = new CGL.Uniform(shader, "f", "centerX", centerX), + centerYUniform = new CGL.Uniform(shader, "f", "centerY", centerY), + offsetXUniform = new CGL.Uniform(shader, "f", "offsetX", offsetX), + offsetYUniform = new CGL.Uniform(shader, "f", "offsetY", offsetY); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +inClear.onChange = +multiplierTex.onChange = function () +{ + shader.toggleDefine("MASK_SCALE", multiplierTex.isLinked()); + shader.toggleDefine("CLEAR", inClear.get()); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + if (multiplierTex.get()) cgl.setTexture(1, multiplierTex.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.ScaleTexture_v2.prototype = new CABLES.Op(); +CABLES.OPS["942ef040-9be9-4848-9122-61cb28cb7789"]={f:Ops.Gl.TextureEffects.ScaleTexture_v2,objName:"Ops.Gl.TextureEffects.ScaleTexture_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ScrollTexture +// +// ************************************************************** + +Ops.Gl.TextureEffects.ScrollTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"scroll_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amountX;\nUNI float amountY;\n\n#ifdef HAS_MASK\n UNI sampler2D texMask;\n#endif\n\nvoid main()\n{\n float amX=amountX;\n float amY=amountY;\n\n #ifdef HAS_MASK\n vec4 m=texture(texMask,texCoord);\n\n\n amX*=(m.r-0.5)*2.0;\n amY*=(m.g-0.5)*2.0;\n #endif\n\n vec4 col=vec4(0.0,0.0,0.0,1.0);\n float x=mod(texCoord.x+amX,1.0);\n float y=mod(texCoord.y+amY,1.0);\n\n\n #ifdef NO_REPEAT\n x=texCoord.x+amX*0.1;\n y=texCoord.y+amY*0.1;\n #endif\n\n col=texture(tex,vec2(x,y));\n\n #ifdef NO_REPEAT\n if(x>1.0 || x<0.0 || y>1.0 || y<0.0) col=vec4(0.0,0.0,0.0,0.0);\n #endif\n outColor= col;\n}",}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + amountX = op.inValue("amountX"), + amountY = op.inValue("amountY"), + textureMask = op.inTexture("Mask"), + repeat = op.inValueBool("Repeat", true); + +repeat.onChange = updateRepeat; + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); +shader.setSource(shader.getDefaultVertexShader(), attachments.scroll_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountXUniform = new CGL.Uniform(shader, "f", "amountX", amountX), + amountYUniform = new CGL.Uniform(shader, "f", "amountY", amountY), + unitexMask = new CGL.Uniform(shader, "t", "texMask", 1); + +updateRepeat(); + +textureMask.onChange = function () +{ + if (textureMask.get())shader.define("MASK"); + else shader.removeDefine("MASK"); +}; + +function updateRepeat() +{ + if (!repeat.get())shader.define("NO_REPEAT"); + else shader.removeDefine("NO_REPEAT"); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + if (textureMask.get()) cgl.setTexture(1, textureMask.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.ScrollTexture.prototype = new CABLES.Op(); +CABLES.OPS["9b151d99-7888-4948-81c7-cd23b334e8d4"]={f:Ops.Gl.TextureEffects.ScrollTexture,objName:"Ops.Gl.TextureEffects.ScrollTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Shapes2d_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Shapes2d_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"shapes_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float aspect;\n\nUNI bool mirrorX;\nUNI bool mirrorY;\n\nUNI float xPos;\nUNI float yPos;\n\nUNI bool invertColor;\nUNI bool fillShape;\n\nUNI float width;\nUNI float height;\nUNI float lineThickness;\n\nUNI float rotate;\n\nUNI float r;\nUNI float g;\nUNI float b;\nUNI float a;\n\n{{CGL.BLENDMODES3}}\n\n#define PI 3.14159265\n#define TAU (2.0*PI)\n\nvoid pR(inout vec2 p, float a)\n{\n\tp = cos(a)*p + sin(a)*vec2(p.y, -p.x);\n}\n\nfloat sdCircle( vec2 p, float r )\n{\n return length(p) - r;\n}\n\nfloat sdBox( in vec2 p, in vec2 b )\n{\n vec2 d = abs(p)-b;\n return length(max(d,vec2(0))) + min(max(d.x,d.y),0.0);\n}\n\nfloat sdEquilateralTriangle( in vec2 p , in float size )\n{\n const float k = sqrt(3.0);\n p/= vec2(size);\n p.x = abs(p.x) - 1.0;\n p.y = -p.y + 1.0/k;\n if( p.x + k*p.y > 0.0 ) p = vec2( p.x - k*p.y, -k*p.x - p.y )/2.0;\n p.x -= clamp( p.x, -2.0, 0.0 );\n return (-length(p)*sign(p.y))*size;\n}\n\nfloat sdTriangleIsosceles( in vec2 p, in vec2 q )\n{\n\n p.y +=0.5;\n p.x = abs(p.x);\n\n vec2 a = p - q*clamp( dot(p,q)/dot(q,q), 0.0, 1.0 );\n vec2 b = p - q*vec2( clamp( p.x/q.x, 0.0, 1.0 ), 1.0 );\n float s = -sign( q.y );\n vec2 d = min( vec2( dot(a,a), s*(p.x*q.y-p.y*q.x) ),\n vec2( dot(b,b), s*(p.y-q.y) ));\n\n return -sqrt(d.x)*sign(d.y);\n}\n\nfloat ndot(vec2 a, vec2 b ) { return a.x*b.x - a.y*b.y; }\n\nfloat sdRhombus( in vec2 p, in vec2 b )\n{\n vec2 q = abs(p);\n float h = clamp((-2.0*ndot(q,b)+ndot(b,b))/dot(b,b),-1.0,1.0);\n float d = length( q - 0.5*b*vec2(1.0-h,1.0+h) );\n return d * sign( q.x*b.y + q.y*b.x - b.x*b.y );\n}\n\nfloat sdPentagon( in vec2 p, in float r )\n{\n const vec3 k = vec3(0.809016994,0.587785252,0.726542528);\n p.x = abs(p.x);\n p -= 2.0*min(dot(vec2(-k.x,k.y),p),0.0)*vec2(-k.x,k.y);\n p -= 2.0*min(dot(vec2( k.x,k.y),p),0.0)*vec2( k.x,k.y);\n p -= vec2(clamp(p.x,-r*k.z,r*k.z),r);\n return length(p)*sign(p.y);\n}\n\nfloat sdHexagon( in vec2 p, in float r )\n{\n const vec3 k = vec3(-0.866025404,0.5,0.577350269);\n p = abs(p);\n p -= 2.0*min(dot(k.xy,p),0.0)*k.xy;\n p -= vec2(clamp(p.x, -k.z*r, k.z*r), r);\n return length(p)*sign(p.y);\n}\n\nfloat sdOctogon( in vec2 p, in float r )\n{\n const vec3 k = vec3(-0.9238795325, 0.3826834323, 0.4142135623 );\n p = abs(p);\n p -= 2.0*min(dot(vec2( k.x,k.y),p),0.0)*vec2( k.x,k.y);\n p -= 2.0*min(dot(vec2(-k.x,k.y),p),0.0)*vec2(-k.x,k.y);\n p -= vec2(clamp(p.x, -k.z*r, k.z*r), r);\n return length(p)*sign(p.y);\n}\n\nfloat sdHexagram( in vec2 p, in float r )\n{\n const vec4 k=vec4(-0.5,0.8660254038,0.5773502692,1.7320508076);\n p = abs(p);\n p -= 2.0*min(dot(k.xy,p),0.0)*k.xy;\n p -= 2.0*min(dot(k.yx,p),0.0)*k.yx;\n p -= vec2(clamp(p.x,r*k.z,r*k.w),r);\n return length(p)*sign(p.y);\n}\n\nvoid main()\n{\n vec2 p = texCoord-0.5;\n p.y/=aspect;\n\n p *= 2.0;\n\n float d =0.0;\n\n if(mirrorX)p.x = abs(p.x);\n if(mirrorY)p.y = abs(p.y);\n\n p -= vec2(xPos,yPos/aspect);\n\n pR(p,rotate * (TAU) + PI);\n\n #ifdef IS_CIRCLE\n\n d = sdCircle(p,width);\n #endif\n\n #ifdef IS_EQUI_TRIANGLE\n d = sdEquilateralTriangle(p,width);\n #endif\n\n #ifdef IS_ISO_TRIANGLE\n d = sdTriangleIsosceles(p,vec2(width,height));\n #endif\n\n #ifdef IS_BOX\n d = sdBox(p,vec2(width,height));\n #endif\n\n #ifdef IS_RHOMBUS\n d = sdRhombus(p,vec2(width,height));\n #endif\n\n #ifdef IS_PENTAGON\n d = sdPentagon(p,width);\n #endif\n\n #ifdef IS_HEXAGON\n d = sdHexagon(p,width);\n #endif\n\n #ifdef IS_OCTOGON\n d = sdOctogon(p,width);\n #endif\n\n #ifdef IS_HEXAGRAM\n d = sdHexagram(p*2.0,width);\n #endif\n\n if (fillShape == false)\n {\n d = abs(d)-abs(lineThickness*0.01);\n }\n if(invertColor)\n {\n d = sign(d);\n }\n else\n {\n d = 1.0 - sign(d);\n }\n\n d = clamp(d,0.0,1.0);\n\n vec4 col = vec4(vec4(r,g,b,a)) ;\n vec4 base = texture(tex,texCoord);\n outColor = cgl_blendPixel(base,col,d*amount);\n}\n\n\n",}; +/* +Shaders are from Iq's webapge +https://www.iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm +*/ + +const render = op.inTrigger("render"); +const blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"); +const maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op); + +const amount = op.inValueSlider("Amount", 1); + +const shapeSelect = op.inValueSelect("Shape", ["circle", "eqi triangle", "iso triangle", "box", "rhombus", "pentagon", + "hexagon", "octogon", "hexagram"], "circle"); +const mirrorX = op.inValueBool("Mirror X", false); +const mirrorY = op.inValueBool("Mirror Y", false); + +const xPos = op.inValueFloat("Offset X", 0.0); +const yPos = op.inValueFloat("Offset Y", 0.0); + +const fillShape = op.inValueBool("fillShape", true); +const lineThickness = op.inValue("Line thickness", 1.0); +const invertColor = op.inValueBool("Invert color", false); + +const width = op.inValue("width", 0.5); +const height = op.inValue("height", 0.5); + +const inRotate = op.inValueSlider("Rotate", 0.0); + +const r = op.inValueSlider("r", Math.random()), + g = op.inValueSlider("g", Math.random()), + b = op.inValueSlider("b", Math.random()), + a = op.inValueSlider("a", 1.0); +r.setUiAttribs({ "colorPick": true }); + +const trigger = op.outTrigger("trigger"); + +let selectIndex = 0; + +function onFilterChange() +{ + let selectedMode = shapeSelect.get(); + + if ((selectedMode === "circle") || (selectedMode === "eqi triangle") || (selectedMode === "pentagon") + || (selectedMode === "hexagon") || (selectedMode === "octogon") || (selectedMode === "hexagram")) + selectIndex = 0; + + else if ((selectedMode === "box") || (selectedMode === "iso triangle") || (selectedMode === "rhombus")) + selectIndex = 1; + + if (selectIndex === 0) + { + height.setUiAttribs({ "greyout": true }); + width.setUiAttribs({ "title": "Size" }); + } + else if (selectIndex === 1) + { + height.setUiAttribs({ "greyout": false }); + width.setUiAttribs({ "title": "Width" }); + } +} + +fillShape.onChange = function () +{ + lineThickness.setUiAttribs({ "greyout": fillShape.get() }); +}; + +op.init = shapeSelect.onChange = function () +{ + onFilterChange(); + // choose shape + shader.toggleDefine("IS_CIRCLE", shapeSelect.get()); + shader.toggleDefine("IS_EQUI_TRIANGLE", shapeSelect.get() === "eqi triangle"); + shader.toggleDefine("IS_ISO_TRIANGLE", shapeSelect.get() === "iso triangle"); + shader.toggleDefine("IS_BOX", shapeSelect.get() === "box"); + shader.toggleDefine("IS_RHOMBUS", shapeSelect.get() === "rhombus"); + shader.toggleDefine("IS_PENTAGON", shapeSelect.get() === "pentagon"); + shader.toggleDefine("IS_HEXAGON", shapeSelect.get() === "hexagon"); + shader.toggleDefine("IS_OCTOGON", shapeSelect.get() === "octogon"); + shader.toggleDefine("IS_HEXAGRAM", shapeSelect.get() === "hexagram"); +}; + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.shapes_frag); + +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); +const mirrorXUniform = new CGL.Uniform(shader, "b", "mirrorX", mirrorX); +const mirrorYUniform = new CGL.Uniform(shader, "b", "mirrorY", mirrorY); + +const xPosUniform = new CGL.Uniform(shader, "f", "xPos", xPos); +const yPosUniform = new CGL.Uniform(shader, "f", "yPos", yPos); +const invertColorUniform = new CGL.Uniform(shader, "b", "invertColor", invertColor); +const fillShapeUniform = new CGL.Uniform(shader, "b", "fillShape", fillShape); + +const uniWidth = new CGL.Uniform(shader, "f", "width", width); +const uniHeight = new CGL.Uniform(shader, "f", "height", height); +const uniModifier = new CGL.Uniform(shader, "f", "lineThickness", lineThickness); +const rotateUniform = new CGL.Uniform(shader, "f", "rotate", inRotate); + +let uniformR = new CGL.Uniform(shader, "f", "r", r); +let uniformG = new CGL.Uniform(shader, "f", "g", g); +let uniformB = new CGL.Uniform(shader, "f", "b", b); +let uniformA = new CGL.Uniform(shader, "f", "a", a); +let uniformAspect = new CGL.Uniform(shader, "f", "aspect", 1); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +render.onTriggered = update; +function update() +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + fillShapeUniform.setValue(fillShape.get()); + uniformAspect.setValue(cgl.currentTextureEffect.aspectRatio); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +} + + +}; + +Ops.Gl.TextureEffects.Shapes2d_v2.prototype = new CABLES.Op(); +CABLES.OPS["1b81100b-7c09-4171-ae82-8865b905720e"]={f:Ops.Gl.TextureEffects.Shapes2d_v2,objName:"Ops.Gl.TextureEffects.Shapes2d_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Sharpen +// +// ************************************************************** + +Ops.Gl.TextureEffects.Sharpen = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"sharpen_frag":"\nIN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\n\nUNI float pX,pY;\n\nconst vec4 lumcoeff = vec4(0.299,0.587,0.114, 0.);\n\nfloat desaturate(vec4 color)\n{\n vec3 c= vec3(dot(vec3(0.2126,0.7152,0.0722), color.rgb));\n return (c.r+c.g+c.b)/3.0;\n}\n\n\n\nvoid main()\n{\n \n vec4 col=vec4(1.0,0.0,0.0,1.0);\n col=texture(tex,texCoord);\n \n \n float colorL = desaturate(texture(tex, texCoord+vec2(-pX,0) ));\n float colorR = desaturate(texture(tex, texCoord+vec2( pX,0) ));\n float colorA = desaturate(texture(tex, texCoord+vec2( 0,-pY) ));\n float colorB = desaturate(texture(tex, texCoord+vec2( 0, pY) ));\n \n float colorLA = desaturate(texture(tex, texCoord+vec2(-pX,pY)));\n float colorRA = desaturate(texture(tex, texCoord+vec2( pX,pY)));\n float colorLB = desaturate(texture(tex, texCoord+vec2(-pX,-pY)));\n float colorRB = desaturate(texture(tex, texCoord+vec2( pX,-pY)));\n \n vec4 final = col + col * amount * (8.0*desaturate(col) - colorL - colorR - colorA - colorB - colorLA - colorRA - colorLB - colorRB);\n\n outColor= final;\n\n}",}; +const render = op.inTrigger("Render"); +const trigger = op.outTrigger("Trigger"); +const amount = op.inValueSlider("amount", 0.5); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.sharpen_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +const uniPx = new CGL.Uniform(shader, "f", "pX", 1 / 1024); +const uniPy = new CGL.Uniform(shader, "f", "pY", 1 / 1024); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + uniPx.setValue(1 / cgl.currentTextureEffect.getCurrentSourceTexture().width); + uniPy.setValue(1 / cgl.currentTextureEffect.getCurrentSourceTexture().height); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Sharpen.prototype = new CABLES.Op(); +CABLES.OPS["55647083-131d-4c70-b667-21fecf311ea5"]={f:Ops.Gl.TextureEffects.Sharpen,objName:"Ops.Gl.TextureEffects.Sharpen"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.SkewStretchImage_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.SkewStretchImage_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"invert_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float stretchTopX;\nUNI float stretchBotX;\nUNI float stretchLeft;\nUNI float stretchRight;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n vec4 col=vec4(1.0,0.0,0.0,1.0);\n\n vec2 tc=texCoord;\n\n #ifdef SMOOTHSTEP\n tc.y=smoothstep(0.,1.,tc.y);\n tc.x=smoothstep(0.,1.,tc.x);\n #endif\n\n vec2 tcnorm=texCoord;\n\n tcnorm-=0.5;\n tcnorm*=2.0;\n\n tcnorm.x=mix(tcnorm.x*stretchBotX,tcnorm.x,tc.y);\n tcnorm.x=mix(tcnorm.x*stretchTopX,tcnorm.x,1.0-tc.y);\n\n tcnorm.y=mix(tcnorm.y*stretchLeft,tcnorm.y,tc.x);\n tcnorm.y=mix(tcnorm.y*stretchRight,tcnorm.y,1.0-tc.x);\n\n tc=tcnorm/2.0+0.5;\n\n col=texture(tex,tc);\n\n #ifdef CLAMP\n if(tc.x<0.0 || tc.x>1.0 || tc.y<0.0 || tc.y>1.0) col=vec4(0.0,0.0,0.0,0.0);\n #endif\n\n vec4 base=texture(tex,texCoord);\n base.a=0.0;\n\n outColor=cgl_blendPixel(base,col,amount);\n}\n",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + inClamp = op.inBool("Clamp", true), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "skewstrechimage"); +shader.setSource(shader.getDefaultVertexShader(), attachments.invert_frag); + +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +shader.addUniformFrag("f", "stretchTopX", op.inFloat("Stretch Top", 1)); +shader.addUniformFrag("f", "stretchBotX", op.inFloat("Stretch Bottom", 1)); +shader.addUniformFrag("f", "stretchLeft", op.inFloat("Stretch Left", 1)); +shader.addUniformFrag("f", "stretchRight", op.inFloat("Stretch Right", 1)); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +inClamp.onChange = updateDefines; + +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("CLAMP", inClamp.get()); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.SkewStretchImage_v2.prototype = new CABLES.Op(); +CABLES.OPS["665bbc0c-2fd7-4683-a1df-e57d8f17da93"]={f:Ops.Gl.TextureEffects.SkewStretchImage_v2,objName:"Ops.Gl.TextureEffects.SkewStretchImage_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Stripes_v4 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Stripes_v4 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"stripes_v3_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float num;\nUNI float width;\nUNI float axis;\nUNI float offset;\nUNI float rotate;\n\nUNI float r;\nUNI float g;\nUNI float b;\n\n\n{{CGL.BLENDMODES3}}\n\n#define PI 3.14159265\n#define TAU (2.0*PI)\n\nvoid pR(inout vec2 p, float a)\n{\n\tp = cos(a)*p + sin(a)*vec2(p.y, -p.x);\n}\nvoid main()\n{\n vec2 uv = texCoord-0.5;\n pR(uv.xy,rotate*TAU);\n float stripe=0.0;\n\n float v=0.0;\n float c=1.0;\n v=uv.y;\n v+=offset;\n\n float m=mod(v,1.0/num);\n\n #ifdef CIRCULAR\n m=mod((length(uv)+offset)*1.5,1.0/num);\n #endif\n\n float rm=width*2.0*1.0/num/2.0;\n\n if(m>rm)\n stripe=mix(stripe,1.,1.0);\n\n #ifdef STRIPES_SMOOTHED\n m*=2.0;\n stripe= r * smoothstep(0.,1., abs((((m-rm) )/(rm))));\n #endif\n\n #ifdef INVERT\n stripe=1.0-stripe;\n #endif\n\n //blend section\n vec4 col=vec4(vec3(r,g,b),1.0);\n vec4 base=texture(tex,texCoord);\n\n outColor=cgl_blendPixel(base,col,amount*stripe);\n}\n",}; +const + render = op.inTrigger("Render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + num = op.inValue("Num", 5), + width = op.inValue("Width", 0.5), + rotate = op.inValueSlider("Rotate", 0), + offset = op.inValue("Offset", 0), + smoothed = op.inValueBool("Gradients"), + circular = op.inValueBool("Circular"), + invert = op.inValueBool("Invert"), + r = op.inValueSlider("r", Math.random()), + g = op.inValueSlider("g", Math.random()), + b = op.inValueSlider("b", Math.random()), + trigger = op.outTrigger("trigger"); + +r.setUiAttribs({ "colorPick": true }); + +smoothed.onChange = + circular.onChange = + invert.onChange = updateDefines; + +function updateDefines() +{ + shader.toggleDefine("STRIPES_SMOOTHED", smoothed.get()); + shader.toggleDefine("CIRCULAR", circular.get()); + shader.toggleDefine("INVERT", invert.get()); +} + +const + cgl = op.patch.cgl, + shader = new CGL.Shader(cgl, "textureeffect stripes"); + +shader.setSource(shader.getDefaultVertexShader(), attachments.stripes_v3_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + rotateUniform = new CGL.Uniform(shader, "f", "rotate", rotate), + numUniform = new CGL.Uniform(shader, "f", "num", num), + uniWidth = new CGL.Uniform(shader, "f", "width", width), + uniOffset = new CGL.Uniform(shader, "f", "offset", offset), + uniformR = new CGL.Uniform(shader, "f", "r", r), + uniformG = new CGL.Uniform(shader, "f", "g", g), + uniformB = new CGL.Uniform(shader, "f", "b", b); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Stripes_v4.prototype = new CABLES.Op(); +CABLES.OPS["a1d57718-20a0-4d18-89d3-69947b0d1acf"]={f:Ops.Gl.TextureEffects.Stripes_v4,objName:"Ops.Gl.TextureEffects.Stripes_v4"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.TexMathModulo +// +// ************************************************************** + +Ops.Gl.TextureEffects.TexMathModulo = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"invert_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D texMask;\nUNI float amount;\nUNI float modulo;\n\n{{CGL.BLENDMODES}}\n\nvoid main()\n{\n vec4 col=vec4(1.0);\n col=texture(tex,texCoord);\n\n #ifdef USE_MASK\n #ifdef MASK_INVERT\n if(texture(texMask,texCoord).r>0.5)\n {\n outColor= col;\n return;\n }\n #endif\n\n #ifndef MASK_INVERT\n if(texture(texMask,texCoord).r<0.5)\n {\n outColor= col;\n return;\n }\n #endif\n #endif\n\n vec4 invert = vec4(mod(col.rgb,modulo),1.0);\n\n outColor=cgl_blend(col,invert,amount);\n}\n",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + + maskInvert = op.inBool("Mask Invert", false), + mask = op.inTexture("Mask"), + + amount = op.inValueSlider("Amount", 1), + modulo = op.inValueSlider("modulo", 1), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "texmodulo"); + +shader.setSource(shader.getDefaultVertexShader(), attachments.invert_frag); +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + moduloUniform = new CGL.Uniform(shader, "f", "modulo", modulo), + textureMaskUniform = new CGL.Uniform(shader, "t", "texMask", 1); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +maskInvert.onChange = +mask.onChange = () => +{ + shader.toggleDefine("USE_MASK", mask.isLinked()); + shader.toggleDefine("MASK_INVERT", maskInvert.get()); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + if (mask.get())cgl.setTexture(1, mask.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.TexMathModulo.prototype = new CABLES.Op(); +CABLES.OPS["9105dc83-9cb9-4a5e-9ec0-db641436dbe2"]={f:Ops.Gl.TextureEffects.TexMathModulo,objName:"Ops.Gl.TextureEffects.TexMathModulo"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.TextureDifference +// +// ************************************************************** + +Ops.Gl.TextureEffects.TextureDifference = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"tex_difference_frag":"\nIN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D tex1;\nUNI sampler2D tex2;\n\nvoid main()\n{\n\n vec4 col=texture(tex,texCoord);\n \n vec4 col1=texture(tex1,texCoord);\n vec4 col2=texture(tex2,texCoord);\n\n\n outColor = col1-col2;\n outColor.a=1.0;\n\n}\n",}; +const render = op.inTrigger("render"); +const texture1 = op.inTexture("Texture 1"); +const texture2 = op.inTexture("Texture 2"); + +const trigger = op.outTrigger("Next"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.tex_difference_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const unitex1 = new CGL.Uniform(shader, "t", "tex1", 1); +const unitex2 = new CGL.Uniform(shader, "t", "tex2", 2); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + if (texture1.get() && texture2.get()) + { + let texture = cgl.currentTextureEffect.getCurrentSourceTexture(); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, texture.tex); + cgl.setTexture(1, texture1.get().tex); + cgl.setTexture(2, texture2.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + } + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.TextureDifference.prototype = new CABLES.Op(); +CABLES.OPS["e8f01999-ad25-4a75-9cac-46468551ba67"]={f:Ops.Gl.TextureEffects.TextureDifference,objName:"Ops.Gl.TextureEffects.TextureDifference"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ToNormalMap_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.ToNormalMap_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"tonormal_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI vec2 size;\nUNI float strength;\nUNI float sizeMul;\n\nvoid main()\n{\n float tl = abs(texture(tex, texCoord + (size*sizeMul) * vec2(-1.0, -1.0)).x); // top left\n float l = abs(texture(tex, texCoord + (size*sizeMul) * vec2(-1.0, 0.0)).x); // left\n float bl = abs(texture(tex, texCoord + (size*sizeMul) * vec2(-1.0, 1.0)).x); // bottom left\n float t = abs(texture(tex, texCoord + (size*sizeMul) * vec2( 0.0, -1.0)).x); // top\n float b = abs(texture(tex, texCoord + (size*sizeMul) * vec2( 0.0, 1.0)).x); // bottom\n float tr = abs(texture(tex, texCoord + (size*sizeMul) * vec2( 1.0, -1.0)).x); // top right\n float r = abs(texture(tex, texCoord + (size*sizeMul) * vec2( 1.0, 0.0)).x); // right\n float br = abs(texture(tex, texCoord + (size*sizeMul) * vec2( 1.0, 1.0)).x); // bottom right\n\n // Compute dx using Sobel:\n // -1 0 1\n // -2 0 2\n // -1 0 1\n float dX = tr + 2.0*r + br -tl - 2.0*l - bl;\n\n // Compute dy using Sobel:\n // -1 -2 -1\n // 0 0 0\n // 1 2 1\n float dY = bl + 2.0*b + br -tl - 2.0*t - tr;\n\n // Build the normalized normal\n vec4 N = vec4(normalize(vec3(dX,dY, 1.0 / strength)), 1.0);\n N= N * 0.5 + 0.5;\n\n outColor= N;\n}",}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + strength = op.inValue("Strength", 4), + sizeMul = op.inValue("Step Multiplier", 1); + +const + cgl = op.patch.cgl, + shader = new CGL.Shader(cgl, op.name); + +// from: https://forum.openframeworks.cc/t/compute-normal-map-from-image/1400/11 +shader.setSource(shader.getDefaultVertexShader(), attachments.tonormal_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + uniStrength = new CGL.Uniform(shader, "f", "strength", strength), + unisizeMul = new CGL.Uniform(shader, "f", "sizeMul", sizeMul), + uniSize = new CGL.Uniform(shader, "2f", "size", 0,0); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + const effectTex=cgl.currentTextureEffect.getCurrentSourceTexture(); + + cgl.setTexture(0, effectTex.tex); + + uniSize.setValue([1/effectTex.width,1/effectTex.height]); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.ToNormalMap_v2.prototype = new CABLES.Op(); +CABLES.OPS["5dfb2856-b589-4bd9-8f4e-b518da115d11"]={f:Ops.Gl.TextureEffects.ToNormalMap_v2,objName:"Ops.Gl.TextureEffects.ToNormalMap_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Twirl_v4 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Twirl_v4 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"twirl_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\nUNI float twistAmount;\nUNI float times;\nUNI float radius;\nUNI float centerX;\nUNI float centerY;\nUNI float aspect;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n vec2 center=vec2(centerX,centerY);\n center =((center+1.0)/2.0);\n vec2 tc = texCoord;\n tc -= center;\n\n float dist = length(vec2(tc.x,tc.y/aspect));\n if (dist < radius)\n {\n float percent = (radius - dist) / radius;\n float theta = percent * percent * twistAmount * 8.0;\n float s = sin(theta);\n float c = cos(theta);\n tc = vec2(dot(tc, vec2(c, -s)), dot(tc, vec2(s, c)));\n }\n tc += center;\n\n vec4 col = texture(tex, tc);\n vec4 base=texture(tex,texCoord);\n outColor=cgl_blendPixel(base,col,amount);\n}\n",}; +const render = op.inTrigger("Render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + twistAmount = op.inValue("Twist amount", 500), + radius = op.inValue("Radius", 0.5), + centerX = op.inValue("Center X", 0), + centerY = op.inValue("Center Y", 0), + trigger = op.outTrigger("Next"); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.twirl_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + uniTwistAmount = new CGL.Uniform(shader, "f", "twistAmount", 1), + uniRadius = new CGL.Uniform(shader, "f", "radius", radius), + uniAspect = new CGL.Uniform(shader, "f", "aspect", 1), + unicenterX = new CGL.Uniform(shader, "f", "centerX", centerX), + unicenterY = new CGL.Uniform(shader, "f", "centerY", centerY); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op,3)) return; + + let texture = cgl.currentTextureEffect.getCurrentSourceTexture(); + + uniTwistAmount.setValue(twistAmount.get() * (1 / texture.width)); + uniAspect.setValue(cgl.currentTextureEffect.aspectRatio); + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Twirl_v4.prototype = new CABLES.Op(); +CABLES.OPS["6691bf7f-602d-4a24-b648-cab4b2a2c15e"]={f:Ops.Gl.TextureEffects.Twirl_v4,objName:"Ops.Gl.TextureEffects.Twirl_v4"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Vibrance +// +// ************************************************************** + +Ops.Gl.TextureEffects.Vibrance = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"vibrance_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\n\nconst vec4 lumcoeff = vec4(0.299,0.587,0.114, 0.);\n\nvoid main()\n{\n vec4 col=vec4(1.0,0.0,0.0,1.0);\n col=texture(tex,texCoord);\n\n float luma = dot(col, lumcoeff);\n vec4 mask = (col - vec4(luma));\n mask = clamp(mask, 0.0, 1.0);\n float lumaMask = dot(lumcoeff, mask);\n lumaMask = 1.0 - lumaMask;\n vec4 vibrance = mix(vec4(luma), col, 1.0 + amount * lumaMask);\n outColor= vibrance;\n}",}; +const render = op.inTrigger("Render"); +const trigger = op.outTrigger("Trigger"); +const amount = op.inValue("amount", 2); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.vibrance_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Vibrance.prototype = new CABLES.Op(); +CABLES.OPS["9c71c980-e439-4397-9c2b-c2ae085eaed9"]={f:Ops.Gl.TextureEffects.Vibrance,objName:"Ops.Gl.TextureEffects.Vibrance"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Vignette_v3 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Vignette_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"vignette_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float lensRadius1;\nUNI float aspect;\nUNI float amount;\nUNI float strength;\nUNI float sharp;\n\nUNI vec3 vcol;\n\n{{CGL.BLENDMODES3}}\n\nvoid main()\n{\n vec4 base=texture(tex,texCoord);\n vec4 vvcol=vec4(vcol,1.0);\n vec4 col=texture(tex,texCoord);\n vec2 tcPos=vec2(texCoord.x,(texCoord.y-0.5)*aspect+0.5);\n float dist = distance(tcPos, vec2(0.5,0.5));\n float am = (1.0-smoothstep( (lensRadius1+0.5), (lensRadius1*0.99+0.5)*sharp, dist));\n\n col=mix(col,vvcol,am*strength);\n\n #ifndef ALPHA\n outColor=cgl_blendPixel(base,col,amount);\n #endif\n\n #ifdef ALPHA\n outColor=vec4(base.rgb,base.a*(1.0-am*strength));\n #endif\n}\n",}; +const + render = op.inTrigger("Render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + amount = op.inValueSlider("Amount", 1), + trigger = op.outTrigger("Trigger"), + strength = op.inValueSlider("Strength", 1), + lensRadius1 = op.inValueSlider("Radius", 0.3), + sharp = op.inValueSlider("Sharp", 0.25), + aspect = op.inValue("Aspect", 1), + r = op.inValueSlider("r", 0), + g = op.inValueSlider("g", 0), + b = op.inValueSlider("b", 0), + alpha = op.inBool("Alpha", false); + +r.setUiAttribs({ "colorPick": true }); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "vignette"); + +shader.setSource(shader.getDefaultVertexShader(), attachments.vignette_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + uniLensRadius1 = new CGL.Uniform(shader, "f", "lensRadius1", lensRadius1), + uniaspect = new CGL.Uniform(shader, "f", "aspect", aspect), + unistrength = new CGL.Uniform(shader, "f", "strength", strength), + unisharp = new CGL.Uniform(shader, "f", "sharp", sharp), + unir = new CGL.Uniform(shader, "3f", "vcol", r, g, b); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +alpha.onChange = updateDefines; +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("ALPHA", alpha.get()); + + r.setUiAttribs({ "greyout": alpha.get() }); + g.setUiAttribs({ "greyout": alpha.get() }); + b.setUiAttribs({ "greyout": alpha.get() }); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Vignette_v3.prototype = new CABLES.Op(); +CABLES.OPS["588302cb-f5a7-4129-90d2-ba66212d69e5"]={f:Ops.Gl.TextureEffects.Vignette_v3,objName:"Ops.Gl.TextureEffects.Vignette_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.WaveformGradient_v4 +// +// ************************************************************** + +Ops.Gl.TextureEffects.WaveformGradient_v4 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"waveform_v2_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float uFreq;\nUNI float uOffset;\nUNI float uPow;\nUNI float uRotate;\nUNI float amount;\n\nUNI float r;\nUNI float g;\nUNI float b;\n\n{{CGL.BLENDMODES3}}\n\n#define PI 3.14159265359\n#define TAU (2.0 * PI)\n\nvoid pR(inout vec2 p, float a)\n{\n float s = sin(a),c=cos(a); p *= mat2(c,s,-s,c);\n}\n\nfloat pModMirror1(inout float p, float size) {\n\tfloat halfsize = size * 0.5;\n\tfloat c = floor((p + halfsize)/size);\n\tp = mod(p + halfsize,size) - halfsize;\n\tp *= mod(c, 2.0) * 2.0 - 1.0;\n\treturn c;\n}\n\nvoid main()\n{\n vec2 uv = texCoord;\n float v = 0.0;\n\n uv -= 0.5;\n pR(uv,TAU * uRotate);\n uv += 0.5 + uOffset;\n\n uv.x *= uFreq;\n\n #ifdef MODE_SINE\n uv.x += 0.5;\n pModMirror1(uv.x,1.0);\n v = pow(cos(PI * uv.x / 2.0),uPow);\n #endif\n\n #ifdef MODE_SAW\n uv.x = mod(uv.x,1.0);\n v = pow(min(cos(PI * uv.x /2.0),1.0 - abs(uv.x)),uPow);\n #endif\n\n #ifdef MODE_TRI\n uv.x += 0.5;\n pModMirror1(uv.x,1.0);\n uv.x = -abs(uv.x);\n uv.x = fract(uv.x);\n v = pow(uv.x,uPow);\n #endif\n\n #ifdef MODE_SQR\n pModMirror1(uv.x,1.0);\n uv.x = -abs(uv.x);\n uv.x = fract(uv.x);\n v = step(uv.x,uPow);\n #endif\n\n vec4 col = vec4(vec3(v*r,v*g,v*b),1.0);\n vec4 base = texture(tex,texCoord);\n\n outColor = cgl_blendPixel(base,col,amount);\n}\n",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + amount = op.inValueSlider("Amount", 1), + mode = op.inValueSelect("Mode", ["Sine", "Sawtooth", "Triangle", "Square"], "Sine"), + freq = op.inValue("Frequency", 4), + pow = op.inValue("Pow factor", 6), + offset = op.inValue("Offset", 0), + rotate = op.inFloatSlider("Rotate", 0), + r = op.inValueSlider("r", 1.0), + g = op.inValueSlider("g", 1.0), + b = op.inValueSlider("b", 1.0), + trigger = op.outTrigger("trigger"); + +op.setPortGroup("Waveform", [mode, freq, pow, offset, rotate]); +op.setPortGroup("Color", [r, g, b]); +r.setUiAttribs({ "colorPick": true }); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.waveform_v2_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + freqUniform = new CGL.Uniform(shader, "f", "uFreq", freq), + offsetUniform = new CGL.Uniform(shader, "f", "uOffset", offset), + powUniform = new CGL.Uniform(shader, "f", "uPow", pow), + rotateUniform = new CGL.Uniform(shader, "f", "uRotate", rotate), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + uniformR = new CGL.Uniform(shader, "f", "r", r), + uniformG = new CGL.Uniform(shader, "f", "g", g), + uniformB = new CGL.Uniform(shader, "f", "b", b); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount,maskAlpha); +mode.onChange = updateMode; +updateMode(); + + +function updateMode() +{ + shader.toggleDefine("MODE_SAW",mode.get() == "Sawtooth"); + shader.toggleDefine("MODE_SINE",mode.get() == "Sine"); + shader.toggleDefine("MODE_TRI",mode.get() == "Triangle"); + shader.toggleDefine("MODE_SQR",mode.get() == "Square"); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op,3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.WaveformGradient_v4.prototype = new CABLES.Op(); +CABLES.OPS["0f9561ce-ea3c-4630-9990-9dae77893517"]={f:Ops.Gl.TextureEffects.WaveformGradient_v4,objName:"Ops.Gl.TextureEffects.WaveformGradient_v4"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Waveform_v3 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Waveform_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"wave_v2_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D tex1;\nUNI float amount;\n\nUNI float r;\nUNI float g;\nUNI float b;\n\nUNI float uAmp;\nUNI float uFreq;\nUNI float uWidth;\nUNI float uGlow;\nUNI float uWaveSelect;\nUNI bool uInvert;\nUNI bool uSolid;\n\nUNI float uOffSetX;\nUNI float uOffSetY;\nUNI float uRotate;\n\n{{CGL.BLENDMODES3}}\n\n#define PI 3.14159265359\n#define TAU (2.0*PI)\n\nfloat vmax(vec2 v)\n{\n\treturn max(v.x, v.y);\n}\n\nvoid pR(inout vec2 p, float a)\n{\n float s = sin(a),c=cos(a); p *= mat2(c,s,-s,c);\n}\n\nfloat pMod1(inout float p, float size)\n{\n\tfloat halfsize = size * 0.5;\n\tfloat c = floor((p + halfsize) / size);\n\tp = mod(p + halfsize, size) - halfsize;\n\treturn c;\n}\n\nfloat pModMirror1(inout float p, float size)\n{\n\tfloat halfsize = size * 0.5;\n\tfloat c = floor((p + halfsize) / size);\n\tp = mod(p + halfsize,size) - halfsize;\n\tp *= mod(c, 2.0) * 2.0 - 1.0;\n\treturn c;\n}\n\nfloat fCapsule2D(vec2 p, float r, float c)\n{\n\treturn mix(abs(p.x) - r, length(vec2(p.x, abs(p.y) - c)) - r, step(c, abs(p.y)));\n}\n\nfloat SineWave(vec2 p, float amplitude, float frequency, float line_width, float line_glow, bool solid)\n{\n float v = sin(p.x * frequency * PI);\n v *= amplitude;\n\n float d = 0.0;\n\n if (solid == false)\n {\n d = abs(v * amplitude - p.y * 0.5);\n d -= line_width;\n return smoothstep(0.0, line_glow, d);\n }\n else\n {\n d = v * amplitude - p.y * 0.5;\n d -= -line_width;\n return smoothstep(0.0, line_glow, -d);\n }\n}\n\nfloat SawWave(vec2 p, float amplitude, float frequency, float line_width, float line_glow, bool solid)\n{\n float inverse_frequency = 2.0 / frequency;\n vec2 p1 = p;\n pMod1(p1.x, inverse_frequency);\n\n float d1 = fCapsule2D(p1, 0.0, amplitude);\n p.x += inverse_frequency * 0.5;\n pMod1(p.x, inverse_frequency);\n pR(p, atan(inverse_frequency, amplitude * 2.0));\n\n float d = fCapsule2D(p, 0.0, 0.5 * length(vec2(inverse_frequency, 2.0 * amplitude)));\n\td = min(d, d1);\n d -= line_width;\n\n if(solid == false)\n {\n return smoothstep(0.0, line_glow, d);\n }\n else\n return smoothstep(0.0, line_glow, min(d,p.x));\n}\n\nfloat TriangleWave(vec2 p, float amplitude, float frequency, float line_width, float line_glow, bool solid)\n{\n float inverse_frequency = 1.0 / frequency;\n p.x -= inverse_frequency;\n pModMirror1(p.x, inverse_frequency);\n pR(p, atan(inverse_frequency, amplitude * 2.0));\n\n float d = fCapsule2D(p, 0.0, 0.5 * length(vec2(inverse_frequency, 2.0 * amplitude)));\n d -= line_width;\n\n if (solid == false)\n {\n return smoothstep(0.0, line_glow, d);\n }\n else\n return smoothstep(0.0, line_glow, min(d,p.x));\n}\n\nfloat SquareWave(vec2 p, float amplitude, float frequency, float line_width, float line_glow, bool solid)\n{\n float inverse_frequency = 0.5 / frequency;\n vec2 p1 = p;\n pMod1(p1.x, 2.0 * inverse_frequency);\n\n float d1 = fCapsule2D(p1, 0.0, abs(amplitude));\n p.x -= inverse_frequency * 0.5;\n float cell = pMod1(p.x, inverse_frequency);\n\n if(cell < 0.0) cell = -cell + 1.0;\n if(int(cell * 0.5) % 2 == 1) p.y -= amplitude;\n else p.y += amplitude;\n\n float d = fCapsule2D(p.yx, 0.0, abs(inverse_frequency));\n d = min(d, d1);\n d -= line_width;\n\n if (solid == false)\n {\n return smoothstep(0.0, line_glow, d);\n }\n else\n return smoothstep(0.0, line_glow, p.y);\n}\n\nvoid main()\n{\n vec4 rgb = vec4(r,g,b,1.0);\n\tvec2 uv = texCoord;\n\n uv -= 0.5;\n pR(uv.xy,uRotate * TAU);\n uv += 0.5;\n\n float wave = 0.0;\n #ifdef SINE\n wave = 1.0 - SineWave (uv - vec2(uOffSetX,uOffSetY), uAmp, uFreq , uWidth, uGlow, uSolid);\n #endif\n #ifdef SAWTOOTH\n wave = 1.0 - SawWave (uv - vec2(uOffSetX,uOffSetY), uAmp, uFreq, uWidth, uGlow, uSolid);\n #endif\n #ifdef TRIANGLE\n wave = 1.0 - TriangleWave (uv - vec2(uOffSetX,uOffSetY), uAmp, uFreq, uWidth, uGlow, uSolid);\n #endif\n #ifdef SQUARE\n wave = 1.0 - SquareWave (uv - vec2(uOffSetX,uOffSetY), uAmp, uFreq, uWidth, uGlow, uSolid);\n #endif\n\n #ifdef INVERT\n wave = 1.0-wave;\n #endif\n\n vec4 col = vec4(r,g,b,1.0);\n\n vec4 base=texture(tex,texCoord);\n\n outColor=cgl_blendPixel(base,col,wave*amount);\n}\n",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + maskAlpha = CGL.TextureEffect.AddBlendAlphaMask(op), + waveSelect = op.inValueSelect("Waveform", ["Sine", "Sawtooth", "Triangle", "Square"], "Sine"), + amplitude = op.inValueSlider("Amplitude", 0.5), + frequency = op.inFloat("Frequency", 2.0), + lineWidth = op.inValueSlider("Line Width", 0.1), + lineGlow = op.inValueSlider("Line Glow", 0.1), + invertCol = op.inValueBool("invert color", false), + solidFill = op.inValueBool("Solid fill", false), + offsetX = op.inValueSlider("Offset X", 0.0), + offsetY = op.inValueSlider("Offset Y", 0.5), + rotate = op.inValueSlider("Rotate", 0.0), + r = op.inValueSlider("r", 1.0), + g = op.inValueSlider("g", 1.0), + b = op.inValueSlider("b", 1.0); + +const trigger = op.outTrigger("trigger"); + +r.setUiAttribs({ "colorPick": true }); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.wave_v2_frag); + +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + amountUniform = new CGL.Uniform(shader, "f", "amount", amount), + uniformR = new CGL.Uniform(shader, "f", "r", r), + uniformG = new CGL.Uniform(shader, "f", "g", g), + uniformB = new CGL.Uniform(shader, "f", "b", b), + amplitudeUniform = new CGL.Uniform(shader, "f", "uAmp", amplitude), + frequencyUniform = new CGL.Uniform(shader, "f", "uFreq", frequency), + lineWidthUniform = new CGL.Uniform(shader, "f", "uWidth", lineWidth), + lineGlowUniform = new CGL.Uniform(shader, "f", "uGlow", lineGlow), + waveSelectUniform = new CGL.Uniform(shader, "f", "uWaveSelect", 1), + invertUniform = new CGL.Uniform(shader, "b", "uInvert", invertCol), + solidFillUniform = new CGL.Uniform(shader, "b", "uSolid", solidFill), + offSetXUniform = new CGL.Uniform(shader, "f", "uOffSetX", offsetX), + offSetYUniform = new CGL.Uniform(shader, "f", "uOffSetY", offsetY), + rotateUniform = new CGL.Uniform(shader, "f", "uRotate", rotate); + +waveSelect.onChange = invertCol.onChange = updateDefines; +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("SINE", waveSelect.get() == "Sine"); + shader.toggleDefine("SAWTOOTH", waveSelect.get() == "Sawtooth"); + shader.toggleDefine("TRIANGLE", waveSelect.get() == "Triangle"); + shader.toggleDefine("SQUARE", waveSelect.get() == "Square"); + shader.toggleDefine("INVERT", invertCol.get()); +} + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount, maskAlpha); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Waveform_v3.prototype = new CABLES.Op(); +CABLES.OPS["fce7d8bc-5a2e-49b8-8f55-8ab8784493d5"]={f:Ops.Gl.TextureEffects.Waveform_v3,objName:"Ops.Gl.TextureEffects.Waveform_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Wobble_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.Wobble_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"wobble_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D texMask;\nUNI float time;\nUNI float speedX;\nUNI float speedY;\nUNI float repeatX;\nUNI float repeatY;\nUNI float mul;\n\n{{CGL.LUMINANCE}}\n\nvoid main()\n{\n float mult=1.0;\n #ifdef HAS_MASK\n #ifdef MASK_SRC_R\n mult*=texture(texMask,texCoord).r;\n #endif\n #ifdef MASK_SRC_G\n mult*=texture(texMask,texCoord).g;\n #endif\n #ifdef MASK_SRC_B\n mult*=texture(texMask,texCoord).b;\n #endif\n #ifdef MASK_SRC_A\n mult*=texture(texMask,texCoord).a;\n #endif\n #ifdef MASK_SRC_LUM\n mult*=cgl_luminance(texture(texMask,texCoord).rgb);\n #endif\n #ifdef MASK_INV\n mult=1.0-mult;\n #endif\n #endif\n\n mult*=mul;\n\n vec2 tc = texCoord + cos( (time*vec2(speedX, speedY) + vec2(texCoord.s*repeatX,texCoord.t*repeatY)))*mult;\n vec4 col=texture(tex,tc);\n\n outColor= col;\n}",}; +const + render = op.inTrigger("Render"), + time = op.inValue("time", 0), + speedX = op.inValue("SpeedX", 4), + speedY = op.inValue("SpeedY", 8), + + repeatX = op.inValue("RepeatX", 11), + repeatY = op.inValue("RepeatY", 11), + mul = op.inValue("Multiply", 0.01), + + inMaskTex = op.inTexture("Amount Map"), + inMaskSource = op.inSwitch("Source Amount Map", ["R", "G", "B", "A", "Lum"], "R"), + inMaskInv = op.inBool("Invert Amount Map", false), + + trigger = op.outTrigger("Trigger"); + +op.setPortGroup("Amount Map", [inMaskTex, inMaskSource, inMaskInv]); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.wobble_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + timeUniform = new CGL.Uniform(shader, "f", "time", time), + speedXUniform = new CGL.Uniform(shader, "f", "speedX", speedX), + speedYUniform = new CGL.Uniform(shader, "f", "speedY", speedY), + repeatXUniform = new CGL.Uniform(shader, "f", "repeatX", repeatX), + repeatYUniform = new CGL.Uniform(shader, "f", "repeatY", repeatY), + mulUniform = new CGL.Uniform(shader, "f", "mul", mul), + maskUniform = new CGL.Uniform(shader, "t", "texMask", 1); + +inMaskTex.onChange = +inMaskSource.onChange = +inMaskInv.onChange = () => +{ + shader.toggleDefine("HAS_MASK", inMaskTex.isLinked()); + shader.toggleDefine("MASK_SRC_R", inMaskSource.get() == "R"); + shader.toggleDefine("MASK_SRC_G", inMaskSource.get() == "G"); + shader.toggleDefine("MASK_SRC_B", inMaskSource.get() == "B"); + shader.toggleDefine("MASK_SRC_A", inMaskSource.get() == "A"); + shader.toggleDefine("MASK_SRC_LUM", inMaskSource.get() == "Lum"); + shader.toggleDefine("MASK_INV", inMaskInv.get()); + inMaskSource.setUiAttribs({ "greyout": !inMaskTex.isLinked() }); + inMaskInv.setUiAttribs({ "greyout": !inMaskTex.isLinked() }); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + if (inMaskTex.get()) cgl.setTexture(1, inMaskTex.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Wobble_v2.prototype = new CABLES.Op(); +CABLES.OPS["04a8a8bc-feb9-4791-8724-ee24bbb150db"]={f:Ops.Gl.TextureEffects.Wobble_v2,objName:"Ops.Gl.TextureEffects.Wobble_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ZoomBlur_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.ZoomBlur_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"zoomblur_frag":"UNI sampler2D tex;\nUNI float x;\nUNI float y;\nUNI float strength;\nIN vec2 texCoord;\n\n#ifdef HAS_MASK\n UNI sampler2D texMask;\n#endif\n\nfloat random(vec3 scale, float seed)\n{\n return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);\n}\n\n#ifdef MASK_SRC_LUM\n {{CGL.LUMINANCE}}\n#endif\n\nvoid main()\n{\n float total = 0.0;\n vec4 color = vec4(0.0);\n vec2 center=vec2(x,y);\n center=(center/2.0)+0.5;\n\n vec2 texSize=vec2(1.0,1.0);\n vec2 toCenter = center - texCoord * texSize;\n\n /* randomize the lookup values to hide the fixed number of samples */\n float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);\n float am = strength;\n\n #ifdef HAS_MASK\n\n float mul=1.0;\n #ifdef MASK_SRC_R\n mul=texture(texMask,texCoord).r;\n #endif\n #ifdef MASK_SRC_G\n mul=texture(texMask,texCoord).g;\n #endif\n #ifdef MASK_SRC_B\n mul=texture(texMask,texCoord).b;\n #endif\n #ifdef MASK_SRC_A\n mul=texture(texMask,texCoord).a;\n #endif\n #ifdef MASK_SRC_LUM\n mul=cgl_luminance(texture(texMask,texCoord).rgb);\n #endif\n\n #ifdef MASK_INV\n mul=1.0-mul;\n #endif\n\n am=am*mul;\n\n if(am<=0.02)\n {\n outColor=texture(tex, texCoord);\n return;\n }\n #endif\n\n for (float t = 0.0; t <= 40.0; t++)\n {\n float percent = (t + offset) / 40.0;\n float weight = 4.0 * (percent - percent * percent);\n vec4 smpl = texture(tex, texCoord + toCenter * percent * am / texSize);\n\n smpl.rgb *= smpl.a;\n\n color += smpl * weight;\n total += weight;\n }\n\n outColor = color / total;\n}",}; +const + render = op.inTrigger("render"), + strength = op.inValueSlider("Strength", 0.5), + x = op.inValue("X", 0), + y = op.inValue("Y", 0), + inMaskTex = op.inTexture("Strength Map"), + inMaskSource = op.inSwitch("Source Strength Map", ["R", "G", "B", "A", "Lum"], "R"), + inMaskInv = op.inBool("Invert Strength Map", false), + trigger = op.outTrigger("trigger"); + +op.setPortGroup("Strengh Map", [inMaskTex, inMaskSource, inMaskInv]); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "zoomblur"); + +shader.setSource(shader.getDefaultVertexShader(), attachments.zoomblur_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + textureMask = new CGL.Uniform(shader, "t", "texMask", 1), + uniX = new CGL.Uniform(shader, "f", "x", x), + uniY = new CGL.Uniform(shader, "f", "y", y), + strengthUniform = new CGL.Uniform(shader, "f", "strength", strength); + +inMaskSource.onChange = + inMaskInv.onChange = + inMaskTex.onChange = updateDefines; + +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("HAS_MASK", inMaskTex.isLinked()); + + shader.toggleDefine("MASK_SRC_R", inMaskSource.get() == "R"); + shader.toggleDefine("MASK_SRC_G", inMaskSource.get() == "G"); + shader.toggleDefine("MASK_SRC_B", inMaskSource.get() == "B"); + shader.toggleDefine("MASK_SRC_A", inMaskSource.get() == "A"); + shader.toggleDefine("MASK_SRC_LUM", inMaskSource.get() == "Lum"); + + shader.toggleDefine("MASK_INV", inMaskInv.get()); + + inMaskSource.setUiAttribs({ "greyout": !inMaskTex.isLinked() }); + inMaskInv.setUiAttribs({ "greyout": !inMaskTex.isLinked() }); +} + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op, 3)) return; + + if (strength.get() > 0) + { + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + if (inMaskTex.get() && inMaskTex.get().tex) cgl.setTexture(1, inMaskTex.get().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + } + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.ZoomBlur_v2.prototype = new CABLES.Op(); +CABLES.OPS["b720a2f5-5501-48ef-90de-94a280ba6fbd"]={f:Ops.Gl.TextureEffects.ZoomBlur_v2,objName:"Ops.Gl.TextureEffects.ZoomBlur_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureFromColorArray +// +// ************************************************************** + +Ops.Gl.TextureFromColorArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExe = op.inTrigger("Update"), + inArr = op.inArray("array"), + inWidth = op.inValueInt("width", 32), + inHeight = op.inValueInt("height", 32), + tfilter = op.inSwitch("Filter", ["nearest", "linear", "mipmap"], "nearest"), + wrap = op.inValueSelect("Wrap", ["repeat", "mirrored repeat", "clamp to edge"], "repeat"), + outNext = op.outTrigger("Next"), + outTex = op.outTexture("Texture out"); + +inExe.onTriggered = update; + +const cgl = op.patch.cgl; +let tex = new CGL.Texture(cgl); + +let arrayResized = true; +let pixels = new Uint8Array(8); + +let cgl_filter = CGL.Texture.FILTER_NEAREST; +let cgl_wrap = CGL.Texture.WRAP_REPEAT; + +tfilter.onChange = + wrap.onChange = + inWidth.onChange = + inHeight.onChange = function () + { + if (tex)tex.delete(); + tex = null; + arrayResized = true; + + if (tfilter.get() == "nearest") cgl_filter = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "linear") cgl_filter = CGL.Texture.FILTER_LINEAR; + else if (tfilter.get() == "mipmap") cgl_filter = CGL.Texture.FILTER_MIPMAP; + else if (tfilter.get() == "Anisotropic") cgl_filter = CGL.Texture.FILTER_ANISOTROPIC; + + if (wrap.get() == "repeat") cgl_wrap = CGL.Texture.WRAP_REPEAT; + else if (wrap.get() == "mirrored repeat") cgl_wrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + else if (wrap.get() == "clamp to edge") cgl_wrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + }; + +const emptyTex = CGL.Texture.getEmptyTexture(cgl); + +function update() +{ + let error = false; + let w = inWidth.get(); + let h = inHeight.get(); + let data = inArr.get(); + + if (w <= 0 || h <= 0 || !data) error = true; + + if (error) + { + outTex.set(emptyTex); + return; + } + + if (arrayResized) + { + pixels = new Uint8Array(w * h * 4); + arrayResized = false; + } + let i = 0; + + for (i = 0; i < data.length; i++) + { + pixels[i] = data[i] * 255; + } + for (i = data.length; i < w * h * 4; i++) + { + pixels[i] = 255; + } + + if (!tex)tex = new CGL.Texture(cgl); + + tex.initFromData(pixels, w, h, cgl_filter, cgl_wrap); + + outTex.set(tex); + + outNext.trigger(); +} + + +}; + +Ops.Gl.TextureFromColorArray.prototype = new CABLES.Op(); +CABLES.OPS["7984c105-5b33-471a-833c-0fb310916e30"]={f:Ops.Gl.TextureFromColorArray,objName:"Ops.Gl.TextureFromColorArray"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureToPointArray3 +// +// ************************************************************** + +Ops.Gl.TextureToPointArray3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + cgl = op.patch.cgl, + pUpdate = op.inTrigger("update"), + inCenter = op.inBool("Center", true), + inThresh = op.inFloatSlider("Threshold Remove", 0), + inMulZ = op.inFloat("Z Multiply", 1), + tex = op.inObject("texture"), + inWidth = op.inFloat("Width", 2), + inHeight = op.inFloat("Height", 2), + outTrigger = op.outTrigger("trigger"), + outCoords = op.outArray("Points"), + outNum = op.outNumber("Total Points"), + outMinZ = op.outNumber("Min Z"), + outMaxZ = op.outNumber("Max Z"); + +op.setPortGroup("Size", [inWidth, inHeight]); + +let + fb = null, + pixelData = null, + coords = null, + texChanged = false; +tex.onChange = function () { texChanged = true; }; + +op.toWorkPortsNeedToBeLinked(tex, outCoords); + +let isFloatingPoint = false; +let channelType = op.patch.cgl.gl.UNSIGNED_BYTE; + +pUpdate.onTriggered = function () +{ + let realTexture = tex.get(), gl = cgl.gl; + + if (!realTexture) + { + outCoords.set(null); + outMaxZ.set(0); + outNum.set(0); + return; + } + if (!fb) fb = gl.createFramebuffer(); + if (!coords)coords = []; + + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + if (texChanged) + { + gl.framebufferTexture2D( + gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, + gl.TEXTURE_2D, realTexture.tex, 0 + ); + + channelType = gl.UNSIGNED_BYTE; + + const size = realTexture.width * realTexture.height * 4; + + pixelData = new Uint8Array(size); + + texChanged = false; + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + gl.readPixels( + 0, 0, + realTexture.width, + realTexture.height, + gl.RGBA, + channelType, + pixelData + ); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + coords.length = 0; + + let offX = 0; + let offY = 0; + + let w = inWidth.get(); + let h = inHeight.get(); + const thresh = inThresh.get() * 256; + const mulz = inMulZ.get() / 256; + let maxZ = 0; + let minZ = 99999999; + + if (inCenter.get()) + { + offX = realTexture.width / 2; + offY = realTexture.height / 2; + } + + for (let x = 0; x < realTexture.width; x++) + { + for (let y = 0; y < realTexture.height; y++) + { + if ( + pixelData[(x + (y * realTexture.width)) * 4 + 0] >= thresh || + pixelData[(x + (y * realTexture.width)) * 4 + 1] >= thresh || + pixelData[(x + (y * realTexture.width)) * 4 + 2] >= thresh) + { + const zz = pixelData[(x + (y * realTexture.width)) * 4 + 0] * mulz; + coords.push((x - offX) / realTexture.width * w, (y - offY) / realTexture.height * h, + zz); + maxZ = Math.max(zz, maxZ); + minZ = Math.min(zz, minZ); + } + } + } + + outMinZ.set(minZ); + outMaxZ.set(maxZ); + outCoords.set(null); + outNum.set(coords.length / 3); + outCoords.set(coords); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + outTrigger.trigger(); +}; + + +}; + +Ops.Gl.TextureToPointArray3.prototype = new CABLES.Op(); +CABLES.OPS["93f03721-4b1e-4dee-aef9-7ef17c9cd6c1"]={f:Ops.Gl.TextureToPointArray3,objName:"Ops.Gl.TextureToPointArray3"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureToPoints +// +// ************************************************************** + +Ops.Gl.TextureToPoints = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + cgl = op.patch.cgl, + pUpdate = op.inTriggerButton("update"), + inNum = op.inValueInt("Num Points", 2000), + inSeed = op.inValueFloat("Seed", 1), + zPos = op.inSwitch("Z Position", ["None", "Red", "Green", "Blue", "Alpha"], "Red"), + zMultiply = op.inValueFloat("Z Multiply", 1.0), + tex = op.inObject("texture"), + outTrigger = op.outTrigger("trigger"), + outPoints = op.outArray("Points"), + outPointsNum = op.outValue("NumPoints"); + +let fb = null, + pixelData = null, + texChanged = false; + +op.toWorkPortsNeedToBeLinked(tex, outPoints); + +tex.onChange = function () { texChanged = true; }; + +let channelType = op.patch.cgl.gl.UNSIGNED_BYTE; +let points = []; + +pUpdate.onTriggered = updatePixels; + +const NUM_COL_CHANNELS = 4; + +function updatePixels() +{ + let realTexture = tex.get(), gl = cgl.gl; + + if (!realTexture) return; + if (!fb) fb = gl.createFramebuffer(); + + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + if (texChanged) + { + gl.framebufferTexture2D( + gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, + gl.TEXTURE_2D, realTexture.tex, 0 + ); + + pixelData = new Uint8Array(realTexture.width * realTexture.height * NUM_COL_CHANNELS); + texChanged = false; + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + gl.readPixels( + 0, 0, + realTexture.width, + realTexture.height, + gl.RGBA, + channelType, + pixelData + ); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + let num = inNum.get(); + let numPixels = pixelData.length; + + if (num * 3 != points.length)points.length = num * 3; + + Math.randomSeed = inSeed.get(); + + let pixelStepX = 1 / realTexture.width; + let pixelStepY = 1 / realTexture.height; + + let offsetX = pixelStepX * realTexture.width / 2; + let offsetY = pixelStepY * realTexture.height / 2; + + let ind = 0; + let count = 0; + + let colChanOffset = 0; + if (zPos.get() == "Green")colChanOffset = 1; + else if (zPos.get() == "Blue")colChanOffset = 2; + else if (zPos.get() == "Alpha")colChanOffset = 3; + else if (zPos.get() == "None")colChanOffset = 4; + + while (ind < num * 3) + { + count++; + if (count > num * 3 * 100) return; + let x = Math.floor(Math.seededRandom() * realTexture.width); + let y = Math.floor(Math.seededRandom() * realTexture.height); + let intens = pixelData[(x + (y * realTexture.width)) * NUM_COL_CHANNELS + colChanOffset]; + + if (intens > 10) + { + points[ind++] = ((x * pixelStepX) - (offsetX)); + points[ind++] = ((y * pixelStepY) - (offsetY)); + + if (colChanOffset < 4) points[ind++] = (intens / 255) * zMultiply.get(); + else points[ind++] = 0; + } + } + + outPointsNum.set(ind / 3); + outPoints.set(null); + outPoints.set(points); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + outTrigger.trigger(); +} + + +}; + +Ops.Gl.TextureToPoints.prototype = new CABLES.Op(); +CABLES.OPS["ff757f51-fbb0-4728-b158-644094cd160e"]={f:Ops.Gl.TextureToPoints,objName:"Ops.Gl.TextureToPoints"}; + + + + +// ************************************************************** +// +// Ops.Gl.Texture_v2 +// +// ************************************************************** + +Ops.Gl.Texture_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + filename = op.inUrl("File", [".jpg", ".png", ".webp", ".jpeg", ".avif"]), + tfilter = op.inSwitch("Filter", ["nearest", "linear", "mipmap"]), + wrap = op.inValueSelect("Wrap", ["repeat", "mirrored repeat", "clamp to edge"], "clamp to edge"), + aniso = op.inSwitch("Anisotropic", [0, 1, 2, 4, 8, 16], 0), + flip = op.inValueBool("Flip", false), + unpackAlpha = op.inValueBool("Pre Multiplied Alpha", false), + active = op.inValueBool("Active", true), + inFreeMemory = op.inBool("Save Memory", true), + textureOut = op.outTexture("Texture"), + width = op.outNumber("Width"), + height = op.outNumber("Height"), + ratio = op.outNumber("Aspect Ratio"), + loaded = op.outNumber("Loaded", false), + loading = op.outNumber("Loading", false); + +op.setPortGroup("Size", [width, height]); + +unpackAlpha.setUiAttribs({ "hidePort": true }); + +op.toWorkPortsNeedToBeLinked(textureOut); + +const cgl = op.patch.cgl; + +let loadedFilename = null; +let loadingId = null; +let tex = null; +let cgl_filter = CGL.Texture.FILTER_MIPMAP; +let cgl_wrap = CGL.Texture.WRAP_REPEAT; +let cgl_aniso = 0; +let timedLoader = 0; + +filename.onChange = flip.onChange = function () { reloadSoon(); }; +aniso.onChange = tfilter.onChange = onFilterChange; +wrap.onChange = onWrapChange; +unpackAlpha.onChange = function () { reloadSoon(); }; + +tfilter.set("mipmap"); +wrap.set("repeat"); + +textureOut.set(CGL.Texture.getEmptyTexture(cgl)); + +active.onChange = function () +{ + if (active.get()) + { + if (loadedFilename != filename.get() || !tex) reloadSoon(); + else textureOut.set(tex); + } + else + { + textureOut.set(CGL.Texture.getEmptyTexture(cgl)); + width.set(CGL.Texture.getEmptyTexture(cgl).width); + height.set(CGL.Texture.getEmptyTexture(cgl).height); + if (tex)tex.delete(); + tex = null; + } +}; + +const setTempTexture = function () +{ + const t = CGL.Texture.getTempTexture(cgl); + textureOut.set(t); +}; + +function reloadSoon(nocache) +{ + clearTimeout(timedLoader); + timedLoader = setTimeout(function () + { + realReload(nocache); + }, 30); +} + +function realReload(nocache) +{ + if (!active.get()) return; + // if (filename.get() === null) return; + if (!loadingId)loadingId = cgl.patch.loading.start("textureOp", filename.get()); + + let url = op.patch.getFilePath(String(filename.get())); + + if (nocache)url += "?rnd=" + CABLES.uuid(); + + if (String(filename.get()).indexOf("data:") == 0) url = filename.get(); + + let needsRefresh = false; + if (loadedFilename != filename.get()) needsRefresh = true; + loadedFilename = filename.get(); + + if ((filename.get() && filename.get().length > 1)) + { + loaded.set(false); + loading.set(true); + + const fileToLoad = filename.get(); + + op.setUiAttrib({ "extendTitle": CABLES.basename(url) }); + if (needsRefresh) op.refreshParams(); + + cgl.patch.loading.addAssetLoadingTask(() => + { + op.setUiError("urlerror", null); + + CGL.Texture.load(cgl, url, + function (err, newTex) + { + if (filename.get() != fileToLoad) + { + cgl.patch.loading.finished(loadingId); + loadingId = null; + return; + } + + if (err) + { + setTempTexture(); + op.setUiError("urlerror", "could not load texture: \"" + filename.get() + "\"", 2); + cgl.patch.loading.finished(loadingId); + return; + } + + textureOut.set(newTex); + + width.set(newTex.width); + height.set(newTex.height); + ratio.set(newTex.width / newTex.height); + + // if (!newTex.isPowerOfTwo()) op.setUiError("npot", "Texture dimensions not power of two! - Texture filtering will not work in WebGL 1.", 0); + // else op.setUiError("npot", null); + + if (tex)tex.delete(); + tex = newTex; + textureOut.set(null); + textureOut.set(tex); + + loading.set(false); + loaded.set(true); + + if (inFreeMemory.get()) tex.image = null; + + cgl.patch.loading.finished(loadingId); + }, { + "anisotropic": cgl_aniso, + "wrap": cgl_wrap, + "flip": flip.get(), + "unpackAlpha": unpackAlpha.get(), + "filter": cgl_filter + }); + + // textureOut.set(null); + // textureOut.set(tex); + }); + } + else + { + cgl.patch.loading.finished(loadingId); + setTempTexture(); + } +} + +function onFilterChange() +{ + if (tfilter.get() == "nearest") cgl_filter = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "linear") cgl_filter = CGL.Texture.FILTER_LINEAR; + else if (tfilter.get() == "mipmap") cgl_filter = CGL.Texture.FILTER_MIPMAP; + else if (tfilter.get() == "Anisotropic") cgl_filter = CGL.Texture.FILTER_ANISOTROPIC; + + cgl_aniso = parseFloat(aniso.get()); + + reloadSoon(); +} + +function onWrapChange() +{ + if (wrap.get() == "repeat") cgl_wrap = CGL.Texture.WRAP_REPEAT; + if (wrap.get() == "mirrored repeat") cgl_wrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + if (wrap.get() == "clamp to edge") cgl_wrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + reloadSoon(); +} + +op.onFileChanged = function (fn) +{ + if (filename.get() && filename.get().indexOf(fn) > -1) + { + textureOut.set(CGL.Texture.getEmptyTexture(op.patch.cgl)); + textureOut.set(CGL.Texture.getTempTexture(cgl)); + realReload(true); + } +}; + + +}; + +Ops.Gl.Texture_v2.prototype = new CABLES.Op(); +CABLES.OPS["790f3702-9833-464e-8e37-6f0f813f7e16"]={f:Ops.Gl.Texture_v2,objName:"Ops.Gl.Texture_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.Base64ToTexture +// +// ************************************************************** + +Ops.Gl.Textures.Base64ToTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + dataIn = op.inStringEditor("Base64 / Data URI", ""), + tfilter = op.inSwitch("filter", ["nearest", "linear", "mipmap"], "linear"), + twrap = op.inValueSelect("wrap", ["clamp to edge", "repeat", "mirrored repeat"], "clamp to edge"), + textureOut = op.outTexture("Texture"), + loadingOut = op.outBool("Loading"); + +const image = new Image(); + +let doUpdateTex = false; +let selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; +let selectedFilter = CGL.Texture.FILTER_LINEAR; + +function createTex() +{ + const tex = CGL.Texture.createFromImage(op.patch.cgl, image, + { + "filter": selectedFilter, + "wrap": selectedWrap + }); + textureOut.set(tex); + loadingOut.set(false); +} + +image.onload = function (e) +{ + op.patch.cgl.addNextFrameOnceCallback(createTex.bind(this)); +}; + +dataIn.onChange = () => +{ + updateTex(); +}; + +twrap.onChange = + tfilter.onChange = () => + { + if (tfilter.get() == "nearest") selectedFilter = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "linear") selectedFilter = CGL.Texture.FILTER_LINEAR; + else if (tfilter.get() == "mipmap") selectedFilter = CGL.Texture.FILTER_MIPMAP; + + if (twrap.get() == "repeat") selectedWrap = CGL.Texture.WRAP_REPEAT; + else if (twrap.get() == "mirrored repeat") selectedWrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + else if (twrap.get() == "clamp to edge") selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + updateTex(); + }; + +function updateTex() +{ + loadingOut.set(true); + let data = dataIn.get(); + if (data && !data.startsWith("data:")) + { + data = "data:;base64," + data; + } + image.src = data; +} + + +}; + +Ops.Gl.Textures.Base64ToTexture.prototype = new CABLES.Op(); +CABLES.OPS["cd07e587-432a-4a81-a2b7-51273cf32171"]={f:Ops.Gl.Textures.Base64ToTexture,objName:"Ops.Gl.Textures.Base64ToTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.ColorTexture +// +// ************************************************************** + +Ops.Gl.Textures.ColorTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + r = op.inValueSlider("r", Math.random()), + g = op.inValueSlider("g", Math.random()), + b = op.inValueSlider("b", Math.random()), + a = op.inValueSlider("a", 1.0), + texOut = op.outTexture("texture_out"); + +r.setUiAttribs({ "colorPick": true }); +const cgl = op.patch.cgl; +let fb = null; + +r.onChange = + g.onChange = + b.onChange = + a.onChange = () => { cgl.addNextFrameOnceCallback(render); }; + +cgl.addNextFrameOnceCallback(render); + +function render() +{ + if (!fb) + { + if (cgl.glVersion == 1) fb = new CGL.Framebuffer(cgl, 8, 8, { "name": "colorTexture" }); + else fb = new CGL.Framebuffer2(cgl, 8, 8, { "name": "colorTexture", "depth": false }); + fb.setFilter(CGL.Texture.FILTER_MIPMAP); + } + + fb.renderStart(); + cgl.gl.clearColor(r.get(), g.get(), b.get(), a.get()); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT); + fb.renderEnd(); + texOut.set(fb.getTextureColor()); +} + + +}; + +Ops.Gl.Textures.ColorTexture.prototype = new CABLES.Op(); +CABLES.OPS["59b94270-0364-4c0f-a9fc-ba2561696a23"]={f:Ops.Gl.Textures.ColorTexture,objName:"Ops.Gl.Textures.ColorTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.CombineTextures +// +// ************************************************************** + +Ops.Gl.Textures.CombineTextures = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"rgbe2fp_frag":"UNI sampler2D texR;\nUNI sampler2D texG;\nUNI sampler2D texB;\nUNI sampler2D texA;\nIN vec2 texCoord;\n\nUNI float defaultR;\nUNI float defaultG;\nUNI float defaultB;\nUNI float defaultA;\n\nvoid main()\n{\n float r=defaultR, g=defaultG, b=defaultB, a=defaultA;\n\n #ifdef HAS_R\n #ifdef R_SRC_R\n r=texture(texR,texCoord).r;\n #endif\n #ifdef R_SRC_G\n r=texture(texR,texCoord).g;\n #endif\n #ifdef R_SRC_B\n r=texture(texR,texCoord).b;\n #endif\n #ifdef R_SRC_A\n r=texture(texR,texCoord).a;\n #endif\n #endif\n\n #ifdef HAS_G\n #ifdef G_SRC_R\n g=texture(texG,texCoord).r;\n #endif\n #ifdef G_SRC_G\n g=texture(texG,texCoord).g;\n #endif\n #ifdef G_SRC_B\n g=texture(texG,texCoord).b;\n #endif\n #ifdef G_SRC_A\n g=texture(texG,texCoord).a;\n #endif\n #endif\n\n #ifdef HAS_B\n #ifdef B_SRC_R\n b=texture(texB,texCoord).r;\n #endif\n #ifdef B_SRC_G\n b=texture(texB,texCoord).g;\n #endif\n #ifdef B_SRC_B\n b=texture(texB,texCoord).b;\n #endif\n #ifdef B_SRC_A\n b=texture(texB,texCoord).a;\n #endif\n #endif\n\n #ifdef HAS_A\n #ifdef A_SRC_R\n a=texture(texA,texCoord).r;\n #endif\n #ifdef A_SRC_G\n a=texture(texA,texCoord).g;\n #endif\n #ifdef A_SRC_B\n a=texture(texA,texCoord).b;\n #endif\n #ifdef A_SRC_A\n a=texture(texA,texCoord).a;\n #endif\n #endif\n\n #ifdef INV_R\n r=1.0-r;\n #endif\n #ifdef INV_G\n g=1.0-g;\n #endif\n #ifdef INV_B\n b=1.0-b;\n #endif\n #ifdef INV_A\n a=1.0-a;\n #endif\n\n\n outColor = vec4(r,g,b,a);\n}\n\n\n",}; +const + exec = op.inTrigger("Execute"), + tfilter = op.inSwitch("Filter", ["nearest", "linear", "mipmap"], "linear"), + twrap = op.inValueSelect("Wrap", ["clamp to edge", "repeat", "mirrored repeat"], "repeat"), + inPixel = op.inDropDown("Pixel Format", CGL.Texture.PIXELFORMATS, CGL.Texture.PFORMATSTR_RGBA8UB), + + inTexR = op.inTexture("R"), + inSrcR = op.inSwitch("R Source", ["R", "G", "B", "A"], "R"), + inSrcRVal = op.inSwitch("R Value", ["Source", "Invert"], "Source"), + inSrcRDefault = op.inFloatSlider("R Default", 1), + inTexG = op.inTexture("G"), + inSrcG = op.inSwitch("G Source", ["R", "G", "B", "A"], "G"), + inSrcGVal = op.inSwitch("G Value", ["Source", "Invert"], "Source"), + inSrcGDefault = op.inFloatSlider("G Default", 1), + inTexB = op.inTexture("B"), + inSrcB = op.inSwitch("B Source", ["R", "G", "B", "A"], "B"), + inSrcBVal = op.inSwitch("B Value", ["Source", "Invert"], "Source"), + inSrcBDefault = op.inFloatSlider("B Default", 1), + inTexA = op.inTexture("A"), + inSrcA = op.inSwitch("A Source", ["R", "G", "B", "A"], "R"), + inSrcAVal = op.inSwitch("A Value", ["Source", "Invert"], "Source"), + inSrcADefault = op.inFloatSlider("A Default", 1), + + next = op.outTrigger("Next"), + outTex = op.outTexture("Texture"); + +op.setPortGroup("Red", [inSrcRDefault, inTexR, inSrcR, inSrcRVal]); +op.setPortGroup("Green", [inSrcGDefault, inTexG, inSrcG, inSrcGVal]); +op.setPortGroup("Blue", [inSrcBDefault, inTexB, inSrcB, inSrcBVal]); +op.setPortGroup("Alpha", [inSrcADefault, inTexA, inSrcA, inSrcAVal]); + +const cgl = op.patch.cgl; +let needsUpdate = true; +let tc = null; +let unitexR, unitexG, unitexB, unitexA, uniFloatR, uniFloatG, uniFloatB, uniFloatA; + +inSrcRDefault.onChange = + inSrcGDefault.onChange = + inSrcBDefault.onChange = + inSrcADefault.onChange = + inTexR.onChange = + inTexG.onChange = + inTexB.onChange = + inPixel.onChange = + inTexA.onChange = () => + { + needsUpdate = true; + }; + +inTexR.onLinkChanged = + inTexG.onLinkChanged = + inTexB.onLinkChanged = + inTexA.onLinkChanged = + inSrcR.onChange = + inSrcG.onChange = + inSrcB.onChange = + inSrcA.onChange = + inSrcRVal.onChange = + inSrcGVal.onChange = + inSrcBVal.onChange = + inSrcAVal.onChange = updateDefines; + +tfilter.onChange = + twrap.onChange = initShader; + +function initShader() +{ + let wrap = CGL.Texture.WRAP_REPEAT; + if (twrap.get() == "mirrored repeat") wrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + if (twrap.get() == "clamp to edge") wrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + let filter = CGL.Texture.FILTER_NEAREST; + if (tfilter.get() == "linear") filter = CGL.Texture.FILTER_LINEAR; + if (tfilter.get() == "mipmap") filter = CGL.Texture.FILTER_MIPMAP; + + if (tc)tc.dispose(); + tc = new CGL.CopyTexture(cgl, "combinetextures", + { + "shader": attachments.rgbe2fp_frag, + "isFloatingPointTexture": inPixel.get() == CGL.Texture.PFORMATSTR_RGBA32F, + "filter": filter, + "wrap": wrap + }); + + unitexR = new CGL.Uniform(tc.bgShader, "t", "texR", 0); + unitexG = new CGL.Uniform(tc.bgShader, "t", "texG", 1); + unitexB = new CGL.Uniform(tc.bgShader, "t", "texB", 2); + unitexA = new CGL.Uniform(tc.bgShader, "t", "texA", 3); + + uniFloatR = new CGL.Uniform(tc.bgShader, "f", "defaultR", inSrcRDefault); + uniFloatG = new CGL.Uniform(tc.bgShader, "f", "defaultG", inSrcGDefault); + uniFloatB = new CGL.Uniform(tc.bgShader, "f", "defaultB", inSrcBDefault); + uniFloatA = new CGL.Uniform(tc.bgShader, "f", "defaultA", inSrcADefault); + + updateDefines(); + needsUpdate = true; +} + +function updateDefines() +{ + if (!tc) return; + + inSrcR.setUiAttribs({ "greyout": !inTexR.isLinked() }); + inSrcG.setUiAttribs({ "greyout": !inTexG.isLinked() }); + inSrcB.setUiAttribs({ "greyout": !inTexB.isLinked() }); + inSrcA.setUiAttribs({ "greyout": !inTexA.isLinked() }); + + inSrcRVal.setUiAttribs({ "greyout": !inTexR.isLinked() }); + inSrcGVal.setUiAttribs({ "greyout": !inTexG.isLinked() }); + inSrcBVal.setUiAttribs({ "greyout": !inTexB.isLinked() }); + inSrcAVal.setUiAttribs({ "greyout": !inTexA.isLinked() }); + + inSrcRDefault.setUiAttribs({ "greyout": inTexR.isLinked() }); + inSrcGDefault.setUiAttribs({ "greyout": inTexG.isLinked() }); + inSrcBDefault.setUiAttribs({ "greyout": inTexB.isLinked() }); + inSrcADefault.setUiAttribs({ "greyout": inTexA.isLinked() }); + + tc.bgShader.toggleDefine("R_SRC_R", inSrcR.get() == "R"); + tc.bgShader.toggleDefine("R_SRC_G", inSrcR.get() == "G"); + tc.bgShader.toggleDefine("R_SRC_B", inSrcR.get() == "B"); + tc.bgShader.toggleDefine("R_SRC_A", inSrcR.get() == "A"); + + tc.bgShader.toggleDefine("G_SRC_R", inSrcG.get() == "R"); + tc.bgShader.toggleDefine("G_SRC_G", inSrcG.get() == "G"); + tc.bgShader.toggleDefine("G_SRC_B", inSrcG.get() == "B"); + tc.bgShader.toggleDefine("G_SRC_A", inSrcG.get() == "A"); + + tc.bgShader.toggleDefine("B_SRC_R", inSrcB.get() == "R"); + tc.bgShader.toggleDefine("B_SRC_G", inSrcB.get() == "G"); + tc.bgShader.toggleDefine("B_SRC_B", inSrcB.get() == "B"); + tc.bgShader.toggleDefine("B_SRC_A", inSrcB.get() == "A"); + + tc.bgShader.toggleDefine("A_SRC_R", inSrcA.get() == "R"); + tc.bgShader.toggleDefine("A_SRC_G", inSrcA.get() == "G"); + tc.bgShader.toggleDefine("A_SRC_B", inSrcA.get() == "B"); + tc.bgShader.toggleDefine("A_SRC_A", inSrcA.get() == "A"); + + tc.bgShader.toggleDefine("INV_R", inSrcRVal.get() == "Invert"); + tc.bgShader.toggleDefine("INV_G", inSrcGVal.get() == "Invert"); + tc.bgShader.toggleDefine("INV_B", inSrcBVal.get() == "Invert"); + tc.bgShader.toggleDefine("INV_A", inSrcAVal.get() == "Invert"); + + tc.bgShader.toggleDefine("HAS_R", inTexR.isLinked()); + tc.bgShader.toggleDefine("HAS_G", inTexG.isLinked()); + tc.bgShader.toggleDefine("HAS_B", inTexB.isLinked()); + tc.bgShader.toggleDefine("HAS_A", inTexA.isLinked()); + + needsUpdate = true; +} + +exec.onTriggered = () => +{ + if (needsUpdate && !op.patch.cgl.frameStore.shadowPass) + { + if (!tc)initShader(); + tc.bgShader.popTextures(); + + if (inTexR.get()) tc.bgShader.pushTexture(unitexR, inTexR.get().tex); + else tc.bgShader.pushTexture(unitexR, CGL.Texture.getEmptyTexture(cgl).tex); + if (inTexG.get()) tc.bgShader.pushTexture(unitexG, inTexG.get().tex); + else tc.bgShader.pushTexture(unitexG, CGL.Texture.getEmptyTexture(cgl).tex); + if (inTexB.get()) tc.bgShader.pushTexture(unitexB, inTexB.get().tex); + else tc.bgShader.pushTexture(unitexB, CGL.Texture.getEmptyTexture(cgl).tex); + if (inTexA.get()) tc.bgShader.pushTexture(unitexA, inTexA.get().tex); + else tc.bgShader.pushTexture(unitexA, CGL.Texture.getEmptyTexture(cgl).tex); + + uniFloatR.setValue(inSrcRDefault.get()); + uniFloatG.setValue(inSrcGDefault.get()); + uniFloatB.setValue(inSrcBDefault.get()); + uniFloatA.setValue(inSrcADefault.get()); + + outTex.set(CGL.Texture.getEmptyTexture(cgl)); + outTex.set(tc.copy(inTexR.get() || inTexG.get() || inTexB.get() || inTexA.get() || CGL.Texture.getEmptyTexture(cgl))); + + needsUpdate = false; + } + + next.trigger(); +}; + + +}; + +Ops.Gl.Textures.CombineTextures.prototype = new CABLES.Op(); +CABLES.OPS["5f33dd4a-a553-4f0f-b3b1-66a80cd240a7"]={f:Ops.Gl.Textures.CombineTextures,objName:"Ops.Gl.Textures.CombineTextures"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.CopyTexture +// +// ************************************************************** + +Ops.Gl.Textures.CopyTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"copytexture_frag":"UNI float a;\nUNI sampler2D tex;\n\n#ifdef TEX_MASK\nUNI sampler2D texMask;\n#endif\n\nIN vec2 texCoord;\n\nvoid main()\n{\n vec4 col=texture(tex,texCoord);\n\n #ifdef TEX_MASK\n col.a=texture(texMask,texCoord).r;\n #endif\n\n\n #ifdef GREY_R\n col.rgb=vec3(col.r);\n #endif\n\n #ifdef GREY_G\n col.rgb=vec3(col.g);\n #endif\n\n #ifdef GREY_B\n col.rgb=vec3(col.b);\n #endif\n\n #ifdef GREY_A\n col.rgb=vec3(col.a);\n #endif\n\n #ifdef GREY_LUMI\n col.rgb=vec3( dot(vec3(0.2126,0.7152,0.0722), col.rgb) );\n #endif\n\n\n #ifdef INVERT_A\n col.a=1.0-col.a;\n #endif\n\n #ifdef INVERT_R\n col.r=1.0-col.r;\n #endif\n\n #ifdef INVERT_G\n col.g=1.0-col.g;\n #endif\n\n #ifdef INVERT_B\n col.b=1.0-col.b;\n #endif\n\n #ifdef ALPHA_1\n col.a=1.0;\n #endif\n\n\n\n\n outColor= col;\n}",}; +const + render = op.inTriggerButton("render"), + inTexture = op.inTexture("Texture"), + inTextureMask = op.inTexture("Alpha Mask"), + useVPSize = op.inValueBool("use original size", true), + width = op.inValueInt("width", 640), + height = op.inValueInt("height", 360), + tfilter = op.inSwitch("filter", ["nearest", "linear", "mipmap"], "linear"), + twrap = op.inValueSelect("wrap", ["clamp to edge", "repeat", "mirrored repeat"], "clamp to edge"), + fpTexture = op.inValueBool("HDR"), + alphaMaskMethod = op.inSwitch("Alpha Mask Source", ["A", "1"], "A"), + greyscale = op.inSwitch("Convert Greyscale", ["Off", "R", "G", "B", "A", "Luminance"], "Off"), + invertR = op.inBool("Invert R", false), + invertG = op.inBool("Invert G", false), + invertB = op.inBool("Invert B", false), + invertA = op.inBool("Invert A", false), + + trigger = op.outTrigger("trigger"), + texOut = op.outTexture("texture_out", null), + outRatio = op.outNumber("Aspect Ratio"); + +alphaMaskMethod.setUiAttribs({ "hidePort": true }); +greyscale.setUiAttribs({ "hidePort": true }); +invertR.setUiAttribs({ "hidePort": true }); +invertG.setUiAttribs({ "hidePort": true }); +invertB.setUiAttribs({ "hidePort": true }); + +let autoRefreshTimeout = null; +const cgl = op.patch.cgl; +let lastTex = null; +let effect = null; +let tex = null; +let needsResUpdate = true; + +let w = 2, h = 2; +const prevViewPort = [0, 0, 0, 0]; +let reInitEffect = true; + +op.setPortGroup("Size", [useVPSize, width, height]); + +const bgShader = new CGL.Shader(cgl, "copytexture"); +bgShader.setSource(bgShader.getDefaultVertexShader(), attachments.copytexture_frag); +const textureUniform = new CGL.Uniform(bgShader, "t", "tex", 0); +let textureMaskUniform = new CGL.Uniform(bgShader, "t", "texMask", 1); + +let selectedFilter = CGL.Texture.FILTER_LINEAR; +let selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + +alphaMaskMethod.onChange = + greyscale.onChange = + invertR.onChange = + invertG.onChange = + invertB.onChange = + twrap.onChange = + tfilter.onChange = + fpTexture.onChange = + inTextureMask.onChange = updateSoon; + +render.onLinkChanged = +inTexture.onLinkChanged = +inTexture.onChange = () => +{ + // if (!inTexture.get() || inTexture.get() == CGL.Texture.getEmptyTexture(cgl)) texOut.set(CGL.Texture.getEmptyTexture(cgl)); + updateSoon(); +}; + +render.onTriggered = doRender; +updateSizePorts(); + +function initEffect() +{ + if (effect)effect.delete(); + if (tex) + { + tex.delete(); + tex = null; + } + + effect = new CGL.TextureEffect(cgl, { "isFloatingPointTexture": fpTexture.get(), "clear": false }); + + if (!tex || + tex.width != Math.floor(width.get()) || + tex.height != Math.floor(height.get()) || + tex.wrap != selectedWrap || + tex.isFloatingPoint() != fpTexture.get() + ) + { + if (tex) tex.delete(); + tex = new CGL.Texture(cgl, + { + "name": "copytexture_" + op.id, + "isFloatingPointTexture": fpTexture.get(), + "filter": selectedFilter, + "wrap": selectedWrap, + "width": Math.floor(width.get()), + "height": Math.floor(height.get()), + }); + } + + effect.setSourceTexture(tex); + texOut.set(null); + reInitEffect = false; +} + +function updateSoon() +{ + updateParams(); + if (render.links.length === 0) + { + reInitEffect = true; + + // clearTimeout(autoRefreshTimeout); + // autoRefreshTimeout = setTimeout(() => { doRender(); }, 100); + op.patch.cgl.off(autoRefreshTimeout); + autoRefreshTimeout = op.patch.cgl.on("beginFrame", () => + { + op.patch.cgl.off(autoRefreshTimeout); + + if (needsResUpdate)updateResolution(); + if (!effect)op.log("has no effect"); + if (!inTexture.get()) op.log("has no intexture"); + + doRender(); + }); + } +} + +function updateResolution() +{ + if (!inTexture.get() || inTexture.get() == CGL.Texture.getEmptyTexture(cgl)) return; + if (!effect)initEffect(); + + if (useVPSize.get()) + { + w = inTexture.get().width; + h = inTexture.get().height; + } + else + { + w = Math.floor(width.get()); + h = Math.floor(height.get()); + } + + if ((w != tex.width || h != tex.height) && (w !== 0 && h !== 0)) + { + height.set(h); + width.set(w); + tex.filter = selectedFilter; + tex.setSize(w, h); + outRatio.set(w / h); + effect.setSourceTexture(tex); + } + + if (texOut.get() && selectedFilter != CGL.Texture.FILTER_NEAREST) + { + if (!texOut.get().isPowerOfTwo()) op.setUiError("hintnpot", "texture dimensions not power of two! - texture filtering when scaling will not work on ios devices.", 0); + else op.setUiError("hintnpot", null, 0); + } + else op.setUiError("hintnpot", null, 0); + + needsResUpdate = false; +} + +function updateSizePorts() +{ + width.setUiAttribs({ "greyout": useVPSize.get() }); + height.setUiAttribs({ "greyout": useVPSize.get() }); +} + +function updateResolutionLater() +{ + needsResUpdate = true; + updateSoon(); +} + +useVPSize.onChange = function () +{ + updateSizePorts(); + if (useVPSize.get()) + { + width.onChange = null; + height.onChange = null; + } + else + { + width.onChange = updateResolutionLater; + height.onChange = updateResolutionLater; + } + updateResolution(); +}; + +function doRender() +{ + // op.patch.removeOnAnimCallback(doRender); + // if (!inTexture.get()) + + if (!inTexture.get() || inTexture.get() == CGL.Texture.getEmptyTexture(cgl)) texOut.set(CGL.Texture.getEmptyTexture(cgl)); + + if (!inTexture.get() || inTexture.get() == CGL.Texture.getEmptyTexture(cgl)) + { + lastTex = null;// CGL.Texture.getEmptyTexture(cgl); + trigger.trigger(); + return; + } + else + if (!effect || reInitEffect || lastTex != inTexture.get()) + { + initEffect(); + } + const vp = cgl.getViewPort(); + prevViewPort[0] = vp[0]; + prevViewPort[1] = vp[1]; + prevViewPort[2] = vp[2]; + prevViewPort[3] = vp[3]; + + updateResolution(); + + lastTex = inTexture.get(); + const oldEffect = cgl.currentTextureEffect; + cgl.currentTextureEffect = effect; + effect.setSourceTexture(tex); + + effect.startEffect(); + + // render background color... + cgl.pushShader(bgShader); + cgl.currentTextureEffect.bind(); + cgl.setTexture(0, inTexture.get().tex); + if (inTextureMask.get())cgl.setTexture(1, inTextureMask.get().tex); + + cgl.pushBlend(false); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + cgl.popBlend(); + + texOut.set(effect.getCurrentSourceTexture()); + + effect.endEffect(); + + cgl.setViewPort(prevViewPort[0], prevViewPort[1], prevViewPort[2], prevViewPort[3]); + + cgl.currentTextureEffect = oldEffect; + + cgl.setTexture(0, CGL.Texture.getEmptyTexture(cgl).tex); + + trigger.trigger(); +} + +function updateParams() +{ + bgShader.toggleDefine("TEX_MASK", inTextureMask.get()); + + bgShader.toggleDefine("GREY_R", greyscale.get() === "R"); + bgShader.toggleDefine("GREY_G", greyscale.get() === "G"); + bgShader.toggleDefine("GREY_B", greyscale.get() === "B"); + bgShader.toggleDefine("GREY_A", greyscale.get() === "A"); + bgShader.toggleDefine("GREY_LUMI", greyscale.get() === "Luminance"); + + bgShader.toggleDefine("ALPHA_1", alphaMaskMethod.get() === "1"); + bgShader.toggleDefine("ALPHA_A", alphaMaskMethod.get() === "A"); + + bgShader.toggleDefine("INVERT_R", invertR.get()); + bgShader.toggleDefine("INVERT_G", invertG.get()); + bgShader.toggleDefine("INVERT_B", invertB.get()); + bgShader.toggleDefine("INVERT_A", invertA.get()); + + if (twrap.get() == "repeat") selectedWrap = CGL.Texture.WRAP_REPEAT; + else if (twrap.get() == "mirrored repeat") selectedWrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + else if (twrap.get() == "clamp to edge") selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + if (tfilter.get() == "nearest") selectedFilter = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "linear") selectedFilter = CGL.Texture.FILTER_LINEAR; + else if (tfilter.get() == "mipmap") selectedFilter = CGL.Texture.FILTER_MIPMAP; + + if (bgShader.needsRecompile()) + { + reInitEffect = true; + } + if (tex && ( + tex.width != Math.floor(width.get()) || + tex.height != Math.floor(height.get()) || + tex.wrap != selectedWrap || + tex.isFloatingPoint() != fpTexture.get() + )) + { + reInitEffect = true; + } +} + + +}; + +Ops.Gl.Textures.CopyTexture.prototype = new CABLES.Op(); +CABLES.OPS["18a6d1f4-a7f8-4a3e-ab1d-0c2d2efe3861"]={f:Ops.Gl.Textures.CopyTexture,objName:"Ops.Gl.Textures.CopyTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.EmptyTexture +// +// ************************************************************** + +Ops.Gl.Textures.EmptyTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const width = op.inValue("width", 8); +const height = op.inValue("height", 8); +const textureOut = op.outTexture("texture"); + +const cgl = op.patch.cgl; +const tex = new CGL.Texture(cgl); + +width.onChange = sizeChanged; +height.onChange = sizeChanged; + +sizeChanged(); + +function sizeChanged() +{ + tex.setSize(width.get(), height.get()); + textureOut.set(tex); +} + + +}; + +Ops.Gl.Textures.EmptyTexture.prototype = new CABLES.Op(); +CABLES.OPS["fc124913-0916-4f5c-83e0-702ddf66420c"]={f:Ops.Gl.Textures.EmptyTexture,objName:"Ops.Gl.Textures.EmptyTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.ExrTexture +// +// ************************************************************** + +Ops.Gl.Textures.ExrTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inFile = op.inUrl("EXR File", [".exr"]), + inAlpha = op.inBool("Remove Alpha", false), + inFilter = op.inSwitch("Filter", ["Nearest", "Linear"], "Nearest"), + outTex = op.outTexture("Texture"), + outWidth = op.outNumber("Width"), + outHeight = op.outNumber("Height"), + outChannels = op.outString("Channels"), + outLoading = op.outBool("Loading"); + +let + loadingId = null, + timedLoader = null, + finishedLoading = false; + +const cgl = op.patch.cgl; + +inFilter.onChange = +inAlpha.onChange = +inFile.onChange = reloadSoon; + +function reloadSoon(nocache) +{ + clearTimeout(timedLoader); + timedLoader = setTimeout(function () { loadBin(nocache); }, 30); +} + +function loadBin(addCacheBuster) +{ + // if (!inActive.get()) return; + + if (!loadingId)loadingId = op.patch.loading.start("gltf" + inFile.get(), inFile.get()); + + let url = op.patch.getFilePath(String(inFile.get())); + if (addCacheBuster)url += "?rnd=" + CABLES.generateUUID(); + finishedLoading = false; + outLoading.set(true); + const oReq = new XMLHttpRequest(); + oReq.open("GET", url, true); + oReq.responseType = "arraybuffer"; + + op.patch.loading.addAssetLoadingTask(() => + { + oReq.onload = (oEvent) => + { + const arrayBuffer = oReq.response; + const l = new CABLES.EXRLoader(); + + try + { + const p = l.parse(arrayBuffer); + outTex.set(CGL.Texture.getEmptyTexture(op.patch.cgl)); + + if (p) + { + const arr = new Float32Array(p.data.length); + for (let i = 0; i < p.data.length; i++) + arr[i] = p.data[i]; + + if (inAlpha.get()) + for (let i = 3; i < arr.length; i += 4)arr[i] = 1; + + let channels = ""; + for (let i = 0; i < p.header.channels.length; i++) + channels += p.header.channels[i].name; + + outChannels.set(channels); + + let filter = CGL.Texture.FILTER_NEAREST; + if (inFilter.get() === "Linear")filter = CGL.Texture.FILTER_LINEAR; + const tex = new CGL.Texture(cgl, { + "filter": filter, + "wrap": filter, + "isFloatingPointTexture": true }); + + tex.initFromData(arr, p.width, p.height, filter, filter); + outTex.set(tex); + outWidth.set(p.width); + outHeight.set(p.height); + } + else + { + outWidth.set(0); + outHeight.set(0); + } + } + catch (e) + { + op.logError(e); + } + + cgl.patch.loading.finished(loadingId); + finishedLoading = true; + outLoading.set(false); + }; + + oReq.send(null); + }); +} + +op.onFileChanged = function (fn) +{ + if (inFile.get() && inFile.get().indexOf(fn) > -1) + { + outTex.set(CGL.Texture.getEmptyTexture(op.patch.cgl)); + reloadSoon(true); + } +}; + + +}; + +Ops.Gl.Textures.ExrTexture.prototype = new CABLES.Op(); +CABLES.OPS["81a807c3-f814-4815-a43c-5914c223faf4"]={f:Ops.Gl.Textures.ExrTexture,objName:"Ops.Gl.Textures.ExrTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.GraphTexture +// +// ************************************************************** + +Ops.Gl.Textures.GraphTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + trigger = this.inTrigger("trigger"), + value = this.inValueFloat("value"), + index = this.inValueInt("index"), + inReset = this.inTriggerButton("reset"), + inShowMinMax = op.inValueBool("Show Min/Max"), + inSeed = op.inValueFloat("Color Random Seed", 23), + inWidth = op.inValueInt("Texture Width", 512), + inHeight = op.inValueInt("Texture Height", 512), + inLineWidth = op.inFloat("Line Width", 2), + + texOut = op.outTexture("Texture"), + outCanvas = op.outObject("Canvas Element"); + +const cgl = op.patch.cgl; + +let canvas = document.createElement("canvas"); +canvas.id = "graph_" + Math.random(); +canvas.width = 512; +canvas.height = 512; +// canvas.style.display = "none"; +// var body = document.getElementsByTagName("body")[0]; +// body.appendChild(canvas); +outCanvas.set(canvas); + +// let canvImage = document.getElementById(canvas.id); +let ctx = canvas.getContext("2d"); + +inWidth.onChange = inHeight.onChange = function () +{ + canvas.width = inWidth.get(); + canvas.height = inHeight.get(); +}; + +let buff = []; + +let maxValue = -Number.MAX_VALUE; +let minValue = Number.MAX_VALUE; +let colors = []; +let lastTime = Date.now(); + +value.onLinkChanged = reset; +index.onLinkChanged = reset; +inReset.onTriggered = reset; + +value.onChange = function () +{ + addValue(value.get(), Math.round(index.get())); +}; + +trigger.onTriggered = function () +{ + for (let i = 0; i < buff.length; i++) + if (buff[i]) addValue(buff[i][buff[i].length - 1], i); + + updateGraph(); +}; + +function reset() +{ + buff.length = 0; + maxValue = -999999; + minValue = 999999; +} + +function addValue(val, currentIndex) +{ + maxValue = Math.max(maxValue, parseFloat(val)); + minValue = Math.min(minValue, parseFloat(val)); + + if (!buff[currentIndex]) + { + buff[currentIndex] = []; + Math.randomSeed = inSeed.get() + currentIndex; + + colors[currentIndex] = "rgba(" + Math.round(Math.seededRandom() * 255) + "," + Math.round(Math.seededRandom() * 255) + "," + Math.round(Math.seededRandom() * 255) + ",1)"; + } + + let buf = buff[currentIndex]; + buf.push(val); + + if (!trigger.isLinked()) if (Date.now() - lastTime > 30)updateGraph(); +} + +function updateGraph() +{ + function getPos(v) + { + return canvas.height - ((v / h * canvas.height / 2 * 0.9) + canvas.height / 2); + } + + ctx.fillStyle = "#000"; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + ctx.fillStyle = "#444"; + ctx.fillRect(0, getPos(0), canvas.width, 1); + + for (let b = 0; b < buff.length; b++) + { + let buf = buff[b]; + if (!buf) continue; + + ctx.lineWidth = inLineWidth.get(); + + var h = Math.max(Math.abs(maxValue), Math.abs(minValue)); + let heightmul = canvas.height / h; + let start = Math.max(0, buf.length - canvas.width); + + ctx.beginPath(); + ctx.strokeStyle = colors[b]; + + ctx.moveTo(0, getPos(buf[start])); + + for (let i = start; i < buf.length; i++) + { + ctx.lineTo( + 1 + i - start, + getPos(buf[i])); + } + ctx.stroke(); + } + + ctx.font = "22px monospace"; + + if (inShowMinMax.get()) + { + ctx.fillStyle = "#fff"; + ctx.fillText("max:" + (Math.round(maxValue * 100) / 100), 10, canvas.height - 10); + ctx.fillText("min:" + (Math.round(minValue * 100) / 100), 10, canvas.height - 30); + } + + if (texOut.get()) texOut.get().initTexture(canvas); + else texOut.set(new CGL.Texture.createFromImage(cgl, canvas, + { + "filter": CGL.Texture.FILTER_MIPMAP + + })); + + lastTime = Date.now(); +} + + +}; + +Ops.Gl.Textures.GraphTexture.prototype = new CABLES.Op(); +CABLES.OPS["98d1c79e-71ea-468b-81fc-17da2cd3da89"]={f:Ops.Gl.Textures.GraphTexture,objName:"Ops.Gl.Textures.GraphTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.Histogram +// +// ************************************************************** + +Ops.Gl.Textures.Histogram = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"histogram_frag":"void main()\n{\n float p=1.0/256.0;\n outColor = vec4(1.0,1.0,1.0,p);\n}\n","histogram_vert":"IN vec3 vPosition;\nIN vec2 attrTexCoord;\nUNI sampler2D tex;\n\nfloat lumi(vec3 color)\n{\n return dot(vec3(0.2126,0.7152,0.0722), color);\n}\n\nvoid main()\n{\n vec2 tc=attrTexCoord;\n\n float strength;\n highp float pos=0.0;\n #ifdef HISTOGRAM_R\n strength=texture(tex,tc).r;\n pos=1.0;\n #endif\n\n #ifdef HISTOGRAM_G\n strength=texture(tex,tc).g;\n pos=0.75;\n #endif\n\n #ifdef HISTOGRAM_B\n strength=texture(tex,tc).b;\n pos=0.5;\n #endif\n\n #ifdef HISTOGRAM_LUMI\n strength=lumi(texture(tex,tc).rgb);\n pos=0.25;\n #endif\n\n vec4 model= vec4(strength*2.0-1.0, pos , 0.0,1.0);\n\n gl_PointSize=1.0;\n gl_Position= model;\n}\n","histogram_wave_frag":"UNI sampler2D tex;\nIN vec2 texCoord;\n\nvoid main()\n{\n vec4 col=vec4(0.0,0.0,0.0,1.0);\n float strengthR=texture(tex,vec2(texCoord.x,1.0-0.0)).r;\n float strengthG=texture(tex,vec2(texCoord.x,1.0-0.2)).r;\n float strengthB=texture(tex,vec2(texCoord.x,1.0-0.3)).r;\n float strengthL=texture(tex,vec2(texCoord.x,1.0-0.4)).r;\n\n strengthR*=strengthR;\n strengthG*=strengthG;\n strengthB*=strengthB;\n strengthL*=strengthL;\n\n\n\n if(strengthR*0.5>texCoord.y) col.r=1.0;\n if(strengthG*0.5>texCoord.y) col.g=1.0;\n if(strengthB*0.5>texCoord.y) col.b=1.0;\n\n if(strengthL > texCoord.y*2.0-1.0 && texCoord.y>0.5) col.rgb=vec3(1.0);\n\n outColor= col;\n}\n",}; +const + exe = op.inTrigger("Trigger"), + inTex = op.inTexture("Texture"), + outTex = op.outTexture("Histogram Texture"), + outTexData = op.outTexture("Histogram Data"); + +const cgl = op.patch.cgl; +let meshPoints = null; +let fb = new CGL.Framebuffer2(cgl, 256, 8, { "isFloatingPointTexture": true, + "filter": CGL.Texture.FILTER_NEAREST, + "wrap": CGL.Texture.WRAP_CLAMP_TO_EDGE }); + +// fb.setFilter(CGL.Texture.FILTER_NEAREST); +let effect = null; + +function initEffect() +{ + if (effect)effect.delete(); + effect = new CGL.TextureEffect(cgl, { "isFloatingPointTexture": false }); + + let tex = new CGL.Texture(cgl, + { + "isFloatingPointTexture": false, + "filter": CGL.Texture.FILTER_NEAREST, + "wrap": CGL.Texture.WRAP_CLAMP_TO_EDGE, + "width": 256, + "height": 256, + }); + + effect.setSourceTexture(tex); + outTex.set(null); +} + +function setUpPointVerts() +{ + const geom = new CGL.Geometry(op.name); + let res = 256; + let verts = []; + let texCoords = []; + let i = 0; + verts.length = res * res * 3; + texCoords.length = res * res * 2; + for (let x = 0; x < res; x++) + { + for (let y = 0; y < res; y++) + { + i++; + verts[i * 3 + 2] = verts[i * 3 + 1] = verts[i * 3 + 0] = 0; + texCoords[i * 2] = x / res; + texCoords[i * 2 + 1] = y / res; + } + } + geom.setPointVertices(verts); + geom.texCoords = texCoords; + + meshPoints = new CGL.Mesh(cgl, geom, cgl.gl.POINTS); + meshPoints.setGeom(geom); +} + +let shaderWave = new CGL.Shader(cgl, "imgcompose bg"); +shaderWave.setSource(shaderWave.getDefaultVertexShader(), attachments.histogram_wave_frag); +shaderWave.textureUniform = new CGL.Uniform(shaderWave, "t", "tex", 2); + +let shaderPointsR = new CGL.Shader(cgl, "histogram r"); +shaderPointsR.setSource(attachments.histogram_vert, attachments.histogram_frag); +shaderPointsR.textureUniform = new CGL.Uniform(shaderPointsR, "t", "tex", 0); +shaderPointsR.define("HISTOGRAM_R"); + +let shaderPointsG = new CGL.Shader(cgl, "histogram g"); +shaderPointsG.setSource(attachments.histogram_vert, attachments.histogram_frag); +shaderPointsG.textureUniform = new CGL.Uniform(shaderPointsG, "t", "tex", 0); +shaderPointsG.define("HISTOGRAM_G"); + +let shaderPointsB = new CGL.Shader(cgl, "histogram b"); +shaderPointsB.setSource(attachments.histogram_vert, attachments.histogram_frag); +shaderPointsB.textureUniform = new CGL.Uniform(shaderPointsB, "t", "tex", 0); +shaderPointsB.define("HISTOGRAM_B"); + +let shaderPointsLumi = new CGL.Shader(cgl, "histogram lumi"); +shaderPointsLumi.setSource(attachments.histogram_vert, attachments.histogram_frag); +shaderPointsLumi.textureUniform = new CGL.Uniform(shaderPointsLumi, "t", "tex", 0); +shaderPointsLumi.define("HISTOGRAM_LUMI"); + +setUpPointVerts(); +initEffect(); +let prevViewPort = [0, 0, 0, 0]; + +exe.onTriggered = function () +{ + if (meshPoints && inTex.get()) + { + cgl.pushBlendMode(CGL.BLEND_NORMAL, false); + cgl.pushBlend(true); + + let vp = cgl.getViewPort(); + prevViewPort[0] = vp[0]; + prevViewPort[1] = vp[1]; + prevViewPort[2] = vp[2]; + prevViewPort[3] = vp[3]; + + // setup data + fb.renderStart(cgl); + + cgl.setTexture(0, inTex.get().tex); + meshPoints.render(shaderPointsR); + meshPoints.render(shaderPointsG); + meshPoints.render(shaderPointsB); + meshPoints.render(shaderPointsLumi); + + fb.renderEnd(cgl); + outTexData.set(fb.getTextureColor()); + + // render wave + + cgl.currentTextureEffect = effect; + + effect.startEffect(); + + cgl.pushShader(shaderWave); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(2, fb.getTextureColor().tex); + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + outTex.set(effect.getCurrentSourceTexture()); + + effect.endEffect(); + + cgl.setViewPort(prevViewPort[0], prevViewPort[1], prevViewPort[2], prevViewPort[3]); + + cgl.popBlend(); + cgl.popBlendMode(); + + cgl.currentTextureEffect = null; + } +}; + + +}; + +Ops.Gl.Textures.Histogram.prototype = new CABLES.Op(); +CABLES.OPS["966cefee-8349-4ef3-b64e-69afca0395f5"]={f:Ops.Gl.Textures.Histogram,objName:"Ops.Gl.Textures.Histogram"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.NoiseTexture +// +// ************************************************************** + +Ops.Gl.Textures.NoiseTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + + inWidth = op.inValueInt("Width", 256), + inHeight = op.inValueInt("Height", 256), + tfilter = op.inSwitch("Filter", ["nearest", "linear"], "nearest"), + wrap = op.inValueSelect("Wrap", ["repeat", "mirrored repeat", "clamp to edge"], "repeat"), + inColor = op.inValueBool("Color", false), + inPixel = op.inDropDown("Pixel Format", CGL.Texture.PIXELFORMATS, CGL.Texture.PFORMATSTR_RGBA8UB), + + inSeed = op.inFloat("Seed", 0), + inOutR = op.inBool("Channel R", true), + inMinR = op.inFloat("Min R", 0), + inMaxR = op.inFloat("Max R", 1), + inOutG = op.inBool("Channel G", true), + inMinG = op.inFloat("Min G", 0), + inMaxG = op.inFloat("Max G", 1), + inOutB = op.inBool("Channel B", true), + inMinB = op.inFloat("Min B", 0), + inMaxB = op.inFloat("Max B", 1), + outTex = op.outTexture("Texture"); + +const cgl = op.patch.cgl; + +inSeed.onChange = + inWidth.onChange = + inHeight.onChange = + inPixel.onChange = + inMinR.onChange = + inMaxR.onChange = + inMinG.onChange = + inMaxG.onChange = + inMinB.onChange = + inMaxB.onChange = + inOutR.onChange = + inOutB.onChange = + inOutG.onChange = + tfilter.onChange = + wrap.onChange = + inColor.onChange = update; + +update(); + +function update() +{ + const isFp = inPixel.get() == CGL.Texture.PFORMATSTR_RGBA32F; + if (!isFp) + { + if ( + inMinR.get() < 0.0 || inMinR.get() > 1.0 || + inMinG.get() < 0.0 || inMinG.get() > 1.0 || + inMinB.get() < 0.0 || inMinB.get() > 1.0 || + inMaxR.get() < 0.0 || inMaxR.get() > 1.0 || + inMaxG.get() < 0.0 || inMaxG.get() > 1.0 || + inMaxB.get() < 0.0 || inMaxB.get() > 1.0) op.setUiError("nonfprange", "Non floating point textures have to be between 0 and 1"); + else op.setUiError("nonfprange", null); + } + else op.setUiError("nonfprange", null); + + inMinG.setUiAttribs({ "greyout": !inColor.get() }); + inMaxG.setUiAttribs({ "greyout": !inColor.get() }); + inMinB.setUiAttribs({ "greyout": !inColor.get() }); + inMaxB.setUiAttribs({ "greyout": !inColor.get() }); + + let width = Math.ceil(inWidth.get()); + let height = Math.ceil(inHeight.get()); + + if (width < 1)width = 1; + if (height < 1)height = 1; + + let pixels; + const num = width * 4 * height; + + const minR = inMinR.get(); + const diffR = inMaxR.get() - minR; + + const minG = inMinG.get(); + const diffG = inMaxG.get() - minG; + + const minB = inMinB.get(); + const diffB = inMaxB.get() - minB; + + Math.randomSeed = inSeed.get(); + + if (isFp) + { + pixels = new Float32Array(num); + + if (inColor.get()) + { + for (let i = 0; i < num; i += 4) + { + pixels[i + 0] = minR + Math.seededRandom() * diffR; + pixels[i + 1] = minG + Math.seededRandom() * diffG; + pixels[i + 2] = minB + Math.seededRandom() * diffB; + pixels[i + 3] = 1; + } + } + else + { + for (let i = 0; i < num; i += 4) + { + let c = minR + Math.seededRandom() * diffR; + pixels[i + 0] = pixels[i + 1] = pixels[i + 2] = c; + pixels[i + 3] = 1; + } + } + } + else + { + pixels = new Uint8Array(num); + + if (inColor.get()) + { + for (let i = 0; i < num; i += 4) + { + pixels[i + 0] = (minR + Math.seededRandom() * diffR) * 255; + pixels[i + 1] = (minG + Math.seededRandom() * diffG) * 255; + pixels[i + 2] = (minB + Math.seededRandom() * diffB) * 255; + pixels[i + 3] = 255; + } + } + else + { + for (let i = 0; i < num; i += 4) + { + pixels[i + 0] = + pixels[i + 1] = + pixels[i + 2] = (minR + Math.seededRandom() * diffR) * 255; + pixels[i + 3] = 255; + } + } + } + + if (!inOutR.get()) for (let i = 0; i < num; i += 4)pixels[i + 0] = 0.0; + if (!inOutG.get()) for (let i = 0; i < num; i += 4)pixels[i + 1] = 0.0; + if (!inOutB.get()) for (let i = 0; i < num; i += 4)pixels[i + 2] = 0.0; + + let cgl_filter = CGL.Texture.FILTER_NEAREST; + if (tfilter.get() == "linear") cgl_filter = CGL.Texture.FILTER_LINEAR; + // else if (tfilter.get() == "mipmap") cgl_filter = CGL.Texture.FILTER_MIPMAP; + // else if (tfilter.get() == "Anisotropic") cgl_filter = CGL.Texture.FILTER_ANISOTROPIC; + + let cgl_wrap = CGL.Texture.WRAP_REPEAT; + if (wrap.get() == "mirrored repeat") cgl_wrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + if (wrap.get() == "clamp to edge") cgl_wrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + let tex = new CGL.Texture(cgl, { "isFloatingPointTexture": isFp }); + + tex.initFromData(pixels, width, height, cgl_filter, cgl_wrap); + + outTex.set(CGL.Texture.getEmptyTexture(op.patch.cgl, isFp)); + outTex.set(tex); +} + + +}; + +Ops.Gl.Textures.NoiseTexture.prototype = new CABLES.Op(); +CABLES.OPS["b781bc6b-b2cf-44fe-80eb-a840e430d27d"]={f:Ops.Gl.Textures.NoiseTexture,objName:"Ops.Gl.Textures.NoiseTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.PaletteTexture +// +// ************************************************************** + +Ops.Gl.Textures.PaletteTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + arrayInPalette = op.inArray("Palette array"), + inLinear = op.inValueBool("Smooth"), + arrOut = op.outArray("Color Array"), + textureOut = op.outTexture("Texture"); + +const cgl = op.patch.cgl; + +let canvas = document.createElement("canvas"); +canvas.id = "canvas_" + CABLES.generateUUID(); +canvas.width = 5; +canvas.height = 8; +canvas.style.display = "none"; + +let body = document.getElementsByTagName("body")[0]; +body.appendChild(canvas); +let ctx = canvas.getContext("2d"); + +textureOut.set(CGL.Texture.getEmptyTexture(cgl)); + +let arr = []; +let lastFilter = null; + +let r = 0; +let g = 0; +let b = 0; + +inLinear.onChange = arrayInPalette.onChange = buildTexture; + +function hexToR(h) +{ + return parseInt((cutHex(h)).substring(0, 2), 16); +} + +function hexToG(h) +{ + return parseInt((cutHex(h)).substring(2, 4), 16); +} + +function hexToB(h) +{ + return parseInt((cutHex(h)).substring(4, 6), 16); +} + +function cutHex(h) +{ + return (h.charAt(0) == "#") ? h.substring(1, 7) : h; +} + +function buildTexture() +{ + let colors = arrayInPalette.get(); + let isHexCode; + if (!colors) + { + return; + } + + let stringTest = colors[0]; + let paletteSize = 0; + + if (typeof stringTest === "string") + { + isHexCode = true; + paletteSize = colors.length; + canvas.width = paletteSize; + arr.length = colors.length; + } + else + { + isHexCode = false; + paletteSize = Math.floor(colors.length / 3); + canvas.width = paletteSize; + arr.length = paletteSize; + } + + for (let i = 0; i < paletteSize; i++) + { + if (isHexCode) + { + r = hexToR(colors[i]); + g = hexToG(colors[i]); + b = hexToB(colors[i]); + + arr[i * 3 + 0] = r / 255; + arr[i * 3 + 1] = g / 255; + arr[i * 3 + 2] = b / 255; + } + else + { + r = Math.floor(colors[i * 3 + 0] * 255); + g = Math.floor(colors[i * 3 + 1] * 255); + b = Math.floor(colors[i * 3 + 2] * 255); + + arr[i * 3 + 0] = colors[i * 3 + 0]; + arr[i * 3 + 1] = colors[i * 3 + 1]; + arr[i * 3 + 2] = colors[i * 3 + 2]; + } + + ctx.fillStyle = "rgb(" + r + "," + g + "," + b + ")"; + ctx.fillRect( + canvas.width / paletteSize * i, + 0, + canvas.width / paletteSize, + canvas.height + ); + } + + let filter = CGL.Texture.FILTER_NEAREST; + if (inLinear.get())filter = CGL.Texture.FILTER_LINEAR; + + if (lastFilter == filter && textureOut.get()) textureOut.get().initTexture(canvas, filter); + else textureOut.set(new CGL.Texture.createFromImage(op.patch.cgl, canvas, { "filter": filter })); + + arrOut.set(null); + arrOut.set(arr); + textureOut.get().unpackAlpha = false; + lastFilter = filter; +} + +arrayInPalette.onLinkChanged = function () +{ + if (!arrayInPalette.isLinked()) + { + arrOut.set(null); + textureOut.set(CGL.Texture.getEmptyTexture(cgl)); + lastFilter = null; + } +}; + +op.onDelete = function () +{ + canvas.remove(); +}; + +buildTexture(); + + +}; + +Ops.Gl.Textures.PaletteTexture.prototype = new CABLES.Op(); +CABLES.OPS["8117ed3b-a264-4a46-83a4-3cdb3f743d10"]={f:Ops.Gl.Textures.PaletteTexture,objName:"Ops.Gl.Textures.PaletteTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.SwitchTextures_v2 +// +// ************************************************************** + +Ops.Gl.Textures.SwitchTextures_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("exec"), + num = this.inValueInt("num"), + defaultTransparent = op.inValueBool("Default Texture Transparent", true), + next = op.outTrigger("Next"), + textureOut = this.outTexture("texture"); + +const cgl = op.patch.cgl; +const texturePorts = []; +let index = 0; +let lastIndex = -1; +let tempTexture = CGL.Texture.getEmptyTexture(cgl); + +op.toWorkPortsNeedToBeLinked(exec); +exec.onTriggered = function () { updateTexture(); next.trigger(); }; + + +defaultTransparent.onChange = function () +{ + if (defaultTransparent.get()) tempTexture = CGL.Texture.getEmptyTexture(cgl); + else tempTexture = CGL.Texture.getTempTexture(cgl); + + updateTexture(true); +}; + +for (let i = 0; i < 16; i++) +{ + const tex = op.inTexture("texture" + i); + texturePorts.push(tex); + tex.onChange = forceUpdateTexture; +} + +function forceUpdateTexture() +{ + updateTexture(true); +} + +function updateTexture(force) +{ + index = parseInt(num.get(), 10); + if (!force) + { + if (index == lastIndex) return; + if (index != index) return; + } + if ( + isNaN(index) || + index < 0 || + index > texturePorts.length - 1 + ) + index = 0; + + if (texturePorts[index].get()) textureOut.set(texturePorts[index].get()); + else textureOut.set(tempTexture); + + lastIndex = index; +} + + +}; + +Ops.Gl.Textures.SwitchTextures_v2.prototype = new CABLES.Op(); +CABLES.OPS["a82ae429-ac07-4760-882b-595a857c7ae0"]={f:Ops.Gl.Textures.SwitchTextures_v2,objName:"Ops.Gl.Textures.SwitchTextures_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.TextTexture_v4 +// +// ************************************************************** + +Ops.Gl.Textures.TextTexture_v4 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"text_frag":"UNI sampler2D tex;\nUNI float a;\nUNI vec3 color;\nIN vec2 texCoord;\n\nvec4 myround(vec4 col)\n{\n if(col.a>0.5)return vec4(1.0,1.0,1.0,1.0);\n else return vec4(1.0,1.0,1.0,0.0);\n}\n\nvoid main()\n{\n vec4 col;\n\n #ifndef HARD_EDGE\n // col= vec4(1.0,1.0,1.0,texture(tex,vec2(texCoord.x,(1.0-texCoord.y))).r*a);\n col = texture(tex,vec2(texCoord.x,(1.0-texCoord.y)));\n #endif\n #ifdef HARD_EDGE\n\n float step=0.7;\n col=texture(tex,vec2(texCoord.x,1.0-texCoord.y));\n vec4 col2=texture(tex,vec2(texCoord.x-(fwidth(texCoord.x)*step),1.0-texCoord.y-(fwidth(texCoord.y)*step)));\n vec4 col3=texture(tex,vec2(texCoord.x+(fwidth(texCoord.x)*step),1.0-texCoord.y+(fwidth(texCoord.y)*step)));\n vec4 col4=texture(tex,vec2(texCoord.x+(fwidth(texCoord.x)*step),1.0-texCoord.y-(fwidth(texCoord.y)*step)));\n vec4 col5=texture(tex,vec2(texCoord.x-(fwidth(texCoord.x)*step),1.0-texCoord.y+(fwidth(texCoord.y)*step)));\n\n float f=smoothstep(col.a,0.5,0.8);\n\n col=myround(col);\n col2=myround(col2);\n col3=myround(col3);\n col4=myround(col4);\n col5=myround(col5);\n\n // col.a=(col.a+col2.a+col3.a+col4.a+col5.a)/5.0*a;\n\n #endif\n\n col.rgb=color.rgb;\n\n outColor=col;\n\n}\n","text_vert":"{{MODULES_HEAD}}\n\nIN vec3 vPosition;\nUNI mat4 projMatrix;\nUNI mat4 mvMatrix;\nUNI float aspect;\nOUT vec2 texCoord;\nIN vec2 attrTexCoord;\n\nvoid main()\n{\n vec4 pos=vec4(vPosition, 1.0);\n\n pos.x*=aspect;\n\n texCoord=vec2(attrTexCoord.x,1.0-attrTexCoord.y);;\n\n gl_Position = projMatrix * mvMatrix * pos;\n}\n",}; +function componentToHex(c) +{ + const hex = c.toString(16); + return hex.length == 1 ? "0" + hex : hex; +} + +function rgbToHex(r, g, b) +{ + return "#" + componentToHex(Math.floor(r * 255)) + componentToHex(Math.floor(g * 255)) + componentToHex(Math.floor(b * 255)); +} + +const + render = op.inTriggerButton("Render"), + text = op.inString("text", "cables"), + font = op.inString("font", "Arial"), + weight = op.inString("weight", "normal"), + maximize = op.inValueBool("Maximize Size", true), + inFontSize = op.inValueFloat("fontSize", 30), + lineDistance = op.inValueFloat("Line Height", 1), + lineOffset = op.inValueFloat("Vertical Offset", 0), + // letterSpacing = op.inValueFloat("Spacing", 0), + drawDebug = op.inBool("Show Debug", false), + limitLines = op.inValueInt("Limit Lines", 0), + texWidth = op.inValueInt("texture width", 512), + texHeight = op.inValueInt("texture height", 128), + tfilter = op.inSwitch("filter", ["nearest", "linear", "mipmap"], "linear"), + wrap = op.inValueSelect("Wrap", ["repeat", "mirrored repeat", "clamp to edge"], "clamp to edge"), + aniso = op.inSwitch("Anisotropic", [0, 1, 2, 4, 8, 16], 0), + align = op.inSwitch("align", ["left", "center", "right"], "center"), + valign = op.inSwitch("vertical align", ["top", "center", "bottom"], "center"), + cachetexture = op.inValueBool("Reuse Texture", true), + drawMesh = op.inValueBool("Draw Mesh", true), + meshScale = op.inValueFloat("Scale Mesh", 1.0), + renderHard = op.inValueBool("Hard Edges", false), + inOpacity = op.inFloatSlider("Opacity", 1), + r = op.inValueSlider("r", Math.random()), + g = op.inValueSlider("g", Math.random()), + b = op.inValueSlider("b", Math.random()), + next = op.outTrigger("Next"), + outRatio = op.outNumber("Ratio"), + textureOut = op.outTexture("texture"), + outAspect = op.outNumber("Aspect", 1), + outLines = op.outNumber("Num Lines"); + +r.setUiAttribs({ "colorPick": true }); + +op.setPortGroup("Color", [r, g, b]); +op.setPortGroup("Size", [font, weight, maximize, inFontSize, lineDistance, lineOffset]); +op.setPortGroup("Texture", [texWidth, texHeight, tfilter, aniso]); +op.setPortGroup("Alignment", [valign, align]); +op.setPortGroup("Rendering", [drawMesh, renderHard, meshScale]); + +align.onChange = + valign.onChange = + text.onChange = + inFontSize.onChange = + weight.onChange = + aniso.onChange = + font.onChange = + lineOffset.onChange = + lineDistance.onChange = + cachetexture.onChange = + // letterSpacing.onChange = + limitLines.onChange = + texWidth.onChange = + texHeight.onChange = + maximize.onChange = function () { needsRefresh = true; }; + +wrap.onChange = () => +{ + if (tex)tex.delete(); + tex = null; + needsRefresh = true; +}; + +r.onChange = g.onChange = b.onChange = inOpacity.onChange = function () +{ + if (!drawMesh.get() || textureOut.isLinked()) + needsRefresh = true; +}; +textureOut.onLinkChanged = () => +{ + if (textureOut.isLinked()) needsRefresh = true; +}; + +op.patch.on("fontLoaded", (fontName) => +{ + if (fontName == font.get()) + { + needsRefresh = true; + } +}); + +render.onTriggered = doRender; + +aniso.onChange = +tfilter.onChange = () => +{ + tex = null; + needsRefresh = true; +}; + +textureOut.ignoreValueSerialize = true; + +const cgl = op.patch.cgl; +const body = document.getElementsByTagName("body")[0]; + +let tex = new CGL.Texture(cgl); +const fontImage = document.createElement("canvas"); +fontImage.id = "texturetext_" + CABLES.generateUUID(); +fontImage.style.display = "none"; +body.appendChild(fontImage); + +const ctx = fontImage.getContext("2d"); +let needsRefresh = true; +const mesh = CGL.MESHES.getSimpleRect(cgl, "texttexture rect"); +const vScale = vec3.create(); + +const shader = new CGL.Shader(cgl, "texttexture"); +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); +shader.setSource(attachments.text_vert, attachments.text_frag); +const texUni = new CGL.Uniform(shader, "t", "tex"); +const aspectUni = new CGL.Uniform(shader, "f", "aspect", 0); +const opacityUni = new CGL.Uniform(shader, "f", "a", inOpacity); +const uniColor = new CGL.Uniform(shader, "3f", "color", r, g, b); +// const uniformColor = new CGL.Uniform(shader, "4f", "") + +if (op.patch.isEditorMode()) CABLES.UI.SIMPLEWIREFRAMERECT = CABLES.UI.SIMPLEWIREFRAMERECT || new CGL.WireframeRect(cgl); + +if (cgl.glVersion < 2) +{ + cgl.gl.getExtension("OES_standard_derivatives"); + shader.enableExtension("GL_OES_standard_derivatives"); +} + +renderHard.onChange = function () +{ + shader.toggleDefine("HARD_EDGE", renderHard.get()); +}; + +function doRender() +{ + if (ctx.canvas.width != texWidth.get())needsRefresh = true; + if (needsRefresh) + { + reSize(); + refresh(); + } + + if (drawMesh.get()) + { + vScale[0] = vScale[1] = vScale[2] = meshScale.get(); + cgl.pushBlendMode(CGL.BLEND_NORMAL, false); + cgl.pushModelMatrix(); + mat4.scale(cgl.mMatrix, cgl.mMatrix, vScale); + + shader.popTextures(); + shader.pushTexture(texUni, tex.tex); + aspectUni.set(outAspect.get()); + + if (cgl.shouldDrawHelpers(op)) + CABLES.UI.SIMPLEWIREFRAMERECT.render(outAspect.get(), 1, 1); + + cgl.pushShader(shader); + mesh.render(shader); + + cgl.popShader(); + cgl.popBlendMode(); + cgl.popModelMatrix(); + } + + next.trigger(); +} + +function reSize() +{ + if (!tex) return; + tex.setSize(texWidth.get(), texHeight.get()); + + ctx.canvas.width = fontImage.width = texWidth.get(); + ctx.canvas.height = fontImage.height = texHeight.get(); + + outAspect.set(fontImage.width / fontImage.height); + + needsRefresh = true; +} + +maximize.onChange = function () +{ + inFontSize.setUiAttribs({ "greyout": maximize.get() }); + needsRefresh = true; +}; + +function getLineHeight(fontSize) +{ + return lineDistance.get() * fontSize; +} + +function removeEmptyLines(lines) +{ + if (lines[lines.length - 1] === "" || lines[lines.length - 1] === "\n") + { + lines.length--; + lines = removeEmptyLines(lines); + } + return lines; +} + +function refresh() +{ + cgl.checkFrameStarted("texttrexture refresh"); + + // const num=String(parseInt(letterSpacing.get())); + // fontImage.style["letter-spacing"] = num+"px"; + // fontImage.style["font-kerning"]="normal"; + + ctx.clearRect(0, 0, fontImage.width, fontImage.height); + const rgbString = "rgba(" + Math.floor(r.get() * 255) + "," + + Math.floor(g.get() * 255) + "," + Math.floor(b.get() * 255) + "," + + inOpacity.get() + ")"; + // ctx.fillStyle = "white"; + ctx.fillStyle = rgbString; + // op.log("rgbstring", rgbString); + let fontSize = parseFloat(inFontSize.get()); + let fontname = font.get(); + if (fontname.indexOf(" ") > -1) fontname = "\"" + fontname + "\""; + ctx.font = weight.get() + " " + fontSize + "px " + fontname + ""; + // ctx["font-weight"] = 300; + + ctx.textAlign = align.get(); + + let txt = (text.get() + "").replace(//g, "\n"); + let strings = txt.split("\n"); + + needsRefresh = false; + + strings = removeEmptyLines(strings); + + if (maximize.get()) + { + fontSize = texWidth.get(); + let count = 0; + let maxWidth = 0; + let maxHeight = 0; + + do + { + count++; + if (count > (texHeight.get() + texWidth.get()) / 2) + { + op.log("too many iterations - maximize size"); + break; + } + fontSize -= 5; + ctx.font = weight.get() + " " + fontSize + "px \"" + font.get() + "\""; + maxWidth = 0; + + maxHeight = (fontSize + (strings.length - 1) * getLineHeight(fontSize)) * 1.2; + for (let i = 0; i < strings.length; i++) maxWidth = Math.max(maxWidth, ctx.measureText(strings[i]).width); + } + while (maxWidth > ctx.canvas.width || maxHeight > ctx.canvas.height); + } + else + { + let found = true; + + if (texWidth.get() > 128) + { + found = false; + let newString = ""; + + for (let i = 0; i < strings.length; i++) + { + if (!strings[i]) + { + newString += "\n"; + continue; + } + let sumWidth = 0; + const words = strings[i].split(" "); + + for (let j = 0; j < words.length; j++) + { + if (!words[j]) continue; + sumWidth += ctx.measureText(words[j] + " ").width; + + if (sumWidth > texWidth.get()) + { + found = true; + newString += "\n" + words[j] + " "; + sumWidth = ctx.measureText(words[j] + " ").width; + } + else + { + newString += words[j] + " "; + } + } + newString += "\n"; + } + txt = newString; + strings = txt.split("\n"); + } + strings = removeEmptyLines(strings); + + if (limitLines.get() > 0 && strings.length > limitLines.get()) + { + strings.length = limitLines.get(); + strings[strings.length - 1] += "..."; + } + } + + strings = removeEmptyLines(strings); + const firstLineHeight = fontSize; + const textHeight = firstLineHeight + (strings.length - 1) * getLineHeight(fontSize); + + let posy = lineOffset.get() * fontSize; + + if (valign.get() == "top") posy += firstLineHeight; + else if (valign.get() == "center") posy += (ctx.canvas.height / 2) - (textHeight / 2) + firstLineHeight; + else if (valign.get() == "bottom") posy += ctx.canvas.height - textHeight + firstLineHeight; + + let miny = 999999; + let maxy = -999999; + + const dbg = drawDebug.get(); + + for (let i = 0; i < strings.length; i++) + { + let posx = 0; + if (align.get() == "center") posx = ctx.canvas.width / 2; + if (align.get() == "right") posx = ctx.canvas.width; + + ctx.fillText(strings[i], posx, posy); + + miny = Math.min(miny, posy - firstLineHeight); + maxy = Math.max(maxy, posy); + + if (dbg) + { + ctx.lineWidth = 1; + ctx.strokeStyle = "#FF0000"; + ctx.beginPath(); + ctx.moveTo(0, posy); + ctx.lineTo(21000, posy); + ctx.stroke(); + } + + posy += getLineHeight(fontSize); + } + + if (dbg) + { + ctx.lineWidth = 3; + ctx.strokeStyle = "#FF0000"; + ctx.strokeRect(0, miny, ctx.canvas.width - 3, maxy - miny); + } + + ctx.restore(); + + outRatio.set(ctx.canvas.height / ctx.canvas.width); + outLines.set(strings.length); + textureOut.set(CGL.Texture.getEmptyTexture(cgl)); + + let cgl_wrap = CGL.Texture.WRAP_REPEAT; + if (wrap.get() == "mirrored repeat") cgl_wrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + if (wrap.get() == "clamp to edge") cgl_wrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + let f = CGL.Texture.FILTER_LINEAR; + if (tfilter.get() == "nearest") f = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "mipmap") f = CGL.Texture.FILTER_MIPMAP; + + if (!cachetexture.get() || !tex || !textureOut.get() || tex.width != fontImage.width || tex.height != fontImage.height || tex.anisotropic != parseFloat(aniso.get())) + { + if (tex)tex.delete(); + tex = new CGL.Texture.createFromImage(cgl, fontImage, { "filter": f, "anisotropic": parseFloat(aniso.get()), "wrap": cgl_wrap }); + } + + tex.flip = false; + tex.initTexture(fontImage, f); + textureOut.set(tex); + tex.unpackAlpha = true; +} + + +}; + +Ops.Gl.Textures.TextTexture_v4.prototype = new CABLES.Op(); +CABLES.OPS["afab973f-c9ac-47fd-914c-70b42af5c5d4"]={f:Ops.Gl.Textures.TextTexture_v4,objName:"Ops.Gl.Textures.TextTexture_v4"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.TextureInfo +// +// ************************************************************** + +Ops.Gl.Textures.TextureInfo = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTex = op.inObject("Texture"), + outName = op.outNumber("Name"), + outWidth = op.outNumber("Width"), + outHeight = op.outNumber("Height"), + outRatio = op.outNumber("Ratio"), + outFilter = op.outNumber("Filter"), + outWrap = op.outNumber("Wrap"), + outFlipped = op.outNumber("Flipped"), + outFp = op.outNumber("HDR"), + outDefaultEmpty = op.outNumber("Is Empty Default Texture", false), + outDefaultTex = op.outNumber("Is Default Texture", false), + outId = op.outNumber("Id"); + +outFp.setUiAttribs({ "title": "Pixelformat Float 32bit" }); + +const emptyTex = CGL.Texture.getEmptyTexture(op.patch.cgl); +const defaultTex = CGL.Texture.getTempTexture(op.patch.cgl); + +inTex.onChange = function () +{ + if (inTex.get()) + { + outName.set(inTex.get().name); + outWidth.set(inTex.get().width); + outHeight.set(inTex.get().height); + outRatio.set(inTex.get().width / inTex.get().height); + + let strFilter = "unknown"; + if (inTex.get().filter == CGL.Texture.FILTER_NEAREST)strFilter = "nearest"; + else if (inTex.get().filter == CGL.Texture.FILTER_LINEAR)strFilter = "linear"; + else if (inTex.get().filter == CGL.Texture.FILTER_MIPMAP)strFilter = "mipmap"; + + outFilter.set(inTex.get().filter + " " + strFilter); + + let strWrap = "unknown"; + + if (inTex.get().wrap == CGL.Texture.WRAP_CLAMP_TO_EDGE) strWrap = "clamp to edge"; + else if (inTex.get().wrap == CGL.Texture.WRAP_REPEAT) strWrap = "repeat"; + else if (inTex.get().wrap == CGL.Texture.WRAP_MIRRORED_REPEAT) strWrap = "mirrored repeat"; + + outWrap.set(inTex.get().wrap + " " + strWrap); + + outId.set(inTex.get().id); + outFlipped.set(inTex.get().flipped); + outFp.set(inTex.get().textureType == CGL.Texture.TYPE_FLOAT); + } + else + { + outName.set("no texture"); + outWidth.set(0); + outHeight.set(0); + outRatio.set(0); + outFilter.set(null); + outWrap.set(null); + outId.set(null); + outFlipped.set(false); + outFp.set(false); + } + + outDefaultEmpty.set(inTex.get() == emptyTex); + outDefaultTex.set(inTex.get() == defaultTex); +}; + + +}; + +Ops.Gl.Textures.TextureInfo.prototype = new CABLES.Op(); +CABLES.OPS["71e5ee4c-3455-4c09-abb2-67abf382f35b"]={f:Ops.Gl.Textures.TextureInfo,objName:"Ops.Gl.Textures.TextureInfo"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.TextureSVG_v2 +// +// ************************************************************** + +Ops.Gl.Textures.TextureSVG_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + filename = op.inUrl("File"), + texWidth = op.inValueInt("Texture width"), + texHeight = op.inValueInt("Texture height"), + wrap = op.inValueSelect("Wrap", ["repeat", "mirrored repeat", "clamp to edge"], "repeat"), + tfilter = op.inValueSelect("Filter", ["nearest", "linear", "mipmap"], "mipmap"), + textureOut = op.outTexture("Texture"), + outLoaded = op.outBoolNum("Loaded"); + +tfilter.onChange = onFilterChange; +wrap.onChange = onWrapChange; + +texWidth.set(1024); +texHeight.set(1024); + +const cgl = op.patch.cgl; +let canvas = null; +let ctx = null; + +function removeCanvas() +{ + if (!canvas) return; + canvas.remove(); + canvas = null; +} + +function createCanvas() +{ + if (canvas)removeCanvas(); + canvas = document.createElement("canvas"); + canvas.id = "svgcanvas"; + ctx = canvas.getContext("2d", { "alpha": true }); + + ctx.canvas.width = canvas.width = texWidth.get(); + ctx.canvas.height = canvas.height = texHeight.get(); + + canvas.style.display = "none"; + const body = document.getElementsByTagName("body")[0]; + body.appendChild(canvas); +} + +textureOut.set(new CGL.Texture(cgl)); + +function reSize() +{ + update(); +} + +let data = "data:image/svg+xml," + + "" + + "" + + "
" + + "
" + + "
" + + "
"; + +let cgl_filter = CGL.Texture.FILTER_MIPMAP; +let cgl_wrap = CGL.Texture.WRAP_REPEAT; + +function onFilterChange() +{ + if (tfilter.get() == "nearest") cgl_filter = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "linear") cgl_filter = CGL.Texture.FILTER_LINEAR; + else if (tfilter.get() == "mipmap") cgl_filter = CGL.Texture.FILTER_MIPMAP; + + reload(); +} + +function onWrapChange() +{ + if (wrap.get() == "repeat") cgl_wrap = CGL.Texture.WRAP_REPEAT; + else if (wrap.get() == "mirrored repeat") cgl_wrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + else if (wrap.get() == "clamp to edge") cgl_wrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + reload(); +} + +function reload() +{ + const loadingId = op.patch.loading.start("svg file", filename.get()); + CABLES.ajax( + op.patch.getFilePath(filename.get()), + function (err, _data, xhr) + { + data = "data:image/svg+xml," + _data; + + data = data.replace(/#/g, "%23"); + + op.patch.loading.finished(loadingId); + update(); + } + ); +} + +let startTime = 0; + +function update() +{ + const img = new Image(); + const loadingId = op.patch.loading.start("svg2texture", filename.get()); + + img.onabort = img.onerror = function (e) + { + outLoaded.set(false); + op.logError("could not load file",); + op.patch.loading.finished(loadingId); + + // op.patch.loading.finished(loadingId); + op.setUiError("error", "Could not load SVG file!"); + }; + + outLoaded.set(false); + + img.onload = function () + { + cgl.addNextFrameOnceCallback(() => + { + createCanvas(); + op.patch.loading.finished(loadingId); + canvas.width = texWidth.get(); + canvas.height = texHeight.get(); + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(img, 0, 0, canvas.width, canvas.height); + textureOut.set(new CGL.Texture.createFromImage(cgl, canvas, + { + "wrap": cgl_wrap, + "filter": cgl_filter, + "width": canvas.width, + "height": canvas.height, + "unpackAlpha": true + })); + removeCanvas(); + outLoaded.set(true); + }); + }; + + img.src = data; + startTime = performance.now(); +} + +op.onFileChanged = function (fn) +{ + if (filename.get() && filename.get().endsWith(fn)) + { + reload(); + } +}; + +filename.onChange = reload; +texWidth.onChange = texHeight.onChange = reSize; + +createCanvas(); +reSize(); + +tfilter.set("mipmap"); + + +}; + +Ops.Gl.Textures.TextureSVG_v2.prototype = new CABLES.Op(); +CABLES.OPS["e4f3d8f1-8a49-460a-896c-4d7adcda2494"]={f:Ops.Gl.Textures.TextureSVG_v2,objName:"Ops.Gl.Textures.TextureSVG_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.TextureToBase64 +// +// ************************************************************** + +Ops.Gl.Textures.TextureToBase64 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTex = op.inTexture("Texture"), + start = op.inTriggerButton("Trigger"), + jpeg = op.inBool("Use JPEG", false), + dataUrl = op.inBool("Output dataUrl", false), + outString = op.outString("Base64 string"), + outLoading = op.outBoolNum("Loading"); + +const gl = op.patch.cgl.gl; +let fb = null; +outString.ignoreValueSerialize = true; + +// Create a 2D canvas to store the result +const canvas = document.createElement("canvas"); + +jpeg.onChange = update; +dataUrl.onChange = update; +start.onTriggered = update; + +function update() +{ + op.uiAttr({ "error": null }); + if (!inTex.get() || !inTex.get().tex) return; + outLoading.set(true); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); + + const width = inTex.get().width; + const height = inTex.get().height; + + if (!fb)fb = gl.createFramebuffer(); + + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, inTex.get().tex, 0); + + const canRead = (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + if (!canRead) + { + outLoading.set(true); + op.uiAttr({ "error": "cannot read texture!" }); + return; + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + const data = new Uint8Array(width * height * 4); + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + canvas.width = width; + canvas.height = height; + const context = canvas.getContext("2d"); + + // Copy the pixels to a 2D canvas + const imageData = context.createImageData(width, height); + imageData.data.set(data); + + const data2 = imageData.data; + + // flip image + Array.from({ "length": height }, (val, i) => { return data2.slice(i * width * 4, (i + 1) * width * 4); }) + .forEach((val, i) => { return data2.set(val, (height - i - 1) * width * 4); }); + + context.putImageData(imageData, 0, 0); + let dataString = ""; + if (jpeg.get()) + { + dataString = canvas.toDataURL("image/jpeg", 1.0); + } + else + { + dataString = canvas.toDataURL(); + } + if (!dataUrl.get()) + { + dataString = dataString.split(",", 2)[1]; + } + outString.set(dataString); + outLoading.set(false); +} + +function dataURIToBlob(dataURI, callback) +{ + const binStr = atob(dataURI.split(",")[1]), + len = binStr.length, + arr = new Uint8Array(len); + for (let i = 0; i < len; i++) arr[i] = binStr.charCodeAt(i); + callback(new Blob([arr], { "type": "image/png" })); +} + + +}; + +Ops.Gl.Textures.TextureToBase64.prototype = new CABLES.Op(); +CABLES.OPS["dcc29c06-c3df-434f-9782-736548220bda"]={f:Ops.Gl.Textures.TextureToBase64,objName:"Ops.Gl.Textures.TextureToBase64"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.TextureToCoordinateGrid +// +// ************************************************************** + +Ops.Gl.Textures.TextureToCoordinateGrid = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"rgbe2fp_frag":"UNI sampler2D tex;\nIN vec2 texCoord;\nUNI float aspect;\nUNI float threshold;\n\nvoid main()\n{\n vec4 col=texture(tex,texCoord);\n vec4 outCol=vec4(111111110.0);\n\n if(col.r>threshold)\n {\n outCol=vec4(vec2((texCoord.x-0.5)*aspect,texCoord.y-0.5),0.0,1.0);\n // outCol=vec4(texCoord,0.0,1.0);\n }\n\n\n outColor = outCol;\n}",}; +const + exec = op.inTrigger("Execute"), + inTex = op.inTexture("RGBE Texture"), + inAspect = op.inFloat("Aspect", 1), + inThreshold = op.inFloatSlider("Threshold", 0.2), + next = op.outTrigger("Next"), + outFpTex = op.outTexture("HDR Texture"); + +const tc = new CGL.CopyTexture(op.patch.cgl, "rgbe2hdr", + { + "shader": attachments.rgbe2fp_frag, + "isFloatingPointTexture": true + }); + +const uni1 = new CGL.Uniform(tc.bgShader, "f", "aspect", inAspect); +const uni2 = new CGL.Uniform(tc.bgShader, "f", "threshold", inThreshold); + +exec.onTriggered = () => +{ + if (!inTex.get()) return; + + outFpTex.set(CGL.Texture.getEmptyTexture(op.patch.cgl)); + outFpTex.set(tc.copy(inTex.get())); + + next.trigger(); +}; + + +}; + +Ops.Gl.Textures.TextureToCoordinateGrid.prototype = new CABLES.Op(); +CABLES.OPS["91f30465-4a4c-4447-9b16-072252f0a977"]={f:Ops.Gl.Textures.TextureToCoordinateGrid,objName:"Ops.Gl.Textures.TextureToCoordinateGrid"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.VideoTexture_v3 +// +// ************************************************************** + +Ops.Gl.Textures.VideoTexture_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Update"), + filename = op.inUrl("file", "video"), + play = op.inValueBool("play"), + loop = op.inValueBool("loop", true), + + volume = op.inValueSlider("Volume", 1), + muted = op.inValueBool("mute", true), + + fps = op.inValueFloat("Update FPS", 30), + tfilter = op.inSwitch("Filter", ["nearest", "linear"], "linear"), + wrap = op.inValueSelect("Wrap", ["repeat", "mirrored repeat", "clamp to edge"], "clamp to edge"), + flip = op.inValueBool("flip", true), + + speed = op.inValueFloat("speed", 1), + time = op.inValueFloat("set time"), + rewind = op.inTriggerButton("Rewind"), + + inPreload = op.inValueBool("Preload", true), + inShowSusp = op.inBool("Show Interaction needed Button", true), + + outNext = op.outTrigger("Next"), + textureOut = op.outTexture("texture", null, "texture"), + outDuration = op.outNumber("duration"), + outProgress = op.outNumber("progress"), + outInteractionNeeded = op.outBoolNum("Interaction Needed"), + outTime = op.outNumber("CurrentTime"), + loading = op.outBoolNum("Loading"), + outPlaying = op.outBoolNum("Playing"), + canPlayThrough = op.outBoolNum("Can Play Through", false), + + outWidth = op.outNumber("Width"), + outHeight = op.outNumber("Height"), + outAspect = op.outNumber("Aspect Ratio"), + outHasError = op.outBoolNum("Has Error"), + outError = op.outString("Error Message"); + +op.setPortGroup("Texture", [tfilter, wrap, flip, fps]); +op.setPortGroup("Audio", [muted, volume]); +op.setPortGroup("Timing", [time, rewind, speed]); + +let videoElementPlaying = false; +let embedded = false; +let interActionNeededButton = false; +let addedListeners = false; +let cgl_filter = 0; +let cgl_wrap = 0; +let tex = null; +let timeout = null; +let firstTime = true; +let needsUpdate = true; +let lastTime = 0; + +const cgl = op.patch.cgl; +const videoElement = document.createElement("video"); +videoElement.setAttribute("playsinline", ""); +videoElement.setAttribute("webkit-playsinline", ""); +videoElement.setAttribute("autoplay", "autoplay"); + +const emptyTexture = CGL.Texture.getEmptyTexture(cgl); +op.toWorkPortsNeedToBeLinked(textureOut); +textureOut.set(tex); +textureOut.set(CGL.Texture.getEmptyTexture(cgl)); +play.onChange = updatePlayState; +filename.onChange = reload; +volume.onChange = updateVolume; +op.onMasterVolumeChanged = updateVolume; + +tfilter.onChange = wrap.onChange = () => +{ + tex = null; +}; + +op.onDelete = () => +{ + if (tex)tex.delete(); + videoElement.remove(); +}; + +inExec.onTriggered = () => +{ + if (performance.now() - lastTime > 1000 / fps.get())needsUpdate = true; + + if (needsUpdate) + { + lastTime = performance.now(); + updateTexture(); + } + + outPlaying.set(!videoElement.paused); + + if (interActionNeededButton && !videoElement.paused && play.get()) + { + // remove button after player says no but plays anyhow after some time... + op.log("weirdness..."); + interActionNeededButton = false; + CABLES.interActionNeededButton.remove("videoplayer"); + } + outInteractionNeeded.set(interActionNeededButton); + + outNext.trigger(); +}; + +function reInitTexture() +{ + if (tex)tex.delete(); + + if (tfilter.get() == "nearest") cgl_filter = CGL.Texture.FILTER_NEAREST; + if (tfilter.get() == "linear") cgl_filter = CGL.Texture.FILTER_LINEAR; + + if (wrap.get() == "repeat") cgl_wrap = CGL.Texture.WRAP_REPEAT; + if (wrap.get() == "mirrored repeat") cgl_wrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + if (wrap.get() == "clamp to edge") cgl_wrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + tex = new CGL.Texture(cgl, + { + "wrap": cgl_wrap, + "filter": cgl_filter + }); +} + +rewind.onTriggered = function () +{ + videoElement.currentTime = 0; + textureOut.set(emptyTexture); + needsUpdate = true; +}; + +time.onChange = function () +{ + videoElement.currentTime = time.get() || 0; + needsUpdate = true; +}; + +fps.onChange = function () +{ + needsUpdate = true; +}; + +function doPlay() +{ + videoElement.playbackRate = speed.get(); +} + +function updatePlayState() +{ + if (!embedded) + { + embedVideo(true); + } + + if (play.get()) + { + videoElement.currentTime = time.get() || 0; + + const promise = videoElement.play(); + + if (promise) + promise.then(function () + { + doPlay(); + }).catch(function (error) + { + op.warn("exc", error); + op.log(error); + op.log(videoElement); + + if (videoElement.paused && inShowSusp.get()) + { + interActionNeededButton = true; + CABLES.interActionNeededButton.add(op.patch, "videoplayer", () => + { + interActionNeededButton = false; + videoElement.play(); + doPlay(); + CABLES.interActionNeededButton.remove("videoplayer"); + }); + } + // Automatic playback failed. + // Show a UI element to let the user manually start playback. + }); + } + else videoElement.pause(); +} + +speed.onChange = function () +{ + videoElement.playbackRate = speed.get(); +}; + +loop.onChange = function () +{ + videoElement.loop = loop.get(); +}; + +muted.onChange = function () +{ + videoElement.muted = muted.get(); +}; + +function updateTexture() +{ + const force = needsUpdate; + + if (!filename.get()) + { + textureOut.set(emptyTexture); + return; + } + + if (!videoElementPlaying) return; + + if (!tex)reInitTexture(); + if (tex.width != videoElement.videoWidth || tex.height != videoElement.videoHeight) + { + op.log("video size", videoElement.videoWidth, videoElement.videoHeight); + tex.setSize(videoElement.videoWidth, videoElement.videoHeight); + } + + // tex.height = videoElement.videoHeight; + // tex.width = videoElement.videoWidth; + + outWidth.set(tex.width); + outHeight.set(tex.height); + outAspect.set(tex.width / tex.height); + + if (!canPlayThrough.get()) return; + if (!videoElementPlaying) return; + if (!videoElement) return; + if (videoElement.videoHeight <= 0) + { + op.setUiError("videosize", "video width is 0!"); + op.log(videoElement); + return; + } + if (videoElement.videoWidth <= 0) + { + op.setUiError("videosize", "video height is 0!"); + op.log(videoElement); + return; + } + + const perc = (videoElement.currentTime) / videoElement.duration; + if (!isNaN(perc)) outProgress.set(perc); + + outTime.set(videoElement.currentTime); + + cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, tex.tex); + + if (firstTime) + { + cgl.gl.pixelStorei(cgl.gl.UNPACK_FLIP_Y_WEBGL, flip.get()); + cgl.gl.texImage2D(cgl.gl.TEXTURE_2D, 0, cgl.gl.RGBA, cgl.gl.RGBA, cgl.gl.UNSIGNED_BYTE, videoElement); + tex._setFilter(); + } + else + { + cgl.gl.pixelStorei(cgl.gl.UNPACK_FLIP_Y_WEBGL, flip.get()); + cgl.gl.texSubImage2D(cgl.gl.TEXTURE_2D, 0, 0, 0, cgl.gl.RGBA, cgl.gl.UNSIGNED_BYTE, videoElement); + } + + if (flip.get()) cgl.gl.pixelStorei(cgl.gl.UNPACK_FLIP_Y_WEBGL, false); + + firstTime = false; + + textureOut.set(tex); + needsUpdate = false; + + op.patch.cgl.profileData.profileVideosPlaying++; + + if (videoElement.readyState == 4) loading.set(false); + else loading.set(false); +} + +function initVideo() +{ + videoElement.controls = false; + videoElement.muted = muted.get(); + videoElement.loop = loop.get(); + + needsUpdate = true; + canPlayThrough.set(true); +} + +function updateVolume() +{ + videoElement.volume = Math.min(1, Math.max(0, (volume.get() || 0) * op.patch.config.masterVolume)); +} + +function loadedMetaData() +{ + outDuration.set(videoElement.duration); + updatePlayState(); +} + +function embedVideo(force) +{ + outHasError.set(false); + outError.set(""); + canPlayThrough.set(false); + if (filename.get() && String(filename.get()).length > 1) firstTime = true; + + if (!filename.get()) + { + outError.set(true); + } + + if (inPreload.get() || force) + { + clearTimeout(timeout); + loading.set(true); + videoElement.preload = "true"; + + let url = op.patch.getFilePath(filename.get()); + if (String(filename.get()).indexOf("data:") == 0) url = filename.get(); + if (!url) return; + + op.setUiError("onerror", null); + videoElement.style.display = "none"; + videoElement.setAttribute("src", url); + videoElement.setAttribute("crossOrigin", "anonymous"); + videoElement.playbackRate = speed.get(); + + if (!addedListeners) + { + addedListeners = true; + videoElement.addEventListener("canplaythrough", initVideo, true); + videoElement.addEventListener("loadedmetadata", loadedMetaData); + videoElement.addEventListener("playing", function () { videoElementPlaying = true; }, true); + videoElement.onerror = function () + { + outHasError.set(true); + if (videoElement) + { + outError.set("Error " + videoElement.error.code + "/" + videoElement.error.message); + op.setUiError("onerror", "Could not load video / " + videoElement.error.message, 2); + } + }; + } + embedded = true; + } +} + +function loadVideo() +{ + setTimeout(embedVideo, 100); +} + +function reload() +{ + if (!filename.get()) return; + loadVideo(); +} + + +}; + +Ops.Gl.Textures.VideoTexture_v3.prototype = new CABLES.Op(); +CABLES.OPS["9d66516f-d234-4114-b1d3-67b8e60f5dc6"]={f:Ops.Gl.Textures.VideoTexture_v3,objName:"Ops.Gl.Textures.VideoTexture_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.Textures.WebcamTexture_v3 +// +// ************************************************************** + +Ops.Gl.Textures.WebcamTexture_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"texcopy_frag":"UNI sampler2D tex;\nIN vec2 texCoord;\n\n\nvoid main()\n{\n vec2 tc=vec2(texCoord.x,texCoord.y);\n\n #ifdef FLIPX\n tc.x=1.0-texCoord.x;\n #endif\n #ifdef FLIPY\n tc.y=1.0-texCoord.y;\n #endif\n outColor=texture(tex,tc);\n}",}; +const + inTrigger = op.inTrigger("Render"), + inActive = op.inBool("Active", true), + inGenTex = op.inValueBool("Generate Texture", true), + inInputDevices = op.inDropDown("Webcam Input", ["Default"], "Default"), + inWidth = op.inValueInt("Requested Width", 1280), + inHeight = op.inValueInt("Requested Height", 720), + + flipX = op.inValueBool("Flip X", false), + flipY = op.inValueBool("Flip Y", false), + + inAsDOM = op.inValueBool("Show HTML Element", false), + inCss = op.inStringEditor("CSS", "z-index:99999;\nposition:absolute;\n", "inline-css"), + htmlFlipX = op.inValueBool("Element Flip X", false), + htmlFlipY = op.inValueBool("Element Flip Y", false), + + next = op.outTrigger("Next"), + textureOut = op.outTexture("Texture"), + + outRatio = op.outNumber("Ratio"), + available = op.outBoolNum("Available"), + outWidth = op.outNumber("Size Width"), + outHeight = op.outNumber("Size Height"), + outError = op.outString("Error"), + outElement = op.outObject("HTML Element", null, "element"), + outDevices = op.outArray("Available devices"), + outSelectedDevice = op.outString("Active device"), + outUpdate = op.outTrigger("Texture updated"); + +op.setPortGroup("Camera", [inInputDevices, inWidth, inHeight]); +op.setPortGroup("Texture", [flipX, flipY]); +op.setPortGroup("Video Element", [inAsDOM, inCss, htmlFlipX, htmlFlipY]); + +let tries = 0; +const cgl = op.patch.cgl; +const emptyTexture = CGL.Texture.getEmptyTexture(cgl); +const videoElement = document.createElement("video"); +const eleId = "webcam" + op.id; + +videoElement.setAttribute("id", eleId); +videoElement.setAttribute("autoplay", ""); +videoElement.setAttribute("muted", ""); +videoElement.setAttribute("playsinline", ""); +videoElement.setAttribute("style", inCss.get()); +op.patch.cgl.canvas.parentElement.appendChild(videoElement); + +let tex = null; +let initingDevices = false; +let restarting = false; +let started = false; +let camsLoaded = false; +let loadingId = null; +let currentStream = null; +let camInputDevices = null; +let active = false; +let alreadyRetried = false; +let constraints = null; + +textureOut.set(emptyTexture); + +flipX.onChange = +flipY.onChange = initCopyShader; + +inInputDevices.onChange = + inWidth.onChange = + inHeight.onChange = restartWebcam; +htmlFlipX.onChange = htmlFlipY.onChange = flipVideoElement; +op.onDelete = removeElement; +inAsDOM.onChange = inCss.onChange = updateStyle; + +initTexture(); +updateStyle(); + +let tc = null; + +op.on("loadedValueSet", () => +{ + if (inActive.get()) initDevices(); +}); + +inActive.onChange = () => +{ + if (inActive.get()) initDevices(); +}; + +function initCopyShader() +{ + if (!tc)tc = new CGL.CopyTexture(cgl, "webcamFlippedTexture", { "shader": attachments.texcopy_frag }); + tc.bgShader.toggleDefine("FLIPX", flipX.get()); + tc.bgShader.toggleDefine("FLIPY", !flipY.get()); +} + +function initTexture() +{ + if (tex)tex.delete(); + tex = new CGL.Texture(cgl, { "name": "webcam" }); + if (videoElement) tex.setSize(videoElement.videoWidth, videoElement.videoHeight); +} + +function removeElement() +{ + if (videoElement) videoElement.remove(); +} + +function updateStyle() +{ + if (!inAsDOM.get()) videoElement.setAttribute("style", "display:none;"); + else videoElement.setAttribute("style", inCss.get()); + + inCss.setUiAttribs({ "greyout": !inAsDOM.get() }); + htmlFlipX.setUiAttribs({ "greyout": !inAsDOM.get() }); + htmlFlipY.setUiAttribs({ "greyout": !inAsDOM.get() }); +} + +function flipVideoElement() +{ + if (htmlFlipX.get() && !htmlFlipY.get()) videoElement.style.transform = "scaleX(-1)"; + else if (!htmlFlipX.get() && htmlFlipY.get()) videoElement.style.transform = "scaleY(-1)"; + else if (htmlFlipX.get() && htmlFlipY.get()) videoElement.style.transform = "scale(-1, -1)"; + else videoElement.style.transform = "unset"; +} + +function playCam(shouldPlay) +{ + if (started && camsLoaded) + { + if (shouldPlay) + { + active = true; + videoElement.play(); + } + else + { + active = false; + videoElement.pause(); + } + } +} + +inGenTex.onChange = () => +{ + playCam(inGenTex.get()); +}; + +function updateTexture() +{ + cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, tex.tex); + + cgl.gl.texImage2D(cgl.gl.TEXTURE_2D, 0, cgl.gl.RGBA, cgl.gl.RGBA, cgl.gl.UNSIGNED_BYTE, videoElement); + cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, null); + textureOut.set(emptyTexture); + + if (!tc)initCopyShader(); + if (tc)textureOut.set(tc.copy(tex)); +} + +function stopStream() +{ + if (!currentStream) return; + + playCam(false); + available.set(false); + + currentStream.getTracks().forEach((track) => + { + track.stop(); + }); + currentStream = null; +} + +function camInitComplete(stream) +{ + currentStream = stream; + videoElement.srcObject = stream; + videoElement.onloadedmetadata = (e) => + { + outSelectedDevice.set(stream.getTracks()[0].label); + if (inInputDevices.get() != "Default" && stream.getTracks()[0].label != inInputDevices.get() && tries < 3) + { + tries++; + return restartWebcam(); + } + + const settings = stream.getTracks()[0].getSettings(); + restarting = false; + + const w = settings.width || inWidth.get(); + const h = settings.height || inHeight.get(); + + outHeight.set(h); + outWidth.set(w); + outRatio.set(settings.aspectRatio || w / h); + outError.set(""); + + videoElement.setAttribute("width", settings.width); + videoElement.setAttribute("height", settings.height); + + outElement.set(videoElement); + + tex.setSize(w, h); + + available.set(true); + playCam(inGenTex.get()); + }; +} + +function isCorrectSize() +{ + const constraints = getCamConstraints(); + const check = constraints.video.width == videoElement.videoWidth && constraints.video.height == videoElement.videoHeight; + return check; +} + +function getCamConstraints() +{ + let constr = { "audio": false, "video": {} }; + + if (camsLoaded) + { + let deviceLabel = inInputDevices.get(); + let deviceInfo = null; + + if (!deviceLabel || deviceLabel === "Default" || deviceLabel === "...") + { + deviceInfo = Object.values(camInputDevices)[0]; + } + else + { + deviceInfo = camInputDevices.filter((d) => { return d.label === deviceLabel; }); + if (deviceInfo) + { + deviceInfo = deviceInfo[0]; + } + else + { // otherwise get by number + deviceInfo = Object.values(camInputDevices)[deviceLabel]; + } + + if (!deviceInfo) + { + deviceInfo = Object.values(camInputDevices)[0]; + } + } + constr.video = { "deviceId": { "exact": deviceInfo.deviceId } }; + } + + // constr.video.facingMode = { "exact": inFacing.get() }; + + const w = inWidth.get(); + const h = inHeight.get(); + let width = { "min": 640 }; + let height = { "min": 480 }; + + if (w) + width.ideal = w; + + if (h) + height.ideal = h; + + constr.video.width = width; + constr.video.height = height; + + return constr; +} + +function restartWebcam() +{ + if (!inActive.get()) return; + stopStream(); + restarting = true; + + const constr = getCamConstraints(); + + navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia; + + if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) + { + navigator.mediaDevices.getUserMedia(constr) + .then(camInitComplete) + .catch((error) => + { + restarting = false; + op.logError(error.name + ": " + error.message, error); + outError.set(error.name + ": " + error.message); + }); + } + else if (navigator.getUserMedia) + { + restarting = false; + navigator.getUserMedia(constr, camInitComplete, () => { return available.set(false); }); + } +} + +function initDevices() +{ + if (!inActive.get()) return; + initingDevices = true; + loadingId = cgl.patch.loading.start("Webcam inputs", ""); + const constraints = getCamConstraints(); + + navigator.mediaDevices.getUserMedia(constraints) + .then((res) => { return navigator.mediaDevices.enumerateDevices(); }) + .then((devices) => + { + camInputDevices = devices + .filter((device) => { return device.kind === "videoinput"; }); + + initingDevices = false; + inInputDevices.uiAttribs.values = camInputDevices.map((d, idx) => { return d.label || idx; }); + inInputDevices.uiAttribs.values.unshift("Default"); + outDevices.set(inInputDevices.uiAttribs.values); + cgl.patch.loading.finished(loadingId); + + camsLoaded = true; + + restartWebcam(); + started = true; + }).catch((e) => + { + initingDevices = false; + op.error("error", e); + outError.set(e.name + ": " + e.message); + cgl.patch.loading.finished(loadingId); + camsLoaded = false; + }); +} + +inTrigger.onTriggered = () => +{ + if (!initingDevices && inActive.get()) + { + if (started && camsLoaded && active) + { + updateTexture(); + outUpdate.trigger(); + } + + if (!started && camsLoaded) + { + restartWebcam(); + } + } + + next.trigger(); +}; + + +}; + +Ops.Gl.Textures.WebcamTexture_v3.prototype = new CABLES.Op(); +CABLES.OPS["71c0468d-e942-4574-a91d-b3d7271922d0"]={f:Ops.Gl.Textures.WebcamTexture_v3,objName:"Ops.Gl.Textures.WebcamTexture_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.TriggerOnCanvasResize +// +// ************************************************************** + +Ops.Gl.TriggerOnCanvasResize = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const onResize = op.outTrigger("Resized"); + +let listener = op.patch.cgl.on("resize", resize); + +function resize() +{ + onResize.trigger(); +} + +op.onDelete = () => +{ + op.patch.cgl.off(listener); +}; + + +}; + +Ops.Gl.TriggerOnCanvasResize.prototype = new CABLES.Op(); +CABLES.OPS["856de8cf-b8d1-4668-b8ff-80c68bc73ddd"]={f:Ops.Gl.TriggerOnCanvasResize,objName:"Ops.Gl.TriggerOnCanvasResize"}; + + + + +// ************************************************************** +// +// Ops.Gl.ValidTexture +// +// ************************************************************** + +Ops.Gl.ValidTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; + const + inTex=op.inTexture("Texture"), + inWhich=op.inSwitch("Default",['Empty','Stripes'],'Empty'), + outTex=op.outTexture("Result"); + + +let tex=CGL.Texture.getEmptyTexture(op.patch.cgl); + +inWhich.onChange=function() +{ + if(inWhich.get()=="Empty")tex=CGL.Texture.getEmptyTexture(op.patch.cgl); + else tex=CGL.Texture.getTempTexture(op.patch.cgl); +}; + +inTex.onChange=function() +{ + let t=inTex.get(); + + if(!t) t=tex; + + outTex.set(t); +}; + +}; + +Ops.Gl.ValidTexture.prototype = new CABLES.Op(); +CABLES.OPS["51c24850-aa8b-41e4-936e-68ba718b5e39"]={f:Ops.Gl.ValidTexture,objName:"Ops.Gl.ValidTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.ViewPortSize +// +// ************************************************************** + +Ops.Gl.ViewPortSize = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Exec"), + next = op.outTrigger("Next"), + outX = op.outNumber("X"), + outY = op.outNumber("Y"), + outW = op.outNumber("Width"), + outH = op.outNumber("Height"); + +exec.onTriggered = function () +{ + const vp = op.patch.cgl.getViewPort(); + + outX.set(vp[0]); + outY.set(vp[1]); + outW.set(vp[2]); + outH.set(vp[3]); + + next.trigger(); +}; + + +}; + +Ops.Gl.ViewPortSize.prototype = new CABLES.Op(); +CABLES.OPS["7cb99d8f-d7ef-478e-902b-54e054e387a0"]={f:Ops.Gl.ViewPortSize,objName:"Ops.Gl.ViewPortSize"}; + + + + +// ************************************************************** +// +// Ops.Gl.Viewport2 +// +// ************************************************************** + +Ops.Gl.Viewport2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + ratio = op.inDropDown("ratio", [0.5, 0.5625, 0.75, 1, 1.25, 1.3333333333, 1.777777777778, 2.33333333333333, 3, 4]), + trigger = op.outTrigger("trigger"); + +ratio.set(1.777777777778); + +const posX = op.inValueSelect("Pos X", ["Left", "Right", "Center"], "Center"); + +const cgl = op.patch.cgl; + +let w = 1000, h = 1000; + +function resize() +{ + let _w = cgl.canvasHeight * ratio.get(); + let _h = cgl.canvasHeight; + let _x = 0; + let _y = 0; + + if (_w > cgl.canvasWidth) + { + _w = cgl.canvasWidth; + _h = cgl.canvasWidth / ratio.get(); + } + + if (_w < cgl.canvasWidth) _x = (cgl.canvasWidth - _w) / 2; + if (_h < cgl.canvasHeight) _y = (cgl.canvasHeight - _h) / 2; + + if (_w != w || _h != h) + { + w = _w; + h = _h; + + const vp = cgl.getViewPort(); + + // cgl.setViewPort(0,vp[2]-h,w,h); + + for (let i = 0; i < op.patch.ops.length; i++) + { + if (op.patch.ops[i].onResize)op.patch.ops[i].onResize(); + } + } +} + +op.onDelete = function () +{ + cgl.resetViewPort(); +}; + +const prevViewPort = []; + +render.onTriggered = function () +{ + resize(); + + w = Math.round(w); + h = Math.round(h); + + cgl.gl.enable(cgl.gl.SCISSOR_TEST); + const vp = cgl.getViewPort(); + prevViewPort[0] = vp[0]; + prevViewPort[1] = vp[1]; + prevViewPort[2] = vp[2]; + prevViewPort[3] = vp[3]; + + vp[2] = cgl.canvasWidth; + vp[3] = cgl.canvasHeight; + vp[0] = 0; + vp[1] = 0; + + let x = 0; + if (posX.get() == "Right") x = vp[2] - w; + if (posX.get() == "Center") x = (vp[2] - w) / 2; + + x = Math.round(x); + + cgl.gl.scissor(x, vp[3] - h, w, h); + cgl.setViewPort(x, vp[3] - h, w, h); + + mat4.perspective(cgl.pMatrix, 45, ratio.get(), 0.1, 1100.0); + + trigger.trigger(); + cgl.gl.disable(cgl.gl.SCISSOR_TEST); + cgl.setViewPort(prevViewPort[0], prevViewPort[1], prevViewPort[2], prevViewPort[3]); +}; + + +}; + +Ops.Gl.Viewport2.prototype = new CABLES.Op(); +CABLES.OPS["1444ab6f-a4da-462c-8abe-a1deef2084da"]={f:Ops.Gl.Viewport2,objName:"Ops.Gl.Viewport2"}; + + + + +// ************************************************************** +// +// Ops.Gl.WebGlVersion +// +// ************************************************************** + +Ops.Gl.WebGlVersion = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const ver = op.outNumber("Major Version", op.patch.cgl.glVersion); + +op.onLoaded = function () +{ + ver.set(op.patch.cgl.glVersion); +}; + + +}; + +Ops.Gl.WebGlVersion.prototype = new CABLES.Op(); +CABLES.OPS["d6554d6c-0742-4559-b0a4-29ad0ae1e25b"]={f:Ops.Gl.WebGlVersion,objName:"Ops.Gl.WebGlVersion"}; + + + + +// ************************************************************** +// +// Ops.Graphics.Geometry.ObjGeometry +// +// ************************************************************** + +Ops.Graphics.Geometry.ObjGeometry = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// todo: support quads +const + inStr = op.inString("Obj", ""), + outGeom = op.outObject("Geometry", null, "geometry"), + outStatus = op.outString("Status"); + +inStr.onChange = () => { parse(inStr.get()); }; + +function obj(name) +{ + const a = { + "prim": 0, + "name": name, + "verts": [], + "vertNorms": [], + "texCoords": [], + "indexVerts": [], + "indexNorms": [], + "indexTexcoords": [] + }; + + return a; +} + +function parseTri(parts, o) +{ + for (let j = 0; j < parts.length; j++) + { + const faceParts = parts[j].split("/"); + + if (faceParts.length == 3) + { + o.indexVerts.push(parseInt(faceParts[0]) - 1); + if (faceParts[1])o.indexTexcoords.push(parseInt(faceParts[1]) - 1); + o.indexNorms.push(parseInt(faceParts[2]) - 1); + } + else if (faceParts.length == 1) + { + o.indexVerts.push(parseInt(faceParts[0]) - 1); + } + else if (faceParts.length == 2) + { + o.indexVerts.push(parseInt(faceParts[0]) - 1); + o.indexTexcoords.push(parseInt(faceParts[2]) - 1); + } + else op.warn("unknown face structure", faceParts); + } +} + +function parse(str) +{ + if (!str) return outGeom.set(null); + + let objects = []; + let strStatus = ""; + const lines = str.split("\n"); + + { + let o = obj("unknown"); + + for (let i = 0; i < lines.length; i++) + { + lines[i] = lines[i].replaceAll(" ", " "); + lines[i] = lines[i].replaceAll(" \r", ""); + lines[i] = lines[i].replaceAll(" \n", "\n"); + + if (lines[i].length < 3 || lines[i].charAt(0) == "#") continue; + + // vertices + if (lines[i].charAt(0) == "o" && lines[i].charAt(1) == " ") + { + const parts = lines[i].split(" "); + o.name = obj(parts[1] || "unknown"); + continue; + } + + if (lines[i].charAt(0) == "v") + { + if (o.indexVerts.length > 0) + { + // new object... + if (o.indexVerts.length > 0) objects.push(o); + o = obj("unknown"); + } + + // vertices + if (lines[i].charAt(1) == " ") + { + const parts = lines[i].split(" "); + o.verts.push(parseFloat(parts[1]), parseFloat(parts[2]), parseFloat(parts[3])); + continue; + } + + // texcoords + if (lines[i].charAt(1) == "t" && lines[i].charAt(2) == " ") + { + const parts = lines[i].split(" "); + o.texCoords.push(parseFloat(parts[1]), parseFloat(parts[2]), parseFloat(parts[3])); + continue; + } + + // normals + if (lines[i].charAt(1) == "n" && lines[i].charAt(2) == " ") + { + const parts = lines[i].split(" "); + o.vertNorms.push(parseFloat(parts[1]), parseFloat(parts[2]), parseFloat(parts[3])); + continue; + } + } + + // faces + if (lines[i].charAt(0) == "f" && lines[i].charAt(1) == " ") + { + const parts = lines[i].split(" "); + parts.shift(); + while (parts[parts.length - 1] == "") + { + parts.pop(); + } + + if (o.prim == 0) o.prim = parts.length; + + if (o.prim == 3 && parts.length == 3) // tris + { + parseTri(parts, o); + } + else if (o.prim == 4 && parts.length == 4) // quads + { + parseTri([parts[0], parts[1], parts[2]], o); + parseTri([parts[0], parts[2], parts[3]], o); + } + continue; + } + } + objects.push(o); + } + + op.log("objects", objects); + + let finalgeom = new CGL.Geometry("objfile"); + for (let io = 0; io < objects.length; io++) + { + const geom = new CGL.Geometry("objfile"); + geom.clear(); + + let o = objects[io]; + op.log(o); + + if (o.indexVerts.length > 0) + { + let gVerts = []; + let gNorms = []; + let gTexCoords = []; + let isIndexed = true; + + for (let i = 0; i < o.indexVerts.length; i++) + { + if (isIndexed) + { + if (!(o.indexVerts[i] == o.indexNorms[i] && o.indexNorms[i] == o.indexTexcoords[i])) + { + op.log("false"); + isIndexed = false; + break; + } + } + } + + op.log("isIndexed", isIndexed); + if (isIndexed) + { + geom.verticesIndices = o.indexVerts; + gNorms = o.vertNorms; + + gTexCoords = []; + for (let i = 0; i < o.texCoords.length; i += 3) + { + gTexCoords.push(o.texCoords[i + 0], o.texCoords[i + 1]); + } + gVerts = o.verts; + } + else + for (let i = 0; i < o.indexVerts.length; i++) + { + for (let j = 0; j < 3; j++) + { + gVerts.push(o.verts[o.indexVerts[i] * 3 + j]); + if (o.indexNorms.length > 0)gNorms.push(o.vertNorms[o.indexNorms[i] * 3 + j]); + if (o.indexTexcoords.length > 0 && j < 2)gTexCoords.push(o.texCoords[o.indexTexcoords[i] * 3 + j]); + } + } + + geom.vertices = gVerts; + geom.vertexNormals = gNorms; + geom.texCoords = gTexCoords; + + if (geom.vertexNormals.length == 0) + { + geom.calculateNormals(); + } + } + finalgeom.merge(geom); + // finalgeom = geom; + } + + finalgeom.calcTangentsBitangents(); + + outGeom.set(null); + outGeom.set(finalgeom); + + outStatus.set(strStatus); +} + + +}; + +Ops.Graphics.Geometry.ObjGeometry.prototype = new CABLES.Op(); +CABLES.OPS["8cebb27b-2a6e-4580-a543-b36a91f14879"]={f:Ops.Graphics.Geometry.ObjGeometry,objName:"Ops.Graphics.Geometry.ObjGeometry"}; + + + + +// ************************************************************** +// +// Ops.Html.AppendChild_v2 +// +// ************************************************************** + +Ops.Html.AppendChild_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// constants +let CANVAS_ELEMENT = op.patch.cgl.canvas.parentElement; + +// variables +let lastParent = null; +let lastChild = null; + +// inputs +let parentPort = op.inObject("Parent", null, "element"); +let childPort = op.inObject("Child", null, "element"); + +// outputs +let parentOutPort = op.outObject("Parent Out", null, "element"); +let childOutPort = op.outObject("Child Out", null, "element"); + +// change listeners +parentPort.onChange = update; +childPort.onChange = update; + +// functions + +function update() +{ + let parent = parentPort.get(); + let child = childPort.get(); + if (parent !== lastParent) + { + if (parent) + { + handleParentConnect(parent, child); + } + else + { + handleParentDisconnect(parent, child); + } + lastParent = parent; + } + if (child !== lastChild) + { + if (child) + { + handleChildConnect(parent, child); + } + else + { + handleChildDisconnect(parent, child); + } + lastChild = child; + } + parentOutPort.set(parent); + childOutPort.set(child); +} + +function handleParentConnect(parent, child) +{ + if (child) + { + parent.appendChild(child); + } +} + +function handleParentDisconnect(parent, child) +{ + if (child) + { + CANVAS_ELEMENT.appendChild(child); // if there is no parent, append to patch + } +} + +function handleChildConnect(parent, child) +{ + if (parent) + { + parent.appendChild(child); + } +} + +function handleChildDisconnect(parent, child) +{ + if (lastChild) + { + CANVAS_ELEMENT.appendChild(lastChild); + } +} + + +}; + +Ops.Html.AppendChild_v2.prototype = new CABLES.Op(); +CABLES.OPS["e15cfbc7-d2fa-4348-8964-66d02aec77aa"]={f:Ops.Html.AppendChild_v2,objName:"Ops.Html.AppendChild_v2"}; + + + + +// ************************************************************** +// +// Ops.Html.AudioMediaElement +// +// ************************************************************** + +Ops.Html.AudioMediaElement = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + fileName = op.inUrl("file", "audio"), + inPlay = op.inValueBool("Play"), + volume = op.inValueSlider("Volume"), + + doLoop = op.inValueBool("Loop"), + outPlaying = op.outNumber("Playing"), + outEle = op.outObject("Element", null, "element"), + outEnded = op.outTrigger("Has Ended"); + +volume.set(1.0); +let audio = null; +let playing = false; +outPlaying.set(false); +volume.onChange = updateVolume; + +function play() +{ + if (audio) + { + playing = true; + audio.play(); + } +} + +inPlay.onChange = function () +{ + if (inPlay.get()) + { + play(); + } + else + { + playing = false; + audio.pause(); + } + outPlaying.set(playing); +}; + +this.onDelete = function () +{ + if (audio) audio.pause(); +}; + +doLoop.onChange = function () +{ + if (audio) audio.loop = doLoop.get(); +}; + +function playPause() +{ + if (!audio) return; + + if (op.patch.timer.isPlaying()) audio.play(); + else audio.pause(); +} + +function updateVolume() +{ + if (audio)audio.volume = volume.get() * op.patch.config.masterVolume; +} + +op.onMasterVolumeChanged = updateVolume; + +fileName.onChange = function () +{ + if (!fileName.get()) return; + + let loadingId = op.patch.loading.start("audioplayer", fileName.get()); + + if (audio) + { + audio.pause(); + outPlaying.set(false); + } + audio = new Audio(); + audio.crossOrigin = "anonymous"; + audio.src = op.patch.getFilePath(fileName.get()); + audio.loop = doLoop.get(); + audio.controls = "true"; + audio.crossOrigin = "anonymous"; + + outEle.set(audio); + + var canplaythrough = function () + { + if (inPlay.get()) play(); + op.patch.loading.finished(loadingId); + audio.removeEventListener("canplaythrough", canplaythrough, false); + }; + + audio.addEventListener("canplaythrough", canplaythrough, false); + + audio.addEventListener("ended", function () + { + outPlaying.set(false); + playing = false; + outEnded.trigger(); + if (doLoop.get()) play(); + }, false); +}; + + +}; + +Ops.Html.AudioMediaElement.prototype = new CABLES.Op(); +CABLES.OPS["82c14cd9-e2e7-4944-a04e-cca1bf3ed63e"]={f:Ops.Html.AudioMediaElement,objName:"Ops.Html.AudioMediaElement"}; + + + + +// ************************************************************** +// +// Ops.Html.BackgroundImage_v2 +// +// ************************************************************** + +Ops.Html.BackgroundImage_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inEle = op.inObject("Element"), + active = op.inValueBool("active", true), + filename = op.inUrl("image file"), + inSize = op.inValueSelect("Size", ["auto", "length", "cover", "contain", "initial", "inherit", "75%", "50%", "40%", "30%", "25%", "20%", "10%"], "cover"), + inRepeat = op.inValueSelect("Repeat", ["no-repeat", "repeat", "repeat-x", "repeat-y"], "no-repeat"), + inPosition = op.inValueSelect("Position", ["left top", "left center", "left bottom", "right top", "right center", "right bottom", "center top", "center center", "center bottom"], "center center"), + outEle = op.outObject("HTML Element"); + +op.onLoadedValueSet = +op.onLoaded = +inPosition.onChange = +inSize.onChange = +inEle.onChange = +inRepeat.onChange = +active.onChange = +filename.onChange = update; + +let ele = null; +let cacheBust = null; + +op.onFileChanged = function (fn) +{ + if (filename.get() && filename.get().indexOf(fn) > -1) + { + if (ele)ele.style["background-image"] = "none"; + cacheBust = CABLES.uuid(); + update(); + } +}; + +function remove() +{ + if (ele) + { + ele.style["background-image"] = "none"; + ele.style["background-size"] = "initial"; + ele.style["background-position"] = "initial"; + ele.style["background-repeat"] = "initial"; + } +} + +function update() +{ + if (!inEle.get()) + { + remove(); + return; + } + + op.setUiAttrib({ "extendTitle": CABLES.basename(filename.get()) }); + + ele = inEle.get(); + + if (ele && ele.style && filename.get()) + { + if (!active.get()) + { + ele.style["background-image"] = "none"; + } + else + { + let cb = ""; + if (cacheBust)cb = "?cb=" + cacheBust; + + ele.style["background-image"] = "url(" + op.patch.getFilePath(String(filename.get())) + cb + ")"; + ele.style["background-size"] = inSize.get(); + ele.style["background-position"] = inPosition.get(); + ele.style["background-repeat"] = inRepeat.get(); + } + } + // else + // { + // // really needed ? + // setTimeout(update,100); + // } + + outEle.set(inEle.get()); +} + + +}; + +Ops.Html.BackgroundImage_v2.prototype = new CABLES.Op(); +CABLES.OPS["081c4328-984d-4acd-8758-5d1379cc3a30"]={f:Ops.Html.BackgroundImage_v2,objName:"Ops.Html.BackgroundImage_v2"}; + + + + +// ************************************************************** +// +// Ops.Html.BrowserSpecificFile_v2 +// +// ************************************************************** + +Ops.Html.BrowserSpecificFile_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; + +// input ports +const chromeFilePort = op.inUrl("Chrome File"); +const firefoxFilePort = op.inUrl("Firefox File"); +const safariFilePort = op.inUrl("Safari File"); +const ieFilePort = op.inUrl("IE <= 11 File"); +const edgeFilePort = op.inUrl("Edge File"); +const operaFilePort = op.inUrl("Opera File"); +const defaultFilePort = op.inUrl("Default File"); + +// output port +const outFile = op.outString("Browser Specific File"); +const detectedBrowserPort = op.outString("Detected Browser"); + +// change listeners +chromeFilePort.onChange = checkBrowserAndSetOutput; +firefoxFilePort.onChange = checkBrowserAndSetOutput; +safariFilePort.onChange = checkBrowserAndSetOutput; +ieFilePort.onChange = checkBrowserAndSetOutput; +edgeFilePort.onChange = checkBrowserAndSetOutput; +operaFilePort.onChange = checkBrowserAndSetOutput; +defaultFilePort.onChange = checkBrowserAndSetOutput; + +const pf = platform; + +// functions +const isOpera = pf.name === "Opera" || pf.name === "Opera Mobile"; +const isSafari = pf.name === "Safari" || pf.name === "Firefox for iOS"; +const isIE = pf.name === "IE" || pf.name === "IE Mobile"; +const isEdge = pf.name === "Microsoft Edge"; +const isChrome = pf.name === "Chrome" || pf.name === "Chrome Mobile"; +const isFirefox = pf.name === "Firefox" || pf.name === "Firefox Mobile"; + + +checkBrowserAndSetOutput(); + +function checkBrowserAndSetOutput() { + if(isOpera) { + outFile.set(operaFilePort.get() || defaultFilePort.get()); + } else if(isFirefox) { + detectedBrowserPort.set("Firefox"); + outFile.set(firefoxFilePort.get() || defaultFilePort.get()); + } else if(isSafari) { + detectedBrowserPort.set("Safari"); + outFile.set(safariFilePort.get() || defaultFilePort.get()); + } else if(isIE) { + detectedBrowserPort.set("IE"); + outFile.set(ieFilePort.get() || defaultFilePort.get()); + } else if(isEdge) { + detectedBrowserPort.set("Edge"); + outFile.set(edgeFilePort.get() || defaultFilePort.get()); + } else if(isChrome) { + detectedBrowserPort.set("Chrome"); + outFile.set(chromeFilePort.get() || defaultFilePort.get()); + } else { + detectedBrowserPort.set(pf.name); + outFile.set(defaultFilePort.get()); + } + detectedBrowserPort.set(pf.name); +} + + +}; + +Ops.Html.BrowserSpecificFile_v2.prototype = new CABLES.Op(); +CABLES.OPS["d6432fde-9bc5-4183-a9be-bd87ffcb5392"]={f:Ops.Html.BrowserSpecificFile_v2,objName:"Ops.Html.BrowserSpecificFile_v2"}; + + + + +// ************************************************************** +// +// Ops.Html.CSSFilter +// +// ************************************************************** + +Ops.Html.CSSFilter = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inEle = op.inObject("Element"); +const inMethod = op.inValueSelect("method", ["-", "blur", "brightness", "contrast", "grayscale", "hue-rotate", "invert", "opacity", "saturate", "sepia"]); +const inVal = op.inValue("Value"); + +let suffix = ""; +let prefix = ""; + +inVal.onChange = setValue; +inEle.onChange = setValue; + +let oldEle = null; + +function getCSSFilterString() +{ + return inMethod.get() + "(" + inVal.get() + suffix + ")"; +} + +inEle.onLinkChanged = function () +{ + // remove style when deleting op + if (inEle.isLinked()) return; + + const ele = oldEle;// inEle.get(); + + if (ele && ele.style) + { + let filter = ele.style.filter; + var str = ""; + + if (filter && filter.length > 0) + { + var str = ""; + let parts = filter.split(" "); + for (let i = 0; i < parts.length; i++) + { + if (parts[i].indexOf(inMethod.get()) == 0) + parts[i] = ""; + } + + str = parts.join(" "); + } + ele.style.filter = str; + } +}; + +function setValue() +{ + const ele = inEle.get(); + let str = ""; + + if (ele && ele.style) + { + if (ele != oldEle) oldEle = ele; + let foundMyFilter = false; + let filter = ele.style.filter; + + if (filter && filter.length > 0) + { + let parts = filter.split(" "); + for (let i = 0; i < parts.length; i++) + { + if (parts[i].indexOf(inMethod.get()) == 0) + { + foundMyFilter = true; + parts[i] = getCSSFilterString(); + } + } + + str = parts.join(" "); + } + + if (!foundMyFilter) + str += " " + getCSSFilterString(); + + ele.style.filter = str; + } +} + +inMethod.onChange = function () +{ + let m = inMethod.get(); + + prefix = inMethod.get() + ":"; + + if (m == "blur") suffix = "px"; + if (m == "brightness") suffix = ""; + if (m == "contrast") suffix = "%"; + if (m == "grayscale") suffix = "%"; + if (m == "hue-rotate") suffix = "deg"; + if (m == "invert") suffix = "%"; + if (m == "opacity") suffix = "%"; + if (m == "saturate") suffix = ""; + if (m == "sepia") suffix = "%"; + setValue(); +}; + + +}; + +Ops.Html.CSSFilter.prototype = new CABLES.Op(); +CABLES.OPS["33befabf-7eef-45f6-869f-30e0e4f44739"]={f:Ops.Html.CSSFilter,objName:"Ops.Html.CSSFilter"}; + + + + +// ************************************************************** +// +// Ops.Html.CSSPropertyString +// +// ************************************************************** + +Ops.Html.CSSPropertyString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inEle = op.inObject("Element"), + inProperty = op.inString("Property"), + inValue = op.inString("Value"), + outEle = op.outObject("HTML Element"); + +op.setPortGroup("Element", [inEle]); +op.setPortGroup("Attributes", [inProperty, inValue]); + +inProperty.onChange = updateProperty; +inValue.onChange = update; +let ele = null; + +inEle.onChange = inEle.onLinkChanged = function () +{ + if (ele && ele.style) + { + ele.style[inProperty.get()] = "initial"; + } + update(); +}; + +function updateProperty() +{ + update(); + op.setUiAttrib({ "extendTitle": inProperty.get() + "" }); +} + +function update() +{ + ele = inEle.get(); + if (ele && ele.style) + { + const str = inValue.get(); + try + { + ele.style[inProperty.get()] = str; + } + catch (e) + { + op.logError(e); + } + } + + outEle.set(inEle.get()); +} + + +}; + +Ops.Html.CSSPropertyString.prototype = new CABLES.Op(); +CABLES.OPS["a7abdfb9-4c2a-4ddb-8fc6-55b3fdfbdaf3"]={f:Ops.Html.CSSPropertyString,objName:"Ops.Html.CSSPropertyString"}; + + + + +// ************************************************************** +// +// Ops.Html.CSSProperty_v2 +// +// ************************************************************** + +Ops.Html.CSSProperty_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inEle = op.inObject("Element"), + inProperty = op.inString("Property"), + inValue = op.inFloat("Value"), + inValueSuffix = op.inString("Value Suffix", "px"), + outEle = op.outObject("HTML Element"); + +op.setPortGroup("Element", [inEle]); +op.setPortGroup("Attributes", [inProperty, inValue, inValueSuffix]); + +inProperty.onChange = updateProperty; +inValue.onChange = update; +inValueSuffix.onChange = update; +let ele = null; + +inEle.onChange = inEle.onLinkChanged = function () +{ + if (ele && ele.style) + { + ele.style[inProperty.get()] = "initial"; + } + update(); +}; + +function updateProperty() +{ + update(); + op.setUiAttrib({ "extendTitle": inProperty.get() + "" }); +} + +function update() +{ + ele = inEle.get(); + if (ele && ele.style) + { + const str = inValue.get() + inValueSuffix.get(); + try + { + if (ele.style[inProperty.get()] != str) + ele.style[inProperty.get()] = str; + } + catch (e) + { + op.logError(e); + } + } + else + { + setTimeout(update, 50); + } + + outEle.set(inEle.get()); +} + + +}; + +Ops.Html.CSSProperty_v2.prototype = new CABLES.Op(); +CABLES.OPS["c179aa0e-b558-4130-8c2d-2deab2919a07"]={f:Ops.Html.CSSProperty_v2,objName:"Ops.Html.CSSProperty_v2"}; + + + + +// ************************************************************** +// +// Ops.Html.CSS_v2 +// +// ************************************************************** + +Ops.Html.CSS_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const code = op.inStringEditor("css code"); + +code.setUiAttribs( + { + "editorSyntax": "css", + "ignoreBigPort": true + }); + +let styleEle = null; +const eleId = "css_" + CABLES.uuid(); + +code.onChange = update; +update(); + +function getCssContent() +{ + let css = code.get(); + if (css) + { + let patchId = null; + if (op.storage && op.storage.blueprint && op.storage.blueprint.patchId) + { + patchId = op.storage.blueprint.patchId; + } + css = css.replace(new RegExp("{{ASSETPATH}}", "g"), op.patch.getAssetPath(patchId)); + } + return css; +} + +function update() +{ + styleEle = document.getElementById(eleId); + + if (styleEle) + { + styleEle.textContent = getCssContent(); + } + else + { + styleEle = document.createElement("style"); + styleEle.type = "text/css"; + styleEle.id = eleId; + styleEle.textContent = attachments.css_spinner; + + const head = document.getElementsByTagName("body")[0]; + head.appendChild(styleEle); + } +} + +op.onDelete = function () +{ + styleEle = document.getElementById(eleId); + if (styleEle)styleEle.remove(); +}; + + +}; + +Ops.Html.CSS_v2.prototype = new CABLES.Op(); +CABLES.OPS["a56d3edd-06ad-44ed-9810-dbf714600c67"]={f:Ops.Html.CSS_v2,objName:"Ops.Html.CSS_v2"}; + + + + +// ************************************************************** +// +// Ops.Html.CablesLink +// +// ************************************************************** + +Ops.Html.CablesLink = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let size = op.inValue("size", 40); +let opacity = op.inValue("Opacity", 0.5); + +let element = document.createElement("div"); + +size.onChange = function () +{ + element.style.width = size.get() + "px"; + element.style.height = size.get() + "px"; +}; + +opacity.onChange = function () +{ + element.style.opacity = opacity.get(); +}; + +element.style.padding = "10px"; +element.style = "cableslink"; +element.style.position = "absolute"; +element.style.right = "0px"; +element.style.bottom = "0px"; +element.style.width = "40px"; +element.style.height = "40px"; +element.style.opacity = "0.4"; +element.style.cursor = "pointer"; +element.style["background-image"] = "url(https://cables.gl/img/cables-logo.svg)"; +element.style["z-index"] = "9999"; +element.style["background-size"] = "80%"; +element.style["background-repeat"] = "no-repeat"; + +let canvas = op.patch.cgl.canvas.parentElement; +canvas.appendChild(element); + +element.addEventListener("click", function () +{ + document.location.href = "https://cables.gl"; +}); + +op.onDelete = function () +{ + element.remove(); +}; + + +}; + +Ops.Html.CablesLink.prototype = new CABLES.Op(); +CABLES.OPS["aba114d1-b042-484a-9b66-a9bfe6590b3d"]={f:Ops.Html.CablesLink,objName:"Ops.Html.CablesLink"}; + + + + +// ************************************************************** +// +// Ops.Html.Cursor_v2 +// +// ************************************************************** + +Ops.Html.Cursor_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTriggerButton("Update"), + + cursorPort = op.inDropDown("CSS Cursors", ["auto", "crosshair", "pointer", "hand", "move", "n-resize", "ne-resize", "e-resize", "se-resize", "s-resize", "sw-resize", "w-resize", "nw-resize", "ew-resize", "text", "wait", "help", "none"], "pointer"), + + next = op.outTrigger("Next"); + +const cursorStr = ""; + +exec.onLinkChanged = +next.onLinkChanged = () => +{ + op.patch.cgl.setCursor("auto"); +}; + +exec.onTriggered = () => +{ + op.patch.cgl.setCursor(cursorPort.get()); + next.trigger(); +}; + + +}; + +Ops.Html.Cursor_v2.prototype = new CABLES.Op(); +CABLES.OPS["39486799-bdad-42d3-a300-4642c23578a8"]={f:Ops.Html.Cursor_v2,objName:"Ops.Html.Cursor_v2"}; + + + + +// ************************************************************** +// +// Ops.Html.DivElement_v2 +// +// ************************************************************** + +Ops.Html.DivElement_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inText = op.inString("Text", "Hello Div"), + inId = op.inString("Id"), + inClass = op.inString("Class"), + inStyle = op.inValueEditor("Style", "position:absolute;\nz-index:100;", "inline-css"), + inInteractive = op.inValueBool("Interactive", false), + inVisible = op.inValueBool("Visible", true), + inBreaks = op.inValueBool("Convert Line Breaks", false), + inPropagation = op.inValueBool("Propagate Click-Events", true), + outElement = op.outObject("DOM Element", null, "element"), + outHover = op.outBoolNum("Hover"), + outClicked = op.outTrigger("Clicked"); + +let listenerElement = null; +let oldStr = null; +let prevDisplay = "block"; +let div = null; + +const canvas = op.patch.cgl.canvas.parentElement; + +createElement(); + +inClass.onChange = updateClass; +inBreaks.onChange = inText.onChange = updateText; +inStyle.onChange = updateStyle; +inInteractive.onChange = updateInteractive; +inVisible.onChange = updateVisibility; + +updateText(); +updateStyle(); +warning(); +updateInteractive(); + +op.onDelete = removeElement; + +outElement.onLinkChanged = updateStyle; + +function createElement() +{ + div = document.createElement("div"); + div.dataset.op = op.id; + div.classList.add("cablesEle"); + + if (inId.get()) div.id = inId.get(); + + canvas.appendChild(div); + outElement.set(div); +} + +function removeElement() +{ + if (div) removeClasses(); + if (div && div.parentNode) div.parentNode.removeChild(div); + oldStr = null; + div = null; +} + +function setCSSVisible(visible) +{ + if (!visible) + { + div.style.visibility = "hidden"; + prevDisplay = div.style.display || "block"; + div.style.display = "none"; + } + else + { + // prevDisplay=div.style.display||'block'; + if (prevDisplay == "none") prevDisplay = "block"; + div.style.visibility = "visible"; + div.style.display = prevDisplay; + } +} + +function updateVisibility() +{ + setCSSVisible(inVisible.get()); +} + +function updateText() +{ + let str = inText.get(); + + if (oldStr === str) return; + oldStr = str; + + if (str && inBreaks.get()) str = str.replace(/(?:\r\n|\r|\n)/g, "
"); + + if (div.innerHTML != str) div.innerHTML = str; + outElement.set(null); + outElement.set(div); +} + +// inline css inisde div +function updateStyle() +{ + if (!div) return; + // if (inStyle.get() != div.style) + // { + div.setAttribute("style", inStyle.get()); + updateVisibility(); + outElement.set(null); + outElement.set(div); + // } + + if (!div.parentElement) + { + canvas.appendChild(div); + } + + warning(); +} + +let oldClassesStr = ""; + +function removeClasses() +{ + if (!div) return; + + const classes = (inClass.get() || "").split(" "); + for (let i = 0; i < classes.length; i++) + { + if (classes[i]) div.classList.remove(classes[i]); + } + oldClassesStr = ""; +} + +function updateClass() +{ + const classes = (inClass.get() || "").split(" "); + const oldClasses = (oldClassesStr || "").split(" "); + + let found = false; + + for (let i = 0; i < oldClasses.length; i++) + { + if ( + oldClasses[i] && + classes.indexOf(oldClasses[i].trim()) == -1) + { + found = true; + div.classList.remove(oldClasses[i]); + } + } + + for (let i = 0; i < classes.length; i++) + { + if (classes[i]) + { + div.classList.add(classes[i].trim()); + } + } + + oldClassesStr = inClass.get(); + warning(); +} + +function onMouseEnter(e) +{ + outHover.set(true); +} + +function onMouseLeave(e) +{ + outHover.set(false); +} + +function onMouseClick(e) +{ + if (!inPropagation.get()) + { + e.stopPropagation(); + } + outClicked.trigger(); +} + +function updateInteractive() +{ + removeListeners(); + if (inInteractive.get()) addListeners(); +} + +inId.onChange = function () +{ + div.id = inId.get(); +}; + +function removeListeners() +{ + if (listenerElement) + { + listenerElement.removeEventListener("pointerdown", onMouseClick); + listenerElement.removeEventListener("pointerleave", onMouseLeave); + listenerElement.removeEventListener("pointerenter", onMouseEnter); + listenerElement = null; + } +} + +function addListeners() +{ + if (listenerElement)removeListeners(); + + listenerElement = div; + + if (listenerElement) + { + listenerElement.addEventListener("pointerdown", onMouseClick); + listenerElement.addEventListener("pointerleave", onMouseLeave); + listenerElement.addEventListener("pointerenter", onMouseEnter); + } +} + +op.addEventListener("onEnabledChange", function (enabled) +{ + removeElement(); + if (enabled) + { + createElement(); + updateStyle(); + updateClass(); + updateText(); + updateInteractive(); + } + // if(enabled) updateVisibility(); + // else setCSSVisible(false); +}); + +function warning() +{ + if (inClass.get() && inStyle.get()) + { + op.setUiError("error", "DIV uses external and inline CSS", 1); + } + else + { + op.setUiError("error", null); + } +} + + +}; + +Ops.Html.DivElement_v2.prototype = new CABLES.Op(); +CABLES.OPS["db36db6d-83e4-4d27-b84c-8a20067aaffc"]={f:Ops.Html.DivElement_v2,objName:"Ops.Html.DivElement_v2"}; + + + + +// ************************************************************** +// +// Ops.Html.ElementChilds_v2 +// +// ************************************************************** + +Ops.Html.ElementChilds_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + parentPort = op.inObject("Parent", null, "element"), + outParent = op.outObject("Parent Out", null, "element"); + +const canvas = op.patch.cgl.canvas.parentElement; + +const inPorts = []; +for (let i = 0; i < 10; i++) +{ + const p = op.inObject("Child " + (i + 1)); + inPorts.push(p); + p.onChange = () => + { + rebuild(); + if (!p.get()) + { + const selector = "[data-cables-child-id='" + op.id + "_" + i + "']"; + const currentChild = canvas.querySelector(selector); + if (currentChild) delete currentChild.dataset.cablesChildId; + } + }; + p.onLinkChanged = () => + { + if (!p.isLinked()) + { + const selector = "[data-cables-child-id='" + op.id + "_" + i + "']"; + const currentChild = canvas.querySelector(selector); + if (currentChild) currentChild.remove(); + } + }; +} + +parentPort.onLinkChanged = () => +{ + if (!parentPort.isLinked()) + { + cleanUp(); + } + else + { + rebuild(); + } +}; + +outParent.onLinkChanged = () => +{ + if (!outParent.isLinked()) + { + const parentDiv = parentPort.get(); + if (parentDiv && parentDiv.dataset.op) + { + const inDoc = canvas.querySelector("[data-op=' " + parentDiv.dataset.op + " ']"); + if (!inDoc) + { + canvas.appendChild(parentDiv); + } + } + } +}; + +parentPort.onChange = () => +{ + if (!parentPort.get()) + { + cleanUp(); + } + rebuild(); +}; + +function cleanUp() +{ + for (let i = 0; i < inPorts.length; i++) + { + const selector = "[data-cables-child-id='" + op.id + "_" + i + "']"; + const currentChild = canvas.querySelector(selector); + if (currentChild && currentChild.parentNode) + { + currentChild.remove(); + } + } + outParent.set(null); +} + +function rebuild() +{ + const parent = parentPort.get(); + if (!parent) + { + outParent.set(null); + return; + } + + + if (!parent.querySelector) + { + outParent.set(null); + return; + } + + for (let i = 0; i < inPorts.length; i++) + { + const selector = "[data-cables-child-id='" + op.id + "_" + i + "']"; + const currentChild = parent.querySelector(selector); + if (currentChild) + { + currentChild.remove(); + } + const p = inPorts[i].get(); + if (p && parent) + { + p.dataset.cablesChildId = op.id + "_" + i; + parent.appendChild(p); + } + } + + outParent.set(null); + outParent.set(parent); +} + + +}; + +Ops.Html.ElementChilds_v2.prototype = new CABLES.Op(); +CABLES.OPS["ad7eea9a-f4af-4ab7-bb70-922242529681"]={f:Ops.Html.ElementChilds_v2,objName:"Ops.Html.ElementChilds_v2"}; + + + + +// ************************************************************** +// +// Ops.Html.ElementClientRect +// +// ************************************************************** + +Ops.Html.ElementClientRect = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inUpd=op.inTriggerButton("Update"), + inEle=op.inObject("Element",null,"element"), + outWidth=op.outNumber("Width"), + outHeight=op.outNumber("Height"), + outX=op.outNumber("X"), + outY=op.outNumber("Y"); + +inUpd.onTriggered=()=> +{ + let ele=inEle.get(); + if(!ele) + { + outX.set(0); + outY.set(0); + outWidth.set(0); + outHeight.set(0); + return; + } + const r=ele.getBoundingClientRect(); + const rCanv=op.patch.cgl.canvas.getBoundingClientRect(); + + outX.set(r.left-rCanv.left); + outY.set(r.top-rCanv.top); + outWidth.set(r.width); + outHeight.set(r.height); + +}; + + +}; + +Ops.Html.ElementClientRect.prototype = new CABLES.Op(); +CABLES.OPS["7a046f98-2adc-4f8e-ad47-c600e3ef5bca"]={f:Ops.Html.ElementClientRect,objName:"Ops.Html.ElementClientRect"}; + + + + +// ************************************************************** +// +// Ops.Html.ElementCssTransform +// +// ************************************************************** + +Ops.Html.ElementCssTransform = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inEle = op.inObject("Element", null, "element"), + inDoTranslate = op.inBool("Translate Active", true), + inTransX = op.inFloat("Translate X", 0), + inTransY = op.inFloat("Translate Y", 0), + inTransUnit = op.inSwitch("Unit", ["px", "%"], "px"), + + inDoScale = op.inBool("Scale Active", true), + inScale = op.inFloat("Scale", 1), + + inDoRot = op.inBool("Rotate Active", true), + inRot = op.inFloat("Rot Z", 0), + + inDoOrigin = op.inBool("Set Origin", true), + inOriginX = op.inSwitch("Origin X", ["left", "center", "right"], "center"), + inOriginY = op.inSwitch("Origin Y", ["top", "center", "bottom"], "center"); + +op.setPortGroup("Element", [inEle]); +op.setPortGroup("Translation", [inDoTranslate, inTransY, inTransX, inTransUnit]); +op.setPortGroup("Scaling", [inScale, inDoScale]); +op.setPortGroup("Rotation", [inDoRot, inRot]); +op.setPortGroup("Origin", [inDoOrigin, inOriginX, inOriginY]); + +inTransUnit.onChange = + inDoScale.onChange = + inDoOrigin.onChange = + inOriginX.onChange = + inOriginY.onChange = + inDoRot.onChange = + inDoTranslate.onChange = + inDoRot.onChange = + inTransX.onChange = + inTransY.onChange = + inScale.onChange = + inRot.onChange = update; + +let ele = null; + +inEle.onChange = inEle.onLinkChanged = function () +{ + if (ele && ele.style) + { + ele.style.transform = "initial"; + } + update(); +}; + +function update() +{ + ele = inEle.get(); + if (ele && ele.style) + { + let str = ""; + + if (inDoTranslate.get()) + if (inTransY.get() || inTransX.get()) + str += "translate(" + inTransX.get() + inTransUnit.get() + " , " + inTransY.get() + inTransUnit.get() + ") "; + + if (inDoScale.get()) + if (inScale.get() != 1.0) + str += "scale(" + inScale.get() + ") "; + + if (inDoRot.get()) + if (inRot.get() != 0.0) + str += "rotateZ(" + inRot.get() + "deg) "; + + try + { + ele.style.transform = str; + + if (inDoOrigin.get()) + ele.style["transform-origin"] = inOriginY.get() + " " + inOriginX.get(); + else + ele.style["transform-origin"] = "initial"; + } + catch (e) + { + op.logError(e); + } + } + else + { + setTimeout(update, 50); + } + + // outEle.set(inEle.get()); +} + + +}; + +Ops.Html.ElementCssTransform.prototype = new CABLES.Op(); +CABLES.OPS["777d00c6-5605-43c5-9b6a-b20d465bd3ba"]={f:Ops.Html.ElementCssTransform,objName:"Ops.Html.ElementCssTransform"}; + + + + +// ************************************************************** +// +// Ops.Html.ElementFadeInOut +// +// ************************************************************** + +Ops.Html.ElementFadeInOut = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"fadeInOut_css":"\n.CABLES_animFadedOut\n{\n display:none !important;\n opacity:0;\n}\n\n.CABLES_animFadeOut\n{\n animation: CABLES_keysFadeOut $LENGTHs normal forwards ease-in-out;\n}\n\n.CABLES_animFadeIn\n{\n /*display:block;*/\n animation: CABLES_keysFadeIn $LENGTHs normal forwards ease-in-out;\n}\n\n@keyframes CABLES_keysFadeIn {\n from { opacity: 0; }\n to { opacity: $FULLOPACITY; }\n}\n\n@keyframes CABLES_keysFadeOut {\n from { opacity: $FULLOPACITY; }\n to { opacity: 0; }\n}\n",}; +const inEle = op.inObject("HTML Element"); +const inVisible = op.inValueBool("Visible", true); +const inDuration = op.inValue("Duration", 0.5); +const inOpacity = op.inValue("Opacity", 1); +const outShowing = op.outBoolNum("Is Showing", false); + +let theTimeout = null; +inDuration.onChange = update; +inOpacity.onChange = update; + +inVisible.onChange = updateVisibility; +inEle.onChange = updateVisibility; + +let styleEle = null; +const eleId = "css_" + CABLES.uuid(); + +update(); + +let oldEle = null; +let loaded = true; +const oldvis = null; +loaded = true; + +op.onLoaded = function () +{ + loaded = true; + updateVisibility(); + outShowing.set(inVisible.get()); +}; + +function updateVisibility() +{ + const ele = inEle.get(); + + if (!loaded) + { + setTimeout(updateVisibility, 50); + return; + } + + if (styleEle && ele) + { + // if (ele == oldEle) return; + // oldEle = ele; + if (inVisible.get()) + { + outShowing.set(true); + if (ele && ele.classList && !ele.classList.contains("CABLES_animFadeIn")) + { + clearTimeout(theTimeout); + ele.classList.remove("CABLES_animFadedOut"); + ele.classList.remove("CABLES_animFadeOut"); + ele.classList.add("CABLES_animFadeIn"); + theTimeout = setTimeout(function () + { + ele.classList.remove("CABLES_animFadeIn"); + outShowing.set(true); + }, inDuration.get() * 1000); + } + } + else + { + outShowing.set(true); + if (ele && ele.classList && !ele.classList.contains("CABLES_animFadeOut")) + { + clearTimeout(theTimeout); + ele.classList.remove("CABLES_animFadeIn"); + ele.classList.add("CABLES_animFadeOut"); + theTimeout = setTimeout(function () + { + ele.classList.add("CABLES_animFadedOut"); + outShowing.set(false); + }, inDuration.get() * 1000); + } + } + } + else + { + // op.logError("no html element"); + } +} + +function getCssContent() +{ + let css = attachments.fadeInOut_css; + + while (css.indexOf("$LENGTH") > -1)css = css.replace("$LENGTH", inDuration.get()); + while (css.indexOf("$FULLOPACITY") > -1)css = css.replace("$FULLOPACITY", inOpacity.get()); + + return css; +} + +function update() +{ + styleEle = document.getElementById(eleId); + + if (styleEle) + { + styleEle.textContent = getCssContent(); + } + else + { + styleEle = document.createElement("style"); + styleEle.type = "text/css"; + styleEle.id = eleId; + styleEle.textContent = getCssContent(); + + const head = document.getElementsByTagName("body")[0]; + head.appendChild(styleEle); + } +} + +op.onDelete = function () +{ + const ele = inEle.get(); + + if (ele && ele.classList) + { + ele.classList.remove("CABLES_animFadeIn"); + ele.classList.remove("CABLES_animFadedOut"); + ele.classList.remove("CABLES_animFadeOut"); + } + + styleEle = document.getElementById(eleId); + if (styleEle)styleEle.remove(); +}; + + +}; + +Ops.Html.ElementFadeInOut.prototype = new CABLES.Op(); +CABLES.OPS["392e65eb-4ebe-4adb-8711-e4cfe059c6c9"]={f:Ops.Html.ElementFadeInOut,objName:"Ops.Html.ElementFadeInOut"}; + + + + +// ************************************************************** +// +// Ops.Html.ElementInteraction +// +// ************************************************************** + +Ops.Html.ElementInteraction = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inEle = op.inObject("Element"), + inAct = op.inBool("Active", true), + outIsDownLeft = op.outBool("Mouse Is Down Left"), + outIsDownRight = op.outBool("Mouse Is Down Right"), + outDownLeft = op.outTrigger("Mouse Down Left"), + outDownRight = op.outTrigger("Mouse Down Right"), + outUpLeft = op.outTrigger("Mouse Up Left"), + outUpRight = op.outTrigger("Mouse Up Right"), + outOver = op.outBool("Mouse Over"), + outEnter = op.outTrigger("Mouse Enter"), + outLeave = op.outTrigger("Mouse Leave"), + outPosX = op.outNumber("Offset X"), + outPosY = op.outNumber("Offset Y"); + +let ele = null; + +inEle.onChange = () => +{ + const el = inEle.get(); + + if (el) addListeners(el); + else removeListeners(); +}; + +function addListeners(el) +{ + ele = el; + + ele.addEventListener("pointerenter", onEnter); + ele.addEventListener("pointerleave", onLeave); + ele.addEventListener("pointermove", onMove); + ele.addEventListener("pointerdown", onDown); + ele.addEventListener("pointerup", onUp); + // ele.addEventListener("touchstart",onDown); +} + +function removeListeners() +{ + if (!ele) return; + ele.removeEventListener("pointerenter", onEnter); + ele.removeEventListener("pointerleave", onLeave); + ele.removeEventListener("pointermove", onMove); + ele.removeEventListener("pointerdown", onDown); + ele.removeEventListener("pointerup", onUp); + // ele.removeEventListener("touchstart",onDown); +} + +function onMove(e) +{ + outPosX.set(e.offsetX); + outPosY.set(e.offsetY); + outIsDownLeft.set(e.buttons == 1); + outIsDownRight.set(e.buttons == 2); +} + +function onDown(e) +{ + outPosX.set(e.offsetX); + outPosY.set(e.offsetY); + + if (e.buttons == 1)outDownLeft.trigger(); + if (e.buttons == 2)outDownRight.trigger(); + + ele.setPointerCapture(e.pointerId); + + outIsDownLeft.set(e.buttons == 1); + outIsDownRight.set(e.buttons == 2); +} + +function onUp(e) +{ + outPosX.set(e.offsetX); + outPosY.set(e.offsetY); + + ele.releasePointerCapture(e.pointerId); + + if (e.buttons == 1)outUpLeft.trigger(); + if (e.buttons == 2)outUpRight.trigger(); + outIsDownRight.set(false); + outIsDownLeft.set(false); +} + +function onEnter() +{ + outEnter.trigger(); + outOver.set(true); +} + +function onLeave() +{ + outLeave.trigger(); + outIsDownLeft.set(false); + outOver.set(false); +} + + +}; + +Ops.Html.ElementInteraction.prototype = new CABLES.Op(); +CABLES.OPS["bc2903a0-ee7f-4918-b1d8-ea3a6262e3ee"]={f:Ops.Html.ElementInteraction,objName:"Ops.Html.ElementInteraction"}; + + + + +// ************************************************************** +// +// Ops.Html.ElementSize +// +// ************************************************************** + +Ops.Html.ElementSize = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExe=op.inTrigger("Update"), + inMode=op.inSwitch("Position",['Relative','Absolute'],'Relative'), + inEle=op.inObject("Element"), + outX=op.outNumber("x"), + outY=op.outNumber("y"), + outWidth=op.outNumber("Width"), + outHeight=op.outNumber("Height"); + +inMode.onChange=updateMode; +updateMode(); + +function updateMode() +{ + if(inMode.get()=="Relative") + { + inEle.onChange=updateRel; + inExe.onTriggered=updateRel; + } + else + { + inEle.onChange=updateAbs; + inExe.onTriggered=updateAbs; + } +} + +function updateAbs() +{ + const ele=inEle.get(); + if(!ele)return; + + const r=ele.getBoundingClientRect(); + + outX.set(r.x); + outY.set(r.y); + outWidth.set(r.width); + outHeight.set(r.height); +} + +function updateRel() +{ + const ele=inEle.get(); + if(!ele)return; + + const rcanv=op.patch.cgl.canvas.getBoundingClientRect(); + const r=ele.getBoundingClientRect(); + outX.set(r.x-rcanv.x); + outY.set(r.y-rcanv.y); + outWidth.set(r.width); + outHeight.set(r.height); +} + +}; + +Ops.Html.ElementSize.prototype = new CABLES.Op(); +CABLES.OPS["fb23c251-a43e-4677-9d03-ccd512fee82e"]={f:Ops.Html.ElementSize,objName:"Ops.Html.ElementSize"}; + + + + +// ************************************************************** +// +// Ops.Html.ElementsPositionsByClass +// +// ************************************************************** + +Ops.Html.ElementsPositionsByClass = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inUpd=op.inTriggerButton("Update"), + inClassName=op.inString("Classname",""), + outPosArr=op.outArray("Position"), + outSizeArr=op.outArray("Size"); + +inUpd.onTriggered=()=> +{ + outPosArr.set(null); + outSizeArr.set(null); + + const arrPos=[]; + const arrSize=[]; + + const els=document.getElementsByClassName(inClassName.get()); + const rCanv=op.patch.cgl.canvas.getBoundingClientRect(); + + for(let i=0;i= 0; i--) + { + removeListener(element, subscribedEvents[i]); + } + } +} + +function removeListener(element, eventName) +{ + if (!element || !eventName || !arrayContainsValue(subscribedEvents, eventName)) { return; } + let subscribedEventIndex = subscribedEvents.indexOf(eventName); + element.removeEventListener(eventName, getEventByName(eventName).handler); + subscribedEvents.splice(subscribedEventIndex, 1); +} + +/* +function removeFromArray(arr, v) { + let i = arr.indexOf(v); + if(i > -1) { + arr.splice(i, 1); + } +} +*/ + +function arrayContainsValue(arr, v) +{ + return arr && arr.indexOf(v) > -1; +} + +/** + * Returns an event-object from the events array + * @param {string} name e.g. 'mousedown' + */ +function getEventByName(eventName) +{ + for (let i = 0; i < events.length; i++) + { + if (events[i].name == eventName) + { + return events[i]; + } + } + return null; +} + +/** + * Adds all listeners to the element and saves it in the events array + */ +function addListeners(element) +{ + if (!element) { return; } + events.forEach(function (event) + { + addListener(element, event); + }); +} + +/** + * Adds a listener to the element + * @param {object} element the HTML DOM element + * @param {object} event the event object from the events-array + */ +function addListener(element, event) +{ + if (!element || !event) { return; } + if (subscribedEvents.indexOf(event.name) > -1) { return; } // already subscribed + if (!event.togglePort.get()) { return; } // toggle for event not set + element.addEventListener(event.name, event.handler); + subscribedEvents.push(event.name); +} + +op.onDelete = function () +{ + removeAllListeners(lastElement); + removeAllListeners(elementPort.get()); +}; + + +}; + +Ops.Html.EventListener.prototype = new CABLES.Op(); +CABLES.OPS["73dc05e9-7b63-444b-980b-bd63f511b94a"]={f:Ops.Html.EventListener,objName:"Ops.Html.EventListener"}; + + + + +// ************************************************************** +// +// Ops.Html.FontFile_v2 +// +// ************************************************************** + +Ops.Html.FontFile_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + filename = op.inUrl("file", [".otf", ".ttf", ".woff", ".woff2"]), + fontname = op.inString("family"), + outLoaded = op.outBoolNum("Loaded"), + loadedTrigger = op.outTrigger("Loaded Trigger"); + +let loadingId = null; + +filename.onChange = function () +{ + outLoaded.set(false); + addStyle(); +}; + +fontname.onChange = addStyle; + +let fontFaceObj; + +function addStyle() +{ + if (filename.get() && fontname.get()) + { + if (document.fonts) + { + fontFaceObj = new FontFace(fontname.get(), "url(" + op.patch.getFilePath(String(filename.get())) + ")"); + + loadingId = op.patch.cgl.patch.loading.start("FontFile", filename.get()); + + // Add the FontFace to the FontFaceSet + document.fonts.add(fontFaceObj); + + // Get the current status of the FontFace + // (should be 'unloaded') + + // Load the FontFace + fontFaceObj.load(); + + // Get the current status of the Fontface + // (should be 'loading' or 'loaded' if cached) + + // Wait until the font has been loaded, log the current status. + fontFaceObj.loaded.then((fontFace) => + { + outLoaded.set(true); + loadedTrigger.trigger(); + op.patch.cgl.patch.loading.finished(loadingId); + + op.patch.emitEvent("fontLoaded", fontname.get()); + + // Throw an error if loading wasn't successful + }, (fontFace) => + { + op.setUiError("loadingerror", "Font loading error!" + fontFaceObj.status); + // op.logError("Font loading error! Current status", fontFaceObj.status); + }); + } + else + { // font loading api not supported + const fileUrl = op.patch.getFilePath(String(filename.get())); + const styleStr = "" + .endl() + "@font-face" + .endl() + "{" + .endl() + " font-family: \"" + fontname.get() + "\";" + .endl() + " src: url(\"" + fileUrl + "\") format(\"truetype\");" + .endl() + "}"; + + const style = document.createElement("style"); + style.type = "text/css"; + style.innerHTML = styleStr; + document.getElementsByTagName("head")[document.getElementsByTagName("head").length - 1].appendChild(style); + // TODO: Poll if font loaded + } + } +} + + +}; + +Ops.Html.FontFile_v2.prototype = new CABLES.Op(); +CABLES.OPS["68177370-116e-4c76-aef3-3b10d68e7227"]={f:Ops.Html.FontFile_v2,objName:"Ops.Html.FontFile_v2"}; + + + + +// ************************************************************** +// +// Ops.Html.FullscreenMode +// +// ************************************************************** + +Ops.Html.FullscreenMode = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + doRequest = op.inTriggerButton("Request Fullscreen"), + doExit = op.inTriggerButton("Exit Fullscreen"), + inEle = op.inSwitch("Element", ["Canvas", "Document"], "Canvas"), + isFullscreen = op.outBoolNum("Is Fullscreen"); + +doExit.onTriggered = exitFs; +doRequest.onTriggered = startFs; + +let countStarts = 0; + +function setState() +{ + const isFull = (!window.screenTop && !window.screenY); + isFullscreen.set(isFull); +} + +function startFs() +{ + countStarts++; + if (countStarts > 30) + { + doRequest.onTriggered = null; + op.setUiAttrib({ "error": "Fullscreen Request shound not triggered that often: op disabled" }); + exitFs(); + } + + let elem = null; + if (inEle == "Canvas") elem = op.patch.cgl.canvas.parentElement; + else elem = document.documentElement; + + if (elem.requestFullScreen) elem.requestFullScreen(); + else if (elem.mozRequestFullScreen) elem.mozRequestFullScreen(); + else if (elem.webkitRequestFullScreen)elem.webkitRequestFullScreen(); + else if (elem.msRequestFullScreen)elem.msRequestFullScreen(); + + setTimeout(setState, 100); + setTimeout(setState, 500); + setTimeout(setState, 1000); +} + +function exitFs() +{ + countStarts--; + if (document.exitFullscreen) document.exitFullscreen(); + else if (document.mozCancelFullScreen) document.mozCancelFullScreen(); + else if (document.webkitExitFullscreen) document.webkitExitFullscreen(); + else if (document.msExitFullscreen)document.msExitFullscreen(); + + setTimeout(setState, 100); + setTimeout(setState, 500); + setTimeout(setState, 1000); +} + + +}; + +Ops.Html.FullscreenMode.prototype = new CABLES.Op(); +CABLES.OPS["fe933b35-696d-4738-be03-c0c011ed67a0"]={f:Ops.Html.FullscreenMode,objName:"Ops.Html.FullscreenMode"}; + + + + +// ************************************************************** +// +// Ops.Html.GetCssVariable +// +// ************************************************************** + +Ops.Html.GetCssVariable = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTriggerButton("Update"), + varname = op.inString("Var Name"), + result = op.outString("Result"); + +const root = document.documentElement; + +exe.onTriggered = function () +{ + result.set(root.style.getPropertyValue("--" + varname.get())); +}; + + +}; + +Ops.Html.GetCssVariable.prototype = new CABLES.Op(); +CABLES.OPS["ef03f407-e365-47c7-9829-be54ba53c54d"]={f:Ops.Html.GetCssVariable,objName:"Ops.Html.GetCssVariable"}; + + + + +// ************************************************************** +// +// Ops.Html.HyperLink_v2 +// +// ************************************************************** + +Ops.Html.HyperLink_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTriggerButton("Open"), + inUrl = op.inString("URL", "https://cables.gl"), + inTarget = op.inString("Target Name", "_self"), + inSpecs = op.inString("Specs", ""); + +exec.onTriggered = function () +{ + // document.location.href=inUrl.get(); + window.open(inUrl.get(), inTarget.get(), inSpecs.get()); +}; + + +}; + +Ops.Html.HyperLink_v2.prototype = new CABLES.Op(); +CABLES.OPS["a669d4f7-1e35-463c-bf8b-08c9f1b68e04"]={f:Ops.Html.HyperLink_v2,objName:"Ops.Html.HyperLink_v2"}; + + + + +// ************************************************************** +// +// Ops.Html.IFrame_v3 +// +// ************************************************************** + +Ops.Html.IFrame_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + src = op.inString("URL", "https://undev.studio"), + elId = op.inString("ID"), + active = op.inBool("Active", true), + inStyle = op.inStringEditor("Style", "position:absolute;\nz-index:9999;\nborder:0;\nwidth:50%;\nheight:50%;"), + outEle = op.outObject("Element"); + +op.setPortGroup("Attributes", [src, elId]); + +let element = null; + +op.onDelete = removeEle; + +op.onLoadedValueSet = op.init = () => +{ + addElement(); + updateSoon(); + inStyle.onChange = + src.onChange = + elId.onChange = updateSoon; + + active.onChange = updateActive; +}; + +function addElement() +{ + if (!active.get()) return; + if (element) removeEle(); + element = document.createElement("iframe"); + updateAttribs(); + const parent = op.patch.cgl.canvas.parentElement; + parent.appendChild(element); + outEle.set(element); +} + +let timeOut = null; + +function updateSoon() +{ + clearTimeout(timeOut); + timeOut = setTimeout(updateAttribs, 30); +} + +function updateAttribs() +{ + if (!element) return; + element.setAttribute("style", inStyle.get()); + element.setAttribute("src", src.get()); + element.setAttribute("id", elId.get()); +} + +function removeEle() +{ + if (element && element.parentNode)element.parentNode.removeChild(element); + element = null; + outEle.set(element); +} + +function updateActive() +{ + if (!active.get()) + { + removeEle(); + return; + } + + addElement(); +} + + +}; + +Ops.Html.IFrame_v3.prototype = new CABLES.Op(); +CABLES.OPS["9e74b275-a1ed-4d10-aba4-4b3311363a99"]={f:Ops.Html.IFrame_v3,objName:"Ops.Html.IFrame_v3"}; + + + + +// ************************************************************** +// +// Ops.Html.LoadingIndicator +// +// ************************************************************** + +Ops.Html.LoadingIndicator = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"css_ellipsis_css":".lds-ellipsis {\n\n}\n.lds-ellipsis div {\n position: absolute;\n /*top: 33px;*/\n margin-top:-12px;\n margin-left:-13px;\n width: 13px;\n height: 13px;\n border-radius: 50%;\n background: #fff;\n animation-timing-function: cubic-bezier(0, 1, 1, 0);\n}\n.lds-ellipsis div:nth-child(1) {\n left: 8px;\n animation: lds-ellipsis1 0.6s infinite;\n}\n.lds-ellipsis div:nth-child(2) {\n left: 8px;\n animation: lds-ellipsis2 0.6s infinite;\n}\n.lds-ellipsis div:nth-child(3) {\n left: 32px;\n animation: lds-ellipsis2 0.6s infinite;\n}\n.lds-ellipsis div:nth-child(4) {\n left: 56px;\n animation: lds-ellipsis3 0.6s infinite;\n}\n@keyframes lds-ellipsis1 {\n 0% {\n transform: scale(0);\n }\n 100% {\n transform: scale(1);\n }\n}\n@keyframes lds-ellipsis3 {\n 0% {\n transform: scale(1);\n }\n 100% {\n transform: scale(0);\n }\n}\n@keyframes lds-ellipsis2 {\n 0% {\n transform: translate(0, 0);\n }\n 100% {\n transform: translate(24px, 0);\n }\n}\n","css_ring_css":".lds-ring {\n}\n.lds-ring div {\n box-sizing: border-box;\n display: block;\n position: absolute;\n width: 100%;\n height: 100%;\n margin: 0;\n border: 3px solid #fff;\n border-radius: 50%;\n animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n border-color: #fff transparent transparent transparent;\n}\n.lds-ring div:nth-child(1) {\n animation-delay: -0.45s;\n}\n.lds-ring div:nth-child(2) {\n animation-delay: -0.3s;\n}\n.lds-ring div:nth-child(3) {\n animation-delay: -0.15s;\n}\n@keyframes lds-ring {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n","css_spinner_css":"._cables_spinner {\n /*width: 40px;*/\n /*height: 40px;*/\n /*margin: 100px auto;*/\n background-color: #777;\n\n border-radius: 100%;\n -webkit-animation: sk-scaleout 1.0s infinite ease-in-out;\n animation: sk-scaleout 1.0s infinite ease-in-out;\n}\n\n@-webkit-keyframes sk-scaleout {\n 0% { -webkit-transform: scale(0) }\n 100% {\n -webkit-transform: scale(1.0);\n opacity: 0;\n }\n}\n\n@keyframes sk-scaleout {\n 0% {\n -webkit-transform: scale(0);\n transform: scale(0);\n } 100% {\n -webkit-transform: scale(1.0);\n transform: scale(1.0);\n opacity: 0;\n }\n}",}; +const + inVisible = op.inBool("Visible", true), + inStyle = op.inSwitch("Style", ["Spinner", "Ring", "Ellipsis"], "Ring"); + +const div = document.createElement("div"); +div.dataset.op = op.id; +const canvas = op.patch.cgl.canvas.parentElement; + +inStyle.onChange = updateStyle; + +div.appendChild(document.createElement("div")); +div.appendChild(document.createElement("div")); +div.appendChild(document.createElement("div")); + +const size = 50; + +div.style.width = size + "px"; +div.style.height = size + "px"; +div.style.top = "50%"; +div.style.left = "50%"; +// div.style.border="1px solid red"; + +div.style["margin-left"] = "-" + size / 2 + "px"; +div.style["margin-top"] = "-" + size / 2 + "px"; + +div.style.position = "absolute"; +div.style["z-index"] = "9999999"; + +inVisible.onChange = updateVisible; + +let eleId = "css_loadingicon_" + CABLES.uuid(); + +const styleEle = document.createElement("style"); +styleEle.type = "text/css"; +styleEle.id = eleId; + +let head = document.getElementsByTagName("body")[0]; +head.appendChild(styleEle); + +op.onDelete = () => +{ + remove(); + if (styleEle)styleEle.remove(); +}; + +updateStyle(); + +function updateStyle() +{ + const st = inStyle.get(); + if (st == "Spinner") + { + div.classList.add("_cables_spinner"); + styleEle.textContent = attachments.css_spinner_css; + } + else div.classList.remove("_cables_spinner"); + + if (st == "Ring") + { + div.classList.add("lds-ring"); + styleEle.textContent = attachments.css_ring_css; + } + else div.classList.remove("lds-ring"); + + if (st == "Ellipsis") + { + div.classList.add("lds-ellipsis"); + styleEle.textContent = attachments.css_ellipsis_css; + } + else div.classList.remove("lds-ellipsis"); +} + +function remove() +{ + div.remove(); + // if (styleEle)styleEle.remove(); +} + +function updateVisible() +{ + remove(); + if (inVisible.get()) canvas.appendChild(div); +} + + +}; + +Ops.Html.LoadingIndicator.prototype = new CABLES.Op(); +CABLES.OPS["e102834c-6dcf-459c-9e22-44ebccfc0d3b"]={f:Ops.Html.LoadingIndicator,objName:"Ops.Html.LoadingIndicator"}; + + + + +// ************************************************************** +// +// Ops.Html.MailtoLink +// +// ************************************************************** + +Ops.Html.MailtoLink = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inEmail = op.inString("Email", "test@test.com"), + inSubject = op.inString("Subject", ""), + exec = op.inTriggerButton("Execute"); + +exec.onTriggered = function () +{ + let str = "mailto:"; + str += inEmail.get(); + if (inSubject.get())str += "?subject=" + inSubject.get(); + window.location.href = str; +}; + + +}; + +Ops.Html.MailtoLink.prototype = new CABLES.Op(); +CABLES.OPS["6d03ec3b-f8b2-4544-bdb3-df771e857069"]={f:Ops.Html.MailtoLink,objName:"Ops.Html.MailtoLink"}; + + + + +// ************************************************************** +// +// Ops.Html.MarkdownToHtml +// +// ************************************************************** + +Ops.Html.MarkdownToHtml = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr = op.inStringEditor("Markdown", "##hello\n\nthis is some text...", "markdown"), + outStr = op.outString("Html"); + +inStr.onChange = update; +update(); + +function update() +{ + let str = inStr.get(); + + str = marked.parse(str); + outStr.set(str); +} + + +}; + +Ops.Html.MarkdownToHtml.prototype = new CABLES.Op(); +CABLES.OPS["26c97760-6e6b-4ff7-9715-dc510d23ab22"]={f:Ops.Html.MarkdownToHtml,objName:"Ops.Html.MarkdownToHtml"}; + + + + +// ************************************************************** +// +// Ops.Html.ModalOverlay +// +// ************************************************************** + +Ops.Html.ModalOverlay = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inEle = op.inObject("Content Element"), + inShow = op.inTriggerButton("Show"), + inClose = op.inTriggerButton("Close"), + closeButton = op.inBool("Show Closebutton", true), + inOpacity = op.inFloatSlider("Opacity", 0.5), + outVisible = op.outBool("Visible"), + outClosed = op.outTrigger("Closed"), + outElement = op.outObject("Element"); + +const eleContainer = document.createElement("div"); +const eleClose = document.createElement("div"); + +eleClose.innerHTML = "×"; +eleClose.style.color = "white"; +eleClose.style.position = "fixed"; +eleClose.style.top = +eleClose.style.right = "25px"; +eleClose.style["line-height"] = "25px"; +eleClose.style["z-index"] = "9999"; +eleClose.style.cursor = "pointer"; +eleClose.style["font-size"] = "50px"; +eleClose.addEventListener("pointerdown", hide); +eleContainer.addEventListener("pointerdown", hide); +eleContainer.appendChild(eleClose); + +inOpacity.onChange = updateBgColor; +eleContainer.style.display = "none"; +inShow.onTriggered = show; +inClose.onTriggered = hide; + +closeButton.onChange = updateCloseButton; + +function updateCloseButton() +{ + if (!eleClose) return; + if (closeButton.get()) eleClose.style.display = "block"; + else eleClose.style.display = "none"; +} + +inEle.onChange = function () +{ + let ele = inEle.get(); + if (ele && eleContainer) eleContainer.appendChild(ele); +}; + +function hide() +{ + outVisible.set(false); + eleContainer.style.display = "none"; + outClosed.trigger(); +} + +function updateBgColor() +{ + eleContainer.style["background-color"] = "rgba(0,0,0," + inOpacity.get() + ")"; +} + +function show() +{ + outVisible.set(true); + updateCloseButton(); + eleContainer.style.display = "block"; + + eleContainer.dataset.op = op.id; + let parent = op.patch.cgl.canvas.parentElement; + + eleContainer.style = "overflow:auto;top:0;width:100%;height:100%;position:absolute;z-index:9999"; + updateBgColor(); + + parent.appendChild(eleContainer); + outElement.set(eleContainer); +} + + +}; + +Ops.Html.ModalOverlay.prototype = new CABLES.Op(); +CABLES.OPS["a8ba593a-4d5a-4b55-8ee7-9b6f9920da1f"]={f:Ops.Html.ModalOverlay,objName:"Ops.Html.ModalOverlay"}; + + + + +// ************************************************************** +// +// Ops.Html.MouseCursorImage_v2 +// +// ************************************************************** + +Ops.Html.MouseCursorImage_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTriggerButton("Update"), + filename = op.inUrl("file"), + offX = op.inValueInt("Offset X"), + offY = op.inValueInt("Offset Y"), + next = op.outTrigger("Next"); + +offX.onChange = + offY.onChange = + filename.onChange = updateStr; + +exec.onTriggered = update; + +let str = "auto"; + +function updateStr() +{ + str = "url(" + op.patch.getFilePath(String(filename.get())) + ") " + offX.get() + " " + offX.get() + ", auto"; +} + +function update() +{ + op.patch.cgl.setCursor(str); + next.trigger(); +} + +exec.onLinkChanged = +next.onLinkChanged = () => +{ + op.patch.cgl.setCursor("auto"); +}; + + +}; + +Ops.Html.MouseCursorImage_v2.prototype = new CABLES.Op(); +CABLES.OPS["2a6be938-3db8-438e-82f2-60167529eb47"]={f:Ops.Html.MouseCursorImage_v2,objName:"Ops.Html.MouseCursorImage_v2"}; + + + + +// ************************************************************** +// +// Ops.Html.Notification +// +// ************************************************************** + +Ops.Html.Notification = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"defaultstyle_txt":"visibility: hidden;\nbackground-color: #282828;\ncolor: #fff;\n\npadding: 16px;\nposition: absolute;\nz-index: 9999;\nfont-size: 17px;\nopacity:0;\nborder-radius:10px;\ntext-align:center;\nleft: 50%;\ntransform: translate(-50%, 0);\n",}; +const + triggerAnim = op.inTriggerButton("Trigger animation"), + inText = op.inString("Text", "Hello!
This is a pop up"), + inClass = op.inString("Class"), + inStyle = op.inValueEditor("Style", attachments.defaultstyle_txt, "none"), + inVisible = op.inValueBool("Active", true), + inBreaks = op.inValueBool("Convert Line Breaks", false), + fadeInDuration = op.inFloat("Fade in", 0.5), + holdDuration = op.inFloat("Hold ", 2.0), + fadeOutDuration = op.inFloat("Fade out", 0.8), + percentOrPixel = op.inSwitch("mode", ["%", "px"], "%"), + divSide = op.inSwitch("Side", ["bottom", "top"], "bottom"), + startPosition = op.inFloat("Starting position", 0), + endPosition = op.inFloat("Ending position", 5), + finishedTrigger = op.outTrigger("Finished trigger"), + finished = op.outBool("Finished", false), + outElement = op.outObject("DOM Element"); + +op.setPortGroup("Animation", [fadeInDuration, holdDuration, fadeOutDuration]); +op.setPortGroup("HTML CSS", [inText, inClass, inStyle, inVisible, inBreaks]); +op.setPortGroup("Positioning", [percentOrPixel, divSide, startPosition, endPosition]); + +const divid = "notification_" + CABLES.uuid(); + +// inStyle.setUiAttribs({editorSyntax:'css'}); +const listenerElement = null; +let oldStr = null; + +let prevDisplay = "block"; + +const div = document.createElement("div"); +div.dataset.op = op.id; +div.id = divid; + +const canvas = op.patch.cgl.canvas.parentElement; + +canvas.appendChild(div); +outElement.set(div); + +inClass.onChange = updateClass; +inBreaks.onChange = inText.onChange = updateText; +inStyle.onChange = updateStyle; +inVisible.onChange = updateVisibility; + +triggerAnim.onTriggered = popUpAnim; + +updateText(); +updateStyle(); +warning(); + +op.onDelete = removeElement; + +outElement.onLinkChanged = updateStyle; + +let animInProgress = false; + +function setCSSVisible(visible) +{ + if (!visible) + { + div.style.visibility = "hidden"; + prevDisplay = div.style.display || "block"; + div.style.display = "none"; + } + else + { + if (prevDisplay == "none") prevDisplay = "block"; + div.style.visibility = "visible"; + div.style.display = "none"; + } +} + +function updateVisibility() +{ + setCSSVisible(inVisible.get()); +} + +function updateText() +{ + let str = inText.get(); + + if (oldStr === str) return; + oldStr = str; + + if (str && inBreaks.get()) str = str.replace(/(?:\r\n|\r|\n)/g, "
"); + + if (div.innerHTML != str) div.innerHTML = str; + outElement.set(null); + outElement.set(div); +} + +function removeElement() +{ + if (div && div.parentNode) div.parentNode.removeChild(div); +} +// inline css inisde div +function updateStyle() +{ + if (inStyle.get() != div.style) + { + div.setAttribute("style", inStyle.get()); + + updateVisibility(); + outElement.set(null); + outElement.set(div); + } + warning(); +} + +function updateClass() +{ + div.setAttribute("class", inClass.get()); + warning(); +} + +op.addEventListener("onEnabledChange", function (enabled) +{ + op.log("css changed"); + setCSSVisible(div.style.visibility != "visible"); +}); + +function warning() +{ + if (inClass.get() && inStyle.get()) op.setUiError("error", "DIV uses external and inline CSS", 1); + else op.setUiError("error", null); +} + +function popUpAnim() +{ + if (!inVisible.get()) return; + + const mode = percentOrPixel.get(); + const start = startPosition.get() + mode; + const end = endPosition.get() + mode; + + const targetDiv = document.getElementById(divid); + div.style.display = "block"; + + const animData = {}; + // this function cascades into each stage when started + startAnim(mode, start, end, animData); +} + +function startAnim(mode, start, end, animData) +{ + // stop the glitches from it being triggered multiple times + if (animInProgress) return; + + finished.set(false); + animInProgress = true; + + animData.easing = ["cubic-bezier(0.0, 0.0, 0.2, 1.0)", "linear"]; + animData.opacity = [0, 1]; + + if (divSide.get() == "bottom") animData.bottom = [start, end]; + else animData.top = [start, end]; + + document.getElementById(divid).animate( + animData, fadeInDuration.get() * 1000).onfinish = function () + { + holdAnim(mode, start, end, animData); + }; +} + +function holdAnim(mode, start, end, animData) +{ + animData.easing = ["linear", "linear"]; + animData.opacity = [1, 1]; + + if (divSide.get() == "bottom") animData.bottom = [end, end]; + else animData.top = [end, end]; + + document.getElementById(divid).animate(animData, holdDuration.get() * 1000).onfinish = + function () + { + endAnim(mode, start, end, animData); + }; +} + +function endAnim(mode, start, end, animData) +{ + animData.easing = ["cubic-bezier(0.0, 0.0, 0.2, 1.0)", "linear"]; + animData.opacity = [1, 0]; + + if (divSide.get() == "bottom") animData.bottom = [end, start]; + else animData.top = [end, start]; + + document.getElementById(divid).animate( + animData, fadeOutDuration.get() * 1000).onfinish = function () + { + div.style.display = "none"; + animInProgress = false; + finishedTrigger.trigger(); + finished.set(true); + }; +} + + +}; + +Ops.Html.Notification.prototype = new CABLES.Op(); +CABLES.OPS["cf3960f3-ced0-4928-9082-a9cf7f8573a6"]={f:Ops.Html.Notification,objName:"Ops.Html.Notification"}; + + + + +// ************************************************************** +// +// Ops.Html.PlayerControlPanel_v2 +// +// ************************************************************** + +Ops.Html.PlayerControlPanel_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"css_progressui_css":".progressUI\n{\n padding: 10px;\n position: absolute;\n border-radius: 10px;\n background-color: rgba(0,0,0,0.45);\n margin: 20px;\n bottom: 10px;\n height:30px;\n margin-left:50%;\n transform: translate(-50%);\n display: flex;\n align-items: center;\n}\n\n.progressUI .buttonContainer {\n display: flex;\n align-content: center;\n height: 100%;\n}\n\n.progressUI .progress\n{\n font-family: Monospace;\n float:left;\n color:white;\n width: auto;\n margin-left:15px;\n margin-right: 10px;\n}\n\n.progressUI .progressContainer\n{\n width:200px;\n overflow: hidden;\n background: rgba(0,0,0,0.4);\n border-radius: 4px;\n float:left;\n display: flex;\n flex-direction: row;\n align-items: center;\n height: 100%;\n}\n\n.progressUI .button\n{\n cursor: pointer;\n box-sizing: border-box;\n background: rgba(0,0,0,0.4);\n display: flex;\n align-content: center;\n padding: 5px;\n padding-left: 10px;\n padding-right: 10px;\n margin-right: 5px;\n border-radius: 5px;\n float:left;\n display: flex;\n align-items: center;\n}\n\n.progressUIIcon\n{\n display: inline-block;\n vertical-align: middle;\n width: 15px;\n height: 15px;\n background-color: white;\n -webkit-mask-repeat: no-repeat !important;\n -webkit-mask-size: 100% !important;\n}\n\n.progressUI .progressContainer .progressbar {\n height: 100%;\n width: 97%;\n}\n\n.progressUI_icon-play {\n -webkit-mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-play'%3E%3Cpath d='M5 3l14 9-14 9V3z'/%3E%3C/svg%3E\");\n mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-play'%3E%3Cpath d='M5 3l14 9-14 9V3z'/%3E%3C/svg%3E\");\n}\n\n.progressUI_icon-pause {\n -webkit-mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-pause'%3E%3Cpath d='M6 4h4v16H6zM14 4h4v16h-4z'/%3E%3C/svg%3E\");\n mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-pause'%3E%3Cpath d='M6 4h4v16H6zM14 4h4v16h-4z'/%3E%3C/svg%3E\");\n}\n\n.progressUI_icon-rewind {\n -webkit-mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-rewind'%3E%3Cpath d='M11 19l-9-7 9-7v14zM22 19l-9-7 9-7v14z'/%3E%3C/svg%3E\");\n mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-rewind'%3E%3Cpath d='M11 19l-9-7 9-7v14zM22 19l-9-7 9-7v14z'/%3E%3C/svg%3E\");\n}\n\n.progressUI_icon-fast-forward {\n -webkit-mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-fast-forward'%3E%3Cpath d='M13 19l9-7-9-7v14zM2 19l9-7-9-7v14z'/%3E%3C/svg%3E\");\n mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-fast-forward'%3E%3Cpath d='M13 19l9-7-9-7v14zM2 19l9-7-9-7v14z'/%3E%3C/svg%3E\");\n}\n\n.progressUI_icon-skip-back {\n -webkit-mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-skip-back'%3E%3Cpath d='M19 20L9 12l10-8v16zM5 19V5'/%3E%3C/svg%3E\");\n mask: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-skip-back'%3E%3Cpath d='M19 20L9 12l10-8v16zM5 19V5'/%3E%3C/svg%3E\");\n}\n",}; +const inMax = op.inFloat("Length", 30); +const inCurrent = op.inFloat("Current", 0); +const inClamp = op.inBool("Clamp", false); +const inIsPlaying = op.inBool("Is Playing", false); +const inVisible = op.inBool("Visible", true); +const inShowValue = op.inBool("Show Time"); +const inShowSkip = op.inBool("Show Skip Buttons"); + +const outPlay = op.outTrigger("Play clicked"); +const outPause = op.outTrigger("Pause clicked"); +const outRewind = op.outTrigger("Rewind clicked"); +const outBack = op.outTrigger("Skip Back clicked"); +const outForward = op.outTrigger("Skip Forward clicked"); + +const outDragged = op.outTrigger("Dragged"); +const outValue = op.outNumber("Current Value"); +const outDragging = op.outBoolNum("Dragging", false); +const outElement = op.outObject("DOM Element", null, "element"); + +let div = document.createElement("div"); +div.id = "progressUI_" + op.id; +div.classList.add("progressUI"); +outElement.set(div); + +const cgl = op.patch.cgl; +let canvas = op.patch.cgl.canvas.parentElement; +canvas.appendChild(div); + +let progressContainer = document.createElement("div"); +if (!inVisible.get()) +{ + div.style.display = "none"; +} +let progressbar = document.createElement("input"); +let progress = document.createElement("div"); +const buttonContainer = document.createElement("div"); + +progressContainer.classList.add("progressContainer"); + +progressContainer.appendChild(progressbar); + +progressbar.setAttribute("type", "range"); +progressbar.setAttribute("step", 0.01); +progressbar.setAttribute("min", 0); +progressbar.setAttribute("max", inMax.get()); +progressbar.setAttribute("value", inCurrent.get()); +progressbar.classList.add("progressbar"); +progressbar.addEventListener("input", handleInput); +let wasPlaying = false; +let isDragging = false; + +div.appendChild(buttonContainer); +div.appendChild(progressContainer); +div.appendChild(progress); + +let eleId = "css_progressui_" + CABLES.uuid(); + +const styleEle = document.createElement("style"); +styleEle.type = "text/css"; +styleEle.id = eleId; + +let head = document.getElementsByTagName("body")[0]; +head.appendChild(styleEle); + +buttonContainer.classList.add("buttonContainer"); + +let skipbackbutton = addButton("", "progressUI_icon-skip-back"); +buttonContainer.appendChild(skipbackbutton); + +let rewindButton = addButton("", "progressUI_icon-rewind", "skip"); +if (!inShowSkip.get()) +{ + rewindButton.style.display = "none"; +} +buttonContainer.appendChild(rewindButton); +rewindButton.addEventListener("pointerdown", () => +{ + outBack.trigger(); +}); + +let playButton = addButton("", "progressUI_icon-play"); +buttonContainer.appendChild(playButton); + +let forwardButton = addButton("", "progressUI_icon-fast-forward", "skip"); +if (!inShowSkip.get()) +{ + forwardButton.style.display = "none"; +} +buttonContainer.appendChild(forwardButton); + +forwardButton.addEventListener("pointerdown", () => +{ + outForward.trigger(); +}); + +progress.classList.add("progress"); +progress.innerHTML = "00:00:000"; + +function addButton(title, icon, additionalClass) +{ + let button = document.createElement("div"); + button.classList.add("button"); + button.classList.add(additionalClass); + button.innerHTML = title; + + if (icon) + { + let buttonicon = document.createElement("div"); + buttonicon.classList.add("progressUIIcon"); + buttonicon.classList.add(icon); + button.appendChild(buttonicon); + } + return button; +} + +inMax.onChange = () => +{ + progressbar.setAttribute("max", inMax.get()); +}; + +inVisible.onChange = () => +{ + if (inVisible.get()) + { + div.style.removeProperty("display"); + } + else + { + div.style.display = "none"; + } +}; + +inShowValue.onChange = () => +{ + if (inShowValue.get()) + { + div.classList.add("showValue"); + progress.style.display = "block"; + } + else + { + div.classList.remove("showValue"); + progress.style.display = "none"; + } +}; + +inShowSkip.onChange = () => +{ + if (inShowSkip.get()) + { + div.querySelectorAll(".button.skip").forEach((skip) => + { + skip.style.display = "block"; + }); + } + else + { + div.querySelectorAll(".button.skip").forEach((skip) => + { + skip.style.display = "none"; + }); + } +}; + +if (!inShowValue.get()) +{ + progress.style.display = "none"; +} +progressbar.addEventListener("pointerdown", () => +{ + isDragging = true; + if (inIsPlaying.get()) + { + wasPlaying = true; + outPause.trigger(); + updatePlayButton(); + } +}); +progressbar.addEventListener("pointermove", () => +{ + const currentProgress = progressbar.value; + if (isDragging) + { + outDragging.set(isDragging); + updateProgressDisplay(currentProgress); + outValue.set(currentProgress); + outDragged.trigger(); + } +}); + +progressbar.addEventListener("pointerup", () => +{ + const currentProgress = progressbar.value; + updateProgressDisplay(currentProgress); + outValue.set(currentProgress); + + if (isDragging) + { + outDragged.trigger(); + } + + isDragging = false; + outDragging.set(isDragging); + if (wasPlaying) + { + wasPlaying = false; + outPlay.trigger(); + updatePlayButton(); + } +}); + +function updateStyle() +{ + styleEle.textContent = attachments.css_progressui_css; +} + +function updatePlayButton() +{ + playButton.querySelector(".progressUIIcon").classList.remove("progressUI_icon-play"); + playButton.querySelector(".progressUIIcon").classList.remove("progressUI_icon-pause"); + if (inIsPlaying.get()) + { + playButton.querySelector(".progressUIIcon").classList.add("progressUI_icon-pause"); + } + else + { + playButton.querySelector(".progressUIIcon").classList.add("progressUI_icon-play"); + } +} + +playButton.addEventListener("pointerdown", function () +{ + if (inIsPlaying.get()) + { + outPause.trigger(); + } + else + { + outPlay.trigger(); + } + updatePlayButton(); +}); + +skipbackbutton.addEventListener("pointerdown", () => +{ + outValue.set(0); + outRewind.trigger(); +}); + +op.onDelete = function () +{ + if (div) div.remove(); + if (styleEle) styleEle.remove(); +}; + +function handleInput(e) +{ + inCurrent.onChange = null; + const newValue = e.target.value; + outValue.set(newValue); + inCurrent.onChange = currentValueChange; +} + +function currentValueChange() +{ + let currentValue = inCurrent.get(); + if (inClamp.get() && currentValue > inMax.get()) + { + currentValue = inMax.get(); + } + progressbar.value = currentValue; + outValue.set(currentValue); + updateProgressDisplay(); +} + +let lasttime = 0; +function updateProgressDisplay(currentValue = null) +{ + let displayValue = currentValue || inCurrent.get(); + let t = displayValue; + if (t != lasttime) + { + progress.innerHTML = formatValue(t); + lasttime = t; + } +} + +function formatValue(t) +{ + const minutes = String(new Date(t * 1000).getUTCMinutes()).padStart(2, "0"); + const seconds = String(new Date(t * 1000).getUTCSeconds()).padStart(2, "0"); + const millis = String(new Date(t * 1000).getUTCMilliseconds()).padStart(2, "0").padEnd(3, "0"); + const html = minutes + ":" + seconds + ":" + millis; + return html; +} + +updateStyle(); +updatePlayButton(); + +inCurrent.onChange = currentValueChange; +inIsPlaying.onChange = updatePlayButton; + + +}; + +Ops.Html.PlayerControlPanel_v2.prototype = new CABLES.Op(); +CABLES.OPS["12ac1d94-f043-454d-92a8-60733d2908b2"]={f:Ops.Html.PlayerControlPanel_v2,objName:"Ops.Html.PlayerControlPanel_v2"}; + + + + +// ************************************************************** +// +// Ops.Html.QrCode +// +// ************************************************************** + +Ops.Html.QrCode = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + text = op.inString("Text", "https://cables.gl"), + outDataUrl = op.outString("Image DataUrl"), + outElement=op.outObject("Element",null,"element"); + +const cgl = op.patch.cgl; +const parentEle = document.createElement("div"); +parentEle.id = "qrcode_" + CABLES.generateUUID(); +parentEle.style.display = "none"; +const body = document.getElementsByTagName("body")[0]; +body.appendChild(parentEle); + + +const img = document.createElement("img"); + + +text.onChange = generate; + +let qrCanvas=null; +generate(); + + +function generate() +{ + + while (parentEle.hasChildNodes()) + { + parentEle.removeChild(parentEle.lastChild); + } + const q=new QRCode(parentEle, { + "text": text.get(), + "width": 256, + "height": 256, + "colorDark": "#000000", + "colorLight": "#ffffff", + "correctLevel": QRCode.CorrectLevel.H + }); + + + + + qrCanvas = document.querySelector("#" + parentEle.id + " canvas"); + qrCanvas.style.display="block"; + + + + outElement.set(null); + outElement.set(img); + + const dataurl=qrCanvas.toDataURL("image/png"); + img.src=dataurl; + outDataUrl.set(dataurl); + +} + + +}; + +Ops.Html.QrCode.prototype = new CABLES.Op(); +CABLES.OPS["7e27a058-8162-4fd3-b08d-eba16f0fb551"]={f:Ops.Html.QrCode,objName:"Ops.Html.QrCode"}; + + + + +// ************************************************************** +// +// Ops.Html.QuerySelectorAll +// +// ************************************************************** + +Ops.Html.QuerySelectorAll = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inUpdate = op.inTriggerButton("Update"), + queryPort = op.inString("Query"), + inMode = op.inValueSelect("Mode", ["document", "string input"], "document"), + inMimeType = op.inValueSelect("Type", ["text/html", "text/xml"], "text/html"), + inSource = op.inStringEditor("Document", "xml"), + elementPort = op.outArray("Elements"); + +if (inMode.get() === "document") +{ + inSource.setUiAttribs({ "greyout": true }); + inMimeType.set("text/html"); + inMimeType.setUiAttribs({ "greyout": true }); +} + +inUpdate.onTriggered = +queryPort.onChange = +inMimeType.onChange = +inSource.onChange = update; + +inMode.onChange = modeChange; + +function update() +{ + const q = queryPort.get(); + const theDocument = inSource.get(); + const mode = inMode.get(); + if (mode === "string input" && theDocument) + { + let parser = new DOMParser(); + let htmlDoc = null; + try + { + htmlDoc = parser.parseFromString(theDocument, inMimeType.get()); + const el = Array.from(htmlDoc.querySelectorAll(q)); + elementPort.set(el); + } + catch (e) + { + op.logError(e); + } + } + else + { + try + { + const el = Array.from(document.querySelectorAll(q)); + elementPort.set(el); + } + catch (e) + { + op.logError(e); + } + } +} + +function modeChange() +{ + if (inMode.get() === "document") + { + inSource.setUiAttribs({ "greyout": true }); + inMimeType.set("text/html"); + inMimeType.setUiAttribs({ "greyout": true }); + } + else + { + inSource.setUiAttribs({ "greyout": false }); + inMimeType.setUiAttribs({ "greyout": false }); + } +} + + +}; + +Ops.Html.QuerySelectorAll.prototype = new CABLES.Op(); +CABLES.OPS["001799c7-9ddf-4f3e-b260-e865f0ed2c0e"]={f:Ops.Html.QuerySelectorAll,objName:"Ops.Html.QuerySelectorAll"}; + + + + +// ************************************************************** +// +// Ops.Html.QuerySelector_v2 +// +// ************************************************************** + +Ops.Html.QuerySelector_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inUpdate = op.inTriggerButton("Update"), + queryPort = op.inString("Query"), + inMode = op.inValueSelect("Mode", ["document", "string input"], "document"), + inMimeType = op.inValueSelect("Type", ["text/html", "text/xml"], "text/html"), + inSource = op.inStringEditor("Document", "xml"), + elementPort = op.outObject("Element"); + +if (inMode.get() === "document") +{ + inSource.setUiAttribs({ "greyout": true }); + inMimeType.set("text/html"); + inMimeType.setUiAttribs({ "greyout": true }); +} + +inUpdate.onTriggered = +queryPort.onChange = +inMimeType.onChange = +inSource.onChange = update; + +inMode.onChange = modeChange; + +function update() +{ + const q = queryPort.get(); + const theDocument = inSource.get(); + const mode = inMode.get(); + if (mode === "string input" && theDocument) + { + let parser = new DOMParser(); + let htmlDoc = null; + try + { + htmlDoc = parser.parseFromString(theDocument, inMimeType.get()); + const el = htmlDoc.querySelector(q); + elementPort.set(el); + } + catch (e) + { + op.logError(e); + } + } + else + { + try + { + const el = document.querySelector(q); + elementPort.set(el); + } + catch (e) + { + op.logError(e); + } + } +} + +function modeChange() +{ + if (inMode.get() === "document") + { + inSource.setUiAttribs({ "greyout": true }); + inMimeType.set("text/html"); + inMimeType.setUiAttribs({ "greyout": true }); + } + else + { + inSource.setUiAttribs({ "greyout": false }); + inMimeType.setUiAttribs({ "greyout": false }); + } +} + + +}; + +Ops.Html.QuerySelector_v2.prototype = new CABLES.Op(); +CABLES.OPS["a1a2189b-564c-4dd7-b3d9-a6cebc0cd94e"]={f:Ops.Html.QuerySelector_v2,objName:"Ops.Html.QuerySelector_v2"}; + + + + +// ************************************************************** +// +// Ops.Html.ReloadPage +// +// ************************************************************** + +Ops.Html.ReloadPage = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +var exec=op.inTrigger("Exec"); + +exec.onTriggered=function() +{ + location.reload(); + +}; + +}; + +Ops.Html.ReloadPage.prototype = new CABLES.Op(); +CABLES.OPS["d0060a4e-ffed-4a8d-8f6d-bfd9a23319de"]={f:Ops.Html.ReloadPage,objName:"Ops.Html.ReloadPage"}; + + + + +// ************************************************************** +// +// Ops.Html.RemoveAllClasses +// +// ************************************************************** + +Ops.Html.RemoveAllClasses = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe=op.inTriggerButton("Remove"); +const inName=op.inValueString("Classname"); + +exe.onTriggered=function() +{ + var els=document.getElementsByClassName(inName.get()); + + for(var i=0;i +{ + if (!inActive.get()) return next.trigger(); + + setProperties(); + next.trigger(); +}; + +op.onDelete = removeProperties; + +let oldEle = null; + +inAlignHor.onChange = + inAlignVert.onChange = + inRotate.onChange = + inScale.onChange = updateTransform; + +function updateTransform() +{ + const ele = inEle.get(); + if (!ele) + { + oldEle = null; + return; + } + + let translateStr = ""; + if (inAlignVert.get() == "Left")translateStr = "0%"; + if (inAlignVert.get() == "Center")translateStr = "-50%"; + if (inAlignVert.get() == "Right")translateStr = "-100%"; + + translateStr += ", "; + if (inAlignHor.get() == "Top")translateStr += "0%"; + if (inAlignHor.get() == "Center")translateStr += "-50%"; + if (inAlignHor.get() == "Bottom")translateStr += "-100%"; + + const str = "translate(" + translateStr + ") scale(" + inScale.get() + ") rotate(" + inRotate.get() + "deg)"; + + if (ele.style.transform != str) ele.style.transform = str; +} + +inEle.onChange = function () +{ + const ele = inEle.get(); + if (!ele) + { + removeProperties(oldEle); + + oldEle = null; + return; + } + + updateTransform(); + setProperties(); +}; + +inEle.onLinkChanged = function () +{ + cachedLeft = -1; + cachedTop = -1; + + if (!inEle.isLinked()) + { + if (oldEle) + { + removeProperties(oldEle); + } + } + else + { + oldEle = inEle.get(); + } + updateTransform(); +}; + +function getScreenCoord() +{ + mat4.multiply(m, cgl.vMatrix, cgl.mMatrix); + vec3.transformMat4(pos, [0, 0, 0], m); + vec3.transformMat4(trans, pos, cgl.pMatrix); + + const vp = cgl.getViewPort(); + + const w = cgl.canvasWidth / cgl.pixelDensity; + const h = cgl.canvasHeight / cgl.pixelDensity; + + if (inOrtho.get()) + { + x = ((w * 0.5 + trans[0] * w * 0.5 / 1)); + y = ((h * 0.5 - trans[1] * h * 0.5 / 1)); + } + else + { + x = (w - (w * 0.5 - trans[0] * w * 0.5)); // / trans[2] + y = (h - (h * 0.5 + trans[1] * h * 0.5)); // / trans[2] + } + + visible = pos[2] < 0.0 && x > 0 && x < vp[2] && y > 0 && y < vp[3]; +} + +function setProperties() +{ + const ele = inEle.get(); + oldEle = ele; + if (ele && ele.style) + { + getScreenCoord(); + const yy = cgl.canvas.offsetTop + y; + + if (yy != cachedTop) + { + ele.style.top = yy + "px"; + cachedTop = yy; + } + + if (x != cachedLeft) + { + ele.style.left = x + "px"; + cachedLeft = x; + } + + if (inHideBehind.get()) + { + if (visible)ele.style.display = "initial"; + else ele.style.display = "none"; + } + } +} + +function removeProperties(ele) +{ + cachedLeft = -1; + cachedTop = -1; + + if (!ele) ele = inEle.get(); + if (ele && ele.style) + { + ele.style.top = "initial"; + ele.style.left = "initial"; + ele.style.transform = "initial"; + } +} + +op.addEventListener("onEnabledChange", function (enabled) +{ + if (enabled) setProperties(); + else removeProperties(); +}); + + +}; + +Ops.Html.TransformElement.prototype = new CABLES.Op(); +CABLES.OPS["caca0307-d460-47df-8674-b7d2601239ab"]={f:Ops.Html.TransformElement,objName:"Ops.Html.TransformElement"}; + + + + +// ************************************************************** +// +// Ops.Html.VideoElement +// +// ************************************************************** + +Ops.Html.VideoElement = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + // src=op.inString("URL",'https://undev.studio'), + src = op.inUrl("File", null, ""), + elId = op.inString("ID"), + play = op.inBool("Play"), + controls = op.inBool("Controls", true), + active = op.inBool("Active", true), + loop = op.inBool("Loop", false), + inMuted = op.inBool("Muted", false), + inStyle = op.inStringEditor("Style", "position:absolute;\nz-index:9999;\nborder:0;\nwidth:50%;\nheight:50%;"), + rewind = op.inTriggerButton("Rewind"), + outEle = op.outObject("Element"), + outPlaying = op.outBool("Playing"), + outCanplaythrough = op.outBool("Can Play Through"), + outTime = op.outNumber("Time"), + outEnded = op.outTrigger("Ended"), + outHasError = op.outBool("Has Error"), + outError = op.outString("Error Message"); +op.setPortGroup("Attributes", [src, elId]); + +let element = document.createElement("video"); +let timeOut = null; + +op.onDelete = removeEle; + +op.onLoaded = init; + +function init() +{ + addElement(); + updateSoon(); + + inStyle.onChange = + src.onChange = + elId.onChange = updateSoon; + + active.onChange = updateActive; +} + +init(); + +loop.onChange = +controls.onChange = +inMuted.onChange = updateVideoSettings; + +function updateVideoSettings() +{ + if (!element) return; + if (controls.get()) element.controls = "true"; + else + { + element.controls = "true"; + element.removeAttribute("controls"); + } + + if (loop.get()) element.loop = "true"; + else element.removeAttribute("loop"); + + if (inMuted.get()) element.muted = "true"; + else element.removeAttribute("muted"); +} + +function updatePlay() +{ + if (!element) return; + if (play.get())element.play(); + else element.pause(); +} + +play.onChange = () => +{ + updatePlay(); +}; + +rewind.onTriggered = function () +{ + if (element) element.currentTime = 0; +}; + +function addElement() +{ + if (!active.get()) return; + if (element) removeEle(); + element = document.createElement("video"); + element.setAttribute("playsinline", ""); + element.setAttribute("webkit-playsinline", ""); + element.preload = "true"; + updateVideoSettings(); + element.setAttribute("crossOrigin", "anonymous"); + outCanplaythrough.set(false); + + outHasError.set(false); + outError.set(""); + + element.addEventListener("canplaythrough", () => + { + outCanplaythrough.set(true); + }, true); + element.addEventListener("play", () => + { + outPlaying.set(true); + }, true); + element.addEventListener("ended", () => + { + outEnded.trigger(); + }, true); + element.addEventListener("pause", () => + { + outPlaying.set(false); + }, true); + + element.addEventListener("timeupdate", () => + { + if (element)outTime.set(element.currentTime); + }, true); + + element.onerror = function () + { + outHasError.set(true); + if (element && element.error) + { + outError.set("Error " + element.error.code + "/" + element.error.message); + op.log("Error " + element.error.code + "; details: " + element.error.message); + } + }; + + // element.playbackRate = speed.get(); + // if (!addedListeners) + // { + // addedListeners = true; + // element.addEventListener("canplaythrough", initVideo, true); + // element.addEventListener("loadedmetadata", loadedMetaData); + // element.addEventListener("playing", function () { videoElementPlaying = true; }, true); + // } + + updateAttribs(); + const parent = op.patch.cgl.canvas.parentElement; + parent.appendChild(element); + + updateVideoSettings(); + + if (play.get())updatePlay(); + + outEle.set(element); +} + +function updateSoon() +{ + clearTimeout(timeOut); + timeOut = setTimeout(updateAttribs, 30); +} + +function updateAttribs() +{ + if (!element || !src.get()) return; + element.setAttribute("style", inStyle.get()); + element.setAttribute("src", src.get()); + element.setAttribute("id", elId.get()); +} + +function removeEle() +{ + if (element && element.parentNode)element.parentNode.removeChild(element); + element = null; + outEle.set(element); +} + +function updateActive() +{ + if (!active.get()) + { + removeEle(); + return; + } + + addElement(); +} + + +}; + +Ops.Html.VideoElement.prototype = new CABLES.Op(); +CABLES.OPS["5315a156-3a4f-4ff3-80c7-1b73c839d388"]={f:Ops.Html.VideoElement,objName:"Ops.Html.VideoElement"}; + + + + +// ************************************************************** +// +// Ops.Html.WindowClose +// +// ************************************************************** + +Ops.Html.WindowClose = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec=op.inTriggerButton("Close"); + +inExec.onTriggered=function() +{ + window.close(); +}; + +}; + +Ops.Html.WindowClose.prototype = new CABLES.Op(); +CABLES.OPS["4f5d56b9-28a0-47fe-86f7-7b765268d694"]={f:Ops.Html.WindowClose,objName:"Ops.Html.WindowClose"}; + + + + +// ************************************************************** +// +// Ops.Html.WindowHasFocus +// +// ************************************************************** + +Ops.Html.WindowHasFocus = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + outFocussed = op.outBool("has focus"), + outVisible = op.outBool("Tab Visible", true); + +const focused = true; + +outFocussed.set(document.hasFocus()); + +window.addEventListener("blur", handleBlur); +window.addEventListener("focus", handleFocus); + +document.addEventListener("visibilitychange", updateVisibility); + +op.onDelete = function () +{ + document.removeEventListener("visibilitychange", updateVisibility); +}; + +function handleFocus() +{ + outFocussed.set(true); +} + +function handleBlur() +{ + outFocussed.set(false); +} + +function updateVisibility(e) +{ + outVisible.set(!document.hidden); +} + + +}; + +Ops.Html.WindowHasFocus.prototype = new CABLES.Op(); +CABLES.OPS["6542896e-aa13-4b57-81e0-163597f4149a"]={f:Ops.Html.WindowHasFocus,objName:"Ops.Html.WindowHasFocus"}; + + + + +// ************************************************************** +// +// Ops.Html.WindowInfo +// +// ************************************************************** + +Ops.Html.WindowInfo = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + outWidth = op.outNumber("clientWidth"), + outHeight = op.outNumber("clientHeight"), + outHeightBody = op.outNumber("body scroll Height"), + outIframeChild = op.outBoolNum("Iframe Parent", window.top != window.self); + +window.addEventListener("resize", update); + +update(); + +function update() +{ + outWidth.set(window.innerWidth); + outHeight.set(window.innerHeight); + + outHeightBody.set(document.documentElement.scrollHeight); +} + + +}; + +Ops.Html.WindowInfo.prototype = new CABLES.Op(); +CABLES.OPS["9655045c-3539-457d-be65-a1456a58906a"]={f:Ops.Html.WindowInfo,objName:"Ops.Html.WindowInfo"}; + + + + +// ************************************************************** +// +// Ops.Html.YoutubePlayer +// +// ************************************************************** + +Ops.Html.YoutubePlayer = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + src = op.inString("Video Id", "dQw4w9WgXcQ"), + active = op.inBool("Active", true), + inStyle = op.inStringEditor("Style"), + elId = op.inString("ElementID"), + paramAutoplay = op.inBool("Autoplay", false), + paramCC = op.inBool("Display Captions", false), + paramLoop = op.inBool("Loop", false), + paramFs = op.inBool("Allow Fullscreen", true), + paramControls = op.inBool("Hide Controls", false), + paramStart = op.inInt("Start at Second", 0), + + outEle = op.outObject("Element"), + outDirectLink = op.outString("Direct Link"); + // outImageMax=op.outString("Thumbnail Max"); + +const defaultStyle = "position:absolute;\n\ +z-index:9;\n\ +border:0;\n"; + +op.setPortGroup("Youtube Options", [paramAutoplay, paramCC, paramLoop, paramFs, paramControls, paramStart]); + +// https://developers.google.com/youtube/player_parameters + +let element = null; +let initialized = false; + +paramStart.onChange = + paramAutoplay.onChange = + paramCC.onChange = + paramLoop.onChange = + paramFs.onChange = + paramControls.onChange = + src.onChange = updateURL; + +elId.onChange = updateID; +inStyle.onChange = updateStyle; +op.onDelete = removeEle; + +active.onChange = update; + +op.init = function () +{ + initialized = true; + setTimeout(() => { update(); }, 100); +}; + +inStyle.set(defaultStyle); + +function update() +{ + if (!active.get()) + { + removeEle(); + return; + } + + addElement(); +} + +function addElement() +{ + if (!initialized) return; + if (element) removeEle(); + + const parent = op.patch.cgl.canvas.parentElement; + element = document.createElement("iframe"); + element.dataset.op = op.id; + element.style.position = "absolute"; + element.allowfullscreen = true; + element.frameborder = 0; + element.allow = "accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"; + + parent.appendChild(element); + + updateURL(); + updateID(); + updateStyle(); + + outEle.set(null); + outEle.set(element); +} + +function removeEle() +{ + if (element && element.parentNode) element.parentNode.removeChild(element); + element = null; + outEle.set(null); +} + +function updateURL() +{ + if (src.get()) outDirectLink.set("https://www.youtube.com/watch?v=" + src.get()); + + if (!initialized) return; + if (!active.get()) return; + const urlParams = []; + + if (paramAutoplay.get()) urlParams.push("autoplay=1"); + if (paramCC.get()) urlParams.push("cc_load_policy=1"); + if (paramLoop.get()) urlParams.push("loop=1"); + if (paramFs.get()) urlParams.push("fs=1"); + if (paramControls.get()) urlParams.push("controls=0"); + if (paramStart.get() > 0) urlParams.push("start=" + paramStart.get()); + + let urlParamsStr = ""; + if (urlParams.length > 0) urlParamsStr = "?" + urlParams.join("&") + "&rel=0"; + + const urlStr = "https://www.youtube.com/embed/" + src.get() + urlParamsStr; + if (element) + element.setAttribute("src", urlStr); +} + +function updateID() +{ + if (!active.get()) return; + if (element) element.setAttribute("id", elId.get()); +} + +function updateStyle() +{ + if (!active.get()) return; + if (element) element.style = inStyle.get(); +} + + +}; + +Ops.Html.YoutubePlayer.prototype = new CABLES.Op(); +CABLES.OPS["b60ad395-d6ad-4309-86c5-c6bbffaf176c"]={f:Ops.Html.YoutubePlayer,objName:"Ops.Html.YoutubePlayer"}; + + + + +// ************************************************************** +// +// Ops.Json.AjaxRequest_v2 +// +// ************************************************************** + +Ops.Json.AjaxRequest_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const filename = op.inUrl("file"), + jsonp = op.inValueBool("JsonP", false), + headers = op.inObject("headers", {}), + inBody = op.inStringEditor("body", ""), + inMethod = op.inDropDown("HTTP Method", ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "CONNECT", "OPTIONS", "TRACE"], "GET"), + inContentType = op.inString("Content-Type", "application/json"), + inParseJson = op.inBool("parse json", true), + inAutoRequest = op.inBool("Auto request", true), + reloadTrigger = op.inTriggerButton("reload"), + outData = op.outObject("data"), + outString = op.outString("response"), + isLoading = op.outBoolNum("Is Loading", false), + outTrigger = op.outTrigger("Loaded"); + +filename.setUiAttribs({ "title": "URL" }); +reloadTrigger.setUiAttribs({ "buttonTitle": "trigger request" }); + +outData.ignoreValueSerialize = true; +outString.ignoreValueSerialize = true; + +inAutoRequest.onChange = filename.onChange = jsonp.onChange = headers.onChange = inMethod.onChange = inParseJson.onChange = function () +{ + delayedReload(false); +}; + +reloadTrigger.onTriggered = function () +{ + delayedReload(true); +}; + +let loadingId = 0; +let reloadTimeout = 0; + +function delayedReload(force = false) +{ + clearTimeout(reloadTimeout); + reloadTimeout = setTimeout(function () { reload(null, force); }, 100); +} + +op.onFileChanged = function (fn) +{ + if (filename.get() && filename.get().indexOf(fn) > -1) reload(true); +}; + +function reload(addCachebuster, force = false) +{ + if (!inAutoRequest.get() && !force) return; + if (!filename.get()) return; + + op.patch.loading.finished(loadingId); + + loadingId = op.patch.loading.start("jsonFile", "" + filename.get()); + isLoading.set(true); + + op.setUiAttrib({ "extendTitle": CABLES.basename(filename.get()) }); + op.setUiError("jsonerr", null); + + let httpClient = CABLES.ajax; + if (jsonp.get()) httpClient = CABLES.jsonp; + + let url = op.patch.getFilePath(filename.get()); + if (addCachebuster)url += "?rnd=" + CABLES.generateUUID(); + + op.patch.loading.addAssetLoadingTask(() => + { + const body = inBody.get(); + httpClient( + url, + (err, _data, xhr) => + { + outData.set(null); + outString.set(null); + if (err) + { + op.patch.loading.finished(loadingId); + isLoading.set(false); + + op.logError(err); + return; + } + try + { + let data = _data; + if (typeof data === "string" && inParseJson.get()) + { + data = JSON.parse(_data); + outData.set(data); + } + outString.set(_data); + op.uiAttr({ "error": null }); + op.patch.loading.finished(loadingId); + outTrigger.trigger(); + isLoading.set(false); + } + catch (e) + { + op.logError(e); + op.setUiError("jsonerr", "Problem while loading json:
" + e); + op.patch.loading.finished(loadingId); + isLoading.set(false); + } + }, + inMethod.get(), + (body && body.length > 0) ? body : null, + inContentType.get(), + null, + headers.get() || {} + ); + }); +} + + +}; + +Ops.Json.AjaxRequest_v2.prototype = new CABLES.Op(); +CABLES.OPS["e0879058-5505-4dc4-b9ff-47a3d3c8a71a"]={f:Ops.Json.AjaxRequest_v2,objName:"Ops.Json.AjaxRequest_v2"}; + + + + +// ************************************************************** +// +// Ops.Json.ArrayGetArrayByPath +// +// ************************************************************** + +Ops.Json.ArrayGetArrayByPath = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const objectIn = op.inArray("Array"); +const pathIn = op.inString("Path"); +const resultOut = op.outArray("Output"); +const foundOut = op.outBool("Found"); + +objectIn.onChange = update; +pathIn.onChange = update; + +function update() +{ + const data = objectIn.get(); + const path = pathIn.get(); + op.setUiError("missing", null); + if (data && path) + { + if (!Array.isArray(data) && !(typeof data === "object")) + { + foundOut.set(false); + op.setUiError("notiterable", "input object of type " + (typeof data) + " is not travesable by path"); + } + else + { + op.setUiError("notiterable", null); + const parts = path.split("."); + op.setUiAttrib({ "extendTitle": parts[parts.length - 1] + "" }); + let result = resolve(path, data); + if (result === undefined) + { + const errorMsg = "could not find element at path " + path; + foundOut.set(false); + result = null; + op.setUiError("missing", errorMsg, 2); + } + else if (!Array.isArray(result)) + { + const errorMsg = "element at path " + path + " is not an array"; + foundOut.set(false); + result = null; + op.setUiError("missing", errorMsg, 2); + } + else + { + foundOut.set(true); + } + resultOut.set(result); + } + } + else + { + foundOut.set(false); + } +} + +function resolve(path, obj = self, separator = ".") +{ + const properties = Array.isArray(path) ? path : path.split(separator); + return properties.reduce((prev, curr) => prev && prev[curr], obj); +} + + +}; + +Ops.Json.ArrayGetArrayByPath.prototype = new CABLES.Op(); +CABLES.OPS["f8fd1e41-d56a-4046-83a1-2ca194c828fc"]={f:Ops.Json.ArrayGetArrayByPath,objName:"Ops.Json.ArrayGetArrayByPath"}; + + + + +// ************************************************************** +// +// Ops.Json.ArrayGetArrayValuesByPath +// +// ************************************************************** + +Ops.Json.ArrayGetArrayValuesByPath = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const objectIn = op.inArray("Array"); +const pathIn = op.inString("Path"); +const resultOut = op.outArray("Output"); +const foundOut = op.outBool("Found"); + +objectIn.onChange = update; +pathIn.onChange = update; + +function update() +{ + const data = objectIn.get(); + let result = []; + const path = pathIn.get(); + op.setUiError("path", null); + + if (data && path) + { + if (!Array.isArray(data)) + { + foundOut.set(false); + op.setUiError("notiterable", "input of type " + (typeof data) + " is not an array"); + } + else + { + op.setUiError("notiterable", null); + const parts = path.split("."); + foundOut.set(false); + + const pathSuffix = parts.slice(1).join("."); + + for (let i = 0; i < data.length; i++) + { + const resolvePath = i + "." + pathSuffix; + const resolvedData = resolve(resolvePath, data); + if (typeof resolvedData !== "undefined") + { + foundOut.set(true); + } + result.push(resolvedData); + } + const titleParts = pathIn.get().split("."); + op.setUiAttrib({ "extendTitle": titleParts[titleParts.length - 1] + "" }); + if (foundOut.get()) + { + resultOut.set(result); + } + else + { + op.setUiError("path", "given path seems to be invalid!", 1); + resultOut.set([]); + } + } + } + else + { + foundOut.set(false); + } +} + +function resolve(path, obj = self, separator = ".") +{ + const properties = Array.isArray(path) ? path : path.split(separator); + return properties.reduce((prev, curr) => prev && prev[curr], obj); +} + + +}; + +Ops.Json.ArrayGetArrayValuesByPath.prototype = new CABLES.Op(); +CABLES.OPS["f4aa5756-c681-47ac-a997-b4f91760db96"]={f:Ops.Json.ArrayGetArrayValuesByPath,objName:"Ops.Json.ArrayGetArrayValuesByPath"}; + + + + +// ************************************************************** +// +// Ops.Json.ArrayGetNumberByPath +// +// ************************************************************** + +Ops.Json.ArrayGetNumberByPath = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const objectIn = op.inArray("Array"); +const pathIn = op.inString("Path"); +const resultOut = op.outNumber("Output"); +const foundOut = op.outBool("Found"); + +objectIn.onChange = update; +pathIn.onChange = update; + +function update() +{ + const data = objectIn.get(); + const path = pathIn.get(); + op.setUiError("missing", null); + if (data && path) + { + if (!Array.isArray(data) && !(typeof data === "object")) + { + foundOut.set(false); + op.setUiError("notiterable", "input object of type " + (typeof data) + " is not travesable by path"); + } + else + { + op.setUiError("notiterable", null); + const parts = path.split("."); + op.setUiAttrib({ "extendTitle": parts[parts.length - 1] + "" }); + let result = resolve(path, data); + if (result === undefined) + { + const errorMsg = "could not find element at path " + path; + foundOut.set(false); + result = null; + op.setUiError("missing", errorMsg, 2); + } + else if (typeof result !== "number") + { + const errorMsg = "element at path " + path + " is not a number"; + foundOut.set(false); + result = null; + op.setUiError("missing", errorMsg, 2); + } + else + { + foundOut.set(true); + } + resultOut.set(result); + } + } + else + { + foundOut.set(false); + } +} + +function resolve(path, obj = self, separator = ".") +{ + const properties = Array.isArray(path) ? path : path.split(separator); + return properties.reduce((prev, curr) => prev && prev[curr], obj); +} + + +}; + +Ops.Json.ArrayGetNumberByPath.prototype = new CABLES.Op(); +CABLES.OPS["9a8ac7c9-dc88-44cb-b4f7-fead5ebb9ed7"]={f:Ops.Json.ArrayGetNumberByPath,objName:"Ops.Json.ArrayGetNumberByPath"}; + + + + +// ************************************************************** +// +// Ops.Json.ArrayGetObjectByPath +// +// ************************************************************** + +Ops.Json.ArrayGetObjectByPath = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const objectIn = op.inArray("Array"); +const pathIn = op.inString("Path"); +const resultOut = op.outObject("Output"); +const foundOut = op.outBool("Found"); + +objectIn.onChange = update; +pathIn.onChange = update; + +function update() +{ + const data = objectIn.get(); + const path = pathIn.get(); + op.setUiError("missing", null); + if (data && path) + { + if (!Array.isArray(data) && !(typeof data === "object")) + { + foundOut.set(false); + op.setUiError("notiterable", "input object of type " + (typeof data) + " is not travesable by path"); + } + else + { + op.setUiError("notiterable", null); + const parts = path.split("."); + op.setUiAttrib({ "extendTitle": parts[parts.length - 1] + "" }); + let result = resolve(path, data); + if (result === undefined) + { + const errorMsg = "could not find element at path " + path; + foundOut.set(false); + result = null; + op.setUiError("missing", errorMsg, 2); + } + else if (Array.isArray(result) || result === null || typeof result !== "object") + { + const errorMsg = "element at path " + path + " is not an object"; + foundOut.set(false); + result = null; + op.setUiError("missing", errorMsg, 2); + } + else + { + foundOut.set(true); + } + resultOut.set(result); + } + } + else + { + foundOut.set(false); + } +} + +function resolve(path, obj = self, separator = ".") +{ + const properties = Array.isArray(path) ? path : path.split(separator); + return properties.reduce((prev, curr) => prev && prev[curr], obj); +} + + +}; + +Ops.Json.ArrayGetObjectByPath.prototype = new CABLES.Op(); +CABLES.OPS["c73970f0-f8fb-4d12-af19-649d17b0195f"]={f:Ops.Json.ArrayGetObjectByPath,objName:"Ops.Json.ArrayGetObjectByPath"}; + + + + +// ************************************************************** +// +// Ops.Json.ArrayGetStringByPath +// +// ************************************************************** + +Ops.Json.ArrayGetStringByPath = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const objectIn = op.inArray("Array"); +const pathIn = op.inString("Path"); +const returnPathIn = op.inBool("Return path if missing", false); +const resultOut = op.outString("Output"); +const foundOut = op.outBool("Found"); + +objectIn.onChange = update; +pathIn.onChange = update; +returnPathIn.onChange = update; + +function update() +{ + const data = objectIn.get(); + const path = pathIn.get(); + op.setUiError("missing", null); + if (data && path) + { + if (!Array.isArray(data) && !(typeof data === "object")) + { + foundOut.set(false); + op.setUiError("notiterable", "input object of type " + (typeof data) + " is not travesable by path"); + } + else + { + op.setUiError("notiterable", null); + const parts = path.split("."); + op.setUiAttrib({ "extendTitle": parts[parts.length - 1] + "" }); + let result = resolve(path, data); + if (result === undefined) + { + const errorMsg = "could not find element at path " + path; + let errorLevel = 2; + result = null; + foundOut.set(false); + if (returnPathIn.get()) + { + result = path; + errorLevel = 1; + } + else + { + result = null; + } + op.setUiError("missing", errorMsg, errorLevel); + } + else + { + foundOut.set(true); + result = String(result); + } + resultOut.set(result); + } + } + else + { + foundOut.set(false); + } +} + +function resolve(path, obj = self, separator = ".") +{ + const properties = Array.isArray(path) ? path : path.split(separator); + return properties.reduce((prev, curr) => prev && prev[curr], obj); +} + + +}; + +Ops.Json.ArrayGetStringByPath.prototype = new CABLES.Op(); +CABLES.OPS["064fc275-f61d-4c5f-9692-28c2062248bf"]={f:Ops.Json.ArrayGetStringByPath,objName:"Ops.Json.ArrayGetStringByPath"}; + + + + +// ************************************************************** +// +// Ops.Json.CsvArray +// +// ************************************************************** + +Ops.Json.CsvArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + filename = op.inUrl("file"), + result = op.outArray("result"), + len = op.outNumber("num items"); + +const reload = function () +{ + CABLES.ajax( + op.patch.getFilePath(filename.get()), + function (err, _data, xhr) + { + try + { + const data = JSON.parse(_data); + result.set(data); + len.set(data.length); + } + catch (e) + { + op.logError(e); + result.set(null); + len.set(0); + } + }); +}; + +filename.onChange = reload; + + +}; + +Ops.Json.CsvArray.prototype = new CABLES.Op(); +CABLES.OPS["2e76c1f8-19ac-4e9d-8db8-58b2f9fbc1d3"]={f:Ops.Json.CsvArray,objName:"Ops.Json.CsvArray"}; + + + + +// ************************************************************** +// +// Ops.Json.CsvColumnArray_v2 +// +// ************************************************************** + +Ops.Json.CsvColumnArray_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + colName = op.inString("Column Name", "name"), + inArr = op.inArray("CSV Array"), + inNumbers = op.inBool("Numbers", false), + result = op.outArray("Result"); + +colName.onChange = +inNumbers.onChange = + inArr.onChange = update; + +function update() +{ + let iArr = inArr.get(); + let iName = colName.get(); + + if (!iArr) + { + result.set(null); + return; + } + + op.setUiError("notfound", null); + op.setUiError("notnum", null); + + if (iArr[0].hasOwnProperty(iName)) + { + let arr = []; + + let hasStrings = false; + + if (inNumbers.get()) + { + for (let i = 0; i < iArr.length; i++) + { + let n = Number(iArr[i][iName] || 0); + arr.push(n); + if (!CABLES.UTILS.isNumeric(iArr[i][iName])) + { + hasStrings = true; + } + } + + if (hasStrings) + { + op.setUiError("notnum", "Parse Error / Not all values numerical!"); + } + } + else + { + for (let i = 0; i < iArr.length; i++) + arr.push(iArr[i][iName]); + } + result.set(arr); + } + else + op.setUiError("notfound", "Column not found"); +} + + +}; + +Ops.Json.CsvColumnArray_v2.prototype = new CABLES.Op(); +CABLES.OPS["2503021e-1599-40d9-b038-bf5a36c6b2c7"]={f:Ops.Json.CsvColumnArray_v2,objName:"Ops.Json.CsvColumnArray_v2"}; + + + + +// ************************************************************** +// +// Ops.Json.FilterValidObject +// +// ************************************************************** + +Ops.Json.FilterValidObject = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inObj=op.inObject("Object"), + outObject=op.outObject("Last Valid Object"), + outValid=op.outBool("Is Valid"); + +inObj.onChange= + update; + + +function update() +{ + const obj=inObj.get(); + + var r=true; + + if(!obj) r=false; + + if(r) outObject.set(obj); + + outValid.set(r); +} + +}; + +Ops.Json.FilterValidObject.prototype = new CABLES.Op(); +CABLES.OPS["a851cddb-74e5-41e7-ac75-709beae914fd"]={f:Ops.Json.FilterValidObject,objName:"Ops.Json.FilterValidObject"}; + + + + +// ************************************************************** +// +// Ops.Json.GateObject +// +// ************************************************************** + +Ops.Json.GateObject = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + valueInPort = op.inObject("Object In"), + passThroughPort = op.inValueBool("Pass Through", false), + onlyValid = op.inValueBool("Only Valid Objects", false), + valueOutPort = op.outObject("Object Out"); + +valueInPort.onChange = + passThroughPort.onChange = update; +valueInPort.changeAlways = true; + +function update() +{ + if (!valueInPort.get() && onlyValid.get()) return; + if (passThroughPort.get()) valueOutPort.set(valueInPort.get()); + // else valueOutPort.set(null); +} + + +}; + +Ops.Json.GateObject.prototype = new CABLES.Op(); +CABLES.OPS["95e04331-49d6-42da-81d8-5a75261ab22f"]={f:Ops.Json.GateObject,objName:"Ops.Json.GateObject"}; + + + + +// ************************************************************** +// +// Ops.Json.GetStringFromObject +// +// ************************************************************** + +Ops.Json.GetStringFromObject = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + data = op.inObject("data"), + key = op.inString("key"), + result = op.outString("result"); + +result.ignoreValueSerialize = true; +data.ignoreValueSerialize = true; + +data.onChange = exec; + +key.onChange = function () +{ + op.setUiAttrib({ "extendTitle": key.get() }); + exec(); +}; + +function exec() +{ + const dat = data.get(); + const theKey = key.get(); + + if (dat && dat.hasOwnProperty(theKey)) result.set(dat[theKey]); + else result.set(null); +} + + +}; + +Ops.Json.GetStringFromObject.prototype = new CABLES.Op(); +CABLES.OPS["6562a543-2147-485d-8fd3-58fe3357684e"]={f:Ops.Json.GetStringFromObject,objName:"Ops.Json.GetStringFromObject"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectFilterContentByKey +// +// ************************************************************** + +Ops.Json.ObjectFilterContentByKey = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inObj=op.inObject("Object"), + inStr=op.inString("name",""), + inRemoveNull=op.inBool("Remove Null",false), + outObj=op.outObject("Result"); + +inObj.onChange= + inStr.onChange= + inRemoveNull.onChange=update; + +function update() +{ + const obj=JSON.parse(JSON.stringify(inObj.get())); + + filter(obj); + + outObj.set(null); + outObj.set(obj); +} + +function filter(obj) +{ + for(let i in obj) + { + if(inStr.get() && i.indexOf(inStr.get())!==0)delete obj[i]; + if(inRemoveNull.get() && obj[i]===null)delete obj[i]; + + if(typeof obj[i] =="object") filter(obj[i]); + } +} + +}; + +Ops.Json.ObjectFilterContentByKey.prototype = new CABLES.Op(); +CABLES.OPS["89bddc38-000b-4982-8b37-b6e48f0b001b"]={f:Ops.Json.ObjectFilterContentByKey,objName:"Ops.Json.ObjectFilterContentByKey"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectFunnel +// +// ************************************************************** + +Ops.Json.ObjectFunnel = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inObj1 = op.inObject("Object1"), + inObj2 = op.inObject("Object2"), + inObj3 = op.inObject("Object3"), + inObj4 = op.inObject("Object4"), + inObj5 = op.inObject("Object5"); + +let outObj = op.outObject("Out Object"); + +inObj1.onChange = function () +{ + outObj.set(null); + outObj.set(inObj1.get()); +}; + +inObj2.onChange = function () +{ + outObj.set(null); + outObj.set(inObj2.get()); +}; + +inObj3.onChange = function () +{ + outObj.set(null); + outObj.set(inObj3.get()); +}; + +inObj4.onChange = function () +{ + outObj.set(null); + outObj.set(inObj4.get()); +}; + +inObj5.onChange = function () +{ + outObj.set(null); + outObj.set(inObj5.get()); +}; + + +}; + +Ops.Json.ObjectFunnel.prototype = new CABLES.Op(); +CABLES.OPS["ff67d867-098e-4eb1-8b37-00ec0863ce5e"]={f:Ops.Json.ObjectFunnel,objName:"Ops.Json.ObjectFunnel"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectGetArrayByPath +// +// ************************************************************** + +Ops.Json.ObjectGetArrayByPath = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const objectIn = op.inObject("Object"); +const pathIn = op.inString("Path"); +const resultOut = op.outArray("Output"); +const foundOut = op.outBool("Found"); + +objectIn.onChange = update; +pathIn.onChange = update; + +function update() +{ + const data = objectIn.get(); + const path = pathIn.get(); + op.setUiError("missing", null); + if (data && path) + { + if (!Array.isArray(data) && !(typeof data === "object")) + { + foundOut.set(false); + op.setUiError("notiterable", "input object of type " + (typeof data) + " is not travesable by path"); + } + else + { + op.setUiError("notiterable", null); + const parts = path.split("."); + op.setUiAttrib({ "extendTitle": parts[parts.length - 1] + "" }); + let result = resolve(path, data); + if (result === undefined) + { + const errorMsg = "could not find element at path " + path; + foundOut.set(false); + result = null; + op.setUiError("missing", errorMsg, 2); + } + else if (!Array.isArray(result)) + { + const errorMsg = "element at path " + path + " is not an array"; + foundOut.set(false); + result = null; + op.setUiError("missing", errorMsg, 2); + } + else + { + foundOut.set(true); + } + resultOut.set(result); + } + } + else + { + foundOut.set(false); + } +} + +function resolve(path, obj = self, separator = ".") +{ + const properties = Array.isArray(path) ? path : path.split(separator); + return properties.reduce((prev, curr) => prev && prev[curr], obj); +} + + +}; + +Ops.Json.ObjectGetArrayByPath.prototype = new CABLES.Op(); +CABLES.OPS["a9354531-a42d-4216-ad8c-364df989a9a1"]={f:Ops.Json.ObjectGetArrayByPath,objName:"Ops.Json.ObjectGetArrayByPath"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectGetArrayValuesByPath +// +// ************************************************************** + +Ops.Json.ObjectGetArrayValuesByPath = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const objectIn = op.inObject("Object"); +const pathIn = op.inString("Path"); +const resultOut = op.outArray("Output"); +const foundOut = op.outBool("Found"); + +objectIn.onChange = update; +pathIn.onChange = update; + +function update() +{ + const data = objectIn.get(); + let result = []; + const path = pathIn.get(); + op.setUiError("path", null); + + if (data && path) + { + if (typeof data !== "object") + { + foundOut.set(false); + op.setUiError("notiterable", "input object of type " + (typeof data) + " is not travesable by path"); + } + else if (Array.isArray(data)) + { + foundOut.set(false); + op.setUiError("notiterable", "input of type " + (typeof data) + " is not an object"); + } + else + { + op.setUiError("notiterable", null); + const parts = path.split("."); + foundOut.set(false); + + // find first array in path + let checkPath = ""; + let pathPrefix = ""; + let pathSuffix = ""; + let checkData = null; + for (let i = 0; i < parts.length; i++) + { + checkPath += parts[i]; + checkData = resolve(checkPath, data); + if (Array.isArray(checkData)) + { + pathPrefix = checkPath; + pathSuffix = parts.splice(i + 2, parts.length - (i + 2)).join("."); + break; + } + checkPath += "."; + } + if (checkData) + { + if (parts.length > 1) + { + for (let i = 0; i < checkData.length; i++) + { + let resolvePath = pathPrefix + "." + i; + if (pathSuffix && pathSuffix !== "") + { + resolvePath += "." + pathSuffix; + } + const resolvedData = resolve(resolvePath, data); + if (typeof resolvedData !== "undefined") + { + foundOut.set(true); + } + result.push(resolvedData); + } + } + else + { + if (Array.isArray(checkData)) + { + result = checkData; + } + else + { + result = [checkData]; + } + foundOut.set(true); + } + + const titleParts = pathIn.get().split("."); + const extendTitle = titleParts[titleParts.length - 1] + ""; + op.setUiAttrib({ "extendTitle": extendTitle }); + } + if (foundOut.get()) + { + resultOut.set(result); + } + else + { + op.setUiError("path", "given path seems to be invalid!", 1); + resultOut.set([]); + } + } + } + else + { + foundOut.set(false); + } +} + +function resolve(path, obj = self, separator = ".") +{ + const properties = Array.isArray(path) ? path : path.split(separator); + return properties.reduce((prev, curr) => prev && prev[curr], obj); +} + + +}; + +Ops.Json.ObjectGetArrayValuesByPath.prototype = new CABLES.Op(); +CABLES.OPS["609a645e-5e24-4a5e-a379-804c5b64f5d5"]={f:Ops.Json.ObjectGetArrayValuesByPath,objName:"Ops.Json.ObjectGetArrayValuesByPath"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectGetArray_v2 +// +// ************************************************************** + +Ops.Json.ObjectGetArray_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + data = op.inObject("data"), + key = op.inString("key"), + result = op.outArray("result"), + arrLength = op.outNumber("Length"); + +result.ignoreValueSerialize = true; +data.ignoreValueSerialize = true; + +data.onChange = update; + +key.onChange = function () +{ + if (!key.isLinked())op.setUiAttrib({ "extendTitle": key.get() }); + update(); +}; + +function update() +{ + result.set(null); + const dat = data.get(); + const k = key.get(); + if (dat && (dat.hasOwnProperty(k) || dat[k])) + { + result.set(dat[k]); + if (!result.get()) + { + arrLength.set(0); + } + else + { + arrLength.set(result.get().length); + } + } + else + { + arrLength.set(0); + } +} + + +}; + +Ops.Json.ObjectGetArray_v2.prototype = new CABLES.Op(); +CABLES.OPS["7c06a818-9c07-493a-8c4f-04eb2c7796f5"]={f:Ops.Json.ObjectGetArray_v2,objName:"Ops.Json.ObjectGetArray_v2"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectGetNumberByPath +// +// ************************************************************** + +Ops.Json.ObjectGetNumberByPath = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const objectIn = op.inObject("Object"); +const pathIn = op.inString("Path"); +const resultOut = op.outNumber("Output"); +const foundOut = op.outBool("Found"); + +objectIn.onChange = update; +pathIn.onChange = update; + +function update() +{ + const data = objectIn.get(); + const path = pathIn.get(); + op.setUiError("missing", null); + if (data && path) + { + if (!Array.isArray(data) && !(typeof data === "object")) + { + foundOut.set(false); + op.setUiError("notiterable", "input object of type " + (typeof data) + " is not travesable by path"); + } + else + { + op.setUiError("notiterable", null); + const parts = path.split("."); + op.setUiAttrib({ "extendTitle": parts[parts.length - 1] + "" }); + let result = resolve(path, data); + if (result === undefined) + { + const errorMsg = "could not find element at path " + path; + foundOut.set(false); + result = null; + op.setUiError("missing", errorMsg, 2); + } + else if (typeof result !== "number") + { + const errorMsg = "element at path " + path + " is not a number"; + foundOut.set(false); + result = null; + op.setUiError("missing", errorMsg, 2); + } + else + { + foundOut.set(true); + } + resultOut.set(result); + } + } + else + { + foundOut.set(false); + } +} + +function resolve(path, obj = self, separator = ".") +{ + const properties = Array.isArray(path) ? path : path.split(separator); + return properties.reduce((prev, curr) => prev && prev[curr], obj); +} + + +}; + +Ops.Json.ObjectGetNumberByPath.prototype = new CABLES.Op(); +CABLES.OPS["ec736baf-feb8-4d8d-b04c-173fc197759c"]={f:Ops.Json.ObjectGetNumberByPath,objName:"Ops.Json.ObjectGetNumberByPath"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectGetNumber_v2 +// +// ************************************************************** + +Ops.Json.ObjectGetNumber_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + data = op.inObject("Data"), + key = op.inString("Key"), + result = op.outNumber("Result"), + outFound = op.outBoolNum("Found"); + +result.ignoreValueSerialize = true; +data.ignoreValueSerialize = true; + +data.onChange = exec; + +key.onChange = function () +{ + if (!key.isLinked())op.setUiAttrib({ "extendTitle": key.get() }); + exec(); +}; + +function exec() +{ + if (data.get()) + { + const val = data.get()[key.get()]; + result.set(val); + if (val === undefined) outFound.set(0); + else outFound.set(1); + } + else + { + result.set(null); + outFound.set(0); + } +} + + +}; + +Ops.Json.ObjectGetNumber_v2.prototype = new CABLES.Op(); +CABLES.OPS["a7335e79-046e-40da-9e9c-db779b0a5e53"]={f:Ops.Json.ObjectGetNumber_v2,objName:"Ops.Json.ObjectGetNumber_v2"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectGetObjectByPath +// +// ************************************************************** + +Ops.Json.ObjectGetObjectByPath = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const objectIn = op.inObject("Object"); +const pathIn = op.inString("Path"); +const resultOut = op.outObject("Output"); +const foundOut = op.outBool("Found"); + +objectIn.onChange = update; +pathIn.onChange = update; + +function update() +{ + const data = objectIn.get(); + const path = pathIn.get(); + op.setUiError("missing", null); + if (data && path) + { + if (!Array.isArray(data) && !(typeof data === "object")) + { + foundOut.set(false); + op.setUiError("notiterable", "input object of type " + (typeof data) + " is not travesable by path"); + } + else + { + op.setUiError("notiterable", null); + const parts = path.split("."); + op.setUiAttrib({ "extendTitle": parts[parts.length - 1] + "" }); + let result = resolve(path, data); + if (result === undefined) + { + const errorMsg = "could not find element at path " + path; + foundOut.set(false); + result = null; + op.setUiError("missing", errorMsg, 2); + } + else if (Array.isArray(result) || result === null || typeof result !== "object") + { + const errorMsg = "element at path " + path + " is not an object"; + foundOut.set(false); + result = null; + op.setUiError("missing", errorMsg, 2); + } + else + { + foundOut.set(true); + } + resultOut.set(result); + } + } + else + { + foundOut.set(false); + } +} + +function resolve(path, obj = self, separator = ".") +{ + const properties = Array.isArray(path) ? path : path.split(separator); + return properties.reduce((prev, curr) => prev && prev[curr], obj); +} + + +}; + +Ops.Json.ObjectGetObjectByPath.prototype = new CABLES.Op(); +CABLES.OPS["574513c7-472b-433c-bf99-d906d3c737cd"]={f:Ops.Json.ObjectGetObjectByPath,objName:"Ops.Json.ObjectGetObjectByPath"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectGetObject_v2 +// +// ************************************************************** + +Ops.Json.ObjectGetObject_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + data = op.inObject("Object"), + key = op.inString("Key"), + result = op.outObject("Result"); + +result.ignoreValueSerialize = true; +data.ignoreValueSerialize = true; + +op.setUiAttrib({ "extendTitlePort": key.name }); + +key.onChange = +data.onChange = update; + +function update() +{ + if (data.get()) + { + result.set(data.get()[key.get()]); + } + else + { + result.set(null); + } +} + + +}; + +Ops.Json.ObjectGetObject_v2.prototype = new CABLES.Op(); +CABLES.OPS["d1dfa305-89db-4ca1-b0ac-2d6321d76ae8"]={f:Ops.Json.ObjectGetObject_v2,objName:"Ops.Json.ObjectGetObject_v2"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectGetString +// +// ************************************************************** + +Ops.Json.ObjectGetString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + data = op.inObject("data"), + key = op.inString("Key"), + result = op.outString("Result"); + +result.ignoreValueSerialize = true; +data.ignoreValueSerialize = true; + +op.setUiAttrib({ "extendTitlePort": key.name }); + +key.onChange = +data.onChange = exec; + +function exec() +{ + if (data.get()) + { + result.set(data.get()[key.get()]); + } + else + { + result.set(null); + } +} + + +}; + +Ops.Json.ObjectGetString.prototype = new CABLES.Op(); +CABLES.OPS["7d86cd28-f7d8-44a1-a4da-466c4782aaec"]={f:Ops.Json.ObjectGetString,objName:"Ops.Json.ObjectGetString"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectGetStringByPath +// +// ************************************************************** + +Ops.Json.ObjectGetStringByPath = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const objectIn = op.inObject("Object"); +const pathIn = op.inString("Path"); +const returnPathIn = op.inBool("Output path if missing", false); +const resultOut = op.outString("Output"); +const foundOut = op.outBool("Found"); + +objectIn.ignoreValueSerialize = true; + +objectIn.onChange = update; +pathIn.onChange = update; +returnPathIn.onChange = update; + +function update() +{ + const data = objectIn.get(); + const path = pathIn.get(); + op.setUiError("missing", null); + if (data && path) + { + if (!Array.isArray(data) && !(typeof data === "object")) + { + foundOut.set(false); + op.setUiError("notiterable", "input object of type " + (typeof data) + " is not travesable by path"); + } + else + { + op.setUiError("notiterable", null); + const parts = path.split("."); + op.setUiAttrib({ "extendTitle": parts[parts.length - 1] + "" }); + let result = resolve(path, data); + if (result === undefined) + { + const errorMsg = "could not find element at path " + path; + let errorLevel = 2; + result = null; + foundOut.set(false); + if (returnPathIn.get()) + { + result = path; + errorLevel = 1; + } + else + { + result = null; + } + op.setUiError("missing", errorMsg, errorLevel); + } + else + { + foundOut.set(true); + result = String(result); + } + resultOut.set(result); + } + } + else + { + foundOut.set(false); + } +} + +function resolve(path, obj = self, separator = ".") +{ + const properties = Array.isArray(path) ? path : path.split(separator); + return properties.reduce((prev, curr) => prev && prev[curr], obj); +} + + +}; + +Ops.Json.ObjectGetStringByPath.prototype = new CABLES.Op(); +CABLES.OPS["497a6b7c-e33c-45e4-8fb2-a9149d972b5b"]={f:Ops.Json.ObjectGetStringByPath,objName:"Ops.Json.ObjectGetStringByPath"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectIsNull +// +// ************************************************************** + +Ops.Json.ObjectIsNull = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inObj = op.inObject("Object"); +const outResult = op.outBoolNum("Result"); + +inObj.onChange = function () +{ + outResult.set(!inObj.get()); +}; + + +}; + +Ops.Json.ObjectIsNull.prototype = new CABLES.Op(); +CABLES.OPS["2fd858a8-3dff-43e4-bd85-a62c7d23b5a2"]={f:Ops.Json.ObjectIsNull,objName:"Ops.Json.ObjectIsNull"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectIterate +// +// ************************************************************** + +Ops.Json.ObjectIterate = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inObj = op.inObject("Object"), + outKey = op.outNumber("Key"); + +inObj.onChange = function () +{ + let obj = inObj.get(); + + if (obj) + { + for (let i in obj) + { + outKey.set(i); + } + } +}; + + +}; + +Ops.Json.ObjectIterate.prototype = new CABLES.Op(); +CABLES.OPS["128f5b07-17f9-43fb-ab61-c170a9a9cd8d"]={f:Ops.Json.ObjectIterate,objName:"Ops.Json.ObjectIterate"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectKeys +// +// ************************************************************** + +Ops.Json.ObjectKeys = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inObj = op.inObject("Object"), + outNumKeys = op.outNumber("Num Keys"), + outKeys = op.outArray("Keys"); + +inObj.onChange = function () +{ + let o = inObj.get(); + if (!o) + { + outNumKeys.set(0); + outKeys.set([]); + return; + } + + let keys = Object.keys(o); + outNumKeys.set(keys.length); + outKeys.set(keys); +}; + + +}; + +Ops.Json.ObjectKeys.prototype = new CABLES.Op(); +CABLES.OPS["83b4d148-8cb3-4a45-8824-957eeaf02e22"]={f:Ops.Json.ObjectKeys,objName:"Ops.Json.ObjectKeys"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectOr +// +// ************************************************************** + +Ops.Json.ObjectOr = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + object0=op.inObject("Object 1"), + object1=op.inObject("Object 2"), + object2=op.inObject("Object 3"), + object3=op.inObject("Object 4"), + object4=op.inObject("Object 5"), + object5=op.inObject("Object 6"), + object6=op.inObject("Object 7"), + object7=op.inObject("Object 8"), + result=op.outObject("Result"); + +object0.onChange=exec; +object1.onChange=exec; +object2.onChange=exec; +object3.onChange=exec; +object4.onChange=exec; +object5.onChange=exec; +object6.onChange=exec; +object7.onChange=exec; + + +function exec() +{ + result.set( object0.get() || object1.get() || object2.get() || object3.get() || object4.get() || object5.get() || object6.get() || object7.get() ); +} + + + +}; + +Ops.Json.ObjectOr.prototype = new CABLES.Op(); +CABLES.OPS["98c9a790-c018-466a-9c36-7afd0d2a8826"]={f:Ops.Json.ObjectOr,objName:"Ops.Json.ObjectOr"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectRecorder +// +// ************************************************************** + +Ops.Json.ObjectRecorder = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTriggerButton("Exec"), + reset = op.inTriggerButton("reset"), + download = op.inTriggerButton("download"), + inObj = op.inObject("Object"), + numObjects = op.outValue("Num Objects"); + +let data = []; + +reset.onTriggered = function () +{ + data.length = 0; + numObjects.set(data.length); +}; + +exec.onTriggered = function () +{ + if (inObj.get()) data.push(JSON.parse(JSON.stringify(inObj.get()))); + numObjects.set(data.length); +}; +download.onTriggered = function () +{ + let dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(data)); + let downloadAnchorNode = document.createElement("a"); + downloadAnchorNode.setAttribute("href", dataStr); + downloadAnchorNode.setAttribute("download", "jsonexport.json"); + downloadAnchorNode.click(); + downloadAnchorNode.remove(); +}; + + +}; + +Ops.Json.ObjectRecorder.prototype = new CABLES.Op(); +CABLES.OPS["5a6c7435-34ee-4897-9fda-548db54aff02"]={f:Ops.Json.ObjectRecorder,objName:"Ops.Json.ObjectRecorder"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectSetArray +// +// ************************************************************** + +Ops.Json.ObjectSetArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inObject = op.inObject("Object"), + outObject = op.outObject("Result Object"), + inKey = op.inString("Key"), + inValue = op.inArray("Value"); + +inObject.onChange = + inKey.onChange = + inValue.onChange = update; + +function update() +{ + let obj = inObject.get(); + if (!obj)obj = {}; + + if (inKey.get()) obj[inKey.get()] = inValue.get(); + + outObject.set(null); + outObject.set(obj); +} + + +}; + +Ops.Json.ObjectSetArray.prototype = new CABLES.Op(); +CABLES.OPS["d89cbbe0-5c6e-4b6c-84b3-1fa588f19a79"]={f:Ops.Json.ObjectSetArray,objName:"Ops.Json.ObjectSetArray"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectSetNumber +// +// ************************************************************** + +Ops.Json.ObjectSetNumber = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inObject=op.inObject("Object"), + outObject=op.outObject("Result Object"), + inKey=op.inString("Key"), + inValue=op.inValueFloat("Number"); + +inObject.onChange= + inKey.onChange= + inValue.onChange=update; + +function update() +{ + var obj=inObject.get(); + if(!obj)obj={}; + + obj[inKey.get()]=inValue.get(); + + outObject.set(null); + outObject.set(obj); +} + + +}; + +Ops.Json.ObjectSetNumber.prototype = new CABLES.Op(); +CABLES.OPS["e50fd010-5db1-48a7-91dc-94799ae1cb3b"]={f:Ops.Json.ObjectSetNumber,objName:"Ops.Json.ObjectSetNumber"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectSetObject +// +// ************************************************************** + +Ops.Json.ObjectSetObject = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inObject = op.inObject("Object"); +const inKey = op.inString("Key"); +const inValue = op.inObject("Object Value"); +const inUpdate = op.inTriggerButton("Set Object"); +const outObject = op.outObject("Result Object"); + +// inObject.onChange=update; +// inKey.onChange=update; +inUpdate.onTriggered = update; + +let obj = null; + +op.onDelete = +inObject.onChange = () => +{ + if (obj) + delete obj[inKey.get()]; +}; + +function update() +{ + obj = inObject.get(); + if (!obj) + { + obj = {}; + } + else + { + let changed = false; + + if (inKey.get().indexOf(",") > -1) + { + const keys = inKey.get().split(","); + + for (let i in keys) + { + if (keys[i] && keys[i].length > 0) + { + if (obj[keys[i]] != inValue.get())changed = true; + obj[keys[i]] = inValue.get(); + } + } + } + else + { + if (obj[inKey.get()] != inValue.get())changed = true; + obj[inKey.get()] = inValue.get(); + } + + outObject.set(null); + } + + outObject.set(obj); +} + + +}; + +Ops.Json.ObjectSetObject.prototype = new CABLES.Op(); +CABLES.OPS["ba7cad72-f226-4c27-b5e6-b20dabb8a3a4"]={f:Ops.Json.ObjectSetObject,objName:"Ops.Json.ObjectSetObject"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectSetObjectSimple +// +// ************************************************************** + +Ops.Json.ObjectSetObjectSimple = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inObject = op.inObject("Object"); +const inKey = op.inString("Key"); +const inValue = op.inObject("Object Value"); +const outObject = op.outObject("Result Object"); + +op.onDelete = removeKey; + +inObject.onLinkChanged = +inValue.onChange = +inKey.onChange = () => +{ + removeKey(); + update(); + op.setUiAttrib({ "extendTitle": inKey.get() }); +}; + +outObject.onLinkChanged = +inObject.onChange = update; + +let currentKey = ""; + +let obj = {}; + +function removeKey() +{ + delete obj[currentKey]; +} + +function copyObject() +{ + +} + +function update() +{ + obj = inObject.get() || {}; + + let changed = false; + + currentKey = inKey.get(); + if (obj[inKey.get()] != inValue.get())changed = true; + obj[inKey.get()] = inValue.get(); + + outObject.set(null); + outObject.set(obj); +} + + +}; + +Ops.Json.ObjectSetObjectSimple.prototype = new CABLES.Op(); +CABLES.OPS["448f0905-dd4c-4909-9ddb-352c7f4467de"]={f:Ops.Json.ObjectSetObjectSimple,objName:"Ops.Json.ObjectSetObjectSimple"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectSetString +// +// ************************************************************** + +Ops.Json.ObjectSetString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inObject=op.inObject("Object"), + outObject=op.outObject("Result Object"), + inKey=op.inString("Key"), + inValue=op.inString("Value"); + +inObject.onChange= + inKey.onChange= + inValue.onChange=update; + +function update() +{ + var obj=inObject.get(); + if(!obj)obj={}; + + obj[inKey.get()]=inValue.get(); + + outObject.set(null); + outObject.set(obj); +} + + +}; + +Ops.Json.ObjectSetString.prototype = new CABLES.Op(); +CABLES.OPS["31f19b25-2ed8-4ac6-84d4-a146da9e3a05"]={f:Ops.Json.ObjectSetString,objName:"Ops.Json.ObjectSetString"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectStringify_v2 +// +// ************************************************************** + +Ops.Json.ObjectStringify_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inObj = op.inObject("Object"), + inBeautify = op.inValueBool("Beautify"), + outString = op.outString("Result"), + outError = op.outBoolNum("Error"); + +inBeautify.onChange = inObj.onChange = update; + +function update() +{ + try + { + if (!inBeautify.get())outString.set(JSON.stringify(inObj.get())); + else outString.set(JSON.stringify(inObj.get(), false, 4)); + outError.set(0); + } + catch (e) + { + op.error(e); + outString.set("error"); + outError.set(1); + } +} + + +}; + +Ops.Json.ObjectStringify_v2.prototype = new CABLES.Op(); +CABLES.OPS["89fc70ea-2350-4a0e-9a24-4efca10cced6"]={f:Ops.Json.ObjectStringify_v2,objName:"Ops.Json.ObjectStringify_v2"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectToArray +// +// ************************************************************** + +Ops.Json.ObjectToArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inObj = op.inObject("Object"); +const outArray = op.outArray("Array"); + +inObj.onChange = function () +{ + outArray.set(inObj.get()); +}; + + +}; + +Ops.Json.ObjectToArray.prototype = new CABLES.Op(); +CABLES.OPS["f8ac4574-ffe3-4618-a27f-30d190308e2c"]={f:Ops.Json.ObjectToArray,objName:"Ops.Json.ObjectToArray"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectTrigger +// +// ************************************************************** + +Ops.Json.ObjectTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTrigger=op.inTriggerButton("Trigger"), + inObj=op.inObject("Object"), + outTrigger=op.outTrigger("Next"), + outObj=op.outObject("Result"); + +inTrigger.onTriggered=function() +{ + outObj.set(null); + outObj.set(inObj.get()); + outTrigger.trigger(); +}; + + +}; + +Ops.Json.ObjectTrigger.prototype = new CABLES.Op(); +CABLES.OPS["e437c074-190f-4adb-8265-3fddea27fe33"]={f:Ops.Json.ObjectTrigger,objName:"Ops.Json.ObjectTrigger"}; + + + + +// ************************************************************** +// +// Ops.Json.ObjectValues +// +// ************************************************************** + +Ops.Json.ObjectValues = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inObj = op.inObject("Object"), + outNumValues = op.outNumber("Num values"), + outValues = op.outArray("Values"); + +inObj.onChange = () => +{ + const sourceObj = inObj.get(); + if (!sourceObj) + { + outNumValues.set(0); + outValues.set([]); + return; + } + + const values = Object.values(sourceObj); + outNumValues.set(values.length); + outValues.set(values); +}; + + +}; + +Ops.Json.ObjectValues.prototype = new CABLES.Op(); +CABLES.OPS["32ff73f5-7947-42b0-83fa-e079af7beb5c"]={f:Ops.Json.ObjectValues,objName:"Ops.Json.ObjectValues"}; + + + + +// ************************************************************** +// +// Ops.Json.ParseObject_v2 +// +// ************************************************************** + +Ops.Json.ParseObject_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + str = op.inStringEditor("JSON String", "{}", "json"), + outObj = op.outObject("Result"), + isValid = op.outBoolNum("Valid"); + +str.onChange = parse; +parse(); + +function parse() +{ + if (!str.get()) + { + outObj.set(null); + isValid.set(false); + return; + } + try + { + const obj = JSON.parse(str.get()); + outObj.set(null); + outObj.set(obj); + isValid.set(true); + op.setUiError("invalidjson", null); + } + catch (ex) + { + op.logError(ex); + isValid.set(false); + + let outStr = ""; + const parts = ex.message.split(" "); + for (let i = 0; i < parts.length - 1; i++) + { + const num = parseFloat(parts[i + 1]); + if (num && parts[i] == "position") + { + const outStrA = str.get().substring(num - 15, num); + const outStrB = str.get().substring(num, num + 1); + const outStrC = str.get().substring(num + 1, num + 15); + outStr = "" + outStrA + "" + outStrB + "" + outStrC + " "; + } + } + + op.setUiError("invalidjson", "INVALID JSON
can not parse string to object:
" + ex.message + "
" + outStr); + } +} + + +}; + +Ops.Json.ParseObject_v2.prototype = new CABLES.Op(); +CABLES.OPS["2ce8a4d3-37d3-4cdc-abd1-a560fbe841ee"]={f:Ops.Json.ParseObject_v2,objName:"Ops.Json.ParseObject_v2"}; + + + + +// ************************************************************** +// +// Ops.Json.RouteObject +// +// ************************************************************** + +Ops.Json.RouteObject = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; + +const + NUM_PORTS = 10, + DEFAULT_OBJECT = {}, + indexPort = op.inInt('index'), + objectPort = op.inObject('Object in'), + defaultObjectPort = op.inObject('default object', DEFAULT_OBJECT), + objectPorts = createOutPorts(DEFAULT_OBJECT); + +indexPort.onChange = objectPort.onChange = defaultObjectPort.onChange = update; + +setDefaultValues(); +update(); + +function createOutPorts() +{ + var arrayObjects = []; + for(var i=0; i port.set(null)); + if(defaultObjectPort.get()) + { + objectPorts.forEach(port => port.set(defaultValue)); + } +}; + +function update() +{ + setDefaultValues(); + var index = indexPort.get(); + var value = objectPort.get(); + + index = Math.floor(index); + index = clamp(index, 0, NUM_PORTS-1); + objectPorts[index].set(value); +}; + +function clamp(value, min, max) +{ + return Math.min(Math.max(value, min), max); +}; + + +}; + +Ops.Json.RouteObject.prototype = new CABLES.Op(); +CABLES.OPS["bc969951-32b5-4226-9944-80a719a65497"]={f:Ops.Json.RouteObject,objName:"Ops.Json.RouteObject"}; + + + + +// ************************************************************** +// +// Ops.Json.SaveJsonFile +// +// ************************************************************** + +Ops.Json.SaveJsonFile = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; + +const + download = op.inTriggerButton("download"), + filename = op.inString("Filename", "jsonexport"), + inObject = op.inObject("Object"); + +download.onTriggered = function () +{ + const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(inObject.get(), null, 2)); + const downloadAnchorNode = document.createElement("a"); + downloadAnchorNode.setAttribute("href", dataStr); + downloadAnchorNode.setAttribute("download", filename.get() + ".json"); + downloadAnchorNode.click(); + downloadAnchorNode.remove(); +}; + + +}; + +Ops.Json.SaveJsonFile.prototype = new CABLES.Op(); +CABLES.OPS["04596a28-9563-4f42-8756-2d2a831baa60"]={f:Ops.Json.SaveJsonFile,objName:"Ops.Json.SaveJsonFile"}; + + + + +// ************************************************************** +// +// Ops.Json.SwitchObject +// +// ************************************************************** + +Ops.Json.SwitchObject = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const NUM_PORTS = 8; + +const inIndex = op.inValueInt("Object Index", 0); +const objectPorts = []; +const outObject = op.outObject("object out"); + +op.onLoaded = function () { indexChanged(); }; +inIndex.onChange = indexChanged; + +for (let i = 0; i < NUM_PORTS; i++) +{ + let port = op.inObject("object port " + i); + port.inputNum = i; + port.onChange = onPortChange.bind(port); + objectPorts[i] = port; +} + +function indexChanged() +{ + let index = Math.max(0, Math.floor(inIndex.get())); + if (index < 0) index = 0; + else if (index > NUM_PORTS - 1) index = NUM_PORTS - 1; + + outObject.set(null); + outObject.set(objectPorts[index].get()); +} + +function onPortChange() +{ + if (this.inputNum != inIndex.get()) return; + + outObject.set(null); + outObject.set(this.get()); +} + + +}; + +Ops.Json.SwitchObject.prototype = new CABLES.Op(); +CABLES.OPS["345d535e-267d-49fb-98c0-c8a8f9424160"]={f:Ops.Json.SwitchObject,objName:"Ops.Json.SwitchObject"}; + + + + +// ************************************************************** +// +// Ops.Libs.Lottie.LottieSVGPlayer +// +// ************************************************************** + +Ops.Libs.Lottie.LottieSVGPlayer = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inEle = op.inObject("HTML Element"), + inData = op.inObject("JSON Data"), + inPlayMode = op.inSwitch("Play Mode", ["Auto", "Frame"], "Auto"), + + inFrame = op.inFloat("Render Frame", 0), + inLoop = op.inValueBool("Loop", true), + + inPlay = op.inValueBool("Play", true), + + inDir = op.inBool("Play Backward"), + inRewind = op.inTriggerButton("Rewind"), + + outComplete = op.outBool("Completed", false), + outProgress = op.outNumber("Progress"), + outTotalFrames = op.outNumber("Total Frames"); + +op.setPortGroup("Timing", [inLoop, inPlayMode, inFrame, inPlay, inRewind, inDir]); + +let anim = null; +let playmodeAuto = true; + +inPlay.onChange = play; +inRewind.onTriggered = inLoop.onChange = inEle.onChange = inData.onChange = updateData; +inFrame.onChange = gotoFrame; +inDir.onChange = updateDir; +inPlayMode.onChange = updateUi; +updateUi(); + +function updateUi() +{ + playmodeAuto = inPlayMode.get() === "Auto"; + + inPlay.setUiAttribs({ "greyout": !playmodeAuto }); + inDir.setUiAttribs({ "greyout": !playmodeAuto }); + inRewind.setUiAttribs({ "greyout": !playmodeAuto }); + inFrame.setUiAttribs({ "greyout": playmodeAuto }); + if (playmodeAuto) play(); + else gotoFrame(); +} + +function dispose() +{ + if (anim) + { + anim.destroy(); + anim = null; + outTotalFrames.set(0); + } +} + +function play() +{ + if (!anim) return; + if (!playmodeAuto) return gotoFrame(); + + outComplete.set(false); + if (!inPlay.get())anim.pause(); + else anim.play(); +} + +function gotoFrame() +{ + if (playmodeAuto) return; + if (!anim) return; + + let fr = inFrame.get(); + if (inLoop.get())fr %= anim.totalFrames; + + anim.goToAndStop(fr, true); +} + +function updateDir() +{ + if (!anim) return; + if (!inDir.get()) anim.setDirection(1); + else anim.setDirection(-1); + + if (inPlay.get() && playmodeAuto) play(); +} + +function updateData() +{ + if (anim)dispose(); + if (!inEle.get() || !inData.get()) return; + if (Object.keys(inData.get()).length === 0) return; + + updateUi(); + + const params = { + "container": inEle.get(), + "renderer": "svg", + "loop": inLoop.get() == true, + "autoplay": (inPlay.get() == true && playmodeAuto), + "animationData": inData.get() + }; + + anim = lottie.loadAnimation(params); + + anim.addEventListener("complete", () => + { + outComplete.set(true); + }); + + anim.addEventListener("enterFrame", (e) => + { + outProgress.set(e.currentTime / (e.totalTime - 1)); + }); + outTotalFrames.set(anim.totalFrames); + updateDir(); + gotoFrame(); +} + + +}; + +Ops.Libs.Lottie.LottieSVGPlayer.prototype = new CABLES.Op(); +CABLES.OPS["c4ed075b-c897-4788-9cc0-2df638671f67"]={f:Ops.Libs.Lottie.LottieSVGPlayer,objName:"Ops.Libs.Lottie.LottieSVGPlayer"}; + + + + +// ************************************************************** +// +// Ops.Libs.Lottie.LottieTexturePlayer_v2 +// +// ************************************************************** + +Ops.Libs.Lottie.LottieTexturePlayer_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe = op.inTrigger("exe"), + inData = op.inObject("JSON Data"), + inPlayMode = op.inSwitch("Play Mode", ["Auto", "Frame"], "Auto"), + inFrame = op.inFloat("frame"), + inPlay = op.inBool("play"), + inRewind = op.inTriggerButton("Rewind"), + speed = op.inFloat("speed", 1), + width = op.inInt("texture width", 1280), + height = op.inInt("texture height", 720), + tfilter = op.inDropDown("Filter", ["nearest", "linear", "mipmap"], "linear"), + wrap = op.inDropDown("wrap", ["repeat", "mirrored repeat", "clamp to edge"], "repeat"), + bmScale = op.inSwitch("scale", ["fit", "nofit"], "fit"), + textureOut = op.outTexture("texture"), + outTotalFrames = op.outNumber("Total Frames"); + +const cgl = op.patch.cgl; +const canvasId = "bodymovin_" + CABLES.generateUUID(); +let createTexture = false; +let canvasImage = null; +let anim = null; +let ctx = null; +let canvas = null; +let cgl_filter = CGL.Texture.FILTER_LINEAR; +let cgl_wrap = CGL.Texture.WRAP_REPEAT; +let lastFrame = -2; +let playmodeAuto = true; +let updateTexture = true; +let tex = null; + +op.setPortGroup("Player Timing", [inPlayMode, inFrame, inPlay, inRewind, speed]); +op.setPortGroup("Texture Settings", [tfilter, wrap, width, height, bmScale]); + +inPlayMode.onChange = updateUi; +tfilter.onChange = onLottieFilterChange; +inData.onChange = reload; +bmScale.onChange = +width.onChange = + height.onChange = reloadForce; + +inPlay.onChange = function () +{ + if (anim) + if (inPlay.get()) anim.play(); + else anim.pause(); +}; + +inRewind.onTriggered = function () +{ + if (inPlay.get()) anim.goToAndPlay(0, true); + else anim.goToAndStop(0, true); +}; + +speed.onChange = function () +{ + if (anim) anim.setSpeed(speed.get()); +}; + +wrap.onChange = function () +{ + if (wrap.get() == "repeat") cgl_wrap = CGL.Texture.WRAP_REPEAT; + if (wrap.get() == "mirrored repeat") cgl_wrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + if (wrap.get() == "clamp to edge") cgl_wrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + createTexture = true; +}; + +function onLottieFilterChange() +{ + cgl_filter = CGL.Texture.FILTER_NEAREST; + if (tfilter.get() == "linear") cgl_filter = CGL.Texture.FILTER_LINEAR; + if (tfilter.get() == "mipmap") cgl_filter = CGL.Texture.FILTER_MIPMAP; + + createTexture = true; +} + +exe.onTriggered = function () +{ + if (!anim) return; + + outTotalFrames.set(anim.totalFrames); + + if (!canvasImage || !canvas) return; + + if (playmodeAuto) + { + updateTexture = true; + } + else + { + if (lastFrame != inFrame.get()) + { + lastFrame = inFrame.get(); + + if (inFrame.get() != -1.0) + { + anim.goToAndStop(inFrame.get(), true); + } + updateTexture = true; + } + } + + if (!textureOut.get() || createTexture) + { + const texOpts = + { + "wrap": cgl_wrap, + "filter": cgl_filter, + "unpackAlpha": false, + }; + if (tex) tex.delete(); + tex = new CGL.Texture.createFromImage(cgl, canvasImage, texOpts); + textureOut.set(tex); + createTexture = false; + } + if (updateTexture && tex) + { + tex.initTexture(canvasImage); + updateTexture = false; + } +}; + +op.onDelete = function () +{ + if (anim)anim.stop(); + anim = null; +}; + +function reloadForce() +{ + createTexture = true; + reload(true); +} + +function updateUi() +{ + playmodeAuto = inPlayMode.get() === "Auto"; + + inPlay.setUiAttribs({ "greyout": !playmodeAuto }); + inRewind.setUiAttribs({ "greyout": !playmodeAuto }); + speed.setUiAttribs({ "greyout": !playmodeAuto }); + inFrame.setUiAttribs({ "greyout": playmodeAuto }); + + if (anim) + { + if (playmodeAuto) if (inPlay.get()) anim.play(); + if (!playmodeAuto) anim.stop(); + } +} + +function reload(force) +{ + if (!inData.get() || Object.keys(inData.get()).length === 0) + { + if (anim)anim.stop(); + + anim = null; + if (tex)tex.delete(); + tex = null; + + createTexture = true; + canvasImage = null; + lastFrame = -2; + updateTexture = true; + + return; + } + + updateUi(); + + outTotalFrames.set(0); + if (anim) anim.stop(); + + if (!canvasImage || force) + { + if (tex)tex = tex.delete(); + if (canvas) canvas.remove(); + canvas = document.createElement("canvas"); + canvas.id = canvasId; + + canvas.width = width.get(); + canvas.height = height.get(); + canvas.style.display = "none"; + + const body = document.getElementsByTagName("body")[0]; + body.appendChild(canvas); + + canvasImage = document.getElementById(canvas.id); + ctx = canvasImage.getContext("2d"); + } + + const animData = { + "animType": "canvas", + "loop": false, + "prerender": true, + "autoplay": playmodeAuto && inPlay.get(), + "animationData": inData.get(), + "rendererSettings": + { + "context": ctx, + "clearCanvas": true, + "scaleMode": bmScale.get() + } + }; + + anim = bodymovin.loadAnimation(animData); + anim.setSpeed(speed.get()); + + anim.addEventListener("DOMLoaded", function (e) // sometimes anim loading seems to be async ? + { + finishedLoading(); + }); + + finishedLoading(); +} +function finishedLoading() +{ + if (!playmodeAuto) + { + anim.goToAndPlay(0, true); + lastFrame = -2; + } + if (playmodeAuto && inPlay.get()) anim.play(); +} + + +}; + +Ops.Libs.Lottie.LottieTexturePlayer_v2.prototype = new CABLES.Op(); +CABLES.OPS["2fc89999-18bc-4d68-a81e-79d2280051c0"]={f:Ops.Libs.Lottie.LottieTexturePlayer_v2,objName:"Ops.Libs.Lottie.LottieTexturePlayer_v2"}; + + + + +// ************************************************************** +// +// Ops.Libs.Mediapipe.FaceMesh +// +// ************************************************************** + +Ops.Libs.Mediapipe.FaceMesh = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inGeom = op.inObject("Geom"), + inPoints = op.inArray("Points"), + outGeom = op.outObject("result geom"); + +inPoints.onChange = () => +{ + const points = inPoints.get(); + + if (points && g) + { + for (let i = 0; i < g.vertices.length; i += 3) + { + g.vertices[i + 0] = points[i + 0]; + g.vertices[i + 1] = points[i + 1]; + } + + g.calculateNormals(); + outGeom.set(null); + outGeom.set(g); + } +}; + +const verts = [ + 0.000000, -3.406404, 5.979507, + 0.000000, -1.126865, 7.475604, + 0.000000, -2.089024, 6.058267, + -0.463928, 0.955357, 6.633583, + 0.000000, -0.463170, 7.586580, + 0.000000, 0.365669, 7.242870, + 0.000000, 2.473255, 5.788627, + -4.253081, 2.577646, 3.279702, + 0.000000, 4.019042, 5.284764, + 0.000000, 4.885979, 5.385258, + 0.000000, 8.261778, 4.481535, + 0.000000, -3.706811, 5.864924, + 0.000000, -3.918301, 5.569430, + 0.000000, -3.994436, 5.219482, + 0.000000, -4.542400, 5.404754, + 0.000000, -4.745577, 5.529457, + 0.000000, -5.019567, 5.601448, + 0.000000, -5.365123, 5.535441, + 0.000000, -6.149624, 5.071372, + 0.000000, -1.501095, 7.112196, + -0.416106, -1.466449, 6.447657, + -7.087960, 5.434801, 0.099620, + -2.628639, 2.035898, 3.848121, + -3.198363, 1.985815, 3.796952, + -3.775151, 2.039402, 3.646194, + -4.465819, 2.422950, 3.155168, + -2.164289, 2.189867, 3.851822, + -3.208229, 3.223926, 4.115822, + -2.673803, 3.205337, 4.092203, + -3.745193, 3.165286, 3.972409, + -4.161018, 3.059069, 3.719554, + -5.062006, 1.934418, 2.776093, + -2.266659, -7.425768, 4.389812, + -4.445859, 2.663991, 3.173422, + -7.214530, 2.263009, 0.073150, + -5.799793, 2.349546, 2.204059, + -2.844939, -0.720868, 4.433130, + -0.711452, -3.329355, 5.877044, + -0.606033, -3.924562, 5.444923, + -1.431615, -3.500953, 5.496189, + -1.914910, -3.803146, 5.028930, + -1.131043, -3.973937, 5.189648, + -1.563548, -4.082763, 4.842263, + -2.650112, -5.003649, 4.188483, + -0.427049, -1.094134, 7.360529, + -0.496396, -0.475659, 7.440358, + -5.253307, 3.881582, 3.363159, + -1.718698, 0.974609, 4.558359, + -1.608635, -0.942516, 5.814193, + -1.651267, -0.610868, 5.581319, + -4.765501, -0.701554, 3.534632, + -0.478306, 0.295766, 7.101013, + -3.734964, 4.508230, 4.550454, + -4.588603, 4.302037, 4.048484, + -6.279331, 6.615427, 1.425850, + -1.220941, 4.142165, 5.106035, + -2.193489, 3.100317, 4.000575, + -3.102642, -4.352984, 4.095905, + -6.719682, -4.788645, -1.745401, + -1.193824, -1.306795, 5.737747, + -0.729766, -1.593712, 5.833208, + -2.456206, -4.342621, 4.283884, + -2.204823, -4.304508, 4.162499, + -4.985894, 4.802461, 3.751977, + -1.592294, -1.257709, 5.456949, + -2.644548, 4.524654, 4.921559, + -2.760292, 5.100971, 5.015990, + -3.523964, 8.005976, 3.729163, + -5.599763, 5.715470, 2.724259, + -3.063932, 6.566144, 4.529981, + -5.720968, 4.254584, 2.830852, + -6.374393, 4.785590, 1.591691, + -0.672728, -3.688016, 5.737804, + -1.262560, -3.787691, 5.417779, + -1.732553, -3.952767, 5.000579, + -1.043625, -1.464973, 5.662455, + -2.321234, -4.329069, 4.258156, + -2.056846, -4.477671, 4.520883, + -2.153084, -4.276322, 4.038093, + -0.946874, -1.035249, 6.512274, + -1.469132, -4.036351, 4.604908, + -1.024340, -3.989851, 4.926693, + -0.533422, -3.993222, 5.138202, + -0.769720, -6.095394, 4.985883, + -0.699606, -5.291850, 5.448304, + -0.669687, -4.949770, 5.509612, + -0.630947, -4.695101, 5.449371, + -0.583218, -4.517982, 5.339869, + -1.537170, -4.423206, 4.745470, + -1.615600, -4.475942, 4.813632, + -1.729053, -4.618680, 4.854463, + -1.838624, -4.828746, 4.823737, + -2.368250, -3.106237, 4.868096, + -7.542244, -1.049282, -2.431321, + 0.000000, -1.724003, 6.601390, + -1.826614, -4.399531, 4.399021, + -1.929558, -4.411831, 4.497052, + -0.597442, -2.013686, 5.866456, + -1.405627, -1.714196, 5.241087, + -0.662449, -1.819321, 5.863759, + -2.342340, 0.572222, 4.294303, + -3.327324, 0.104863, 4.113860, + -1.726175, -0.919165, 5.273355, + -5.133204, 7.485602, 2.660442, + -4.538641, 6.319907, 3.683424, + -3.986562, 5.109487, 4.466315, + -2.169681, -5.440433, 4.455874, + -1.395634, 5.011963, 5.316032, + -1.619500, 6.599217, 4.921106, + -1.891399, 8.236377, 4.274997, + -4.195832, 2.235205, 3.375099, + -5.733342, 1.411738, 2.431726, + -1.859887, 2.355757, 3.843181, + -4.988612, 3.074654, 3.083858, + -1.303263, 1.416453, 4.831091, + -1.305757, -0.672779, 6.415959, + -6.465170, 0.937119, 1.689873, + -5.258659, 0.945811, 2.974312, + -4.432338, 0.722096, 3.522615, + -3.300681, 0.861641, 3.872784, + -2.430178, 1.131492, 4.039035, + -1.820731, 1.467954, 4.224124, + -0.563221, 2.307693, 5.566789, + -6.338145, -0.529279, 1.881175, + -5.587698, 3.208071, 2.687839, + -0.242624, -1.462857, 7.071491, + -1.611251, 0.339326, 4.895421, + -7.743095, 2.364999, -2.005167, + -1.391142, 1.851048, 4.448999, + -1.785794, -0.978284, 4.850470, + -4.670959, 2.664461, 3.084075, + -1.333970, -0.283761, 6.097047, + -7.270895, -2.890917, -2.252455, + -1.856432, 2.585245, 3.757904, + -0.923388, 0.073076, 6.671944, + -5.000589, -6.135128, 1.892523, + -5.085276, -7.178590, 0.714711, + -7.159291, -0.811820, -0.072044, + -5.843051, -5.248023, 0.924091, + -6.847258, 3.662916, 0.724695, + -2.412942, -8.258853, 4.119213, + -0.179909, -1.689864, 6.573301, + -2.103655, -0.163946, 4.566119, + -6.407571, 2.236021, 1.560843, + -3.670075, 2.360153, 3.635230, + -3.177186, 2.294265, 3.775704, + -2.196121, -4.598322, 4.479786, + -6.234883, -1.944430, 1.663542, + -1.292924, -9.295920, 4.094063, + -3.210651, -8.533278, 2.802001, + -4.068926, -7.993109, 1.925119, + 0.000000, 6.545390, 5.027311, + 0.000000, -9.403378, 4.264492, + -2.724032, 2.315802, 3.777151, + -2.288460, 2.398891, 3.697603, + -1.998311, 2.496547, 3.689148, + -6.130040, 3.399261, 2.038516, + -2.288460, 2.886504, 3.775031, + -2.724032, 2.961810, 3.871767, + -3.177186, 2.964136, 3.876973, + -3.670075, 2.927714, 3.724325, + -4.018389, 2.857357, 3.482983, + -7.555811, 4.106811, -0.991917, + -4.018389, 2.483695, 3.440898, + 0.000000, -2.521945, 5.932265, + -1.776217, -2.683946, 5.213116, + -1.222237, -1.182444, 5.952465, + -0.731493, -2.536683, 5.815343, + 0.000000, 3.271027, 5.236015, + -4.135272, -6.996638, 2.671970, + -3.311811, -7.660815, 3.382963, + -1.313701, -8.639995, 4.702456, + -5.940524, -6.223629, -0.631468, + -1.998311, 2.743838, 3.744030, + -0.901447, 1.236992, 5.754256, + 0.000000, -8.765243, 4.891441, + -2.308977, -8.974196, 3.609070, + -6.954154, -2.439843, -0.131163, + -1.098819, -4.458788, 5.120727, + -1.181124, -4.579996, 5.189564, + -1.255818, -4.787901, 5.237051, + -1.325085, -5.106507, 5.205010, + -1.546388, -5.819392, 4.757893, + -1.953754, -4.183892, 4.431713, + -2.117802, -4.137093, 4.555096, + -2.285339, -4.051196, 4.582438, + -2.850160, -3.665720, 4.484994, + -5.278538, -2.238942, 2.861224, + -0.946709, 1.907628, 5.196779, + -1.314173, 3.104912, 4.231404, + -1.780000, 2.860000, 3.881555, + -1.845110, -4.098880, 4.247264, + -5.436187, -4.030482, 2.109852, + -0.766444, 3.182131, 4.861453, + -1.938616, -6.614410, 4.521085, + 0.000000, 1.059413, 6.774605, + -0.516573, 1.583572, 6.148363, + 0.000000, 1.728369, 6.316750, + -1.246815, 0.230297, 5.681036, + 0.000000, -7.942194, 5.181173, + 0.000000, -6.991499, 5.153478, + -0.997827, -6.930921, 4.979576, + -3.288807, -5.382514, 3.795752, + -2.311631, -1.566237, 4.590085, + -2.680250, -6.111567, 4.096152, + -3.832928, -1.537326, 4.137731, + -2.961860, -2.274215, 4.440943, + -4.386901, -2.683286, 3.643886, + -1.217295, -7.834465, 4.969286, + -1.542374, -0.136843, 5.201008, + -3.878377, -6.041764, 3.311079, + -3.084037, -6.809842, 3.814195, + -3.747321, -4.503545, 3.726453, + -6.094129, -3.205991, 1.473482, + -4.588995, -4.728726, 2.983221, + -6.583231, -3.941269, 0.070268, + -3.492580, -3.195820, 4.130198, + -1.255543, 0.802341, 5.307551, + -1.126122, -0.933602, 6.538785, + -1.443109, -1.142774, 5.905127, + -0.923043, -0.529042, 7.003423, + -1.755386, 3.529117, 4.327696, + -2.632589, 3.713828, 4.364629, + -3.388062, 3.721976, 4.309028, + -4.075766, 3.675413, 4.076063, + -4.622910, 3.474691, 3.646321, + -5.171755, 2.535753, 2.670867, + -7.297331, 0.763172, -0.048769, + -4.706828, 1.651000, 3.109532, + -4.071712, 1.476821, 3.476944, + -3.269817, 1.470659, 3.731945, + -2.527572, 1.617311, 3.865444, + -1.970894, 1.858505, 3.961782, + -1.579543, 2.097941, 4.084996, + -7.664182, 0.673132, -2.435867, + -1.397041, -1.340139, 5.630378, + -0.884838, 0.658740, 6.233232, + -0.767097, -0.968035, 7.077932, + -0.460213, -1.334106, 6.787447, + -0.748618, -1.067994, 6.798303, + -1.236408, -1.585568, 5.480490, + -0.387306, -1.409990, 6.957705, + -0.319925, -1.607931, 6.508676, + -1.639633, 2.556298, 3.863736, + -1.255645, 2.467144, 4.203800, + -1.031362, 2.382663, 4.615849, + -4.253081, 2.772296, 3.315305, + -4.530000, 2.910000, 3.339685, + 0.463928, 0.955357, 6.633583, + 4.253081, 2.577646, 3.279702, + 0.416106, -1.466449, 6.447657, + 7.087960, 5.434801, 0.099620, + 2.628639, 2.035898, 3.848121, + 3.198363, 1.985815, 3.796952, + 3.775151, 2.039402, 3.646194, + 4.465819, 2.422950, 3.155168, + 2.164289, 2.189867, 3.851822, + 3.208229, 3.223926, 4.115822, + 2.673803, 3.205337, 4.092203, + 3.745193, 3.165286, 3.972409, + 4.161018, 3.059069, 3.719554, + 5.062006, 1.934418, 2.776093, + 2.266659, -7.425768, 4.389812, + 4.445859, 2.663991, 3.173422, + 7.214530, 2.263009, 0.073150, + 5.799793, 2.349546, 2.204059, + 2.844939, -0.720868, 4.433130, + 0.711452, -3.329355, 5.877044, + 0.606033, -3.924562, 5.444923, + 1.431615, -3.500953, 5.496189, + 1.914910, -3.803146, 5.028930, + 1.131043, -3.973937, 5.189648, + 1.563548, -4.082763, 4.842263, + 2.650112, -5.003649, 4.188483, + 0.427049, -1.094134, 7.360529, + 0.496396, -0.475659, 7.440358, + 5.253307, 3.881582, 3.363159, + 1.718698, 0.974609, 4.558359, + 1.608635, -0.942516, 5.814193, + 1.651267, -0.610868, 5.581319, + 4.765501, -0.701554, 3.534632, + 0.478306, 0.295766, 7.101013, + 3.734964, 4.508230, 4.550454, + 4.588603, 4.302037, 4.048484, + 6.279331, 6.615427, 1.425850, + 1.220941, 4.142165, 5.106035, + 2.193489, 3.100317, 4.000575, + 3.102642, -4.352984, 4.095905, + 6.719682, -4.788645, -1.745401, + 1.193824, -1.306795, 5.737747, + 0.729766, -1.593712, 5.833208, + 2.456206, -4.342621, 4.283884, + 2.204823, -4.304508, 4.162499, + 4.985894, 4.802461, 3.751977, + 1.592294, -1.257709, 5.456949, + 2.644548, 4.524654, 4.921559, + 2.760292, 5.100971, 5.015990, + 3.523964, 8.005976, 3.729163, + 5.599763, 5.715470, 2.724259, + 3.063932, 6.566144, 4.529981, + 5.720968, 4.254584, 2.830852, + 6.374393, 4.785590, 1.591691, + 0.672728, -3.688016, 5.737804, + 1.262560, -3.787691, 5.417779, + 1.732553, -3.952767, 5.000579, + 1.043625, -1.464973, 5.662455, + 2.321234, -4.329069, 4.258156, + 2.056846, -4.477671, 4.520883, + 2.153084, -4.276322, 4.038093, + 0.946874, -1.035249, 6.512274, + 1.469132, -4.036351, 4.604908, + 1.024340, -3.989851, 4.926693, + 0.533422, -3.993222, 5.138202, + 0.769720, -6.095394, 4.985883, + 0.699606, -5.291850, 5.448304, + 0.669687, -4.949770, 5.509612, + 0.630947, -4.695101, 5.449371, + 0.583218, -4.517982, 5.339869, + 1.537170, -4.423206, 4.745470, + 1.615600, -4.475942, 4.813632, + 1.729053, -4.618680, 4.854463, + 1.838624, -4.828746, 4.823737, + 2.368250, -3.106237, 4.868096, + 7.542244, -1.049282, -2.431321, + 1.826614, -4.399531, 4.399021, + 1.929558, -4.411831, 4.497052, + 0.597442, -2.013686, 5.866456, + 1.405627, -1.714196, 5.241087, + 0.662449, -1.819321, 5.863759, + 2.342340, 0.572222, 4.294303, + 3.327324, 0.104863, 4.113860, + 1.726175, -0.919165, 5.273355, + 5.133204, 7.485602, 2.660442, + 4.538641, 6.319907, 3.683424, + 3.986562, 5.109487, 4.466315, + 2.169681, -5.440433, 4.455874, + 1.395634, 5.011963, 5.316032, + 1.619500, 6.599217, 4.921106, + 1.891399, 8.236377, 4.274997, + 4.195832, 2.235205, 3.375099, + 5.733342, 1.411738, 2.431726, + 1.859887, 2.355757, 3.843181, + 4.988612, 3.074654, 3.083858, + 1.303263, 1.416453, 4.831091, + 1.305757, -0.672779, 6.415959, + 6.465170, 0.937119, 1.689873, + 5.258659, 0.945811, 2.974312, + 4.432338, 0.722096, 3.522615, + 3.300681, 0.861641, 3.872784, + 2.430178, 1.131492, 4.039035, + 1.820731, 1.467954, 4.224124, + 0.563221, 2.307693, 5.566789, + 6.338145, -0.529279, 1.881175, + 5.587698, 3.208071, 2.687839, + 0.242624, -1.462857, 7.071491, + 1.611251, 0.339326, 4.895421, + 7.743095, 2.364999, -2.005167, + 1.391142, 1.851048, 4.448999, + 1.785794, -0.978284, 4.850470, + 4.670959, 2.664461, 3.084075, + 1.333970, -0.283761, 6.097047, + 7.270895, -2.890917, -2.252455, + 1.856432, 2.585245, 3.757904, + 0.923388, 0.073076, 6.671944, + 5.000589, -6.135128, 1.892523, + 5.085276, -7.178590, 0.714711, + 7.159291, -0.811820, -0.072044, + 5.843051, -5.248023, 0.924091, + 6.847258, 3.662916, 0.724695, + 2.412942, -8.258853, 4.119213, + 0.179909, -1.689864, 6.573301, + 2.103655, -0.163946, 4.566119, + 6.407571, 2.236021, 1.560843, + 3.670075, 2.360153, 3.635230, + 3.177186, 2.294265, 3.775704, + 2.196121, -4.598322, 4.479786, + 6.234883, -1.944430, 1.663542, + 1.292924, -9.295920, 4.094063, + 3.210651, -8.533278, 2.802001, + 4.068926, -7.993109, 1.925119, + 2.724032, 2.315802, 3.777151, + 2.288460, 2.398891, 3.697603, + 1.998311, 2.496547, 3.689148, + 6.130040, 3.399261, 2.038516, + 2.288460, 2.886504, 3.775031, + 2.724032, 2.961810, 3.871767, + 3.177186, 2.964136, 3.876973, + 3.670075, 2.927714, 3.724325, + 4.018389, 2.857357, 3.482983, + 7.555811, 4.106811, -0.991917, + 4.018389, 2.483695, 3.440898, + 1.776217, -2.683946, 5.213116, + 1.222237, -1.182444, 5.952465, + 0.731493, -2.536683, 5.815343, + 4.135272, -6.996638, 2.671970, + 3.311811, -7.660815, 3.382963, + 1.313701, -8.639995, 4.702456, + 5.940524, -6.223629, -0.631468, + 1.998311, 2.743838, 3.744030, + 0.901447, 1.236992, 5.754256, + 2.308977, -8.974196, 3.609070, + 6.954154, -2.439843, -0.131163, + 1.098819, -4.458788, 5.120727, + 1.181124, -4.579996, 5.189564, + 1.255818, -4.787901, 5.237051, + 1.325085, -5.106507, 5.205010, + 1.546388, -5.819392, 4.757893, + 1.953754, -4.183892, 4.431713, + 2.117802, -4.137093, 4.555096, + 2.285339, -4.051196, 4.582438, + 2.850160, -3.665720, 4.484994, + 5.278538, -2.238942, 2.861224, + 0.946709, 1.907628, 5.196779, + 1.314173, 3.104912, 4.231404, + 1.780000, 2.860000, 3.881555, + 1.845110, -4.098880, 4.247264, + 5.436187, -4.030482, 2.109852, + 0.766444, 3.182131, 4.861453, + 1.938616, -6.614410, 4.521085, + 0.516573, 1.583572, 6.148363, + 1.246815, 0.230297, 5.681036, + 0.997827, -6.930921, 4.979576, + 3.288807, -5.382514, 3.795752, + 2.311631, -1.566237, 4.590085, + 2.680250, -6.111567, 4.096152, + 3.832928, -1.537326, 4.137731, + 2.961860, -2.274215, 4.440943, + 4.386901, -2.683286, 3.643886, + 1.217295, -7.834465, 4.969286, + 1.542374, -0.136843, 5.201008, + 3.878377, -6.041764, 3.311079, + 3.084037, -6.809842, 3.814195, + 3.747321, -4.503545, 3.726453, + 6.094129, -3.205991, 1.473482, + 4.588995, -4.728726, 2.983221, + 6.583231, -3.941269, 0.070268, + 3.492580, -3.195820, 4.130198, + 1.255543, 0.802341, 5.307551, + 1.126122, -0.933602, 6.538785, + 1.443109, -1.142774, 5.905127, + 0.923043, -0.529042, 7.003423, + 1.755386, 3.529117, 4.327696, + 2.632589, 3.713828, 4.364629, + 3.388062, 3.721976, 4.309028, + 4.075766, 3.675413, 4.076063, + 4.622910, 3.474691, 3.646321, + 5.171755, 2.535753, 2.670867, + 7.297331, 0.763172, -0.048769, + 4.706828, 1.651000, 3.109532, + 4.071712, 1.476821, 3.476944, + 3.269817, 1.470659, 3.731945, + 2.527572, 1.617311, 3.865444, + 1.970894, 1.858505, 3.961782, + 1.579543, 2.097941, 4.084996, + 7.664182, 0.673132, -2.435867, + 1.397041, -1.340139, 5.630378, + 0.884838, 0.658740, 6.233232, + 0.767097, -0.968035, 7.077932, + 0.460213, -1.334106, 6.787447, + 0.748618, -1.067994, 6.798303, + 1.236408, -1.585568, 5.480490, + 0.387306, -1.409990, 6.957705, + 0.319925, -1.607931, 6.508676, + 1.639633, 2.556298, 3.863736, + 1.255645, 2.467144, 4.203800, + 1.031362, 2.382663, 4.615849, + 4.253081, 2.772296, 3.315305, + 4.530000, 2.910000, 3.339685]; +const faces = [ + 174, 156, 134, + 247, 34, 8, + 383, 399, 363, + 264, 467, 250, + 309, 416, 325, + 79, 96, 192, + 357, 390, 265, + 128, 35, 163, + 369, 265, 390, + 140, 163, 35, + 268, 1, 303, + 38, 73, 1, + 12, 303, 1, + 12, 1, 73, + 350, 452, 351, + 121, 122, 232, + 453, 351, 452, + 233, 232, 122, + 268, 303, 270, + 38, 40, 73, + 304, 270, 303, + 74, 73, 40, + 358, 344, 351, + 129, 122, 115, + 278, 351, 344, + 48, 115, 122, + 351, 453, 358, + 122, 129, 233, + 454, 358, 453, + 234, 233, 129, + 300, 334, 298, + 70, 68, 105, + 333, 298, 334, + 104, 105, 68, + 176, 153, 397, + 176, 172, 153, + 378, 397, 153, + 149, 153, 172, + 382, 385, 383, + 155, 156, 158, + 399, 383, 385, + 174, 158, 156, + 281, 348, 331, + 51, 102, 119, + 349, 331, 348, + 120, 119, 102, + 270, 304, 271, + 40, 41, 74, + 305, 271, 304, + 75, 74, 41, + 10, 337, 152, + 10, 152, 108, + 338, 152, 337, + 109, 108, 152, + 345, 279, 361, + 116, 132, 49, + 280, 361, 279, + 50, 49, 132, + 263, 432, 419, + 33, 195, 212, + 425, 419, 432, + 205, 212, 195, + 305, 409, 271, + 75, 41, 185, + 410, 271, 409, + 186, 185, 41, + 273, 311, 408, + 43, 184, 81, + 416, 408, 311, + 192, 81, 184, + 323, 271, 411, + 93, 187, 41, + 410, 411, 271, + 186, 41, 187, + 348, 450, 349, + 119, 120, 230, + 451, 349, 450, + 231, 230, 120, + 435, 433, 431, + 215, 211, 213, + 423, 431, 433, + 203, 213, 211, + 314, 315, 19, + 84, 19, 85, + 18, 19, 315, + 18, 85, 19, + 308, 376, 307, + 78, 77, 147, + 292, 307, 376, + 62, 147, 77, + 260, 388, 261, + 30, 31, 161, + 389, 261, 388, + 162, 161, 31, + 287, 415, 385, + 57, 158, 191, + 399, 385, 415, + 174, 191, 158, + 419, 425, 407, + 195, 183, 205, + 336, 407, 425, + 107, 205, 183, + 368, 417, 365, + 139, 136, 193, + 435, 365, 417, + 215, 193, 136, + 392, 424, 328, + 166, 99, 204, + 359, 328, 424, + 130, 204, 99, + 299, 302, 285, + 69, 55, 72, + 252, 285, 302, + 22, 72, 55, + 5, 276, 6, + 5, 6, 46, + 282, 6, 276, + 52, 46, 6, + 255, 374, 254, + 25, 24, 145, + 375, 254, 374, + 146, 145, 24, + 321, 322, 308, + 91, 78, 92, + 376, 308, 322, + 147, 92, 78, + 281, 426, 412, + 51, 188, 206, + 428, 412, 426, + 208, 206, 188, + 422, 314, 201, + 202, 201, 84, + 19, 201, 314, + 19, 84, 201, + 336, 322, 407, + 107, 183, 92, + 406, 407, 322, + 182, 92, 183, + 406, 322, 405, + 182, 181, 92, + 321, 405, 322, + 91, 92, 181, + 18, 315, 17, + 18, 17, 85, + 316, 17, 315, + 86, 85, 17, + 426, 267, 427, + 206, 207, 37, + 424, 427, 267, + 204, 37, 207, + 370, 397, 401, + 141, 177, 172, + 378, 401, 397, + 149, 172, 177, + 392, 270, 323, + 166, 93, 40, + 271, 323, 270, + 41, 40, 93, + 418, 466, 414, + 194, 190, 246, + 465, 414, 466, + 245, 246, 190, + 258, 259, 387, + 28, 160, 29, + 386, 387, 259, + 159, 29, 160, + 261, 389, 468, + 31, 248, 162, + 467, 468, 389, + 247, 162, 248, + 249, 457, 420, + 4, 197, 237, + 400, 420, 457, + 175, 237, 197, + 334, 299, 333, + 105, 104, 69, + 285, 333, 299, + 55, 69, 104, + 286, 9, 418, + 56, 194, 9, + 169, 418, 9, + 169, 9, 194, + 341, 262, 347, + 112, 118, 32, + 449, 347, 262, + 229, 32, 118, + 286, 418, 442, + 56, 222, 194, + 414, 442, 418, + 190, 194, 222, + 328, 461, 327, + 99, 98, 241, + 329, 327, 461, + 100, 241, 98, + 278, 356, 330, + 48, 101, 127, + 372, 330, 356, + 143, 127, 101, + 310, 393, 439, + 80, 219, 167, + 440, 439, 393, + 220, 167, 219, + 382, 383, 257, + 155, 27, 156, + 342, 257, 383, + 113, 156, 27, + 361, 280, 421, + 132, 199, 50, + 430, 421, 280, + 210, 50, 199, + 366, 365, 380, + 137, 151, 136, + 395, 380, 365, + 170, 136, 151, + 356, 278, 438, + 127, 218, 48, + 344, 438, 278, + 115, 48, 218, + 444, 445, 283, + 224, 53, 225, + 284, 283, 445, + 54, 225, 53, + 282, 276, 364, + 52, 135, 46, + 441, 364, 276, + 221, 46, 135, + 432, 263, 396, + 212, 171, 33, + 370, 396, 263, + 141, 33, 171, + 338, 300, 339, + 109, 110, 70, + 298, 339, 300, + 68, 70, 110, + 336, 274, 322, + 107, 92, 44, + 376, 322, 274, + 147, 44, 92, + 349, 451, 350, + 120, 121, 231, + 452, 350, 451, + 232, 231, 121, + 468, 360, 343, + 248, 114, 131, + 447, 343, 360, + 227, 131, 114, + 283, 284, 335, + 53, 106, 54, + 294, 335, 284, + 64, 54, 106, + 251, 459, 463, + 21, 243, 239, + 462, 463, 459, + 242, 239, 243, + 277, 354, 301, + 47, 71, 125, + 384, 301, 354, + 157, 125, 71, + 326, 293, 325, + 97, 96, 63, + 309, 325, 293, + 79, 63, 96, + 284, 277, 294, + 54, 64, 47, + 301, 294, 277, + 71, 47, 64, + 448, 265, 346, + 228, 117, 35, + 373, 346, 265, + 144, 35, 117, + 353, 346, 347, + 124, 118, 117, + 341, 347, 346, + 112, 117, 118, + 2, 20, 275, + 2, 45, 20, + 355, 275, 20, + 126, 20, 45, + 249, 282, 457, + 4, 237, 52, + 364, 457, 282, + 135, 52, 237, + 426, 427, 428, + 206, 208, 207, + 437, 428, 427, + 217, 207, 208, + 381, 382, 253, + 154, 23, 155, + 257, 253, 382, + 27, 155, 23, + 392, 394, 270, + 166, 40, 168, + 268, 270, 394, + 38, 168, 40, + 200, 429, 201, + 200, 201, 209, + 422, 201, 429, + 202, 209, 201, + 331, 330, 267, + 102, 37, 101, + 372, 267, 330, + 143, 101, 37, + 423, 433, 274, + 203, 44, 213, + 288, 274, 433, + 58, 213, 44, + 291, 251, 329, + 61, 100, 21, + 463, 329, 251, + 243, 21, 100, + 259, 287, 386, + 29, 159, 57, + 385, 386, 287, + 158, 57, 159, + 343, 447, 354, + 114, 125, 227, + 266, 354, 447, + 36, 227, 125, + 258, 387, 260, + 28, 30, 160, + 388, 260, 387, + 161, 160, 30, + 431, 423, 432, + 211, 212, 203, + 425, 432, 423, + 205, 203, 212, + 446, 343, 277, + 226, 47, 114, + 354, 277, 343, + 125, 114, 47, + 425, 423, 336, + 205, 107, 203, + 274, 336, 423, + 44, 203, 107, + 307, 293, 308, + 77, 78, 63, + 326, 308, 293, + 97, 63, 78, + 367, 448, 353, + 138, 124, 228, + 346, 353, 448, + 117, 228, 124, + 303, 269, 304, + 73, 74, 39, + 272, 304, 269, + 42, 39, 74, + 372, 359, 267, + 143, 37, 130, + 424, 267, 359, + 204, 130, 37, + 328, 295, 461, + 99, 241, 65, + 456, 461, 295, + 236, 65, 241, + 295, 332, 279, + 65, 49, 103, + 280, 279, 332, + 50, 103, 49, + 304, 272, 305, + 74, 75, 42, + 273, 305, 272, + 43, 42, 75, + 428, 437, 435, + 208, 215, 217, + 433, 435, 437, + 213, 217, 215, + 305, 273, 409, + 75, 185, 43, + 408, 409, 273, + 184, 43, 185, + 395, 431, 396, + 170, 171, 211, + 432, 396, 431, + 212, 211, 171, + 396, 370, 379, + 171, 150, 141, + 401, 379, 370, + 177, 141, 150, + 297, 335, 300, + 67, 70, 106, + 334, 300, 335, + 105, 106, 70, + 418, 169, 352, + 194, 123, 169, + 7, 352, 169, + 7, 169, 123, + 281, 412, 353, + 51, 124, 188, + 377, 353, 412, + 148, 188, 124, + 320, 321, 326, + 90, 97, 91, + 308, 326, 321, + 78, 91, 97, + 286, 296, 337, + 56, 108, 66, + 297, 337, 296, + 67, 66, 108, + 405, 321, 404, + 181, 180, 91, + 320, 404, 321, + 90, 91, 180, + 331, 349, 330, + 102, 101, 120, + 350, 330, 349, + 121, 120, 101, + 335, 294, 334, + 106, 105, 64, + 299, 334, 294, + 69, 64, 105, + 324, 455, 367, + 94, 138, 235, + 448, 367, 455, + 228, 235, 138, + 17, 316, 16, + 17, 16, 86, + 317, 16, 316, + 87, 86, 16, + 430, 280, 359, + 210, 130, 50, + 332, 359, 280, + 103, 50, 130, + 16, 317, 15, + 16, 15, 87, + 318, 15, 317, + 88, 87, 15, + 9, 286, 10, + 9, 10, 56, + 337, 10, 286, + 108, 56, 10, + 330, 350, 278, + 101, 48, 121, + 351, 278, 350, + 122, 121, 48, + 253, 254, 381, + 23, 154, 24, + 375, 381, 254, + 146, 24, 154, + 403, 404, 319, + 179, 89, 180, + 320, 319, 404, + 90, 180, 89, + 352, 7, 420, + 123, 197, 7, + 198, 420, 7, + 198, 7, 197, + 325, 319, 326, + 96, 97, 89, + 320, 326, 319, + 90, 89, 97, + 398, 368, 366, + 173, 137, 139, + 365, 366, 368, + 136, 139, 137, + 289, 436, 398, + 59, 173, 216, + 368, 398, 436, + 139, 216, 173, + 439, 440, 345, + 219, 116, 220, + 279, 345, 440, + 49, 220, 116, + 272, 312, 273, + 42, 43, 82, + 311, 273, 312, + 81, 82, 43, + 6, 282, 196, + 6, 196, 52, + 249, 196, 282, + 4, 52, 196, + 274, 288, 376, + 44, 147, 58, + 292, 376, 288, + 62, 58, 147, + 397, 429, 176, + 172, 176, 209, + 200, 176, 429, + 200, 209, 176, + 269, 313, 272, + 39, 42, 83, + 312, 272, 313, + 82, 83, 42, + 445, 446, 284, + 225, 54, 226, + 277, 284, 446, + 47, 226, 54, + 255, 340, 374, + 25, 145, 111, + 391, 374, 340, + 164, 111, 145, + 296, 283, 297, + 66, 67, 53, + 335, 297, 283, + 106, 53, 67, + 347, 449, 348, + 118, 119, 229, + 450, 348, 449, + 230, 229, 119, + 455, 357, 448, + 235, 228, 128, + 265, 448, 357, + 35, 128, 228, + 337, 297, 338, + 108, 109, 67, + 300, 338, 297, + 70, 67, 109, + 152, 338, 11, + 152, 11, 109, + 339, 11, 338, + 110, 109, 11, + 279, 440, 295, + 49, 65, 220, + 456, 295, 440, + 236, 220, 65, + 408, 416, 293, + 184, 63, 192, + 309, 293, 416, + 79, 192, 63, + 359, 372, 430, + 130, 210, 143, + 356, 430, 372, + 127, 143, 210, + 346, 373, 341, + 117, 112, 144, + 266, 341, 373, + 36, 144, 112, + 389, 391, 467, + 162, 247, 164, + 250, 467, 391, + 8, 164, 247, + 353, 347, 281, + 124, 51, 118, + 348, 281, 347, + 119, 118, 51, + 296, 443, 283, + 66, 53, 223, + 444, 283, 443, + 224, 223, 53, + 20, 95, 355, + 20, 126, 95, + 371, 355, 95, + 142, 95, 126, + 296, 286, 443, + 66, 223, 56, + 442, 443, 286, + 222, 56, 223, + 420, 198, 249, + 197, 4, 198, + 196, 249, 198, + 196, 198, 4, + 360, 264, 256, + 131, 26, 34, + 250, 256, 264, + 8, 34, 26, + 276, 275, 441, + 46, 221, 45, + 458, 441, 275, + 238, 45, 221, + 301, 384, 302, + 71, 72, 157, + 369, 302, 384, + 140, 157, 72, + 418, 352, 466, + 194, 246, 123, + 413, 466, 352, + 189, 123, 246, + 467, 264, 468, + 247, 248, 34, + 360, 468, 264, + 131, 34, 248, + 390, 252, 369, + 163, 140, 22, + 302, 369, 252, + 72, 22, 140, + 375, 387, 381, + 146, 154, 160, + 386, 381, 387, + 159, 160, 154, + 380, 395, 379, + 151, 150, 170, + 396, 379, 395, + 171, 170, 150, + 352, 420, 413, + 123, 189, 197, + 400, 413, 420, + 175, 197, 189, + 427, 323, 437, + 207, 217, 93, + 411, 437, 323, + 187, 93, 217, + 388, 374, 389, + 161, 162, 145, + 391, 389, 374, + 164, 145, 162, + 394, 327, 165, + 168, 165, 98, + 3, 165, 327, + 3, 98, 165, + 355, 371, 462, + 126, 242, 142, + 463, 462, 371, + 243, 142, 242, + 1, 268, 165, + 1, 165, 38, + 394, 165, 268, + 168, 38, 165, + 12, 13, 303, + 12, 73, 13, + 269, 303, 13, + 39, 13, 73, + 387, 375, 388, + 160, 161, 146, + 374, 388, 375, + 145, 146, 161, + 13, 14, 269, + 13, 39, 14, + 313, 269, 14, + 83, 14, 39, + 294, 301, 299, + 64, 69, 71, + 302, 299, 301, + 72, 71, 69, + 341, 266, 262, + 112, 32, 36, + 447, 262, 266, + 227, 36, 32, + 381, 386, 382, + 154, 155, 159, + 385, 382, 386, + 158, 159, 155, + 281, 331, 426, + 51, 206, 102, + 267, 426, 331, + 37, 102, 206, + 424, 392, 427, + 204, 207, 166, + 323, 427, 392, + 93, 166, 207, + 430, 356, 421, + 210, 199, 127, + 438, 421, 356, + 218, 127, 199, + 392, 328, 394, + 166, 168, 99, + 327, 394, 328, + 98, 99, 168, + 458, 439, 441, + 238, 221, 219, + 345, 441, 439, + 116, 219, 221, + 383, 363, 342, + 156, 113, 134, + 464, 342, 363, + 244, 134, 113, + 458, 462, 460, + 238, 240, 242, + 459, 460, 462, + 239, 242, 240, + 435, 431, 365, + 215, 136, 211, + 395, 365, 431, + 170, 211, 136, + 415, 464, 399, + 191, 174, 244, + 363, 399, 464, + 134, 244, 174, + 263, 429, 370, + 33, 141, 209, + 397, 370, 429, + 172, 209, 141, + 458, 275, 462, + 238, 242, 45, + 355, 462, 275, + 126, 45, 242, + 317, 404, 318, + 87, 88, 180, + 403, 318, 404, + 179, 180, 88, + 316, 405, 317, + 86, 87, 181, + 404, 317, 405, + 180, 181, 87, + 315, 406, 316, + 85, 86, 182, + 405, 316, 406, + 181, 182, 86, + 314, 407, 315, + 84, 85, 183, + 406, 315, 407, + 182, 183, 85, + 419, 407, 422, + 195, 202, 183, + 314, 422, 407, + 84, 183, 202, + 367, 402, 324, + 138, 94, 178, + 362, 324, 402, + 133, 178, 94, + 409, 408, 307, + 185, 77, 184, + 293, 307, 408, + 63, 184, 77, + 409, 307, 410, + 185, 186, 77, + 292, 410, 307, + 62, 77, 186, + 411, 410, 288, + 187, 58, 186, + 292, 288, 410, + 62, 186, 58, + 437, 411, 433, + 217, 213, 187, + 288, 433, 411, + 58, 187, 213, + 435, 417, 428, + 215, 208, 193, + 412, 428, 417, + 188, 193, 208, + 265, 369, 373, + 35, 144, 140, + 384, 373, 369, + 157, 140, 144, + 458, 460, 439, + 238, 219, 240, + 310, 439, 460, + 80, 240, 219, + 353, 377, 367, + 124, 138, 148, + 402, 367, 377, + 178, 148, 138, + 5, 2, 276, + 5, 46, 2, + 275, 276, 2, + 45, 2, 46, + 429, 263, 422, + 209, 202, 33, + 419, 422, 263, + 195, 33, 202, + 328, 359, 295, + 99, 65, 130, + 332, 295, 359, + 103, 130, 65, + 368, 436, 417, + 139, 193, 216, + 434, 417, 436, + 214, 216, 193, + 456, 440, 290, + 236, 60, 220, + 393, 290, 440, + 167, 220, 60, + 329, 463, 327, + 100, 98, 243, + 371, 327, 463, + 142, 243, 98, + 327, 371, 3, + 98, 3, 142, + 95, 3, 371, + 95, 142, 3, + 461, 456, 306, + 241, 76, 236, + 290, 306, 456, + 60, 236, 76, + 449, 340, 450, + 229, 230, 111, + 255, 450, 340, + 25, 111, 230, + 262, 447, 256, + 32, 26, 227, + 360, 256, 447, + 131, 227, 26, + 450, 255, 451, + 230, 231, 25, + 254, 451, 255, + 24, 25, 231, + 451, 254, 452, + 231, 232, 24, + 253, 452, 254, + 23, 24, 232, + 452, 253, 453, + 232, 233, 23, + 257, 453, 253, + 27, 23, 233, + 257, 342, 453, + 27, 233, 113, + 454, 453, 342, + 234, 113, 233, + 414, 465, 415, + 190, 191, 245, + 464, 415, 465, + 244, 245, 191, + 442, 414, 287, + 222, 57, 190, + 415, 287, 414, + 191, 190, 57, + 442, 287, 443, + 222, 223, 57, + 259, 443, 287, + 29, 57, 223, + 443, 259, 444, + 223, 224, 29, + 258, 444, 259, + 28, 29, 224, + 445, 444, 260, + 225, 30, 224, + 258, 260, 444, + 28, 224, 30, + 260, 261, 445, + 30, 225, 31, + 446, 445, 261, + 226, 31, 225, + 261, 468, 446, + 31, 226, 248, + 343, 446, 468, + 114, 248, 226, + 251, 310, 459, + 21, 239, 80, + 460, 459, 310, + 240, 80, 239, + 291, 306, 393, + 61, 167, 76, + 290, 393, 306, + 60, 76, 167, + 461, 306, 329, + 241, 100, 76, + 291, 329, 306, + 61, 76, 100, + 377, 434, 402, + 148, 178, 214, + 436, 402, 434, + 216, 214, 178, + 251, 291, 310, + 21, 80, 61, + 393, 310, 291, + 167, 61, 80, + 412, 417, 377, + 188, 148, 193, + 434, 377, 417, + 214, 193, 148, + 342, 464, 454, + 113, 234, 244, + 465, 454, 464, + 245, 244, 234, + 454, 465, 358, + 234, 129, 245, + 466, 358, 465, + 246, 245, 129, + 413, 344, 466, + 189, 246, 115, + 358, 466, 344, + 129, 115, 246, + 438, 344, 400, + 218, 175, 115, + 413, 400, 344, + 189, 115, 175, + 364, 441, 361, + 135, 132, 221, + 345, 361, 441, + 116, 221, 132, + 457, 421, 400, + 237, 175, 199, + 438, 400, 421, + 218, 199, 175, + 457, 364, 421, + 237, 199, 135, + 361, 421, 364, + 132, 135, 199, + 362, 402, 289, + 133, 59, 178, + 436, 289, 402, + 216, 178, 59, + 354, 266, 384, + 125, 157, 36, + 373, 384, 266, + 144, 36, 157, + 256, 250, 340, + 26, 111, 8, + 391, 340, 250, + 164, 8, 111, + 262, 256, 449, + 32, 229, 26, + 340, 449, 256, + 111, 26, 229, + 15, 318, 14, + 15, 14, 88, + 313, 14, 318, + 83, 88, 14, + 318, 403, 313, + 88, 83, 179, + 312, 313, 403, + 82, 179, 83, + 403, 319, 312, + 179, 82, 89, + 311, 312, 319, + 81, 89, 82, + 319, 325, 311, + 89, 81, 96, + 416, 311, 325, + 192, 96, 81]; + +let tc = [0.499977, 0.652534, 0.500026, 0.5474870000000001, 0.499974, 0.602372, 0.482113, 0.47197900000000004, 0.500151, 0.527156, 0.49991, 0.49825299999999995, 0.499523, 0.40106200000000003, 0.289712, 0.380764, 0.499955, 0.31239799999999995, 0.499987, 0.269919, 0.500023, 0.10704999999999998, 0.500023, 0.666234, 0.500016, 0.679224, 0.500023, 0.692348, 0.499977, 0.6952780000000001, 0.499977, 0.7059340000000001, 0.499977, 0.7193849999999999, 0.499977, 0.737019, 0.499968, 0.781371, 0.499816, 0.562981, 0.473773, 0.5739099999999999, 0.104907, 0.25414099999999995, 0.36593, 0.40957600000000005, 0.338758, 0.413025, 0.31112, 0.40946000000000005, 0.274658, 0.389131, 0.393362, 0.403706, 0.345234, 0.34401099999999996, 0.370094, 0.34607600000000005, 0.319322, 0.34726500000000005, 0.297903, 0.353591, 0.247792, 0.41081, 0.396889, 0.842755, 0.280098, 0.37560000000000004, 0.10631, 0.399956, 0.209925, 0.39135299999999995, 0.355808, 0.5344059999999999, 0.471751, 0.650404, 0.474155, 0.680192, 0.439785, 0.6572290000000001, 0.414617, 0.666541, 0.450374, 0.6808609999999999, 0.428771, 0.6826909999999999, 0.374971, 0.727805, 0.486717, 0.5476289999999999, 0.485301, 0.5273950000000001, 0.257765, 0.31449000000000005, 0.401223, 0.455172, 0.429819, 0.5486150000000001, 0.421352, 0.533741, 0.276896, 0.532057, 0.48337, 0.499587, 0.337212, 0.282883, 0.296392, 0.29324300000000003, 0.169295, 0.19381400000000004, 0.44758, 0.30261000000000005, 0.39239, 0.353888, 0.35449, 0.6967840000000001, 0.067305, 0.730105, 0.442739, 0.5728260000000001, 0.457098, 0.584792, 0.381974, 0.6947110000000001, 0.392389, 0.694203, 0.277076, 0.27193199999999995, 0.422552, 0.563233, 0.385919, 0.28136399999999995, 0.383103, 0.25583999999999996, 0.331431, 0.11971399999999999, 0.229924, 0.23200299999999996, 0.364501, 0.189114, 0.229622, 0.29954099999999995, 0.173287, 0.278748, 0.472879, 0.6661980000000001, 0.446828, 0.668527, 0.422762, 0.67389, 0.445308, 0.580066, 0.388103, 0.693961, 0.403039, 0.70654, 0.403629, 0.693953, 0.460042, 0.557139, 0.431158, 0.692366, 0.452182, 0.692366, 0.475387, 0.692366, 0.465828, 0.77919, 0.472329, 0.736226, 0.473087, 0.717857, 0.473122, 0.704626, 0.473033, 0.6952780000000001, 0.427942, 0.6952780000000001, 0.426479, 0.70354, 0.423162, 0.711846, 0.418309, 0.720063, 0.390095, 0.639573, 0.013954, 0.5600339999999999, 0.499914, 0.580147, 0.4132, 0.6954, 0.409626, 0.701823, 0.46808, 0.6015349999999999, 0.422729, 0.585985, 0.46308, 0.593784, 0.37212, 0.473414, 0.334562, 0.496073, 0.411671, 0.5469649999999999, 0.242176, 0.14767600000000003, 0.290777, 0.20144600000000001, 0.327338, 0.25652699999999995, 0.39951, 0.748921, 0.441728, 0.261676, 0.429765, 0.18783399999999995, 0.412198, 0.10890100000000003, 0.288955, 0.398952, 0.218937, 0.435411, 0.412782, 0.39897000000000005, 0.257135, 0.35544, 0.427685, 0.43796100000000004, 0.44834, 0.5369360000000001, 0.17856, 0.457554, 0.247308, 0.457194, 0.286267, 0.46767499999999995, 0.332828, 0.460712, 0.368756, 0.447207, 0.398964, 0.432655, 0.47641, 0.405806, 0.189241, 0.5239240000000001, 0.228962, 0.348951, 0.490726, 0.5624009999999999, 0.40467, 0.48513300000000004, 0.019469, 0.40156400000000003, 0.426243, 0.420431, 0.396993, 0.548797, 0.26647, 0.376977, 0.439121, 0.518958, 0.032314, 0.6443570000000001, 0.419054, 0.387155, 0.462783, 0.505747, 0.238979, 0.779745, 0.198221, 0.8319380000000001, 0.10755, 0.540755, 0.18361, 0.7402569999999999, 0.13441, 0.33368299999999995, 0.385764, 0.883154, 0.490967, 0.579378, 0.382385, 0.5085729999999999, 0.174399, 0.397671, 0.318785, 0.396235, 0.343364, 0.400597, 0.3961, 0.710217, 0.187885, 0.588538, 0.430987, 0.944065, 0.318993, 0.898285, 0.266248, 0.8697010000000001, 0.500023, 0.19057599999999997, 0.499977, 0.954453, 0.36617, 0.398822, 0.393207, 0.395537, 0.410373, 0.39108, 0.194993, 0.342102, 0.388665, 0.36228400000000005, 0.365962, 0.35597100000000004, 0.343364, 0.35535700000000003, 0.318785, 0.35834, 0.301415, 0.36315600000000003, 0.058133, 0.319076, 0.301415, 0.38744900000000004, 0.499988, 0.6184339999999999, 0.415838, 0.624196, 0.445682, 0.5660769999999999, 0.465844, 0.620641, 0.499923, 0.35152399999999995, 0.288719, 0.8199460000000001, 0.335279, 0.85282, 0.440512, 0.902419, 0.128294, 0.791941, 0.408772, 0.37389399999999995, 0.455607, 0.451801, 0.499877, 0.90899, 0.375437, 0.924192, 0.11421, 0.615022, 0.448662, 0.6952780000000001, 0.44802, 0.7046319999999999, 0.447112, 0.715808, 0.444832, 0.7307939999999999, 0.430012, 0.766809, 0.406787, 0.685673, 0.400738, 0.6810689999999999, 0.3924, 0.6777029999999999, 0.367856, 0.6639189999999999, 0.247923, 0.601333, 0.45277, 0.42084999999999995, 0.436392, 0.35988699999999996, 0.416164, 0.368714, 0.413386, 0.692366, 0.228018, 0.6835720000000001, 0.468268, 0.35267099999999996, 0.411362, 0.804327, 0.499989, 0.46982500000000005, 0.479154, 0.442654, 0.499974, 0.43963699999999994, 0.432112, 0.49358900000000006, 0.499886, 0.8669169999999999, 0.499913, 0.8217289999999999, 0.456549, 0.8192010000000001, 0.344549, 0.745439, 0.378909, 0.57401, 0.374293, 0.780185, 0.319688, 0.570738, 0.357155, 0.60427, 0.295284, 0.6215809999999999, 0.44775, 0.8624769999999999, 0.410986, 0.508723, 0.313951, 0.775308, 0.354128, 0.812553, 0.324548, 0.703993, 0.189096, 0.6463, 0.279777, 0.714658, 0.133823, 0.682701, 0.336768, 0.644733, 0.429884, 0.466522, 0.455528, 0.5486230000000001, 0.437114, 0.5588960000000001, 0.467288, 0.529925, 0.414712, 0.33521999999999996, 0.377046, 0.322778, 0.344108, 0.32015099999999996, 0.312876, 0.32233199999999995, 0.283526, 0.33319, 0.241246, 0.38278599999999996, 0.102986, 0.46876300000000004, 0.267612, 0.42456000000000005, 0.297879, 0.433176, 0.333434, 0.433878, 0.366427, 0.42611600000000005, 0.396012, 0.41669599999999996, 0.420121, 0.41022800000000004, 0.007561, 0.480777, 0.432949, 0.569518, 0.458639, 0.479089, 0.473466, 0.545744, 0.476088, 0.56383, 0.468472, 0.555057, 0.433991, 0.582362, 0.483518, 0.5629839999999999, 0.482483, 0.5778490000000001, 0.42645, 0.389799, 0.438999, 0.39649500000000004, 0.450067, 0.40043399999999996, 0.289712, 0.36825300000000005, 0.27667, 0.36337299999999995, 0.517862, 0.47194800000000003, 0.710288, 0.380764, 0.526227, 0.5739099999999999, 0.895093, 0.25414099999999995, 0.63407, 0.40957600000000005, 0.661242, 0.413025, 0.68888, 0.40946000000000005, 0.725342, 0.389131, 0.60663, 0.403705, 0.654766, 0.34401099999999996, 0.629906, 0.34607600000000005, 0.680678, 0.34726500000000005, 0.702097, 0.353591, 0.752212, 0.410805, 0.602918, 0.842863, 0.719902, 0.37560000000000004, 0.893693, 0.39996, 0.790082, 0.391354, 0.643998, 0.5344880000000001, 0.528249, 0.650404, 0.52585, 0.680191, 0.560215, 0.6572290000000001, 0.585384, 0.666541, 0.549626, 0.6808609999999999, 0.571228, 0.6826920000000001, 0.624852, 0.728099, 0.51305, 0.547282, 0.515097, 0.527252, 0.742247, 0.314507, 0.598631, 0.454979, 0.570338, 0.548575, 0.578632, 0.533623, 0.723087, 0.532054, 0.516446, 0.49963900000000006, 0.662801, 0.282918, 0.703624, 0.29327099999999995, 0.830705, 0.19381400000000004, 0.552386, 0.30256799999999995, 0.60761, 0.353888, 0.645429, 0.696707, 0.932695, 0.730105, 0.557261, 0.5728260000000001, 0.542902, 0.584792, 0.618026, 0.6947110000000001, 0.607591, 0.694203, 0.722943, 0.27196299999999995, 0.577414, 0.563167, 0.614083, 0.28138700000000005, 0.616907, 0.25588599999999995, 0.668509, 0.11991399999999997, 0.770092, 0.23202100000000003, 0.635536, 0.189249, 0.770391, 0.29955600000000004, 0.826722, 0.278755, 0.527121, 0.6661980000000001, 0.553172, 0.668527, 0.577238, 0.67389, 0.554692, 0.580066, 0.611897, 0.693961, 0.596961, 0.70654, 0.596371, 0.693953, 0.539958, 0.557139, 0.568842, 0.692366, 0.547818, 0.692366, 0.524613, 0.692366, 0.53409, 0.779141, 0.527671, 0.736226, 0.526913, 0.717857, 0.526878, 0.704626, 0.526967, 0.6952780000000001, 0.572058, 0.6952780000000001, 0.573521, 0.70354, 0.576838, 0.711846, 0.581691, 0.720063, 0.609945, 0.63991, 0.986046, 0.5600339999999999, 0.5868, 0.6954, 0.590372, 0.701823, 0.531915, 0.601537, 0.577268, 0.585935, 0.536915, 0.5937859999999999, 0.627543, 0.473352, 0.665586, 0.49595100000000003, 0.588354, 0.546862, 0.757824, 0.14767600000000003, 0.70925, 0.20150800000000002, 0.672684, 0.25658099999999995, 0.600409, 0.7490049999999999, 0.558266, 0.261672, 0.570304, 0.187871, 0.588166, 0.10904400000000003, 0.711045, 0.398952, 0.78107, 0.43540500000000004, 0.587247, 0.39893199999999995, 0.74287, 0.35544600000000004, 0.572156, 0.43765200000000004, 0.551868, 0.53657, 0.821442, 0.45755599999999996, 0.752702, 0.457182, 0.713757, 0.467627, 0.667113, 0.460673, 0.631101, 0.44715400000000005, 0.600862, 0.432473, 0.523481, 0.40562699999999996, 0.810748, 0.523926, 0.771046, 0.348959, 0.509127, 0.562718, 0.595293, 0.485024, 0.980531, 0.40156400000000003, 0.5735, 0.42000000000000004, 0.602995, 0.5486880000000001, 0.73353, 0.376977, 0.560611, 0.5190170000000001, 0.967686, 0.6443570000000001, 0.580985, 0.38715999999999995, 0.537728, 0.505385, 0.760966, 0.779753, 0.801779, 0.8319380000000001, 0.892441, 0.540761, 0.816351, 0.7402599999999999, 0.865595, 0.33368699999999996, 0.614074, 0.883246, 0.508953, 0.579438, 0.617942, 0.508316, 0.825608, 0.397675, 0.681215, 0.396235, 0.656636, 0.400597, 0.6039, 0.710217, 0.812086, 0.5885389999999999, 0.568013, 0.944565, 0.681008, 0.898285, 0.733752, 0.8697010000000001, 0.63383, 0.398822, 0.606793, 0.395537, 0.58966, 0.391062, 0.805016, 0.34210799999999997, 0.611335, 0.36228400000000005, 0.634038, 0.35597100000000004, 0.656636, 0.35535700000000003, 0.681215, 0.35834, 0.698585, 0.36315600000000003, 0.941867, 0.319076, 0.698585, 0.38744900000000004, 0.584177, 0.624107, 0.554318, 0.5660769999999999, 0.534154, 0.6206400000000001, 0.711218, 0.819975, 0.66463, 0.8528709999999999, 0.5591, 0.902632, 0.871706, 0.791941, 0.591234, 0.37389399999999995, 0.544341, 0.451584, 0.624563, 0.924192, 0.88577, 0.615029, 0.551338, 0.6952780000000001, 0.55198, 0.7046319999999999, 0.552888, 0.715808, 0.555168, 0.7307939999999999, 0.569944, 0.767035, 0.593203, 0.685676, 0.599262, 0.6810689999999999, 0.6076, 0.6777029999999999, 0.631938, 0.6635, 0.752033, 0.601315, 0.547226, 0.42039499999999996, 0.563544, 0.35982800000000004, 0.583841, 0.368714, 0.586614, 0.692366, 0.771915, 0.683578, 0.531597, 0.352483, 0.588371, 0.804441, 0.520797, 0.442565, 0.567985, 0.493479, 0.543283, 0.8192550000000001, 0.655317, 0.7455149999999999, 0.621009, 0.5740179999999999, 0.62556, 0.780312, 0.680198, 0.570719, 0.642764, 0.604338, 0.704663, 0.62153, 0.552012, 0.862592, 0.589072, 0.508637, 0.685945, 0.775357, 0.645735, 0.81264, 0.675343, 0.703978, 0.810858, 0.646305, 0.720122, 0.7146669999999999, 0.866152, 0.682705, 0.663187, 0.644597, 0.570082, 0.466326, 0.544562, 0.548376, 0.562759, 0.558785, 0.531987, 0.5301400000000001, 0.585271, 0.33517699999999995, 0.622953, 0.32277900000000004, 0.655896, 0.320163, 0.687132, 0.322346, 0.716482, 0.33320099999999997, 0.758757, 0.382787, 0.897013, 0.468769, 0.732392, 0.424547, 0.702114, 0.43316299999999996, 0.666525, 0.433866, 0.633505, 0.426088, 0.603876, 0.41658700000000004, 0.579658, 0.409945, 0.99244, 0.480777, 0.567192, 0.56942, 0.541366, 0.47889899999999996, 0.526564, 0.546118, 0.523913, 0.56383, 0.531529, 0.555057, 0.566036, 0.582329, 0.516311, 0.5630539999999999, 0.517472, 0.577877, 0.573595, 0.389807, 0.560698, 0.395332, 0.549756, 0.39975099999999997, 0.710288, 0.36825300000000005, 0.72333, 0.36337299999999995]; + +for (let i = 0; i < faces.length; i++) +{ + faces[i]--; +} + +const geom = new CGL.Geometry("fratze"); +geom.clear(); + +geom.vertices = new Float32Array(verts); +geom.texCoords = new Float32Array(tc); + +geom.vertexNormals = new Float32Array(verts); +geom.verticesIndices = faces; + +outGeom.set(null); +outGeom.set(geom); + +const g = geom.copy(); + + +}; + +Ops.Libs.Mediapipe.FaceMesh.prototype = new CABLES.Op(); +CABLES.OPS["7e13efda-330f-4c5e-bc84-e14e5af99cd4"]={f:Ops.Libs.Mediapipe.FaceMesh,objName:"Ops.Libs.Mediapipe.FaceMesh"}; + + + + +// ************************************************************** +// +// Ops.Libs.Mediapipe.MpFaceTracking +// +// ************************************************************** + +Ops.Libs.Mediapipe.MpFaceTracking = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inEle = op.inObject("Element"), + inRefineLand = op.inBool("Refine LandMarks", false), + outPoints = op.outArray("Points"), + outFound = op.outNumber("Found"), + outResult = op.outObject("Result"); + +// https://google.github.io/mediapipe/solutions/face_mesh.html + +let camera = null; + +inRefineLand.onChange = setOptions; + +inEle.onChange = () => +{ + const el = inEle.get(); + if (!el) return; + + camera = new Camera(el, { + "onFrame": async () => + { + await faceMesh.send({ "image": el }); + }, + "width": el.width, + "height": el.height + }); + camera.start(); +}; + +const faceMesh = new FaceMesh({ "locateFile": (file) => + `https://cdn.jsdelivr.net/npm/@mediapipe/face_mesh/${file}` }); + +faceMesh.setOptions({ + "maxNumFaces": 1, + "minDetectionConfidence": 0.5, + "minTrackingConfidence": 0.5 +}); + +setOptions(); + +function setOptions() +{ + faceMesh.setOptions({ + "maxNumFaces": 1, + "minDetectionConfidence": 0.5, + "minTrackingConfidence": 0.5, + "refineLandmarks": inRefineLand.get() + }); +} + +faceMesh.onResults((r) => +{ + let points = []; + + if (r && r.multiFaceLandmarks) + { + outFound.set(r.multiFaceLandmarks.length); + if (r.multiFaceLandmarks[0]) for (let i = 0; i < r.multiFaceLandmarks[0].length; i++) + { + points.push( + (r.multiFaceLandmarks[0][i].x - 0.5) * 2, + -1 * (r.multiFaceLandmarks[0][i].y - 0.5) * 2, 0); + } + } + else outFound.set(0); + + outPoints.set(points); + outResult.set(r); +}); + + +}; + +Ops.Libs.Mediapipe.MpFaceTracking.prototype = new CABLES.Op(); +CABLES.OPS["57df26fc-916c-469b-a343-83572c731025"]={f:Ops.Libs.Mediapipe.MpFaceTracking,objName:"Ops.Libs.Mediapipe.MpFaceTracking"}; + + + + +// ************************************************************** +// +// Ops.Libs.Mediapipe.MpHand +// +// ************************************************************** + +Ops.Libs.Mediapipe.MpHand = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inMpResult = op.inObject("Hands Result"), + inWhichHand = op.inSwitch("Hand", ["Left", "Right"], "Left"), + inMinScore = op.inFloatSlider("Min Score", 0.2), + outPoints = op.outArray("Points"), + outLines = op.outArray("Lines"), + outResult = op.outObject("Data"), + outFound = op.outBoolNum("Found Hand"), + outScore = op.outNumber("Score"); + +function getLines(points) +{ + const lines = []; + lines.push(points[0 * 3 + 0], points[0 * 3 + 1], points[0 * 3 + 2]); // thumb + lines.push(points[1 * 3 + 0], points[1 * 3 + 1], points[1 * 3 + 2]); + lines.push(points[1 * 3 + 0], points[1 * 3 + 1], points[1 * 3 + 2]); + lines.push(points[2 * 3 + 0], points[2 * 3 + 1], points[2 * 3 + 2]); + lines.push(points[2 * 3 + 0], points[2 * 3 + 1], points[2 * 3 + 2]); + lines.push(points[3 * 3 + 0], points[3 * 3 + 1], points[3 * 3 + 2]); + lines.push(points[3 * 3 + 0], points[3 * 3 + 1], points[3 * 3 + 2]); + lines.push(points[4 * 3 + 0], points[4 * 3 + 1], points[4 * 3 + 2]); + + lines.push(points[0 * 3 + 0], points[0 * 3 + 1], points[0 * 3 + 2]); // wrist + lines.push(points[5 * 3 + 0], points[5 * 3 + 1], points[5 * 3 + 2]); + lines.push(points[5 * 3 + 0], points[5 * 3 + 1], points[5 * 3 + 2]); + lines.push(points[9 * 3 + 0], points[9 * 3 + 1], points[9 * 3 + 2]); + lines.push(points[9 * 3 + 0], points[9 * 3 + 1], points[9 * 3 + 2]); + lines.push(points[13 * 3 + 0], points[13 * 3 + 1], points[13 * 3 + 2]); + lines.push(points[13 * 3 + 0], points[13 * 3 + 1], points[13 * 3 + 2]); + lines.push(points[17 * 3 + 0], points[17 * 3 + 1], points[17 * 3 + 2]); + lines.push(points[17 * 3 + 0], points[17 * 3 + 1], points[17 * 3 + 2]); + lines.push(points[0 * 3 + 0], points[0 * 3 + 1], points[0 * 3 + 2]); + + lines.push(points[5 * 3 + 0], points[5 * 3 + 1], points[5 * 3 + 2]); // index finger + lines.push(points[6 * 3 + 0], points[6 * 3 + 1], points[6 * 3 + 2]); + lines.push(points[6 * 3 + 0], points[6 * 3 + 1], points[6 * 3 + 2]); + lines.push(points[7 * 3 + 0], points[7 * 3 + 1], points[7 * 3 + 2]); + lines.push(points[7 * 3 + 0], points[7 * 3 + 1], points[7 * 3 + 2]); + lines.push(points[8 * 3 + 0], points[8 * 3 + 1], points[8 * 3 + 2]); + + lines.push(points[9 * 3 + 0], points[9 * 3 + 1], points[9 * 3 + 2]); // middle finger + lines.push(points[10 * 3 + 0], points[10 * 3 + 1], points[10 * 3 + 2]); + lines.push(points[10 * 3 + 0], points[10 * 3 + 1], points[10 * 3 + 2]); + lines.push(points[11 * 3 + 0], points[11 * 3 + 1], points[11 * 3 + 2]); + lines.push(points[11 * 3 + 0], points[11 * 3 + 1], points[11 * 3 + 2]); + lines.push(points[12 * 3 + 0], points[12 * 3 + 1], points[12 * 3 + 2]); + + lines.push(points[13 * 3 + 0], points[13 * 3 + 1], points[13 * 3 + 2]); // ring finger + lines.push(points[14 * 3 + 0], points[14 * 3 + 1], points[14 * 3 + 2]); + lines.push(points[14 * 3 + 0], points[14 * 3 + 1], points[14 * 3 + 2]); + lines.push(points[15 * 3 + 0], points[15 * 3 + 1], points[15 * 3 + 2]); + lines.push(points[15 * 3 + 0], points[15 * 3 + 1], points[15 * 3 + 2]); + lines.push(points[16 * 3 + 0], points[16 * 3 + 1], points[16 * 3 + 2]); + + lines.push(points[17 * 3 + 0], points[17 * 3 + 1], points[17 * 3 + 2]); // ring finger + lines.push(points[18 * 3 + 0], points[18 * 3 + 1], points[18 * 3 + 2]); + lines.push(points[18 * 3 + 0], points[18 * 3 + 1], points[18 * 3 + 2]); + lines.push(points[19 * 3 + 0], points[19 * 3 + 1], points[19 * 3 + 2]); + lines.push(points[19 * 3 + 0], points[19 * 3 + 1], points[19 * 3 + 2]); + lines.push(points[20 * 3 + 0], points[20 * 3 + 1], points[20 * 3 + 2]); + + return lines; +} + +inMpResult.onChange = () => +{ + let points = []; + let points2 = []; + let lines = null; + let lines2 = null; + let r = inMpResult.get(); + + if (r && r.multiHandedness) + { + + } + else + { + outFound.set(false); + outScore.set(0); + return; + } + + let idx = 0; + + let found = false; + + if (r.multiHandedness) + { + for (let i = 0; i < r.multiHandedness.length; i++) + { + if (r.multiHandedness[i].label == inWhichHand.get()) + { + idx = i; + outScore.set(r.multiHandedness[i].score); + found = true; + } + } + } + + if (found && outScore.get() > inMinScore.get()) + { + outFound.set(true); + if (r && r.multiHandLandmarks && r.multiHandLandmarks[idx]) + { + for (let i = 0; i < r.multiHandLandmarks[idx].length; i++) + { + points[i * 3] = (r.multiHandLandmarks[idx][i].x - 0.5) * 2; + points[i * 3 + 1] = -1 * (r.multiHandLandmarks[idx][i].y - 0.5) * 2; + points[i * 3 + 2] = 0; + } + lines = getLines(points); + + outPoints.set(points); + outLines.set(lines); + outResult.set(r.multiHandLandmarks[idx]); + } + } + else + { + outResult.set(null); + outPoints.set(null); + outLines.set(null); + + outFound.set(false); + } +}; + + +}; + +Ops.Libs.Mediapipe.MpHand.prototype = new CABLES.Op(); +CABLES.OPS["935b0d02-1dce-4d5c-87a8-f1fa36c5d25e"]={f:Ops.Libs.Mediapipe.MpHand,objName:"Ops.Libs.Mediapipe.MpHand"}; + + + + +// ************************************************************** +// +// Ops.Libs.Mediapipe.MpHandCoordinate +// +// ************************************************************** + +Ops.Libs.Mediapipe.MpHandCoordinate = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; + +// https://google.github.io/mediapipe/solutions/hands.html + +const marks=["WRIST","THUMB_CMC","THUMB_MCP","THUMB_IP","THUMB_TIP","INDEX_FINGER_MCP","INDEX_FINGER_PIP","INDEX_FINGER_DIP","INDEX_FINGER_TIP","MIDDLE_FINGER_MCP","MIDDLE_FINGER_PIP","MIDDLE_FINGER_DIP","MIDDLE_FINGER_TIP","RING_FINGER_MCP","RING_FINGER_PIP","RING_FINGER_DIP","RING_FINGER_TIP","PINKY_MCP","PINKY_PIP","PINKY_DIP","PINKY_TIP"]; + +const + inHand=op.inArray("Hand Points"), + inWhich=op.inDropDown("Joint",marks,"WRIST"), + outX=op.outNumber("X"), + outY=op.outNumber("Y"), + outZ=op.outNumber("Z"); + +let idx=0; + +inWhich.onChange=()=> +{ + idx=marks.indexOf(inWhich.get()); + update(); +}; + +inHand.onChange=update; + +function update() +{ + const arr=inHand.get(); + + if(arr && arr.length>idx*3) + { + outX.set(arr[idx*3+0]); + outY.set(arr[idx*3+1]); + outZ.set(arr[idx*3+2]); + } + +} + +}; + +Ops.Libs.Mediapipe.MpHandCoordinate.prototype = new CABLES.Op(); +CABLES.OPS["d3adef3d-5c99-48fd-86f0-48ec4a290afb"]={f:Ops.Libs.Mediapipe.MpHandCoordinate,objName:"Ops.Libs.Mediapipe.MpHandCoordinate"}; + + + + +// ************************************************************** +// +// Ops.Libs.Mediapipe.MpHandTracking +// +// ************************************************************** + +Ops.Libs.Mediapipe.MpHandTracking = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// todo: warn if ele not dom object , e..g. texture! + +const + inEle = op.inObject("Element", null, "element"), + inMinConfDetect = op.inFloatSlider("Min Confidence Detect", 0.5), + inMinConfTrack = op.inFloatSlider("Min Confidence Tracking", 0.5), + + outResult = op.outObject("Result"), + outFound = op.outNumber("Found Hands"); + +const hands = new Hands({ "locateFile": (file) => +{ return `https://cdn.jsdelivr.net/npm/@mediapipe/hands@0.1/${file}`; } }); + +let camera = null; +updateOptions(); + +inMinConfTrack.onChange = + inMinConfDetect.onChange = updateOptions; + +inEle.onChange = () => +{ + if (!inEle.get()) return; + + camera = new Camera(inEle.get(), { + "onFrame": async () => + { + const ele = inEle.get(); + + if (ele) await hands.send({ "image": ele }); + }, + "width": inEle.get().width, + "height": inEle.get().height + }); + camera.start(); +}; + +function updateOptions() +{ + hands.setOptions({ + "maxNumHands": 2, + "minDetectionConfidence": inMinConfDetect.get(), + "minTrackingConfidence": inMinConfTrack.get() + }); +} + +hands.onResults((r) => +{ + if (r && r.multiHandedness) + { + outFound.set(r.multiHandedness.length); + } + else + { + outFound.set(0); + } + + outResult.set(r); +}); + + +}; + +Ops.Libs.Mediapipe.MpHandTracking.prototype = new CABLES.Op(); +CABLES.OPS["5251e50f-abaf-4ca3-a809-61f8ca58ec35"]={f:Ops.Libs.Mediapipe.MpHandTracking,objName:"Ops.Libs.Mediapipe.MpHandTracking"}; + + + + +// ************************************************************** +// +// Ops.Libs.Mediapipe.MpPoseGetCoordinate +// +// ************************************************************** + +Ops.Libs.Mediapipe.MpPoseGetCoordinate = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + marks = ["Nose", "Left eye inner", "Left eye", "Left eye outer", "Right eye inner", "Right eye", "Right eye outer", "Left ear", "Right ear", "Mouth left", "Mouth right", "Left shoulder", "Right shoulder", "Left elbow", "Right elbow", "Left wrist", "Right wrist", "Left pinky #1 knuckle", "Right pinky #1 knuckle", "Left index #1 knuckle", "Right index #1 knuckle", "Left thumb #2 knuckle", "Right thumb #2 knuckle", "Left hip", "Right hip", "Left knee", "Right knee", "Left ankle", "Right ankle", "Left heel", "Right heel", "Left foot index", "Right foot index"], + + inArr = op.inArray("Landmarks"), + inWhich = op.inDropDown("Landmark", marks, "Nose"), + outX = op.outNumber("X"), + outY = op.outNumber("Y"), + outZ = op.outNumber("Z"); + +let index = 0; + +inWhich.onChange = () => +{ + index = marks.indexOf(inWhich.get()); +}; + +inArr.onChange = () => +{ + const arr = inArr.get(); + + if (arr && arr[index]) + { + outX.set((arr[index].x - 0.5) * 2.0); + outY.set((arr[index].y - 0.5) * -2.0); + outZ.set(arr[index].z); + } +}; + + +}; + +Ops.Libs.Mediapipe.MpPoseGetCoordinate.prototype = new CABLES.Op(); +CABLES.OPS["725c90f3-3526-420f-b921-4d214c281e25"]={f:Ops.Libs.Mediapipe.MpPoseGetCoordinate,objName:"Ops.Libs.Mediapipe.MpPoseGetCoordinate"}; + + + + +// ************************************************************** +// +// Ops.Libs.Mediapipe.MpPoseTracking +// +// ************************************************************** + +Ops.Libs.Mediapipe.MpPoseTracking = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"texcopy_frag":"UNI sampler2D tex;\nIN vec2 texCoord;\n\n\nvoid main()\n{\n vec2 tc=vec2(texCoord.x,texCoord.y);\n\n #ifdef FLIPX\n tc.x=1.0-texCoord.x;\n #endif\n #ifdef FLIPY\n tc.y=1.0-texCoord.y;\n #endif\n outColor=texture(tex,tc);\n}",}; +// todo: warn if ele not dom object , e..g. texture! + +const + inEle = op.inObject("Element", null, "element"), + + inModelComplexity = op.inSwitch("Model Complexity", ["0", "1", "2"], "1"), + inSmoothLandmarks = op.inBool("Smooth Landmarks", true), + + inMinDetectionConfidence = op.inFloatSlider("Min Detection Confidence", 0.5), + inMinTrackingConfidence = op.inFloatSlider("Min Tracking Confidence", 0.5), + + inEnableSegmentation = op.inBool("Enable Segmentation", false), + inUpdateSeg = op.inTrigger("Update Texture"), + inSmoothSegmentation = op.inBool("Smooth Segmentation", false), + flipX = op.inValueBool("Flip X", false), + flipY = op.inValueBool("Flip Y", false), + + outPoints = op.outArray("Points"), + outTex = op.outTexture("Segmentation Mask"), + outLandmarks = op.outArray("Landmarks"), + outLines = op.outArray("Lines"), + outFound = op.outNumber("Found"); + +op.setPortGroup("Segmentation", [inEnableSegmentation, inSmoothSegmentation, flipX, flipY, inUpdateSeg]); + +const pose = new Pose({ "locateFile": (file) => +{ return `https://cdn.jsdelivr.net/npm/@mediapipe/pose/${file}`; } }); + +const cgl = op.patch.cgl; +let camera = null; +let lines = []; +let segMaskBitmap = null; +let points = []; +let points2 = []; +let tc = null; +let canvasTexture = null; + +updateOptions(); + +flipX.onChange = +flipY.onChange = initCopyShader; + +inSmoothLandmarks.onChange = + inModelComplexity.onChange = + inEnableSegmentation.onChange = + inSmoothSegmentation.onChange = + inMinDetectionConfidence.onChange = + inMinTrackingConfidence.onChange = updateOptions; + +function updateOptions() +{ + pose.setOptions({ + "modelComplexity": parseInt(inModelComplexity.get()), + "smoothLandmarks": inSmoothLandmarks.get(), + "enableSegmentation": inEnableSegmentation.get(), + "smoothSegmentation": inSmoothSegmentation.get(), + "minDetectionConfidence": inMinDetectionConfidence.get(), + "minTrackingConfidence": inMinTrackingConfidence.get() + }); + + inSmoothSegmentation.setUiAttribs({ "greyout": !inEnableSegmentation.get() }); + flipX.setUiAttribs({ "greyout": !inEnableSegmentation.get() }); + flipY.setUiAttribs({ "greyout": !inEnableSegmentation.get() }); +} + +function initCopyShader() +{ + if (!tc)tc = new CGL.CopyTexture(cgl, "webcamFlippedTexture", { "shader": attachments.texcopy_frag }); + tc.bgShader.toggleDefine("FLIPX", flipX.get()); + tc.bgShader.toggleDefine("FLIPY", !flipY.get()); +} + +inEle.onChange = () => +{ + const el = inEle.get(); + if (!el) + { + return; + } + camera = new Camera(el, { + "onFrame": async () => + { + await pose.send({ "image": el }); + }, + "width": el.width, + "height": el.height + }); + camera.start(); +}; + +inUpdateSeg.onTriggered = () => +{ + outTex.set(CGL.Texture.getEmptyTexture(cgl)); + if (!segMaskBitmap) return; + + if (!canvasTexture) + { + canvasTexture = new CGL.Texture.createFromImage(cgl, segMaskBitmap); + } + else + canvasTexture.initTexture(segMaskBitmap, CGL.Texture.FILTER_LINEAR); + + if (tc) + { + outTex.set(tc.copy(canvasTexture)); + } + else + outTex.set(canvasTexture); +}; + +pose.onResults((r) => +{ + if (r && r.poseLandmarks) + { + for (let i = 0; i < r.poseLandmarks.length; i++) + { + points[i * 3] = (r.poseLandmarks[i].x - 0.5) * 2.0; + points[i * 3 + 1] = (r.poseLandmarks[i].y - 0.5) * -2; + points[i * 3 + 2] = r.poseLandmarks[i].z * 1.0; + } + + if (r.segmentationMask) + { + segMaskBitmap = r.segmentationMask; + } + + outPoints.set(null); + outPoints.set(points); + + outLandmarks.set(r.poseLandmarks); + + lines = []; + + // top body + lines.push( + points[11 * 3 + 0], points[11 * 3 + 1], points[11 * 3 + 2], + points[12 * 3 + 0], points[12 * 3 + 1], points[12 * 3 + 2]); + lines.push( + points[12 * 3 + 0], points[12 * 3 + 1], points[12 * 3 + 2], + points[24 * 3 + 0], points[24 * 3 + 1], points[24 * 3 + 2]); + lines.push( + points[24 * 3 + 0], points[24 * 3 + 1], points[24 * 3 + 2], + points[23 * 3 + 0], points[23 * 3 + 1], points[23 * 3 + 2]); + lines.push( + points[11 * 3 + 0], points[11 * 3 + 1], points[11 * 3 + 2], + points[23 * 3 + 0], points[23 * 3 + 1], points[23 * 3 + 2]); + + // left arm + lines.push( + points[11 * 3 + 0], points[11 * 3 + 1], points[11 * 3 + 2], + points[13 * 3 + 0], points[13 * 3 + 1], points[13 * 3 + 2]); + lines.push( + points[13 * 3 + 0], points[13 * 3 + 1], points[13 * 3 + 2], + points[15 * 3 + 0], points[15 * 3 + 1], points[15 * 3 + 2]); + + // right arm + lines.push( + points[12 * 3 + 0], points[12 * 3 + 1], points[12 * 3 + 2], + points[14 * 3 + 0], points[14 * 3 + 1], points[14 * 3 + 2]); + lines.push( + points[14 * 3 + 0], points[14 * 3 + 1], points[14 * 3 + 2], + points[16 * 3 + 0], points[16 * 3 + 1], points[16 * 3 + 2]); + + // left leg + lines.push( + points[23 * 3 + 0], points[23 * 3 + 1], points[23 * 3 + 2], + points[25 * 3 + 0], points[25 * 3 + 1], points[25 * 3 + 2]); + lines.push( + points[25 * 3 + 0], points[25 * 3 + 1], points[25 * 3 + 2], + points[27 * 3 + 0], points[27 * 3 + 1], points[27 * 3 + 2]); + lines.push( + points[27 * 3 + 0], points[27 * 3 + 1], points[27 * 3 + 2], + points[29 * 3 + 0], points[29 * 3 + 1], points[29 * 3 + 2]); + + // right leg + lines.push( + points[24 * 3 + 0], points[24 * 3 + 1], points[24 * 3 + 2], + points[26 * 3 + 0], points[26 * 3 + 1], points[26 * 3 + 2]); + lines.push( + points[26 * 3 + 0], points[26 * 3 + 1], points[26 * 3 + 2], + points[28 * 3 + 0], points[28 * 3 + 1], points[28 * 3 + 2]); + lines.push( + points[28 * 3 + 0], points[28 * 3 + 1], points[28 * 3 + 2], + points[30 * 3 + 0], points[30 * 3 + 1], points[30 * 3 + 2]); + + // left hand + lines.push( + points[15 * 3 + 0], points[15 * 3 + 1], points[15 * 3 + 2], + points[21 * 3 + 0], points[21 * 3 + 1], points[21 * 3 + 2], + + points[15 * 3 + 0], points[15 * 3 + 1], points[15 * 3 + 2], + points[17 * 3 + 0], points[17 * 3 + 1], points[17 * 3 + 2], + + points[17 * 3 + 0], points[17 * 3 + 1], points[17 * 3 + 2], + points[19 * 3 + 0], points[19 * 3 + 1], points[19 * 3 + 2], + + points[19 * 3 + 0], points[19 * 3 + 1], points[19 * 3 + 2], + points[15 * 3 + 0], points[15 * 3 + 1], points[15 * 3 + 2]); + + // right hand + lines.push( + points[16 * 3 + 0], points[16 * 3 + 1], points[16 * 3 + 2], + points[22 * 3 + 0], points[22 * 3 + 1], points[22 * 3 + 2], + + points[16 * 3 + 0], points[16 * 3 + 1], points[16 * 3 + 2], + points[18 * 3 + 0], points[18 * 3 + 1], points[18 * 3 + 2], + + points[18 * 3 + 0], points[18 * 3 + 1], points[18 * 3 + 2], + points[20 * 3 + 0], points[20 * 3 + 1], points[20 * 3 + 2], + + points[20 * 3 + 0], points[20 * 3 + 1], points[20 * 3 + 2], + points[16 * 3 + 0], points[16 * 3 + 1], points[16 * 3 + 2]); + + lines.push( + points[27 * 3 + 0], points[27 * 3 + 1], points[27 * 3 + 2], + points[31 * 3 + 0], points[31 * 3 + 1], points[31 * 3 + 2], + + points[31 * 3 + 0], points[31 * 3 + 1], points[31 * 3 + 2], + points[29 * 3 + 0], points[29 * 3 + 1], points[29 * 3 + 2]); + + lines.push( + points[28 * 3 + 0], points[28 * 3 + 1], points[28 * 3 + 2], + points[32 * 3 + 0], points[32 * 3 + 1], points[32 * 3 + 2], + + points[32 * 3 + 0], points[32 * 3 + 1], points[32 * 3 + 2], + points[30 * 3 + 0], points[30 * 3 + 1], points[30 * 3 + 2]); + + outLines.set(lines); + } + else + { + outPoints.set(null); + outLandmarks.set(null); + outLines.set(null); + } +}); + + +}; + +Ops.Libs.Mediapipe.MpPoseTracking.prototype = new CABLES.Op(); +CABLES.OPS["279774b0-9897-4f36-840e-5f823cfc988a"]={f:Ops.Libs.Mediapipe.MpPoseTracking,objName:"Ops.Libs.Mediapipe.MpPoseTracking"}; + + + + +// ************************************************************** +// +// Ops.Libs.OpenType.OpentypeFont +// +// ************************************************************** + +Ops.Libs.OpenType.OpentypeFont = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + filename = op.inUrl("Font File", [".otf", ".ttf", ".woff", ".woff2"]), + outFont = op.outObject("Opentype Font", null, "opentype"); + +filename.onChange = async function () +{ + const font = await opentype.load(filename.get()); + outFont.set(font); +}; + + +}; + +Ops.Libs.OpenType.OpentypeFont.prototype = new CABLES.Op(); +CABLES.OPS["f85574bb-3869-4a14-8dcc-70414bd8cfcd"]={f:Ops.Libs.OpenType.OpentypeFont,objName:"Ops.Libs.OpenType.OpentypeFont"}; + + + + +// ************************************************************** +// +// Ops.Libs.OpenType.OpentypeToSvgPath +// +// ************************************************************** + +Ops.Libs.OpenType.OpentypeToSvgPath = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inFont = op.inObject("Opentype Font"), + inStr = op.inString("Text", "cables"), + inLs = op.inFloat("Letter Spacing", 0), + outPathStr = op.outString("Path String"); + +inStr.onChange = +inLs.onChange = +inFont.onChange = async function () +{ + const font = inFont.get(); + if (!font || !font.getPath) + { + outPathStr.set(""); + return; + } + + const paths = font.getPaths(inStr.get(), 0, 0, 72); + let str = ""; + + let ls = inLs.get(); + + for (let i = 0; i < paths.length; i++) + { + for (let j = 0; j < paths[i].commands.length; j++) + { + if (paths[i].commands[j].hasOwnProperty("x")) + paths[i].commands[j].x += i * ls; + if (paths[i].commands[j].hasOwnProperty("x1")) + paths[i].commands[j].x1 += i * ls; + } + str += paths[i].toPathData(); + } + + outPathStr.set(str); +}; + + +}; + +Ops.Libs.OpenType.OpentypeToSvgPath.prototype = new CABLES.Op(); +CABLES.OPS["4d901c72-b8dc-45dc-ac2e-608e5da40677"]={f:Ops.Libs.OpenType.OpentypeToSvgPath,objName:"Ops.Libs.OpenType.OpentypeToSvgPath"}; + + + + +// ************************************************************** +// +// Ops.Libs.Trackingjs.TrackWebcamColor +// +// ************************************************************** + +Ops.Libs.Trackingjs.TrackWebcamColor = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inUpdate=op.inTrigger("Update"), + inEle = op.inObject("Video Element"), + inThresh=op.inFloatSlider("Threshold",0.5), + + inResize=op.inFloatSlider("Resize Video",0.3), + + r = op.inValueSlider("r", Math.random()), + g = op.inValueSlider("g", Math.random()), + b = op.inValueSlider("b", Math.random()), + + outArrPos = op.outArray("Positions"), + outArrSizes = op.outArray("Sizes"); + +const color={r:0,g:80,b:150}; +let started=false; + +r.setUiAttribs({ "colorPick": true }); +r.onChange= + g.onChange= + b.onChange=()=> + { + color.r=Math.round(r.get()*255); + color.g=Math.round(g.get()*255); + color.b=Math.round(b.get()*255); + }; + + +let canvas= document.createElement("canvas"); +const eleId = "video2canv" + CABLES.uuid(); +canvas.setAttribute("id", eleId); + + +tracking.ColorTracker.registerColor("dynamic", function (r, g, b) +{ + return getColorDistance(color, { "r": r, "g": g, "b": b }) < inThresh.get()*255; +}); + + +let tracker = new tracking.ColorTracker("dynamic"); +// let tracker = new tracking.ObjectTracker("face"); + + + +tracker.on("track", function (e) +{ + const arrRects = []; + const arrSizes=[]; + + const r=canvas.width/canvas.height; + + + if (e.data.length !== 0) + { + + e.data.forEach(function (rect) + { + arrRects.push(r*(rect.x/canvas.width-0.5),1.0-rect.y/canvas.height-0.5,0); + arrSizes.push(r*(rect.width/canvas.width),rect.height/canvas.height,0); + }); + + } + + outArrPos.set(arrRects); + outArrSizes.set(arrSizes); +}); + +inUpdate.onTriggered=() => +{ + const videoEle=inEle.get(); + if(videoEle) + { + + if(videoEle.videoWidth && videoEle.videoHeight) + { + + let w=videoEle.videoWidth; + let h=videoEle.videoHeight; + + w=Math.round(w*inResize.get()); + h=Math.round(h*inResize.get()); + + canvas.setAttribute("width",w); + canvas.setAttribute("height",h); + + canvas.getContext('2d', { alpha: false }).drawImage(videoEle, 0, 0, w, h); + + } + } + + + // canvas = inCanvas.get(); + if (!started && canvas) + { + // started=true; + tracking.track(canvas, tracker, { "camera": true }); + } +}; + +function getColorDistance(target, actual) +{ + return Math.sqrt( + (target.r - actual.r) * (target.r - actual.r) + + (target.g - actual.g) * (target.g - actual.g) + + (target.b - actual.b) * (target.b - actual.b) + ); +} + + + +}; + +Ops.Libs.Trackingjs.TrackWebcamColor.prototype = new CABLES.Op(); +CABLES.OPS["546beec8-fcf3-4456-a7f5-8fd81ca717ab"]={f:Ops.Libs.Trackingjs.TrackWebcamColor,objName:"Ops.Libs.Trackingjs.TrackWebcamColor"}; + + + + +// ************************************************************** +// +// Ops.Math.Abs +// +// ************************************************************** + +Ops.Math.Abs = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number = op.inValue("number"), + result = op.outNumber("result"); + +number.onChange = function () +{ + result.set(Math.abs(number.get())); +}; + + +}; + +Ops.Math.Abs.prototype = new CABLES.Op(); +CABLES.OPS["6b5af21d-065f-44d2-9442-8b7a254753f6"]={f:Ops.Math.Abs,objName:"Ops.Math.Abs"}; + + + + +// ************************************************************** +// +// Ops.Math.Accumulator +// +// ************************************************************** + +Ops.Math.Accumulator = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("Trigger in"), + inAddNumber = op.inValueFloat("Add to number", 0.0), + inMultiplier = op.inValueFloat("Multiplier to add number", 1.0), + inSetNumber = op.inValueFloat("Default Value", 1.0), + inSet = op.inTriggerButton("Set Default Value"), + outNumber = op.outNumber("Current value"); + +let lastTime = performance.now(); +let currentNumber = 0.0; +let firsttime = true; + +inSet.onTriggered = resetNumber; + +function resetNumber() +{ + currentNumber = inSetNumber.get(); + outNumber.set(currentNumber); + firsttime = true; +} + +exe.onTriggered = function () +{ + if (!firsttime) + { + let diff = (performance.now() - lastTime) / 100; + currentNumber += inAddNumber.get() * diff * inMultiplier.get(); + outNumber.set(currentNumber); + } + lastTime = performance.now(); + firsttime = false; +}; + + +}; + +Ops.Math.Accumulator.prototype = new CABLES.Op(); +CABLES.OPS["460574ca-dca2-4283-8c37-57a8c446a51f"]={f:Ops.Math.Accumulator,objName:"Ops.Math.Accumulator"}; + + + + +// ************************************************************** +// +// Ops.Math.AddUp +// +// ************************************************************** + +Ops.Math.AddUp = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number = op.inValue("Number"), + doAdd = op.inTriggerButton("Add"), + doReset = op.inTriggerButton("Reset"), + result = op.outNumber("Result"); + +let value = 0; + +doAdd.onTriggered = function () +{ + value += number.get(); + result.set(value); +}; + +doReset.onTriggered = function () +{ + value = 0; + result.set(value); +}; + + +}; + +Ops.Math.AddUp.prototype = new CABLES.Op(); +CABLES.OPS["f1c76976-4c8f-43a5-a9c7-6e4c7d21c749"]={f:Ops.Math.AddUp,objName:"Ops.Math.AddUp"}; + + + + +// ************************************************************** +// +// Ops.Math.AngleBetweenPoints +// +// ************************************************************** + +Ops.Math.AngleBetweenPoints = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + p1x = op.inValue("Point 1 X"), + p1y = op.inValue("Point 1 Y"), + p2x = op.inValue("Point 2 X"), + p2y = op.inValue("Point 2 Y"), + outAngle = op.outNumber("Angle", 0); + +p1x.onChange = + p2x.onChange = + p1y.onChange = + p2y.onChange = update; + +function update() +{ + let theta = Math.atan2( + p1y.get() - p2y.get(), + p1x.get() - p2x.get()); + + let angle = theta * 180 / Math.PI * -1; + + outAngle.set(angle); +} + + +}; + +Ops.Math.AngleBetweenPoints.prototype = new CABLES.Op(); +CABLES.OPS["03e20aba-a22a-40de-9287-a32fc495a643"]={f:Ops.Math.AngleBetweenPoints,objName:"Ops.Math.AngleBetweenPoints"}; + + + + +// ************************************************************** +// +// Ops.Math.Array3MultiplyMatrix +// +// ************************************************************** + +Ops.Math.Array3MultiplyMatrix = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Update"), + inArr = op.inArray("Array", null, 3), + inMat = op.inArray("Matrix", null, 16), + outArr = op.outArray("Result", null, 3); + +let theArr = []; +exec.onTriggered = function () +{ + let arr = inArr.get(); + if (!arr) + { + outArr.set(null); + return; + } + theArr.length = arr.length; + let mMat = inMat.get(); + let vec = vec4.create(); + vec[3] = 1; + + for (let i = 0; i < arr.length / 3; i++) + { + vec[0] = arr[i * 3 + 0]; + vec[1] = arr[i * 3 + 1]; + vec[2] = arr[i * 3 + 2]; + + vec3.transformMat4(vec, vec, mMat); + + theArr[i * 3 + 0] = vec[0]; + theArr[i * 3 + 1] = vec[1]; + theArr[i * 3 + 2] = vec[2]; + } + + outArr.set(null); + outArr.set(theArr); +}; + + +}; + +Ops.Math.Array3MultiplyMatrix.prototype = new CABLES.Op(); +CABLES.OPS["a83aca4c-48ab-41ad-9943-3f4d03777ae8"]={f:Ops.Math.Array3MultiplyMatrix,objName:"Ops.Math.Array3MultiplyMatrix"}; + + + + +// ************************************************************** +// +// Ops.Math.Array3To2dProjection +// +// ************************************************************** + +Ops.Math.Array3To2dProjection = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("Exec"), + inArr = op.inArray("Array3x"), + fov = op.inValueFloat("fov", 45), + w = op.inValueFloat("w", 1), + h = op.inValueFloat("h", 1), + px = op.inValueFloat("Pos X", -0.5), + py = op.inValueFloat("Pos Y", -0.5), + coordmul = op.inValueFloat("mul"), + next = op.outTrigger("Next"), + outArr = op.outArray("Array2x"); + +exe.onTriggered = function () +{ + // if (needsUpdate) + update(); +}; + +exe.onChange = + inArr.onChange = + fov.onChange = + w.onChange = + h.onChange = + px.onChange = + py.onChange = + coordmul.onChange = update; + +const cgl = op.patch.cgl; + +let needsUpdate = false; + +let minX = 9999999; +let maxX = -9999999; +let minY = 9999999; +let maxY = -9999999; + +let pos = vec3.create(); +let m = mat4.create(); +let trans = vec3.create(); +let pm = mat4.create(); + +function proj(p) +{ + pm = mat4.perspective(pm, fov.get() * CGL.DEG2RAD, 1, 0.0001, 100); + + mat4.multiply(m, cgl.vMatrix, cgl.mMatrix); + vec3.transformMat4(pos, [px.get(), py.get(), 0], m); + vec3.add(pos, pos, p); + + vec3.transformMat4(trans, pos, pm); + + let height = h.get(); + let width = w.get(); + let x = trans[0] * width; + let y = trans[1] * height; + + return [x, y, 0]; +} + +inArr.onChange = function () +{ + needsUpdate = true; +}; + +function update() +{ + let points3d = inArr.get(); + if (!points3d) return; + + let ind = 0; + let laserArr = []; + let point = vec3.create(); + + for (let i = 0; i < points3d.length / 3; i++) + { + vec3.set(point, + points3d[i * 3 + 0], + points3d[i * 3 + 1], + points3d[i * 3 + 2] + ); + + let vv = proj(point); + + let x = vv[0]; + let y = vv[1]; + if (x == null)x = 0; + if (y == null)y = 0; + + x += w.get() / 2; + y += h.get() / 2; + + minX = Math.min(x, minX); + maxX = Math.max(x, maxX); + + minY = Math.min(y, minY); + maxY = Math.max(y, maxY); + + laserArr[ind++] = x; + laserArr[ind++] = y; + laserArr[ind++] = 0; + } + + outArr.set(null); + outArr.set(laserArr); + needsUpdate = false; + + next.trigger(); +} + + +}; + +Ops.Math.Array3To2dProjection.prototype = new CABLES.Op(); +CABLES.OPS["8ac0bd90-ba6f-40f7-8429-21bff899cb14"]={f:Ops.Math.Array3To2dProjection,objName:"Ops.Math.Array3To2dProjection"}; + + + + +// ************************************************************** +// +// Ops.Math.Atan2 +// +// ************************************************************** + +Ops.Math.Atan2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + x = op.inValue("X"), + y = op.inValue("Y"), + phase = op.inValue("Phase", 0.0), + mul = op.inValue("Frequency", 1.0), + result = op.outNumber("Result"); + +x.onChange = + y.onChange = update; + +function update() +{ + result.set( + mul.get() * Math.atan2(x.get(), y.get()) + phase.get() + ); +} + + +}; + +Ops.Math.Atan2.prototype = new CABLES.Op(); +CABLES.OPS["93ebaebf-0ebf-4aae-b0d8-2996ae44f1ed"]={f:Ops.Math.Atan2,objName:"Ops.Math.Atan2"}; + + + + +// ************************************************************** +// +// Ops.Math.Average +// +// ************************************************************** + +Ops.Math.Average = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number = op.inValue("number"), + infl = op.inValueSlider("Influence", 0.2), + result = op.outNumber("result"); + +number.onChange = function () +{ + let influence = infl.get(); + result.set((result.get() * (1.0 - influence) + number.get()) * influence); +}; + +number.set(1); + + +}; + +Ops.Math.Average.prototype = new CABLES.Op(); +CABLES.OPS["12a93cd3-348b-460a-aa02-f66690062322"]={f:Ops.Math.Average,objName:"Ops.Math.Average"}; + + + + +// ************************************************************** +// +// Ops.Math.ButterflyCurve +// +// ************************************************************** + +Ops.Math.ButterflyCurve = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inVal = op.inValue("Value"), + outX = op.outNumber("X"), + outY = op.outNumber("Y"); + +inVal.onChange = update; + +function update() +{ + let t = inVal.get(); + + let x = Math.cos(t) * Math.pow(Math.exp(Math.cos(t)) - 2 * Math.cos(4 * t) - Math.sin(t / 12), 2); + let y = Math.sin(t) * Math.pow(Math.exp(Math.cos(t)) - 2 * Math.cos(4 * t) - Math.sin(t / 12), 2); + + outX.set(x); + outY.set(y); +} + + +}; + +Ops.Math.ButterflyCurve.prototype = new CABLES.Op(); +CABLES.OPS["d9023bba-8122-4eed-8d61-32461cad8aba"]={f:Ops.Math.ButterflyCurve,objName:"Ops.Math.ButterflyCurve"}; + + + + +// ************************************************************** +// +// Ops.Math.Ceil +// +// ************************************************************** + +Ops.Math.Ceil = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const number1 = op.inValue("Number"); +const result = op.outNumber("Result"); + +function exec() +{ + result.set(Math.ceil(number1.get())); +} + +number1.onChange = exec; + + +}; + +Ops.Math.Ceil.prototype = new CABLES.Op(); +CABLES.OPS["15ba7aa9-b1c3-4b20-b6bf-b52a3ba8c8c5"]={f:Ops.Math.Ceil,objName:"Ops.Math.Ceil"}; + + + + +// ************************************************************** +// +// Ops.Math.CircleCoordinates +// +// ************************************************************** + +Ops.Math.CircleCoordinates = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inPos = op.inFloat("Position"), + inRadius = op.inFloat("Radius", 1), + outX = op.outNumber("X"), + outY = op.outNumber("Y"); + +inPos.onChange = + inRadius.onChange = calc; + +function calc() +{ + const r = inRadius.get(); + const degInRad = (360 * inPos.get()) * CGL.DEG2RAD; + + outX.set(Math.sin(degInRad) * r); + outY.set(Math.cos(degInRad) * r); +} + + +}; + +Ops.Math.CircleCoordinates.prototype = new CABLES.Op(); +CABLES.OPS["76fdea4d-1653-46d6-80f3-af34018f043d"]={f:Ops.Math.CircleCoordinates,objName:"Ops.Math.CircleCoordinates"}; + + + + +// ************************************************************** +// +// Ops.Math.Clamp +// +// ************************************************************** + +Ops.Math.Clamp = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + val = op.inValueFloat("val", 0.5), + min = op.inValueFloat("min", 0), + max = op.inValueFloat("max", 1), + ignore = op.inValueBool("ignore outside values"), + result = op.outNumber("result"); + +val.onChange = min.onChange = max.onChange = clamp; + +function clamp() +{ + if (ignore.get()) + { + if (val.get() > max.get()) return; + if (val.get() < min.get()) return; + } + result.set(Math.min(Math.max(val.get(), min.get()), max.get())); +} + + +}; + +Ops.Math.Clamp.prototype = new CABLES.Op(); +CABLES.OPS["cda1a98e-5e16-40bd-9b18-a67e9eaad5a1"]={f:Ops.Math.Clamp,objName:"Ops.Math.Clamp"}; + + + + +// ************************************************************** +// +// Ops.Math.Compare.Between +// +// ************************************************************** + +Ops.Math.Compare.Between = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number = op.inValue("value", 2), + number1 = op.inValue("number1", 1), + number2 = op.inValue("number2", 3), + result = op.outNumber("result"); + +number1.onChange = exec; +number2.onChange = exec; +number.onChange = exec; +exec(); + +function exec() +{ + result.set( + number.get() > Math.min(number1.get(), number2.get()) && + number.get() < Math.max(number1.get(), number2.get()) + ); +} + + +}; + +Ops.Math.Compare.Between.prototype = new CABLES.Op(); +CABLES.OPS["d629959e-838d-4541-b12f-15e2d6ff5131"]={f:Ops.Math.Compare.Between,objName:"Ops.Math.Compare.Between"}; + + + + +// ************************************************************** +// +// Ops.Math.Compare.BetweenEquals +// +// ************************************************************** + +Ops.Math.Compare.BetweenEquals = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number = op.inValueFloat("Value", 2), + range1 = op.inValueFloat("Range 1", 1), + range2 = op.inValueFloat("Range 2", 3), + result = op.outNumber("Result"); + +number.onChange = range1.onChange = range2.onChange = exec; +exec(); + +function exec() +{ + result.set( + number.get() >= Math.min(range1.get(), range2.get()) && + number.get() <= Math.max(range1.get(), range2.get()) + ); +} + + +}; + +Ops.Math.Compare.BetweenEquals.prototype = new CABLES.Op(); +CABLES.OPS["e2d6d6c4-84c7-42d7-a1b2-e9c5d4c5c13e"]={f:Ops.Math.Compare.BetweenEquals,objName:"Ops.Math.Compare.BetweenEquals"}; + + + + +// ************************************************************** +// +// Ops.Math.Compare.CompareNumbers +// +// ************************************************************** + +Ops.Math.Compare.CompareNumbers = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + logicSelectMode = op.inValueSelect("Comparison mode", [">", "<", ">=", "<=", "==", "!=", "><", ">=<"], ">"), + numberIn_1 = op.inFloat("Value in", 0), + numberIn_2 = op.inFloat("Condition value", 1), + numberIn_3 = op.inFloat("Max", 1), + resultNumberOut = op.outNumber("Result"); + +let logicFunc; + +logicSelectMode.onChange = onFilterChange; + +numberIn_1.onChange = numberIn_2.onChange = numberIn_3.onChange = update; + +onFilterChange(); + +function onFilterChange() +{ + let logicSelectValue = logicSelectMode.get(); + if (logicSelectValue === ">") logicFunc = function (a, b, c) { if (a > b) return 1; return 0; }; + else if (logicSelectValue === "<") logicFunc = function (a, b, c) { if (a < b) return 1; return 0; }; + else if (logicSelectValue === ">=") logicFunc = function (a, b, c) { if (a >= b) return 1; return 0; }; + else if (logicSelectValue === "<=") logicFunc = function (a, b, c) { if (a <= b) return 1; return 0; }; + else if (logicSelectValue === "==") logicFunc = function (a, b, c) { if (a === b) return 1; return 0; }; + else if (logicSelectValue === "!=") logicFunc = function (a, b, c) { if (a !== b) return 1; return 0; }; + else if (logicSelectValue === "><") logicFunc = function (a, b, c) { if (a > Math.min(b, c) && a < Math.max(b, c)) return 1; return 0; }; + else if (logicSelectValue === ">=<") logicFunc = function (a, b, c) { if (a >= Math.min(b, c) && a <= Math.max(b, c)) return 1; return 0; }; + + if (logicSelectValue === "><" || logicSelectValue === ">=<") + { + numberIn_3.setUiAttribs({ "greyout": false }); + numberIn_2.setUiAttribs({ "title": "Min" }); + } + else + { + numberIn_3.setUiAttribs({ "greyout": true }); + numberIn_2.setUiAttribs({ "title": "Condition value" }); + } + update(); + op.setUiAttrib({ "extendTitle": logicSelectValue }); +} + +function update() +{ + let n1 = numberIn_1.get(); + let n2 = numberIn_2.get(); + let n3 = numberIn_3.get(); + + let resultNumber = logicFunc(n1, n2, n3); + + resultNumberOut.set(resultNumber); +} + + +}; + +Ops.Math.Compare.CompareNumbers.prototype = new CABLES.Op(); +CABLES.OPS["169137db-9853-4384-ac5b-d10a0bbda5c2"]={f:Ops.Math.Compare.CompareNumbers,objName:"Ops.Math.Compare.CompareNumbers"}; + + + + +// ************************************************************** +// +// Ops.Math.Compare.Equals +// +// ************************************************************** + +Ops.Math.Compare.Equals = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number1 = op.inValue("number1", 1), + number2 = op.inValue("number2", 1), + result = op.outBoolNum("result"); + +number1.onChange = + number2.onChange = exec; +exec(); + +function exec() +{ + result.set(number1.get() == number2.get()); +} + + +}; + +Ops.Math.Compare.Equals.prototype = new CABLES.Op(); +CABLES.OPS["4dd3cc55-eebc-4187-9d4e-2e053a956fab"]={f:Ops.Math.Compare.Equals,objName:"Ops.Math.Compare.Equals"}; + + + + +// ************************************************************** +// +// Ops.Math.Compare.GreaterOrEquals +// +// ************************************************************** + +Ops.Math.Compare.GreaterOrEquals = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + result = op.outBoolNum("result"), + number1 = op.inValueFloat("number1"), + number2 = op.inValueFloat("number2"); + +number1.onLinkChanged = + number2.onLinkChanged = + number1.onChange = + number2.onChange = exec; + +function exec() +{ + result.set(number1.get() >= number2.get()); +} + + +}; + +Ops.Math.Compare.GreaterOrEquals.prototype = new CABLES.Op(); +CABLES.OPS["5f9ce320-1e8d-49cb-9927-337e0b3f4d45"]={f:Ops.Math.Compare.GreaterOrEquals,objName:"Ops.Math.Compare.GreaterOrEquals"}; + + + + +// ************************************************************** +// +// Ops.Math.Compare.GreaterThan +// +// ************************************************************** + +Ops.Math.Compare.GreaterThan = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number1 = op.inValueFloat("number1"), + number2 = op.inValueFloat("number2"), + result = op.outBoolNum("result"); + +op.setTitle(">"); + +number1.onChange = number2.onChange = exec; + +function exec() +{ + result.set(number1.get() > number2.get()); +} + + +}; + +Ops.Math.Compare.GreaterThan.prototype = new CABLES.Op(); +CABLES.OPS["b250d606-f7f8-44d3-b099-c29efff2608a"]={f:Ops.Math.Compare.GreaterThan,objName:"Ops.Math.Compare.GreaterThan"}; + + + + +// ************************************************************** +// +// Ops.Math.Compare.IfBetweenThen +// +// ************************************************************** + +Ops.Math.Compare.IfBetweenThen = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + number = op.inValue("number", 0), + min = op.inValue("min", 0), + max = op.inValue("max", 1), + triggerThen = op.outTrigger("then"), + triggerElse = op.outTrigger("else"), + outBetween = op.outBoolNum("bs between"); + +exe.onTriggered = function () +{ + if (number.get() >= min.get() && number.get() < max.get()) + { + outBetween.set(true); + triggerThen.trigger(); + } + else + { + outBetween.set(false); + triggerElse.trigger(); + } +}; + + +}; + +Ops.Math.Compare.IfBetweenThen.prototype = new CABLES.Op(); +CABLES.OPS["c80437f0-f0e1-465c-9cea-8a044aa2feaa"]={f:Ops.Math.Compare.IfBetweenThen,objName:"Ops.Math.Compare.IfBetweenThen"}; + + + + +// ************************************************************** +// +// Ops.Math.Compare.IsEven +// +// ************************************************************** + +Ops.Math.Compare.IsEven = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number = op.inValueFloat("number1"), + result = op.outBoolNum("result"); + +number.onChange = exec; +exec(); + +function exec() +{ + result.set(!(number.get() & 1)); +} + + +}; + +Ops.Math.Compare.IsEven.prototype = new CABLES.Op(); +CABLES.OPS["f462c64a-3e17-4de8-a77d-6735725fc9cc"]={f:Ops.Math.Compare.IsEven,objName:"Ops.Math.Compare.IsEven"}; + + + + +// ************************************************************** +// +// Ops.Math.Compare.LessThan +// +// ************************************************************** + +Ops.Math.Compare.LessThan = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const number1 = op.inValue("number1"); +const number2 = op.inValue("number2"); +const result = op.outBoolNum("result"); + +op.setTitle("<"); + +number1.onChange = exec; +number2.onChange = exec; +exec(); + +function exec() +{ + result.set(number1.get() < number2.get()); +} + + +}; + +Ops.Math.Compare.LessThan.prototype = new CABLES.Op(); +CABLES.OPS["04fd113f-ade1-43fb-99fa-f8825f8814c0"]={f:Ops.Math.Compare.LessThan,objName:"Ops.Math.Compare.LessThan"}; + + + + +// ************************************************************** +// +// Ops.Math.Cosine +// +// ************************************************************** + +Ops.Math.Cosine = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + value = op.inValue("Value"), + phase = op.inValue("Phase", 0.0), + mul = op.inValue("Frequency", 1.0), + amplitude = op.inValue("Amplitude", 1.0), + invert = op.inValueBool("asine", false), + result = op.outNumber("Result"); + +let calculate = Math.cos; + +value.onChange = function () +{ + result.set( + amplitude.get() * calculate((value.get() * mul.get()) + phase.get()) + ); +}; + +invert.onChange = function () +{ + if (invert.get()) calculate = Math.acos; + else calculate = Math.cos; +}; + + +}; + +Ops.Math.Cosine.prototype = new CABLES.Op(); +CABLES.OPS["b51166c4-e0a8-441a-b724-1531effdc52f"]={f:Ops.Math.Cosine,objName:"Ops.Math.Cosine"}; + + + + +// ************************************************************** +// +// Ops.Math.Crossfade +// +// ************************************************************** + +Ops.Math.Crossfade = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inFade = op.inFloatSlider("Crossfade",0.5); +const inMinOut = op.inFloat("Out Min", 0); +const inMaxOut = op.inFloat("Out Max", 1); +op.setPortGroup("Range",[inMinOut, inMaxOut]); + +const anim = new CABLES.Anim(); +const inDropdownAnim = anim.createPort(op,"Easing", function() { + anim.keys[0].setEasing(anim.defaultEasing); +}); + +anim.setValue(0,0); +anim.setValue(1,1); +op.setPortGroup("Easing",[inDropdownAnim]); + +const outA = op.outNumber("A"); +const outB = op.outNumber("B"); + + +function handleMinMaxChange() { + anim.keys[0].time= anim.keys[0].value = Math.min(inMinOut.get(),inMaxOut.get()); + anim.keys[1].time= anim.keys[1].value = Math.max(inMinOut.get(),inMaxOut.get()); + handleValueChange(); +} +function handleValueChange() { + const val = inFade.get(); + + const realMin = Math.min(inMaxOut.get(), inMinOut.get()); + const realMax = Math.max(inMaxOut.get(), inMinOut.get()); + + // Y = (X-A)/(B-A) * (D-C) + C + const resultA = anim.getValue((1-val) * (realMax - realMin) + realMin); + const resultB = anim.getValue(val * (realMax - realMin) + realMin); + + outA.set(resultA); + outB.set(resultB); +} + +function updateMinMax() { + anim.keys[0].time = anim.keys[0].value = Math.min(inMinOut.get(), inMaxOut.get()); + anim.keys[1].time = anim.keys[1].value = Math.max(inMinOut.get(), inMaxOut.get()); +} + +handleValueChange(); + +inMinOut.onChange = inMaxOut.onChange = handleMinMaxChange; +inFade.onChange = handleValueChange; + + +}; + +Ops.Math.Crossfade.prototype = new CABLES.Op(); +CABLES.OPS["6c8d01a2-dc8c-43c3-a569-c2ab0ba42747"]={f:Ops.Math.Crossfade,objName:"Ops.Math.Crossfade"}; + + + + +// ************************************************************** +// +// Ops.Math.DegreeToVector +// +// ************************************************************** + +Ops.Math.DegreeToVector = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + deg = op.inValueFloat("degree", 0), + x = op.outNumber("x"), + y = op.outNumber("y"); + +deg.onChange = update; + +function update() +{ + let rad = deg.get() * CGL.DEG2RAD; + x.set(-1 * Math.sin(rad)); + y.set(Math.cos(rad)); +} + + +}; + +Ops.Math.DegreeToVector.prototype = new CABLES.Op(); +CABLES.OPS["56b1618b-4eed-41a8-87a2-57397ffc9029"]={f:Ops.Math.DegreeToVector,objName:"Ops.Math.DegreeToVector"}; + + + + +// ************************************************************** +// +// Ops.Math.Degrees +// +// ************************************************************** + +Ops.Math.Degrees = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + value = op.inValue("Radians"), + result = op.outNumber("Result"); + +// convert radians into degrees +value.onChange = function () +{ + result.set( + value.get() * 180 / Math.PI + ); +}; + + +}; + +Ops.Math.Degrees.prototype = new CABLES.Op(); +CABLES.OPS["53385f87-13eb-4c19-8b04-6632a72e967c"]={f:Ops.Math.Degrees,objName:"Ops.Math.Degrees"}; + + + + +// ************************************************************** +// +// Ops.Math.Delta +// +// ************************************************************** + +Ops.Math.Delta = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + val = op.inValue("Value"), + changeAlwaysPort = op.inValueBool("Change Always", false), + inReset = op.inTrigger("Reset"), + result = op.outNumber("Delta"); + +val.changeAlways = false; + +let oldVal = 0; +let firstTime = true; + +changeAlwaysPort.onChange = function () +{ + val.changeAlways = changeAlwaysPort.get(); +}; + +inReset.onTriggered = function () +{ + firstTime = true; +}; + +val.onChange = function () +{ + let change = oldVal - val.get(); + oldVal = val.get(); + if (firstTime) + { + firstTime = false; + return; + } + result.set(change); +}; + + +}; + +Ops.Math.Delta.prototype = new CABLES.Op(); +CABLES.OPS["0f203337-e13c-47ec-a09f-b309212540b0"]={f:Ops.Math.Delta,objName:"Ops.Math.Delta"}; + + + + +// ************************************************************** +// +// Ops.Math.DeltaSum +// +// ************************************************************** + +Ops.Math.DeltaSum = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inVal = op.inValue("Delta Value"), + defVal = op.inValue("Default Value", 0), + inMul = op.inValue("Multiply", 1), + inReset = op.inTriggerButton("Reset"), + inLimit = op.inValueBool("Limit", false), + inMin = op.inValue("Min", 0), + inMax = op.inValue("Max", 100), + inRubber = op.inValue("Rubberband", 0), + outVal = op.outNumber("Absolute Value"); + +inVal.changeAlways = true; + +op.setPortGroup("Limit", [inLimit, inMin, inMax, inRubber]); + +let value = 0; +let lastEvent = CABLES.now(); +let rubTimeout = null; + +inLimit.onChange = updateLimit; +defVal.onChange = + inReset.onTriggered = resetValue; + +inMax.onChange = + inMin.onChange = updateValue; + +updateLimit(); + +function resetValue() +{ + let v = defVal.get(); + + if (inLimit.get()) + { + v = Math.max(inMin.get(), v); + v = Math.min(inMax.get(), v); + } + + value = v; + outVal.set(value); +} + +function updateLimit() +{ + inMin.setUiAttribs({ "greyout": !inLimit.get() }); + inMax.setUiAttribs({ "greyout": !inLimit.get() }); + inRubber.setUiAttribs({ "greyout": !inLimit.get() }); + + updateValue(); +} + +function releaseRubberband() +{ + const min = inMin.get(); + const max = inMax.get(); + + if (value < min) value = min; + if (value > max) value = max; + + outVal.set(value); +} + +function updateValue() +{ + if (inLimit.get()) + { + const min = inMin.get(); + const max = inMax.get(); + const rubber = inRubber.get(); + const minr = inMin.get() - rubber; + const maxr = inMax.get() + rubber; + + if (value < minr) value = minr; + if (value > maxr) value = maxr; + + if (rubber !== 0.0) + { + clearTimeout(rubTimeout); + rubTimeout = setTimeout(releaseRubberband.bind(this), 300); + } + } + + outVal.set(value); +} + +inVal.onChange = function () +{ + let v = inVal.get(); + + const rubber = inRubber.get(); + + if (rubber !== 0.0) + { + const min = inMin.get(); + const max = inMax.get(); + const minr = inMin.get() - rubber; + const maxr = inMax.get() + rubber; + + if (value < min) + { + const aa = Math.abs(value - minr) / rubber; + v *= (aa * aa); + } + if (value > max) + { + const aa = Math.abs(maxr - value) / rubber; + v *= (aa * aa); + } + } + + lastEvent = CABLES.now(); + value += v * inMul.get(); + updateValue(); +}; + + +}; + +Ops.Math.DeltaSum.prototype = new CABLES.Op(); +CABLES.OPS["d9d4b3db-c24b-48da-b798-9e6230d861f7"]={f:Ops.Math.DeltaSum,objName:"Ops.Math.DeltaSum"}; + + + + +// ************************************************************** +// +// Ops.Math.Difference +// +// ************************************************************** + +Ops.Math.Difference = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + num1 = op.inValue("Number A"), + num2 = op.inValue("Number B"), + result = op.outNumber("Result"); + +num1.onChange = + num2.onChange = update; + +function update() +{ + let r = num1.get() - num2.get(); + r = Math.abs(r); + result.set(r); +} + + +}; + +Ops.Math.Difference.prototype = new CABLES.Op(); +CABLES.OPS["5431b943-18aa-46e4-bd32-a7eee30d4e51"]={f:Ops.Math.Difference,objName:"Ops.Math.Difference"}; + + + + +// ************************************************************** +// +// Ops.Math.Distance2d +// +// ************************************************************** + +Ops.Math.Distance2d = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + x1 = op.inValue("x1"), + y1 = op.inValue("y1"), + x2 = op.inValue("x2"), + y2 = op.inValue("y2"), + dist = op.outNumber("distance"); + +x1.onChange = +y1.onChange = +x2.onChange = +y2.onChange = calc; + +function calc() +{ + const xd = x2.get() - x1.get(); + const yd = y2.get() - y1.get(); + dist.set(Math.sqrt(xd * xd + yd * yd)); +} + + +}; + +Ops.Math.Distance2d.prototype = new CABLES.Op(); +CABLES.OPS["d181cc7c-adbb-467b-842b-e6a854c58bfc"]={f:Ops.Math.Distance2d,objName:"Ops.Math.Distance2d"}; + + + + +// ************************************************************** +// +// Ops.Math.Distance3d +// +// ************************************************************** + +Ops.Math.Distance3d = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let x1 = op.inValueFloat("x1"); +let y1 = op.inValueFloat("y1"); +let z1 = op.inValueFloat("z1"); + +let x2 = op.inValueFloat("x2"); +let y2 = op.inValueFloat("y2"); +let z2 = op.inValueFloat("z2"); + +let dist = op.addOutPort(new CABLES.Port(op, "distance")); +op.setPortGroup("Point 1", [x1, y1, z1]); +op.setPortGroup("Point 2", [x2, y2, z2]); + +x1.onChange = calc; +y1.onChange = calc; +z1.onChange = calc; +x2.onChange = calc; +y2.onChange = calc; +z2.onChange = calc; + +function calc() +{ + let xd = x2.get() - x1.get(); + let yd = y2.get() - y1.get(); + let zd = z2.get() - z1.get(); + dist.set(Math.sqrt(xd * xd + yd * yd + zd * zd)); +} + + +}; + +Ops.Math.Distance3d.prototype = new CABLES.Op(); +CABLES.OPS["6c5772d8-c6f4-4cad-a8e7-f669c0186964"]={f:Ops.Math.Distance3d,objName:"Ops.Math.Distance3d"}; + + + + +// ************************************************************** +// +// Ops.Math.Distance3dNew +// +// ************************************************************** + +Ops.Math.Distance3dNew = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + calc = op.inTriggerButton("Calc"), + + x1 = op.inValueFloat("x1"), + y1 = op.inValueFloat("y1"), + z1 = op.inValueFloat("z1"), + + x2 = op.inValueFloat("x2"), + y2 = op.inValueFloat("y2"), + z2 = op.inValueFloat("z2"), + + inMin = op.inValue("Min", 0); + +op.setPortGroup("Point 1", [x1, y1, z1]); +op.setPortGroup("Point 2", [x2, y2, z2]); + +const next = op.outTrigger("Next"); +const dist = op.addOutPort(new CABLES.Port(op, "distance")); + +let min = inMin.get(); + +inMin.onChange = function () +{ + min = inMin.get(); +}; + +calc.onTriggered = function () +{ + const xd = x2.get() - x1.get(); + if (Math.abs(xd) > min) return; + + const yd = y2.get() - y1.get(); + if (Math.abs(yd) > min) return; + + const zd = z2.get() - z1.get(); + if (Math.abs(zd) > min) return; + + dist.set(Math.sqrt(xd * xd + yd * yd + zd * zd)); + + next.trigger(); +}; + + +}; + +Ops.Math.Distance3dNew.prototype = new CABLES.Op(); +CABLES.OPS["6b344add-6c4d-4365-858f-a365e4adb183"]={f:Ops.Math.Distance3dNew,objName:"Ops.Math.Distance3dNew"}; + + + + +// ************************************************************** +// +// Ops.Math.Divide +// +// ************************************************************** + +Ops.Math.Divide = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number1 = op.inValueFloat("number1", 1), + number2 = op.inValueFloat("number2", 2), + result = op.outNumber("result"); + +op.setTitle("/"); + +number1.onChange = number2.onChange = exec; +exec(); + +function exec() +{ + result.set(number1.get() / number2.get()); +} + + +}; + +Ops.Math.Divide.prototype = new CABLES.Op(); +CABLES.OPS["86fcfd8c-038d-4b91-9820-a08114f6b7eb"]={f:Ops.Math.Divide,objName:"Ops.Math.Divide"}; + + + + +// ************************************************************** +// +// Ops.Math.Ease +// +// ************************************************************** + +Ops.Math.Ease = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inVal = op.inValue("Value"), + inMin = op.inValue("Min", 0), + inMax = op.inValue("Max", 1), + result = op.outNumber("Result"), + anim = new CABLES.Anim(); + +anim.createPort(op, "Easing", updateAnimEasing); +anim.setValue(0, 0); +anim.setValue(1, 1); + +op.onLoaded = inMin.onChange = inMax.onChange = updateMinMax; + +function updateMinMax() +{ + anim.keys[0].time = anim.keys[0].value = Math.min(inMin.get(), inMax.get()); + anim.keys[1].time = anim.keys[1].value = Math.max(inMin.get(), inMax.get()); +} + +function updateAnimEasing() +{ + anim.keys[0].setEasing(anim.defaultEasing); +} + +inVal.onChange = function () +{ + const r = anim.getValue(inVal.get()); + result.set(r); +}; + + +}; + +Ops.Math.Ease.prototype = new CABLES.Op(); +CABLES.OPS["8f6e4a08-33e6-408f-ac4a-198bd03b417b"]={f:Ops.Math.Ease,objName:"Ops.Math.Ease"}; + + + + +// ************************************************************** +// +// Ops.Math.Exp +// +// ************************************************************** + +Ops.Math.Exp = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const number = op.inValueFloat("number"); +const result = op.outNumber("result"); + +number.onChange = function () +{ + let r = Math.exp(number.get()); + if (isNaN(r))r = 0; + result.set(r); +}; + + +}; + +Ops.Math.Exp.prototype = new CABLES.Op(); +CABLES.OPS["612727c2-b2e5-446c-99bb-7e30132f2ff6"]={f:Ops.Math.Exp,objName:"Ops.Math.Exp"}; + + + + +// ************************************************************** +// +// Ops.Math.FlipSign +// +// ************************************************************** + +Ops.Math.FlipSign = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inval = op.inValueFloat("Value", 1), + result = op.outNumber("Result"); + +inval.onChange = update; +update(); + +function update() +{ + result.set(inval.get() * -1); +} + + +}; + +Ops.Math.FlipSign.prototype = new CABLES.Op(); +CABLES.OPS["f5c858a2-2654-4108-86fe-319efa70ecec"]={f:Ops.Math.FlipSign,objName:"Ops.Math.FlipSign"}; + + + + +// ************************************************************** +// +// Ops.Math.Floor +// +// ************************************************************** + +Ops.Math.Floor = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const number1 = op.inValue("Number"); +const result = op.outNumber("Result"); +number1.onChange = exec; + +function exec() +{ + result.set(Math.floor(number1.get())); +} + + +}; + +Ops.Math.Floor.prototype = new CABLES.Op(); +CABLES.OPS["0c77617c-b688-4b55-addf-2cbcaabf98af"]={f:Ops.Math.Floor,objName:"Ops.Math.Floor"}; + + + + +// ************************************************************** +// +// Ops.Math.Fract +// +// ************************************************************** + +Ops.Math.Fract = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + value = op.inValue("Value"), + result = op.outNumber("Result"); + +value.onChange = function () +{ + const v = value.get(); + result.set(v - Math.floor(v)); +}; + + +}; + +Ops.Math.Fract.prototype = new CABLES.Op(); +CABLES.OPS["12573ba7-866d-40c4-9ddd-14d9331ffe6f"]={f:Ops.Math.Fract,objName:"Ops.Math.Fract"}; + + + + +// ************************************************************** +// +// Ops.Math.GaussianRandomArray +// +// ************************************************************** + +Ops.Math.GaussianRandomArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inNum = op.inValueInt("Num", 100), + outArr = op.outArray("Array"), + inDev = op.inValue("Deviation", 1), + seed = op.inValueFloat("Random Seed"); + +let arr = []; +let stdDev = 1; +let previous = false; +let nextGaussian = null; +let y2; + +seed.onChange = inDev.onChange = inNum.onChange = update; +update(); + +// from https://github.com/processing/p5.js/blob/master/src/math/random.js + +function randomGaussian(mean, sd) +{ + let y1, x1, x2, w; + if (previous) + { + y1 = y2; + previous = false; + } + else + { + do + { + x1 = Math.seededRandom() * 2 - 1; + x2 = Math.seededRandom() * 2 - 1; + w = x1 * x1 + x2 * x2; + } while (w >= 1); + w = Math.sqrt((-2 * Math.log(w)) / w); + y1 = x1 * w; + y2 = x2 * w; + previous = true; + } + + let m = mean || 0; + let s = sd || 1; + return y1 * s + m; +} + +function update() +{ + stdDev = inDev.get(); + Math.randomSeed = seed.get(); + + arr.length = Math.floor(inNum.get()) || 0; + for (let i = 0; i < arr.length; i++) + { + arr[i] = randomGaussian(0, stdDev); + } + + outArr.set(null); + outArr.set(arr); +} + + +}; + +Ops.Math.GaussianRandomArray.prototype = new CABLES.Op(); +CABLES.OPS["1a8c3535-6fce-4cba-8601-ddb7a5dd7656"]={f:Ops.Math.GaussianRandomArray,objName:"Ops.Math.GaussianRandomArray"}; + + + + +// ************************************************************** +// +// Ops.Math.Incrementor +// +// ************************************************************** + +Ops.Math.Incrementor = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + increment = op.inTriggerButton("Increment"), + decrement = op.inTriggerButton("Decrement"), + inLength = op.inValueInt("Length"), + inLimit = op.inBool("Limit", true), + reset = op.inTriggerButton("Reset"), + inMode = op.inSwitch("Mode", ["Rewind", "Stop at Max"], "Rewind"), + inDefault = op.inValueInt("Default", 0), + outChanged = op.outTrigger("Changed"), + value = op.outNumber("Value"), + outRestarted = op.outTrigger("Restarted"); + +value.ignoreValueSerialize = true; +inLength.set(10); +let val = 0; +value.set(0); + +inLength.onTriggered = reset; +inDefault.onChange = doReset; +reset.onTriggered = doReset; + +const MODE_REWIND = 0; +const MODE_STOP = 1; + +let mode = MODE_REWIND; + +inMode.onChange = function () +{ + if (inMode.get() == "Rewind") + { + mode = MODE_REWIND; + } + if (inMode.get() == "Stop at Max") + { + mode = MODE_STOP; + } +}; + +inLimit.onChange = () => +{ + inLength.setUiAttribs({ "greyout": !inLimit.get() }); +}; + +function doReset() +{ + value.set(null); + val = inDefault.get(); + value.set(val); + outRestarted.trigger(); +} + +decrement.onTriggered = function () +{ + val--; + if (inLimit.get()) + { + if (mode == MODE_REWIND && val < 0)val = inLength.get() - 1; + if (mode == MODE_STOP && val < 0)val = 0; + } + value.set(val); + + outChanged.trigger(); +}; + +increment.onTriggered = function () +{ + val++; + if (inLimit.get()) + { + if (mode == MODE_REWIND && val >= inLength.get()) + { + val = 0; + outRestarted.trigger(); + } + if (mode == MODE_STOP && val >= inLength.get())val = inLength.get() - 1; + } + + value.set(val); + + outChanged.trigger(); +}; + + +}; + +Ops.Math.Incrementor.prototype = new CABLES.Op(); +CABLES.OPS["45cc0011-ada8-4423-8f5b-39a3810b8389"]={f:Ops.Math.Incrementor,objName:"Ops.Math.Incrementor"}; + + + + +// ************************************************************** +// +// Ops.Math.IndexFraction +// +// ************************************************************** + +Ops.Math.IndexFraction = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inValue=op.inFloat("Number",0.5), + inIdx=op.inInt("Index",0), + outValue=op.outNumber("Result"); + + inIdx.onChange=inValue.onChange = update; + +function update() +{ + const idx=inIdx.get(); + const val=inValue.get(); + + if(idxMath.ceil(val)) outValue.set(0.0); + else outValue.set(val-Math.floor(val)); +} + +}; + +Ops.Math.IndexFraction.prototype = new CABLES.Op(); +CABLES.OPS["924f3516-7d1c-4829-a24d-515bf3e7f43f"]={f:Ops.Math.IndexFraction,objName:"Ops.Math.IndexFraction"}; + + + + +// ************************************************************** +// +// Ops.Math.Interpolate +// +// ************************************************************** + +Ops.Math.Interpolate = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + val1 = op.inFloat("Value 1"), + val2 = op.inFloat("Value 2"), + perc = op.inFloatSlider("Percentage"), + result = op.outNumber("Result"); + +val1.onChange = +val2.onChange = +perc.onChange = update; + +function update() +{ + result.set((val2.get() - val1.get()) * perc.get() + val1.get()); +} + + +}; + +Ops.Math.Interpolate.prototype = new CABLES.Op(); +CABLES.OPS["d126e2c8-221e-428f-8ff4-8b8c5f6b8905"]={f:Ops.Math.Interpolate,objName:"Ops.Math.Interpolate"}; + + + + +// ************************************************************** +// +// Ops.Math.IsNumberRising +// +// ************************************************************** + +Ops.Math.IsNumberRising = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inNum = op.inFloat("Number", 0), + outRising = op.outNumber("Rising"); + +let last = 0; + +inNum.onChange = () => +{ + outRising.set(inNum.get() > last); + last = inNum.get(); +}; + + +}; + +Ops.Math.IsNumberRising.prototype = new CABLES.Op(); +CABLES.OPS["1598fbdf-eab9-41a1-98de-794795255359"]={f:Ops.Math.IsNumberRising,objName:"Ops.Math.IsNumberRising"}; + + + + +// ************************************************************** +// +// Ops.Math.Log +// +// ************************************************************** + +Ops.Math.Log = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const number = op.inValueFloat("number"); +const result = op.outNumber("result"); + +number.onChange = function () +{ + let r = Math.log(number.get()); + if (isNaN(r))r = 0; + result.set(r); +}; + + +}; + +Ops.Math.Log.prototype = new CABLES.Op(); +CABLES.OPS["7440b1ca-71d9-42a3-a927-d7b45b8857f9"]={f:Ops.Math.Log,objName:"Ops.Math.Log"}; + + + + +// ************************************************************** +// +// Ops.Math.MapGeoCoordsSpherical +// +// ************************************************************** + +Ops.Math.MapGeoCoordsSpherical = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Coordinates"), + inRad = op.inFloat("Radius", 1), + outArr = op.outArray("Result"); + +let arr = []; +inRad.onChange = + inArr.onChange = update; + +function update() +{ + outArr.set(null); + let iarr = inArr.get(); + + if (!iarr) return; + + let l = iarr.length / 2 * 3; + arr.length = l; + const radius = inRad.get(); + + for (let i = 0; i < iarr.length; i += 2) + { + const + lat = iarr[i + 0], + lon = iarr[i + 1], + phi = (90 - lat) * (Math.PI / 180), + theta = (lon + 180) * (Math.PI / 180); + + const x = -((radius) * Math.sin(phi) * Math.cos(theta)), + z = ((radius) * Math.sin(phi) * Math.sin(theta)), + y = ((radius) * Math.cos(phi)); + + arr[i / 2 * 3 + 0] = x; + arr[i / 2 * 3 + 1] = y; + arr[i / 2 * 3 + 2] = z; + } + + outArr.set(arr); +} + + +}; + +Ops.Math.MapGeoCoordsSpherical.prototype = new CABLES.Op(); +CABLES.OPS["e4c6786b-abf6-4762-b8f9-ed89dd532e23"]={f:Ops.Math.MapGeoCoordsSpherical,objName:"Ops.Math.MapGeoCoordsSpherical"}; + + + + +// ************************************************************** +// +// Ops.Math.MapRange +// +// ************************************************************** + +Ops.Math.MapRange = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + v = op.inValueFloat("value", 0), + old_min = op.inValueFloat("old min", 0), + old_max = op.inValueFloat("old max", 1), + new_min = op.inValueFloat("new min", -1), + new_max = op.inValueFloat("new max", 1), + easing = op.inValueSelect("Easing", ["Linear", "Smoothstep", "Smootherstep"], "Linear"), + result = op.outNumber("result", 0); + +op.setPortGroup("Input Range", [old_min, old_max]); +op.setPortGroup("Output Range", [new_min, new_max]); + +let ease = 0; +let r = 0; + +v.onChange = + old_min.onChange = + old_max.onChange = + new_min.onChange = + new_max.onChange = exec; + +exec(); + +easing.onChange = function () +{ + if (easing.get() == "Smoothstep") ease = 1; + else if (easing.get() == "Smootherstep") ease = 2; + else ease = 0; +}; + +function exec() +{ + const nMin = new_min.get(); + const nMax = new_max.get(); + const oMin = old_min.get(); + const oMax = old_max.get(); + let x = v.get(); + + if (x >= Math.max(oMax, oMin)) + { + result.set(nMax); + return; + } + else + if (x <= Math.min(oMax, oMin)) + { + result.set(nMin); + return; + } + + let reverseInput = false; + const oldMin = Math.min(oMin, oMax); + const oldMax = Math.max(oMin, oMax); + if (oldMin != oMin) reverseInput = true; + + let reverseOutput = false; + const newMin = Math.min(nMin, nMax); + const newMax = Math.max(nMin, nMax); + if (newMin != nMin) reverseOutput = true; + + let portion = 0; + + if (reverseInput) portion = (oldMax - x) * (newMax - newMin) / (oldMax - oldMin); + else portion = (x - oldMin) * (newMax - newMin) / (oldMax - oldMin); + + if (reverseOutput) r = newMax - portion; + else r = portion + newMin; + + if (ease === 0) + { + result.set(r); + } + else + if (ease == 1) + { + x = Math.max(0, Math.min(1, (r - nMin) / (nMax - nMin))); + result.set(nMin + x * x * (3 - 2 * x) * (nMax - nMin)); // smoothstep + } + else + if (ease == 2) + { + x = Math.max(0, Math.min(1, (r - nMin) / (nMax - nMin))); + result.set(nMin + x * x * x * (x * (x * 6 - 15) + 10) * (nMax - nMin)); // smootherstep + } +} + + +}; + +Ops.Math.MapRange.prototype = new CABLES.Op(); +CABLES.OPS["2617b407-60a0-4ff6-b4a7-18136cfa7817"]={f:Ops.Math.MapRange,objName:"Ops.Math.MapRange"}; + + + + +// ************************************************************** +// +// Ops.Math.Math +// +// ************************************************************** + +Ops.Math.Math = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const num0 = op.inFloat("number 0", 0), + num1 = op.inFloat("number 1", 0), + mathDropDown = op.inSwitch("math mode", ["+", "-", "*", "/", "%", "min", "max"], "+"), + result = op.outNumber("result"); + +let mathFunc; + +num0.onChange = num1.onChange = update; +mathDropDown.onChange = onFilterChange; + +let n0 = 0; +let n1 = 0; + +const mathFuncAdd = function (a, b) { return a + b; }; +const mathFuncSub = function (a, b) { return a - b; }; +const mathFuncMul = function (a, b) { return a * b; }; +const mathFuncDiv = function (a, b) { return a / b; }; +const mathFuncMod = function (a, b) { return a % b; }; +const mathFuncMin = function (a, b) { return Math.min(a, b); }; +const mathFuncMax = function (a, b) { return Math.max(a, b); }; + +function onFilterChange() +{ + let mathSelectValue = mathDropDown.get(); + + if (mathSelectValue == "+") mathFunc = mathFuncAdd; + else if (mathSelectValue == "-") mathFunc = mathFuncSub; + else if (mathSelectValue == "*") mathFunc = mathFuncMul; + else if (mathSelectValue == "/") mathFunc = mathFuncDiv; + else if (mathSelectValue == "%") mathFunc = mathFuncMod; + else if (mathSelectValue == "min") mathFunc = mathFuncMin; + else if (mathSelectValue == "max") mathFunc = mathFuncMax; + update(); + op.setUiAttrib({ "extendTitle": mathSelectValue }); +} + +function update() +{ + n0 = num0.get(); + n1 = num1.get(); + + result.set(mathFunc(n0, n1)); +} + +onFilterChange(); + + +}; + +Ops.Math.Math.prototype = new CABLES.Op(); +CABLES.OPS["e9fdcaca-a007-4563-8a4d-e94e08506e0f"]={f:Ops.Math.Math,objName:"Ops.Math.Math"}; + + + + +// ************************************************************** +// +// Ops.Math.MathExpression +// +// ************************************************************** + +Ops.Math.MathExpression = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inA = op.inFloat("A", 0); +const inB = op.inFloat("B", 1); +const inC = op.inFloat("C", 2); +const inD = op.inFloat("D", 3); +op.setPortGroup("Parameters", [inA, inB, inC, inD]); +const inExpression = op.inString("Expression", "a*(b+c+d)"); +op.setPortGroup("Expression", [inExpression]); +const outResult = op.outNumber("Result"); +const outExpressionIsValid = op.outBool("Expression Valid"); + +let currentFunction = inExpression.get(); +let functionValid = false; + +const createFunction = () => +{ + try + { + currentFunction = new Function("m", "a", "b", "c", "d", `with(m) { return ${inExpression.get()} }`); + functionValid = true; + evaluateFunction(); + outExpressionIsValid.set(functionValid); + } + catch (e) + { + functionValid = false; + outExpressionIsValid.set(functionValid); + if (e instanceof ReferenceError || e instanceof SyntaxError) return; + } +}; + +const evaluateFunction = () => +{ + if (functionValid) + { + outResult.set(currentFunction(Math, inA.get(), inB.get(), inC.get(), inD.get())); + if (!inExpression.get()) outResult.set(0); + } + + outExpressionIsValid.set(functionValid); +}; + + +inA.onChange = inB.onChange = inC.onChange = inD.onChange = evaluateFunction; +inExpression.onChange = createFunction; +createFunction(); + + +}; + +Ops.Math.MathExpression.prototype = new CABLES.Op(); +CABLES.OPS["d2343a1e-64ea-45b2-99ed-46e167bbdcd3"]={f:Ops.Math.MathExpression,objName:"Ops.Math.MathExpression"}; + + + + +// ************************************************************** +// +// Ops.Math.Max +// +// ************************************************************** + +Ops.Math.Max = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + value = op.inValueFloat("value", 1), + max = op.inValueFloat("Maximum", 1), + result = op.outNumber("result"); + +max.onChange = + value.onChange = exec; + +exec(); + +function exec() +{ + let v = Math.max(value.get(), max.get()); + if (v == v) result.set(v); +} + + +}; + +Ops.Math.Max.prototype = new CABLES.Op(); +CABLES.OPS["07f0be49-c226-4029-8039-3b620145dc2a"]={f:Ops.Math.Max,objName:"Ops.Math.Max"}; + + + + +// ************************************************************** +// +// Ops.Math.MaxSinceReset +// +// ************************************************************** + +Ops.Math.MaxSinceReset = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const valuePort = op.inValue("Value"); +const resetPort = op.inTriggerButton("Reset"); +const maxPort = op.outNumber("Maximum"); + +let first; +let lastMax; + +// change listeners +resetPort.onTriggered = reset; +valuePort.onChange = update; + +// init +reset(); + +/** + * On Value change + */ +function update() +{ + let value = valuePort.get(); + if (first) + { + maxPort.set(value); + lastMax = value; + } + else + { + lastMax = Math.max(lastMax, value); + maxPort.set(lastMax); + } + first = false; +} + +/** + * On Reset + */ +function reset() +{ + first = true; +} + + +}; + +Ops.Math.MaxSinceReset.prototype = new CABLES.Op(); +CABLES.OPS["d3fdb4e1-199d-487a-a719-1315aa49fcfb"]={f:Ops.Math.MaxSinceReset,objName:"Ops.Math.MaxSinceReset"}; + + + + +// ************************************************************** +// +// Ops.Math.MercatorCoord +// +// ************************************************************** + +Ops.Math.MercatorCoord = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inLat = op.inValue("Latitude"), + inLon = op.inValue("Longitude"), + inMapWidth = op.inValue("MapWidth", 1), + outX = op.outNumber("X"), + outY = op.outNumber("Y"); + +inLat.onChange = + inLon.onChange = + inMapWidth.onChange = update; + + +function update() +{ + let mapWidth = inMapWidth.get();// 1.289672544080605; + let mapHeight = 1; + + let latitude = inLat.get(); + let longitude = inLon.get(); + // get x value + let x = (longitude + 180) * (mapWidth / 360); + + // convert from degrees to radians + let latRad = latitude * Math.PI / 180; + + // get y value + let mercN = Math.log(Math.tan((Math.PI / 4) + (latRad / 2))); + let y = (mapHeight / 2) - (mapWidth * mercN / (2 * Math.PI)); + + // x-=mapWidth/2; + + outX.set(x); + outY.set(0 - y); +} + + +}; + +Ops.Math.MercatorCoord.prototype = new CABLES.Op(); +CABLES.OPS["d95c5ba8-ed6e-4147-bf5f-8e44be3ef6cf"]={f:Ops.Math.MercatorCoord,objName:"Ops.Math.MercatorCoord"}; + + + + +// ************************************************************** +// +// Ops.Math.MercatorCoordsArray +// +// ************************************************************** + +Ops.Math.MercatorCoordsArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("LatLon Array"), + inMapWidth = op.inValue("MapWidth", 100), + inCenterLat = op.inValue("Center Lat", 0), + inCenterLon = op.inValue("Center Lon", 0), + outArr = op.outArray("Result"); + +inArr.onChange = + inMapWidth.onChange = + // inMapHeight.onChange= + inCenterLat.onChange = + inCenterLon.onChange = update; + +function calcLon(lon, mapWidth) +{ + const x = (lon + 180) * (mapWidth / 360); + return x; +} + +function calcLat(lat, mapWidth, mapHeight) +{ + const latRad = lat * Math.PI / 180; + + // get y value + const mercN = Math.log(Math.tan((Math.PI / 4) + (latRad / 2))); + const y = (mapHeight / 2) - (mapWidth * mercN / (2 * Math.PI)); + return y; +} + +function update() +{ + const mapWidth = inMapWidth.get();// 1.289672544080605; + const mapHeight = 1;// inMapHeight.get();// 1; + + const centerLon = calcLon(inCenterLon.get(), mapWidth, mapHeight); + const centerLat = calcLat(inCenterLat.get(), mapWidth, mapHeight); + + const arr = inArr.get(); + + if (!arr) + { + outArr.set(null); + return; + } + + const newArray = []; + + for (let i = 0; i < arr.length; i += 2) + { + const latitude = arr[i];// inLat.get(); + const longitude = arr[i + 1];// inLon.get(); + + let lon = calcLon(longitude, mapWidth, mapHeight); + let lat = calcLat(latitude, mapWidth, mapHeight); + + // convert from degrees to radians + // x-=mapWidth/2; + + lon -= centerLon; + lat -= centerLat; + + newArray.push(lon, 0 - lat); + } + + outArr.set(null); + outArr.set(newArray); +} + + +}; + +Ops.Math.MercatorCoordsArray.prototype = new CABLES.Op(); +CABLES.OPS["96e77c88-58b8-4948-bd61-c95d604a2607"]={f:Ops.Math.MercatorCoordsArray,objName:"Ops.Math.MercatorCoordsArray"}; + + + + +// ************************************************************** +// +// Ops.Math.MinSinceReset +// +// ************************************************************** + +Ops.Math.MinSinceReset = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let valuePort = op.inValue("Value"); +let resetPort = op.inTriggerButton("Reset"); +let minPort = op.outNumber("Minimum"); + +let first; +let lastMin; + +resetPort.onTriggered = reset; +valuePort.onChange = update; + +reset(); + +function update() +{ + let value = valuePort.get(); + if (first) + { + minPort.set(value); + lastMin = value; + } + else + { + lastMin = Math.min(lastMin, value); + minPort.set(lastMin); + } + first = false; +} + +function reset() +{ + first = true; +} + + +}; + +Ops.Math.MinSinceReset.prototype = new CABLES.Op(); +CABLES.OPS["30da693f-70bd-46bf-97d5-9f31e7f76bba"]={f:Ops.Math.MinSinceReset,objName:"Ops.Math.MinSinceReset"}; + + + + +// ************************************************************** +// +// Ops.Math.Min_v3 +// +// ************************************************************** + +Ops.Math.Min_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + val1 = op.inValue("Value 1", 1), + val2 = op.inValue("Value 2", 2), + result = op.outNumber("result"); + +val1.onChange = + val2.onChange = exec; + +exec(); + +function exec() +{ + let v = Math.min(val1.get(), val2.get()); + result.set(v); +} + + +}; + +Ops.Math.Min_v3.prototype = new CABLES.Op(); +CABLES.OPS["24a9062d-380c-4690-8fe7-6703787fa94c"]={f:Ops.Math.Min_v3,objName:"Ops.Math.Min_v3"}; + + + + +// ************************************************************** +// +// Ops.Math.Modulo +// +// ************************************************************** + +Ops.Math.Modulo = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number1 = op.inValueFloat("number1", 1), + number2 = op.inValueFloat("number2", 2), + pingpong = op.inValueBool("pingpong"), + result = op.outNumber("result"); + +let calculateFunction = calculateModule; + +number1.onChange = +number2.onChange = exec; + +pingpong.onChange = updatePingPong; + +exec(); + +function exec() +{ + let n2 = number2.get(); + let n1 = number1.get(); + + result.set(calculateFunction(n1, n2)); +} + +function calculateModule(n1, n2) +{ + let re = ((n1 % n2) + n2) % n2; + if (re != re) re = 0; + return re; +} + +function calculatePingPong(i, n) +{ + let cycle = 2 * n; + i %= cycle; + if (i >= n) return cycle - i; + else return i; +} + +function updatePingPong() +{ + if (pingpong.get()) calculateFunction = calculatePingPong; + else calculateFunction = calculateModule; +} + + +}; + +Ops.Math.Modulo.prototype = new CABLES.Op(); +CABLES.OPS["ebc13b25-3705-4265-8f06-5f985b6a7bb1"]={f:Ops.Math.Modulo,objName:"Ops.Math.Modulo"}; + + + + +// ************************************************************** +// +// Ops.Math.MulMatrixXyz +// +// ************************************************************** + +Ops.Math.MulMatrixXyz = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Update"), + inX = op.inFloat("X", 0), + inY = op.inFloat("Y", 0), + inZ = op.inFloat("Z", 0), + inMat = op.inArray("Matrix"), + outNext = op.outTrigger("Next"), + outX = op.outNumber("Result X"), + outY = op.outNumber("Result Y"), + outZ = op.outNumber("Result Z"); + +let theArr = []; +let vec = vec4.create(); + +exec.onTriggered = function () +{ + const mMat = inMat.get(); + + if (!mMat) return; + + vec4.set(vec, inX.get(), inY.get(), inZ.get(), 1); + + vec3.transformMat4(vec, vec, mMat); + + outX.set(vec[0]); + outY.set(vec[1]); + outZ.set(vec[2]); + + outNext.trigger(); +}; + + +}; + +Ops.Math.MulMatrixXyz.prototype = new CABLES.Op(); +CABLES.OPS["69cc5915-fd7f-4c6c-9a8c-8553c6bab0c5"]={f:Ops.Math.MulMatrixXyz,objName:"Ops.Math.MulMatrixXyz"}; + + + + +// ************************************************************** +// +// Ops.Math.Multiply +// +// ************************************************************** + +Ops.Math.Multiply = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number1 = op.inValueFloat("number1", 1), + number2 = op.inValueFloat("number2", 2), + result = op.outNumber("result"); + +op.setTitle("*"); + +number1.onChange = number2.onChange = update; +update(); + +function update() +{ + const n1 = number1.get(); + const n2 = number2.get(); + + result.set(n1 * n2); +} + + +}; + +Ops.Math.Multiply.prototype = new CABLES.Op(); +CABLES.OPS["1bbdae06-fbb2-489b-9bcc-36c9d65bd441"]={f:Ops.Math.Multiply,objName:"Ops.Math.Multiply"}; + + + + +// ************************************************************** +// +// Ops.Math.NumberDivisible +// +// ************************************************************** + +Ops.Math.NumberDivisible = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + num = op.inValue("Number"), + divisor = op.inValue("Divisor"), + result = op.outBoolNum("Result"); + +num.onChange = divisor.onChange = function () +{ + result.set(num.get() % divisor.get() === 0); +}; + + +}; + +Ops.Math.NumberDivisible.prototype = new CABLES.Op(); +CABLES.OPS["4059e4ee-da93-490a-a00c-6fe0f0ee8efc"]={f:Ops.Math.NumberDivisible,objName:"Ops.Math.NumberDivisible"}; + + + + +// ************************************************************** +// +// Ops.Math.OneMinus +// +// ************************************************************** + +Ops.Math.OneMinus = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inValue = op.inValue("Value"), + result = op.outNumber("Result"); + +inValue.onChange = update; +update(); + +function update() +{ + result.set(1 - inValue.get()); +} + + +}; + +Ops.Math.OneMinus.prototype = new CABLES.Op(); +CABLES.OPS["f34d019d-59ae-40d6-a55d-a7691bbc40e0"]={f:Ops.Math.OneMinus,objName:"Ops.Math.OneMinus"}; + + + + +// ************************************************************** +// +// Ops.Math.PerlinNoise_v2 +// +// ************************************************************** + +Ops.Math.PerlinNoise_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inX = op.inFloat("X", 0), + inY = op.inFloat("Y", 0), + inZ = op.inFloat("Z", 0), + inScale = op.inFloat("Scale", 4), + inSeed = op.inFloat("Seed", 1), + + result = op.outNumber("Result"); + +const PERLIN_YWRAPB = 4; +const PERLIN_YWRAP = 1 << PERLIN_YWRAPB; +const PERLIN_ZWRAPB = 8; +const PERLIN_ZWRAP = 1 << PERLIN_ZWRAPB; +const PERLIN_SIZE = 4095; + +let perlin_octaves = 4; // default to medium smooth +let perlin_amp_falloff = 0.5; // 50% reduction/octave + +const scaled_cosine = (i) => 0.5 * (1.0 - Math.cos(i * Math.PI)); + +let perlin = null; + +inX.onChange = + inY.onChange = + inZ.onChange = update; + +function update() +{ + let s = inScale.get(); + let r = noise(inX.get() * s, inY.get() * s, inZ.get() * s); + result.set(r); +} + +function noise(x, y = 0, z = 0) +{ + if (perlin == null) + { + perlin = new Array(PERLIN_SIZE + 1); + for (let i = 0; i < PERLIN_SIZE + 1; i++) + { + perlin[i] = Math.random(); + } + } + + if (x < 0) + { + x = -x; + } + if (y < 0) + { + y = -y; + } + if (z < 0) + { + z = -z; + } + + let xi = Math.floor(x), + yi = Math.floor(y), + zi = Math.floor(z); + let xf = x - xi; + let yf = y - yi; + let zf = z - zi; + let rxf, ryf; + + let r = 0; + let ampl = 0.5; + + let n1, n2, n3; + + for (let o = 0; o < perlin_octaves; o++) + { + let of = xi + (yi << PERLIN_YWRAPB) + (zi << PERLIN_ZWRAPB); + + rxf = scaled_cosine(xf); + ryf = scaled_cosine(yf); + + n1 = perlin[of & PERLIN_SIZE]; + n1 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n1); + n2 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE]; + n2 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n2); + n1 += ryf * (n2 - n1); + + of += PERLIN_ZWRAP; + n2 = perlin[of & PERLIN_SIZE]; + n2 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n2); + n3 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE]; + n3 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n3); + n2 += ryf * (n3 - n2); + + n1 += scaled_cosine(zf) * (n2 - n1); + + r += n1 * ampl; + ampl *= perlin_amp_falloff; + xi <<= 1; + xf *= 2; + yi <<= 1; + yf *= 2; + zi <<= 1; + zf *= 2; + + if (xf >= 1.0) + { + xi++; + xf--; + } + if (yf >= 1.0) + { + yi++; + yf--; + } + if (zf >= 1.0) + { + zi++; + zf--; + } + } + return r; +} + +inSeed.onChange = () => +{ + Math.randomSeed = inSeed.get(); + perlin = new Array(PERLIN_SIZE + 1); + for (let i = 0; i < PERLIN_SIZE + 1; i++) + { + perlin[i] = Math.seededRandom(); + } +}; + + +}; + +Ops.Math.PerlinNoise_v2.prototype = new CABLES.Op(); +CABLES.OPS["b1a19b32-4ccd-4bce-a37d-e386e53dfc1c"]={f:Ops.Math.PerlinNoise_v2,objName:"Ops.Math.PerlinNoise_v2"}; + + + + +// ************************************************************** +// +// Ops.Math.Pi +// +// ************************************************************** + +Ops.Math.Pi = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + multiply = op.inValueFloat("Multiply amount", 1.0), + p = op.outNumber("Pi", Math.PI); + +multiply.onChange = function () +{ + p.setValue(Math.PI * multiply.get()); +}; + + +}; + +Ops.Math.Pi.prototype = new CABLES.Op(); +CABLES.OPS["311e8179-9a7c-43de-9eb2-84577d702974"]={f:Ops.Math.Pi,objName:"Ops.Math.Pi"}; + + + + +// ************************************************************** +// +// Ops.Math.PointInRectangle2d +// +// ************************************************************** + +Ops.Math.PointInRectangle2d = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + x = op.inValue("x"), + y = op.inValue("y"), + + rtop = op.inValue("rect top"), + rleft = op.inValue("rect left"), + rright = op.inValue("rect right"), + rbottom = op.inValue("rect bottom"), + + result = op.outBoolNum("Result"), + outX = op.outNumber("Pos x"), + outY = op.outNumber("Pos y"); + +x.onChange = y.onChange = function () +{ + let isIn = (x.get() > rleft.get() && x.get() < rright.get() && y.get() > rtop.get() && y.get() < rbottom.get()); + + outX.set(Math.max(0, Math.min(1.0, (x.get() - rleft.get()) / (rright.get() - rleft.get())))); + outY.set(Math.max(0, Math.min(1.0, (y.get() - rtop.get()) / (rbottom.get() - rtop.get())))); + + result.set(isIn == true); +}; + + +}; + +Ops.Math.PointInRectangle2d.prototype = new CABLES.Op(); +CABLES.OPS["6d722288-0fec-43da-bf41-0372426fb685"]={f:Ops.Math.PointInRectangle2d,objName:"Ops.Math.PointInRectangle2d"}; + + + + +// ************************************************************** +// +// Ops.Math.Pow +// +// ************************************************************** + +Ops.Math.Pow = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + base = op.inValueFloat("Base"), + exponent = op.inValueFloat("Exponent"), + result = op.outNumber("Result"); + +exponent.set(2); + +base.onChange = update; +exponent.onChange = update; + +function update() +{ + let r = Math.pow(base.get(), exponent.get()); + if (isNaN(r))r = 0; + result.set(r); +} + + +}; + +Ops.Math.Pow.prototype = new CABLES.Op(); +CABLES.OPS["3bb3f98f-27d6-44c4-b4e5-186e10f0809d"]={f:Ops.Math.Pow,objName:"Ops.Math.Pow"}; + + + + +// ************************************************************** +// +// Ops.Math.PowerOfTwoSize +// +// ************************************************************** + +Ops.Math.PowerOfTwoSize = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inW = op.inValueInt("Width"), + inH = op.inValueInt("Height"), + inStrat = op.inValueSelect("Strategy", ["floor", "floor/2", "ceil"], "floor"), + outW = op.outNumber("Width Result"), + outH = op.outNumber("Height Result"); +inStrat.onChange = updateStrategy; +inW.onChange = inH.onChange = update; +let getPOT = null; +updateStrategy(); + +function isPOT(x) +{ + return (x == 1 || x == 2 || x == 4 || x == 8 || x == 16 || x == 32 || x == 64 || x == 128 || x == 256 || x == 512 || x == 1024 || x == 2048 || x == 4096 || x == 8192 || x == 16384); +} + +function updateStrategy() +{ + let s = inStrat.get(); + + if (s == "floor")getPOT = getPotNextfloor; + if (s == "floor/2")getPOT = getPotNextfloorx2; + if (s == "ceil")getPOT = getPotNextBigger; + if (s == "nearest")getPOT = getPotNearest; + + update(); +} + +function getPotNextBigger(x) +{ + // if(x>8192)return 16384; + // if(x>4096)return 8129; + if (x > 2048) return 4096; + if (x > 1024) return 2048; + if (x > 512) return 1024; + if (x > 256) return 512; + if (x > 128) return 256; + if (x > 64) return 128; + if (x > 32) return 64; + if (x > 16) return 32; + if (x > 8) return 16; + if (x > 4) return 8; + if (x > 2) return 4; +} + +function getPotNextfloorx2(x) +{ + return Math.ceil(getPotNextfloor(x) / 2); +} + +function getPotNextfloor(x) +{ + if (x < 2) return 1; + if (x < 4) return 2; + if (x < 8) return 4; + if (x < 16) return 8; + if (x < 32) return 16; + if (x < 64) return 32; + if (x < 128) return 64; + if (x < 256) return 128; + if (x < 512) return 256; + if (x < 1024) return 512; + if (x < 2048) return 1024; + if (x < 4096) return 2048; + if (x < 8192) return 4096; + // if(x<16384)return 8192; +} + +function getPotNearest(x) +{ + if (x > 3072) return 4096; + if (x > 1536) return 2048; + if (x > 768) return 1024; + if (x > 320) return 512; + if (x > 191) return 256; + if (x > 95) return 128; + if (x > 47) return 64; + if (x > 23) return 32; + if (x > 11) return 16; + if (x > 5) return 8; + if (x > 3) return 4; + return 2; +} + +function update() +{ + let w = inW.get(); + let h = inH.get(); + + if (!isPOT(w)) w = getPOT(w); + if (!isPOT(h)) h = getPOT(h); + + outW.set(w); + outH.set(h); +} + + +}; + +Ops.Math.PowerOfTwoSize.prototype = new CABLES.Op(); +CABLES.OPS["58e01e34-0f42-4861-ad9a-ed96e08f8565"]={f:Ops.Math.PowerOfTwoSize,objName:"Ops.Math.PowerOfTwoSize"}; + + + + +// ************************************************************** +// +// Ops.Math.Radians +// +// ************************************************************** + +Ops.Math.Radians = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + value = op.inValue("Degrees"), + result = op.outNumber("Result"), + calculate = Math.cos; + +// convert degrees into radians +value.onChange = function () +{ + result.set( + value.get() * Math.PI / 180 + ); +}; + + +}; + +Ops.Math.Radians.prototype = new CABLES.Op(); +CABLES.OPS["d6daab6e-791e-4c4c-ac01-d887447de4f9"]={f:Ops.Math.Radians,objName:"Ops.Math.Radians"}; + + + + +// ************************************************************** +// +// Ops.Math.RandomCounter +// +// ************************************************************** + +Ops.Math.RandomCounter = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inCount=op.inTriggerButton("Count"), + inMin=op.inFloat("Step Min",0.5), + inMax=op.inFloat("Step Max",1), + outNum=op.outNumber("Result"); + +inCount.onTriggered=count; + +let v=0; + + +function count() +{ + + let r=Math.seededRandom() * (inMax.get() - inMin.get()) + inMin.get(); + + if(Math.seededRandom()>0.5) v+=r; + else v-=r; + + outNum.set(v); + +} + +}; + +Ops.Math.RandomCounter.prototype = new CABLES.Op(); +CABLES.OPS["48c712f0-bb8e-4a0b-9b97-26da68a68223"]={f:Ops.Math.RandomCounter,objName:"Ops.Math.RandomCounter"}; + + + + +// ************************************************************** +// +// Ops.Math.RandomNumbers_v3 +// +// ************************************************************** + +Ops.Math.RandomNumbers_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inSeed = op.inValueFloat("Seed", 1), + min = op.inValueFloat("Min", 0), + max = op.inValueFloat("Max", 1), + outX = op.outNumber("X"), + outY = op.outNumber("Y"), + outZ = op.outNumber("Z"), + outW = op.outNumber("W"); + +inSeed.onChange = + min.onChange = + max.onChange = update; +update(); + +function update() +{ + const inMin = min.get(); + const inMax = max.get(); + Math.randomSeed = Math.abs(inSeed.get() || 0) * 571.1 + 1.0; + outX.set(Math.seededRandom() * (inMax - inMin) + inMin); + outY.set(Math.seededRandom() * (inMax - inMin) + inMin); + outZ.set(Math.seededRandom() * (inMax - inMin) + inMin); + outW.set(Math.seededRandom() * (inMax - inMin) + inMin); +} + + +}; + +Ops.Math.RandomNumbers_v3.prototype = new CABLES.Op(); +CABLES.OPS["d2b970e1-9406-4459-995c-5a594acd88e3"]={f:Ops.Math.RandomNumbers_v3,objName:"Ops.Math.RandomNumbers_v3"}; + + + + +// ************************************************************** +// +// Ops.Math.RotationFromNormal +// +// ************************************************************** + +Ops.Math.RotationFromNormal = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inNormalX = op.inValue("Normal X"); +const inNormalY = op.inValue("Normal Y"); +const inNormalZ = op.inValue("Normal Z"); +const inRecalculate = op.inTriggerButton("recalculate"); + +const outRotation = op.outArray("RotationMatrix"); + +const identMat = mat4.create(); +const outMat = mat4.create(); +const upVec = vec3.fromValues(0, 1, 0); +const tmpVec = vec3.create(); +const tmpQuat = quat.create(); + +outRotation.set(identMat); + +inRecalculate.onTriggered = function () +{ + vec3.set( + tmpVec, + inNormalX.get(), + inNormalY.get(), + inNormalZ.get() + ); + + vec3.normalize(tmpVec, tmpVec); + quat.identity(tmpQuat); + quat.rotationTo(tmpQuat, upVec, tmpVec); + mat4.fromQuat(outMat, tmpQuat); + outRotation.set(identMat); + outRotation.set(outMat); +}; + + +}; + +Ops.Math.RotationFromNormal.prototype = new CABLES.Op(); +CABLES.OPS["9b39dd02-9558-4297-ba8a-8f21f690d128"]={f:Ops.Math.RotationFromNormal,objName:"Ops.Math.RotationFromNormal"}; + + + + +// ************************************************************** +// +// Ops.Math.Round +// +// ************************************************************** + +Ops.Math.Round = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number1 = op.inValueFloat("number"), + decPlaces = op.inInt("Decimal Places", 0), + result = op.outNumber("result"); + +let decm = 0; + +number1.onChange = exec; +decPlaces.onChange = updateDecm; + +updateDecm(); + +function updateDecm() +{ + decm = Math.pow(10, decPlaces.get()); + exec(); +} + +function exec() +{ + result.set(Math.round(number1.get() * decm) / decm); +} + + +}; + +Ops.Math.Round.prototype = new CABLES.Op(); +CABLES.OPS["1a1ef636-6d02-42ba-ae1e-627b917d0d2b"]={f:Ops.Math.Round,objName:"Ops.Math.Round"}; + + + + +// ************************************************************** +// +// Ops.Math.RoundEven +// +// ************************************************************** + +Ops.Math.RoundEven = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inNum = op.inValueFloat("Number"), + inMode = op.inSwitch("Mode", ["Ceil", "Floor"], "Ceil"), + result = op.outNumber("Result"); + +inMode.onChange = inNum.onChange = function () +{ + let value = 0; + switch (inMode.get()) + { + case "Floor": + value = 2 * (Math.floor(inNum.get() / 2.0)); + break; + default: + case "Ceil": + value = 2 * (Math.round(inNum.get() / 2.0)); + break; + } + result.set(value); +}; + + +}; + +Ops.Math.RoundEven.prototype = new CABLES.Op(); +CABLES.OPS["b4c116ba-ab64-4903-80bb-35c8d65819a1"]={f:Ops.Math.RoundEven,objName:"Ops.Math.RoundEven"}; + + + + +// ************************************************************** +// +// Ops.Math.SchlickBias +// +// ************************************************************** + +Ops.Math.SchlickBias = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inX=op.inFloat("Value",0), + inGain=op.inFloatSlider("Gain",0.5), + inBias=op.inFloatSlider("Bias",0.5), + result=op.outNumber("Result"); + +inX.onChange= +inBias.onChange= +inGain.onChange=getGain; + +function getBias(x,bias) +{ + const r= x / ((1 / bias - 2) * (1 - x) + 1); + return r; +} + +function getGain() +{ + const gain=inGain.get(); + const x=inX.get(); + let r= x < 0.5 ? getBias(x * 2.0, gain)/2.0 : getBias(x * 2.0 - 1.0,1.0 - gain)/2.0 + 0.5; + + r=getBias(r,inBias.get()); + + + result.set(r); + +} + + + + +}; + +Ops.Math.SchlickBias.prototype = new CABLES.Op(); +CABLES.OPS["ea957aae-c9c7-4d2a-a227-c2a10042f554"]={f:Ops.Math.SchlickBias,objName:"Ops.Math.SchlickBias"}; + + + + +// ************************************************************** +// +// Ops.Math.Sign +// +// ************************************************************** + +Ops.Math.Sign = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + value = op.inValue("Value"), + noZeroIn = op.inBool("Remove zero", false), + result = op.outNumber("Result"); + +value.onChange = function () +{ + let direction = 0; + let val = value.get() * 999; + let noZero = noZeroIn.get(); + + if (!noZero) + { + direction = Math.round(Math.max(Math.min(val, 1), -1)); + } + else + { + direction = (val < 0) ? -1 : 1; + } + result.set(direction); +}; + + +}; + +Ops.Math.Sign.prototype = new CABLES.Op(); +CABLES.OPS["a0d6ed0e-9b6b-4d84-a599-882feeadd769"]={f:Ops.Math.Sign,objName:"Ops.Math.Sign"}; + + + + +// ************************************************************** +// +// Ops.Math.SimpleMovingAverage +// +// ************************************************************** + +Ops.Math.SimpleMovingAverage = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + val = op.inValue("Value"), + num = op.inValueInt("Number of Values", 10), + result = op.outNumber("Result"); + +val.changeAlways = true; +let buffer = []; +let index = 0; + +num.onChange = init; +init(); + +function init() +{ + let n = Math.abs(Math.floor(num.get())); + buffer.length = n; + + for (let i = 0; i < buffer.length; i++)buffer[i] = null; + index = 0; +} + +val.onChange = function () +{ + index++; + if (index >= buffer.length)index = 0; + buffer[index] = val.get(); + + let avg = 0; + let divide = 0; + for (let i = 0; i < buffer.length; i++) + { + if (buffer[i] !== null) // ignore zeroes + { + avg += buffer[i]; + divide++; + } + } + + result.set(avg / divide || 1); +}; + + +}; + +Ops.Math.SimpleMovingAverage.prototype = new CABLES.Op(); +CABLES.OPS["b28c1e66-1c88-4394-bf73-327c0e82ea34"]={f:Ops.Math.SimpleMovingAverage,objName:"Ops.Math.SimpleMovingAverage"}; + + + + +// ************************************************************** +// +// Ops.Math.Sine +// +// ************************************************************** + +Ops.Math.Sine = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + value = op.inValue("value"), + phase = op.inValue("phase", 0.0), + mul = op.inValue("frequency", 1.0), + amplitude = op.inValue("amplitude", 1.0), + invert = op.inValueBool("asine", false), + result = op.outNumber("result"); + +let calculate = Math.sin; + +mul.onChange = +amplitude.onChange = +phase.onChange = +value.onChange = function () +{ + result.set( + amplitude.get() * calculate((value.get() * mul.get()) + phase.get()) + ); +}; + +invert.onChange = function () +{ + if (invert.get()) calculate = Math.asin; + else calculate = Math.sin; +}; + + +}; + +Ops.Math.Sine.prototype = new CABLES.Op(); +CABLES.OPS["d24da018-9f3d-428b-85c9-6ff14d77548b"]={f:Ops.Math.Sine,objName:"Ops.Math.Sine"}; + + + + +// ************************************************************** +// +// Ops.Math.SmoothStep_v2 +// +// ************************************************************** + +Ops.Math.SmoothStep_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + result = op.outNumber("result"), + number = op.inValueFloat("number", 0), + min = op.inValueFloat("min", 0), + max = op.inValueFloat("max", 1); + +number.onChange = max.onChange = min.onChange = exec; +exec(); + +function exec() +{ + let x = Math.max(0, Math.min(1, (number.get() - min.get()) / (max.get() - min.get()))); + result.set(x * x * (3 - 2) * (max.get() - min.get())); // smoothstep +} + + +}; + +Ops.Math.SmoothStep_v2.prototype = new CABLES.Op(); +CABLES.OPS["b5c41eea-ac30-4ac7-9481-eefe42e8199c"]={f:Ops.Math.SmoothStep_v2,objName:"Ops.Math.SmoothStep_v2"}; + + + + +// ************************************************************** +// +// Ops.Math.SmootherStep +// +// ************************************************************** + +Ops.Math.SmootherStep = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + val = op.inValueFloat("val", 0), + min = op.inValueFloat("min", 0), + max = op.inValueFloat("max", 1), + result = op.outNumber("result"); + +val.onChange = max.onChange = min.onChange = exec; +exec(); + +function exec() +{ + let x = Math.max(0, Math.min(1, (val.get() - min.get()) / (max.get() - min.get()))); + result.set(x * x * x * (x * (x * 6 - 15) + 10) * (max.get() - min.get())); // smootherstep +} + + +}; + +Ops.Math.SmootherStep.prototype = new CABLES.Op(); +CABLES.OPS["c66da84f-ff2f-45de-b3c2-557bdf1cb946"]={f:Ops.Math.SmootherStep,objName:"Ops.Math.SmootherStep"}; + + + + +// ************************************************************** +// +// Ops.Math.Speed +// +// ************************************************************** + +Ops.Math.Speed = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExe = op.inTrigger("Update"), + inVal = op.inValue("Value"), + result = op.outNumber("Speed"); + +inVal.alwaysChange = true; + +let lastVal = 0; +let lastTime = CABLES.now(); +inExe.onTriggered = update; + +function update() +{ + let diff = Math.abs(inVal.get() - lastVal); + let diffTime = CABLES.now() - lastTime; + + let speed = diff * (1000 / diffTime); + + result.set(speed); + + lastVal = inVal.get(); + lastTime = CABLES.now(); +} + + +}; + +Ops.Math.Speed.prototype = new CABLES.Op(); +CABLES.OPS["ff6b8c7b-00c6-48f2-9b43-d059e52143fe"]={f:Ops.Math.Speed,objName:"Ops.Math.Speed"}; + + + + +// ************************************************************** +// +// Ops.Math.Sqrt +// +// ************************************************************** + +Ops.Math.Sqrt = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number = op.inValue("number"), + result = op.outNumber("result"); + +number.onChange = function () +{ + let r = Math.sqrt(number.get()); + if (isNaN(r))r = 0; + result.set(r); +}; + + +}; + +Ops.Math.Sqrt.prototype = new CABLES.Op(); +CABLES.OPS["dec567c3-231d-4146-964d-891fde8924f1"]={f:Ops.Math.Sqrt,objName:"Ops.Math.Sqrt"}; + + + + +// ************************************************************** +// +// Ops.Math.Subtract +// +// ************************************************************** + +Ops.Math.Subtract = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number1 = op.inValue("number1", 1), + number2 = op.inValue("number2", 1), + result = op.outNumber("result"); + +op.setTitle("-"); + +number1.onChange = + number2.onChange = exec; +exec(); + +function exec() +{ + let v = number1.get() - number2.get(); + if (!isNaN(v)) result.set(v); +} + + +}; + +Ops.Math.Subtract.prototype = new CABLES.Op(); +CABLES.OPS["a4ffe852-d200-4b96-9347-68feb01122ca"]={f:Ops.Math.Subtract,objName:"Ops.Math.Subtract"}; + + + + +// ************************************************************** +// +// Ops.Math.Sum +// +// ************************************************************** + +Ops.Math.Sum = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number1 = op.inValueFloat("number1", 1), + number2 = op.inValueFloat("number2", 1), + result = op.outNumber("result"); + +op.setTitle("+"); + +number1.onChange = +number2.onChange = exec; +exec(); + +function exec() +{ + const v = number1.get() + number2.get(); + if (!isNaN(v)) + result.set(v); +} + + +}; + +Ops.Math.Sum.prototype = new CABLES.Op(); +CABLES.OPS["c8fb181e-0b03-4b41-9e55-06b6267bc634"]={f:Ops.Math.Sum,objName:"Ops.Math.Sum"}; + + + + +// ************************************************************** +// +// Ops.Math.Tangent +// +// ************************************************************** + +Ops.Math.Tangent = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + value = op.inValue("Value"), + phase = op.inValue("Phase", 0.0), + mul = op.inValue("Frequency", 1.0), + amplitude = op.inValue("Amplitude", 1.0), + invert = op.inValueBool("asine", false), + result = op.outNumber("Result"); + +let calculate = Math.tan; + +value.onChange = function () +{ + result.set( + amplitude.get() * calculate((value.get() * mul.get()) + phase.get()) + ); +}; + +invert.onChange = function () +{ + if (invert.get()) calculate = Math.atan; + else calculate = Math.tan; +}; + + +}; + +Ops.Math.Tangent.prototype = new CABLES.Op(); +CABLES.OPS["be52d1f0-1004-4161-9ba9-7921c38955c0"]={f:Ops.Math.Tangent,objName:"Ops.Math.Tangent"}; + + + + +// ************************************************************** +// +// Ops.Math.TriggerMathExpression +// +// ************************************************************** + +Ops.Math.TriggerMathExpression = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inExec = op.inTrigger("Calculate"), + inExpression = op.inString("Expression", "x*(y+z)"), + + inX = op.inFloat("X", 0), + inY = op.inFloat("Y", 0), + inZ = op.inFloat("Z", 0), + inW = op.inFloat("W", 0), + + inA = op.inFloat("A", 0), + inB = op.inFloat("B", 0), + inC = op.inFloat("C", 0), + inD = op.inFloat("D", 0), + + inI = op.inFloat("I", 0), + + next = op.outTrigger("Next"), + outResult = op.outNumber("Result"), + outExpressionIsValid = op.outBool("Expression Valid"); + +op.setPortGroup("Parameters", [inA, inB, inC, inD, inX, inY, inZ, inW, inI]); + +let currentFunction = inExpression.get(); +let functionValid = false; + +inExec.onTriggered = evaluateFunction; +inExpression.onChange = createFunction; + +createFunction(); + +function createFunction() +{ + try + { + currentFunction = new Function("m", "a", "b", "c", "d", "x", "y", "z", "w", "i", "with(m) { return " + inExpression.get() + " }"); + + functionValid = true; + evaluateFunction(); + outExpressionIsValid.set(functionValid); + } + catch (e) + { + functionValid = false; + outExpressionIsValid.set(functionValid); + if (e instanceof ReferenceError || e instanceof SyntaxError) return; + } +} + +function evaluateFunction() +{ + if (functionValid) + { + outResult.set(currentFunction(Math, inA.get(), inB.get(), inC.get(), inD.get(), inX.get(), inY.get(), inZ.get(), inW.get(), inI.get())); + if (!inExpression.get()) outResult.set(0); + } + + outExpressionIsValid.set(functionValid); + next.trigger(); +} + + +}; + +Ops.Math.TriggerMathExpression.prototype = new CABLES.Op(); +CABLES.OPS["7ba04c59-5b31-44f9-bd15-865a6db67c81"]={f:Ops.Math.TriggerMathExpression,objName:"Ops.Math.TriggerMathExpression"}; + + + + +// ************************************************************** +// +// Ops.Math.TriggerRandomNumber_v2 +// +// ************************************************************** + +Ops.Math.TriggerRandomNumber_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTriggerButton("Generate"), + min = op.inValue("min", 0), + max = op.inValue("max", 1), + outTrig = op.outTrigger("next"), + result = op.outNumber("result"), + inInteger = op.inValueBool("Integer", false), + noDupe = op.inValueBool("No consecutive duplicates", false); + +op.setPortGroup("Value Range", [min, max]); + +exe.onTriggered = + max.onChange = + min.onChange = + inInteger.onChange = genRandom; + +genRandom(); + +function genRandom() +{ + let r = (Math.random() * (max.get() - min.get())) + min.get(); + + if (inInteger.get())r = randInt(); + + if (min.get() != max.get() && max.get() > min.get()) + while (noDupe.get() && r == result.get()) r = randInt(); + + result.set(r); + outTrig.trigger(); +} + +function randInt() +{ + return Math.floor((Math.random() * ((max.get() - min.get() + 1))) + min.get()); +} + + +}; + +Ops.Math.TriggerRandomNumber_v2.prototype = new CABLES.Op(); +CABLES.OPS["26f446cc-9107-4164-8209-5254487fa132"]={f:Ops.Math.TriggerRandomNumber_v2,objName:"Ops.Math.TriggerRandomNumber_v2"}; + + + + +// ************************************************************** +// +// Ops.Math.VectorLength +// +// ************************************************************** + +Ops.Math.VectorLength = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + x = op.inValue("X"), + y = op.inValue("Y"), + z = op.inValue("Z"), + l = op.outNumber("Length"); + +x.onChange = + y.onChange = + z.onChange = update; + +let vec = vec3.create(); + +function update() +{ + vec3.set(vec, x.get(), y.get(), z.get()); + l.set(vec3.len(vec)); +} + + +}; + +Ops.Math.VectorLength.prototype = new CABLES.Op(); +CABLES.OPS["a9e7bda2-7f57-4df2-83e3-74cdf63371d7"]={f:Ops.Math.VectorLength,objName:"Ops.Math.VectorLength"}; + + + + +// ************************************************************** +// +// Ops.Net.CorsProxy_v2 +// +// ************************************************************** + +Ops.Net.CorsProxy_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let a = op.inString("URL", ""); +let result = op.outString("CORS URL"); +let CORS_CABLES_PROXY = "https://cors.cables.gl/"; + +a.onChange = update; + +update(); + +function update() +{ + result.set(CORS_CABLES_PROXY + a.get()); +} + + +}; + +Ops.Net.CorsProxy_v2.prototype = new CABLES.Op(); +CABLES.OPS["0cac2fb2-cac2-4b50-82c1-f7047ef96e0a"]={f:Ops.Net.CorsProxy_v2,objName:"Ops.Net.CorsProxy_v2"}; + + + + +// ************************************************************** +// +// Ops.Net.WebSocket.WebSocketSend +// +// ************************************************************** + +Ops.Net.WebSocket.WebSocketSend = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inConnection = op.inObject("Connection", null, "Websocket"), + inObject = op.inObject("Object"), + inSend = op.inTriggerButton("Send"), + inStringify = op.inBool("Send String", true), + outSent = op.outBoolNum("Sent"); + +let connection = null; + +inConnection.onChange = function () +{ + connection = inConnection.get(); +}; + +inSend.onTriggered = function () +{ + if (connection && inObject.get()) + { + if (inStringify.get())connection.send(JSON.stringify(inObject.get())); + else connection.send(inObject.get()); + + outSent.set(true); + } + else + { + outSent.set(false); + } +}; + + +}; + +Ops.Net.WebSocket.WebSocketSend.prototype = new CABLES.Op(); +CABLES.OPS["071149e8-5ac5-43dd-a052-e32dbd80cae2"]={f:Ops.Net.WebSocket.WebSocketSend,objName:"Ops.Net.WebSocket.WebSocketSend"}; + + + + +// ************************************************************** +// +// Ops.Net.WebSocket.WebSocket_v2 +// +// ************************************************************** + +Ops.Net.WebSocket.WebSocket_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inUrl = op.inString("URL"), + outConnection = op.outObject("Connection", null, "Websocket"), + outResult = op.outObject("Result"), + outConnected = op.outBoolNum("Connected"), + outValidJson = op.outBoolNum("Valid JSON"), + outReceived = op.outTrigger("Received Data"), + outRaw = op.outString("Raw Data"); + +let connection = null; +let timeout = null; +let connectedTo = ""; + +inUrl.onChange = connect; +timeout = setTimeout(checkConnection, 2000); + +inUrl.set(); + +let connecting = false; + +function checkConnection() +{ + if (!outConnected.get() && !connecting) + { + op.log("reconnect websocket..."); + connect(); + } + + timeout = setTimeout(checkConnection, 2000); +} + +op.onDelete = function () +{ + if (outConnected.get())connection.close(); + connecting = false; + clearTimeout(timeout); +}; + +function connect() +{ + op.setUiError("connection", null); + op.setUiError("jsonvalid", null); + + if (outConnected.get() && connectedTo == inUrl.get()) return; + + if (!inUrl.get() || inUrl.get() === "") + { + op.log("websocket: invalid url "); + outConnected.set(false); + return; + } + + window.WebSocket = window.WebSocket || window.MozWebSocket; + + if (!window.WebSocket) + op.logError("Sorry, but your browser doesn't support WebSockets."); + + try + { + connecting = true; + if (connection !== null)connection.close(); + connection = new WebSocket(inUrl.get()); + } + catch (e) + { + op.log("could not connect to", inUrl.get()); + connecting = false; + op.log(e); + } + + if (connection) + { + connection.onerror = function (message) + { + connecting = false; + op.log("ws error"); + outConnected.set(false); + outConnection.set(null); + op.setUiError("connection", "Error connecting to websocket server", 2); + }; + + connection.onclose = function (message) + { + connecting = false; + op.log("ws close"); + outConnected.set(false); + outConnection.set(null); + }; + + connection.onopen = function (message) + { + connecting = false; + outConnected.set(true); + connectedTo = inUrl.get(); + outConnection.set(connection); + }; + + connection.onmessage = function (message) + { + op.setUiError("jsonvalid", null); + outRaw.set(message.data); + try + { + const json = JSON.parse(message.data); + outResult.set(null); + outResult.set(json); + outValidJson.set(true); + } + catch (e) + { + op.log(e); + op.log("This doesn't look like a valid JSON: ", message.data); + op.setUiError("jsonvalid", "Received message was not valid JSON", 0); + outValidJson.set(false); + } + outReceived.trigger(); + }; + } +} + + +}; + +Ops.Net.WebSocket.WebSocket_v2.prototype = new CABLES.Op(); +CABLES.OPS["e747dc72-8214-41ca-9aae-9041f20dd6ac"]={f:Ops.Net.WebSocket.WebSocket_v2,objName:"Ops.Net.WebSocket.WebSocket_v2"}; + + + + +// ************************************************************** +// +// Ops.Patch.CallBack_v2 +// +// ************************************************************** + +Ops.Patch.CallBack_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe = op.inTriggerButton("exe"); +const callbackname = op.inString("Callback Name", "myFunction"); +const val0 = op.inString("Parameter 1", ""); +const val1 = op.inString("Parameter 2", ""); +const val2 = op.inString("Parameter 3", ""); + +let values = [0, 0, 0]; + +val0.onChange = function () { values[0] = val0.get(); }; +val1.onChange = function () { values[1] = val1.get(); }; +val2.onChange = function () { values[2] = val2.get(); }; + +exe.onTriggered = function () +{ + if (op.patch.config.hasOwnProperty(callbackname.get())) + { + op.patch.config[callbackname.get()](values); + } + else + { + op.log("callback ", callbackname.get(), " not found! Parameters: ", values); + } +}; + + +}; + +Ops.Patch.CallBack_v2.prototype = new CABLES.Op(); +CABLES.OPS["cfc87cb1-a74b-482f-9fad-e1777cb7ffd4"]={f:Ops.Patch.CallBack_v2,objName:"Ops.Patch.CallBack_v2"}; + + + + +// ************************************************************** +// +// Ops.Patch.Function_v2 +// +// ************************************************************** + +Ops.Patch.Function_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + funcName = op.inString("Function Name", "default"), + triggerButton = op.inTriggerButton("Trigger"), + inString1 = op.inString("Default Parameter 1"), + inString2 = op.inString("Default Parameter 2"), + inString3 = op.inString("Default Parameter 3"), + outTrigger = op.outTrigger("Next"), + outString1 = op.outString("Parameter 1"), + outString2 = op.outString("Parameter 2"), + outString3 = op.outString("Parameter 3"); + +triggerButton.onTriggered = triggered; + +funcName.onChange = function () +{ + op.patch.config[funcName.get()] = triggered; +}; + +function triggered() +{ + const arg1 = arguments.hasOwnProperty(0) ? arguments[0] : inString1.get(); + const arg2 = arguments.hasOwnProperty(1) ? arguments[1] : inString2.get(); + const arg3 = arguments.hasOwnProperty(2) ? arguments[2] : inString3.get(); + outString1.set(arg1); + outString2.set(arg2); + outString3.set(arg3); + outTrigger.trigger(); +} + + +}; + +Ops.Patch.Function_v2.prototype = new CABLES.Op(); +CABLES.OPS["39043a11-1ae0-4568-93a7-ec1493df2662"]={f:Ops.Patch.Function_v2,objName:"Ops.Patch.Function_v2"}; + + + + +// ************************************************************** +// +// Ops.Patch.LoadingStatusTask +// +// ************************************************************** + +Ops.Patch.LoadingStatusTask = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// vars +let stack = []; +let uuid = CABLES.uuid(); + +// inputs +let startPort = op.inTriggerButton("Start Task"); +let stopPort = op.inTriggerButton("End Task"); + +// listeners +startPort.onTriggered = startTask; +stopPort.onTriggered = stopTask; + +function startTask() +{ + let id = uuid + " (" + (stack.length + 1) + ")"; + let loadingId = op.patch.loading.start("task", id); + if (CABLES.UI) + { + gui.jobs().start({ "id": loadingId, "title": "loading task " + id }); + } + + stack.push(loadingId); +} + +function stopTask() +{ + let loadingId = stack.pop(); + op.patch.loading.finished(loadingId); + if (CABLES.UI) + { + gui.jobs().finish(loadingId); + } +} + + +}; + +Ops.Patch.LoadingStatusTask.prototype = new CABLES.Op(); +CABLES.OPS["38d0f6ba-a4d8-4093-9cab-17e1b5dd52ae"]={f:Ops.Patch.LoadingStatusTask,objName:"Ops.Patch.LoadingStatusTask"}; + + + + +// ************************************************************** +// +// Ops.Patch.LoadingStatus_v2 +// +// ************************************************************** + +Ops.Patch.LoadingStatus_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + preRenderOps = op.inValueBool("PreRender Ops"), + startTimeLine = op.inBool("Play Timeline", true), + + next = op.outTrigger("Next"), + outInitialFinished = op.outBool("Finished Initial Loading", false), + outLoading = op.outBool("Loading"), + outProgress = op.outNumber("Progress"), + outList = op.outArray("Jobs"), + loadingFinished = op.outTrigger("Trigger Loading Finished "); + +const cgl = op.patch.cgl; +const patch = op.patch; + +let finishedOnce = false; +const preRenderTimes = []; +let firstTime = true; + +document.body.classList.add("cables-loading"); + +let loadingId = cgl.patch.loading.start("loadingStatusInit", "loadingStatusInit"); + +exe.onTriggered = () => +{ + const jobs = op.patch.loading.getListJobs(); + outProgress.set(patch.loading.getProgress()); + + let hasFinished = jobs.length === 0; + const notFinished = !hasFinished; + // outLoading.set(!hasFinished); + + if (notFinished) + { + outList.set(op.patch.loading.getListJobs()); + } + + if (notFinished) + { + if (firstTime) + { + if (preRenderOps.get()) op.patch.preRenderOps(); + op.patch.timer.setTime(0); + if (startTimeLine.get()) + { + op.patch.timer.play(); + } + else + { + op.patch.timer.pause(); + } + } + firstTime = false; + + document.body.classList.remove("cables-loading"); + document.body.classList.add("cables-loaded"); + } + else + { + finishedOnce = true; + outList.set(op.patch.loading.getListJobs()); + + if (patch.loading.getProgress() < 1.0) + { + op.patch.timer.setTime(0); + op.patch.timer.pause(); + } + } + + outInitialFinished.set(finishedOnce); + + if (outLoading.get() && hasFinished) loadingFinished.trigger(); + + outLoading.set(notFinished); + + next.trigger(); + + if (loadingId) + { + cgl.patch.loading.finished(loadingId); + loadingId = null; + } +}; + + +}; + +Ops.Patch.LoadingStatus_v2.prototype = new CABLES.Op(); +CABLES.OPS["e62f7f4c-7436-437e-8451-6bc3c28545f7"]={f:Ops.Patch.LoadingStatus_v2,objName:"Ops.Patch.LoadingStatus_v2"}; + + + + +// ************************************************************** +// +// Ops.Patch.PlayButton +// +// ************************************************************** + +Ops.Patch.PlayButton = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"inner_css":"\nborder-style:solid;\nborder-color:transparent transparent transparent #ccc;\nbox-sizing:border-box;\nwidth:50px;\nheight:50px;\nmargin-top:25px;\nmargin-left:36px;\nborder-width:25px 0px 25px 40px;\npointer-events:none;\n","outer_css":"width:100px;\nheight:100px;\nleft:50%;\ntop:50%;\nborder-radius:100%;\nposition:absolute;\ncursor:pointer;\nopacity:0.7;\ntransform:translate(-50%,-50%);\nz-index:999999;\nbackground-color:#333;\nborder:5px solid #333;",}; +const + inExec = op.inTrigger("Trigger"), + inIfSuspended = op.inValueBool("Only if Audio Suspended"), + inReset = op.inTriggerButton("Reset"), + inStyleOuter = op.inStringEditor("Style Outer", attachments.outer_css), + inStyleInner = op.inStringEditor("Style Inner", attachments.inner_css), + inActive = op.inBool("Active", true), + outNext = op.outTrigger("Next"), + notClickedNext = op.outTrigger("Not Clicked"), + outState = op.outString("Audiocontext State"), + outEle = op.outObject("Element"), + outClicked = op.outBoolNum("Clicked", false), + outClickedTrigger = op.outTrigger("Clicked Trigger"); + +op.toWorkPortsNeedToBeLinked(inExec); +let audioCtx = CABLES.WEBAUDIO.createAudioContext(op); + +const canvas = op.patch.cgl.canvas.parentElement; +let wasClicked = false; +let ele = null; +let elePlay = null; +createElements(); + +inStyleOuter.onChange = + inStyleInner.onChange = createElements; + +audioCtx.addEventListener("statechange", updateState); + +inActive.onChange = () => +{ + if (!inActive.get())ele.style.display = "none"; + else ele.style.display = "block"; +}; + +function createElements() +{ + if (elePlay) elePlay.remove(); + if (ele) ele.remove(); + + ele = document.createElement("div"); + ele.style = inStyleOuter.get(); + outEle.set(ele); + + canvas.appendChild(ele); + + elePlay = document.createElement("div"); + elePlay.style = inStyleInner.get(); + + ele.appendChild(elePlay); + ele.classList.add("playButton"); + + ele.addEventListener("mouseenter", hover); + ele.addEventListener("mouseleave", hoverOut); + ele.addEventListener("click", clicked); + ele.addEventListener("touchStart", clicked); + op.onDelete = removeElements; +} + +inReset.onTriggered = function () +{ + createElements(); + wasClicked = false; + outClicked.set(wasClicked); +}; + +function updateState() +{ + outState.set(audioCtx.state); + if (inIfSuspended.get() && audioCtx.state == "running") clicked(); +} + +inExec.onTriggered = function () +{ + if (wasClicked) outNext.trigger(); + else notClickedNext.trigger(); +}; + +function clicked() +{ + removeElements(); + if (audioCtx && audioCtx.state == "suspended")audioCtx.resume(); + wasClicked = true; + outClicked.set(wasClicked); + outClickedTrigger.trigger(); +} + +function removeElements() +{ + if (elePlay) elePlay.remove(); + if (ele) ele.remove(); +} + +function hoverOut() +{ + if (ele) ele.style.opacity = 0.7; +} + +function hover() +{ + if (ele) ele.style.opacity = 1.0; +} + + +}; + +Ops.Patch.PlayButton.prototype = new CABLES.Op(); +CABLES.OPS["32e53fa2-4545-4c53-a94d-2204aa079246"]={f:Ops.Patch.PlayButton,objName:"Ops.Patch.PlayButton"}; + + + + +// ************************************************************** +// +// Ops.Physics.Ammo.AmmoBody +// +// ************************************************************** + +Ops.Physics.Ammo.AmmoBody = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// https://github.com/enable3d/enable3d/blob/master/packages/ammoPhysics/src/three-to-ammo.js + +const + inExec = op.inTrigger("Update"), + inName = op.inString("Name", ""), + inMass = op.inFloat("Mass", 0), + inFriction = op.inFloat("Friction", 0.5), + inRollingFriction = op.inFloat("Rolling Friction", 0.5), + inRestitution = op.inFloat("Restitution", 0.5), + + inShape = op.inDropDown("Shape", ["Box", "Sphere", "Cylinder", "Capsule", "Cone", "Geom Convex Hull", "Triangle Shape"], "Box"), + inGeom = op.inObject("Geometry", null, "geometry"), + inGeomSimplify = op.inInt("Simplify Max Triangles", 50), + inRadius = op.inFloat("Radius", 0.5), + inSizeX = op.inFloat("Size X", 1), + inSizeY = op.inFloat("Size Y", 1), + inSizeZ = op.inFloat("Size Z", 1), + + inPositions = op.inArray("Positions", null, 3), + inPosIndex = op.inBool("Append Index to name", true), + + inNeverDeactivate = op.inBool("Never Deactivate"), + inGhostObject = op.inBool("Ghost Object"), + inActive = op.inBool("Active", true), + inReset = op.inTriggerButton("Reset"), + inActivate = op.inTriggerButton("Activate"), + + next = op.outTrigger("next"), + outRayHit = op.outBoolNum("Ray Hit"), + transformed = op.outTrigger("Transformed"); + +op.setPortGroup("Array", [inPositions, inPosIndex]); + +inExec.onTriggered = update; + +const cgl = op.patch.cgl; +let bodies = []; +let world = null; +let tmpTrans = null; + +const tmpOrigin = vec3.create(); +const tmpQuat = quat.create(); +const tmpScale = vec3.create(); +let transMat = mat4.create(); + +let btOrigin = null; +let btQuat = null; +let doResetPos = false; +let colShape = null; + +let doScale = true; +let needsRemove = false; +inName.onChange = updateBodyMeta; + +op.setPortGroup("Parameters", [inRestitution, inFriction, inRollingFriction, inMass]); +op.setPortGroup("Shape", [inShape, inGeom, inGeomSimplify, inRadius, inSizeY, inSizeX, inSizeZ]); +op.setPortGroup("Flags", [inNeverDeactivate, inActive, inGhostObject]); + +inExec.onLinkChanged = + inFriction.onChange = + inRestitution.onChange = + inRollingFriction.onChange = + inGeomSimplify.onChange = + inGhostObject.onChange = + inGeom.onChange = + inShape.onChange = + inMass.onChange = + inRadius.onChange = + inSizeY.onChange = + inSizeZ.onChange = + inPositions.onChange = + inSizeX.onChange = () => + { + needsRemove = true; + }; + +inPosIndex.onChange = updateBodyMeta; +op.onDelete = removeBody; + +inActive.onChange = () => +{ + if (!inActive.get()) removeBody(); +}; + +inActivate.onTriggered = () => +{ + for (let i = 0; i < bodies.length; i++) + bodies[i].activate(); +}; + +function removeBody() +{ + if (world) + { + for (let i = 0; i < bodies.length; i++) + world.removeRigidBody(bodies[i]); + } + + bodies.length = 0; +} + +inReset.onTriggered = () => +{ + needsRemove = true; +}; + +function updateBodyMeta() +{ + const n = inName.get(); + const appendIndex = inPosIndex.get(); + const posArr = inPositions.get(); + + if (world) + for (let i = 0; i < bodies.length; i++) + { + let name = n; + if (appendIndex && posArr)name = n + "." + i; + + world.setBodyMeta(bodies[i], + { + "name": name, + "mass": inMass.get(), + }); + } + + op.setUiAttribs({ "extendTitle": inName.get() }); +} + +function setup() +{ + if (!inActive.get()) return; + doScale = true; + + removeBody(); + + if (!tmpTrans)tmpTrans = new Ammo.btTransform(); + // if (!transform)transform = new Ammo.btTransform(); + + if (colShape)Ammo.destroy(colShape); + colShape = null; + // transform.setIdentity(); + // CABLES.AmmoWorld.copyCglTransform(cgl, transform); + + op.setUiError("nogeom", null); + if (inShape.get() == "Box") colShape = new Ammo.btBoxShape(new Ammo.btVector3(inSizeX.get() / 2, inSizeY.get() / 2, inSizeZ.get() / 2)); + else if (inShape.get() == "Sphere") colShape = new Ammo.btSphereShape(inRadius.get()); + else if (inShape.get() == "Cylinder") colShape = new Ammo.btCylinderShape(new Ammo.btVector3(inSizeX.get() / 2, inSizeY.get() / 2, inSizeZ.get() / 2)); + else if (inShape.get() == "Capsule") colShape = new Ammo.btCapsuleShape(inRadius.get(), inSizeY.get()); + else if (inShape.get() == "Cone") colShape = new Ammo.btConeShape(inRadius.get(), inSizeY.get()); + else if (inShape.get() == "Triangle Shape") + { + const geom = inGeom.get(); + if (!geom || !inGeom.isLinked()) + { + op.setUiError("nogeom", "Shape needs geometry connected"); + return; + } + else op.setUiError("nogeom", null); + if (!geom) return; + + let mesh = new Ammo.btTriangleMesh(true, true); + + for (let i = 0; i < geom.verticesIndices.length / 3; i++) + { + mesh.addTriangle( + new Ammo.btVector3( + geom.vertices[geom.verticesIndices[i * 3] * 3 + 0], + geom.vertices[geom.verticesIndices[i * 3] * 3 + 1], + geom.vertices[geom.verticesIndices[i * 3] * 3 + 2] + ), + new Ammo.btVector3( + geom.vertices[geom.verticesIndices[i * 3 + 1] * 3 + 0], + geom.vertices[geom.verticesIndices[i * 3 + 1] * 3 + 1], + geom.vertices[geom.verticesIndices[i * 3 + 1] * 3 + 2] + ), + new Ammo.btVector3( + geom.vertices[geom.verticesIndices[i * 3 + 2] * 3 + 0], + geom.vertices[geom.verticesIndices[i * 3 + 2] * 3 + 1], + geom.vertices[geom.verticesIndices[i * 3 + 2] * 3 + 2] + ), + false); + } + + colShape = new Ammo.btBvhTriangleMeshShape(mesh, true, true); + } + else if (inShape.get() == "Geom Convex Hull") + { + const geom = inGeom.get(); + if (!geom || !inGeom.isLinked()) + { + op.setUiError("nogeom", "Shape needs geometry connected"); + return; + } + else op.setUiError("nogeom", null); + if (!geom) return; + + colShape = CABLES.AmmoWorld.createConvexHullFromGeom(geom, inGeomSimplify.get()); + + doScale = false; + } + else + { + inGeomSimplify.setUiAttribs({ "greyout": true }); + op.log("unknown shape type", inShape.get()); + return; + } + + if (inShape.get() == "Geom Convex Hull") + { + inRadius.setUiAttribs({ "greyout": true }); + inSizeX.setUiAttribs({ "greyout": true }); + inSizeY.setUiAttribs({ "greyout": true }); + inSizeZ.setUiAttribs({ "greyout": true }); + inGeomSimplify.setUiAttribs({ "greyout": false }); + } + else + { + inSizeX.setUiAttribs({ "greyout": inShape.get() == "Sphere" || inShape.get() == "Capsule" || inShape.get() == "Cone" }); + inSizeY.setUiAttribs({ "greyout": inShape.get() == "Sphere" }); + inSizeZ.setUiAttribs({ "greyout": inShape.get() == "Sphere" || inShape.get() == "Capsule" || inShape.get() == "Cone" }); + inRadius.setUiAttribs({ "greyout": inShape.get() == "Box" }); + } + + colShape.setMargin(0.05); + + let mass = inMass.get(); + let localInertia = new Ammo.btVector3(0, 0, 0); + colShape.calculateLocalInertia(mass, localInertia); + + let num = 1; + let posArr = null; + if (inPositions.isLinked()) + { + num = 0; + posArr = inPositions.get(); + + if (posArr && posArr.length) + { + num = Math.max(num, posArr.length / 3); + } + } + + for (let i = 0; i < num; i++) + { + let transform = new Ammo.btTransform(); + + const motionState = new Ammo.btDefaultMotionState(transform); + + let rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, colShape, localInertia); + const body = new Ammo.btRigidBody(rbInfo); + world.addRigidBody(body); + + // CF_STATIC_OBJECT= 1, + // CF_KINEMATIC_OBJECT= 2, + // CF_NO_CONTACT_RESPONSE = 4, + // CF_CUSTOM_MATERIAL_CALLBACK = 8,//this allows per-triangle material (friction/restitution) + // CF_CHARACTER_OBJECT = 16, + // CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing + // CF_DISABLE_SPU_COLLISION_PROCESSING = 64//disable parallel/SPU processing + if (inGhostObject.get()) + body.setCollisionFlags(body.getCollisionFlags() | 4); + + bodies.push(body); + // motionStates.push(motionState); + } + setPositions(); + + world.on("rayCastHit", (name) => + { + outRayHit.set(name == inName.get()); + }); + + updateParams(); + updateBodyMeta(); +} + +function setPositions() +{ + let posArr = inPositions.get(); + + for (let i = 0; i < bodies.length; i++) + { + bodies[i].getMotionState().getWorldTransform(tmpTrans); + + if (posArr) + { + cgl.pushModelMatrix(); + + mat4.translate(cgl.mMatrix, cgl.mMatrix, [ + posArr[i * 3 + 0], posArr[i * 3 + 1], posArr[i * 3 + 2]]); + } + CABLES.AmmoWorld.copyCglTransform(cgl, tmpTrans); + if (posArr)cgl.popModelMatrix(); + + bodies[i].getMotionState().setWorldTransform(tmpTrans); + bodies[i].setWorldTransform(tmpTrans); + } +} + +function updateParams() +{ + if (!world || bodies.length == 0) return; + for (let i = 0; i < bodies.length; i++) + { + bodies[i].setFriction(inFriction.get()); + bodies[i].setRollingFriction(inRollingFriction.get()); + bodies[i].setRestitution(inRestitution.get()); + } +} + +function renderTransformed() +{ + if (!bodies.length) return; + if (!inActive.get()) return; + + ping(); + + if (transformed.isLinked()) + for (let i = 0; i < bodies.length; i++) + { + const body = bodies[i]; + let ms = body.getMotionState(); + if (ms) + { + ms.getWorldTransform(tmpTrans); + let p = tmpTrans.getOrigin(); + let q = tmpTrans.getRotation(); + + cgl.pushModelMatrix(); + + mat4.identity(cgl.mMatrix); + + let scale = [inSizeX.get(), inSizeY.get(), inSizeZ.get()]; + + if (inShape.get() == "Sphere") scale = [inRadius.get() * 2, inRadius.get() * 2, inRadius.get() * 2]; + if (inShape.get() == "Cone") scale = [inRadius.get() * 2, inSizeY.get(), inRadius.get() * 2]; + // if (inShape.get() == "Cylinder") scale = [inRadius.get() * 2, inSizeY.get(), inRadius.get() * 2]; + if (inShape.get() == "Capsule") scale = [inRadius.get() * 2, inSizeY.get() * 2, inRadius.get() * 2]; + + mat4.fromRotationTranslationScale(transMat, [q.x(), q.y(), q.z(), q.w()], [p.x(), p.y(), p.z()], scale); + mat4.mul(cgl.mMatrix, cgl.mMatrix, transMat); + + transformed.trigger(); + + cgl.popModelMatrix(); + } + } +} + +function ping() +{ + if (world) + for (let i = 0; i < bodies.length; i++) + world.pingBody(bodies[i]); +} + +function update() +{ + if (world && bodies.length && bodies[0] && world.getBodyMeta(bodies[0]) == undefined)removeBody(); + if (needsRemove) + { + removeBody(); + needsRemove = false; + } + if (world != cgl.frameStore.ammoWorld) removeBody(); + + world = cgl.frameStore.ammoWorld; + if (!world) + { + outRayHit.set(false); + return; + } + if (!bodies.length) setup(world); + if (!bodies.length) return; + if (bodies[0] && inNeverDeactivate.get()) bodies[0].activate(); // body.setActivationState(Ammo.DISABLE_DEACTIVATION); did not work..... + + if (inMass.get() == 0 || doResetPos) + { + setPositions(); + doResetPos = false; + } + + renderTransformed(); + + next.trigger(); +} + + +}; + +Ops.Physics.Ammo.AmmoBody.prototype = new CABLES.Op(); +CABLES.OPS["d9c57405-9cc0-475f-b81d-21401a7ab326"]={f:Ops.Physics.Ammo.AmmoBody,objName:"Ops.Physics.Ammo.AmmoBody"}; + + + + +// ************************************************************** +// +// Ops.Physics.Ammo.AmmoBodyCollision +// +// ************************************************************** + +Ops.Physics.Ammo.AmmoBodyCollision = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("update"), + inName0 = op.inString("Name 1", ""), + inName0Match = op.inSwitch("Match Name 1", ["exact", "start", "contain"], "exact"), + inName1 = op.inString("Name 2", ""), + inName1Match = op.inSwitch("Match Name 2", ["exact", "start", "contain"], "exact"), + next = op.outTrigger("Next"), + outColliding = op.outBoolNum("Colliding"), + outNumCollisions = op.outNumber("Num Collisions"), + outCollisions = op.outArray("Collisions"); + +let oldWorld = null; + +exec.onTriggered = () => +{ + const ammoWorld = op.patch.cgl.frameStore.ammoWorld; + if (!ammoWorld) return; + + if (oldWorld != ammoWorld) + { + oldWorld = ammoWorld; + } + const match0 = inName0Match.get(); + const match1 = inName1Match.get(); + const name0 = inName0.get(); + const name1 = inName1.get(); + + let filterFunc = (col) => + { + let isColliding = false; + let found = false; + let otherName = "name1"; + if (match0 === "exact") + { + if (col.name0 === name0) + { + found = true; + } + else if (col.name1 === name0) + { + found = true; + otherName = "name0"; + } + } + else if (match0 === "start") + { + if (col.name0.startsWith(name0)) + { + found = true; + } + else if (col.name1.startsWith(name0)) + { + found = true; + otherName = "name0"; + } + } + else if (match0 === "contain") + { + if (col.name0.includes(inName0.get())) + { + found = true; + } + else if (col.name1.includes(inName0.get())) + { + found = true; + otherName = "name0"; + } + } + if (found) + { + if (name1) + { + if (match1 === "exact") + { + if (col[otherName] === name1) isColliding = true; + } + else if (match1 === "start") + { + if (col[otherName].startsWith(name1)) isColliding = true; + } + else if (match1 === "contain") + { + if (col[otherName].includes(name1)) isColliding = true; + } + } + else + { + isColliding = true; + } + } + return isColliding; + }; + + const allCols = ammoWorld.getCollisions(); + const cols = allCols.filter(filterFunc); + outCollisions.set(cols); + outNumCollisions.set(cols.length); + outColliding.set(cols.length > 0); + + next.trigger(); +}; + + +}; + +Ops.Physics.Ammo.AmmoBodyCollision.prototype = new CABLES.Op(); +CABLES.OPS["6fd02be3-0c73-4fbd-88a1-d60313ad5622"]={f:Ops.Physics.Ammo.AmmoBodyCollision,objName:"Ops.Physics.Ammo.AmmoBodyCollision"}; + + + + +// ************************************************************** +// +// Ops.Physics.Ammo.AmmoCharacter +// +// ************************************************************** + +Ops.Physics.Ammo.AmmoCharacter = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Update"), + inRadius = op.inFloat("Radius", 1), + inStyle = op.inSwitch("View", ["3rd Person", "1st Person"], "3rd Person"), + // inSizeX = op.inFloat("Size X", 1), + inSizeY = op.inFloat("Height", 2.04), + // inSizeZ = op.inFloat("Size Z", 1), + inMass = op.inFloat("Mass", 0), + inName = op.inString("Name", ""), + inActivate = op.inTriggerButton("Activate"), + + inMoveXP = op.inBool("Move X+", false), + inMoveXM = op.inBool("Move X-", false), + inMoveYP = op.inBool("Move Y+", false), + inMoveYM = op.inBool("Move Y-", false), + inMoveZP = op.inBool("Move Z+", false), + inMoveZM = op.inBool("Move Z-", false), + + inDirX = op.inFloat("Dir X"), + inDirY = op.inFloat("Dir Y"), + inDirZ = op.inFloat("Dir Z"), + + inResetX = op.inFloat("Set Pos X"), + inResetY = op.inFloat("Set Pos Y"), + inResetZ = op.inFloat("Set Pos Z"), + // inSetPos = op.inTriggerButton("Set Pos"), + inReset = op.inTriggerButton("Reset"), + + inSpeed = op.inFloat("Speed", 1), + inFallVelocity = op.inFloat("Add Velocity Y", 0.5), + + next = op.outTrigger("next"), + outX = op.outNumber("Position X"), + outY = op.outNumber("Position Y"), + outZ = op.outNumber("Position Z"), + transformed = op.outTrigger("Transformed"); + +inExec.onTriggered = update; + +op.setPortGroup("Reset", [inResetX, inResetY, inResetZ, inReset]); + +const cgl = op.patch.cgl; +let body = null; +let world = null; +let tmpTrans = null; +let transform = null; +let motionState = null; +const tmpOrigin = vec3.create(); +const tmpQuat = quat.create(); +const tmpScale = vec3.create(); +let transMat = mat4.create(); + +let forceQuat = null; +let initX = 0, initY = 0, initZ = 0; + +let btOrigin = null; +let btQuat = null; +let doResetPos = false; + +inName.onChange = updateBodyMeta; + +op.onDelete = + inMass.onChange = + inRadius.onChange = + inSizeY.onChange = () => + { + removeBody(); + }; + +inActivate.onTriggered = () => +{ + if (body)body.activate(); +}; + +function removeBody() +{ + if (world && body) world.removeRigidBody(body); + body = null; +} + +inReset.onTriggered = () => +{ + initX = inResetX.get(); + initY = inResetY.get(); + initZ = inResetZ.get(); + + removeBody(); +}; + +let btVelocity = null; + +function updateBodyMeta() +{ + if (world) + world.setBodyMeta(body, + { + "name": inName.get(), + "mass": inMass.get(), + }); + + op.setUiAttribs({ "extendTitle": inName.get() }); +} + +function setup() +{ + if (world && body) world.removeRigidBody(body); + + tmpTrans = new Ammo.btTransform(); + transform = new Ammo.btTransform(); + + transform.setIdentity(); + + copyCglTransform(transform); + + motionState = new Ammo.btDefaultMotionState(transform); + + let colShape = new Ammo.btCapsuleShape(inRadius.get(), inSizeY.get() - inRadius.get()); + + colShape.setMargin(0.05); + + let localInertia = new Ammo.btVector3(0, 0, 0); + colShape.calculateLocalInertia(inMass.get(), localInertia); + + let rbInfo = new Ammo.btRigidBodyConstructionInfo(inMass.get(), motionState, colShape, localInertia); + body = new Ammo.btRigidBody(rbInfo); + // body.setDamping(0.7, 0.01); + + world.addRigidBody(body); + + updateBodyMeta(); +} + +function renderTransformed() +{ + let ms = body.getMotionState(); + if (ms) + { + ms.getWorldTransform(tmpTrans); + let p = tmpTrans.getOrigin(); + let q = tmpTrans.getRotation(); + + if (inStyle.get() == "3rd Person") + q.setValue(tmpQuat[0], tmpQuat[1], tmpQuat[2], tmpQuat[3]); + + cgl.pushModelMatrix(); + + mat4.identity(cgl.mMatrix); + + let scale = [inRadius.get(), inRadius.get(), inRadius.get()]; + + mat4.fromRotationTranslationScale(transMat, [q.x(), q.y(), q.z(), q.w()], [ + p.x(), p.y(), p.z()], scale); + mat4.mul(cgl.mMatrix, cgl.mMatrix, transMat); + + transformed.trigger(); + + cgl.popModelMatrix(); + } +} + +function copyCglTransform(transform) +{ + if (!btOrigin) + { + btOrigin = new Ammo.btVector3(0, 0, 0); + btQuat = new Ammo.btQuaternion(0, 0, 0, 0); + } + mat4.getTranslation(tmpOrigin, cgl.mMatrix); + mat4.getRotation(tmpQuat, cgl.mMatrix); + + let changed = false; + + btOrigin.setValue(tmpOrigin[0], tmpOrigin[1], tmpOrigin[2]); + btOrigin = new Ammo.btVector3(initX, initY, initZ); + btQuat.setValue(tmpQuat[0], tmpQuat[1], tmpQuat[2], tmpQuat[3]); + + transform.setOrigin(btOrigin); + transform.setRotation(btQuat); +} + +function update() +{ + if (world != cgl.frameStore.ammoWorld) removeBody(); + + world = cgl.frameStore.ammoWorld; + if (!world) return; + if (!body) setup(world); + if (!body) return; + body.activate(); // body.setActivationState(Ammo.DISABLE_DEACTIVATION); did not work..... + + if (!btVelocity) + { + btVelocity = new Ammo.btVector3(0, 0, 0); + } + + let vx = 0, vy = 0, vz = 0.0; + let speed = inSpeed.get(); + + let doMove = false; + if (inMoveZP.get()) + { + vx = inDirX.get() * speed; + vy = inDirY.get() * speed; + vz = inDirZ.get() * speed; + doMove = true; + } + if (inMoveZM.get()) + { + vx = -inDirX.get() * speed; + vy = -inDirY.get() * speed; + vz = -inDirZ.get() * speed; + doMove = true; + } + + if (inMoveXP.get()) + { + vx = -inDirZ.get() * speed; + vy = inDirY.get() * speed; + vz = inDirX.get() * speed; + doMove = true; + } + if (inMoveXM.get()) + { + vx = inDirZ.get() * speed; + vy = inDirY.get() * speed; + vz = -inDirX.get() * speed; + doMove = true; + } + + if (inMoveYP.get()) vy = 3; + else vy = 0; + + doMove = true; + + if (doMove) + { + btVelocity.setValue(vx, vy - inFallVelocity.get(), vz); + body.setLinearVelocity(btVelocity); + } + + if (inMass.get() == 0 || doResetPos) + { + copyCglTransform(transform); + motionState.setWorldTransform(transform); + + body.setWorldTransform(transform); + + doResetPos = false; + } + + motionState.getWorldTransform(transform); + + // force upright position + if (!forceQuat) forceQuat = new Ammo.btQuaternion(); + forceQuat.setEulerZYX(0, 90, 0); + transform.setRotation(forceQuat); + body.setWorldTransform(transform); + let p = tmpTrans.getOrigin(); + + outX.set(p.x()); + outY.set(p.y()); + outZ.set(p.z()); + + renderTransformed(); + + next.trigger(); +} + + +}; + +Ops.Physics.Ammo.AmmoCharacter.prototype = new CABLES.Op(); +CABLES.OPS["5f6c2a84-8de9-41e5-948a-d9c5ed49022f"]={f:Ops.Physics.Ammo.AmmoCharacter,objName:"Ops.Physics.Ammo.AmmoCharacter"}; + + + + +// ************************************************************** +// +// Ops.Physics.Ammo.AmmoCharacterFpsCamera +// +// ************************************************************** + +Ops.Physics.Ammo.AmmoCharacterFpsCamera = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + enablePointerLock = op.inBool("Enable pointer lock", true), + trigger = op.outTrigger("trigger"), + isLocked = op.outBoolNum("isLocked", false), + inHeight = op.inFloat("Height", 2), + inName = op.inString("Character Name", "player1"), + mouseSpeed = op.inFloat("Mouse Speed", 1), + inActive = op.inBool("Active", true), + outMouseDown = op.outTrigger("Mouse Left"), + outMouseDownRight = op.outTrigger("Mouse Right"), + outDirX = op.outNumber("Dir X"), + outDirY = op.outNumber("Dir Y"), + outDirZ = op.outNumber("Dir Z"), + outRotX = op.outNumber("Rot X"), + outRotY = op.outNumber("Rot Y"); + +op.toWorkPortsNeedToBeLinked(render); + +const cgl = op.patch.cgl; +const viewMatrix = mat4.create(); +const vPos = vec3.create(); +let speedx = 0, speedy = 0, speedz = 0; +const movementSpeedFactor = 0.5; +const canvas = document.getElementById("glcanvas"); +const DEG2RAD = 3.14159 / 180.0; +let rotX = 0; +let rotY = 0; +let lastMove = 0; +let mouseNoPL = { "firstMove": true, + "deltaX": 0, + "deltaY": 0, +}; + +initListener(); + +enablePointerLock.onChange = initListener; + +inActive.onChange = () => +{ + document.exitPointerLock(); + removeListener(); + + lockChangeCallback(); + + if (inActive.get()) initListener(); +}; + +let tmpTrans = null; + +render.onTriggered = function () +{ + if (!Ammo) return; + if (!inActive.get()) return trigger.trigger(); + if (!tmpTrans) tmpTrans = new Ammo.btTransform(); + + if (cgl.frameStore.shadowPass) return trigger.trigger(); + + cgl.pushViewMatrix(); + + const ammoWorld = cgl.frameStore.ammoWorld; + + if (!ammoWorld) + { + op.log("char no ammoworld"); + return; + } + + const body = ammoWorld.getBodyByName(inName.get()); + + if (body) + { + let ms = body.getMotionState(); + ms.getWorldTransform(tmpTrans); + let p = tmpTrans.getOrigin(); + vec3.set(vPos, -p.x(), -p.y() - inHeight.get(), -p.z()); + } + else + { + op.log("char body not found!"); + } + + if (rotX < -90)rotX = -90; + if (rotX > 90)rotX = 90; + + mat4.identity(cgl.vMatrix); + + mat4.rotateX(cgl.vMatrix, cgl.vMatrix, DEG2RAD * rotX); + mat4.rotateY(cgl.vMatrix, cgl.vMatrix, DEG2RAD * rotY); + + mat4.translate(cgl.vMatrix, cgl.vMatrix, vPos); + + trigger.trigger(); + cgl.popViewMatrix(); + + outRotX.set(rotX); + outRotY.set(rotY); + + // for dir vec + mat4.identity(viewMatrix); + mat4.rotateX(viewMatrix, viewMatrix, DEG2RAD * rotX); + mat4.rotateY(viewMatrix, viewMatrix, DEG2RAD * rotY); + mat4.transpose(viewMatrix, viewMatrix); + + const dir = vec4.create(); + vec4.transformMat4(dir, [0, 0, 1, 1], viewMatrix); + + vec4.normalize(dir, dir); + outDirX.set(-dir[0]); + outDirY.set(-dir[1]); + outDirZ.set(-dir[2]); +}; + +function moveCallback(e) +{ + const mouseSensitivity = 0.1; + rotX += e.movementY * mouseSensitivity * mouseSpeed.get(); + rotY += e.movementX * mouseSensitivity * mouseSpeed.get(); + + if (rotX < -90.0) rotX = -90.0; + if (rotX > 90.0) rotX = 90.0; + if (rotY < -180.0) rotY += 360.0; + if (rotY > 180.0) rotY -= 360.0; +} + +function mouseDown(e) +{ + if (e.which == 3) outMouseDownRight.trigger(); + else outMouseDown.trigger(); +} + +function lockChangeCallback(e) +{ + if (document.pointerLockElement === canvas || + document.mozPointerLockElement === canvas || + document.webkitPointerLockElement === canvas) + { + document.addEventListener("pointerdown", mouseDown, false); + document.addEventListener("pointermove", moveCallback, false); + isLocked.set(true); + } + else + { + document.removeEventListener("pointerdown", mouseDown, false); + document.removeEventListener("pointermove", moveCallback, false); + isLocked.set(false); + } +} + +function startPointerLock(e) +{ + const test = false; + + if (render.isLinked() && enablePointerLock.get() && e.buttons == 1) + { + document.addEventListener("pointermove", moveCallback, false); + canvas.requestPointerLock = canvas.requestPointerLock || + canvas.mozRequestPointerLock || + canvas.webkitRequestPointerLock; + canvas.requestPointerLock(); + } +} + +function removeListener() +{ + cgl.canvas.removeEventListener("pointermove", moveCallbackNoPL, false); + cgl.canvas.removeEventListener("pointerup", upCallbackNoPL, false); + + document.removeEventListener("pointerlockchange", lockChangeCallback, false); + document.removeEventListener("mozpointerlockchange", lockChangeCallback, false); + document.removeEventListener("webkitpointerlockchange", lockChangeCallback, false); + document.getElementById("glcanvas").removeEventListener("mousedown", startPointerLock); +} + +function initListener() +{ + if (enablePointerLock.get()) + { + document.addEventListener("pointerlockchange", lockChangeCallback, false); + document.addEventListener("mozpointerlockchange", lockChangeCallback, false); + document.addEventListener("webkitpointerlockchange", lockChangeCallback, false); + document.getElementById("glcanvas").addEventListener("mousedown", startPointerLock); + + cgl.canvas.removeEventListener("pointermove", moveCallbackNoPL, false); + cgl.canvas.removeEventListener("pointerup", upCallbackNoPL, false); + } + else + { + cgl.canvas.addEventListener("pointermove", moveCallbackNoPL, false); + cgl.canvas.addEventListener("pointerup", upCallbackNoPL, false); + } +} + +function upCallbackNoPL(e) +{ + try { cgl.canvas.releasePointerCapture(e.pointerId); } + catch (e) {} + mouseNoPL.firstMove = true; +} + +function moveCallbackNoPL(e) +{ + if (e && e.buttons == 1) + { + try { cgl.canvas.setPointerCapture(e.pointerId); } + catch (_e) {} + + if (!mouseNoPL.firstMove) + { + const deltaX = (e.clientX - mouseNoPL.lastX) * mouseSpeed.get() * 0.5; + const deltaY = (e.clientY - mouseNoPL.lastY) * mouseSpeed.get() * 0.5; + + rotX += deltaY; + rotY += deltaX; + } + + mouseNoPL.firstMove = false; + mouseNoPL.lastX = e.clientX; + mouseNoPL.lastY = e.clientY; + } +} + + +}; + +Ops.Physics.Ammo.AmmoCharacterFpsCamera.prototype = new CABLES.Op(); +CABLES.OPS["0dca47aa-09e4-4b5d-b0d8-22390a950293"]={f:Ops.Physics.Ammo.AmmoCharacterFpsCamera,objName:"Ops.Physics.Ammo.AmmoCharacterFpsCamera"}; + + + + +// ************************************************************** +// +// Ops.Physics.Ammo.AmmoDebugRenderer +// +// ************************************************************** + +Ops.Physics.Ammo.AmmoDebugRenderer = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inRender = op.inTrigger("Render"), + inDrawWireframe = op.inBool("Draw Wireframe", true), + inDrawAABB = op.inBool("Draw AABB", false), + inDrawContacts = op.inBool("Draw Contact Points", true), + inIgnClear = op.inBool("Depth", true), + + inActive = op.inBool("Active", true), + + outNext = op.outTrigger("Next"); + +op.setPortGroup("Options", [inDrawContacts, inDrawWireframe, inDrawAABB, inIgnClear]); + +const cgl = op.patch.cgl; + +let debugDrawer = null; +let oldWorld = null; + +inRender.onTriggered = () => +{ + if (cgl.frameStore.shadowPass) return outNext.trigger(); + + const ammoWorld = cgl.frameStore.ammoWorld; + if (!ammoWorld) return; + + if (!debugDrawer || oldWorld != ammoWorld.world) + { + debugDrawer = new CABLES.AmmoDebugDrawer(ammoWorld.world, { }); + debugDrawer.enable(); + oldWorld = ammoWorld.world; + } + + if (!inActive.get()) + { + outNext.trigger(); + return; + } + + if (!ammoWorld) return; + + let debugmode = 0; + if (inDrawWireframe.get())debugmode |= 1; + if (inDrawAABB.get())debugmode |= 2; + if (inDrawContacts.get())debugmode |= 8; + + outNext.trigger(); + + debugmode |= 16384; + + if (debugmode) + { + cgl.pushModelMatrix(); + cgl.pushDepthTest(inIgnClear.get()); + cgl.pushDepthWrite(inIgnClear.get()); + + mat4.identity(cgl.mMatrix); + + debugDrawer.setDebugMode(debugmode); + debugDrawer.update(); + debugDrawer.render(cgl); + // outPoints.set(debugDrawer.verts); + + cgl.popDepthTest(); + cgl.popDepthWrite(); + cgl.popModelMatrix(); + } +}; + + +}; + +Ops.Physics.Ammo.AmmoDebugRenderer.prototype = new CABLES.Op(); +CABLES.OPS["e4b4f6c9-483b-486e-abbc-fbc4254a65d1"]={f:Ops.Physics.Ammo.AmmoDebugRenderer,objName:"Ops.Physics.Ammo.AmmoDebugRenderer"}; + + + + +// ************************************************************** +// +// Ops.Physics.Ammo.AmmoEmitter +// +// ************************************************************** + +Ops.Physics.Ammo.AmmoEmitter = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Exec"), + inLimit = op.inInt("Limit Bodies", 10), + + inRadius = op.inFloat("Radius", 1), + inMass = op.inFloat("Mass", 1), + inNameIndex = op.inBool("Add index to name", true), + + inName = op.inString("Name", "emitterBody"), + + inFriction = op.inFloat("Friction", 0.5), + inRollingFriction = op.inFloat("Rolling Friction", 0.5), + inRestitution = op.inFloat("Restitution", 0.5), + + inDirX = op.inFloat("Dir X"), + inDirY = op.inFloat("Dir Y"), + inDirZ = op.inFloat("Dir Z"), + inSpeed = op.inFloat("Speed"), + + inSpawn = op.inTriggerButton("Spawn One"), + inRemove = op.inTriggerButton("Remove All"), + inActivate = op.inTriggerButton("Activate All"), + inRemoveFalling = op.inBool("Remove Y<-100", true), + // inLifeTime=op.inFloat("Lifetime",0), + + next = op.outTrigger("Next"), + outNum = op.outNumber("Total Bodies"), + outPos = op.outArray("Positions", 3), + outRot = op.outArray("Rotations Quats", 4); + +let shouldspawnOne = false; +inSpawn.onTriggered = () => { shouldspawnOne = true; }; + +const bodies = []; +const cgl = op.patch.cgl; + +let countAll = 0; +let world = null; +let tmpTrans = null; +let btVelocity = null; + +inRemove.onTriggered = removeAll; + +inExec.onLinkChanged = +inNameIndex.onChange = + op.onDelete = removeAll; + +inName.onChange = () => { op.setUiAttribs({ "extendTitle": inName.get() }); }; + +function removeAll() +{ + for (let i = 0; i < bodies.length; i++) + { + world.removeRigidBody(bodies[i].body); + } + + outPos.set(null); + outRot.set(null); + + bodies.length = 0; +} + +inActivate.onTriggered = () => +{ + for (let i = 0; i < bodies.length; i++) bodies[i].body.activate(); +}; + +function setArrayTransformed(body, i, arrPos) +{ + if (!body) return; + let ms = body.ms; + if (ms) + { + ms.getWorldTransform(tmpTrans); + let p = tmpTrans.getOrigin(); + let q = tmpTrans.getRotation(); + + // cgl.pushModelMatrix(); + + // mat4.identity(cgl.mMatrix); + + // let scale = [inSizeX.get(), inSizeY.get(), inSizeZ.get()]; + + // if (inShape.get() == "Sphere") scale = [inRadius.get() * 2, inRadius.get() * 2, inRadius.get() * 2]; + // if (inShape.get() == "Cone") scale = [inRadius.get() * 2, inSizeY.get(), inRadius.get() * 2]; + // if (inShape.get() == "Cylinder") scale = [inRadius.get() * 2, inSizeY.get(), inRadius.get() * 2]; + // if (inShape.get() == "Capsule") scale = [inRadius.get() * 2, inSizeY.get() * 2, inRadius.get() * 2]; + + arrPos[i * 3] = p.x(); + arrPos[i * 3 + 1] = p.y(); + arrPos[i * 3 + 2] = p.z(); + + arrRot[i * 4] = q.x(); + arrRot[i * 4 + 1] = q.y(); + arrRot[i * 4 + 2] = q.z(); + arrRot[i * 4 + 3] = q.w(); + + // mat4.fromRotationTranslationScale(transMat, [q.x(), q.y(), q.z(), q.w()], [p.x(), p.y(), p.z()], scale); + // mat4.mul(cgl.mMatrix, cgl.mMatrix, transMat); + + // transformed.trigger(); + + // cgl.popModelMatrix(); + } +} + +function spawn() +{ + if (!world) return; + if (!tmpTrans) tmpTrans = new Ammo.btTransform(); + + let transform = null; + let colShape = new Ammo.btSphereShape(inRadius.get()); + + colShape.setMargin(0.05); + + let localInertia = new Ammo.btVector3(0, 0, 0); + colShape.calculateLocalInertia(inMass.get(), localInertia); + + transform = new Ammo.btTransform(); + transform.setIdentity(); + + CABLES.AmmoWorld.copyCglTransform(cgl, transform); + + let motionState = new Ammo.btDefaultMotionState(transform); + + let rbInfo = new Ammo.btRigidBodyConstructionInfo(inMass.get(), motionState, colShape, localInertia); + let body = new Ammo.btRigidBody(rbInfo); + + body.setFriction(inFriction.get()); + body.setRollingFriction(inRollingFriction.get()); + body.setRestitution(inRestitution.get()); + + let speed = inSpeed.get(); + let vx = inDirX.get() * speed; + let vy = inDirY.get() * speed; + let vz = inDirZ.get() * speed; + + if (!btVelocity) btVelocity = new Ammo.btVector3(0, 0, 0); + + btVelocity.setValue(vx, vy, vz); + body.setLinearVelocity(btVelocity); + + world.addRigidBody(body); + + let name = inName.get() + "_" + countAll; + if (!inNameIndex.get())name = inName.get(); + + world.setBodyMeta(body, + { + "name": name + }); + + motionState.setWorldTransform(transform); + body.setWorldTransform(transform); + + if (bodies.length >= inLimit.get()) + { + world.removeRigidBody(bodies[0].body); + bodies.shift(); + } + + bodies.push({ "body": body, "ms": motionState }); + + countAll++; + + outNum.set(bodies.length); + + shouldspawnOne = false; +} + +function dispose() +{ + for (let i = 0; i < bodies.length; i++) + { + world.removeRigidBody(bodies[i].body); + } + + bodies.length = 0; +} + +let arrPos = []; +let arrRot = []; + +inExec.onTriggered = () => +{ + if (shouldspawnOne) spawn(); + if (world != cgl.frameStore.ammoWorld) + { + world = cgl.frameStore.ammoWorld; + world.on("dispose", dispose); + } + + if (inRemoveFalling.get()) + { + for (let i = 0; i < bodies.length; i++) + if (bodies[i]) + { + bodies[i].ms.getWorldTransform(tmpTrans); + let p = tmpTrans.getOrigin(); + if (p.y() < -100)bodies.splice(i, 1); + } + } + + arrPos.length = bodies.length * 3; + arrRot.length = bodies.length * 4; + for (let i = 0; i < bodies.length; i++) + { + if (!bodies[i]) continue; + setArrayTransformed(bodies[i], i, arrPos); + } + outPos.set(null); + outPos.set(arrPos); + outRot.set(null); + outRot.set(arrRot); + + next.trigger(); +}; + + +}; + +Ops.Physics.Ammo.AmmoEmitter.prototype = new CABLES.Op(); +CABLES.OPS["0c568898-f2e0-47b3-b44f-5d0e7c2cda57"]={f:Ops.Physics.Ammo.AmmoEmitter,objName:"Ops.Physics.Ammo.AmmoEmitter"}; + + + + +// ************************************************************** +// +// Ops.Physics.Ammo.AmmoRaycast +// +// ************************************************************** + +Ops.Physics.Ammo.AmmoRaycast = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Update"), + inCoords = op.inSwitch("Ray Coordinates", ["Screen XY", "Points 3d"], "Screen XY"), + inX = op.inValueFloat("Screen X"), + inY = op.inValueFloat("Screen Y"), + inRayPoints = op.inArray("Ray Points"), + active = op.inBool("Active", true), + inCursor = op.inBool("Change Cursor", true), + next = op.outTrigger("next"), + + outHasHit = op.outBoolNum("Has Hit", false), + outName = op.outString("Hit Body Name", ""), + outX = op.outNumber("Hit X"), + outY = op.outNumber("Hit Y"), + outZ = op.outNumber("Hit Z"); + +inExec.onTriggered = update; + +const cgl = op.patch.cgl; +let world = null; +let didsetCursor = false; +let mat = mat4.create(); +let isScreenCoords = true; + +inCoords.onChange = updateCoordsType; +updateCoordsType(); + +function updateCoordsType() +{ + isScreenCoords = inCoords.get() == "Screen XY"; + inX.setUiAttribs({ "greyout": !isScreenCoords }); + inY.setUiAttribs({ "greyout": !isScreenCoords }); + inRayPoints.setUiAttribs({ "greyout": isScreenCoords }); +} + +function update() +{ + world = cgl.frameStore.ammoWorld; + + // for(let i=0;i +{ + needsReset = true; +}; + +inActivateAll.onTriggered = () => +{ + if (ammoWorld) ammoWorld.activateAllBodies(); +}; + +inGravX.onChange = inGravZ.onChange = inGravY.onChange = updateGravity; + +function updateGravity() +{ + if (ammoWorld && ammoWorld.world) + ammoWorld.world.setGravity(new Ammo.btVector3(inGravX.get(), inGravY.get(), inGravZ.get())); +} + +function update() +{ + if (needsReset) + { + if (ammoWorld)ammoWorld.dispose(); + ammoWorld = null; + needsReset = false; + } + + if (!ammoWorld) + { + if (Ammo.cablesSetupDone) + { + ammoWorld = new CABLES.AmmoWorld(); + updateGravity(); + cgl.patch.loading.finished(loadingId); + loadingId = null; + } + else + { + if (!loadingId) loadingId = cgl.patch.loading.start("ammoWorld", "ammoWASM"); + return; + } + } + if (!ammoWorld.world) return; + + deltaTime = performance.now() - lastTime; + + if (inSim.get()) ammoWorld.frame(); + + const old = cgl.frameStore.ammoWorld; + cgl.frameStore.ammoWorld = ammoWorld; + + outNumBodies.set(ammoWorld.numBodies()); + outBodiesMeta.set(ammoWorld.getListBodies()); + outCollisions.set(ammoWorld.getCollisions()); + + ammoWorld.autoRemove = inAutoRemove.get(); + + next.trigger(); + + lastTime = performance.now(); + cgl.frameStore.ammoWorld = old; +} + + +}; + +Ops.Physics.Ammo.AmmoWorld.prototype = new CABLES.Op(); +CABLES.OPS["1005fcd0-5f40-49c5-8d46-45e95fcecf37"]={f:Ops.Physics.Ammo.AmmoWorld,objName:"Ops.Physics.Ammo.AmmoWorld"}; + + + + +// ************************************************************** +// +// Ops.Physics.Ammo.GltfAmmoBodies +// +// ************************************************************** + +Ops.Physics.Ammo.GltfAmmoBodies = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExec = op.inTrigger("Exec"), + inShape = op.inSwitch("Shape", ["Convex Hull", "Triangle Shape"], "Convex Hull"), + inNames = op.inString("Filter Meshes", ""), + inMass = op.inFloat("Mass kg", 0), + + inActive = op.inBool("Active", true), + outNum = op.outNumber("Meshes", 0); + +const cgl = op.patch.cgl; +const bodies = []; +const vec = vec3.create(); +const empty = vec3.create(); +const trMat = mat4.create(); +const size = 1.0; + +let world = null; +let scene = null; +let added = false; +let currentSceneLoaded = 0; + +inExec.onTriggered = update; + +const SHAPE_BOX = 0; +const SHAPE_SPHERE = 1; +const shape = SHAPE_BOX; +const sizeVec = vec3.create(); + +const meshCube = new CGL.WireCube(cgl); + +let tmpTrans = null; + +inMass.onChange = +inShape.onChange = +inNames.onChange = +inExec.onLinkChanged = () => +{ + removeFromWorld(); + added = false; +}; + +inActive.onChange = () => +{ + if (!inActive.get())removeFromWorld(); + update(); +}; + +function update() +{ + if (!inActive.get()) return; + if (!added || world != cgl.frameStore.ammoWorld) addToWorld(); + + if (world && bodies.length && bodies[0] && world.getBodyMeta(bodies[0].body) == undefined)removeFromWorld(); + + ping(); + for (let i = 0; i < bodies.length; i++) + { + cgl.pushModelMatrix(); + + mat4.identity(cgl.mMatrix); + + mat4.mul(cgl.mMatrix, cgl.mMatrix, bodies[i].node.modelMatAbs()); + + if (!tmpTrans)tmpTrans = new Ammo.btTransform(); + + CABLES.AmmoWorld.copyCglTransform(cgl, tmpTrans); + + bodies[i].motionState.setWorldTransform(tmpTrans); + bodies[i].body.setWorldTransform(tmpTrans); + + cgl.popModelMatrix(); + } +} + +function removeFromWorld() +{ + if (world) + { + for (let i = 0; i < bodies.length; i++) + { + world.removeRigidBody(bodies[i].body); + } + } + bodies.length = 0; + outNum.set(bodies.length); + world = null; + added = false; +} + +function ping() +{ + if (world) + for (let i = 0; i < bodies.length; i++) + world.pingBody(bodies[i].body); +} + +function addToWorld() +{ + scene = cgl.frameStore.currentScene; + if (!scene || !cgl.frameStore.ammoWorld) return; + + if (world != cgl.frameStore.ammoWorld || currentSceneLoaded != scene.loaded) removeFromWorld(); + + world = cgl.frameStore.ammoWorld; + + if (!world) + { + op.logError("no physics world!?"); + outNum.set(0); + return; + } + if (!scene) return; + + currentSceneLoaded = scene.loaded; + for (let i = 0; i < scene.nodes.length; i++) + { + if (!scene.nodes[i].mesh) continue; + if (scene.nodes[i].name.indexOf(inNames.get()) == -1) continue; + + let colShape = null; + + scene.nodes[i].transform(cgl, 0); + scene.nodes[i].updateMatrix(); + + const sc = scene.nodes[i]._scale || [1, 1, 1]; + const geom = scene.nodes[i].mesh.meshes[0].geom; + + if (inShape.get() == "Convex Hull") + { + colShape = CABLES.AmmoWorld.createConvexHullFromGeom(geom, 100, sc); + } + else + { + let mesh = new Ammo.btTriangleMesh(true, true); + + for (let i = 0; i < geom.verticesIndices.length / 3; i++) + { + mesh.addTriangle( + new Ammo.btVector3( + sc[0] * geom.vertices[geom.verticesIndices[i * 3] * 3 + 0], + sc[0] * geom.vertices[geom.verticesIndices[i * 3] * 3 + 1], + sc[0] * geom.vertices[geom.verticesIndices[i * 3] * 3 + 2] + ), + new Ammo.btVector3( + sc[0] * geom.vertices[geom.verticesIndices[i * 3 + 1] * 3 + 0], + sc[0] * geom.vertices[geom.verticesIndices[i * 3 + 1] * 3 + 1], + sc[0] * geom.vertices[geom.verticesIndices[i * 3 + 1] * 3 + 2] + ), + new Ammo.btVector3( + sc[0] * geom.vertices[geom.verticesIndices[i * 3 + 2] * 3 + 0], + sc[0] * geom.vertices[geom.verticesIndices[i * 3 + 2] * 3 + 1], + sc[0] * geom.vertices[geom.verticesIndices[i * 3 + 2] * 3 + 2] + ), + false); + } + + colShape = new Ammo.btBvhTriangleMeshShape(mesh, true, true); + } + + colShape.setMargin(0.05); + + let localInertia = new Ammo.btVector3(0, 0, 0); + colShape.calculateLocalInertia(inMass.get(), localInertia); + + let transform = new Ammo.btTransform(); + let motionState = new Ammo.btDefaultMotionState(transform); + + let rbInfo = new Ammo.btRigidBodyConstructionInfo(inMass.get(), motionState, colShape, localInertia); + let body = new Ammo.btRigidBody(rbInfo); + world.addRigidBody(body); + + world.setBodyMeta(body, + { + "name": scene.nodes[i].name, + "mass": inMass.get(), + + }); + + bodies.push( + { + "node": scene.nodes[i], + "motionState": motionState, + "body": body + }); + } + + outNum.set(bodies.length); + + added = true; +} + + +}; + +Ops.Physics.Ammo.GltfAmmoBodies.prototype = new CABLES.Op(); +CABLES.OPS["ea7553aa-0836-4512-9253-34b86d62accc"]={f:Ops.Physics.Ammo.GltfAmmoBodies,objName:"Ops.Physics.Ammo.GltfAmmoBodies"}; + + + + +// ************************************************************** +// +// Ops.Points.PointsCircle +// +// ************************************************************** + +Ops.Points.PointsCircle = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + outArr = op.outArray("Points", 3), + percent = op.inValueSlider("percent", 1), + segments = op.inValue("segments", 40), + radius = op.inValue("radius", 1), + outTotalPoints = op.outNumber("Total points"), + outArrayLength = op.outNumber("Array lengths"); + +radius.onChange = + percent.onChange = + segments.onChange = calcArray; + +function calcArray() +{ + const segs = Math.max(3, Math.floor(segments.get())); + const points = []; + + let count = 0; + for (let i = 0; i < segs * percent.get(); i++) + { + let degInRad = (360 / segs) * i * CGL.DEG2RAD; + let posx = Math.cos(degInRad) * radius.get(); + let posy = Math.sin(degInRad) * radius.get(); + + points.push(posx); + points.push(posy); + points.push(0); + } + + outArr.set(null); + outArr.set(points); + outTotalPoints.set(points.length / 3); + outArrayLength.set(points.length); +} + +calcArray(); + + +}; + +Ops.Points.PointsCircle.prototype = new CABLES.Op(); +CABLES.OPS["ef54ba67-8b1d-41b0-8140-bb97061eaa97"]={f:Ops.Points.PointsCircle,objName:"Ops.Points.PointsCircle"}; + + + + +// ************************************************************** +// +// Ops.Points.PointsCube +// +// ************************************************************** + +Ops.Points.PointsCube = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const numx = op.inValueInt("num x", 5), + numy = op.inValueInt("num y", 5), + numz = op.inValueInt("num z", 5), + mul = op.inValue("mul", 1), + center = op.inValueBool("center", true), + outArray = op.outArray("Array out"), + idx = op.outNumber("Total points"), + arrayLengthOut = op.outNumber("Array length"); + +let newArr = []; +outArray.set(newArr); + +numx.onChange = +numy.onChange = +numz.onChange = +mul.onChange = +center.onChange = update; + +function update() +{ + newArr.length = 0; + + let subX = 0; + let subY = 0; + let subZ = 0; + + if (center.get()) + { + subX = ((numx.get() - 1) * mul.get()) / 2.0; + subY = ((numy.get() - 1) * mul.get()) / 2.0; + subZ = ((numz.get() - 1) * mul.get()) / 2.0; + } + + let xTemp = 0; + let yTemp = 0; + let zTemp = 0; + + let m = mul.get(); + + for (var z = 0; z < numz.get(); z++) + { + zTemp = (z * m) - subZ; + + for (var y = 0; y < numy.get(); y++) + { + yTemp = (y * m) - subY; + + for (var x = 0; x < numx.get(); x++) + { + xTemp = (x * m) - subX; + + newArr.push(xTemp); + newArr.push(yTemp); + newArr.push(zTemp); + } + } + } + idx.set(x * y * z); + outArray.set(null); + outArray.set(newArr); + arrayLengthOut.set(newArr.length); +} + +update(); + + +}; + +Ops.Points.PointsCube.prototype = new CABLES.Op(); +CABLES.OPS["6030193b-089c-4565-a7b8-d837501ded52"]={f:Ops.Points.PointsCube,objName:"Ops.Points.PointsCube"}; + + + + +// ************************************************************** +// +// Ops.Points.PointsHexagonGrid +// +// ************************************************************** + +Ops.Points.PointsHexagonGrid = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const numxIn = op.inInt("Rows", 5), + numyIn = op.inInt("Colums", 5), + pointyOrTopped = op.inSwitch("Hex facing", ["Pointy", "Topped"], "Topped"), + flipCorners = op.inBool("Flip corners", false), + tileXOffsetIn = op.inFloat("Tile X offset", 1), + tileYOffsetIn = op.inFloat("Tile Y offset", 1), + multiplierIn = op.inFloat("Multiplier", 1), + arrayOut = op.outArray("Array out"); + +tileXOffsetIn.onChange = tileYOffsetIn.onChange = numxIn.onChange = numyIn.onChange = multiplierIn.onChange = flipCorners.onChange = pointyOrTopped.onChange = update; + +op.setPortGroup("Dimensions", [numxIn, numyIn]); +op.setPortGroup("Orientation", [flipCorners, pointyOrTopped]); +op.setPortGroup("Spacing", [tileXOffsetIn, tileYOffsetIn, multiplierIn]); + +update(); + +function update() +{ + const arr = []; + + let offsetX = 0; + let offsetY = 0; + + let w = 0; + let h = 0; + + const multiplier = multiplierIn.get(); + + if (pointyOrTopped.get() === "Pointy") + { + w = numyIn.get(); + h = numxIn.get(); + + offsetX = tileXOffsetIn.get() * 1.7; + offsetY = tileYOffsetIn.get() * 1.432; + + for (let x = 0; x < w; x++) + { + for (let y = 0; y < h; y++) + { + let yFlipped = y; + if (flipCorners.get()) yFlipped = y + 1; + + if (yFlipped % 2 == 0) + { + arr.push((x - w / 2) * offsetX * multiplier); + arr.push((y - h / 2) * offsetY * multiplier); + arr.push(0); + } + else + { + arr.push( + ((x - w / 2) * offsetX + offsetX / 2) * multiplier + ); + arr.push((y - h / 2) * offsetY * multiplier); + arr.push(0); + } + } + } + } + else + { + w = numxIn.get(); + h = numyIn.get(); + + offsetX = tileYOffsetIn.get() * 1.7; + offsetY = tileXOffsetIn.get() * 1.432; + + for (let x = 0; x < w; x++) + { + for (let y = 0; y < h; y++) + { + let yFlipped = y; + if (flipCorners.get()) yFlipped = y + 1; + + if (yFlipped % 2 == 0) + { + arr.push((y - h / 2) * offsetY * multiplier); + arr.push((x - w / 2) * offsetX * multiplier); + arr.push(0); + } + else + { + arr.push((y - h / 2) * offsetY * multiplier); + arr.push( + ((x - w / 2) * offsetX + offsetX / 2) * multiplier + ); + arr.push(0); + } + } + } + } + arrayOut.set(arr); +} + + +}; + +Ops.Points.PointsHexagonGrid.prototype = new CABLES.Op(); +CABLES.OPS["989c4d70-8567-47f2-8df3-85c68d422107"]={f:Ops.Points.PointsHexagonGrid,objName:"Ops.Points.PointsHexagonGrid"}; + + + + +// ************************************************************** +// +// Ops.Points.PointsPlane_v2 +// +// ************************************************************** + +Ops.Points.PointsPlane_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inNumX = op.inValueInt("Rows", 32), + inNumY = op.inValueInt("Columns", 32), + inHeight = op.inFloat("Width", 2), + inWidth = op.inFloat("Height", 2), + inRowOffset = op.inFloat("Row Offset", 0), + inCenter = op.inValueBool("Center", true), + outArr = op.outArray("Result", [], 3), + outTotalPoints = op.outNumber("Total points"), + outArrayLength = op.outNumber("Array length"), + outRowNums = op.outArray("Row Numbers", [], 1), + outColNums = op.outArray("Column Numbers", [], 1); + +inNumX.onChange = +inNumY.onChange = +inCenter.onChange = +inWidth.onChange = +inRowOffset.onChange = +inHeight.onChange = generate; + +const arr = []; +const arrRowNums = []; +const arrColNums = []; +outArr.set(arr); +generate(); + +function generate() +{ + arr.length = 0; + const numX = Math.max(0, inNumX.get()); + const numY = Math.max(0, inNumY.get()); + + let stepX = 0; + let stepY = 0; + + // to avoid divide by zero + if (numX == 1) + { + stepX = inWidth.get() / (numX); + } + else + { + stepX = inWidth.get() / (numX - 1); + } + if (numY == 1) + { + stepY = inHeight.get() / (numY); + } + else + { + stepY = inHeight.get() / (numY - 1); + } + + let i = 0; + + let centerX = 0; + let centerY = 0; + + if (inCenter.get()) + { + centerX = inWidth.get() / 2; + centerY = inHeight.get() / 2; + } + + const l = Math.floor(numX) * Math.floor(numY) * 3; + + arr.length = l; + arrColNums.length = l / 3; + arrRowNums.length = l / 3; + + let offRow = inRowOffset.get(); + let off = 0; + for (let y = 0; y < numY; y++) + { + for (let x = 0; x < numX; x++) + { + off = 0; + if (x % 2 == 0 && offRow)off = offRow; + + arrColNums[i / 3] = y; + arrRowNums[i / 3] = x; + + arr[i++] = stepY * y - centerY + off; + arr[i++] = stepX * x - centerX; + + arr[i++] = 0; + } + } + + outRowNums.set(null); + outRowNums.set(arrRowNums); + + outColNums.set(null); + outColNums.set(arrColNums); + + outArr.set(null); + outArr.set(arr); + outTotalPoints.set(arr.length / 3); + outArrayLength.set(arr.length); +} + + +}; + +Ops.Points.PointsPlane_v2.prototype = new CABLES.Op(); +CABLES.OPS["d453f898-17d4-4e2c-b8c7-7b7b34c0ff68"]={f:Ops.Points.PointsPlane_v2,objName:"Ops.Points.PointsPlane_v2"}; + + + + +// ************************************************************** +// +// Ops.Points.PointsSphereRandom +// +// ************************************************************** + +Ops.Points.PointsSphereRandom = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + num = op.inValueInt("Amount of points", 100), + size = op.inValue("Sphere size", 1), + seed = op.inValue("Random seed", 0), + distRand = op.inValueSlider("Random distance from sphere", 0), + distrib = op.inValueSelect("Distribution", ["Uniform", "Poles", "Half"], "Uniform"), + outArray = op.outArray("Array out", 3), + totalPointsOut = op.outNumber("Total points"), + arrayLengthOut = op.outNumber("Array length"); + +let newArr = []; +outArray.set(newArr); + +seed.onChange = + num.onChange = + size.onChange = + distrib.onChange = + distRand.onChange = + outArray.onLinkChanged = generate; + +generate(); + +function generate() +{ + const verts = []; + verts.length = Math.max(0, Math.round(num.get()) * 3); + + Math.randomSeed = seed.get(); + + let rndq = quat.create(); + let tempv = vec3.create(); + + let dist = 0; + if (distrib.get() == "Poles")dist = 1; + if (distrib.get() == "Half")dist = 2; + + let dRand = distRand.get(); + + for (let i = 0; i < num.get(); i++) + { + if (dist == 1 || dist == 2) + { + rndq[0] = Math.seededRandom(); + rndq[1] = Math.seededRandom(); + rndq[2] = Math.seededRandom(); + rndq[3] = Math.seededRandom(); + } + else + { + rndq[0] = Math.seededRandom() * 2.0 - 1.0; + rndq[1] = Math.seededRandom() * 2.0 - 1.0; + rndq[2] = Math.seededRandom() * 2.0 - 1.0; + rndq[3] = Math.seededRandom() * 2.0 - 1.0; + } + + quat.normalize(rndq, rndq); + + if (dist == 2) + { + tempv[0] = size.get(); + } + else + { + if (i % 2 === 0) tempv[0] = -size.get(); + else tempv[0] = size.get(); + } + + tempv[1] = 0; + tempv[2] = 0; + + if (dRand !== 0) tempv[0] -= Math.random() * dRand; + + vec3.transformQuat(tempv, tempv, rndq); + verts[i * 3] = tempv[0]; + verts[i * 3 + 1] = tempv[1]; + verts[i * 3 + 2] = tempv[2]; + } + + outArray.set(null); + outArray.set(verts); + totalPointsOut.set(verts.length / 3); + arrayLengthOut.set(verts.length); +} + + +}; + +Ops.Points.PointsSphereRandom.prototype = new CABLES.Op(); +CABLES.OPS["1ea17de7-adad-4053-943a-4874bccf54e9"]={f:Ops.Points.PointsSphereRandom,objName:"Ops.Points.PointsSphereRandom"}; + + + + +// ************************************************************** +// +// Ops.Sequence +// +// ************************************************************** + +Ops.Sequence = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + cleanup = op.inTriggerButton("Clean up connections"); + +const + exes = [], + triggers = [], + num = 16; + +let updateTimeout = null; + +exe.onTriggered = triggerAll; +cleanup.onTriggered = clean; +cleanup.setUiAttribs({ "hidePort": true }); +cleanup.setUiAttribs({ "hideParam": true }); + +for (let i = 0; i < num; i++) +{ + const p = op.outTrigger("trigger " + i); + triggers.push(p); + p.onLinkChanged = updateButton; + + if (i < num - 1) + { + let newExe = op.inTrigger("exe " + i); + newExe.onTriggered = triggerAll; + exes.push(newExe); + } +} + +function updateButton() +{ + clearTimeout(updateTimeout); + updateTimeout = setTimeout(() => + { + let show = false; + for (let i = 0; i < triggers.length; i++) + if (triggers[i].links.length > 1) show = true; + + cleanup.setUiAttribs({ "hideParam": !show }); + + if (op.isCurrentUiOp()) op.refreshParams(); + }, 60); +} + +function triggerAll() +{ + for (let i = 0; i < triggers.length; i++) triggers[i].trigger(); +} + +function clean() +{ + let count = 0; + for (let i = 0; i < triggers.length; i++) + { + let removeLinks = []; + + if (triggers[i].links.length > 1) + for (let j = 1; j < triggers[i].links.length; j++) + { + while (triggers[count].links.length > 0) count++; + + removeLinks.push(triggers[i].links[j]); + const otherPort = triggers[i].links[j].getOtherPort(triggers[i]); + op.patch.link(op, "trigger " + count, otherPort.parent, otherPort.name); + count++; + } + + for (let j = 0; j < removeLinks.length; j++) removeLinks[j].remove(); + } + updateButton(); +} + + +}; + +Ops.Sequence.prototype = new CABLES.Op(); +CABLES.OPS["a466bc1f-06e9-4595-8849-bffb9fe22f99"]={f:Ops.Sequence,objName:"Ops.Sequence"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.Button_v2 +// +// ************************************************************** + +Ops.Sidebar.Button_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// inputs +const parentPort = op.inObject("link"); +const buttonTextPort = op.inString("Text", "Button"); + +// outputs +const siblingsPort = op.outObject("childs"); +const buttonPressedPort = op.outTrigger("Pressed Trigger"); + +const inGreyOut = op.inBool("Grey Out", false); +const inVisible = op.inBool("Visible", true); + +// vars +const el = document.createElement("div"); +el.dataset.op = op.id; +el.classList.add("cablesEle"); +el.classList.add("sidebar__item"); +el.classList.add("sidebar--button"); +const input = document.createElement("div"); +input.classList.add("sidebar__button-input"); +el.appendChild(input); +input.addEventListener("click", onButtonClick); +const inputText = document.createTextNode(buttonTextPort.get()); +input.appendChild(inputText); +op.toWorkNeedsParent("Ops.Sidebar.Sidebar"); + +// events +parentPort.onChange = onParentChanged; +buttonTextPort.onChange = onButtonTextChanged; +op.onDelete = onDelete; + +const greyOut = document.createElement("div"); +greyOut.classList.add("sidebar__greyout"); +el.appendChild(greyOut); +greyOut.style.display = "none"; + +inGreyOut.onChange = function () +{ + greyOut.style.display = inGreyOut.get() ? "block" : "none"; +}; + +inVisible.onChange = function () +{ + el.style.display = inVisible.get() ? "block" : "none"; +}; + +function onButtonClick() +{ + buttonPressedPort.trigger(); +} + +function onButtonTextChanged() +{ + const buttonText = buttonTextPort.get(); + input.textContent = buttonText; + if (CABLES.UI) + { + op.setTitle("Button: " + buttonText); + } +} + +function onParentChanged() +{ + siblingsPort.set(null); + const parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(el); + siblingsPort.set(parent); + } + else + { // detach + if (el.parentElement) + { + el.parentElement.removeChild(el); + } + } +} + +function showElement(el) +{ + if (el) + { + el.style.display = "block"; + } +} + +function hideElement(el) +{ + if (el) + { + el.style.display = "none"; + } +} + +function onDelete() +{ + removeElementFromDOM(el); +} + +function removeElementFromDOM(el) +{ + if (el && el.parentNode && el.parentNode.removeChild) + { + el.parentNode.removeChild(el); + } +} + + +}; + +Ops.Sidebar.Button_v2.prototype = new CABLES.Op(); +CABLES.OPS["5e9c6933-0605-4bf7-8671-a016d917f327"]={f:Ops.Sidebar.Button_v2,objName:"Ops.Sidebar.Button_v2"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.ColorPicker_v3 +// +// ************************************************************** + +Ops.Sidebar.ColorPicker_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"colorrick_css":".colorRick_dialog\n{\n --width:256px;\n --height:256px;\n --width-hue:20px;\n --pad:10px;\n --colorblock-height:20px;\n --inputcontainer-height:120px;\n\n background-color: #333;\n width:calc(var(--width) + 3*var(--pad) + var(--width-hue));\n height:calc(var(--height) + var(--colorblock-height) + 30px + var(--inputcontainer-height));\n position: absolute;\n border-radius: 10px;\n overflow: hidden;\n z-index: 999999;\n\n}\n\n.colorRick_dialog *\n{\n font-size: 13px;\n}\n\n.colorRick_area\n{\n width:var(--width);\n height:var(--height);\n left:var(--pad);\n top:var(--pad);\n background: linear-gradient(to right, rgb(255, 255, 255), rgb(0, 255, 11));\n position: absolute;\n cursor:pointer;\n}\n\n.colorRick_brightness\n{\n background: linear-gradient(hsla(0,0%,100%,0),#000);\n width:100%;\n height:100%;\n pointer-events: none;\n}\n\n.colorRick_hue\n{\n cursor:pointer;\n top:var(--pad);\n background:linear-gradient(red,#f0f 17%,#00f 34%,#0ff 50%,#0f0 67%,#ff0 84%,red);\n height:var(--height);\n\n width:var(--width-hue);\n position: absolute;\n left:calc(var(--width) + var(--pad) + var(--pad));\n}\n\n.colorRick_preview\n{\n position: absolute;\n width:calc(var(--width) / 10 * 9);\n height:var(--colorblock-height);\n top:calc(var(--height) + 20px);\n margin-left:10px;\n}\n\n.colorRick_preview_orig\n{\n margin-left:calc(calc(var(--width) / 10 * 9) + 10px);\n width:calc(var(--width) / 10);\n cursor:pointer;\n}\n\n.colorRick_cursor\n{\n width:4px;\n height:4px;\n border:1px solid transparent;\n background-color: white;\n position: absolute;\n pointer-events: none;\n border-radius: 100%;\n}\n\n.colorRick_cursor_hue\n{\n position: absolute;\n width:24px;\n margin-left: -2px;\n height:0px;\n border-top:1px solid white;\n border-bottom:1px solid white;\n position: absolute;\n pointer-events: none;\n}\n\n.colorRick_inputcontainer\n{\n position: absolute;\n\n height:var(--inputcontainer-height);\n /* top:250px; */\n top:calc(var(--height) + 20px + 20px + 10px);\n left:0px;\n width:100%;\n background-color: #000;\n padding:10px;\n}\n\n.colorRick_inputcontainer table\n{\n width:var(--width);\n}\n\n.colorRick_inputcontainer, .colorRick_inputcontainer table\n{\n color:#999;\n}\n\n.colorRick_input\n{\n background-color: #444;\n border:0px solid transparent;\n opacity: 1;\n color:#ddd;\n}\n\n.colorRick_input_small\n{\n width:60px;\n margin-left:10px;\n}\n\n.colorRick_input_hex\n{\n width:100px;\n}\n\n.colorRick_invalid\n{\n opacity: 0.5;\n}\n\n.colorRick_inputcontainer table\n{\n /* width:90%; */\n}\n\n.colorRick_inputcontainer table,.colorRick_inputcontainer table td, .colorRick_inputcontainer table tr\n{\n /* pointer-events: none; */\n user-select: none;\n\n vertical-align: top;\n}\n\n.colorRick_inputcontainer table td.right\n{\n text-align: right;\n height: 30px;\n}\n",}; +// constants +const DEFAULT_COLOR_HEX = "#07F78C"; + +// inputs +const parentPort = op.inObject("Link"); +const labelPort = op.inString("Text", "Hex Color"); +const defaultColorArr = hexToRgbNorm(DEFAULT_COLOR_HEX); +const inputRedPort = op.inValueSlider("Input Red", defaultColorArr[0]); +const inputGreenPort = op.inValueSlider("Input Green", defaultColorArr[1]); +const inputBluePort = op.inValueSlider("Input Blue", defaultColorArr[2]); +// const inputValuePort = op.inValueString('Input', DEFAULT_COLOR_HEX); +const setDefaultValueButtonPort = op.inTriggerButton("Set Default"); +const defaultValuePort = op.inValueString("Default", DEFAULT_COLOR_HEX); +defaultValuePort.setUiAttribs({ "hidePort": true, "greyout": true }); + +// outputs +const siblingsPort = op.outObject("Children"); +const redPort = op.outNumber("Red", 0.0); +const greenPort = op.outNumber("Green", 0.0); +const bluePort = op.outNumber("Blue", 0.0); + +const outHex = op.outString("Hex", DEFAULT_COLOR_HEX); + +// vars +const el = document.createElement("div"); +el.dataset.op = op.id; +el.classList.add("cablesEle"); +el.addEventListener("dblclick", function () +{ + let defaultValue = defaultValuePort.get(); + input.setAttribute("value", defaultValue); + if (defaultValue) + { + if (defaultValue.length === 6 && defaultValue.charAt(0) !== "#") + { + defaultValue = "#" + defaultValue; + } + if (defaultValue.length === 7) + { + input.value = defaultValue; + colorInput.value = defaultValue; + setColorOutPorts(defaultValue); + } + } +}); + +el.classList.add("sidebar__item"); +el.classList.add("sidebar__color-picker"); +el.classList.add("sidebar__reloadable"); + +const styleEle = document.createElement("style"); +styleEle.type = "text/css"; +styleEle.textContent = attachments.colorrick_css; + +const head = document.getElementsByTagName("body")[0]; +head.appendChild(styleEle); + +const label = document.createElement("div"); +label.classList.add("sidebar__item-label"); +const labelTextNode = document.createTextNode(labelPort.get()); +label.appendChild(labelTextNode); +el.appendChild(label); +// var inputWrapper = document.createElement('div'); +// inputWrapper.classList.add('sidebar__text-input-input-wrapper'); +// el.appendChild(inputWrapper); +const input = document.createElement("input"); +input.classList.add("sidebar__color-picker-input"); +/* input.classList.add('jscolor'); */ /* color picker library */ +input.setAttribute("type", "text"); +input.setAttribute("value", defaultValuePort.get()); +// inputWrapper.appendChild(input); +el.appendChild(input); +input.addEventListener("input", onInput); +const colorInput = document.createElement("div"); +colorInput.classList.add("sidebar__color-picker-color-input"); +// colorInput.setAttribute("type", "color"); +colorInput.style.backgroundColor = defaultValuePort.get(); +// colorInput.addEventListener("change", onColorPickerChange, false); + +colorInput.addEventListener("click", function () +{ + new ColorRick( + { + "ele": this, + "color": this.style.backgroundColor || "#ff0000", + "onChange": (col) => + { + const hex = col.hex(); + this.style.backgroundColor = hex; + setColorOutPorts(hex); + input.value = hex; + outHex.set(hex); + setInputsByHex(hex); + + op.refreshParams(); + } + }); +}); + +el.appendChild(colorInput); +input.addEventListener("input", onInput); + +onDefaultValueChanged(); /* initialize once */ + +// events +parentPort.onChange = onParentChanged; +labelPort.onChange = onLabelTextChanged; +defaultValuePort.onChange = onDefaultValueChanged; +op.onDelete = onDelete; +setDefaultValueButtonPort.onTriggered = setDefaultColor; +inputRedPort.onChange = inputColorChanged; +inputGreenPort.onChange = inputColorChanged; +inputBluePort.onChange = inputColorChanged; + +// functions + +function inputColorChanged() +{ + const hex = getInputColorHex(); + colorInput.style.backgroundColor = hex; + input.value = hex; + setColorOutPorts(hex); +} + +/** + * Returns the color of the op params ("input red", "input green", "input blue") as hex + */ +function getInputColorHex() +{ + const r = CABLES.clamp(inputRedPort.get(), 0, 1); + const g = CABLES.clamp(inputGreenPort.get(), 0, 1); + const b = CABLES.clamp(inputBluePort.get(), 0, 1); + const hex = rgbNormToHex(r, g, b); + return hex; +} + +function setDefaultColor() +{ + // let hexCol = inputValuePort.get().trim(); + const hex = getInputColorHex(); + defaultValuePort.set(hex); + outHex.set(hex); + op.refreshParams(); +} + +/* +function onInputValuePortChange() { + let hexCol = inputValuePort.get().trim(); + if(hexCol.length === 6 && hexCol.charAt(0) !== '#') { + hexCol = '#' + hexCol; + } + if(hexCol.length === 7) { + colorInput.value = hexCol; + input.value = hexCol; + setColorOutPorts(hexCol); + } +} +*/ + +function hexToRgbNorm(hexColor) +{ + if (!hexColor || hexColor.length !== 7) { return; } + return hexColor + .match(/[A-Za-z0-9]{2}/g) + .map(function (v) + { + return parseInt(v, 16) / 255; + }); +} + +/** + * Helper for rgbNormToHex / rgbToHex + * Converts a number in range [0..255] to hex [00..FF] (with left padding) + */ +function componentToHex(c) +{ + const hex = c.toString(16); + return hex.length == 1 ? "0" + hex : hex; +} + +/** + * r, g, b in range [0..1] + * @returns {string} e.g. "#ff0000" + */ +function rgbNormToHex(r, g, b) +{ + return "#" + componentToHex(Math.floor(255 * r)) + componentToHex(Math.floor(255 * g)) + componentToHex(Math.floor(255 * b)); +} + +/** + * Sets the op param color input ports by hex value (e.g. "#FF0000") + * Does NOT update the gui + */ +function setInputsByHex(hex) +{ + const colorArr = hexToRgbNorm(hex); + inputRedPort.set(colorArr[0]); + inputGreenPort.set(colorArr[1]); + inputBluePort.set(colorArr[2]); + outHex.set(hex); +} + +function onInput(ev) +{ + let newValue = ev.target.value; + if (newValue.length === 6 && newValue.charAt(0) !== "#") + { + newValue = "#" + newValue; + } + if (newValue.length === 7) + { + colorInput.value = newValue; + setColorOutPorts(newValue); + // inputValuePort.set(newValue) + setInputsByHex(newValue); + outHex.set(newValue); + op.refreshParams(); + } +} + +// hex must be 7 digits +function setColorOutPorts(hex) +{ + const colorArr = hexToRgbNorm(hex); + outHex.set(hex); + redPort.set(colorArr[0]); + greenPort.set(colorArr[1]); + bluePort.set(colorArr[2]); +} + +function onDefaultValueChanged() +{ + let defaultValue = defaultValuePort.get(); + input.setAttribute("value", defaultValue); + if (defaultValue) + { + if (defaultValue.length === 6 && defaultValue.charAt(0) !== "#") + { + defaultValue = "#" + defaultValue; + } + if (defaultValue.length === 7) + { + input.value = defaultValue; + colorInput.value = defaultValue; + setColorOutPorts(defaultValue); + } + } +} + +function onLabelTextChanged() +{ + const labelText = labelPort.get(); + label.textContent = labelText; + + if (CABLES.UI) op.setTitle("Color Picker: " + labelText); +} + +function onParentChanged() +{ + siblingsPort.set(null); + const parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(el); + siblingsPort.set(parent); + } + else + { // detach + if (el.parentElement) + { + el.parentElement.removeChild(el); + } + } +} + +function showElement(el) +{ + if (el) + { + el.style.display = "block"; + } +} + +function hideElement(el) +{ + if (el) + { + el.style.display = "none"; + } +} + +function onDelete() +{ + removeElementFromDOM(el); +} + +function removeElementFromDOM(el) +{ + if (el && el.parentNode && el.parentNode.removeChild) + { + el.parentNode.removeChild(el); + } +} + + +}; + +Ops.Sidebar.ColorPicker_v3.prototype = new CABLES.Op(); +CABLES.OPS["52dc1ef8-deb0-4664-a924-4c5548aa8a55"]={f:Ops.Sidebar.ColorPicker_v3,objName:"Ops.Sidebar.ColorPicker_v3"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.DisplayValue_v2 +// +// ************************************************************** + +Ops.Sidebar.DisplayValue_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// inputs +const parentPort = op.inObject("link"); +const labelPort = op.inString("Text", "Value"); +const valuePort = op.inString("Value", ""); + +// outputs +const siblingsPort = op.outObject("childs"); + +// vars +const el = document.createElement("div"); +el.dataset.op = op.id; +el.classList.add("cablesEle"); +el.classList.add("sidebar__item"); +el.classList.add("sidebar__value-display"); +const label = document.createElement("div"); +label.classList.add("sidebar__item-label"); +const labelTextNode = document.createTextNode(labelPort.get()); +label.appendChild(labelTextNode); +el.appendChild(label); +const value = document.createElement("div"); +value.textContent = valuePort.get(); +value.classList.add("sidebar__item-value-label"); +el.appendChild(value); + +// events +parentPort.onChange = onParentChanged; +labelPort.onChange = onLabelTextChanged; +valuePort.onChange = onValueChanged; +op.onDelete = onDelete; + +// functions + +function onValueChanged() +{ + value.textContent = valuePort.get(); +} + +function onLabelTextChanged() +{ + const labelText = labelPort.get(); + label.textContent = labelText; + if (CABLES.UI) + { + op.setTitle("Value: " + labelText); + } +} + +function onParentChanged() +{ + siblingsPort.set(null); + const parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(el); + siblingsPort.set(parent); + } + else + { // detach + if (el.parentElement) + { + el.parentElement.removeChild(el); + } + } +} + +function showElement(element) +{ + if (element) + { + element.style.display = "block"; + } +} + +function hideElement(element) +{ + if (element) + { + element.style.display = "none"; + } +} + +function onDelete() +{ + removeElementFromDOM(el); +} + +function removeElementFromDOM(element) +{ + if (element && element.parentNode && element.parentNode.removeChild) + { + element.parentNode.removeChild(element); + } +} + + +}; + +Ops.Sidebar.DisplayValue_v2.prototype = new CABLES.Op(); +CABLES.OPS["3dd9927e-0d34-4442-8a8a-0ab843aee6e3"]={f:Ops.Sidebar.DisplayValue_v2,objName:"Ops.Sidebar.DisplayValue_v2"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.DropDown_v2 +// +// ************************************************************** + +Ops.Sidebar.DropDown_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// inputs +const parentPort = op.inObject("Link"); +const labelPort = op.inString("Text", "Value"); +const valuesPort = op.inArray("Values"); +const defaultValuePort = op.inString("Default", ""); +const inGreyOut = op.inBool("Grey Out", false); +const inVisible = op.inBool("Visible", true); +const inSize = op.inInt("Lines", 1); +const setDefaultValueButtonPort = op.inTriggerButton("Set Default"); +setDefaultValueButtonPort.onTriggered = setDefault; + +// outputs +const siblingsPort = op.outObject("Children"); +const valuePort = op.outString("Result", defaultValuePort.get()); +const outIndex = op.outNumber("Index"); + +defaultValuePort.setUiAttribs({ "title": "Input" }); + +// vars +const el = document.createElement("div"); +el.addEventListener("dblclick", function () +{ + valuePort.set(defaultValuePort.get()); + const optionElements = input.querySelectorAll("option"); + optionElements.forEach(function (optionElement, index) + { + if (optionElement.value.trim() === defaultValuePort.get()) + { + optionElement.selected = true; + outIndex.set(index); + } + else + { + optionElement.removeAttribute("selected"); + } + }); +}); + +el.dataset.op = op.id; +el.classList.add("cablesEle"); +el.classList.add("sidebar__item"); +el.classList.add("sidebar__select"); +el.classList.add("sidebar__reloadable"); + +const label = document.createElement("div"); +label.classList.add("sidebar__item-label"); +const labelText = document.createTextNode(labelPort.get()); +label.appendChild(labelText); +el.appendChild(label); +const input = document.createElement("select"); + +input.classList.add("sidebar__select-select"); +el.appendChild(input); +input.addEventListener("input", onInput); + +const greyOut = document.createElement("div"); +greyOut.classList.add("sidebar__greyout"); +el.appendChild(greyOut); +greyOut.style.display = "none"; + +inGreyOut.onChange = function () +{ + greyOut.style.display = inGreyOut.get() ? "block" : "none"; +}; + +inVisible.onChange = function () +{ + el.style.display = inVisible.get() ? "block" : "none"; +}; + +// events +parentPort.onChange = onParentChanged; +labelPort.onChange = onLabelTextChanged; +defaultValuePort.onChange = onDefaultValueChanged; +op.onDelete = onDelete; +valuesPort.onChange = onValuesPortChange; + +let options = []; +// functions + +inSize.onChange = () => +{ + input.setAttribute("size", inSize.get()); +}; + +op.onLoaded = function () +{ + valuePort.set(defaultValuePort.get()); +}; + +function onValuesPortChange() +{ + // remove all children + while (input.lastChild) + { + input.removeChild(input.lastChild); + } + options = valuesPort.get(); + const defaultValue = defaultValuePort.get(); + if (options) + { + options.forEach(function (option) + { + const optionEl = document.createElement("option"); + + optionEl.setAttribute("value", option); + if (option === defaultValue || option === valuePort.get()) + { + optionEl.setAttribute("selected", ""); + } + const textEl = document.createTextNode(option); + optionEl.appendChild(textEl); + input.appendChild(optionEl); + }); + } + else + { + valuePort.set(""); + } + + outIndex.set(0); + setSelectedProperty(); /* set the selected property for the default value */ +} + +let finalIndex = 0; +function setSelectedProperty(defaultinput) +{ + const optionElements = input.querySelectorAll("option"); + + let finalEle = null; + + optionElements.forEach(function (optionElement, index) + { + if (optionElement.value.trim() === valuePort.get()) + { + finalEle = optionElement; + finalIndex = index; + } + optionElement.removeAttribute("selected"); + }); + + if (defaultinput) + { + const defaultItem = defaultValuePort.get() + "".trim(); + + optionElements.forEach(function (optionElement, index) + { + if (optionElement.value.trim() === defaultItem) + { + finalEle = optionElement; + finalIndex = index; + } + + optionElement.removeAttribute("selected"); + }); + } + + if (finalEle) finalEle.setAttribute("selected", ""); + outIndex.set(finalIndex); +} + +function onInput(ev) +{ + valuePort.set(ev.target.value); + outIndex.set(options.indexOf(ev.target.value)); + setSelectedProperty(); +} + +function onDefaultValueChanged() +{ + const defaultValue = defaultValuePort.get(); + valuePort.set(defaultValue); + input.value = defaultValue; + setSelectedProperty(); +} + +function onLabelTextChanged() +{ + const lblText = labelPort.get(); + label.textContent = lblText; + if (CABLES.UI) + { + op.setTitle("Dropdown: " + lblText); + } +} + +function onParentChanged() +{ + siblingsPort.set(null); + const parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(el); + siblingsPort.set(parent); + } + else + { // detach + if (el.parentElement) + { + el.parentElement.removeChild(el); + } + } +} + +function showElement(ele) +{ + if (ele) + { + ele.style.display = "block"; + } + setSelectedProperty(); +} + +function hideElement(ele) +{ + if (ele) + { + ele.style.display = "none"; + } +} + +function onDelete() +{ + removeElementFromDOM(el); +} + +function removeElementFromDOM(ele) +{ + if (ele && ele.parentNode && ele.parentNode.removeChild) + { + ele.parentNode.removeChild(ele); + } +} + +function setDefault() +{ + defaultValuePort.set(input.value); + op.refreshParams(); +} + + +}; + +Ops.Sidebar.DropDown_v2.prototype = new CABLES.Op(); +CABLES.OPS["7b3f93d6-4de1-41fd-aa26-e74c8285c662"]={f:Ops.Sidebar.DropDown_v2,objName:"Ops.Sidebar.DropDown_v2"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.Group +// +// ************************************************************** + +Ops.Sidebar.Group = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// inputs +let parentPort = op.inObject("link"); +let labelPort = op.inString("Text", "Group"); +const inShowTitle = op.inBool("Show Title", true); +let defaultMinimizedPort = op.inValueBool("Default Minimized"); +const inVisible = op.inBool("Visible", true); + +// outputs +let nextPort = op.outObject("next"); +let childrenPort = op.outObject("childs"); + +inVisible.onChange = function () +{ + el.style.display = inVisible.get() ? "block" : "none"; +}; + +// vars +let el = document.createElement("div"); +el.dataset.op = op.id; +el.classList.add("sidebar__group"); +onDefaultMinimizedPortChanged(); +let header = document.createElement("div"); +header.classList.add("sidebar__group-header"); +header.classList.add("cablesEle"); +el.appendChild(header); +header.addEventListener("click", onClick); +let headerTitle = document.createElement("div"); +headerTitle.classList.add("sidebar__group-header-title"); +// headerTitle.textContent = labelPort.get(); +header.appendChild(headerTitle); +let headerTitleText = document.createElement("span"); +headerTitleText.textContent = labelPort.get(); +headerTitleText.classList.add("sidebar__group-header-title-text"); +headerTitle.appendChild(headerTitleText); +let icon = document.createElement("span"); +icon.classList.add("sidebar__group-header-icon"); +icon.classList.add("iconsidebar-chevron-up"); +headerTitle.appendChild(icon); +let groupItems = document.createElement("div"); +groupItems.classList.add("sidebar__group-items"); +el.appendChild(groupItems); +op.toWorkPortsNeedToBeLinked(parentPort); + +// events +parentPort.onChange = onParentChanged; +labelPort.onChange = onLabelTextChanged; +defaultMinimizedPort.onChange = onDefaultMinimizedPortChanged; +op.onDelete = onDelete; + +// functions + +inShowTitle.onChange = () => +{ + if (inShowTitle.get())header.style.display = "block"; + else header.style.display = "none"; +}; + +function onDefaultMinimizedPortChanged() +{ + if (defaultMinimizedPort.get()) + { + el.classList.add("sidebar__group--closed"); + } + else + { + el.classList.remove("sidebar__group--closed"); + } +} + +function onClick(ev) +{ + ev.stopPropagation(); + el.classList.toggle("sidebar__group--closed"); +} + +function onLabelTextChanged() +{ + let labelText = labelPort.get(); + headerTitleText.textContent = labelText; + if (CABLES.UI) + { + op.setTitle("Group: " + labelText); + } +} + +function onParentChanged() +{ + childrenPort.set(null); + let parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(el); + childrenPort.set({ + "parentElement": groupItems, + "parentOp": op, + }); + nextPort.set(parent); + } + else + { // detach + if (el.parentElement) + { + el.parentElement.removeChild(el); + } + } +} + +function showElement(el) +{ + if (el) + { + el.style.display = "block"; + } +} + +function hideElement(el) +{ + if (el) + { + el.style.display = "none"; + } +} + +function onDelete() +{ + removeElementFromDOM(el); +} + +function removeElementFromDOM(el) +{ + if (el && el.parentNode && el.parentNode.removeChild) + { + el.parentNode.removeChild(el); + } +} + + +}; + +Ops.Sidebar.Group.prototype = new CABLES.Op(); +CABLES.OPS["86ea2333-b51c-48ed-94c2-8b7b6e9ff34c"]={f:Ops.Sidebar.Group,objName:"Ops.Sidebar.Group"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.Incrementor_v2 +// +// ************************************************************** + +Ops.Sidebar.Incrementor_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// inputs +const parentPort = op.inObject("link"); +const labelPort = op.inString("Label", "Incrementor"); +const inMin = op.inValue("min", 0); +const inMax = op.inValue("max", 10); +const inStepsize = op.inValue("stepsize", 1); +const inDefault = op.inValue("Default", 0); +const inValues = op.inArray("Values"); +const inSetDefault = op.inTriggerButton("Set Default"); +inSetDefault.onTriggered = setDefaultValue; + +// outputs +const siblingsPort = op.outObject("childs"); +const outValue = op.outNumber("value"); + +// vars +let currentPosition = 0; + +const containerEl = document.createElement("div"); +containerEl.dataset.op = op.id; +containerEl.classList.add("cablesEle"); +containerEl.classList.add("sidebar__item"); +const label = document.createElement("div"); +label.classList.add("sidebar__item-label"); +label.addEventListener("dblclick", function () +{ + outValue.set(inDefault.get()); +}); +const labelTextEl = document.createTextNode(labelPort.get()); +label.appendChild(labelTextEl); +containerEl.appendChild(label); + +const innerContainer = document.createElement("span"); +innerContainer.classList.add("sidebar__item__right"); + +// value +const valueEl = document.createElement("span"); +valueEl.style.marginRight = "10px"; + +let valueText = document.createTextNode(inMin.get()); +if (Array.isArray(inValues.get())) +{ + valueText = document.createTextNode(inValues.get()[currentPosition]); +} + +valueEl.appendChild(valueText); +innerContainer.appendChild(valueEl); + +// previous +const prevEl = document.createElement("span"); +prevEl.classList.add("sidebar--button"); +prevEl.style.marginRight = "3px"; +const prevInput = document.createElement("div"); +prevInput.classList.add("sidebar__button-input"); +prevInput.classList.add("minus"); +prevEl.appendChild(prevInput); +prevInput.addEventListener("click", onPrev); +const prevText = document.createTextNode("-"); +prevInput.appendChild(prevText); +innerContainer.appendChild(prevEl); + +// next +const nextEl = document.createElement("span"); +nextEl.classList.add("sidebar--button"); +const nextInput = document.createElement("div"); +nextInput.classList.add("sidebar__button-input"); +nextInput.classList.add("plus"); +nextEl.appendChild(nextInput); +nextInput.addEventListener("click", onNext); +const nextText = document.createTextNode("+"); +nextInput.appendChild(nextText); + +innerContainer.appendChild(nextEl); +containerEl.appendChild(innerContainer); + +op.toWorkNeedsParent("Ops.Sidebar.Sidebar"); + +function setDefaultValue() +{ + inDefault.set(outValue.get()); + op.refreshParams(); +} + +// events +parentPort.onChange = onParentChanged; +inValues.onChange = onValueChange; +labelPort.onChange = onLabelTextChanged; +op.onDelete = onDelete; + +op.onLoaded = op.onInit = function () +{ + if (Array.isArray(inValues.get())) + { + inDefault.setUiAttribs({ "greyout": true }); + } + else + { + outValue.set(inDefault.get()); + valueText.textContent = inDefault.get(); + } +}; + +function onValueChange() +{ + const values = inValues.get(); + let value = inMin.get(); + if (Array.isArray(values)) + { + value = values[currentPosition]; + inMin.setUiAttribs({ "greyout": true }); + inMax.set(values.length - 1); + inMax.setUiAttribs({ "greyout": true }); + inStepsize.setUiAttribs({ "greyout": true }); + inStepsize.set(1); + inDefault.setUiAttribs({ "greyout": true }); + inDefault.set(0); + } + else + { + inMin.setUiAttribs({ "greyout": false }); + inMax.setUiAttribs({ "greyout": false }); + inStepsize.setUiAttribs({ "greyout": false }); + inDefault.setUiAttribs({ "greyout": false }); + } + outValue.set(value); + valueText.textContent = value; +} + +function onNext() +{ + const values = inValues.get(); + let value = 0; + if (!Array.isArray(values)) + { + // no array given, increment/decrement according to params + const currentValue = outValue.get(); + value = Math.min(currentValue + inStepsize.get(), inMax.get()); + } + else + { + // user inputs an array, iterate fields, ignore min/max/stepsize + if (currentPosition < values.length - 1) + { + currentPosition += Math.ceil(inStepsize.get()); + } + value = values[currentPosition]; + } + valueText.textContent = value; + outValue.set(value); +} + +function onPrev() +{ + const values = inValues.get(); + let value = 0; + if (!Array.isArray(values)) + { + // no array given, increment/decrement according to params + const currentValue = outValue.get(); + value = Math.max(currentValue - inStepsize.get(), inMin.get()); + } + else + { + // user inputs an array, iterate fields, ignore min/max/stepsize + if (currentPosition > 0) + { + currentPosition -= Math.ceil(inStepsize.get()); + } + value = values[currentPosition]; + } + valueText.textContent = value; + outValue.set(value); +} + +function onParentChanged() +{ + siblingsPort.set(null); + const parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(containerEl); + siblingsPort.set(parent); + } + else if (containerEl.parentElement) + { + // detach + containerEl.parentElement.removeChild(containerEl); + } +} + +function onLabelTextChanged() +{ + const labelText = labelPort.get(); + label.textContent = labelText; + + if (CABLES.UI) + { + op.setTitle(labelText); + } +} + +function onDelete() +{ + removeElementFromDOM(containerEl); +} + +function removeElementFromDOM(el) +{ + if (el && el.parentNode && el.parentNode.removeChild) + { + el.parentNode.removeChild(el); + } +} + + +}; + +Ops.Sidebar.Incrementor_v2.prototype = new CABLES.Op(); +CABLES.OPS["13932cbc-2bd4-4b2a-b6e0-cda6df4cec54"]={f:Ops.Sidebar.Incrementor_v2,objName:"Ops.Sidebar.Incrementor_v2"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.LocalFileToDataUrl +// +// ************************************************************** + +Ops.Sidebar.LocalFileToDataUrl = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// inputs +const parentPort = op.inObject("link"); +const labelPort = op.inString("Text", "Select File:"); +const inId = op.inValueString("Id", ""); +const inVisible = op.inBool("Visible", true); +const inGreyOut = op.inBool("Grey Out", false); +const inOpenDialog = op.inTriggerButton("Show Dialog"); +const reset = op.inTriggerButton("Reset"); + +// outputs + +const siblingsPort = op.outObject("childs"); +const outDataURL = op.outString("Data URL"); +outDataURL.ignoreValueSerialize = true; + +// vars +const el = document.createElement("div"); +el.dataset.op = op.id; +el.classList.add("cablesEle"); +el.classList.add("sidebar__item"); +el.classList.add("sidebar__text"); +const label = document.createElement("div"); +label.classList.add("sidebar__item-label"); +const labelText = document.createTextNode(labelPort.get()); +label.appendChild(labelText); +el.appendChild(label); + +const fileInputEle = document.createElement("input"); +fileInputEle.type = "file"; +fileInputEle.id = "file"; +fileInputEle.name = "file"; + +fileInputEle.style["background-color"] = "transparent"; +fileInputEle.style.width = "90%"; +fileInputEle.style.display = "none"; +// fileInputEle.style.float = "left"; + +const elReset = document.createElement("div"); +elReset.style.cursor = "pointer"; +elReset.style.position = "absolute"; +elReset.style.right = "10px"; +elReset.style["margin-top"] = "15px"; +elReset.innerHTML = "  ✕"; + +const fileInputButton = document.createElement("div"); +fileInputButton.classList.add("sidebar__button-input"); +fileInputButton.innerHTML = "Choose File"; +fileInputButton.onclick = () => { fileInputEle.click(); }; +inOpenDialog.onTriggered = () => { fileInputButton.click(); }; +fileInputButton.style["margin-top"] = "10px"; +fileInputButton.style.width = "80%"; + +el.appendChild(elReset); +el.appendChild(fileInputButton); +el.appendChild(fileInputEle); + +const imgEl = document.createElement("img"); + +fileInputEle.addEventListener("change", handleFileSelect, false); + +const greyOut = document.createElement("div"); +greyOut.classList.add("sidebar__greyout"); +el.appendChild(greyOut); +greyOut.style.display = "none"; + +inGreyOut.onChange = function () +{ + greyOut.style.display = inGreyOut.get() ? "block" : "none"; +}; + +inVisible.onChange = function () +{ + el.style.display = inVisible.get() ? "block" : "none"; +}; + +function onReset() +{ + fileInputEle.value = ""; + outDataURL.set(""); +} + +reset.onTriggered = onReset; +elReset.addEventListener("click", onReset); + +function handleFileSelect(evt) +{ + const reader = new FileReader(); + + reader.onabort = function (e) + { + op.log("File read cancelled"); + }; + + reader.onload = function (e) + { + outDataURL.set(e.target.result); + }; + + if (evt.target.files[0]) reader.readAsDataURL(evt.target.files[0]); + else outDataURL.set(""); +} + +// events +parentPort.onChange = onParentChanged; +labelPort.onChange = onLabelTextChanged; +inId.onChange = onIdChanged; +op.onDelete = onDelete; + +op.toWorkNeedsParent("Ops.Sidebar.Sidebar"); + +// functions + +function onIdChanged() +{ + el.id = inId.get(); +} + +function onLabelTextChanged() +{ + const labelText = labelPort.get(); + label.textContent = labelText; +} + +function onParentChanged() +{ + siblingsPort.set(null); + const parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(el); + siblingsPort.set(parent); + } + else + { // detach + if (el.parentElement) + { + el.parentElement.removeChild(el); + } + } +} + +function showElement(el) +{ + if (el) + { + el.style.display = "block"; + } +} + +function hideElement(el) +{ + if (el) + { + el.style.display = "none"; + } +} + +function onDelete() +{ + removeElementFromDOM(el); +} + +function removeElementFromDOM(el) +{ + if (el && el.parentNode && el.parentNode.removeChild) + { + el.parentNode.removeChild(el); + } +} + + +}; + +Ops.Sidebar.LocalFileToDataUrl.prototype = new CABLES.Op(); +CABLES.OPS["c99d271e-aa5e-4a9d-a4d3-4c5137c189e8"]={f:Ops.Sidebar.LocalFileToDataUrl,objName:"Ops.Sidebar.LocalFileToDataUrl"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.LocalTextureFile +// +// ************************************************************** + +Ops.Sidebar.LocalTextureFile = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// inputs +let parentPort = op.inObject("link"), + labelPort = op.inString("Text", "Select File:"), + inId = op.inValueString("Id", ""), + + tfilter = op.inSwitch("Filter", ["nearest", "linear", "mipmap"], "linear"), + wrap = op.inValueSelect("Wrap", ["repeat", "mirrored repeat", "clamp to edge"], "clamp to edge"); + +// outputs +let siblingsPort = op.outObject("childs"); +const outTex = op.outTexture("Texture"); + +// vars +let el = document.createElement("div"); +el.dataset.op = op.id; +el.classList.add("cablesEle"); +el.classList.add("sidebar__item"); +el.classList.add("sidebar__text"); +let label = document.createElement("div"); +label.classList.add("sidebar__item-label"); +let labelText = document.createTextNode(labelPort.get()); +label.appendChild(labelText); +el.appendChild(label); + +const fileInputEle = document.createElement("input"); +fileInputEle.type = "file"; +fileInputEle.id = "file"; +fileInputEle.name = "file"; +fileInputEle.style.width = "95%"; +el.appendChild(fileInputEle); + +outTex.set(CGL.Texture.getEmptyTexture(op.patch.cgl)); + +const imgEl = document.createElement("img"); + +tfilter.onChange = wrap.onChange = () => +{ + fileInputEle.dispatchEvent(new Event("change")); +}; +fileInputEle.addEventListener("change", handleFileSelect, false); + +function handleFileSelect(evt) +{ + const reader = new FileReader(); + + reader.onabort = function (e) + { + op.log("File read cancelled"); + }; + + reader.onload = function (e) + { + let image = new Image(); + image.onerror = function (e) + { + outTex.set(CGL.Texture.getEmptyTexture(op.patch.cgl)); + op.log("image error", e); + }; + image.onload = function (e) + { + let cgl_filter = CGL.Texture.FILTER_LINEAR; + let cgl_wrap = CGL.Texture.WRAP_REPEAT; + if (tfilter.get() == "nearest") cgl_filter = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "linear") cgl_filter = CGL.Texture.FILTER_LINEAR; + else if (tfilter.get() == "mipmap") cgl_filter = CGL.Texture.FILTER_MIPMAP; + else if (tfilter.get() == "Anisotropic") cgl_filter = CGL.Texture.FILTER_ANISOTROPIC; + + if (wrap.get() == "repeat") cgl_wrap = CGL.Texture.WRAP_REPEAT; + if (wrap.get() == "mirrored repeat") cgl_wrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + if (wrap.get() == "clamp to edge") cgl_wrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + let tex = CGL.Texture.createFromImage(op.patch.cgl, image, { "filter": cgl_filter, "wrap": cgl_wrap }); + outTex.set(tex); + }; + image.src = e.target.result; + }; + + if (evt && evt.target && evt.target.files[0]) + reader.readAsDataURL(evt.target.files[0]); +} + +// events +parentPort.onChange = onParentChanged; +labelPort.onChange = onLabelTextChanged; +inId.onChange = onIdChanged; +op.onDelete = onDelete; + +op.toWorkNeedsParent("Ops.Sidebar.Sidebar"); + +// functions + +function onIdChanged() +{ + el.id = inId.get(); +} + +function onLabelTextChanged() +{ + let labelText = labelPort.get(); + label.textContent = labelText; +} + +function onParentChanged() +{ + siblingsPort.set(null); + let parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(el); + siblingsPort.set(parent); + } + else + { // detach + if (el.parentElement) + { + el.parentElement.removeChild(el); + } + } +} + +function showElement(el) +{ + if (el) el.style.display = "block"; +} + +function hideElement(el) +{ + if (el) el.style.display = "none"; +} + +function onDelete() +{ + removeElementFromDOM(el); +} + +function removeElementFromDOM(el) +{ + if (el && el.parentNode && el.parentNode.removeChild) + { + el.parentNode.removeChild(el); + } +} + + +}; + +Ops.Sidebar.LocalTextureFile.prototype = new CABLES.Op(); +CABLES.OPS["6e8600c4-fb7d-4315-88d4-4f10009538a7"]={f:Ops.Sidebar.LocalTextureFile,objName:"Ops.Sidebar.LocalTextureFile"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.NumberInput_v2 +// +// ************************************************************** + +Ops.Sidebar.NumberInput_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// inputs +const parentPort = op.inObject("Link"); +const labelPort = op.inString("Text", "Number"); +const inputValuePort = op.inValue("Input", 0); +const setDefaultValueButtonPort = op.inTriggerButton("Set Default"); +const defaultValuePort = op.inValue("Default", 0); +defaultValuePort.setUiAttribs({ "hidePort": true, "greyout": true }); + +// outputs +const siblingsPort = op.outObject("Children"); +const valuePort = op.outNumber("Result", defaultValuePort.get()); + +// vars +const el = document.createElement("div"); +el.addEventListener("dblclick", function () +{ + valuePort.set(parseFloat(defaultValuePort.get())); + inputValuePort.set(parseFloat(defaultValuePort.get())); +}); +el.dataset.op = op.id; +el.classList.add("cablesEle"); +el.classList.add("sidebar__item"); +el.classList.add("sidebar__text-input"); +el.classList.add("sidebar__reloadable"); + +const label = document.createElement("div"); +label.classList.add("sidebar__item-label"); +const labelTextNode = document.createTextNode(labelPort.get()); +label.appendChild(labelTextNode); +el.appendChild(label); +// var inputWrapper = document.createElement('div'); +// inputWrapper.classList.add('sidebar__text-input-input-wrapper'); +// el.appendChild(inputWrapper); +const input = document.createElement("input"); +input.classList.add("sidebar__text-input-input"); +input.setAttribute("type", "text"); +input.setAttribute("value", defaultValuePort.get()); +// inputWrapper.appendChild(input); +el.appendChild(input); +input.addEventListener("input", onInput); + +// events +parentPort.onChange = onParentChanged; +labelPort.onChange = onLabelTextChanged; +defaultValuePort.onChange = onDefaultValueChanged; +op.onDelete = onDelete; +inputValuePort.onChange = onInputValuePortChanged; +setDefaultValueButtonPort.onTriggered = setDefaultValue; + +// functions + +function setDefaultValue() +{ + defaultValuePort.set(parseFloat(inputValuePort.get())); + op.refreshParams(); +} + +function onInputValuePortChanged() +{ + let val = parseFloat(inputValuePort.get()); + if (isNaN(val)) { val = 0; } + input.value = val; + valuePort.set(val); +} + +function onInput(ev) +{ + let newVal = parseFloat(ev.target.value); + if (isNaN(newVal)) { newVal = 0; } + valuePort.set(newVal); + inputValuePort.set(newVal); + op.refreshParams(); +} + +function onDefaultValueChanged() +{ + /* + var defaultValue = defaultValuePort.get(); + valuePort.set(defaultValue); + input.value = defaultValue; + */ +} + +function onLabelTextChanged() +{ + const labelText = labelPort.get(); + label.textContent = labelText; + if (CABLES.UI) + { + op.setTitle("Number Input: " + labelText); + } +} + +function onParentChanged() +{ + siblingsPort.set(null); + const parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(el); + siblingsPort.set(parent); + } + else + { // detach + if (el.parentElement) + { + el.parentElement.removeChild(el); + } + } +} + +function showElement(element) +{ + if (element) + { + element.style.display = "block"; + } +} + +function hideElement(element) +{ + if (element) + { + element.style.display = "none"; + } +} + +function onDelete() +{ + removeElementFromDOM(el); +} + +function removeElementFromDOM(element) +{ + if (element && element.parentNode && element.parentNode.removeChild) + { + element.parentNode.removeChild(element); + } +} + + +}; + +Ops.Sidebar.NumberInput_v2.prototype = new CABLES.Op(); +CABLES.OPS["c4f3f1d7-de07-4c06-921e-32baeef4fc68"]={f:Ops.Sidebar.NumberInput_v2,objName:"Ops.Sidebar.NumberInput_v2"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.Presets_v2 +// +// ************************************************************** + +Ops.Sidebar.Presets_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const parentPort = op.inObject("link"); +const labelPort = op.inString("Text", "Presets"); +const siblingsPort = op.outObject("Children"); + +const inAddPreset = op.inTriggerButton("Add Preset"); +const inUpdatePreset = op.inTriggerButton("Update current Preset"); +const outIndex = op.outNumber("Index"); + +inAddPreset.onTriggered = addPreset; +inUpdatePreset.onTriggered = updatePreset; +parentPort.onChange = onParentChanged; + +const presetPorts = []; +const presetTitlePorts = []; + +const el = document.createElement("div"); +el.classList.add("sidebar__item"); +el.classList.add("sidebar__select"); +const label = document.createElement("div"); +label.classList.add("sidebar__item-label"); +const labelText = document.createTextNode(labelPort.get()); +label.appendChild(labelText); +el.appendChild(label); +const selectList = document.createElement("select"); +selectList.classList.add("sidebar__select-select"); +el.appendChild(selectList); + +const MAX_PRESETS = 8; + +for (let i = 0; i < MAX_PRESETS; i++) +{ + const inpTitle = op.inString("Preset Title " + i); + const inp = op.inObject("Preset " + i); + presetPorts.push(inp); + presetTitlePorts.push(inpTitle); + + inpTitle.onLinkChanged = inp.onLinkChanged = updateSelect; +} + +selectList.onchange = function () +{ + outIndex.set(selectList.selectedIndex); + setSidebar(selectList.options[selectList.selectedIndex].value); +}; + +op.patch.addEventListener("patchLoadEnd", initialize); +op.init = initialize; + +function initialize() +{ + setTimeout(() => + { + for (let i = 0; i < MAX_PRESETS; i++) + if (presetPorts[i].isLinked()) + setSidebar(i); + setSidebar(0); + }, 1000); +} + +function updateSelect() +{ + while (selectList.firstChild) selectList.removeChild(selectList.firstChild); + + for (let i = 0; i < MAX_PRESETS; i++) + { + if (presetPorts[i].isLinked()) + { + const option = document.createElement("option"); + option.value = i; + + const other = presetPorts[i].links[0].getOtherPort(presetPorts[i]); + + // other.parent.removeListener("onTitleChange",updateSelect); + + // if (!other.parent.hasEventListener(other.parent.onTitlechangeevent)) + // other.parent.onTitlechangeevent = other.parent.addEventListener("onTitleChange", updateSelect); + + option.text = "" + presetTitlePorts[i].get(); + selectList.appendChild(option); + } + } +} + +function onParentChanged() +{ + siblingsPort.set(null); + const parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(el); + siblingsPort.set(parent); + } + else + { // detach + if (el.parentElement) + { + el.parentElement.removeChild(el); + } + } +} + +function deSerializeSidebar(obj) +{ + if (!obj) return; + if (!obj.ops) return; + + for (let i = 0; i < obj.ops.length; i++) + { + const theOp = op.patch.getOpById(obj.ops[i].id); + if (theOp) + { + for (const portName in obj.ops[i].ports) + { + const p = theOp.getPortByName(portName); + if (p) + { + if (typeof obj.ops[i].ports[portName] !== "object") + { + p.set(obj.ops[i].ports[portName]); + } + else + { + p.set(obj.ops[i].ports[portName].value); + } + } + else + { + op.warn("unknown preset"); + } + + const def = theOp.getPortByName("Input"); + if (def) + { + def.set(obj.ops[i].ports[portName]); + } + const namedInPort = theOp.getPortByName("Input " + p.name); + if (namedInPort) + { + namedInPort.set(obj.ops[i].ports[portName]); + } + } + } + } +} + +function setSidebar(idx) +{ + const obj = presetPorts[idx].get(); + deSerializeSidebar(obj); +} + +function onDelete() +{ + removeElementFromDOM(el); +} + +function removeElementFromDOM(element) +{ + if (element && element.parentNode && element.parentNode.removeChild) + { + element.parentNode.removeChild(element); + } +} + +function updatePreset() +{ + const r = serializeSidebar(); + const idx = selectList.options[selectList.selectedIndex].value; + + const valueOp = presetPorts[idx].links[0].getOtherPort(presetPorts[idx]).parent; + valueOp.getPortByName("JSON String").set(JSON.stringify(r)); +} + +function serializeSidebar() +{ + const values = []; + for (let i = 0; i < op.patch.ops.length; i++) + { + if ( + op.patch.ops[i].objName.indexOf("Ops.Sidebar.Sidebar") == -1 && + op.patch.ops[i].objName.indexOf("AsObject") == -1 && + op.patch.ops[i].objName.indexOf("Group") == -1 && + op.patch.ops[i].objName.indexOf("Preset") == -1 && + op.patch.ops[i].objName.indexOf("Ops.Sidebar") === 0 + ) + { + let foundPort = false; + + const theOp = op.patch.ops[i]; + const p = {}; + p.id = theOp.id; + p.objName = theOp.objName; + p.ports = {}; + + for (let j = 0; j < op.patch.ops[i].portsOut.length; j++) + { + if (theOp.portsOut[j].type == CABLES.OP_PORT_TYPE_VALUE) + { + p.ports[theOp.portsOut[j].name] = theOp.portsOut[j].get(); + foundPort = true; + } + } + + if (foundPort)values.push(p); + } + } + + const r = { "ops": values }; + + if (CABLES.UI && gui) gui.setStateUnsaved(); + return r; +} + +function addPreset() +{ + let freePort = 0; + let i = 0; + for (i = 0; i < MAX_PRESETS; i++) + { + if (!presetPorts[i].isLinked()) + { + freePort = presetPorts[i]; + break; + } + } + + const r = serializeSidebar(); + + const newOp = op.patch.addOp("Ops.Json.ParseObject_v2"); + + newOp.getPortByName("JSON String").set(JSON.stringify(r)); + + if (CABLES.UI) gui.patchView.centerSelectOp(newOp.id); + + op.patch.link(op, freePort.name, newOp, "Result"); +} + +op.serializeSidebar = serializeSidebar; +op.deSerializeSidebar = deSerializeSidebar; + + +}; + +Ops.Sidebar.Presets_v2.prototype = new CABLES.Op(); +CABLES.OPS["9ef53cbc-f47b-4631-92f1-470bd40c2866"]={f:Ops.Sidebar.Presets_v2,objName:"Ops.Sidebar.Presets_v2"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.SideBarStyle +// +// ************************************************************** + +Ops.Sidebar.SideBarStyle = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const parentPort = op.inObject("link"), + inWidth = op.inInt("Width", 220), + inBorderRadius = op.inFloat("Round Corners", 10), + inColorSpecial = op.inString("Special Color", "#07f78c"), + + siblingsPort = op.outObject("childs"); + +inColorSpecial.onChange = +inBorderRadius.onChange = +inWidth.onChange = setStyle; + +parentPort.onChange = onParentChanged; +op.onDelete = onDelete; + +op.toWorkNeedsParent("Ops.Sidebar.Sidebar"); + +let sideBarEle = null; + +function setStyle() +{ + if (!sideBarEle) return; + + sideBarEle.style.setProperty("--sidebar-width", inWidth.get() + "px"); + + sideBarEle.style.setProperty("--sidebar-color", inColorSpecial.get()); + + sideBarEle.style.setProperty("--sidebar-border-radius", Math.round(inBorderRadius.get()) + "px"); + + op.patch.emitEvent("sidebarStylesChanged"); +} + +function onParentChanged() +{ + siblingsPort.set(null); + const parent = parentPort.get(); + if (parent && parent.parentElement) + { + siblingsPort.set(parent); + sideBarEle = parent.parentElement.parentElement; + setStyle(); + } + else + { + sideBarEle = null; + } +} + +function showElement(el) +{ + if (!el) return; + el.style.display = "block"; +} + +function hideElement(el) +{ + if (!el) return; + el.style.display = "none"; +} + +function onDelete() +{ +} + + +}; + +Ops.Sidebar.SideBarStyle.prototype = new CABLES.Op(); +CABLES.OPS["87d78a59-c8d4-4269-a3f8-af273741aae4"]={f:Ops.Sidebar.SideBarStyle,objName:"Ops.Sidebar.SideBarStyle"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.SideBarSwitch +// +// ************************************************************** + +Ops.Sidebar.SideBarSwitch = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const parentPort = op.inObject("link"), + inArr = op.inArray("Names"), + inStyle = op.inSwitch("Style", ["Tabs", "Switch"], "Switch"), + labelPort = op.inString("Text", "Switch"), + + inInput = op.inInt("Input", 0), + + setDefaultValueButtonPort = op.inTriggerButton("Set Default"), + inGreyOut = op.inBool("Grey Out", false), + + inDefault = op.inValue("Default", 0), + + siblingsPort = op.outObject("childs"), + outIndex = op.outNumber("Index", -1), + outStr = op.outString("String"); + +let elTabActive = null; +const el = document.createElement("div"); +el.classList.add("sidebar__item"); +el.dataset.op = op.id; +el.classList.add("cablesEle"); +inDefault.setUiAttribs({ "greyout": true }); + +const label = document.createElement("div"); +label.classList.add("sidebar__item-label"); +const labelText = document.createTextNode(labelPort.get()); +label.appendChild(labelText); +el.appendChild(label); + +const switchGroup = document.createElement("div"); +el.appendChild(switchGroup); + +const greyOut = document.createElement("div"); +greyOut.classList.add("sidebar__greyout"); +el.appendChild(greyOut); +greyOut.style.display = "none"; + +parentPort.onChange = onParentChanged; +op.onDelete = onDelete; + +op.toWorkNeedsParent("Ops.Sidebar.Sidebar"); +op.setPortGroup("Default Item", [inDefault, setDefaultValueButtonPort]); +const tabEles = []; + +inArr.onChange = rebuildHtml; +inStyle.onChange = updateStyle; +updateStyle(); + +labelPort.onChange = () => +{ + label.innerHTML = labelPort.get(); +}; + +inGreyOut.onChange = function () +{ + greyOut.style.display = inGreyOut.get() ? "block" : "none"; +}; + +function rebuildHtml() +{ + tabEles.length = 0; + switchGroup.innerHTML = ""; + elTabActive = null; + + const arr = inArr.get(); + if (!arr) return; + + for (let i = 0; i < arr.length; i++) + { + const el = addTab(String(arr[i])); + if (i == inDefault.get())setActiveTab(el); + } +} + +setDefaultValueButtonPort.onTriggered = () => +{ + inDefault.set(outIndex.get()); + op.refreshParams(); +}; + +function updateStyle() +{ + if (inStyle.get() == "Tabs") + { + el.classList.add("sidebar_tabs"); + switchGroup.classList.remove("sidebar_switchs"); + label.style.display = "none"; + } + else + { + el.classList.remove("sidebar_tabs"); + switchGroup.classList.add("sidebar_switchs"); + label.style.display = "inline-block"; + } + + labelPort.setUiAttribs({ "greyout": inStyle.get() == "Tabs" }); + + rebuildHtml(); +} + +function addTab(title) +{ + const tabEle = document.createElement("div"); + + if (inStyle.get() == "Tabs") tabEle.classList.add("sidebar_tab"); + else tabEle.classList.add("sidebar_switch"); + + tabEle.id = "tabEle" + tabEles.length; + tabEle.innerHTML = title; + tabEle.dataset.index = tabEles.length; + tabEle.dataset.txt = title; + + tabEle.addEventListener("click", tabClicked); + + switchGroup.appendChild(tabEle); + + tabEles.push(tabEle); + + return tabEle; +} + +inInput.onChange = () => +{ + if (tabEles.length > inInput.get()) + tabClicked({ "target": tabEles[inInput.get()] }); + // setActiveTab(tabEles[inInput.get()]); +}; + +function setActiveTab(el) +{ + if (el) + { + elTabActive = el; + op.log(el.dataset.index); + outIndex.set(parseInt(el.dataset.index)); + outStr.set(el.dataset.txt); + + if (inStyle.get() == "Tabs") el.classList.add("sidebar_tab_active"); + else el.classList.add("sidebar_switch_active"); + } +} + +function tabClicked(e) +{ + if (elTabActive) + if (inStyle.get() == "Tabs") elTabActive.classList.remove("sidebar_tab_active"); + else elTabActive.classList.remove("sidebar_switch_active"); + setActiveTab(e.target); +} + +function onParentChanged() +{ + siblingsPort.set(null); + const parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(el); + siblingsPort.set(parent); + } + else + { + if (el.parentElement) + el.parentElement.removeChild(el); + } +} + +function showElement(el) +{ + if (!el) return; + el.style.display = "block"; +} + +function hideElement(el) +{ + if (!el) return; + el.style.display = "none"; +} + +function onDelete() +{ + removeElementFromDOM(el); +} + +function removeElementFromDOM(el) +{ + if (el && el.parentNode && el.parentNode.removeChild) + { + el.parentNode.removeChild(el); + } +} + + +}; + +Ops.Sidebar.SideBarSwitch.prototype = new CABLES.Op(); +CABLES.OPS["ebc8c92c-5fa6-4598-a9c6-b8e12f22f7c2"]={f:Ops.Sidebar.SideBarSwitch,objName:"Ops.Sidebar.SideBarSwitch"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.Sidebar +// +// ************************************************************** + +Ops.Sidebar.Sidebar = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"style_css":" /*\n * SIDEBAR\n http://danielstern.ca/range.css/#/\n https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-progress-value\n */\n\n.sidebar-icon-undo\n{\n width:10px;\n height:10px;\n background-image: url(\"data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='grey' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 7v6h6'/%3E%3Cpath d='M21 17a9 9 0 00-9-9 9 9 0 00-6 2.3L3 13'/%3E%3C/svg%3E\");\n background-size: 19px;\n background-repeat: no-repeat;\n top: -19px;\n margin-top: -7px;\n}\n\n.icon-chevron-down {\n top: 2px;\n right: 9px;\n}\n\n.iconsidebar-chevron-up,.sidebar__close-button {\n\tbackground-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM4ODg4ODgiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLWNoZXZyb24tdXAiPjxwb2x5bGluZSBwb2ludHM9IjE4IDE1IDEyIDkgNiAxNSI+PC9wb2x5bGluZT48L3N2Zz4=);\n}\n\n.iconsidebar-minimizebutton {\n background-position: 98% center;\n background-repeat: no-repeat;\n}\n\n.sidebar-cables-right\n{\n right: 15px;\n left: initial !important;\n}\n\n.sidebar-cables {\n --sidebar-color: #07f78c;\n --sidebar-width: 220px;\n --sidebar-border-radius: 10px;\n --sidebar-monospace-font-stack: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo, Courier, monospace;\n --sidebar-hover-transition-time: .2s;\n\n position: absolute;\n top: 15px;\n left: 15px;\n border-radius: var(--sidebar-border-radius);\n z-index: 100000;\n color: #BBBBBB;\n width: var( --sidebar-width);\n max-height: 100%;\n box-sizing: border-box;\n overflow-y: auto;\n overflow-x: hidden;\n font-size: 13px;\n font-family: Arial;\n line-height: 1em; /* prevent emojis from breaking height of the title */\n}\n\n.sidebar-cables::selection {\n background-color: var(--sidebar-color);\n color: #EEEEEE;\n}\n\n.sidebar-cables::-webkit-scrollbar {\n background-color: transparent;\n --cables-scrollbar-width: 8px;\n width: var(--cables-scrollbar-width);\n}\n\n.sidebar-cables::-webkit-scrollbar-track {\n background-color: transparent;\n width: var(--cables-scrollbar-width);\n}\n\n.sidebar-cables::-webkit-scrollbar-thumb {\n background-color: #333333;\n border-radius: 4px;\n width: var(--cables-scrollbar-width);\n}\n\n.sidebar-cables--closed {\n width: auto;\n}\n\n.sidebar__close-button {\n background-color: #222;\n /*-webkit-user-select: none; */\n /*-moz-user-select: none; */\n /*-ms-user-select: none; */\n /*user-select: none; */\n /*transition: background-color var(--sidebar-hover-transition-time);*/\n /*color: #CCCCCC;*/\n height: 2px;\n /*border-bottom:20px solid #222;*/\n\n /*box-sizing: border-box;*/\n /*padding-top: 2px;*/\n /*text-align: center;*/\n /*cursor: pointer;*/\n /*border-radius: 0 0 var(--sidebar-border-radius) var(--sidebar-border-radius);*/\n /*opacity: 1.0;*/\n /*transition: opacity 0.3s;*/\n /*overflow: hidden;*/\n}\n\n.sidebar__close-button-icon {\n display: inline-block;\n /*opacity: 0;*/\n width: 20px;\n height: 20px;\n /*position: relative;*/\n /*top: -1px;*/\n\n\n}\n\n.sidebar--closed {\n width: auto;\n margin-right: 20px;\n}\n\n.sidebar--closed .sidebar__close-button {\n margin-top: 8px;\n margin-left: 8px;\n padding:10px;\n\n height: 25px;\n width:25px;\n border-radius: 50%;\n cursor: pointer;\n opacity: 0.3;\n background-repeat: no-repeat;\n background-position: center center;\n transform:rotate(180deg);\n}\n\n.sidebar--closed .sidebar__group\n{\n display:none;\n\n}\n.sidebar--closed .sidebar__close-button-icon {\n background-position: 0px 0px;\n}\n\n.sidebar__close-button:hover {\n background-color: #111111;\n opacity: 1.0 !important;\n}\n\n/*\n * SIDEBAR ITEMS\n */\n\n.sidebar__items {\n /* max-height: 1000px; */\n /* transition: max-height 0.5;*/\n background-color: #222;\n padding-bottom: 20px;\n}\n\n.sidebar--closed .sidebar__items {\n /* max-height: 0; */\n height: 0;\n display: none;\n pointer-interactions: none;\n}\n\n.sidebar__item__right {\n float: right;\n}\n\n/*\n * SIDEBAR GROUP\n */\n\n.sidebar__group {\n /*background-color: #1A1A1A;*/\n overflow: hidden;\n box-sizing: border-box;\n animate: height;\n /*background-color: #151515;*/\n /* max-height: 1000px; */\n /* transition: max-height 0.5s; */\n--sidebar-group-header-height: 33px;\n}\n\n.sidebar__group-items\n{\n padding-top: 15px;\n padding-bottom: 15px;\n}\n\n.sidebar__group--closed {\n /* max-height: 13px; */\n height: var(--sidebar-group-header-height);\n}\n\n.sidebar__group-header {\n box-sizing: border-box;\n color: #EEEEEE;\n background-color: #151515;\n -webkit-user-select: none; /* Chrome all / Safari all */\n -moz-user-select: none; /* Firefox all */\n -ms-user-select: none; /* IE 10+ */\n user-select: none; /* Likely future */\n\n /*height: 100%;//var(--sidebar-group-header-height);*/\n\n padding-top: 7px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n cursor: pointer;\n /*transition: background-color var(--sidebar-hover-transition-time);*/\n position: relative;\n}\n\n.sidebar__group-header:hover {\n background-color: #111111;\n}\n\n.sidebar__group-header-title {\n /*float: left;*/\n overflow: hidden;\n padding: 0 15px;\n padding-top:5px;\n padding-bottom:10px;\n font-weight:bold;\n}\n\n.sidebar__group-header-undo {\n float: right;\n overflow: hidden;\n padding-right: 15px;\n padding-top:5px;\n font-weight:bold;\n }\n\n.sidebar__group-header-icon {\n width: 17px;\n height: 14px;\n background-repeat: no-repeat;\n display: inline-block;\n position: absolute;\n background-size: cover;\n\n /* icon open */\n /* feather icon: chevron up */\n background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM4ODg4ODgiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLWNoZXZyb24tdXAiPjxwb2x5bGluZSBwb2ludHM9IjE4IDE1IDEyIDkgNiAxNSI+PC9wb2x5bGluZT48L3N2Zz4=);\n top: 4px;\n right: 5px;\n opacity: 0.0;\n transition: opacity 0.3;\n}\n\n.sidebar__group-header:hover .sidebar__group-header-icon {\n opacity: 1.0;\n}\n\n/* icon closed */\n.sidebar__group--closed .sidebar__group-header-icon {\n /* feather icon: chevron down */\n background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM4ODg4ODgiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLWNoZXZyb24tZG93biI+PHBvbHlsaW5lIHBvaW50cz0iNiA5IDEyIDE1IDE4IDkiPjwvcG9seWxpbmU+PC9zdmc+);\n top: 4px;\n right: 5px;\n}\n\n/*\n * SIDEBAR ITEM\n */\n\n.sidebar__item\n{\n box-sizing: border-box;\n padding: 7px;\n padding-left:15px;\n padding-right:15px;\n\n overflow: hidden;\n position: relative;\n}\n\n.sidebar__item-label {\n display: inline-block;\n -webkit-user-select: none; /* Chrome all / Safari all */\n -moz-user-select: none; /* Firefox all */\n -ms-user-select: none; /* IE 10+ */\n user-select: none; /* Likely future */\n width: calc(50% - 7px);\n margin-right: 7px;\n margin-top: 2px;\n text-overflow: ellipsis;\n /* overflow: hidden; */\n}\n\n.sidebar__item-value-label {\n font-family: var(--sidebar-monospace-font-stack);\n display: inline-block;\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n max-width: 60%;\n}\n\n.sidebar__item-value-label::selection {\n background-color: var(--sidebar-color);\n color: #EEEEEE;\n}\n\n.sidebar__item + .sidebar__item,\n.sidebar__item + .sidebar__group,\n.sidebar__group + .sidebar__item,\n.sidebar__group + .sidebar__group {\n /*border-top: 1px solid #272727;*/\n}\n\n/*\n * SIDEBAR ITEM TOGGLE\n */\n\n/*.sidebar__toggle */\n.icon_toggle{\n cursor: pointer;\n}\n\n.sidebar__toggle-input {\n --sidebar-toggle-input-color: #CCCCCC;\n --sidebar-toggle-input-color-hover: #EEEEEE;\n --sidebar-toggle-input-border-size: 2px;\n display: inline;\n float: right;\n box-sizing: border-box;\n border-radius: 50%;\n cursor: pointer;\n --toggle-size: 11px;\n margin-top: 2px;\n background-color: transparent !important;\n border: var(--sidebar-toggle-input-border-size) solid var(--sidebar-toggle-input-color);\n width: var(--toggle-size);\n height: var(--toggle-size);\n transition: background-color var(--sidebar-hover-transition-time);\n transition: border-color var(--sidebar-hover-transition-time);\n}\n.sidebar__toggle:hover .sidebar__toggle-input {\n border-color: var(--sidebar-toggle-input-color-hover);\n}\n\n.sidebar__toggle .sidebar__item-value-label {\n -webkit-user-select: none; /* Chrome all / Safari all */\n -moz-user-select: none; /* Firefox all */\n -ms-user-select: none; /* IE 10+ */\n user-select: none; /* Likely future */\n max-width: calc(50% - 12px);\n}\n.sidebar__toggle-input::after { clear: both; }\n\n.sidebar__toggle--active .icon_toggle\n{\n\n background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjE1cHgiIHdpZHRoPSIzMHB4IiBmaWxsPSIjMDZmNzhiIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMTAwIDEwMCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PGcgZGlzcGxheT0ibm9uZSI+PGcgZGlzcGxheT0iaW5saW5lIj48Zz48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZmlsbD0iIzA2Zjc4YiIgZD0iTTMwLDI3QzE3LjM1LDI3LDcsMzcuMzUsNyw1MGwwLDBjMCwxMi42NSwxMC4zNSwyMywyMywyM2g0MCBjMTIuNjUsMCwyMy0xMC4zNSwyMy0yM2wwLDBjMC0xMi42NS0xMC4zNS0yMy0yMy0yM0gzMHogTTcwLDY3Yy05LjM4OSwwLTE3LTcuNjEtMTctMTdzNy42MTEtMTcsMTctMTdzMTcsNy42MSwxNywxNyAgICAgUzc5LjM4OSw2Nyw3MCw2N3oiPjwvcGF0aD48L2c+PC9nPjwvZz48Zz48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTMwLDI3QzE3LjM1LDI3LDcsMzcuMzUsNyw1MGwwLDBjMCwxMi42NSwxMC4zNSwyMywyMywyM2g0MCAgIGMxMi42NSwwLDIzLTEwLjM1LDIzLTIzbDAsMGMwLTEyLjY1LTEwLjM1LTIzLTIzLTIzSDMweiBNNzAsNjdjLTkuMzg5LDAtMTctNy42MS0xNy0xN3M3LjYxMS0xNywxNy0xN3MxNyw3LjYxLDE3LDE3ICAgUzc5LjM4OSw2Nyw3MCw2N3oiPjwvcGF0aD48L2c+PGcgZGlzcGxheT0ibm9uZSI+PGcgZGlzcGxheT0iaW5saW5lIj48cGF0aCBmaWxsPSIjMDZmNzhiIiBzdHJva2U9IiMwNmY3OGIiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBkPSJNNyw1MGMwLDEyLjY1LDEwLjM1LDIzLDIzLDIzaDQwICAgIGMxMi42NSwwLDIzLTEwLjM1LDIzLTIzbDAsMGMwLTEyLjY1LTEwLjM1LTIzLTIzLTIzSDMwQzE3LjM1LDI3LDcsMzcuMzUsNyw1MEw3LDUweiI+PC9wYXRoPjwvZz48Y2lyY2xlIGRpc3BsYXk9ImlubGluZSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiMwNmY3OGIiIHN0cm9rZT0iIzA2Zjc4YiIgc3Ryb2tlLXdpZHRoPSI0IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIGN4PSI3MCIgY3k9IjUwIiByPSIxNyI+PC9jaXJjbGU+PC9nPjxnIGRpc3BsYXk9Im5vbmUiPjxwYXRoIGRpc3BsYXk9ImlubGluZSIgZD0iTTcwLDI1SDMwQzE2LjIxNSwyNSw1LDM2LjIxNSw1LDUwczExLjIxNSwyNSwyNSwyNWg0MGMxMy43ODUsMCwyNS0xMS4yMTUsMjUtMjVTODMuNzg1LDI1LDcwLDI1eiBNNzAsNzEgICBIMzBDMTguNDIxLDcxLDksNjEuNTc5LDksNTBzOS40MjEtMjEsMjEtMjFoNDBjMTEuNTc5LDAsMjEsOS40MjEsMjEsMjFTODEuNTc5LDcxLDcwLDcxeiBNNzAsMzFjLTEwLjQ3NywwLTE5LDguNTIzLTE5LDE5ICAgczguNTIzLDE5LDE5LDE5czE5LTguNTIzLDE5LTE5UzgwLjQ3NywzMSw3MCwzMXogTTcwLDY1Yy04LjI3MSwwLTE1LTYuNzI5LTE1LTE1czYuNzI5LTE1LDE1LTE1czE1LDYuNzI5LDE1LDE1Uzc4LjI3MSw2NSw3MCw2NXoiPjwvcGF0aD48L2c+PC9zdmc+);\n opacity: 1;\n transform: rotate(0deg);\n}\n\n\n.icon_toggle\n{\n float: right;\n width:40px;\n height:18px;\n background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjE1cHgiIHdpZHRoPSIzMHB4IiBmaWxsPSIjYWFhYWFhIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMTAwIDEwMCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PGcgZGlzcGxheT0ibm9uZSI+PGcgZGlzcGxheT0iaW5saW5lIj48Zz48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZmlsbD0iI2FhYWFhYSIgZD0iTTMwLDI3QzE3LjM1LDI3LDcsMzcuMzUsNyw1MGwwLDBjMCwxMi42NSwxMC4zNSwyMywyMywyM2g0MCBjMTIuNjUsMCwyMy0xMC4zNSwyMy0yM2wwLDBjMC0xMi42NS0xMC4zNS0yMy0yMy0yM0gzMHogTTcwLDY3Yy05LjM4OSwwLTE3LTcuNjEtMTctMTdzNy42MTEtMTcsMTctMTdzMTcsNy42MSwxNywxNyAgICAgUzc5LjM4OSw2Nyw3MCw2N3oiPjwvcGF0aD48L2c+PC9nPjwvZz48Zz48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTMwLDI3QzE3LjM1LDI3LDcsMzcuMzUsNyw1MGwwLDBjMCwxMi42NSwxMC4zNSwyMywyMywyM2g0MCAgIGMxMi42NSwwLDIzLTEwLjM1LDIzLTIzbDAsMGMwLTEyLjY1LTEwLjM1LTIzLTIzLTIzSDMweiBNNzAsNjdjLTkuMzg5LDAtMTctNy42MS0xNy0xN3M3LjYxMS0xNywxNy0xN3MxNyw3LjYxLDE3LDE3ICAgUzc5LjM4OSw2Nyw3MCw2N3oiPjwvcGF0aD48L2c+PGcgZGlzcGxheT0ibm9uZSI+PGcgZGlzcGxheT0iaW5saW5lIj48cGF0aCBmaWxsPSIjYWFhYWFhIiBzdHJva2U9IiNhYWFhYWEiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBkPSJNNyw1MGMwLDEyLjY1LDEwLjM1LDIzLDIzLDIzaDQwICAgIGMxMi42NSwwLDIzLTEwLjM1LDIzLTIzbDAsMGMwLTEyLjY1LTEwLjM1LTIzLTIzLTIzSDMwQzE3LjM1LDI3LDcsMzcuMzUsNyw1MEw3LDUweiI+PC9wYXRoPjwvZz48Y2lyY2xlIGRpc3BsYXk9ImlubGluZSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiNhYWFhYWEiIHN0cm9rZT0iI2FhYWFhYSIgc3Ryb2tlLXdpZHRoPSI0IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIGN4PSI3MCIgY3k9IjUwIiByPSIxNyI+PC9jaXJjbGU+PC9nPjxnIGRpc3BsYXk9Im5vbmUiPjxwYXRoIGRpc3BsYXk9ImlubGluZSIgZD0iTTcwLDI1SDMwQzE2LjIxNSwyNSw1LDM2LjIxNSw1LDUwczExLjIxNSwyNSwyNSwyNWg0MGMxMy43ODUsMCwyNS0xMS4yMTUsMjUtMjVTODMuNzg1LDI1LDcwLDI1eiBNNzAsNzEgICBIMzBDMTguNDIxLDcxLDksNjEuNTc5LDksNTBzOS40MjEtMjEsMjEtMjFoNDBjMTEuNTc5LDAsMjEsOS40MjEsMjEsMjFTODEuNTc5LDcxLDcwLDcxeiBNNzAsMzFjLTEwLjQ3NywwLTE5LDguNTIzLTE5LDE5ICAgczguNTIzLDE5LDE5LDE5czE5LTguNTIzLDE5LTE5UzgwLjQ3NywzMSw3MCwzMXogTTcwLDY1Yy04LjI3MSwwLTE1LTYuNzI5LTE1LTE1czYuNzI5LTE1LDE1LTE1czE1LDYuNzI5LDE1LDE1Uzc4LjI3MSw2NSw3MCw2NXoiPjwvcGF0aD48L2c+PC9zdmc+);\n background-size: 50px 37px;\n background-position: -6px -10px;\n transform: rotate(180deg);\n opacity: 0.4;\n}\n\n\n\n/*.sidebar__toggle--active .sidebar__toggle-input {*/\n/* transition: background-color var(--sidebar-hover-transition-time);*/\n/* background-color: var(--sidebar-toggle-input-color);*/\n/*}*/\n/*.sidebar__toggle--active .sidebar__toggle-input:hover*/\n/*{*/\n/* background-color: var(--sidebar-toggle-input-color-hover);*/\n/* border-color: var(--sidebar-toggle-input-color-hover);*/\n/* transition: background-color var(--sidebar-hover-transition-time);*/\n/* transition: border-color var(--sidebar-hover-transition-time);*/\n/*}*/\n\n/*\n * SIDEBAR ITEM BUTTON\n */\n\n.sidebar__button {}\n\n.sidebar__button-input {\n -webkit-user-select: none; /* Chrome all / Safari all */\n -moz-user-select: none; /* Firefox all */\n -ms-user-select: none; /* IE 10+ */\n user-select: none; /* Likely future */\n min-height: 24px;\n background-color: transparent;\n color: #CCCCCC;\n box-sizing: border-box;\n padding-top: 3px;\n text-align: center;\n border-radius: 125px;\n border:2px solid #555;\n cursor: pointer;\n padding-bottom: 3px;\n}\n\n.sidebar__button-input.plus, .sidebar__button-input.minus {\n display: inline-block;\n min-width: 20px;\n}\n\n.sidebar__button-input:hover {\n background-color: #333;\n border:2px solid var(--sidebar-color);\n}\n\n/*\n * VALUE DISPLAY (shows a value)\n */\n\n.sidebar__value-display {}\n\n/*\n * SLIDER\n */\n\n.sidebar__slider {\n --sidebar-slider-input-height: 3px;\n}\n\n.sidebar__slider-input-wrapper {\n width: 100%;\n\n margin-top: 8px;\n position: relative;\n}\n\n.sidebar__slider-input {\n -webkit-appearance: none;\n appearance: none;\n margin: 0;\n width: 100%;\n height: var(--sidebar-slider-input-height);\n background: #555;\n cursor: pointer;\n outline: 0;\n\n -webkit-transition: .2s;\n transition: background-color .2s;\n border: none;\n}\n\n.sidebar__slider-input:focus, .sidebar__slider-input:hover {\n border: none;\n}\n\n.sidebar__slider-input-active-track {\n user-select: none;\n position: absolute;\n z-index: 11;\n top: 0;\n left: 0;\n background-color: var(--sidebar-color);\n pointer-events: none;\n height: var(--sidebar-slider-input-height);\n max-width: 100%;\n}\n\n/* Mouse-over effects */\n.sidebar__slider-input:hover {\n /*background-color: #444444;*/\n}\n\n/*.sidebar__slider-input::-webkit-progress-value {*/\n/* background-color: green;*/\n/* color:green;*/\n\n/* }*/\n\n/* The slider handle (use -webkit- (Chrome, Opera, Safari, Edge) and -moz- (Firefox) to override default look) */\n\n.sidebar__slider-input::-moz-range-thumb\n{\n position: absolute;\n height: 15px;\n width: 15px;\n z-index: 900 !important;\n border-radius: 20px !important;\n cursor: pointer;\n background: var(--sidebar-color) !important;\n user-select: none;\n\n}\n\n.sidebar__slider-input::-webkit-slider-thumb\n{\n position: relative;\n appearance: none;\n -webkit-appearance: none;\n user-select: none;\n height: 15px;\n width: 15px;\n display: block;\n z-index: 900 !important;\n border: 0;\n border-radius: 20px !important;\n cursor: pointer;\n background: #777 !important;\n}\n\n.sidebar__slider-input:hover ::-webkit-slider-thumb {\n background-color: #EEEEEE !important;\n}\n\n/*.sidebar__slider-input::-moz-range-thumb {*/\n\n/* width: 0 !important;*/\n/* height: var(--sidebar-slider-input-height);*/\n/* background: #EEEEEE;*/\n/* cursor: pointer;*/\n/* border-radius: 0 !important;*/\n/* border: none;*/\n/* outline: 0;*/\n/* z-index: 100 !important;*/\n/*}*/\n\n.sidebar__slider-input::-moz-range-track {\n background-color: transparent;\n z-index: 11;\n}\n\n/*.sidebar__slider-input::-moz-range-thumb:hover {*/\n /* background-color: #EEEEEE; */\n/*}*/\n\n\n/*.sidebar__slider-input-wrapper:hover .sidebar__slider-input-active-track {*/\n/* background-color: #EEEEEE;*/\n/*}*/\n\n/*.sidebar__slider-input-wrapper:hover .sidebar__slider-input::-moz-range-thumb {*/\n/* background-color: #fff !important;*/\n/*}*/\n\n/*.sidebar__slider-input-wrapper:hover .sidebar__slider-input::-webkit-slider-thumb {*/\n/* background-color: #EEEEEE;*/\n/*}*/\n\n.sidebar__slider input[type=text],\n.sidebar__slider input[type=paddword]\n{\n box-sizing: border-box;\n /*background-color: #333333;*/\n text-align: right;\n color: #BBBBBB;\n display: inline-block;\n background-color: transparent !important;\n\n width: 40%;\n height: 18px;\n outline: none;\n border: none;\n border-radius: 0;\n padding: 0 0 0 4px !important;\n margin: 0;\n}\n\n.sidebar__slider input[type=text]:active,\n.sidebar__slider input[type=text]:focus,\n.sidebar__slider input[type=text]:hover\n.sidebar__slider input[type=password]:active,\n.sidebar__slider input[type=password]:focus,\n.sidebar__slider input[type=password]:hover\n{\n\n color: #EEEEEE;\n}\n\n/*\n * TEXT / DESCRIPTION\n */\n\n.sidebar__text .sidebar__item-label {\n width: auto;\n display: block;\n max-height: none;\n margin-right: 0;\n line-height: 1.1em;\n}\n\n/*\n * SIDEBAR INPUT\n */\n.sidebar__text-input textarea,\n.sidebar__text-input input[type=text],\n.sidebar__text-input input[type=password] {\n box-sizing: border-box;\n background-color: #333333;\n color: #BBBBBB;\n display: inline-block;\n width: 50%;\n height: 18px;\n outline: none;\n border: none;\n border-radius: 0;\n border:1px solid #666;\n padding: 0 0 0 4px !important;\n margin: 0;\n}\n\n.sidebar__text-input textarea:focus::placeholder {\n color: transparent;\n}\n\n.sidebar__color-picker .sidebar__item-label\n{\n width:45%;\n}\n\n.sidebar__text-input textarea,\n.sidebar__text-input input[type=text]:active,\n.sidebar__text-input input[type=text]:focus,\n.sidebar__text-input input[type=text]:hover,\n.sidebar__text-input input[type=password]:active,\n.sidebar__text-input input[type=password]:focus,\n.sidebar__text-input input[type=password]:hover {\n background-color: transparent;\n color: #EEEEEE;\n}\n\n.sidebar__text-input textarea\n{\n margin-top:10px;\n height:60px;\n width:100%;\n}\n\n/*\n * SIDEBAR SELECT\n */\n\n\n\n .sidebar__select {}\n .sidebar__select-select {\n color: #BBBBBB;\n /*-webkit-appearance: none;*/\n /*-moz-appearance: none;*/\n appearance: none;\n /*box-sizing: border-box;*/\n width: 50%;\n /*height: 20px;*/\n background-color: #333333;\n /*background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM4ODg4ODgiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLWNoZXZyb24tZG93biI+PHBvbHlsaW5lIHBvaW50cz0iNiA5IDEyIDE1IDE4IDkiPjwvcG9seWxpbmU+PC9zdmc+);*/\n background-repeat: no-repeat;\n background-position: right center;\n background-size: 16px 16px;\n margin: 0;\n /*padding: 0 2 2 6px;*/\n border-radius: 5px;\n border: 1px solid #777;\n background-color: #444;\n cursor: pointer;\n outline: none;\n padding-left: 5px;\n\n }\n\n.sidebar__select-select:hover,\n.sidebar__select-select:active,\n.sidebar__select-select:active {\n background-color: #444444;\n color: #EEEEEE;\n}\n\n/*\n * COLOR PICKER\n */\n\n\n .sidebar__color-picker input[type=text] {\n box-sizing: border-box;\n background-color: #333333;\n color: #BBBBBB;\n display: inline-block;\n width: calc(50% - 21px); /* 50% minus space of picker circle */\n height: 18px;\n outline: none;\n border: none;\n border-radius: 0;\n padding: 0 0 0 4px !important;\n margin: 0;\n margin-right: 7px;\n}\n\n.sidebar__color-picker input[type=text]:active,\n.sidebar__color-picker input[type=text]:focus,\n.sidebar__color-picker input[type=text]:hover {\n background-color: #444444;\n color: #EEEEEE;\n}\n\ndiv.sidebar__color-picker-color-input,\n.sidebar__color-picker input[type=color],\n.sidebar__palette-picker input[type=color] {\n display: inline-block;\n border-radius: 100%;\n height: 14px;\n width: 14px;\n\n padding: 0;\n border: none;\n /*border:2px solid red;*/\n border-color: transparent;\n outline: none;\n background: none;\n appearance: none;\n -moz-appearance: none;\n -webkit-appearance: none;\n cursor: pointer;\n position: relative;\n top: 3px;\n}\n.sidebar__color-picker input[type=color]:focus,\n.sidebar__palette-picker input[type=color]:focus {\n outline: none;\n}\n.sidebar__color-picker input[type=color]::-moz-color-swatch,\n.sidebar__palette-picker input[type=color]::-moz-color-swatch {\n border: none;\n}\n.sidebar__color-picker input[type=color]::-webkit-color-swatch-wrapper,\n.sidebar__palette-picker input[type=color]::-webkit-color-swatch-wrapper {\n padding: 0;\n}\n.sidebar__color-picker input[type=color]::-webkit-color-swatch,\n.sidebar__palette-picker input[type=color]::-webkit-color-swatch {\n border: none;\n border-radius: 100%;\n}\n\n/*\n * Palette Picker\n */\n.sidebar__palette-picker .sidebar__palette-picker-color-input.first {\n margin-left: 0;\n}\n.sidebar__palette-picker .sidebar__palette-picker-color-input.last {\n margin-right: 0;\n}\n.sidebar__palette-picker .sidebar__palette-picker-color-input {\n margin: 0 4px;\n}\n\n.sidebar__palette-picker .circlebutton {\n width: 14px;\n height: 14px;\n border-radius: 1em;\n display: inline-block;\n top: 3px;\n position: relative;\n}\n\n/*\n * Preset\n */\n.sidebar__item-presets-preset\n{\n padding:4px;\n cursor:pointer;\n padding-left:8px;\n padding-right:8px;\n margin-right:4px;\n background-color:#444;\n}\n\n.sidebar__item-presets-preset:hover\n{\n background-color:#666;\n}\n\n.sidebar__greyout\n{\n background: #222;\n opacity: 0.8;\n width: 100%;\n height: 100%;\n position: absolute;\n z-index: 1000;\n right: 0;\n top: 0;\n}\n\n.sidebar_tabs\n{\n background-color: #151515;\n padding-bottom: 0px;\n}\n\n.sidebar_switchs\n{\n float: right;\n}\n\n.sidebar_tab\n{\n float:left;\n background-color: #151515;\n border-bottom:1px solid transparent;\n padding-right:7px;\n padding-left:7px;\n padding-bottom: 5px;\n padding-top: 5px;\n cursor:pointer;\n}\n\n.sidebar_tab_active\n{\n background-color: #272727;\n color:white;\n}\n\n.sidebar_tab:hover\n{\n border-bottom:1px solid #777;\n color:white;\n}\n\n\n.sidebar_switch\n{\n float:left;\n background-color: #444;\n padding-right:7px;\n padding-left:7px;\n padding-bottom: 5px;\n padding-top: 5px;\n cursor:pointer;\n}\n\n.sidebar_switch:last-child\n{\n border-top-right-radius: 7px;\n border-bottom-right-radius: 7px;\n}\n\n.sidebar_switch:first-child\n{\n border-top-left-radius: 7px;\n border-bottom-left-radius: 7px;\n}\n\n\n.sidebar_switch_active\n{\n background-color: #999;\n color:white;\n}\n\n.sidebar_switch:hover\n{\n color:white;\n}\n",}; +// vars +const CSS_ELEMENT_CLASS = "cables-sidebar-style"; /* class for the style element to be generated */ +const CSS_ELEMENT_DYNAMIC_CLASS = "cables-sidebar-dynamic-style"; /* things which can be set via op-port, but not attached to the elements themselves, e.g. minimized opacity */ +const SIDEBAR_CLASS = "sidebar-cables"; +const SIDEBAR_ID = "sidebar" + CABLES.uuid(); +const SIDEBAR_ITEMS_CLASS = "sidebar__items"; +const SIDEBAR_OPEN_CLOSE_BTN_CLASS = "sidebar__close-button"; + +const BTN_TEXT_OPEN = ""; // 'Close'; +const BTN_TEXT_CLOSED = ""; // 'Show Controls'; + +let openCloseBtn = null; +let openCloseBtnIcon = null; +let headerTitleText = null; + +// inputs +const visiblePort = op.inValueBool("Visible", true); +const opacityPort = op.inValueSlider("Opacity", 1); +const defaultMinimizedPort = op.inValueBool("Default Minimized"); +const minimizedOpacityPort = op.inValueSlider("Minimized Opacity", 0.5); +const undoButtonPort = op.inValueBool("Show undo button", false); +const inMinimize = op.inValueBool("Show Minimize", false); + +const inTitle = op.inString("Title", "Sidebar"); +const side = op.inValueBool("Side"); + +// outputs +const childrenPort = op.outObject("childs"); +childrenPort.setUiAttribs({ "title": "Children" }); + +const isOpenOut = op.outBool("Opfened"); +isOpenOut.setUiAttribs({ "title": "Opened" }); + +let sidebarEl = document.querySelector("." + SIDEBAR_ID); +if (!sidebarEl) +{ + sidebarEl = initSidebarElement(); +} +// if(!sidebarEl) return; +const sidebarItemsEl = sidebarEl.querySelector("." + SIDEBAR_ITEMS_CLASS); +childrenPort.set({ + "parentElement": sidebarItemsEl, + "parentOp": op, +}); +onDefaultMinimizedPortChanged(); +initSidebarCss(); +updateDynamicStyles(); + +// change listeners +visiblePort.onChange = onVisiblePortChange; +opacityPort.onChange = onOpacityPortChange; +defaultMinimizedPort.onChange = onDefaultMinimizedPortChanged; +minimizedOpacityPort.onChange = onMinimizedOpacityPortChanged; +undoButtonPort.onChange = onUndoButtonChange; +op.onDelete = onDelete; + +// functions + +function onMinimizedOpacityPortChanged() +{ + updateDynamicStyles(); +} + +inMinimize.onChange = updateMinimize; + +function updateMinimize(header) +{ + if (!header || header.uiAttribs) header = document.querySelector(".sidebar-cables .sidebar__group-header"); + if (!header) return; + + const undoButton = document.querySelector(".sidebar-cables .sidebar__group-header .sidebar__group-header-undo"); + + if (inMinimize.get()) + { + header.classList.add("iconsidebar-chevron-up"); + header.classList.add("iconsidebar-minimizebutton"); + + if (undoButton)undoButton.style.marginRight = "20px"; + } + else + { + header.classList.remove("iconsidebar-chevron-up"); + header.classList.remove("iconsidebar-minimizebutton"); + + if (undoButton)undoButton.style.marginRight = "initial"; + } +} + +side.onChange = function () +{ + if (side.get()) sidebarEl.classList.add("sidebar-cables-right"); + else sidebarEl.classList.remove("sidebar-cables-right"); +}; + +function onUndoButtonChange() +{ + const header = document.querySelector(".sidebar-cables .sidebar__group-header"); + if (header) + { + initUndoButton(header); + } +} + +function initUndoButton(header) +{ + if (header) + { + const undoButton = document.querySelector(".sidebar-cables .sidebar__group-header .sidebar__group-header-undo"); + if (undoButton) + { + if (!undoButtonPort.get()) + { + // header.removeChild(undoButton); + undoButton.remove(); + } + } + else + { + if (undoButtonPort.get()) + { + const headerUndo = document.createElement("span"); + headerUndo.classList.add("sidebar__group-header-undo"); + headerUndo.classList.add("sidebar-icon-undo"); + + headerUndo.addEventListener("click", function (event) + { + event.stopPropagation(); + const reloadables = document.querySelectorAll(".sidebar-cables .sidebar__reloadable"); + const doubleClickEvent = document.createEvent("MouseEvents"); + doubleClickEvent.initEvent("dblclick", true, true); + reloadables.forEach((reloadable) => + { + reloadable.dispatchEvent(doubleClickEvent); + }); + }); + header.appendChild(headerUndo); + } + } + } + updateMinimize(header); +} + +function onDefaultMinimizedPortChanged() +{ + if (!openCloseBtn) { return; } + if (defaultMinimizedPort.get()) + { + sidebarEl.classList.add("sidebar--closed"); + if (visiblePort.get()) + { + isOpenOut.set(false); + } + // openCloseBtn.textContent = BTN_TEXT_CLOSED; + } + else + { + sidebarEl.classList.remove("sidebar--closed"); + if (visiblePort.get()) + { + isOpenOut.set(true); + } + // openCloseBtn.textContent = BTN_TEXT_OPEN; + } +} + +function onOpacityPortChange() +{ + const opacity = opacityPort.get(); + sidebarEl.style.opacity = opacity; +} + +function onVisiblePortChange() +{ + if (visiblePort.get()) + { + sidebarEl.style.display = "block"; + if (!sidebarEl.classList.contains("sidebar--closed")) + { + isOpenOut.set(true); + } + } + else + { + sidebarEl.style.display = "none"; + isOpenOut.set(false); + } +} + +side.onChanged = function () +{ + +}; + +/** + * Some styles cannot be set directly inline, so a dynamic stylesheet is needed. + * Here hover states can be set later on e.g. + */ +function updateDynamicStyles() +{ + const dynamicStyles = document.querySelectorAll("." + CSS_ELEMENT_DYNAMIC_CLASS); + if (dynamicStyles) + { + dynamicStyles.forEach(function (e) + { + e.parentNode.removeChild(e); + }); + } + const newDynamicStyle = document.createElement("style"); + newDynamicStyle.classList.add(CSS_ELEMENT_DYNAMIC_CLASS); + let cssText = ".sidebar--closed .sidebar__close-button { "; + cssText += "opacity: " + minimizedOpacityPort.get(); + cssText += "}"; + const cssTextEl = document.createTextNode(cssText); + newDynamicStyle.appendChild(cssTextEl); + document.body.appendChild(newDynamicStyle); +} + +function initSidebarElement() +{ + const element = document.createElement("div"); + element.classList.add(SIDEBAR_CLASS); + element.classList.add(SIDEBAR_ID); + const canvasWrapper = op.patch.cgl.canvas.parentElement; /* maybe this is bad outside cables!? */ + + // header... + const headerGroup = document.createElement("div"); + headerGroup.classList.add("sidebar__group"); + + element.appendChild(headerGroup); + const header = document.createElement("div"); + header.classList.add("sidebar__group-header"); + + element.appendChild(header); + const headerTitle = document.createElement("span"); + headerTitle.classList.add("sidebar__group-header-title"); + headerTitleText = document.createElement("span"); + headerTitleText.classList.add("sidebar__group-header-title-text"); + headerTitleText.innerHTML = inTitle.get(); + headerTitle.appendChild(headerTitleText); + header.appendChild(headerTitle); + + initUndoButton(header); + updateMinimize(header); + + headerGroup.appendChild(header); + element.appendChild(headerGroup); + headerGroup.addEventListener("click", onOpenCloseBtnClick); + + if (!canvasWrapper) + { + op.warn("[sidebar] no canvas parentelement found..."); + return; + } + canvasWrapper.appendChild(element); + const items = document.createElement("div"); + items.classList.add(SIDEBAR_ITEMS_CLASS); + element.appendChild(items); + openCloseBtn = document.createElement("div"); + openCloseBtn.classList.add(SIDEBAR_OPEN_CLOSE_BTN_CLASS); + openCloseBtn.addEventListener("click", onOpenCloseBtnClick); + // openCloseBtn.textContent = BTN_TEXT_OPEN; + element.appendChild(openCloseBtn); + // openCloseBtnIcon = document.createElement("span"); + + // openCloseBtnIcon.classList.add("sidebar__close-button-icon"); + // openCloseBtnIcon.classList.add("iconsidebar-chevron-up"); + + // openCloseBtn.appendChild(openCloseBtnIcon); + + return element; +} + +inTitle.onChange = function () +{ + if (headerTitleText)headerTitleText.innerHTML = inTitle.get(); +}; + +function setClosed(b) +{ + +} + +function onOpenCloseBtnClick(ev) +{ + ev.stopPropagation(); + if (!sidebarEl) { op.logError("Sidebar could not be closed..."); return; } + sidebarEl.classList.toggle("sidebar--closed"); + const btn = ev.target; + let btnText = BTN_TEXT_OPEN; + if (sidebarEl.classList.contains("sidebar--closed")) + { + btnText = BTN_TEXT_CLOSED; + isOpenOut.set(false); + } + else + { + isOpenOut.set(true); + } +} + +function initSidebarCss() +{ + // var cssEl = document.getElementById(CSS_ELEMENT_ID); + const cssElements = document.querySelectorAll("." + CSS_ELEMENT_CLASS); + // remove old script tag + if (cssElements) + { + cssElements.forEach(function (e) + { + e.parentNode.removeChild(e); + }); + } + const newStyle = document.createElement("style"); + newStyle.innerHTML = attachments.style_css; + newStyle.classList.add(CSS_ELEMENT_CLASS); + document.body.appendChild(newStyle); +} + +function onDelete() +{ + removeElementFromDOM(sidebarEl); +} + +function removeElementFromDOM(el) +{ + if (el && el.parentNode && el.parentNode.removeChild) el.parentNode.removeChild(el); +} + + +}; + +Ops.Sidebar.Sidebar.prototype = new CABLES.Op(); +CABLES.OPS["5a681c35-78ce-4cb3-9858-bc79c34c6819"]={f:Ops.Sidebar.Sidebar,objName:"Ops.Sidebar.Sidebar"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.SidebarText_v2 +// +// ************************************************************** + +Ops.Sidebar.SidebarText_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// inputs +const parentPort = op.inObject("link"); +const labelPort = op.inString("Text", "Value"); +const inId = op.inValueString("Id", ""); + +// outputs +const siblingsPort = op.outObject("childs"); + +// vars +const el = document.createElement("div"); +el.dataset.op = op.id; +el.classList.add("cablesEle"); +el.classList.add("sidebar__item"); +el.classList.add("sidebar__text"); +const label = document.createElement("div"); +label.classList.add("sidebar__item-label"); +const labelText = document.createElement("div");// document.createTextNode(labelPort.get()); +label.appendChild(labelText); +el.appendChild(label); + +// events +parentPort.onChange = onParentChanged; +labelPort.onChange = onLabelTextChanged; +inId.onChange = onIdChanged; +op.onDelete = onDelete; + +op.toWorkNeedsParent("Ops.Sidebar.Sidebar"); + +// functions + +function onIdChanged() +{ + el.id = inId.get(); +} + +function onLabelTextChanged() +{ + const labelText = labelPort.get(); + label.innerHTML = labelText; + if (CABLES.UI) + { + if (labelText && typeof labelText === "string") + { + op.setTitle("Text: " + labelText.substring(0, 10)); // display first 10 characters of text in op title + } + else + { + op.setTitle("Text"); + } + } +} + +function onParentChanged() +{ + siblingsPort.set(null); + const parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(el); + siblingsPort.set(parent); + } + else + { // detach + if (el.parentElement) + { + el.parentElement.removeChild(el); + } + } +} + +function showElement(el) +{ + if (el) + { + el.style.display = "block"; + } +} + +function hideElement(el) +{ + if (el) + { + el.style.display = "none"; + } +} + +function onDelete() +{ + removeElementFromDOM(el); +} + +function removeElementFromDOM(el) +{ + if (el && el.parentNode && el.parentNode.removeChild) + { + el.parentNode.removeChild(el); + } +} + + +}; + +Ops.Sidebar.SidebarText_v2.prototype = new CABLES.Op(); +CABLES.OPS["cc591cc3-ff23-4817-907c-e5be7d5c059d"]={f:Ops.Sidebar.SidebarText_v2,objName:"Ops.Sidebar.SidebarText_v2"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.SidebarVariables +// +// ************************************************************** + +Ops.Sidebar.SidebarVariables = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// inputs +let parentPort = op.inObject("link"); +let inId = op.inValueString("Id", ""); +let inUpdate = op.inTriggerButton("update"); + +// outputs +let siblingsPort = op.outObject("childs"); + +// vars +let el = document.createElement("div"); +el.classList.add("sidebar__item"); +el.classList.add("sidebar__text"); +let label = document.createElement("div"); +// label.classList.add('sidebar__item-label'); + +el.appendChild(label); + +// events +parentPort.onChange = onParentChanged; +inUpdate.onTriggered = update; + +inId.onChange = onIdChanged; +op.onDelete = onDelete; + +op.toWorkNeedsParent("Ops.Sidebar.Sidebar"); + +update(); + +// functions + +function onIdChanged() +{ + el.id = inId.get(); +} + +function update() +{ + // var labelText = labelPort.get(); + // label.textContent = labelText; + // if(CABLES.UI) { + // if(labelText && typeof labelText === 'string') { + // op.setTitle('Text: ' + labelText.substring(0, 10)); // display first 10 characters of text in op title + // } else { + // op.setTitle('Text'); + // } + // } + + let vars = op.patch.getVars(); + let html = ""; + for (let ki in vars) + { + let v = vars[ki].getValue(); + + if (typeof v == "object") v = "[object]"; + html += ""; + } + html += "
" + ki + "" + v + "
"; + + label.innerHTML = html; +} + +function onParentChanged() +{ + siblingsPort.set(null); + let parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(el); + siblingsPort.set(parent); + } + else + { // detach + if (el.parentElement) + { + el.parentElement.removeChild(el); + } + } +} + +function showElement(el) +{ + if (el) + { + el.style.display = "block"; + } +} + +function hideElement(el) +{ + if (el) + { + el.style.display = "none"; + } +} + +function onDelete() +{ + removeElementFromDOM(el); +} + +function removeElementFromDOM(el) +{ + if (el && el.parentNode && el.parentNode.removeChild) + { + el.parentNode.removeChild(el); + } +} + + +}; + +Ops.Sidebar.SidebarVariables.prototype = new CABLES.Op(); +CABLES.OPS["55e502d6-0360-41aa-9c84-deb9f9e0be24"]={f:Ops.Sidebar.SidebarVariables,objName:"Ops.Sidebar.SidebarVariables"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.Slider_v3 +// +// ************************************************************** + +Ops.Sidebar.Slider_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// constants +const STEP_DEFAULT = 0.00001; + +// inputs +const parentPort = op.inObject("link"); +const labelPort = op.inString("Text", "Slider"); +const minPort = op.inValue("Min", 0); +const maxPort = op.inValue("Max", 1); +const stepPort = op.inValue("Step", STEP_DEFAULT); +const labelSuffix = op.inString("Suffix", ""); + +const inGreyOut = op.inBool("Grey Out", false); +const inVisible = op.inBool("Visible", true); + +const inputValuePort = op.inValue("Input", 0.5); +const setDefaultValueButtonPort = op.inTriggerButton("Set Default"); +const reset = op.inTriggerButton("Reset"); + +let parent = null; + +const defaultValuePort = op.inValue("Default", 0.5); +defaultValuePort.setUiAttribs({ "hidePort": true, "greyout": true }); + +// outputs +const siblingsPort = op.outObject("childs"); +const valuePort = op.outNumber("Result", defaultValuePort.get()); + +op.toWorkNeedsParent("Ops.Sidebar.Sidebar"); +op.setPortGroup("Range", [minPort, maxPort, stepPort]); +op.setPortGroup("Display", [inGreyOut, inVisible]); + +// vars +const el = document.createElement("div"); +el.addEventListener("dblclick", function () +{ + valuePort.set(parseFloat(defaultValuePort.get())); + inputValuePort.set(parseFloat(defaultValuePort.get())); +}); + +el.dataset.op = op.id; +el.classList.add("cablesEle"); + +el.classList.add("sidebar__item"); +el.classList.add("sidebar__slider"); +el.classList.add("sidebar__reloadable"); + +op.patch.on("sidebarStylesChanged", () => { updateActiveTrack(); }); + +const label = document.createElement("div"); +label.classList.add("sidebar__item-label"); + +const greyOut = document.createElement("div"); +greyOut.classList.add("sidebar__greyout"); +el.appendChild(greyOut); +greyOut.style.display = "none"; + +const labelText = document.createTextNode(labelPort.get()); +label.appendChild(labelText); +el.appendChild(label); + +const value = document.createElement("input"); +value.value = defaultValuePort.get(); +value.classList.add("sidebar__text-input-input"); +value.setAttribute("type", "text"); +value.oninput = onTextInputChanged; +el.appendChild(value); + +const suffixEle = document.createElement("span"); +// setValueFieldValue(defaultValuePort).get(); +// value.setAttribute("type", "text"); +// value.oninput = onTextInputChanged; + +el.appendChild(suffixEle); + +labelSuffix.onChange = () => +{ + suffixEle.innerHTML = labelSuffix.get(); +}; + +const inputWrapper = document.createElement("div"); +inputWrapper.classList.add("sidebar__slider-input-wrapper"); +el.appendChild(inputWrapper); + +const activeTrack = document.createElement("div"); +activeTrack.classList.add("sidebar__slider-input-active-track"); +inputWrapper.appendChild(activeTrack); +const input = document.createElement("input"); +input.classList.add("sidebar__slider-input"); +input.setAttribute("min", minPort.get()); +input.setAttribute("max", maxPort.get()); +input.setAttribute("type", "range"); +input.setAttribute("step", stepPort.get()); +input.setAttribute("value", defaultValuePort.get()); +input.style.display = "block"; /* needed because offsetWidth returns 0 otherwise */ +inputWrapper.appendChild(input); + +updateActiveTrack(); +input.addEventListener("input", onSliderInput); + +// events +parentPort.onChange = onParentChanged; +labelPort.onChange = onLabelTextChanged; +inputValuePort.onChange = onInputValuePortChanged; +defaultValuePort.onChange = onDefaultValueChanged; +setDefaultValueButtonPort.onTriggered = onSetDefaultValueButtonPress; +minPort.onChange = onMinPortChange; +maxPort.onChange = onMaxPortChange; +stepPort.onChange = stepPortChanged; +op.onDelete = onDelete; + +// op.onLoadedValueSet=function() +op.onLoaded = op.onInit = function () +{ + if (op.patch.config.sidebar) + { + op.patch.config.sidebar[labelPort.get()]; + valuePort.set(op.patch.config.sidebar[labelPort.get()]); + } + else + { + valuePort.set(parseFloat(defaultValuePort.get())); + inputValuePort.set(parseFloat(defaultValuePort.get())); + // onInputValuePortChanged(); + } +}; + +reset.onTriggered = function () +{ + const newValue = parseFloat(defaultValuePort.get()); + valuePort.set(newValue); + setValueFieldValue(newValue); + setInputFieldValue(newValue); + inputValuePort.set(newValue); + updateActiveTrack(); +}; + +inGreyOut.onChange = function () +{ + greyOut.style.display = inGreyOut.get() ? "block" : "none"; +}; + +inVisible.onChange = function () +{ + el.style.display = inVisible.get() ? "block" : "none"; +}; + +function onTextInputChanged(ev) +{ + let newValue = parseFloat(ev.target.value); + if (isNaN(newValue)) newValue = 0; + const min = minPort.get(); + const max = maxPort.get(); + if (newValue < min) { newValue = min; } + else if (newValue > max) { newValue = max; } + // setInputFieldValue(newValue); + valuePort.set(newValue); + updateActiveTrack(); + inputValuePort.set(newValue); + op.refreshParams(); +} + +function onInputValuePortChanged() +{ + let newValue = parseFloat(inputValuePort.get()); + const minValue = minPort.get(); + const maxValue = maxPort.get(); + if (newValue > maxValue) { newValue = maxValue; } + else if (newValue < minValue) { newValue = minValue; } + setValueFieldValue(newValue); + setInputFieldValue(newValue); + valuePort.set(newValue); + updateActiveTrack(); +} + +function onSetDefaultValueButtonPress() +{ + let newValue = parseFloat(inputValuePort.get()); + const minValue = minPort.get(); + const maxValue = maxPort.get(); + if (newValue > maxValue) { newValue = maxValue; } + else if (newValue < minValue) { newValue = minValue; } + setValueFieldValue(newValue); + setInputFieldValue(newValue); + valuePort.set(newValue); + defaultValuePort.set(newValue); + op.refreshParams(); + + updateActiveTrack(); +} + +function onSliderInput(ev) +{ + ev.preventDefault(); + ev.stopPropagation(); + setValueFieldValue(ev.target.value); + const inputFloat = parseFloat(ev.target.value); + valuePort.set(inputFloat); + inputValuePort.set(inputFloat); + op.refreshParams(); + + updateActiveTrack(); + return false; +} + +function stepPortChanged() +{ + const step = stepPort.get(); + input.setAttribute("step", step); + updateActiveTrack(); +} + +function updateActiveTrack(val) +{ + let valueToUse = parseFloat(input.value); + if (typeof val !== "undefined") valueToUse = val; + let availableWidth = activeTrack.parentElement.getBoundingClientRect().width || 220; + if (parent) availableWidth = parseInt(getComputedStyle(parent.parentElement).getPropertyValue("--sidebar-width")) - 20; + + const trackWidth = CABLES.map( + valueToUse, + parseFloat(input.min), + parseFloat(input.max), + 0, + availableWidth - 16 /* subtract slider thumb width */ + ); + activeTrack.style.width = trackWidth + "px"; +} + +function onMinPortChange() +{ + const min = minPort.get(); + input.setAttribute("min", min); + updateActiveTrack(); +} + +function onMaxPortChange() +{ + const max = maxPort.get(); + input.setAttribute("max", max); + updateActiveTrack(); +} + +function onDefaultValueChanged() +{ + const defaultValue = defaultValuePort.get(); + valuePort.set(parseFloat(defaultValue)); + onMinPortChange(); + onMaxPortChange(); + setInputFieldValue(defaultValue); + setValueFieldValue(defaultValue); + + updateActiveTrack(defaultValue); // needs to be passed as argument, is this async? +} + +function onLabelTextChanged() +{ + const labelText = labelPort.get(); + label.textContent = labelText; + if (CABLES.UI) op.setTitle("Slider: " + labelText); +} + +function onParentChanged() +{ + siblingsPort.set(null); + parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(el); + siblingsPort.set(parent); + } + else if (el.parentElement) el.parentElement.removeChild(el); + + updateActiveTrack(); +} + +function setValueFieldValue(v) +{ + value.value = v; +} + +function setInputFieldValue(v) +{ + input.value = v; +} + +function showElement(el) +{ + if (el)el.style.display = "block"; +} + +function hideElement(el) +{ + if (el)el.style.display = "none"; +} + +function onDelete() +{ + removeElementFromDOM(el); +} + +function removeElementFromDOM(el) +{ + if (el && el.parentNode && el.parentNode.removeChild) el.parentNode.removeChild(el); +} + + +}; + +Ops.Sidebar.Slider_v3.prototype = new CABLES.Op(); +CABLES.OPS["74730122-5cba-4d0d-b610-df334ec6220a"]={f:Ops.Sidebar.Slider_v3,objName:"Ops.Sidebar.Slider_v3"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.TextInput_v2 +// +// ************************************************************** + +Ops.Sidebar.TextInput_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + parentPort = op.inObject("Link"), + labelPort = op.inString("Text", "Text"), + defaultValuePort = op.inString("Default", ""), + inPlaceholder = op.inString("Placeholder", ""), + inType = op.inSwitch("Type", ["text", "password"], "text"), + inTextArea = op.inBool("TextArea", false), + inGreyOut = op.inBool("Grey Out", false), + inVisible = op.inBool("Visible", true), + inClear = op.inTriggerButton("Clear"), + siblingsPort = op.outObject("Children"), + valuePort = op.outString("Result", defaultValuePort.get()), + outFocus = op.outBool("Focus"); + +const el = document.createElement("div"); +el.dataset.op = op.id; +el.classList.add("cablesEle"); +el.classList.add("sidebar__item"); +el.classList.add("sidebar__text-input"); +el.classList.add("sidebar__reloadable"); + +const label = document.createElement("div"); +label.classList.add("sidebar__item-label"); +const labelText = document.createTextNode(labelPort.get()); +label.appendChild(labelText); +el.appendChild(label); + +label.addEventListener("dblclick", function () +{ + valuePort.set(defaultValuePort.get()); + input.value = defaultValuePort.get(); +}); + +let input = null; +creatElement(); + +op.toWorkPortsNeedToBeLinked(parentPort); + +inTextArea.onChange = creatElement; +inType.onChange = setAttribs; + +function setAttribs() +{ + input.setAttribute("type", inType.get()); + input.setAttribute("value", defaultValuePort.get()); + input.setAttribute("placeholder", inPlaceholder.get()); +} + +function creatElement() +{ + if (input)input.remove(); + if (!inTextArea.get()) + { + input = document.createElement("input"); + } + else + { + input = document.createElement("textarea"); + onDefaultValueChanged(); + } + + input.classList.add("sidebar__text-input-input"); + + setAttribs(); + + el.appendChild(input); + input.addEventListener("input", onInput); + input.addEventListener("focus", onFocus); + input.addEventListener("blur", onBlur); +} + +const greyOut = document.createElement("div"); +greyOut.classList.add("sidebar__greyout"); +el.appendChild(greyOut); +greyOut.style.display = "none"; + +inClear.onTriggered = () => +{ + input.value = ""; +}; + +function onFocus() +{ + outFocus.set(true); +} + +function onBlur() +{ + outFocus.set(false); +} + +inPlaceholder.onChange = () => +{ + input.setAttribute("placeholder", inPlaceholder.get()); +}; + +inGreyOut.onChange = function () +{ + greyOut.style.display = inGreyOut.get() ? "block" : "none"; +}; + +inVisible.onChange = function () +{ + el.style.display = inVisible.get() ? "block" : "none"; +}; + +// events +parentPort.onChange = onParentChanged; +labelPort.onChange = onLabelTextChanged; +defaultValuePort.onChange = onDefaultValueChanged; +op.onDelete = onDelete; + +// functions + +function onInput(ev) +{ + valuePort.set(ev.target.value); +} + +function onDefaultValueChanged() +{ + const defaultValue = defaultValuePort.get(); + valuePort.set(defaultValue); + input.value = defaultValue; +} + +function onLabelTextChanged() +{ + const labelText = labelPort.get(); + label.textContent = labelText; + if (CABLES.UI) + { + op.setTitle("Text Input: " + labelText); + } +} + +function onParentChanged() +{ + siblingsPort.set(null); + const parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(el); + siblingsPort.set(parent); + } + else + { // detach + if (el.parentElement) + { + el.parentElement.removeChild(el); + } + } +} + +function showElement(el) +{ + if (el) + { + el.style.display = "block"; + } +} + +function hideElement(el) +{ + if (el) + { + el.style.display = "none"; + } +} + +function onDelete() +{ + removeElementFromDOM(el); +} + +function removeElementFromDOM(el) +{ + if (el && el.parentNode && el.parentNode.removeChild) + { + el.parentNode.removeChild(el); + } +} + + +}; + +Ops.Sidebar.TextInput_v2.prototype = new CABLES.Op(); +CABLES.OPS["6538a190-e73c-451b-964e-d010ee267aa9"]={f:Ops.Sidebar.TextInput_v2,objName:"Ops.Sidebar.TextInput_v2"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.Toggle_v3 +// +// ************************************************************** + +Ops.Sidebar.Toggle_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const DEFAULT_VALUE_DEFAULT = true; + +// inputs +const parentPort = op.inObject("link"); +const labelPort = op.inString("Text", "Toggle"); +const inputValuePort = op.inValueBool("Input", DEFAULT_VALUE_DEFAULT); +const setDefaultValueButtonPort = op.inTriggerButton("Set Default"); +const defaultValuePort = op.inValueBool("Default", DEFAULT_VALUE_DEFAULT); +defaultValuePort.setUiAttribs({ "hidePort": true, "greyout": true }); +const inGreyOut = op.inBool("Grey Out", false); +const inVisible = op.inBool("Visible", true); + +// outputs +const siblingsPort = op.outObject("childs"); +const valuePort = op.outNumber("Value", defaultValuePort.get()); + +// vars +const el = document.createElement("div"); +el.dataset.op = op.id; +el.classList.add("cablesEle"); +el.classList.add("sidebar__item"); +el.classList.add("sidebar__toggle"); +el.classList.add("sidebar__reloadable"); + +if (DEFAULT_VALUE_DEFAULT) el.classList.add("sidebar__toggle--active"); + +el.addEventListener("dblclick", function () +{ + valuePort.set(defaultValuePort.get()); + inputValuePort.set(defaultValuePort.get()); +}); + +const label = document.createElement("div"); +label.classList.add("sidebar__item-label"); +const labelText = document.createTextNode(labelPort.get()); +label.appendChild(labelText); +el.appendChild(label); + +const icon = document.createElement("div"); +icon.classList.add("icon_toggle"); +icon.addEventListener("click", onInputClick); +el.appendChild(icon); + +const greyOut = document.createElement("div"); +greyOut.classList.add("sidebar__greyout"); +el.appendChild(greyOut); +greyOut.style.display = "none"; + +// events +parentPort.onChange = onParentChanged; +labelPort.onChange = onLabelTextChanged; +inputValuePort.onChange = onInputValuePortChanged; +op.onDelete = onDelete; +setDefaultValueButtonPort.onTriggered = setDefaultValue; + +function setDefaultValue() +{ + const defaultValue = inputValuePort.get(); + + defaultValuePort.set(defaultValue); + valuePort.set(defaultValue); + op.refreshParams(); +} + +function onInputClick() +{ + el.classList.toggle("sidebar__toggle--active"); + if (el.classList.contains("sidebar__toggle--active")) + { + valuePort.set(true); + inputValuePort.set(true); + icon.classList.add("icon_toggle_true"); + icon.classList.remove("icon_toggle_false"); + } + else + { + icon.classList.remove("icon_toggle_true"); + icon.classList.add("icon_toggle_false"); + + valuePort.set(false); + inputValuePort.set(false); + } + op.refreshParams(); +} + +function onInputValuePortChanged() +{ + const inputValue = inputValuePort.get(); + if (inputValue) + { + el.classList.add("sidebar__toggle--active"); + valuePort.set(true); + } + else + { + el.classList.remove("sidebar__toggle--active"); + valuePort.set(false); + } +} + +function onLabelTextChanged() +{ + const text = labelPort.get(); + label.textContent = text; + if (CABLES.UI) op.setTitle("Toggle: " + text); +} + +function onParentChanged() +{ + siblingsPort.set(null); + const parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(el); + siblingsPort.set(parent); + } + else if (el.parentElement) el.parentElement.removeChild(el); +} + +function showElement(element) +{ + if (element) element.style.display = "block"; +} + +function hideElement(element) +{ + if (element) element.style.display = "none"; +} + +function onDelete() +{ + removeElementFromDOM(el); +} + +function removeElementFromDOM(element) +{ + if (element && element.parentNode && element.parentNode.removeChild) element.parentNode.removeChild(el); +} + +inGreyOut.onChange = function () +{ + greyOut.style.display = inGreyOut.get() ? "block" : "none"; +}; + +inVisible.onChange = function () +{ + el.style.display = inVisible.get() ? "block" : "none"; +}; + + +}; + +Ops.Sidebar.Toggle_v3.prototype = new CABLES.Op(); +CABLES.OPS["fb60ab7d-f2f2-4fc5-bcd0-88c6ed481908"]={f:Ops.Sidebar.Toggle_v3,objName:"Ops.Sidebar.Toggle_v3"}; + + + + +// ************************************************************** +// +// Ops.Sidebar.XYPad +// +// ************************************************************** + +Ops.Sidebar.XYPad = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + parentPort = op.inObject("Link"), + labelPort = op.inString("Text", "XY Pad"), + inRange = op.inSwitch("Range", ["0-1", "-1-1"], "0-1"), + inputX = op.inValueSlider("Input X", 0), + inputY = op.inValueSlider("Input Y", 0), + + flipX = op.inBool("Flip X", false), + flipY = op.inBool("Flip Y", false), + + setDefaultValueButtonPort = op.inTriggerButton("Set Default"), + defaultValuePortX = op.inValueString("Default X", 0.5), + defaultValuePortY = op.inValueString("Default Y", 0.5), + + inVisible = op.inBool("Visible", true); + +const siblingsPort = op.outObject("Children"); + +defaultValuePortX.setUiAttribs({ "hidePort": true, "greyout": true }); +defaultValuePortY.setUiAttribs({ "hidePort": true, "greyout": true }); + +const outX = op.outNumber("X", 0.0); +const outY = op.outNumber("Y", 0.0); + +const el = document.createElement("div"); +el.dataset.op = op.id; +el.classList.add("cablesEle"); +el.addEventListener("dblclick", function () +{ + setOutValue(defaultValuePortX.get(), defaultValuePortY.get()); + redraw(); +}); + +el.classList.add("sidebar__item"); +el.classList.add("sidebar__color-picker"); +el.classList.add("sidebar__reloadable"); + +const label = document.createElement("div"); +label.classList.add("sidebar__item-label"); +const labelTextNode = document.createTextNode(labelPort.get()); +label.appendChild(labelTextNode); +el.appendChild(label); + +const valueX = document.createElement("input"); +valueX.classList.add("sidebar__text-input-input"); +valueX.setAttribute("type", "text"); +valueX.style.width = "40px"; +valueX.style.backgroundColor = "transparent"; +el.appendChild(valueX); + +const valueY = document.createElement("input"); +valueY.classList.add("sidebar__text-input-input"); +valueY.setAttribute("type", "text"); +valueY.style.width = "40px"; +valueY.style.backgroundColor = "transparent"; +el.appendChild(valueY); + +valueX.addEventListener("input", valueInputChanged); +valueY.addEventListener("input", valueInputChanged); +setDefaultValueButtonPort.onTriggered = setDefaultValues; + +inVisible.onChange = function () +{ + el.style.display = inVisible.get() ? "block" : "none"; +}; + +function valueInputChanged() +{ + let x = parseFloat(valueX.value); + let y = parseFloat(valueY.value); + + if (x != x || y != y) return; + + let minX = 0; + let maxX = 1; + let minY = 0; + let maxY = 1; + + x = Math.max(Math.min(x, maxX), minX); + y = Math.max(Math.min(y, maxY), minY); + + if (inRange.get() == "-1-1") + { + minY = minX = -1; + maxY = maxX = 1; + } + + setOutValue( + CABLES.map(x, minX, maxX, 0, 1), + CABLES.map(y, minY, maxY, 0, 1) + ); +} + +const size = 190; + +const canv = document.createElement("canvas"); +canv.width = canv.height = size; +canv.style.width = size + "px"; +canv.style.height = size + "px"; +canv.style.marginTop = "6px"; +canv.style.position = "initial"; +el.appendChild(canv); + +const ctx = canv.getContext("2d"); + +parentPort.onChange = onParentChanged; +labelPort.onChange = onLabelTextChanged; +op.onDelete = onDelete; + +inRange.onChange = () => +{ + setOutValue(defaultValuePortX.get(), defaultValuePortY.get()); + + redraw(); +}; + +redraw(); + +flipX.onChange = flipY.onChange = () => +{ + setOutValue(inputX.get(), inputY.get()); +}; + +canv.addEventListener("pointerdown", (e) => +{ + try { canv.setPointerCapture(e.pointerId); } + catch (e) {} +}); + +canv.addEventListener("pointerup", (e) => +{ + try { canv.releasePointerCapture(e.pointerId); } + catch (e) {} +}); + +inputX.onChange = () => +{ + // outX.set(Math.min(1, Math.max(inputX.get(), 0))); + setOutValue(inputX.get(), inputY.get()); + // redraw(); +}; + +inputY.onChange = () => +{ + // outY.set(Math.min(1, Math.max(inputY.get(), 0))); + setOutValue(inputX.get(), inputY.get()); + // redraw(); +}; + +function move(e) +{ + if (e.buttons == 1) + { + let x = Math.min(size, Math.max(e.offsetX, 0)); + let y = Math.min(size, Math.max(e.offsetY, 0)); + + if (e.shiftKey) + { + const s = size / 10; + x = Math.round(x / s) * s; + y = Math.round(y / s) * s; + } + + setOutValue(x / size, y / size); + inputX.set(x / size); + inputY.set(y / size); + op.refreshParams(); + } +} + +canv.addEventListener("pointermove", move, false); +canv.addEventListener("pointerdown", move, false); + +function setOutValue(x, y) +{ + inputX.set(x); + inputY.set(y); + + if (flipX.get())x = 1 - x; + if (flipY.get())y = 1 - y; + + let ox = x; + let oy = y; + + if (inRange.get() == "0-1") + { + outX.set(ox); + outY.set(oy); + } + else + { + outX.set(((ox) - 0.5) * 2.0); + outY.set(((oy) - 0.5) * 2.0); + } + + if (valueX.value != "" + outX.get()) valueX.value = "" + outX.get(); + if (valueY.value != "" + outY.get()) valueY.value = "" + outY.get(); + + redraw(); +} + +function redraw() +{ + ctx.lineWidth = 1; + ctx.strokeWidth = 1; + + ctx.clearRect(0, 0, size, size); + ctx.fillStyle = "#333"; + ctx.fillRect(0, 0, size, size); + + ctx.strokeStyle = "#555"; + ctx.strokeRect(0, size / 2, size, 0); + ctx.strokeRect(size / 2, 0, 0, size); + ctx.strokeRect(0, 0, size, size); + + ctx.strokeStyle = "#fff"; + ctx.beginPath(); + ctx.arc(inputX.get() * size, inputY.get() * size, 5, 0, Math.PI * 2, true); + ctx.stroke(); +} + +function setDefaultValues() +{ + // const hex = getInputColorHex(); + defaultValuePortY.set(inputY.get()); + defaultValuePortX.set(inputX.get()); + + setOutValue(defaultValuePortX.get(), defaultValuePortY.get()); + + // defaultValuePort.set(hex); + // outHex.set(hex); + + redraw(); + op.refreshParams(); +} + +function inputColorChanged() +{ + redraw(); +} + +function onLabelTextChanged() +{ + const labelText = labelPort.get(); + label.textContent = labelText; + + op.setUiAttrib({ "extendTitle": labelText }); +} + +function onParentChanged() +{ + siblingsPort.set(null); + const parent = parentPort.get(); + if (parent && parent.parentElement) + { + parent.parentElement.appendChild(el); + siblingsPort.set(parent); + } + else if (el.parentElement) el.parentElement.removeChild(el); +} + +function showElement(el) +{ + if (el) el.style.display = "block"; +} + +function hideElement(el) +{ + if (el) el.style.display = "none"; +} + +function onDelete() +{ + removeElementFromDOM(el); +} + +function removeElementFromDOM(el) +{ + if (el && el.parentNode && el.parentNode.removeChild) + { + el.parentNode.removeChild(el); + } +} + + +}; + +Ops.Sidebar.XYPad.prototype = new CABLES.Op(); +CABLES.OPS["84f3d05f-0991-4721-88cb-66776b16a094"]={f:Ops.Sidebar.XYPad,objName:"Ops.Sidebar.XYPad"}; + + + + +// ************************************************************** +// +// Ops.String.AddLineBreaks +// +// ************************************************************** + +Ops.String.AddLineBreaks = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr=op.inString("String",""), + inMaxLineChars=op.inInt("Max Characters per Line",20), + outStr=op.outString("Result"); + +inMaxLineChars.onChange= + inStr.onChange=update; + +function update() +{ + const str=inStr.get(); + if(!str) + { + outStr.set(""); + return; + } + + const numChars=inMaxLineChars.get(); + const parts=str.split(" "); + const lines=[]; + var line=""; + for(var i=0;inumChars) + { + lines.push(line); + line=""; + } + + line+=word; + } + lines.push(line); + outStr.set(lines.join("\n")); +} + + +}; + +Ops.String.AddLineBreaks.prototype = new CABLES.Op(); +CABLES.OPS["9746be6e-bf86-4a5f-86d9-d3b1c26d7f28"]={f:Ops.String.AddLineBreaks,objName:"Ops.String.AddLineBreaks"}; + + + + +// ************************************************************** +// +// Ops.String.ArrayContainsString +// +// ************************************************************** + +Ops.String.ArrayContainsString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array"), + inValue = op.inString("SearchValue"), + outFound = op.outBoolNum("Found", false), + outIndex = op.outNumber("Index", -1); + +inValue.onChange = () => +{ + op.setUiAttrib({ "extendTitle": inValue.get() }); + exec(); +}; + +inArr.onChange = exec; + +function exec() +{ + if (inArr.get()) + { + const index = inArr.get().indexOf(inValue.get()); + + outIndex.set(index); + outFound.set(index > -1); + } +} + + +}; + +Ops.String.ArrayContainsString.prototype = new CABLES.Op(); +CABLES.OPS["bace9c9b-5e96-4a82-9bcd-02e316afb9de"]={f:Ops.String.ArrayContainsString,objName:"Ops.String.ArrayContainsString"}; + + + + +// ************************************************************** +// +// Ops.String.ArrayOfStrings +// +// ************************************************************** + +Ops.String.ArrayOfStrings = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr = op.inString("String", "default"), + inLength = op.inInt("Length", 10), + inAttachNum = op.inBool("Attach Number", false), + outArr = op.outArray("Array"); + +inStr.onChange = + inLength.onChange = + inAttachNum.onChange = update; + +function update() +{ + let arr = []; + let str = inStr.get(); + let l = inLength.get(); + + if (inAttachNum.get()) + for (let i = 0; i < l; i++) + arr[i] = str + i; + else + for (let i = 0; i < l; i++) + arr[i] = str; + + outArr.set(arr); +} + + +}; + +Ops.String.ArrayOfStrings.prototype = new CABLES.Op(); +CABLES.OPS["846f9998-1c05-4757-8011-21020ed01c6d"]={f:Ops.String.ArrayOfStrings,objName:"Ops.String.ArrayOfStrings"}; + + + + +// ************************************************************** +// +// Ops.String.Base64Decode_v2 +// +// ************************************************************** + +Ops.String.Base64Decode_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let r = ""; +const + inString = op.inString("String"), + result = op.outString("Result"); +inString.onChange = function () +{ + result.set(b64DecodeUnicode(inString.get() || "")); +}; + +function b64DecodeUnicode(str) +{ + // Going backwards: from bytestream, to percent-encoding, to original string. + + if (str.indexOf("base64,") > 1) + { + str = str.substring(str.indexOf("base64,") + "base64,".length); + } + + let r = ""; + + try + { + r = decodeURIComponent(atob(str).split("").map(function (c) + { + return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2); + }).join("")); + } + catch (e) + { + op.error(e); + } + + return r; +} + + +}; + +Ops.String.Base64Decode_v2.prototype = new CABLES.Op(); +CABLES.OPS["4986a1d8-390f-48ee-aff4-c4257ddb480a"]={f:Ops.String.Base64Decode_v2,objName:"Ops.String.Base64Decode_v2"}; + + + + +// ************************************************************** +// +// Ops.String.Base64Encode_v2 +// +// ************************************************************** + +Ops.String.Base64Encode_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let inString = op.inString("String"); +let result = op.outString("Result"); + +inString.onChange = function () +{ + result.set(b64EncodeUnicode(inString.get())); +}; + +function b64EncodeUnicode(str) +{ + // first we use encodeURIComponent to get percent-encoded UTF-8, + // then we convert the percent encodings into raw bytes which + // can be fed into btoa. + return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, + function toSolidBytes(match, p1) + { + return String.fromCharCode("0x" + p1); + })); +} + + +}; + +Ops.String.Base64Encode_v2.prototype = new CABLES.Op(); +CABLES.OPS["e6ff2e1b-0c7a-4d0b-b1cf-720c2bbe3514"]={f:Ops.String.Base64Encode_v2,objName:"Ops.String.Base64Encode_v2"}; + + + + +// ************************************************************** +// +// Ops.String.CharacterRotate +// +// ************************************************************** + +Ops.String.CharacterRotate = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inUpdate = op.inTriggerButton("Update"), + inReset = op.inTriggerButton("Reset"), + inText = op.inString("Text"), + inSeed = op.inFloat("Random Seed", 0), + inChars = op.inString("Characters", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 -_+!"), + result = op.outString("Result"); + +let positions = []; +let position = 0; +let resultString = ""; + +inSeed.onChange = init; +inText.onChange = init; +inReset.onTriggered = init; + +function init() +{ + position++; + let txt = inText.get(); + if (!txt) + { + result.set(""); + return; + } + let alphab = inChars.get(); + + resultString = ""; + + Math.randomSeed = inSeed.get(); + + for (let i = 0; i < txt.length; i++) + { + if (inSeed.get() == 0) + { + resultString += alphab[0]; + } + else + { + resultString += alphab[Math.floor(Math.seededRandom() * alphab.length)]; + } + } + + result.set(resultString); +} + +inUpdate.onTriggered = function () +{ + let txt = inText.get(); + let alphab = inChars.get(); + + if (!txt) + { + result.set(""); + return; + } + + if (!resultString) init(); + let newStr = ""; + + for (let i = 0; i < txt.length; i++) + { + if (txt[i] == "\n") + { + newStr += "\n"; + } + else + if (txt[i] != resultString[i]) + { + let newindex = alphab.indexOf(resultString[i]) + 1; + + if (newindex > alphab.length - 1)newindex = 0; + newStr += alphab[newindex]; + } + else + { + newStr += txt[i]; + } + } + resultString = newStr; + + result.set(resultString); +}; + + +}; + +Ops.String.CharacterRotate.prototype = new CABLES.Op(); +CABLES.OPS["9dcc7ad1-c790-4c9d-9f2a-a902bd8d6cc8"]={f:Ops.String.CharacterRotate,objName:"Ops.String.CharacterRotate"}; + + + + +// ************************************************************** +// +// Ops.String.ConcatMulti_v2 +// +// ************************************************************** + +Ops.String.ConcatMulti_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const addSpacesCheckBox = op.inBool("add spaces", false), + newLinesCheckBox = op.inBool("new lines", false), + stringPorts = [], + result = op.outString("concat string"); + +stringPorts.onChange = addSpacesCheckBox.onChange = +newLinesCheckBox.onChange = update; + +addSpacesCheckBox.setUiAttribs({ "hidePort": true }); +newLinesCheckBox.setUiAttribs({ "hidePort": true }); + +for (let i = 0; i < 8; i++) +{ + let p = op.inString("string " + i); + stringPorts.push(p); + p.onChange = update; +} + +function update() +{ + let str = ""; + let nl = ""; + let space = addSpacesCheckBox.get(); + + for (let i = 0; i < stringPorts.length; i++) + { + const inString = stringPorts[i].get(); + if (!inString) continue; + if (i > 0 && space) str += " "; + if (i > 0 && newLinesCheckBox.get()) nl = "\n"; + str += nl; + str += inString; + } + result.set(str); +} + + +}; + +Ops.String.ConcatMulti_v2.prototype = new CABLES.Op(); +CABLES.OPS["bc110e48-812d-489d-b1b3-b09c644c6982"]={f:Ops.String.ConcatMulti_v2,objName:"Ops.String.ConcatMulti_v2"}; + + + + +// ************************************************************** +// +// Ops.String.Concat_v2 +// +// ************************************************************** + +Ops.String.Concat_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + string1 = op.inString("string1", "ABC"), + string2 = op.inString("string2", "XYZ"), + newLine = op.inValueBool("New Line", false), + result = op.outString("result"); + +newLine.onChange = string2.onChange = string1.onChange = exec; +exec(); + +function exec() +{ + let s1 = string1.get(); + let s2 = string2.get(); + if (!s1 && !s2) + { + result.set(""); + return; + } + if (!s1)s1 = ""; + if (!s2)s2 = ""; + + let nl = ""; + if (s1 && s2 && newLine.get())nl = "\n"; + result.set(String(s1) + nl + String(s2)); +} + + +}; + +Ops.String.Concat_v2.prototype = new CABLES.Op(); +CABLES.OPS["a52722aa-0ca9-402c-a844-b7e98a6c6e60"]={f:Ops.String.Concat_v2,objName:"Ops.String.Concat_v2"}; + + + + +// ************************************************************** +// +// Ops.String.CopyToClipboard +// +// ************************************************************** + +Ops.String.CopyToClipboard = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inCopy= op.inTriggerButton("Copy"), + inStr=op.inString("String","cablez"); + +inCopy.onTriggered=()=> +{ + navigator.clipboard.writeText(inStr.get()); +}; + + +}; + +Ops.String.CopyToClipboard.prototype = new CABLES.Op(); +CABLES.OPS["283c7eef-680b-45f2-880a-5d9f0762854b"]={f:Ops.String.CopyToClipboard,objName:"Ops.String.CopyToClipboard"}; + + + + +// ************************************************************** +// +// Ops.String.FilterValidString +// +// ************************************************************** + +Ops.String.FilterValidString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr = op.inString("String", ""), + checkNull = op.inBool("Invalid if null", true), + checkUndefined = op.inBool("Invalid if undefined", true), + checkEmpty = op.inBool("Invalid if empty", true), + checkZero = op.inBool("Invalid if 0", true), + outStr = op.outString("Last Valid String"), + result = op.outBoolNum("Is Valid"); + +inStr.onChange = +checkNull.onChange = +checkUndefined.onChange = +checkEmpty.onChange = +function () +{ + const str = inStr.get(); + let r = true; + + if (r === false)r = false; + if (r && checkZero.get() && (str === 0 || str === "0")) r = false; + if (r && checkNull.get() && str === null) r = false; + if (r && checkUndefined.get() && str === undefined) r = false; + if (r && checkEmpty.get() && str === "") r = false; + + result.set(r); + if (r)outStr.set(str); +}; + + +}; + +Ops.String.FilterValidString.prototype = new CABLES.Op(); +CABLES.OPS["a522235d-f220-46ea-bc26-13a5b20ec8c6"]={f:Ops.String.FilterValidString,objName:"Ops.String.FilterValidString"}; + + + + +// ************************************************************** +// +// Ops.String.GateString +// +// ************************************************************** + +Ops.String.GateString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + valueInPort = op.inString('String In', 'hello'), + passThroughPort = op.inValueBool('Pass Through',false), + valueOutPort = op.outString('String Out',''); + +valueInPort.onChange = +passThroughPort.onChange = update; + +function update() +{ + if(passThroughPort.get()) + { + valueOutPort.set(null); + valueOutPort.set(valueInPort.get()); + } + // else + // valueOutPort.set(''); +} + +}; + +Ops.String.GateString.prototype = new CABLES.Op(); +CABLES.OPS["0ce14933-2d91-4381-9d82-2304aae22c0e"]={f:Ops.String.GateString,objName:"Ops.String.GateString"}; + + + + +// ************************************************************** +// +// Ops.String.LeftPad_v2 +// +// ************************************************************** + +Ops.String.LeftPad_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let val = op.inString("Value", 1); +let char = op.inString("Char", "0"); +let num = op.inInt("Num", 4); +let out = op.outString("String"); + +val.onChange = update; +char.onChange = update; +num.onChange = update; + +function update() +{ + let v = val.get(); + let n = num.get(); + + let pad = ""; + for (let i = 0; i < n; i++)pad += ("" + char.get()); + + let str = v + ""; + str = pad.substring(0, pad.length - str.length) + str; + + out.set(str); +} + + +}; + +Ops.String.LeftPad_v2.prototype = new CABLES.Op(); +CABLES.OPS["da8aba9f-9e9c-4fca-87c9-2726b6e101e2"]={f:Ops.String.LeftPad_v2,objName:"Ops.String.LeftPad_v2"}; + + + + +// ************************************************************** +// +// Ops.String.LimitLineBreaks_v2 +// +// ************************************************************** + +Ops.String.LimitLineBreaks_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr = op.inString("String", "default"), + inNum = op.inInt("Num Lines", 5), + inRev = op.inBool("Reverse", false), + inAppend = op.inBool("Force Num Lines", false), + outStr = op.outString("Result", "default"); + +let stringsNew = []; + +inRev.onChange = + inAppend.onChange = + inStr.onChange = + inNum.onChange = update; + +function update() +{ + let strings = inStr.get().split("\n"); + var num = num = Math.max(0, Math.floor(inNum.get()) + 1); + + if (inRev.get()) + { + if (strings.length > num) + { + for (var i = 0; i < num; i++) + stringsNew[num - i] = strings[strings.length - i]; + + strings = stringsNew; + } + } + else + { + strings.length = Math.min(num, strings.length); + } + + let str = strings.join("\n"); + + if (inAppend.get()) + { + if (strings.length < num) + for (var i = strings.length; i < num; i++) + str += "\n"; + } + + outStr.set(str); +} + + +}; + +Ops.String.LimitLineBreaks_v2.prototype = new CABLES.Op(); +CABLES.OPS["fcf0f2a3-42db-485c-8c0b-15c5eb1f18c7"]={f:Ops.String.LimitLineBreaks_v2,objName:"Ops.String.LimitLineBreaks_v2"}; + + + + +// ************************************************************** +// +// Ops.String.LineBreaksHtml +// +// ************************************************************** + +Ops.String.LineBreaksHtml = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr=op.inString("String",""), + inNum=op.inInt("Add Num Breaks",1), + outStr=op.outString("HTML"); + +inNum.onChange= +inStr.onChange=function() +{ + var str=inStr.get(); + var newlines=''; + + for(var i=0;i
')); + + +}; + +Ops.String.LoremIpsum.prototype = new CABLES.Op(); +CABLES.OPS["c19ebc53-82d5-429c-a6cc-ff350a2c5d3e"]={f:Ops.String.LoremIpsum,objName:"Ops.String.LoremIpsum"}; + + + + +// ************************************************************** +// +// Ops.String.Lowercase_v2 +// +// ************************************************************** + +Ops.String.Lowercase_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr = op.inString("String"), + outStr = op.outString("Result", ""); + +inStr.onChange = function () +{ + if (inStr.get() == 0)outStr.set(""); + else outStr.set((inStr.get() || "").toLowerCase()); +}; + + +}; + +Ops.String.Lowercase_v2.prototype = new CABLES.Op(); +CABLES.OPS["bff9c3d9-e63a-46d2-a59f-932c715aceab"]={f:Ops.String.Lowercase_v2,objName:"Ops.String.Lowercase_v2"}; + + + + +// ************************************************************** +// +// Ops.String.NumTotalLineBreaks +// +// ************************************************************** + +Ops.String.NumTotalLineBreaks = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr=op.inString("String","default"), + outNum=op.outNumber("Total Lines",0); + + +inStr.onChange=function() +{ + var strings=inStr.get().split('\n'); + outNum.set(strings.length); + + +}; + +}; + +Ops.String.NumTotalLineBreaks.prototype = new CABLES.Op(); +CABLES.OPS["76a958cd-def3-40e5-ab2b-c08a3325d9cb"]={f:Ops.String.NumTotalLineBreaks,objName:"Ops.String.NumTotalLineBreaks"}; + + + + +// ************************************************************** +// +// Ops.String.NumberFormatter +// +// ************************************************************** + +Ops.String.NumberFormatter = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inNum = op.inFloat("Input Number"); +const inLocaleSwitch = op.inSwitch("Locale", ["browser", "custom"], "browser"); +const inLocaleString = op.inString("Locale string", "en-US"); +const inStyle = op.inSwitch("Style", ["decimal", "currency", "percent"], "decimal"); +const inMinDig = op.inInt("Minimum Integer Digits", 1); +const inMinFrac = op.inInt("Minimum Fraction Digits", 3); +const inMaxFrac = op.inInt("Maximum Fraction Digits", 3); +op.setPortGroup("Format", [inMinDig, inMinFrac, inMaxFrac]); +const inMinSign = op.inInt("Minimum Significant Digits", 0); +const inMaxSign = op.inInt("Maximum Significant Digits", 0); +op.setPortGroup("Significant Digits", [inMaxSign, inMinSign]); +const inUseGroup = op.inBool("Use Grouping", true); + +const inCurrencyName = op.inString("Currency Name", "EUR"); +const inCurrencyDisplay = op.inSwitch("Currency Display", ["symbol", "code", "name"], "symbol"); +op.setPortGroup("Currency", [inCurrencyName, inCurrencyDisplay]); + +const outString = op.outString("Formatted Number", "0,000"); +const outError = op.outBoolNum("Has error"); + +// Bind functions +inNum.onChange = inLocaleString.onChange = +inStyle.onChange = inMaxFrac.onChange = +inMaxSign.onChange = inMinFrac.onChange = +inMinDig.onChange = inMinSign.onChange = +inUseGroup.onChange = inCurrencyName.onChange = +inCurrencyDisplay.onChange = inLocaleSwitch.onChange = formatNumber; + +function formatNumber() +{ + const num = inNum.get(); + const style = inStyle.get(); + + let minimumFractionDigits = CABLES.clamp(inMinFrac.get(), 0, 20); + let maximumFractionDigits = CABLES.clamp(inMaxFrac.get(), 0, 20); + + op.setUiError("minmaxfrac", null); + if(minimumFractionDigits > maximumFractionDigits) { + op.setUiError("minmaxfrac", "Minimum bigger than maximum for fraction digits, using minimum", 1); + maximumFractionDigits = minimumFractionDigits; + } + + let opts = { + "style": style, + "minimumFractionDigits": minimumFractionDigits, + "maximumFractionDigits": maximumFractionDigits, + "minimumIntegerDigits": CABLES.clamp(inMinDig.get(), 1, 21), + "useGrouping": inUseGroup.get() + }; + + if (inMinSign.get() > 0) opts.minimumSignificantDigits = CABLES.clamp(inMinSign.get(), 1, 21); + if (inMaxSign.get() > 0) opts.maximumSignificantDigits = CABLES.clamp(inMaxSign.get(), 1, 21); + + + op.setUiError("minmaxsig", null); + if(opts.minimumSignificantDigits > opts.maximumSignificantDigits) { + op.setUiError("minmaxsig", "Minimum bigger than maximum for significant digits, using minimum", 1); + opts.maximumSignificantDigits = opts.minimumSignificantDigits; + } + + if (style === "currency") + { + opts.currency = inCurrencyName.get(); + opts.currencyDisplay = inCurrencyDisplay.get(); + } + + try + { + let res = ""; + if (inLocaleSwitch.get() === "browser") + res = num.toLocaleString([], opts); + else + res = num.toLocaleString(inLocaleString.get(), opts); + + outString.set(res); + + if (outError.get()) + op.setUiError("format_error", null); + outError.set(false); + } + catch (e) + { + outError.set(true); + outString.set(""); + op.setUiError("format_error", e); + } +} + + +}; + +Ops.String.NumberFormatter.prototype = new CABLES.Op(); +CABLES.OPS["fb2ac304-5c36-419c-ba71-cdf43aed8a53"]={f:Ops.String.NumberFormatter,objName:"Ops.String.NumberFormatter"}; + + + + +// ************************************************************** +// +// Ops.String.NumberSwitchByString +// +// ************************************************************** + +Ops.String.NumberSwitchByString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inStr = op.inString("String", "default"); +const outNum = op.outNumber("Result", 0); +const numberStrings = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]; + +const strings = []; +const numbers = []; + +inStr.onChange = update; + +for (let i = 0; i < numberStrings.length; i++) +{ + const idx = i + 1; + const istr = op.inString("String " + idx, numberStrings[i]); + const inum = op.inFloat("Number " + idx, idx); + + strings.push(istr); + numbers.push(inum); +} + +function update() +{ + const s = inStr.get(); + + for (let i = 0; i < numberStrings.length; i++) + { + if (strings[i].get() == s)outNum.set(numbers[i].get()); + } +} + + +}; + +Ops.String.NumberSwitchByString.prototype = new CABLES.Op(); +CABLES.OPS["bb3f53ab-c4ad-4c07-81df-d9ca7ee976f2"]={f:Ops.String.NumberSwitchByString,objName:"Ops.String.NumberSwitchByString"}; + + + + +// ************************************************************** +// +// Ops.String.NumberToString_v2 +// +// ************************************************************** + +Ops.String.NumberToString_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + val = op.inValue("Number"), + result = op.outString("Result"); + +val.onChange = update; +update(); + +function update() +{ + result.set(String(val.get() || 0)); +} + + +}; + +Ops.String.NumberToString_v2.prototype = new CABLES.Op(); +CABLES.OPS["5c6d375a-82db-4366-8013-93f56b4061a9"]={f:Ops.String.NumberToString_v2,objName:"Ops.String.NumberToString_v2"}; + + + + +// ************************************************************** +// +// Ops.String.OrString +// +// ************************************************************** + +Ops.String.OrString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + str0=op.inString("String 1"), + str1=op.inString("String 2"), + str2=op.inString("String 3"), + str3=op.inString("String 4"), + str4=op.inString("String 5"), + str5=op.inString("String 6"), + str6=op.inString("String 7"), + str7=op.inString("String 8"), + result=op.outString("Result"); + +str0.onChange= + str1.onChange= + str2.onChange= + str3.onChange= + str4.onChange= + str5.onChange= + str6.onChange= + str7.onChange=exec; + +function exec() +{ + result.set( str0.get() || str1.get() || str2.get() || str3.get() || str4.get() || str5.get() || str6.get() || str7.get() ); +} + + + +}; + +Ops.String.OrString.prototype = new CABLES.Op(); +CABLES.OPS["6b7f9561-6faf-4df7-ac3b-64235dded700"]={f:Ops.String.OrString,objName:"Ops.String.OrString"}; + + + + +// ************************************************************** +// +// Ops.String.ParseFloat +// +// ************************************************************** + +Ops.String.ParseFloat = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + str = op.inString("String", 5711), + outNum = op.outNumber("Number"); + +str.onChange = function () +{ + let num = parseFloat(str.get()); + if (num != num) num = 0; + outNum.set(num); +}; + + +}; + +Ops.String.ParseFloat.prototype = new CABLES.Op(); +CABLES.OPS["fa36a56b-a64d-4269-9a9e-addc16493006"]={f:Ops.String.ParseFloat,objName:"Ops.String.ParseFloat"}; + + + + +// ************************************************************** +// +// Ops.String.ParseInt_v2 +// +// ************************************************************** + +Ops.String.ParseInt_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + str = op.inString("String", 5711), + outNum = op.outNumber("Number"); + +str.onChange = function () +{ + let num = parseInt(str.get()); + if (num != num) num = 0; + outNum.set(num); +}; + + +}; + +Ops.String.ParseInt_v2.prototype = new CABLES.Op(); +CABLES.OPS["6d208424-daf2-4a2b-874f-daac406c1f66"]={f:Ops.String.ParseInt_v2,objName:"Ops.String.ParseInt_v2"}; + + + + +// ************************************************************** +// +// Ops.String.RandomString_v2 +// +// ************************************************************** + +Ops.String.RandomString_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + chars = op.inString("chars", "cables"), + len = op.inInt("Length", 10), + generate = op.inTriggerButton("Generate"), + result = op.outString("Result"); + +generate.onTriggered = gen; +gen(); + +function gen() +{ + const charArray = Array.from(chars.get()); + let str = ""; + if (charArray.length > 0) + { + let numChars = charArray.length - 1; + for (let i = 0; i < Math.abs(len.get()); i++) + str += charArray[Math.round(Math.random() * numChars)]; + } + + result.set(str); +} + + +}; + +Ops.String.RandomString_v2.prototype = new CABLES.Op(); +CABLES.OPS["55285d4a-f542-4c8b-9839-02b33b15c916"]={f:Ops.String.RandomString_v2,objName:"Ops.String.RandomString_v2"}; + + + + +// ************************************************************** +// +// Ops.String.RightPadNumber_v2 +// +// ************************************************************** + +Ops.String.RightPadNumber_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const val=op.inValue("Value",1); +const num=op.inValueInt("Num",4); +const out=op.outString("String"); + +val.onChange=update; +num.onChange=update; + +function update() +{ + var str=val.get()+''; + + var start=str.indexOf("."); + var numChars=num.get(); + + if(start==-1) + { + str+='.'; + } + else + { + var parts=str.split("."); + numChars=num.get()-parts[1].length; + } + + for(var i=0;i port.set(defaultValue)); +}; + +function update() +{ + setDefaultValues(); + var index = indexPort.get(); + var value = valuePort.get(); + index = Math.round(index); + index = clamp(index, 0, NUM_PORTS-1); + valuePorts[index].set(value); +}; + +function clamp(value, min, max) +{ + return Math.min(Math.max(value, min), max); +}; + + +}; + +Ops.String.RouteString.prototype = new CABLES.Op(); +CABLES.OPS["9998ff83-335b-40cd-aa0e-4cae558cb551"]={f:Ops.String.RouteString,objName:"Ops.String.RouteString"}; + + + + +// ************************************************************** +// +// Ops.String.SaveTextFile +// +// ************************************************************** + +Ops.String.SaveTextFile = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + download = op.inTriggerButton("Download"), + filename = op.inString("Filename", "textfile.txt"), + inStr = op.inString("Content String"); + +download.onTriggered = function () +{ + const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(inStr.get()); + const downloadAnchorNode = document.createElement("a"); + downloadAnchorNode.setAttribute("href", dataStr); + downloadAnchorNode.setAttribute("download", filename.get() ); + downloadAnchorNode.click(); + downloadAnchorNode.remove(); +}; + + +}; + +Ops.String.SaveTextFile.prototype = new CABLES.Op(); +CABLES.OPS["ef5929f0-8163-460b-9042-6f20f4f7150b"]={f:Ops.String.SaveTextFile,objName:"Ops.String.SaveTextFile"}; + + + + +// ************************************************************** +// +// Ops.String.StringCompose_v3 +// +// ************************************************************** + +Ops.String.StringCompose_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + format=op.inString('Format',"hello $a, $b $c und $d"), + a=op.inString('String A','world'), + b=op.inString('String B',1), + c=op.inString('String C',2), + d=op.inString('String D',3), + e=op.inString('String E'), + f=op.inString('String F'), + result=op.outString("Result"); + +format.onChange= + a.onChange= + b.onChange= + c.onChange= + d.onChange= + e.onChange= + f.onChange=update; + +update(); + +function update() +{ + var str=format.get()||''; + if(typeof str!='string') + str=''; + + str = str.replace(/\$a/g, a.get()); + str = str.replace(/\$b/g, b.get()); + str = str.replace(/\$c/g, c.get()); + str = str.replace(/\$d/g, d.get()); + str = str.replace(/\$e/g, e.get()); + str = str.replace(/\$f/g, f.get()); + + result.set(str); +} + +}; + +Ops.String.StringCompose_v3.prototype = new CABLES.Op(); +CABLES.OPS["6afea9f4-728d-4f3c-9e75-62ddc1448bf0"]={f:Ops.String.StringCompose_v3,objName:"Ops.String.StringCompose_v3"}; + + + + +// ************************************************************** +// +// Ops.String.StringContains_v2 +// +// ************************************************************** + +Ops.String.StringContains_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr = op.inString("String"), + inValue = op.inString("SearchValue"), + outFound = op.outBoolNum("Found", false), + outIndex = op.outNumber("Index", -1); + +inValue.onChange = + inStr.onChange = exec; + +exec(); + +function exec() +{ + if (inStr.get() && inValue.get().length > 0) + { + const index = inStr.get().indexOf(inValue.get()); + outIndex.set(index); + outFound.set(index > -1); + } + else + { + outIndex.set(-1); + outFound.set(false); + } +} + + +}; + +Ops.String.StringContains_v2.prototype = new CABLES.Op(); +CABLES.OPS["2ca3e5d7-e6b4-46a7-8381-3fe1ad8b6879"]={f:Ops.String.StringContains_v2,objName:"Ops.String.StringContains_v2"}; + + + + +// ************************************************************** +// +// Ops.String.StringEditor +// +// ************************************************************** + +Ops.String.StringEditor = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + v = op.inStringEditor("value", ""), + syntax = op.inValueSelect("Syntax", ["text", "glsl", "css", "html", "xml", "json", "javascript", "inline-css", "sql"], "text"), + result = op.outString("Result"); + +syntax.onChange = updateSyntax; + +function updateSyntax() +{ + let s = syntax.get(); + if (s == "javascript")s = "js"; + v.setUiAttribs({ "editorSyntax": s }); +} + +v.onChange = function () +{ + result.set(v.get()); +}; + + +}; + +Ops.String.StringEditor.prototype = new CABLES.Op(); +CABLES.OPS["6468b7c1-f63e-4db4-b809-4b203d27ead3"]={f:Ops.String.StringEditor,objName:"Ops.String.StringEditor"}; + + + + +// ************************************************************** +// +// Ops.String.StringEquals +// +// ************************************************************** + +Ops.String.StringEquals = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + str1 = op.inString("String 1"), + str2 = op.inString("String 2"), + result = op.outBoolNum("Result"); + +str1.onChange = +str2.onChange = + function () + { + result.set(str1.get() == str2.get()); + }; + + +}; + +Ops.String.StringEquals.prototype = new CABLES.Op(); +CABLES.OPS["ef15195a-760b-4ac5-9630-322b0ba7b722"]={f:Ops.String.StringEquals,objName:"Ops.String.StringEquals"}; + + + + +// ************************************************************** +// +// Ops.String.StringIterator_v2 +// +// ************************************************************** + +Ops.String.StringIterator_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inExe = op.inTrigger("Exec"), + inString = op.inString("String", "cables"), + next = op.outTrigger("Next"), + outChar = op.outString("Character"), + outIndex = op.outNumber("Index"), + outLength = op.outNumber("Length"); + +inExe.onTriggered = function () +{ + let str = inString.get(); + outLength.set(str.length); + + for (let i = 0; i < str.length; i++) + { + outChar.set(str[i]); + outIndex.set(i); + next.trigger(); + } +}; + + +}; + +Ops.String.StringIterator_v2.prototype = new CABLES.Op(); +CABLES.OPS["2def6fdb-de39-4f56-9818-05b7a302583c"]={f:Ops.String.StringIterator_v2,objName:"Ops.String.StringIterator_v2"}; + + + + +// ************************************************************** +// +// Ops.String.StringLength_v2 +// +// ************************************************************** + +Ops.String.StringLength_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr = op.inString("String"), + result = op.outNumber("Result"); + +inStr.onChange = function () +{ + if (!inStr.get()) result.set(0); + else result.set(String(inStr.get()).length); +}; + + +}; + +Ops.String.StringLength_v2.prototype = new CABLES.Op(); +CABLES.OPS["aa47bb8b-d5d7-4175-b217-ab0157d3365d"]={f:Ops.String.StringLength_v2,objName:"Ops.String.StringLength_v2"}; + + + + +// ************************************************************** +// +// Ops.String.StringReplace +// +// ************************************************************** + +Ops.String.StringReplace = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr = op.inString("String"), + inSearch = op.inString("Search For", "foo"), + inRepl = op.inString("Replace", "bar"), + inWhat = op.inSwitch("Replace What", ["All", "First"], "All"), + outStr = op.outString("Result"); + +inRepl.onChange = +inStr.onChange = +inWhat.onChange = +inSearch.onChange = update; + +function update() +{ + let str = ""; + + if (inWhat.get() == "All") str = String(inStr.get()).replace(new RegExp(inSearch.get(), "g"), inRepl.get()); + else str = String(inStr.get()).replace(inSearch.get(), inRepl.get()); + + outStr.set(str); +} + + +}; + +Ops.String.StringReplace.prototype = new CABLES.Op(); +CABLES.OPS["4a053e7a-6b00-4e71-bd51-90cdb190994c"]={f:Ops.String.StringReplace,objName:"Ops.String.StringReplace"}; + + + + +// ************************************************************** +// +// Ops.String.StringTrim_v2 +// +// ************************************************************** + +Ops.String.StringTrim_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr=op.inString("String"), + outStr=op.outString("Result",''); + +inStr.onChange=function() +{ + if(!inStr.get())outStr.set(''); + else outStr.set(inStr.get().trim()); +}; + + +}; + +Ops.String.StringTrim_v2.prototype = new CABLES.Op(); +CABLES.OPS["a9aed302-328a-4d33-bd3f-27e3e6690b9e"]={f:Ops.String.StringTrim_v2,objName:"Ops.String.StringTrim_v2"}; + + + + +// ************************************************************** +// +// Ops.String.String_v2 +// +// ************************************************************** + +Ops.String.String_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + v=op.inString("value",""), + result=op.outString("String"); + +v.onChange=function() +{ + result.set(v.get()); +}; + + + +}; + +Ops.String.String_v2.prototype = new CABLES.Op(); +CABLES.OPS["d697ff82-74fd-4f31-8f54-295bc64e713d"]={f:Ops.String.String_v2,objName:"Ops.String.String_v2"}; + + + + +// ************************************************************** +// +// Ops.String.StripHtml +// +// ************************************************************** + +Ops.String.StripHtml = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr = op.inString("String", ""), + outStr = op.outString("Result"); + +inStr.onChange = function () +{ + // outStr.set((inStr.get() || "").replace(/(<([^>]+)>)/ig, "")); + + const parser = new DOMParser(); + const dom = parser.parseFromString(inStr.get(), "text/html"); + + outStr.set(dom.body.textContent); +}; + + +}; + +Ops.String.StripHtml.prototype = new CABLES.Op(); +CABLES.OPS["8a868fc7-363f-4221-9789-67ffe5830e36"]={f:Ops.String.StripHtml,objName:"Ops.String.StripHtml"}; + + + + +// ************************************************************** +// +// Ops.String.SubString_v2 +// +// ************************************************************** + +Ops.String.SubString_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr=op.inString("String","cables"), + inStart=op.inValueInt("Start",0), + inEnd=op.inValueInt("End",4), + result=op.outString("Result"); + +inStr.onChange= + inStart.onChange= + inEnd.onChange=update; + +update(); + +function update() +{ + var start=inStart.get(); + var end=inEnd.get(); + var str=inStr.get()+''; + result.set( str.substring(start,end) ); +} + +}; + +Ops.String.SubString_v2.prototype = new CABLES.Op(); +CABLES.OPS["6e994ba8-01d1-4da6-98b4-af7e822a2e6c"]={f:Ops.String.SubString_v2,objName:"Ops.String.SubString_v2"}; + + + + +// ************************************************************** +// +// Ops.String.SwitchString +// +// ************************************************************** + +Ops.String.SwitchString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + idx=op.inValueInt("Index"), + result=op.outString("Result"); + +const valuePorts=[]; + +idx.onChange=update; + +for(var i=0;i<10;i++) +{ + var p=op.inString("String "+i); + valuePorts.push( p ); + p.onChange=update; +} + +function update() +{ + if(idx.get()>=0 && valuePorts[idx.get()]) + { + result.set( valuePorts[idx.get()].get() ); + } +} + +}; + +Ops.String.SwitchString.prototype = new CABLES.Op(); +CABLES.OPS["2a7a0c68-f7c9-4249-b19a-d2de5cb4862c"]={f:Ops.String.SwitchString,objName:"Ops.String.SwitchString"}; + + + + +// ************************************************************** +// +// Ops.String.SwitchStringBoolean +// +// ************************************************************** + +Ops.String.SwitchStringBoolean = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inBool=op.inValueBool("Boolean"), + inStrTrue=op.inString("True","Yes"), + inStrFalse=op.inString("False","No"), + result=op.outString("Result"); + +inBool.onChange= +inStrFalse.onChange= +inStrTrue.onChange=update; + +function update() +{ + if(inBool.get())result.set(inStrTrue.get()); + else result.set(inStrFalse.get()); +} + +update(); + +}; + +Ops.String.SwitchStringBoolean.prototype = new CABLES.Op(); +CABLES.OPS["19e3c428-22ce-45a3-b903-fddfc46fc0a3"]={f:Ops.String.SwitchStringBoolean,objName:"Ops.String.SwitchStringBoolean"}; + + + + +// ************************************************************** +// +// Ops.String.UUID +// +// ************************************************************** + +Ops.String.UUID = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + generate = op.inTriggerButton("Generate"), + result = op.outString("Id"); + +generate.onTriggered = update; +update(); + +function update() +{ + result.set(CABLES.uuid()); +} + + +}; + +Ops.String.UUID.prototype = new CABLES.Op(); +CABLES.OPS["0285022c-846a-43d4-8656-35ba3b5e03a6"]={f:Ops.String.UUID,objName:"Ops.String.UUID"}; + + + + +// ************************************************************** +// +// Ops.String.Uppercase_v2 +// +// ************************************************************** + +Ops.String.Uppercase_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr=op.inString("String"), + outStr=op.outString("Result"); + +inStr.onChange=function() +{ + if(!inStr.get())outStr.set(''); + else outStr.set(inStr.get().toUpperCase()); +}; + +}; + +Ops.String.Uppercase_v2.prototype = new CABLES.Op(); +CABLES.OPS["3f7e6ede-63b6-4262-9dcd-176b43374c4d"]={f:Ops.String.Uppercase_v2,objName:"Ops.String.Uppercase_v2"}; + + + + +// ************************************************************** +// +// Ops.Systems.ArraySpray +// +// ************************************************************** + +Ops.Systems.ArraySpray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe = op.inTrigger("exe"); +const timer = op.inValue("time"); +const num = op.inValue("num", 100); +const sizeX = op.inValue("Size X"); +const sizeY = op.inValue("Size Y"); +const sizeZ = op.inValue("Size Z"); +const movementX = op.inValue("movement x", 1); +const movementY = op.inValue("movement y", 1); +const movementZ = op.inValue("movement z", 1); + +const centerX = op.inBool("Center X", false); +const centerY = op.inBool("Center Y", false); +const centerZ = op.inBool("Center Z", false); + +const inReset = op.inTriggerButton("Reset"); +const lifetime = op.inValue("lifetime", 10); +const lifetimeMin = op.inValue("Lifetime Minimum", 5); + +const + outTrigger = op.outTrigger("Trigger Out"), + outPositions = op.outArray("Positions"), + outLifetimes = op.outArray("Lifetime"); +inReset.onTriggered = reset; +const cgl = op.patch.cgl; + +const particles = []; +const transVec = vec3.create(); +const positions = []; +const lifetimes = []; + +num.onChange = + sizeX.onChange = + sizeY.onChange = + sizeZ.onChange = + lifetime.onChange = + centerX.onChange = + centerY.onChange = + centerZ.onChange = + lifetimeMin.onChange = reset; + +reset(); + +function Particle() +{ + this.pos = null; + this.startPos = null; + this.startTime = 0;// timer.get()- (Math.random() * ( lifetime.get() - lifetimeMin.get() ) + lifetimeMin.get())/2.0; + this.lifeTime = 0; + this.lifeTimePercent = 0; + this.endTime = 0; + + this.pos = [0, 0, 0]; + this.moveVec = [0, 0, 0]; + this.idDead = false; + + this.random1 = Math.random(); + this.random2 = Math.random(); + this.random3 = Math.random(); + + this.update = function (time) + { + const timeRunning = time - this.startTime; + if (time > this.endTime) this.isDead = true; + this.lifeTimePercent = timeRunning / (this.lifeTime); + + this.pos = vec3.fromValues( + this.startPos[0] + timeRunning * this.moveVec[0], + (this.startPos[1] + timeRunning * this.moveVec[1]), // -this.lifeTimePercent*this.lifeTimePercent*2.8, + this.startPos[2] + timeRunning * this.moveVec[2] + ); + }; + + this.reAnimate = function (time) + { + this.isDead = false; + this.lifeTime = Math.random() * (lifetime.get() - lifetimeMin.get()) + lifetimeMin.get(); + if (time !== undefined) + { + this.startTime = time; + this.endTime = time + this.lifeTime; + } + else + { + this.startTime = timer.get() - this.lifeTime * Math.random(); + this.endTime = timer.get() + this.lifeTime * Math.random(); + } + + let r = Math.random(); + + if (centerX.get())r -= 0.5; + const x = r * sizeX.get(); + + r = Math.random(); + if (centerY.get())r -= 0.5; + const y = r * sizeY.get(); + + r = Math.random(); + if (centerZ.get())r -= 0.5; + const z = r * sizeZ.get(); + + this.startPos = vec3.fromValues( + x, + y, + z); + + this.moveVec = [ + Math.random() * movementX.get(), + Math.random() * movementY.get(), + Math.random() * movementZ.get() + ]; + }; + this.reAnimate(0); +} + +exe.onTriggered = function () +{ + const time = timer.get(); + + if (positions.length != particles.length * 3) positions.length = particles.length * 3; + if (lifetimes.length != particles.length) lifetimes.length = particles.length; + + for (let i = 0; i < particles.length; i++) + { + if (particles[i].isDead)particles[i].reAnimate(time); + particles[i].update(time); + + positions[i * 3 + 0] = particles[i].pos[0]; + positions[i * 3 + 1] = particles[i].pos[1]; + positions[i * 3 + 2] = particles[i].pos[2]; + + lifetimes[i] = particles[i].lifeTimePercent; + if (lifetimes[i] > 1.0)lifetimes[i] = 1.0; + } + + outPositions.set(null); + outLifetimes.set(null); + outPositions.set(positions); + outLifetimes.set(lifetimes); + outTrigger.trigger(); +}; + +function reset() +{ + particles.length = 0; + + for (let i = 0; i < num.get(); i++) + { + const p = new Particle(); + p.reAnimate(); + particles.push(p); + } +} + + +}; + +Ops.Systems.ArraySpray.prototype = new CABLES.Op(); +CABLES.OPS["27023519-9e88-4b85-9fcf-b316847e0df7"]={f:Ops.Systems.ArraySpray,objName:"Ops.Systems.ArraySpray"}; + + + + +// ************************************************************** +// +// Ops.Systems.Lsystem_v2 +// +// ************************************************************** + +Ops.Systems.Lsystem_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inExe = op.inTrigger("Trigger"); +const inStrAxiom = op.inString("Axiom / seed", "F"); +const inStrConstant1 = op.inString("Constant 1", "F"); +const inStrRule1 = op.inString("Rule 1", "Fx5y2.2F[yxFF]fF[yXFFfzFZF]fF[yXzFFfzFZF]"); +const inStrConstant2 = op.inString("Constant 2", "x"); +const inStrRule2 = op.inString("Rule 2"); +const inStrConstant3 = op.inString("Constant 3", "y"); +const inStrRule3 = op.inString("Rule 3"); +const inStrConstant4 = op.inString("Constant 4", "z"); +const inStrRule4 = op.inString("Rule 4"); + +inStrAxiom.setUiAttribs({ "hidePort": true }); +inStrConstant1.setUiAttribs({ "hidePort": true }); +inStrRule1.setUiAttribs({ "hidePort": true }); +inStrConstant2.setUiAttribs({ "hidePort": true }); +inStrRule2.setUiAttribs({ "hidePort": true }); +inStrConstant3.setUiAttribs({ "hidePort": true }); +inStrRule3.setUiAttribs({ "hidePort": true }); +inStrConstant4.setUiAttribs({ "hidePort": true }); +inStrRule4.setUiAttribs({ "hidePort": true }); + +const inIterations = op.inValueInt("Iterations", 1); +const inStepLength = op.inValue("Step length", 1.0); +const inStepScale = op.inValue("Step scale multiplier", 1.0); +const inDefaultAngle = op.inValue("Default angle", 45.0); +const inRotateMutliplier = op.inValue("Rotation multiplier", 1.0); + +const outTrigger = op.outTrigger("Out trigger geometry"); +const lineTrigger = op.outTrigger("Line/point trigger"); +// const outArray = op.outArray("Matrix Array out"); +const outPoints = op.outArray("Points out"); +const outMax = op.outNumber("Max Size"); +const stringOut = op.outString("Final generated string"); + +const seed = op.inValue("random seed"); +const inRandStr = op.inValue("random strength"); + +let angleMultiplier = inRotateMutliplier.get(); +let len = inStepLength.get(); +let lenScale = inStepScale.get(); + +const cgl = op.patch.cgl; + +// create a matrix +let trans = mat4.create(); +// array to put trans into +const transforms = []; +// pop in and out matrix for branch transforms +const stack = []; + +// used for splines array +const pointArrays = []; +let currentPointArray = []; +const lastPointArray = [0, 0, 0]; + +// this becomes the axiom after the resetAll() is called +let sentence = "";// axiom; + +// an array that holds the string replacment rules +let rules = []; + +let needsCalc = true; +// UI input +inRotateMutliplier.onChange = calcLater; +inStepLength.onChange = calcLater; +inStepScale.onChange = calcLater; +inIterations.onChange = calcLater; +inExe.onTriggered = render; +seed.onChange = calcLater; +inRandStr.onChange = calcLater; +inDefaultAngle.onChange = calcLater; + +// if user changes rules or constants definesRules is updated +inStrAxiom.onChange = defineRules; +inStrConstant1.onChange = defineRules; +inStrRule1.onChange = defineRules; +inStrConstant2.onChange = defineRules; +inStrRule2.onChange = defineRules; +inStrConstant3.onChange = defineRules; +inStrRule3.onChange = defineRules; +inStrConstant4.onChange = defineRules; +inStrRule4.onChange = defineRules; + +op.init = function () +{ + defineRules(); +}; +// creates the constants and the rule sets +function defineRules() +{ + rules = + [ + inStrConstant1.get(), + inStrRule1.get(), + inStrConstant2.get(), + inStrRule2.get(), + inStrConstant3.get(), + inStrRule3.get(), + inStrConstant4.get(), + inStrRule4.get() + ]; + generate(); +} + +// reset everything +function resetAll() +{ + // define axiom here + sentence = inStrAxiom.get(); + angleMultiplier = inRotateMutliplier.get(); + len = inStepLength.get(); + lenScale = inStepScale.get(); +} + +// generates the string from the ruleset array +function generate() +{ + // reset the state of everything + resetAll(); + + let nextSentence = ""; + const iterationsLimit = Math.min(6, inIterations.get()); + let iter; + let i; + let r; + + for (iter = 0; iter < iterationsLimit; iter++) + { + const sentenceArrayLength = sentence.length; + const rulesArrayLength = rules.length;// + + for (i = 0; i < sentenceArrayLength; i++) + { + const current = sentence.charAt(i); + let found = false; + + for (r = 0; r < rulesArrayLength; r += 2) + { + if (current === rules[r]) + { + found = true; + nextSentence += rules[r + 1]; + } + } + // if nothing is found continue no matter what + if (!found)nextSentence += current; + } + // final result + sentence = nextSentence; + nextSentence = ""; + // removing this will add everything on top of each other recursively + // nextSentence=""; + } + stringOut.set(sentence); + // draw everything once with the turtle function + turtle(); + needsCalc = false; +} + +// used to connect start and end of branches together correctly +const pos = vec3.create(); +const empty = vec3.create(); + +// extracts the user defined angle +// FfFx45FF returns 45 on the x axis +function extract(str, pos) +{ + const slicedSentence = str.slice(pos); + + let output = ""; + let parsedNumber = ""; + let currentChar = ""; + let canceled = true; + // starts i at 1 to drop character which is actually the identifying key! + for (let i = 1; i < slicedSentence.length; i++) + { + // output = slicedSentence.slice(i); + output = slicedSentence.substr(i, 8); + for (let j = 0; j < output.length; j++) + { + currentChar = output.charAt(j); + if (!Number.isNaN(currentChar)) + { + parsedNumber += currentChar; + } + else if (Number.isNaN(currentChar)) + { + canceled = true; + break; + } + } + if (canceled) break; + } + return parseFloat(parsedNumber); +} + +// recreates the turtle algorithm +function turtle() +{ + // used to find max distance from starting point + let max = 0; + // create the main transform array + trans = mat4.create(); + transforms.length = 0; + pointArrays.length = 0; + stack.length = 0; + const branchCoordStack = []; + + currentPointArray = []; + let angleUi = ""; + + let currentBranch = 0; + for (let i = 0; i < sentence.length; i++) + { + const current = sentence.charAt(i); + // step forward, create point + if (current == "F") + { + // apply to the trans matrix, take a step + mat4.translate(trans, trans, [0.0, len, 0.0]); + // push matrix for geometry + transforms.push(mat4.clone(trans)); + // get xyz for point array + vec3.transformMat4(pos, empty, trans); + // spline + currentPointArray.push(pos[0], pos[1], pos[2]); + + max = Math.max(max, Math.abs(pos[0])); + max = Math.max(max, Math.abs(pos[1])); + max = Math.max(max, Math.abs(pos[2])); + } + // step forward do not add a point + else if (current == "f") + { + mat4.translate(trans, trans, [0.0, len, 0.0]); + } + // alter step length by step multiplier + else if (current == ">") + { + len *= lenScale; + } + else if (current == "<") + { + len /= lenScale; + } + // turn counter clockwise x defined by angle + else if (current == "x") + { + if (isNaN(sentence.charAt(i + 1))) + angleUi = -inDefaultAngle.get() * angleMultiplier; + else + angleUi = -extract(sentence, i) * angleMultiplier; + mat4.rotateX(trans, trans, CGL.DEG2RAD * (angleUi - Math.seededRandom() * inRandStr.get())); + } + // turn clockwise x defined by angleUi + else if (current == "X") + { + if (isNaN(sentence.charAt(i + 1))) + angleUi = inDefaultAngle.get() * angleMultiplier; + else + angleUi = extract(sentence, i) * angleMultiplier; + mat4.rotateX(trans, trans, CGL.DEG2RAD * (angleUi + Math.seededRandom() * inRandStr.get())); + } + // turn counter clockwise y defined by angleUi + else if (current == "y") + { + if (isNaN(sentence.charAt(i + 1))) + angleUi = -inDefaultAngle.get() * angleMultiplier; + else + angleUi = -extract(sentence, i) * angleMultiplier; + mat4.rotateY(trans, trans, CGL.DEG2RAD * (angleUi - Math.seededRandom() * inRandStr.get())); + } + // turn clockwise y defined by angleUi + else if (current == "Y") + { + if (isNaN(sentence.charAt(i + 1))) + angleUi = inDefaultAngle.get() * angleMultiplier; + else + angleUi = extract(sentence, i) * angleMultiplier; + mat4.rotateY(trans, trans, CGL.DEG2RAD * (angleUi + Math.seededRandom() * inRandStr.get())); + } + // turn counter clockwise z defined by angleUi + else if (current == "z") + { + if (isNaN(sentence.charAt(i + 1))) + angleUi = -inDefaultAngle.get() * angleMultiplier; + else + angleUi = -extract(sentence, i) * angleMultiplier; + mat4.rotateZ(trans, trans, CGL.DEG2RAD * (angleUi - Math.seededRandom() * inRandStr.get())); + } + // turn clockwise z defined by angleUi + else if (current == "Z") + { + if (isNaN(sentence.charAt(i + 1))) + angleUi = inDefaultAngle.get() * angleMultiplier; + else + angleUi = extract(sentence, i) * angleMultiplier; + mat4.rotateZ(trans, trans, CGL.DEG2RAD * (angleUi + Math.seededRandom() * inRandStr.get())); + } + else if (current == "[") + { + // get current transform matrix push into stack, branch start + stack.push(mat4.clone(trans)); + + vec3.transformMat4(pos, empty, trans); + + branchCoordStack.push([pos[0], pos[1], pos[2]]); + + // output current branch number + currentBranch += 1; + } + else if (current == "]") + { + // get the current branch push into the transform matrix + // check if branch has a start to avoid error + if (stack.length === 0) + { + break; + } + + trans = stack[stack.length - 1]; + stack.pop(); + + // this code section is used to correctly connect the branches together with spline + const branchStartCoord = branchCoordStack[branchCoordStack.length - 1]; + + branchCoordStack.pop(); + + pointArrays.push(currentPointArray); + + if (branchStartCoord) currentPointArray = [branchStartCoord[0], branchStartCoord[1], branchStartCoord[2]]; + else currentPointArray = []; + } + } + needsCalc = false; + pointArrays.push(currentPointArray); + // outArray.set(transforms); + outMax.set(max); +} + +function calcLater() +{ + needsCalc = true; +} + +function render() +{ + if (needsCalc) + { + generate(); + } + needsCalc = false; + + // iterate through transforms array and trigger all geometry + for (var i = 0; i < transforms.length; i++) + { + cgl.pushModelMatrix(); + mat4.multiply(cgl.mMatrix, cgl.mMatrix, transforms[i]); + outTrigger.trigger(); + cgl.popModelMatrix(); + } + // iterate through points array for spline xyz data + for (var i = 0; i < pointArrays.length; i++) + { + outPoints.set(pointArrays[i]); + lineTrigger.trigger(); + } +} + + +}; + +Ops.Systems.Lsystem_v2.prototype = new CABLES.Op(); +CABLES.OPS["ef4c436e-3de5-4a97-a392-10a52a5b3dc6"]={f:Ops.Systems.Lsystem_v2,objName:"Ops.Systems.Lsystem_v2"}; + + + + +// ************************************************************** +// +// Ops.Templates.ExampleVizOp +// +// ************************************************************** + +Ops.Templates.ExampleVizOp = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inNum = op.inFloat("Number", 23); + +op.setUiAttrib({ "height": 200, "width": 200, "resizable": true }); + + +op.renderVizLayer = (ctx, layer) => +{ + ctx.fillStyle = "#222"; + ctx.fillRect( + layer.x, layer.y, + layer.width, layer.height); + + const padding = 10; + + ctx.fillStyle = "#05f"; + + let circle = new Path2D(); + circle.arc(layer.x + layer.height / 2, layer.y + layer.height / 2, layer.height/2, 0, 2 * Math.PI, false); + ctx.fill(circle); + + + // draw text, use layer height for fontsize, so it is fixed when resizing the op or zooming the patch + ctx.fillStyle = "#fff"; + const fontSize = layer.height * 0.7; + ctx.font = "normal " + fontSize + "px sourceCodePro"; + ctx.fillText(Math.round(inNum.get() * 10000) / 10000, layer.x + padding, layer.y + fontSize); + + + // this text will not scale and be at fixed size when zooming in/out + ctx.font = "normal " + 12 + "px sourceCodePro"; + ctx.fillText(Math.round(inNum.get() * 10000) / 10000, layer.x + padding, layer.y+20); + + +}; + + +}; + +Ops.Templates.ExampleVizOp.prototype = new CABLES.Op(); +CABLES.OPS["08f3a509-1cad-4dfc-961c-2bd925e066dd"]={f:Ops.Templates.ExampleVizOp,objName:"Ops.Templates.ExampleVizOp"}; + + + + +// ************************************************************** +// +// Ops.Templates.MinimalMaterial +// +// ************************************************************** + +Ops.Templates.MinimalMaterial = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"shader_frag":"{{MODULE_BEGIN_FRAG}}\n\nvoid main()\n{\n vec4 col=vec4(red,0.2,0.2,1.0);\n {{MODULE_COLOR}}\n outColor= col;\n}\n","shader_vert":"{{MODULES_HEAD}}\n\nIN vec3 vPosition;\nUNI mat4 projMatrix;\nUNI mat4 mvMatrix;\n\nvoid main()\n{\n vec4 pos=vec4(vPosition, 1.0);\n {{MODULE_VERTEX_POSITION}}\n gl_Position = projMatrix * mvMatrix * pos;\n}\n",}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + inRed = op.inValueSlider("Red"); + +const cgl = op.patch.cgl; + +function doRender() +{ + cgl.pushShader(shader); + trigger.trigger(); + cgl.popShader(); +} + +const shader = new CGL.Shader(cgl, "MinimalMaterial"); +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); +shader.setSource(attachments.shader_vert, attachments.shader_frag); + +shader.addUniformFrag("f", "red", inRed); + +render.onTriggered = doRender; + + +}; + +Ops.Templates.MinimalMaterial.prototype = new CABLES.Op(); +CABLES.OPS["2df1b492-6a97-4064-b939-ff926d4414d0"]={f:Ops.Templates.MinimalMaterial,objName:"Ops.Templates.MinimalMaterial"}; + + + + +// ************************************************************** +// +// Ops.Templates.PortsArrayExample +// +// ************************************************************** + +Ops.Templates.PortsArrayExample = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// Create a input port of the type Array +const inArr = op.inArray("Array in"); + +// Create a output port of the type Array +const outArray = op.outArray("Array out"); + +// cache for errors +let showingError = false; + +// when array in changes call the function update +inArr.onChange = update; + +// TODO revalute error checking code !! +function update() +{ + // create an array called 'tempArray' and assign + // the array coming in to it + let tempArray = inArr.get(); + + // error checking section + // check if arrays come in correctly on startup + // if no array comes in just return to avoid errors + if (!inArr) + { + return; + } + // set outArray to tempArray + outArray.set(tempArray); +} + + +}; + +Ops.Templates.PortsArrayExample.prototype = new CABLES.Op(); +CABLES.OPS["c31a7377-0eca-476e-8146-c2d9b8d3b908"]={f:Ops.Templates.PortsArrayExample,objName:"Ops.Templates.PortsArrayExample"}; + + + + +// ************************************************************** +// +// Ops.Templates.PortsBooleanExample +// +// ************************************************************** + +Ops.Templates.PortsBooleanExample = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// Create a input port of the type Boolean +const inBoolean = op.inBool("Boolean in", false); + +// Create a output port of the type value +const outBoolean = op.outBoolNum("Boolean out"); + +// when input port changes call the function 'update' +inBoolean.onChange = update; + +// this function runs every time the input port changes +function update() +{ + // set the ouput port to the value of the input port + outBoolean.set(inBoolean.get()); +} + + +}; + +Ops.Templates.PortsBooleanExample.prototype = new CABLES.Op(); +CABLES.OPS["a21cd004-5cdf-4da2-8866-d1372497c3ff"]={f:Ops.Templates.PortsBooleanExample,objName:"Ops.Templates.PortsBooleanExample"}; + + + + +// ************************************************************** +// +// Ops.Templates.PortsObjectExample +// +// ************************************************************** + +Ops.Templates.PortsObjectExample = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +//Create a input port of the type value +const inObj = op.inObject("Object in"); + +//Create a output port of the type value +const outKeyVal=op.outObject("Object Out"); + +//when input port changes call the function 'update' +inObj.onChange = update; + +//this function runs every time the input port changes +function update() +{ + outKeyVal.set(inObj.get()); +}; + + + +}; + +Ops.Templates.PortsObjectExample.prototype = new CABLES.Op(); +CABLES.OPS["d7f414bf-804f-4c1a-987f-dfdbb3d80e27"]={f:Ops.Templates.PortsObjectExample,objName:"Ops.Templates.PortsObjectExample"}; + + + + +// ************************************************************** +// +// Ops.Templates.PortsStringExample +// +// ************************************************************** + +Ops.Templates.PortsStringExample = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +//Create a input port of the type String +const inString = op.inString("String in", "default string"); +//Create a output port of the type String +const outString = op.outString("String out"); + +//when input port changes call the function 'update' +inString.onChange = update; + +//this function runs every time the input port changes +function update() +{ + //set the output to the input string + outString.set(inString.get()); +} + +}; + +Ops.Templates.PortsStringExample.prototype = new CABLES.Op(); +CABLES.OPS["3d387694-022f-431f-b25e-636c6d666518"]={f:Ops.Templates.PortsStringExample,objName:"Ops.Templates.PortsStringExample"}; + + + + +// ************************************************************** +// +// Ops.Templates.PortsTriggerExample +// +// ************************************************************** + +Ops.Templates.PortsTriggerExample = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +//Create a input port of the type Trigger +const inExecute = op.inTrigger("Trigger In"); +//create a button in UI panel of the op which can be clicked +const inButton = op.inTriggerButton("Press me"); + +//Create a output port of the type Trigger +const outTrigger = op.outTrigger("Trigger out"); + +//when input port is triggered call the function 'update' +//Or +//if user presses the button in the op pane call function 'update' +inExecute.onTriggered = inButton.onTriggered= update; + +//this function runs every time the input port is triggered +function update() +{ + //send a trigger out of the output port + outTrigger.trigger(); +} + +}; + +Ops.Templates.PortsTriggerExample.prototype = new CABLES.Op(); +CABLES.OPS["10728b97-ea46-4491-bb66-e6ad01289001"]={f:Ops.Templates.PortsTriggerExample,objName:"Ops.Templates.PortsTriggerExample"}; + + + + +// ************************************************************** +// +// Ops.Templates.PortsValueExample +// +// ************************************************************** + +Ops.Templates.PortsValueExample = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +//Create a input port of the type value +const inVal = op.inFloat("Number in ",0); + +//Create a output port of the type value +const outResult = op.outNumber("Value out"); + +//when input port changes call the function 'update' +inVal.onChange = update; + +//this function runs every time the input port changes +function update() +{ + //set the ouput port to the value of the input port + outResult.set(inVal.get()); +} + +}; + +Ops.Templates.PortsValueExample.prototype = new CABLES.Op(); +CABLES.OPS["362a1c2f-c4e8-41eb-944b-d16c73a8d27b"]={f:Ops.Templates.PortsValueExample,objName:"Ops.Templates.PortsValueExample"}; + + + + +// ************************************************************** +// +// Ops.Templates.ShaderEffectExample +// +// ************************************************************** + +Ops.Templates.ShaderEffectExample = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"shaderEffectExample_body_frag":"\nfloat MOD_v=mod(MOD_posz,MOD_width)/MOD_width;\ncol*=vec4(MOD_v,MOD_v,MOD_v,1.0);","shaderEffectExample_body_vert":"MOD_posz=(viewMatrix*mMatrix*pos).z;\n","shaderEffectExample_head_frag":"\nIN float MOD_posz;\nUNI float MOD_width;","shaderEffectExample_head_vert":"OUT float MOD_posz;",}; +const render = op.inTrigger("Render"); +const inWidth = op.inValue("Width", 0.5); +const next = op.outTrigger("Next"); + +const cgl = op.patch.cgl; + +let shader = null; +let moduleFrag = null; +let moduleVert = null; + +render.onLinkChanged = removeModule; + +function removeModule() +{ + if (shader && moduleFrag) shader.removeModule(moduleFrag); + if (shader && moduleVert) shader.removeModule(moduleVert); + shader = null; +} + +render.onTriggered = function () +{ + if (!cgl.getShader()) return; + + if (cgl.getShader() != shader) + { + if (shader) removeModule(); + shader = cgl.getShader(); + + moduleVert = shader.addModule( + { + "title": op.objName, + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": attachments.shaderEffectExample_head_vert || "", + "srcBodyVert": attachments.shaderEffectExample_body_vert || "" + }); + + moduleFrag = shader.addModule( + { + "title": op.objName, + "name": "MODULE_COLOR", + "srcHeadFrag": attachments.shaderEffectExample_head_frag || "", + "srcBodyFrag": attachments.shaderEffectExample_body_frag || "" + }, moduleVert); + + inWidth.uniform = new CGL.Uniform(shader, "f", moduleFrag.prefix + "width", inWidth); + } + + if (!shader) return; + + next.trigger(); +}; + + +}; + +Ops.Templates.ShaderEffectExample.prototype = new CABLES.Op(); +CABLES.OPS["a0df10ce-7ae5-49a4-83df-6afc1f5a3f3a"]={f:Ops.Templates.ShaderEffectExample,objName:"Ops.Templates.ShaderEffectExample"}; + + + + +// ************************************************************** +// +// Ops.Templates.UiTestOp +// +// ************************************************************** + +Ops.Templates.UiTestOp = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inLoadingTask = op.inBool("Loading Task", false), + inWarning1 = op.inBool("Warning", false), + inUiError = op.inBool("Error", false), + inUiHint = op.inBool("Hint", false), + innum = op.inFloatSlider("Slider", 0), + inResize = op.inBool("Resizable"), + trig = op.inTrigger("trigger"), + + inSwit = op.inBool("greyout"), + ingreyoutLine = op.inFloatSlider("this will greyout"), + + inLog = op.inTriggerButton("op.log()"), + inLogWarn = op.inTriggerButton("op.logWarn()"), + inLogErr = op.inTriggerButton("op.logError()"), + + inPrompt = op.inTriggerButton("Open Prompt"), + inModal = op.inTriggerButton("Open Modal"), + inTab = op.inTriggerButton("Open new Tab"), + inExc = op.inTriggerButton("Throw Exception"), + outBlah = op.outNumber("Something"); + +op.setPortGroup("Greyout", [inSwit, ingreyoutLine]); +op.setPortGroup("Warnings", [inWarning1, inUiHint, inUiError]); +op.setPortGroup("Logging", [inLog, inLogWarn, inLogErr]); +op.setPortGroup("Modal", [inPrompt, inModal]); + +let loadingId = null; + +op.onDelete = () => +{ + if (loadingId) op.patch.loading.finished(loadingId); +}; + +inSwit.onChange = () => +{ + ingreyoutLine.setUiAttribs({ "greyout": inSwit.get() }); +}; + +inLoadingTask.onChange = () => +{ + if (inLoadingTask.get()) loadingId = op.patch.loading.start("test ui op file", "test.txt"); + else + { + op.patch.loading.finished(loadingId); + loadingId = null; + } +}; + +inWarning1.onChange = () => +{ + if (inWarning1.get()) op.setUiError("Warn1", "Warning one", 1); + else op.setUiError("Warn1", null); +}; + +inUiHint.onChange = () => +{ + if (inUiHint.get()) op.setUiError("Hint1", "This is a hint!", 0); + else op.setUiError("Hint1", null); +}; + +inUiError.onChange = () => +{ + if (inUiError.get()) op.setUiError("Warn2", "Warning two", 2); + else op.setUiError("Warn2", null); +}; + +innum.onChange = () => +{ + const q = innum.get(); + + if (q < 0.3) op.setUiError("qRange", "number to small", 1); + else if (q > 0.6) op.setUiError("qRange", "number to big", 1); + else + { + op.log("no error!"); + op.setUiError("qRange", null); + } + op.log(q); +}; + +inLog.onTriggered = () => +{ + // if you dont see this open the logging filter + // by pressing cmd/ctrl+p "logging" + // and deactivate the filter for this op name. + op.log("this is verbose logging!"); +}; + +inLogWarn.onTriggered = () => +{ + op.logWarn("this is a warning!"); +}; + +inLogErr.onTriggered = () => +{ + op.logError("this is an error!"); +}; + +inPrompt.onTriggered = () => +{ + new CABLES.UI.ModalDialog({ + "prompt": true, + "title": "How Much", + "text": "please enter something", + "promptValue": "default", + "promptOk": (v) => + { + console.log("yes! prompt finished", v); + } + }); +}; + +inResize.onChange = () => +{ + op.setUiAttrib({ "resizable": inResize.get() }); +}; + +inModal.onTriggered = () => +{ + new CABLES.UI.ModalDialog({ + "title": "Title", + "text": "Dialog content can be html" + }); +}; + +inExc.onTriggered = () => +{ + throw new Error("crash0r"); +}; + +inTab.onTriggered = () => +{ + const tab = new CABLES.UI.Tab("Example", + { + "icon": "cube", + "padding": true, + "singleton": false + }); + + gui.mainTabs.addTab(tab, true); + tab.addEventListener("onClose", () => { console.log("tab was closed!"); }); + tab.html("this is the tab content. "); + gui.maintabPanel.show(true); +}; + + +}; + +Ops.Templates.UiTestOp.prototype = new CABLES.Op(); +CABLES.OPS["14fb5b5b-2a4e-419d-a15b-f20d41cf663b"]={f:Ops.Templates.UiTestOp,objName:"Ops.Templates.UiTestOp"}; + + + + +// ************************************************************** +// +// Ops.Time.DelayedTrigger +// +// ************************************************************** + +Ops.Time.DelayedTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + delay = op.inValueFloat("delay", 1), + cancel = op.inTriggerButton("Cancel"), + next = op.outTrigger("next"), + outDelaying = op.outBool("Delaying"); + +let lastTimeout = null; + +cancel.onTriggered = function () +{ + if (lastTimeout)clearTimeout(lastTimeout); + lastTimeout = null; +}; + +exe.onTriggered = function () +{ + outDelaying.set(true); + if (lastTimeout)clearTimeout(lastTimeout); + + lastTimeout = setTimeout( + function () + { + outDelaying.set(false); + lastTimeout = null; + next.trigger(); + }, + delay.get() * 1000); +}; + + +}; + +Ops.Time.DelayedTrigger.prototype = new CABLES.Op(); +CABLES.OPS["f4ff66b0-8500-46f7-9117-832aea0c2750"]={f:Ops.Time.DelayedTrigger,objName:"Ops.Time.DelayedTrigger"}; + + + + +// ************************************************************** +// +// Ops.Time.Milliseconds +// +// ************************************************************** + +Ops.Time.Milliseconds = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; + + +const + inUpdate=op.inTrigger("update"), + res=op.outNumber("Result"); + +inUpdate.onTriggered=function() +{ + res.set(performance.now()); +}; + +}; + +Ops.Time.Milliseconds.prototype = new CABLES.Op(); +CABLES.OPS["2f447fcb-3c20-4c2f-9527-84daed3a6b0e"]={f:Ops.Time.Milliseconds,objName:"Ops.Time.Milliseconds"}; + + + + +// ************************************************************** +// +// Ops.Time.TimeSinceTrigger +// +// ************************************************************** + +Ops.Time.TimeSinceTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + trigger = op.inTriggerButton("trigger"), + reset = op.inTriggerButton("reset"), + next = op.outTrigger("next"), + time = op.outNumber("time"); + +let lastTrigger = op.patch.freeTimer.get(); +time.set(0); + +exe.onTriggered = function () +{ + time.set(op.patch.freeTimer.get() - lastTrigger); + next.trigger(); +}; + +reset.onTriggered = function () +{ + time.set(0); +}; + +trigger.onTriggered = function () +{ + lastTrigger = op.patch.freeTimer.get(); + time.set(0); +}; + + +}; + +Ops.Time.TimeSinceTrigger.prototype = new CABLES.Op(); +CABLES.OPS["df54103f-5ef6-4a4f-adcf-dddc005132f8"]={f:Ops.Time.TimeSinceTrigger,objName:"Ops.Time.TimeSinceTrigger"}; + + + + +// ************************************************************** +// +// Ops.TimeLine.AutoPlay +// +// ************************************************************** + +Ops.TimeLine.AutoPlay = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; + +op.patch.timer.play(); + +}; + +Ops.TimeLine.AutoPlay.prototype = new CABLES.Op(); +CABLES.OPS["6069e8fe-6cf5-4be6-be38-4d46056ec9f7"]={f:Ops.TimeLine.AutoPlay,objName:"Ops.TimeLine.AutoPlay"}; + + + + +// ************************************************************** +// +// Ops.TimeLine.DemoPrerender +// +// ************************************************************** + +Ops.TimeLine.DemoPrerender = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Render"), + inEvents = op.inArray("Times"), + inRecord = op.inBool("Record Events", false), + inReset = op.inTriggerButton("Reset"), + inClear = op.inTriggerButton("Clear"), + inReResize = op.inBool("ReRender on Resize", true), + next = op.outTrigger("Next"), + nextPrerendered = op.outTrigger("Prerendered Frame"), + outProgress = op.outNumber("Progress", 0), + numEvents = op.outNumber("Num Events"); + +exec.onTriggered = render; +inEvents.setUiAttribs({ "hidePort": true }); + +let isPrerendering = true; + +let prerenderCount = 0; +let delaystart = false; +let restartTime = 0; +let restartTimeFreeTimer = 0; +let events = [0]; + +op.patch.cgl.on("resize", () => +{ + if (inReResize.get()) + { + if (!isPrerendering && outProgress.get() == 1) + { + restartTime = op.patch.timer.getTime(); + restartTimeFreeTimer = op.patch.freeTimer.getTime(); + + isPrerendering = true; + prerenderCount = 0; + } + } +}); + +inEvents.onChange = () => +{ + numEvents.set(events.length); + events = inEvents.get() || [0]; +}; + +op.patch.cgl.on("heavyEvent", (e) => +{ + if (inRecord.get() && !isPrerendering && CABLES.uniqueArray) + { + events.push(Math.round(op.patch.timer.getTime() * 60) / 60); + events = CABLES.uniqueArray(events); + inEvents.set(events); + } +}); + +let curTime = 0; + +inReset.onTriggered = () => +{ + isPrerendering = true; +}; + +inClear.onTriggered = () => +{ + events = [0]; + inEvents.set(events); +}; + +function fakeNow() +{ + return curTime * 1000; +} + +function render() +{ + if (inRecord.get()) + { + isPrerendering = false; + outProgress.set(1); + next.trigger(); + + return; + } + if (isPrerendering) + { + // for(let i=0;i= events.length) + { + const t = (numExtraFrames - (prerenderCount - events.length)) / numExtraFrames; + + // op.log("empty prerender...", t); + op.patch.timer.setTime(t); + op.patch.freeTimer.setTime(t); + } + + next.trigger(); + next.trigger(); + // next.trigger(); + // next.trigger(); + outProgress.set(Math.min(1, prerenderCount / (events.length + numExtraFrames))); + // op.log("progress...", outProgress.get()); + + nextPrerendered.trigger(); + + if (prerenderCount >= events.length + numExtraFrames) + { + op.patch.timer.setTime(restartTime); + op.patch.freeTimer.setTime(restartTimeFreeTimer); + + // setTimeout(() => + // { + // delaystart = false; + isPrerendering = false; + // op.patch.timer.setTime(0); + // op.patch.freeTimer.setTime(0); + // }, 500); + } + else + prerenderCount++; + } + else + { + next.trigger(); + } +} + + +}; + +Ops.TimeLine.DemoPrerender.prototype = new CABLES.Op(); +CABLES.OPS["962ea9e5-39ee-448c-9a2b-b71ceee47c11"]={f:Ops.TimeLine.DemoPrerender,objName:"Ops.TimeLine.DemoPrerender"}; + + + + +// ************************************************************** +// +// Ops.TimeLine.GotoFrame +// +// ************************************************************** + +Ops.TimeLine.GotoFrame = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +var inFrame=op.inValueInt("Frame"); + +inFrame.onChange=function() +{ + op.patch.timer.setTime(inFrame.get()/30.0); + + if(CABLES.UI) gui.timeLine().updateTime(); +}; + + +}; + +Ops.TimeLine.GotoFrame.prototype = new CABLES.Op(); +CABLES.OPS["5ff97165-b16c-46cc-8ce5-119fddccf1a3"]={f:Ops.TimeLine.GotoFrame,objName:"Ops.TimeLine.GotoFrame"}; + + + + +// ************************************************************** +// +// Ops.TimeLine.PreRender +// +// ************************************************************** + +Ops.TimeLine.PreRender = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Render"), + next = op.outTrigger("Next"), + progress = op.outTrigger("Render Progress"), + done = op.outTrigger("Done"), + inMaxTime = op.inInt("Max Time", 1), + + inStep = op.inInt("Step", 30), + inReset = op.inTriggerButton("Reset"), + outProgress = op.outNumber("Progress", 0); + +exec.onTriggered = render; + +let start = true; +let curTime = -1; +let wait = true; + +inReset.onTriggered = function () +{ + if (curTime < 0) + start = true; +}; + +function render() +{ + if (!start && curTime < 0) + { + if (!wait) + next.trigger(); + wait = false; + return; + } + + const maxTime = inMaxTime.get(); + if (start) + { + curTime = maxTime; + start = false; + wait = true; + } + + const oldInternalNow = CABLES.internalNow; + CABLES.internalNow = function () + { + return curTime * 1000; + }; + + CABLES.overwriteTime = curTime; + op.patch.timer.setTime(curTime); + op.patch.freeTimer.setTime(curTime); + + outProgress.set((maxTime - curTime) / maxTime); + + next.trigger(); + next.trigger(); + next.trigger(); + + CABLES.overwriteTime = undefined; + CABLES.internalNow = oldInternalNow; + + progress.trigger(); + + if (curTime === 0) + { + done.trigger(); + curTime = -1; + } + else + { + curTime -= inStep.get(); + if (curTime < 0) + curTime = 0; + } +} + + +}; + +Ops.TimeLine.PreRender.prototype = new CABLES.Op(); +CABLES.OPS["294efbca-f2b6-46fa-8b28-0530d6b9f9c8"]={f:Ops.TimeLine.PreRender,objName:"Ops.TimeLine.PreRender"}; + + + + +// ************************************************************** +// +// Ops.TimeLine.TimeLineControls +// +// ************************************************************** + +Ops.TimeLine.TimeLineControls = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const plauPause = op.outBoolNum("Play/Stop"); +const time = op.outNumber("time"); + +op.patch.timer.on("playPause", seek); +op.patch.timer.on("timeChange", seek); + +function seek() +{ + plauPause.set(false); + + setTimeout(function () + { + time.set(op.patch.timer.getTime()); + plauPause.set(op.patch.timer.isPlaying()); + }, 10); +} + + +}; + +Ops.TimeLine.TimeLineControls.prototype = new CABLES.Op(); +CABLES.OPS["53cb7b1a-56c7-405f-b427-12db78fbfd2f"]={f:Ops.TimeLine.TimeLineControls,objName:"Ops.TimeLine.TimeLineControls"}; + + + + +// ************************************************************** +// +// Ops.TimeLine.TimeLineFrame +// +// ************************************************************** + +Ops.TimeLine.TimeLineFrame = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +var theTime=op.addOutPort(new CABLES.Port(this,"time")); + +op.onAnimFrame=function(time) +{ + theTime.set(Math.round(time*30.0)); +}; + +}; + +Ops.TimeLine.TimeLineFrame.prototype = new CABLES.Op(); +CABLES.OPS["a6c66f1f-2102-4b68-882b-afd25a4da538"]={f:Ops.TimeLine.TimeLineFrame,objName:"Ops.TimeLine.TimeLineFrame"}; + + + + +// ************************************************************** +// +// Ops.TimeLine.TimeLineLength +// +// ************************************************************** + +Ops.TimeLine.TimeLineLength = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// uses its input port for caching the length of the timeline... + +const + inLength = op.inFloat("len", 0), + outLength = op.outNumber("Length"); + +inLength.setUiAttribs({ "hidePort": true, "hideParam": true }); + +if (CABLES.UI) +{ + inLength.set(gui.timeLine().getTimeLineLength()); + + gui.on("timelineControl", (cmd, l) => + { + if (cmd === "setLength") + { + inLength.set(l); + outLength.set(inLength.get()); + } + }); + outLength.set(inLength.get()); +} + +op.on("loadedValueSet", () => +{ + outLength.set(inLength.get()); +}); + + +}; + +Ops.TimeLine.TimeLineLength.prototype = new CABLES.Op(); +CABLES.OPS["c8aee7f4-ad53-406d-b7fe-527bf271c088"]={f:Ops.TimeLine.TimeLineLength,objName:"Ops.TimeLine.TimeLineLength"}; + + + + +// ************************************************************** +// +// Ops.TimeLine.TimeLineLoop +// +// ************************************************************** + +Ops.TimeLine.TimeLineLoop = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + execute = op.inTrigger("Execute"), + duration = op.inValueFloat("duration", 2), + trigger = op.outTrigger("trigger"); + +execute.onTriggered = function () +{ + if (op.patch.timer.getTime() > duration.get()) + op.patch.timer.setTime(0); + + trigger.trigger(); +}; + + +}; + +Ops.TimeLine.TimeLineLoop.prototype = new CABLES.Op(); +CABLES.OPS["e450a850-7311-48b5-abfc-07ec1fea3b8e"]={f:Ops.TimeLine.TimeLineLoop,objName:"Ops.TimeLine.TimeLineLoop"}; + + + + +// ************************************************************** +// +// Ops.TimeLine.TimeLineOverwrite +// +// ************************************************************** + +Ops.TimeLine.TimeLineOverwrite = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exec = op.inTrigger("exe"); +const newTime = op.inValueFloat("new time"); +const next = op.outTrigger("trigger"); + +let realTime = 0; +exec.onTriggered = function () +{ + realTime = op.patch.timer.getTime(); + + op.patch.timer.overwriteTime = newTime.get(); + next.trigger(); + op.patch.timer.overwriteTime = -1; +}; + + +}; + +Ops.TimeLine.TimeLineOverwrite.prototype = new CABLES.Op(); +CABLES.OPS["f0492ba2-5009-4a9a-bfd9-8a03633df31c"]={f:Ops.TimeLine.TimeLineOverwrite,objName:"Ops.TimeLine.TimeLineOverwrite"}; + + + + +// ************************************************************** +// +// Ops.TimeLine.TimeLinePlay +// +// ************************************************************** + +Ops.TimeLine.TimeLinePlay = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + play = op.inTriggerButton("Play"), + pause = op.inTriggerButton("Pause"), + next = op.outTrigger("Next"); + +play.onTriggered = function () +{ + op.patch.timer.play(); + next.trigger(); +}; + +pause.onTriggered = function () +{ + op.patch.timer.pause(); + next.trigger(); +}; + + +}; + +Ops.TimeLine.TimeLinePlay.prototype = new CABLES.Op(); +CABLES.OPS["fc75b841-a55f-4474-8746-61218588598d"]={f:Ops.TimeLine.TimeLinePlay,objName:"Ops.TimeLine.TimeLinePlay"}; + + + + +// ************************************************************** +// +// Ops.TimeLine.TimeLinePlayer +// +// ************************************************************** + +Ops.TimeLine.TimeLinePlayer = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + play = op.inTriggerButton("Play"), + pause = op.inTriggerButton("Pause"), + rewind = op.inTriggerButton("rewind"), + setTime = op.inFloat("Set current time", 0), + + outPlayTrigger = op.outTrigger("play trigger"), + outPauseTrigger = op.outTrigger("pause trigger"), + outrewindTrigger = op.outTrigger("rewind trigger"), + isPlaying = op.outBool("is Playing"), + outSetTimeTrigger = op.outNumber("set time (seconds)"), + currentTime = op.outNumber("current time"), + currentFrame = op.outNumber("current frame"); + +play.onTriggered = function () +{ + op.patch.timer.play(); + + op.patch.timer.setTime(setTime.get()); + outSetTimeTrigger.set(setTime.get()); + outPlayTrigger.trigger(); +}; + +pause.onTriggered = function () +{ + op.patch.timer.pause(); + outPauseTrigger.trigger(); +}; + +op.onAnimFrame = function (time) +{ + currentFrame.set(Math.round(time * 30.0)); + currentTime.set(time); + isPlaying.set(op.patch.timer.isPlaying()); +}; + +rewind.onTriggered = function () +{ + op.patch.timer.setTime(0); + outrewindTrigger.trigger(); +}; + + +}; + +Ops.TimeLine.TimeLinePlayer.prototype = new CABLES.Op(); +CABLES.OPS["97e57613-6a51-41cf-9de5-fe3dbc2c69b2"]={f:Ops.TimeLine.TimeLinePlayer,objName:"Ops.TimeLine.TimeLinePlayer"}; + + + + +// ************************************************************** +// +// Ops.TimeLine.TimeLineRewind +// +// ************************************************************** + +Ops.TimeLine.TimeLineRewind = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTriggerButton("exe"), + next = op.outTrigger("Next"); + +exe.onTriggered = function () +{ + op.patch.timer.setTime(0); + next.trigger(); +}; + + +}; + +Ops.TimeLine.TimeLineRewind.prototype = new CABLES.Op(); +CABLES.OPS["d3408604-858c-4226-8d4c-1ef669956f35"]={f:Ops.TimeLine.TimeLineRewind,objName:"Ops.TimeLine.TimeLineRewind"}; + + + + +// ************************************************************** +// +// Ops.TimeLine.TimeLineSetTime +// +// ************************************************************** + +Ops.TimeLine.TimeLineSetTime = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTriggerButton("Update"), + inTime = op.inFloat("Time", 0), + next = op.outTrigger("Next"); + +exe.onTriggered = function () +{ + op.patch.timer.setTime(parseFloat(inTime.get())); + next.trigger(); +}; + + +}; + +Ops.TimeLine.TimeLineSetTime.prototype = new CABLES.Op(); +CABLES.OPS["c65f3975-0901-4252-b040-f21f9b144d70"]={f:Ops.TimeLine.TimeLineSetTime,objName:"Ops.TimeLine.TimeLineSetTime"}; + + + + +// ************************************************************** +// +// Ops.TimeLine.TimeLineTime +// +// ************************************************************** + +Ops.TimeLine.TimeLineTime = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const theTime = op.outNumber("time"); + +op.onAnimFrame = function (time) +{ + theTime.set(time); +}; + + +}; + +Ops.TimeLine.TimeLineTime.prototype = new CABLES.Op(); +CABLES.OPS["3ab26f26-a12a-4c48-9411-20591a5f569d"]={f:Ops.TimeLine.TimeLineTime,objName:"Ops.TimeLine.TimeLineTime"}; + + + + +// ************************************************************** +// +// Ops.TimeLine.TimeLineTogglePlay +// +// ************************************************************** + +Ops.TimeLine.TimeLineTogglePlay = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const play=op.inBool("Play",false); + +play.onChange=function() +{ + if(play.get()) op.patch.timer.play(); + else op.patch.timer.pause(); +} + + +}; + +Ops.TimeLine.TimeLineTogglePlay.prototype = new CABLES.Op(); +CABLES.OPS["930c6f38-9271-4021-a58b-14dcfc5763b2"]={f:Ops.TimeLine.TimeLineTogglePlay,objName:"Ops.TimeLine.TimeLineTogglePlay"}; + + + + +// ************************************************************** +// +// Ops.TimeLine.TimelineValue +// +// ************************************************************** + +Ops.TimeLine.TimelineValue = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTime = op.inValue("Time"), + animVal = op.inValue("Value"), + timeUnit = op.inValueSelect("Unit", ["Seconds", "Frames"], "Seconds"), + outVal = op.outNumber("Result"), + outArr = op.outArray("Anim Array"), + outEnded = op.outBoolNum("Anim Finished"); + +inTime.onChange = update; +let hasError = false; + +animVal.setAnimated(true); +animVal.onChange = update; +animVal.anim.onChange = animChange; +op.onLoaded = animChange; + +let useFrames = false; + +timeUnit.onChange = function () +{ + useFrames = (timeUnit.get() == "Frames"); +}; + +function update() +{ + inTime.get(); + + if (animVal.isAnimated()) + { + let t = inTime.get(); + if (useFrames) t /= 30.0; + const v = animVal.anim.getValue(t); + outEnded.set(animVal.anim.hasEnded(t)); + outVal.set(v); + if (hasError) + { + op.setUiError("noanim", null); + hasError = false; + + animVal.anim.onChange = animChange; + } + } + else + { + op.setUiError("noanim", "Port \"animVal\" should be animated"); + hasError = true; + } +} + +function animChange() +{ + const arr = []; + if (animVal.anim.keys && animVal.anim.keys.length > 0) + { + arr.length = animVal.anim.keys.length * 2; + + for (let i = 0; i < animVal.anim.keys.length; i++) + { + arr[i * 2 + 0] = animVal.anim.keys[i].time; + arr[i * 2 + 1] = animVal.anim.keys[i].value; + } + } + + outArr.set(null); + outArr.set(arr); +} + + +}; + +Ops.TimeLine.TimelineValue.prototype = new CABLES.Op(); +CABLES.OPS["c5f260da-c8e3-4890-a37e-937d49b9da7d"]={f:Ops.TimeLine.TimelineValue,objName:"Ops.TimeLine.TimelineValue"}; + + + + +// ************************************************************** +// +// Ops.Trigger.GateTrigger +// +// ************************************************************** + +Ops.Trigger.GateTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger('Execute'), + passThrough = op.inValueBool('Pass Through',true), + triggerOut = op.outTrigger('Trigger out'); + +exe.onTriggered = function() +{ + if(passThrough.get()) + triggerOut.trigger(); +} + + +}; + +Ops.Trigger.GateTrigger.prototype = new CABLES.Op(); +CABLES.OPS["65e8b8a2-ba13-485f-883a-2bcf377989da"]={f:Ops.Trigger.GateTrigger,objName:"Ops.Trigger.GateTrigger"}; + + + + +// ************************************************************** +// +// Ops.Trigger.IfEqualsThen +// +// ************************************************************** + +Ops.Trigger.IfEqualsThen = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe = op.inTrigger("exe"); +let value1 = op.inValue("Value 1", 0); +let value2 = op.inValue("Value 2", 0); + +let triggerThen = op.addOutPort(new CABLES.Port(op, "then", CABLES.OP_PORT_TYPE_FUNCTION)); +let triggerElse = op.addOutPort(new CABLES.Port(op, "else", CABLES.OP_PORT_TYPE_FUNCTION)); + +function exec() +{ + if (value1.get() == value2.get()) + { + triggerThen.trigger(); + } + else + { + triggerElse.trigger(); + } +} + +exe.onTriggered = exec; + + +}; + +Ops.Trigger.IfEqualsThen.prototype = new CABLES.Op(); +CABLES.OPS["e8196d70-d0a6-470a-9448-a7ac0c0e956e"]={f:Ops.Trigger.IfEqualsThen,objName:"Ops.Trigger.IfEqualsThen"}; + + + + +// ************************************************************** +// +// Ops.Trigger.Interval +// +// ************************************************************** + +Ops.Trigger.Interval = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + interval = op.inValue("interval"), + trigger = op.outTrigger("trigger"), + active = op.inValueBool("Active", true); + +active.onChange = function () +{ + if (!active.get()) + { + clearTimeout(timeOutId); + timeOutId = -1; + } + else exec(); +}; + +interval.set(1000); +let timeOutId = -1; + +function exec() +{ + if (!active.get()) return; + if (timeOutId != -1) return; + + timeOutId = setTimeout(function () + { + timeOutId = -1; + trigger.trigger(); + exec(); + }, + interval.get()); +} + +interval.onChange = exec; + +exec(); + + +}; + +Ops.Trigger.Interval.prototype = new CABLES.Op(); +CABLES.OPS["3e9bae10-38af-4e36-9fcc-35faeeaf57f8"]={f:Ops.Trigger.Interval,objName:"Ops.Trigger.Interval"}; + + + + +// ************************************************************** +// +// Ops.Trigger.IsTriggered +// +// ************************************************************** + +Ops.Trigger.IsTriggered = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Trigger"), + next = op.outTrigger("Next"), + result = op.outBool("Was Triggered", false); + +let frameCount = 0; + +op.onAnimFrame = function (tt) +{ + frameCount++; + if (frameCount > 1) result.set(false); +}; + +exec.onTriggered = function () +{ + frameCount = 0; + result.set(true); + next.trigger(); +}; + + +}; + +Ops.Trigger.IsTriggered.prototype = new CABLES.Op(); +CABLES.OPS["7c96fee9-4c2f-45e1-a41b-096b06d286b8"]={f:Ops.Trigger.IsTriggered,objName:"Ops.Trigger.IsTriggered"}; + + + + +// ************************************************************** +// +// Ops.Trigger.NthTrigger_v2 +// +// ************************************************************** + +Ops.Trigger.NthTrigger_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let DEFAULT_NTH = 5; + +// inputs +let exePort = op.inTriggerButton("Execute"); +let nthPort = op.inValue("Nth", DEFAULT_NTH); + +// outputs +let triggerPort = op.outTrigger("Next"); + +let count = 0; +let nth = DEFAULT_NTH; + +exePort.onTriggered = onExeTriggered; +nthPort.onChange = valueChanged; + +function onExeTriggered() +{ + count++; + if (count % nth === 0) + { + count = 0; + triggerPort.trigger(); + } +} + +function valueChanged() +{ + nth = nthPort.get(); + count = 0; +} + + +}; + +Ops.Trigger.NthTrigger_v2.prototype = new CABLES.Op(); +CABLES.OPS["ea43c184-5842-4aa1-b298-5db4515cbed0"]={f:Ops.Trigger.NthTrigger_v2,objName:"Ops.Trigger.NthTrigger_v2"}; + + + + +// ************************************************************** +// +// Ops.Trigger.ProbabilityTrigger +// +// ************************************************************** + +Ops.Trigger.ProbabilityTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inTrigger = op.inTrigger("Trigger In"); +const inProbability = op.inFloatSlider("Probability", 0.5); +const outTrigger = op.outTrigger("Trigger Output"); +const outInverseTrigger = op.outTrigger("Inverse Trigger Output"); +Math.randomSeed = 0; + +let scheduleUpdate = false; +let probability = inProbability.get(); +inProbability.onChange = () => +{ + if (inTrigger.isLinked()) + { + scheduleUpdate = true; + return; + } + probability = inProbability.get(); +}; + +inTrigger.onTriggered = () => +{ + if (scheduleUpdate) + { + probability = inProbability.get(); + scheduleUpdate = false; + } + if (probability >= 1) + { + outTrigger.trigger(); + return; + } + + if (probability <= 0) + { + outInverseTrigger.trigger(); + return; + } + if (Math.seededRandom() < probability) + { + outTrigger.trigger(); + } + else + { + outInverseTrigger.trigger(); + } +}; + + +}; + +Ops.Trigger.ProbabilityTrigger.prototype = new CABLES.Op(); +CABLES.OPS["69436c67-eab0-4829-b0dc-d7bfd863a116"]={f:Ops.Trigger.ProbabilityTrigger,objName:"Ops.Trigger.ProbabilityTrigger"}; + + + + +// ************************************************************** +// +// Ops.Trigger.RandomTrigger +// +// ************************************************************** + +Ops.Trigger.RandomTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Render"), + inNum = op.inValue("Num Times", 3), + inSeed = op.inValue("Seed", 1), + inOnlyOnce = op.inValueBool("Only Once"), + outIndex = op.outNumber("Index"); + +const linked = []; +const triggers = []; + +for (let i = 0; i < 8; i++) +{ + const newIn = op.addOutPort(new CABLES.Port(op, "trigger " + i, CABLES.OP_PORT_TYPE_FUNCTION)); + triggers.push(newIn); + newIn.onLinkChanged = updateLinkedArray; +} + +exec.onTriggered = function () +{ + if (linked.length == 0) return; + + Math.randomSeed = inSeed.get(); + + let numTriggered = 0; + + if (inOnlyOnce.get()) + { + for (var i = 0; i < linked.length; i++) + linked[i].RTwasTriggered = false; + } + + for (var i = 0; i < inNum.get(); i++) + { + outIndex.set(i); + + const r = Math.floor(Math.seededRandom() * linked.length); + + if (linked[r]) + { + if (inOnlyOnce.get()) + { + if (numTriggered == linked.length) + { + return; + } + if (!linked[r].RTwasTriggered) + { + linked[r].trigger(); + numTriggered++; + } + else i--; + } + else + { + linked[r].trigger(); + } + linked[r].RTwasTriggered = true; + } + } +}; + +function updateLinkedArray() +{ + linked.length = 0; + for (let i = 0; i < triggers.length; i++) + { + if (triggers[i].isLinked()) + linked.push(triggers[i]); + } +} + + +}; + +Ops.Trigger.RandomTrigger.prototype = new CABLES.Op(); +CABLES.OPS["3996175e-0424-407b-bcff-a7b4791d75df"]={f:Ops.Trigger.RandomTrigger,objName:"Ops.Trigger.RandomTrigger"}; + + + + +// ************************************************************** +// +// Ops.Trigger.Repeat2d +// +// ************************************************************** + +Ops.Trigger.Repeat2d = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + numx = op.inValueInt("num x", 5), + numy = op.inValueInt("num y", 5), + mul = op.inValueFloat("mul", 1), + center = op.inValueBool("center"), + trigger = op.outTrigger("trigger"), + outX = op.outNumber("x"), + outY = op.outNumber("y"), + idx = op.outNumber("index"), + total = op.outNumber("total iterations"); + +exe.onTriggered = function () +{ + let subX = 0; + let subY = 0; + const m = mul.get(); + const nx = numx.get(); + const ny = numy.get(); + + if (center.get()) + { + subX = ((nx - 1) * m) / 2.0; + subY = ((ny - 1) * m) / 2.0; + } + + for (let y = 0; y < ny; y++) + { + outY.set((y * m) - subY); + for (let x = 0; x < nx; x++) + { + outX.set((x * m) - subX); + idx.set(x + y * nx); + trigger.trigger(); + } + } + total.set(numx.get() * numy.get()); +}; + + +}; + +Ops.Trigger.Repeat2d.prototype = new CABLES.Op(); +CABLES.OPS["79934693-5887-4173-8b48-3e3a18fcf225"]={f:Ops.Trigger.Repeat2d,objName:"Ops.Trigger.Repeat2d"}; + + + + +// ************************************************************** +// +// Ops.Trigger.Repeat_v2 +// +// ************************************************************** + +Ops.Trigger.Repeat_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe=op.inTrigger("Execute"), + num=op.inValueInt("Repeats",5), + dir=op.inSwitch("Direction",['Forward','Backward'],'Forward'), + next=op.outTrigger("Next"), + idx=op.addOutPort(new CABLES.Port(op,"index")); + +dir.onChange=updateDir; +updateDir(); + +function updateDir() +{ + if(dir.get()=="Forward") exe.onTriggered=forward; + else exe.onTriggered=backward; +} + +function forward() +{ + const max=Math.floor(num.get()); + + for(var i=0;i-1;i--) + { + idx.set(i); + next.trigger(); + } +} + + +}; + +Ops.Trigger.Repeat_v2.prototype = new CABLES.Op(); +CABLES.OPS["a4deea80-db97-478f-ad1a-5ee30f2f47cc"]={f:Ops.Trigger.Repeat_v2,objName:"Ops.Trigger.Repeat_v2"}; + + + + +// ************************************************************** +// +// Ops.Trigger.RouteTrigger +// +// ************************************************************** + +Ops.Trigger.RouteTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const NUM_PORTS = 24; + +const exePort = op.inTriggerButton("Execute"); +const switchPort = op.inValueInt("Switch Value"); +const nextTriggerPort = op.outTrigger("Next Trigger"); +const valueOutPort = op.outNumber("Switched Value"); +const triggerPorts = []; +for (let j = 0; j < NUM_PORTS; j++) +{ + triggerPorts[j] = op.outTrigger("Trigger " + j); +} +const defaultTriggerPort = op.outTrigger("Default Trigger"); + +// functions + +function update() +{ + const index = Math.round(switchPort.get()); + if (index >= 0 && index < NUM_PORTS) + { + valueOutPort.set(index); + triggerPorts[index].trigger(); + } + else + { + valueOutPort.set(-1); + defaultTriggerPort.trigger(); + } + nextTriggerPort.trigger(); +} + +// change listeners / trigger events +exePort.onTriggered = update; + + +}; + +Ops.Trigger.RouteTrigger.prototype = new CABLES.Op(); +CABLES.OPS["44ceb5d8-b040-4722-b189-a6fb8172517d"]={f:Ops.Trigger.RouteTrigger,objName:"Ops.Trigger.RouteTrigger"}; + + + + +// ************************************************************** +// +// Ops.Trigger.RouteTriggerString +// +// ************************************************************** + +Ops.Trigger.RouteTriggerString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const NUM_PORTS = 24; +const exePort = op.inTriggerButton("Execute"); +const switchPort = op.inString("Switch Value"); +const nextTriggerPort = op.outTrigger("Next Trigger"); +const valueOutPort = op.outNumber("Switched Index"); + +let index = -1; + +const triggerPorts = []; +const namePorts = []; + +for (let j = 0; j < NUM_PORTS; j++) +{ + triggerPorts[j] = op.outTrigger("Trigger " + j); + namePorts[j] = op.inString("String " + j); + namePorts[j].onChange = updateIndex; +} +// const defaultTriggerPort = op.outTrigger("Default Trigger"); + +op.onLoad = +op.onInit = +switchPort.onChange = updateIndex; + +function updateIndex() +{ + index = -1; + for (let i = 0; i < namePorts.length; i++) + { + if (namePorts[i].get() == switchPort.get()) + { + index = i; + } + } + // if (index >= 0 && index < NUM_PORTS) + // { + // valueOutPort.set(index); + // triggerPorts[index].trigger(); + // } + // else + // { + // valueOutPort.set(-1); + // defaultTriggerPort.trigger(); + // } +} + +exePort.onTriggered = () => +{ + if (index >= 0) triggerPorts[index].trigger(); + + valueOutPort.set(index); + nextTriggerPort.trigger(); +}; + + +}; + +Ops.Trigger.RouteTriggerString.prototype = new CABLES.Op(); +CABLES.OPS["973746cc-8b57-4510-af73-780b771e0dc7"]={f:Ops.Trigger.RouteTriggerString,objName:"Ops.Trigger.RouteTriggerString"}; + + + + +// ************************************************************** +// +// Ops.Trigger.SetNumberOnTrigger +// +// ************************************************************** + +Ops.Trigger.SetNumberOnTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + setValuePort = op.inTriggerButton("Set"), + valuePort = op.inValueFloat("Number"), + outNext = op.outTrigger("Next"), + outValuePort = op.outNumber("Out Value"); + +outValuePort.changeAlways = true; + +setValuePort.onTriggered = function () +{ + outValuePort.set(valuePort.get()); + outNext.trigger(); +}; + + +}; + +Ops.Trigger.SetNumberOnTrigger.prototype = new CABLES.Op(); +CABLES.OPS["9989b1c0-1073-4d5f-bfa0-36dd98b66e27"]={f:Ops.Trigger.SetNumberOnTrigger,objName:"Ops.Trigger.SetNumberOnTrigger"}; + + + + +// ************************************************************** +// +// Ops.Trigger.SwitchTrigger +// +// ************************************************************** + +Ops.Trigger.SwitchTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const NUM_PORTS = 16; + +const + inIndex = op.inValueInt("Trigger Index", 0), + triggerPorts = [], + outTrig = op.outTrigger("Trigger out"); + +for (let i = 0; i < NUM_PORTS; i++) +{ + const port = op.inTrigger("Trigger in " + i); + port.onTriggered = function () { update(i); }; + triggerPorts.onChange = function () { update(i); }; + triggerPorts.push(port); +} + +function update(inputNum) +{ + const index = Math.min(Math.max(inIndex.get(), 0), 15); + if (inputNum == index) outTrig.trigger(); +} + + +}; + +Ops.Trigger.SwitchTrigger.prototype = new CABLES.Op(); +CABLES.OPS["aee29293-0c4f-404d-b724-484bbb57361e"]={f:Ops.Trigger.SwitchTrigger,objName:"Ops.Trigger.SwitchTrigger"}; + + + + +// ************************************************************** +// +// Ops.Trigger.Threshold +// +// ************************************************************** + +Ops.Trigger.Threshold = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// this op will send one trigger out if the threshold has been crossed +// but will not send another until the incoming inValue +// drops below the threshold and go's above it again + +const inValue = op.inValue("Input"), + inThreshold = op.inValue("Threshold"), + output = op.outTrigger("Output"); + +let hasThresholdBeenExceeded = false; + +inValue.onChange = update; +function update() +{ + if (!hasThresholdBeenExceeded && inValue.get() >= inThreshold.get()) + { + hasThresholdBeenExceeded = true; + output.trigger(); + } + else if (hasThresholdBeenExceeded && inValue.get() <= inThreshold.get()) + { + hasThresholdBeenExceeded = false; + } +} + + +}; + +Ops.Trigger.Threshold.prototype = new CABLES.Op(); +CABLES.OPS["ef0891db-6053-42ba-b7d5-29c7cf6d8208"]={f:Ops.Trigger.Threshold,objName:"Ops.Trigger.Threshold"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TimedSequence +// +// ************************************************************** + +Ops.Trigger.TimedSequence = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe = op.inTrigger("exe"); +const current = op.inValueInt("current", 0); +const overwriteTime = op.inValueBool("overwriteTime"); +const ignoreInSubPatch = op.inValueBool("ignoreInSubPatch", false); +const triggerAlways = op.outTrigger("triggerAlways"); +const outNames = op.outArray("Names", []); +const currentKeyTime = op.outNumber("currentKeyTime"); +const outCurrent = op.outNumber("Current"); +let triggers = []; + +for (let i = 0; i < 32; i++) +{ + let p = op.outTrigger("trigger " + i); + p.onLinkChanged = updateNames; + triggers.push(p); +} + +function updateNames() +{ + let names = []; + for (let i = 0; i < triggers.length; i++) + if (triggers[i].isLinked()) names.push(triggers[i].links[0].getOtherPort(triggers[i]).parent.uiAttribs.title); + else names.push("none"); + + outNames.set(names); +} + +op.onLoaded = updateNames; + +let lastUiValue = -1; + +exe.onTriggered = doTrigger; + +function doTrigger(_time) +{ + let spl = 0; + + let outIndex = Math.round(current.get() - 0.5); + + if (window.gui) + { + if (current.get() != lastUiValue) + { + lastUiValue = current.get(); + for (spl = 0; spl < triggers.length; spl++) + { + if (spl == lastUiValue) triggers[spl].setUiActiveState(true); + else triggers[spl].setUiActiveState(false); + } + } + } + + if (current.anim) + { + let time = _time; + if (_time === undefined) time = current.parent.patch.timer.getTime(); + let key = current.anim.getKey(time); + + let timeOff = 0; + if (key) timeOff = key.time; + + currentKeyTime.set(time - timeOff); + + if (current.isAnimated()) + { + if (overwriteTime.get()) + { + current.parent.patch.timer.overwriteTime = currentKeyTime.get(); // todo why current ? why not self ? + } + } + } + + if (op.patch.gui && ignoreInSubPatch.get()) + { + for (let i = 0; i < triggers.length; i++) + { + for (spl = 0; spl < triggers[i].links.length; spl++) + { + if (triggers[i].links[spl]) + { + if (triggers[i].links[spl].portIn.parent.patchId) + { + if (CABLES.UI) + if (gui.patchView.getCurrentSubPatch() == triggers[i].links[spl].portIn.parent.patchId.get()) + { + op.patch.timer.overwriteTime = -1; + + triggers[i].trigger(); + return; + } + } + } + } + } + } + + if (outIndex >= 0 && outIndex < triggers.length) + { + outCurrent.set(outIndex); + triggers[outIndex].trigger(); + } + + op.patch.timer.overwriteTime = -1; + triggerAlways.trigger(); +} + + +}; + +Ops.Trigger.TimedSequence.prototype = new CABLES.Op(); +CABLES.OPS["73c892c9-3e81-4ddc-952a-fbe6bf00ef2c"]={f:Ops.Trigger.TimedSequence,objName:"Ops.Trigger.TimedSequence"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerButton +// +// ************************************************************** + +Ops.Trigger.TriggerButton = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTrig = op.inTriggerButton("Trigger"), + outTrig = op.outTrigger("Next"); + +inTrig.onTriggered = function () +{ + outTrig.trigger(); +}; + + +}; + +Ops.Trigger.TriggerButton.prototype = new CABLES.Op(); +CABLES.OPS["21630924-39e4-4df5-9965-b9136510d156"]={f:Ops.Trigger.TriggerButton,objName:"Ops.Trigger.TriggerButton"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerCounter +// +// ************************************************************** + +Ops.Trigger.TriggerCounter = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTriggerButton("exe"), + reset = op.inTriggerButton("reset"), + trigger = op.outTrigger("trigger"), + num = op.outNumber("timesTriggered"); + +op.toWorkPortsNeedToBeLinked(exe); + +let n = 0; + +reset.onTriggered = +op.onLoaded = + doReset; + +exe.onTriggered = function () +{ + n++; + num.set(n); + op.setUiAttrib({ "extendTitle": n }); + trigger.trigger(); +}; + +function doReset() +{ + n = 0; + op.setUiAttrib({ "extendTitle": n }); + num.set(n); +} + + +}; + +Ops.Trigger.TriggerCounter.prototype = new CABLES.Op(); +CABLES.OPS["e640619f-235c-4543-bbf8-b358e0283180"]={f:Ops.Trigger.TriggerCounter,objName:"Ops.Trigger.TriggerCounter"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerCounterLoop +// +// ************************************************************** + +Ops.Trigger.TriggerCounterLoop = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe = op.inTriggerButton("trigger in"), + reset = op.inTriggerButton("reset"), + trigger = op.outTrigger("trigger out"), + num = op.outNumber("current count"), + + inMinLoopValue = op.inValueInt("Loop min", 0.0), + inMaxLoopValue = op.inValueInt("Loop max", 4.0); + +let n = Math.floor(inMinLoopValue.get()); + +// increments with each trigger and loops +// depending on min and max loop values +// can also work with negative numbers +// if min is greater than max then it decrements +// instead of incrementing +exe.onTriggered = function () +{ + let inMin = Math.floor(inMinLoopValue.get()); + let inMax = Math.floor(inMaxLoopValue.get()); + + if (inMin < inMax) + { + if (n < inMin) + { + n = inMinLoopValue.get(); + } + else if (n >= inMax) + { + n = inMinLoopValue.get(); + } + else + { + n++; + } + } + else if (inMin > inMax) + { + if (n < inMax) + { + n = inMin; + } + else if (n > inMin) + { + inMin; + } + else if (n <= inMax) + { + n = inMin; + } + else + { + n--; + } + } + num.set(n); + op.setUiAttrib({ "extendTitle": n }); + trigger.trigger(); +}; + +reset.onTriggered = function () +{ + let inMin = Math.floor(inMinLoopValue.get()); + let inMax = Math.floor(inMaxLoopValue.get()); + + if (inMin < inMax) + { + n = inMin; + } + else if (inMax < inMin) + { + n = inMin; + } + else + { + n = 0; + } + op.setUiAttrib({ "extendTitle": n }); + num.set(n); +}; + + +}; + +Ops.Trigger.TriggerCounterLoop.prototype = new CABLES.Op(); +CABLES.OPS["d3356c53-e278-433f-af0b-d8327cd99a2d"]={f:Ops.Trigger.TriggerCounterLoop,objName:"Ops.Trigger.TriggerCounterLoop"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerDistributeByValue +// +// ************************************************************** + +Ops.Trigger.TriggerDistributeByValue = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const exe = op.inTrigger("exe"); +let number = op.addInPort(new CABLES.Port(op, "number")); +let max = op.addInPort(new CABLES.Port(op, "max")); +let numOut = op.addInPort(new CABLES.Port(op, "num outputs")); +let num = op.addOutPort(new CABLES.Port(op, "num", CABLES.OP_PORT_TYPE_VALUE)); + +number.set(0); +max.set(1); +numOut.set(2); +num.set(0); + +let triggers = []; +let numTriggers = 20; + +let trigger = function () +{ + let s = max.get() / numOut.get(); + let index = Math.abs(Math.floor(number.get() / s)); + + num.set(index); + + if (!isNaN(index) && index < numTriggers) + { + triggers[index].trigger(); + } +}; + +exe.onTriggered = trigger; + +for (let i = 0; i < numTriggers; i++) +{ + triggers.push(op.addOutPort(new CABLES.Port(op, "trigger " + i, CABLES.OP_PORT_TYPE_FUNCTION))); +} + + +}; + +Ops.Trigger.TriggerDistributeByValue.prototype = new CABLES.Op(); +CABLES.OPS["e697380f-ac93-4d4a-9e9c-b54287773668"]={f:Ops.Trigger.TriggerDistributeByValue,objName:"Ops.Trigger.TriggerDistributeByValue"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerExtender +// +// ************************************************************** + +Ops.Trigger.TriggerExtender = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTriggerPort = op.inTriggerButton("Execute"), + outTriggerPort = op.outTrigger("Next"); + +inTriggerPort.onTriggered = function () +{ + outTriggerPort.trigger(); +}; + + +}; + +Ops.Trigger.TriggerExtender.prototype = new CABLES.Op(); +CABLES.OPS["7ef594f3-4907-47b0-a2d3-9854eda1679d"]={f:Ops.Trigger.TriggerExtender,objName:"Ops.Trigger.TriggerExtender"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerIfDecreased +// +// ************************************************************** + +Ops.Trigger.TriggerIfDecreased = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + value = op.inValue("Value"), + trigger = op.outTrigger("Trigger"); + +let lastValue = -Number.MAX_VALUE; + +value.onChange = function () +{ + const v = value.get(); + if (v < lastValue) + { + trigger.trigger(); + } + lastValue = v; +}; + + +}; + +Ops.Trigger.TriggerIfDecreased.prototype = new CABLES.Op(); +CABLES.OPS["16ec4069-3682-461e-95ff-1d86e3f44512"]={f:Ops.Trigger.TriggerIfDecreased,objName:"Ops.Trigger.TriggerIfDecreased"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerIfIncreased +// +// ************************************************************** + +Ops.Trigger.TriggerIfIncreased = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + value = op.inFloat("Value"), + trigger = op.outTrigger("Trigger"); + +let lastValue = -Number.MAX_VALUE; + +value.onChange = function () +{ + const v = value.get(); + if (v > lastValue) + { + trigger.trigger(); + } + lastValue = v; +}; + + +}; + +Ops.Trigger.TriggerIfIncreased.prototype = new CABLES.Op(); +CABLES.OPS["bc820891-48c7-4287-9b5e-4196e192741b"]={f:Ops.Trigger.TriggerIfIncreased,objName:"Ops.Trigger.TriggerIfIncreased"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerLimiter +// +// ************************************************************** + +Ops.Trigger.TriggerLimiter = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inTriggerPort = op.inTrigger("In Trigger"), + timePort = op.inValue("Milliseconds", 300), + outTriggerPort = op.outTrigger("Out Trigger"), + progress = op.outNumber("Progress"); + +let lastTriggerTime = 0; + +// change listeners +inTriggerPort.onTriggered = function () +{ + const now = CABLES.now(); + let prog = (now - lastTriggerTime) / timePort.get(); + + if (prog > 1.0)prog = 1.0; + if (prog < 0.0)prog = 0.0; + + progress.set(prog); + + if (now >= lastTriggerTime + timePort.get()) + { + lastTriggerTime = now; + outTriggerPort.trigger(); + } +}; + + +}; + +Ops.Trigger.TriggerLimiter.prototype = new CABLES.Op(); +CABLES.OPS["47641d85-9f81-4287-8aa2-35753b0727e0"]={f:Ops.Trigger.TriggerLimiter,objName:"Ops.Trigger.TriggerLimiter"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerNumber +// +// ************************************************************** + +Ops.Trigger.TriggerNumber = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe0 = op.inTriggerButton("0"), + exe1 = op.inTriggerButton("1"), + exe2 = op.inTriggerButton("2"), + exe3 = op.inTriggerButton("3"), + exe4 = op.inTriggerButton("4"), + exe5 = op.inTriggerButton("5"), + exe6 = op.inTriggerButton("6"), + exe7 = op.inTriggerButton("7"), + number = op.outNumber("number"); + +number.changeAlways = true; +const outTrig = op.outTrigger("Triggered"); + +exe0.onTriggered = function () { number.set(0); outTrig.trigger(); }; +exe1.onTriggered = function () { number.set(1); outTrig.trigger(); }; +exe2.onTriggered = function () { number.set(2); outTrig.trigger(); }; +exe3.onTriggered = function () { number.set(3); outTrig.trigger(); }; +exe4.onTriggered = function () { number.set(4); outTrig.trigger(); }; +exe5.onTriggered = function () { number.set(5); outTrig.trigger(); }; +exe6.onTriggered = function () { number.set(6); outTrig.trigger(); }; +exe7.onTriggered = function () { number.set(7); outTrig.trigger(); }; + + +}; + +Ops.Trigger.TriggerNumber.prototype = new CABLES.Op(); +CABLES.OPS["43ed1123-1312-4383-b843-27b8ec540c09"]={f:Ops.Trigger.TriggerNumber,objName:"Ops.Trigger.TriggerNumber"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerOnChangeArray +// +// ************************************************************** + +Ops.Trigger.TriggerOnChangeArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inval=op.inArray("Array"), + next=op.outTrigger("Changed"), + outArr=op.outArray("Result"); + +inval.onChange=function() +{ + outArr.set(inval.get()); + next.trigger(); +}; + +}; + +Ops.Trigger.TriggerOnChangeArray.prototype = new CABLES.Op(); +CABLES.OPS["e4ddec93-4dee-422b-a402-6a0f6e469ce6"]={f:Ops.Trigger.TriggerOnChangeArray,objName:"Ops.Trigger.TriggerOnChangeArray"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerOnChangeObject +// +// ************************************************************** + +Ops.Trigger.TriggerOnChangeObject = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inval = op.inObject("Object"), + next = op.outTrigger("Changed"), + outArr = op.outObject("Result"); + +inval.onChange = function () +{ + outArr.set(inval.get()); + next.trigger(); +}; + + +}; + +Ops.Trigger.TriggerOnChangeObject.prototype = new CABLES.Op(); +CABLES.OPS["c7e3fa27-21e8-44ef-b176-e0e596837abb"]={f:Ops.Trigger.TriggerOnChangeObject,objName:"Ops.Trigger.TriggerOnChangeObject"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerOnChangeString +// +// ************************************************************** + +Ops.Trigger.TriggerOnChangeString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inval = op.inString("String"), + next = op.outTrigger("Changed"), + outStr = op.outString("Result"); + +inval.onChange = function () +{ + outStr.set(inval.get()); + next.trigger(); +}; + + +}; + +Ops.Trigger.TriggerOnChangeString.prototype = new CABLES.Op(); +CABLES.OPS["319d07e0-5cbe-4bc1-89fb-a934fd41b0c4"]={f:Ops.Trigger.TriggerOnChangeString,objName:"Ops.Trigger.TriggerOnChangeString"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerOnChangeTexture +// +// ************************************************************** + +Ops.Trigger.TriggerOnChangeTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inval = op.inTexture("Texture"), + inFilter = op.inBool("Ignore empty/default Texture", false), + next = op.outTrigger("Changed"), + outTex = op.outTexture("Result", CGL.Texture.getEmptyTexture(op.patch.cgl)); + +inval.onLinkChanged = +inval.onChange = function () +{ + const v = inval.get(); + if (inFilter.get() && (v == CGL.Texture.getEmptyTexture(op.patch.cgl) || v == null)) return; + + outTex.set(v || CGL.Texture.getEmptyTexture(op.patch.cgl)); + next.trigger(); +}; + + +}; + +Ops.Trigger.TriggerOnChangeTexture.prototype = new CABLES.Op(); +CABLES.OPS["d7260ecb-d862-496a-8a26-f8165ab49dd2"]={f:Ops.Trigger.TriggerOnChangeTexture,objName:"Ops.Trigger.TriggerOnChangeTexture"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerOnce +// +// ************************************************************** + +Ops.Trigger.TriggerOnce = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTriggerButton("Exec"), + reset = op.inTriggerButton("Reset"), + next = op.outTrigger("Next"), + outTriggered = op.outBoolNum("Was Triggered"); + +let triggered = false; + +op.toWorkPortsNeedToBeLinked(exe); + +reset.onTriggered = function () +{ + triggered = false; + outTriggered.set(triggered); +}; + +exe.onTriggered = function () +{ + if (triggered) return; + + triggered = true; + next.trigger(); + outTriggered.set(triggered); +}; + + +}; + +Ops.Trigger.TriggerOnce.prototype = new CABLES.Op(); +CABLES.OPS["cf3544e4-e392-432b-89fd-fcfb5c974388"]={f:Ops.Trigger.TriggerOnce,objName:"Ops.Trigger.TriggerOnce"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerReceive +// +// ************************************************************** + +Ops.Trigger.TriggerReceive = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const next = op.outTrigger("Triggered"); +op.varName = op.inValueSelect("Named Trigger", [], "", true); + +updateVarNamesDropdown(); +op.patch.addEventListener("namedTriggersChanged", updateVarNamesDropdown); + +let oldName = null; + +function doTrigger() +{ + next.trigger(); +} + +function updateVarNamesDropdown() +{ + if (CABLES.UI) + { + let varnames = []; + let vars = op.patch.namedTriggers; + // varnames.push('+ create new one'); + for (let i in vars) varnames.push(i); + op.varName.uiAttribs.values = varnames; + } +} + +op.varName.onChange = function () +{ + if (oldName) + { + let oldCbs = op.patch.namedTriggers[oldName]; + let a = oldCbs.indexOf(doTrigger); + if (a != -1) oldCbs.splice(a, 1); + } + + op.setTitle(">" + op.varName.get()); + op.patch.namedTriggers[op.varName.get()] = op.patch.namedTriggers[op.varName.get()] || []; + let cbs = op.patch.namedTriggers[op.varName.get()]; + + cbs.push(doTrigger); + oldName = op.varName.get(); + updateError(); + op.patch.emitEvent("opTriggerNameChanged", op, op.varName.get()); +}; + +op.on("uiParamPanel", updateError); + +function updateError() +{ + if (!op.varName.get()) + { + op.setUiError("unknowntrigger", "unknown trigger"); + } + else op.setUiError("unknowntrigger", null); +} + + +}; + +Ops.Trigger.TriggerReceive.prototype = new CABLES.Op(); +CABLES.OPS["0816c999-f2db-466b-9777-2814573574c5"]={f:Ops.Trigger.TriggerReceive,objName:"Ops.Trigger.TriggerReceive"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerReceiveFilter +// +// ************************************************************** + +Ops.Trigger.TriggerReceiveFilter = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const prefixIn = op.inString("Prefix", ""); +const triggerOut = op.outTrigger("Trigger Out"); +const triggerNameOut = op.outString("Trigger Name"); + +const listener = (triggerName) => +{ + const prefix = prefixIn.get(); + if (triggerName) + { + if (prefix) + { + if (triggerName.startsWith(prefix)) + { + triggerNameOut.set(triggerName); + triggerOut.trigger(); + } + } + else + { + triggerNameOut.set(triggerName); + triggerOut.trigger(); + } + } +}; + +prefixIn.onChange = () => +{ + if (prefixIn.get()) + { + op.setUiAttrib({ "extendTitle": prefixIn.get() }); + } +}; + +op.patch.addEventListener("namedTriggerSent", listener); + + +}; + +Ops.Trigger.TriggerReceiveFilter.prototype = new CABLES.Op(); +CABLES.OPS["7bf9e19a-55a8-4eb4-aaeb-5a15a8d2f958"]={f:Ops.Trigger.TriggerReceiveFilter,objName:"Ops.Trigger.TriggerReceiveFilter"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerSend +// +// ************************************************************** + +Ops.Trigger.TriggerSend = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const trigger = op.inTriggerButton("Trigger"); +op.varName = op.inValueSelect("Named Trigger", [], "", true); + +op.varName.onChange = updateName; + +trigger.onTriggered = doTrigger; + +op.patch.addEventListener("namedTriggersChanged", updateVarNamesDropdown); + +updateVarNamesDropdown(); + +function updateVarNamesDropdown() +{ + if (CABLES.UI) + { + const varnames = []; + const vars = op.patch.namedTriggers; + varnames.push("+ create new one"); + for (const i in vars) varnames.push(i); + op.varName.uiAttribs.values = varnames; + } +} + +function updateName() +{ + if (CABLES.UI) + { + if (op.varName.get() == "+ create new one") + { + new CABLES.UI.ModalDialog({ + "prompt": true, + "title": "New Trigger", + "text": "enter a name for the new trigger", + "promptValue": "", + "promptOk": (str) => + { + op.varName.set(str); + op.patch.namedTriggers[str] = op.patch.namedTriggers[str] || []; + updateVarNamesDropdown(); + } + }); + return; + } + + op.refreshParams(); + } + + if (!op.patch.namedTriggers[op.varName.get()]) + { + op.patch.namedTriggers[op.varName.get()] = op.patch.namedTriggers[op.varName.get()] || []; + op.patch.emitEvent("namedTriggersChanged"); + } + + op.setTitle(">" + op.varName.get()); + + op.refreshParams(); + op.patch.emitEvent("opTriggerNameChanged", op, op.varName.get()); +} + +function doTrigger() +{ + const arr = op.patch.namedTriggers[op.varName.get()]; + // fire an event even if noone is receiving this trigger + // this way TriggerReceiveFilter can still handle it + op.patch.emitEvent("namedTriggerSent", op.varName.get()); + + if (!arr) + { + op.setUiError("unknowntrigger", "unknown trigger"); + return; + } + else op.setUiError("unknowntrigger", null); + + for (let i = 0; i < arr.length; i++) + { + arr[i](); + } +} + + +}; + +Ops.Trigger.TriggerSend.prototype = new CABLES.Op(); +CABLES.OPS["ce1eaf2b-943b-4dc0-ab5e-ee11b63c9ed0"]={f:Ops.Trigger.TriggerSend,objName:"Ops.Trigger.TriggerSend"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerSendNamed +// +// ************************************************************** + +Ops.Trigger.TriggerSendNamed = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const trigger = op.inTriggerButton("Trigger"); +const varname = op.inString("Named Trigger", ""); + +trigger.onTriggered = doTrigger; + +varname.onChange = () => +{ + op.setUiAttrib({ "extendTitle": varname.get() }); +}; + +function doTrigger() +{ + const arr = op.patch.namedTriggers[varname.get()]; + // fire an event even if noone is receiving this trigger + // this way TriggerReceiveFilter can still handle it + op.patch.emitEvent("namedTriggerSent", varname.get()); + + if (!arr) + { + return; + } + + for (let i = 0; i < arr.length; i++) + { + arr[i](); + } +} + + +}; + +Ops.Trigger.TriggerSendNamed.prototype = new CABLES.Op(); +CABLES.OPS["45d07cd7-bdfb-48b7-bc76-7606de5afd76"]={f:Ops.Trigger.TriggerSendNamed,objName:"Ops.Trigger.TriggerSendNamed"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggerString +// +// ************************************************************** + +Ops.Trigger.TriggerString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTriggerButton("Trigger"), + inString = op.inString("String", ""), + next = op.outTrigger("Next"), + outString = op.outString("Result"); + +outString.changeAlways = true; +exec.onTriggered = function () +{ + outString.set(inString.get()); + next.trigger(); +}; + + +}; + +Ops.Trigger.TriggerString.prototype = new CABLES.Op(); +CABLES.OPS["217482b8-2ee6-4609-b7ad-4550e6aaa371"]={f:Ops.Trigger.TriggerString,objName:"Ops.Trigger.TriggerString"}; + + + + +// ************************************************************** +// +// Ops.Trigger.TriggersPerSecond +// +// ************************************************************** + +Ops.Trigger.TriggersPerSecond = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + cps = op.outNumber("cps"); + +let timeStart = 0; +let cpsCount = 0; + +exe.onTriggered = function () +{ + if (timeStart === 0)timeStart = CABLES.now(); + let now = CABLES.now(); + + if (now - timeStart > 1000) + { + timeStart = CABLES.now(); + op.setUiAttrib({ "extendTitle": cpsCount }); + cps.set(cpsCount); + cpsCount = 0; + } + + cpsCount++; +}; + + +}; + +Ops.Trigger.TriggersPerSecond.prototype = new CABLES.Op(); +CABLES.OPS["ece2f153-eb31-4268-b0e5-8143ad2fdd81"]={f:Ops.Trigger.TriggersPerSecond,objName:"Ops.Trigger.TriggersPerSecond"}; + + + + +// ************************************************************** +// +// Ops.Trigger.ValueBecameZeroTrigger +// +// ************************************************************** + +Ops.Trigger.ValueBecameZeroTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let valueBefore = -1; + +// input +let valuePort = op.inValue("Value", -1); + +// output +let outTrigger = op.outTrigger("Became Zero Trigger"); + +valuePort.onChange = function () +{ + let value = valuePort.get(); + if (valueBefore != 0 & value == 0) + { + outTrigger.trigger(); + } + valueBefore = value; +}; + + +}; + +Ops.Trigger.ValueBecameZeroTrigger.prototype = new CABLES.Op(); +CABLES.OPS["822f925c-33e8-4b8a-8a89-be5d2e358ed7"]={f:Ops.Trigger.ValueBecameZeroTrigger,objName:"Ops.Trigger.ValueBecameZeroTrigger"}; + + + + +// ************************************************************** +// +// Ops.Ui.Area +// +// ************************************************************** + +Ops.Ui.Area = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inTitle = op.inString("Title", ""); + +inTitle.setUiAttribs({ "hidePort": true }); + +op.setUiAttrib({ "hasArea": true }); + +// exe.onTriggered=function() +// { +// op.patch.instancing.pushLoop(inNum.get()); + +// for(let i=0;i +{ + const mySubPatchOp = getPatchOp(); + + if (!dyn.links.length) return; + + const otherPort = dyn.links[0].getOtherPort(dyn); + dyn.removeLinks(); + + const newPortName = mySubPatchOp.addNewInPort(otherPort); + + const l = gui.scene().link( + otherPort.parent, + otherPort.getName(), + op, + newPortName); + + mySubPatchOp.saveData(); +}; + + +}; + +Ops.Ui.PatchInput.prototype = new CABLES.Op(); +CABLES.OPS["e3f68bc3-892a-4c78-9974-aca25c27025d"]={f:Ops.Ui.PatchInput,objName:"Ops.Ui.PatchInput"}; + + + + +// ************************************************************** +// +// Ops.Ui.PatchOutput +// +// ************************************************************** + +Ops.Ui.PatchOutput = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const dyn = op.addInPort(new CABLES.Port(op, "create port", CABLES.OP_PORT_TYPE_DYNAMIC)); + +function getPatchOp() +{ + for (let i in op.patch.ops) + { + if (op.patch.ops[i].patchId) + { + if (op.patch.ops[i].patchId.get() == op.uiAttribs.subPatch) + { + return op.patch.ops[i]; + } + } + } +} + +dyn.onLinkChanged = () => +{ + const mySubPatchOp = getPatchOp(); + + if (!dyn.links.length) return; + + const otherPort = dyn.links[0].getOtherPort(dyn); + dyn.removeLinks(); + + const newPortName = mySubPatchOp.addNewOutPort(otherPort); + + const l = gui.scene().link( + otherPort.parent, + otherPort.getName(), + op, + newPortName); + + mySubPatchOp.saveData(); +}; + + +}; + +Ops.Ui.PatchOutput.prototype = new CABLES.Op(); +CABLES.OPS["851b44cb-5667-4140-9800-5aeb7031f1d7"]={f:Ops.Ui.PatchOutput,objName:"Ops.Ui.PatchOutput"}; + + + + +// ************************************************************** +// +// Ops.Ui.SubPatch +// +// ************************************************************** + +Ops.Ui.SubPatch = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +op.dyn = op.addInPort(new CABLES.Port(op, "create port", CABLES.OP_PORT_TYPE_DYNAMIC)); +op.dynOut = op.addOutPort(new CABLES.Port(op, "create port out", CABLES.OP_PORT_TYPE_DYNAMIC)); + +const dataStr = op.addInPort(new CABLES.Port(op, "dataStr", CABLES.OP_PORT_TYPE_VALUE, { "display": "readonly" })); +op.patchId = op.addInPort(new CABLES.Port(op, "patchId", CABLES.OP_PORT_TYPE_VALUE, { "display": "readonly" })); + +if (CABLES.UI && CABLES.sandbox.isDevEnv()) +{ + const inMakeBp = op.inTriggerButton("Create Blueprint"); + inMakeBp.setUiAttribs({ "hidePort": true }); + + inMakeBp.onTriggered = makeBlueprint; +} + +dataStr.setUiAttribs({ "hideParam": true }); +op.patchId.setUiAttribs({ "hideParam": true }); + +let data = { "ports": [], "portsOut": [] }; +let oldPatchId = CABLES.generateUUID(); +op.patchId.set(oldPatchId); +getSubPatchInputOp(); +getSubPatchOutputOp(); + +let dataLoaded = false; + +op.saveData = saveData; + +op.patchId.onChange = function () +{ + const oldPatchOps = op.patch.getSubPatchOps(oldPatchId); + + if (oldPatchOps.length == 2) + { + for (let i = 0; i < oldPatchOps.length; i++) + { + op.patch.deleteOp(oldPatchOps[i].id); + } + } + else + { + } +}; + +op.onLoaded = function () +{ +}; + +op.onLoadedValueSet = function () +{ + data = JSON.parse(dataStr.get()); + if (!data) + { + data = { "ports": [], "portsOut": [] }; + } + setupPorts(); +}; + +function loadData() +{ +} + +dataStr.onChange = function () +{ + if (dataLoaded) return; + + if (!dataStr.get()) return; + try + { + loadData(); + } + catch (e) + { + op.logError("cannot load subpatch data..."); + op.logError(e); + } +}; + +function saveData() +{ + dataStr.set(JSON.stringify(data)); +} + +op.addPortListener = addPortListener; +function addPortListener(newPort, newPortInPatch) +{ + if (!newPort.hasSubpatchLstener) + { + newPort.hasSubpatchLstener = true; + newPort.addEventListener("onUiAttrChange", function (attribs) + { + if (attribs.title) + { + let i = 0; + for (i = 0; i < data.portsOut.length; i++) + if (data.portsOut[i].name == newPort.name) + data.portsOut[i].title = attribs.title; + + for (i = 0; i < data.ports.length; i++) + if (data.ports[i].name == newPort.name) + data.ports[i].title = attribs.title; + + saveData(); + } + }); + } + + if (newPort.direction == CABLES.PORT_DIR_IN) + { + if (newPort.type == CABLES.OP_PORT_TYPE_FUNCTION) + { + newPort.onTriggered = function () + { + if (newPortInPatch.isLinked()) + newPortInPatch.trigger(); + }; + } + else + { + newPort.onChange = function () + { + newPortInPatch.set(newPort.get()); + if (!newPort.isLinked()) + { + for (let i = 0; i < data.ports.length; i++) + { + if (data.ports[i].name === newPort.name) + { + data.ports[i].value = newPort.get(); + } + } + saveData(); + } + }; + } + } +} + +op.setupPorts = setupPorts; +function setupPorts() +{ + if (!op.patchId.get()) return; + const ports = data.ports || []; + const portsOut = data.portsOut || []; + let i = 0; + + for (i = 0; i < ports.length; i++) + { + if (!op.getPortByName(ports[i].name)) + { + const newPort = op.addInPort(new CABLES.Port(op, ports[i].name, ports[i].type)); + + const patchInputOp = getSubPatchInputOp(); + const newPortInPatch = patchInputOp.addOutPort(new CABLES.Port(patchInputOp, ports[i].name, ports[i].type)); + + newPort.ignoreValueSerialize = true; + newPort.setUiAttribs({ "editableTitle": true }); + if (ports[i].title) + { + newPort.setUiAttribs({ "title": ports[i].title }); + newPortInPatch.setUiAttribs({ "title": ports[i].title }); + } + if (ports[i].objType) + { + newPort.setUiAttribs({ "objType": ports[i].objType }); + newPortInPatch.setUiAttribs({ "objType": ports[i].objType }); + } + if (ports[i].value) + { + newPort.set(ports[i].value); + newPortInPatch.set(ports[i].value); + } + addPortListener(newPort, newPortInPatch); + } + } + + for (i = 0; i < portsOut.length; i++) + { + if (!op.getPortByName(portsOut[i].name)) + { + const newPortOut = op.addOutPort(new CABLES.Port(op, portsOut[i].name, portsOut[i].type)); + const patchOutputOp = getSubPatchOutputOp(); + const newPortOutPatch = patchOutputOp.addInPort(new CABLES.Port(patchOutputOp, portsOut[i].name, portsOut[i].type)); + + newPortOut.ignoreValueSerialize = true; + newPortOut.setUiAttribs({ "editableTitle": true }); + + if (portsOut[i].title) + { + newPortOut.setUiAttribs({ "title": portsOut[i].title }); + newPortOutPatch.setUiAttribs({ "title": portsOut[i].title }); + } + if (portsOut[i].objType) + { + newPortOut.setUiAttribs({ "objType": portsOut[i].objType }); + newPortOutPatch.setUiAttribs({ "objType": portsOut[i].objType }); + } + + // addPortListener(newPortOut,newPortOutPatch); + addPortListener(newPortOutPatch, newPortOut); + } + } + + dataLoaded = true; +} + +op.addNewInPort = function (otherPort, type, objType) +{ + const newName = "in" + data.ports.length + " " + otherPort.parent.name + " " + otherPort.name; + + const o = { "name": newName, "type": otherPort.type }; + if (otherPort.uiAttribs.objType)o.objType = otherPort.uiAttribs.objType; + + data.ports.push(o); + setupPorts(); + return newName; +}; + +op.dyn.onLinkChanged = function () +{ + if (op.dyn.isLinked()) + { + const otherPort = op.dyn.links[0].getOtherPort(op.dyn); + op.dyn.removeLinks(); + otherPort.removeLinkTo(op.dyn); + + op.log("dyn link changed!!!"); + + // const newName = "in" + data.ports.length + " " + otherPort.parent.name + " " + otherPort.name; + + // const o = { "name": newName, "type": otherPort.type }; + // if (otherPort.uiAttribs.objType)o.objType = otherPort.uiAttribs.objType; + // data.ports.push(o); + + // setupPorts(); + + const newName = op.addNewInPort(otherPort); + + const l = gui.scene().link( + otherPort.parent, + otherPort.getName(), + op, + newName + ); + + dataLoaded = true; + saveData(); + } + else + { + setTimeout(function () + { + op.dyn.removeLinks(); + }, 100); + } +}; + +op.addNewOutPort = function (otherPort, type, objType) +{ + const newName = "out" + data.portsOut.length + " " + otherPort.parent.name + " " + otherPort.name; + + const o = { "name": newName, "type": otherPort.type }; + if (otherPort.uiAttribs.objType)o.objType = otherPort.uiAttribs.objType; + + data.portsOut.push(o); + setupPorts(); + return newName; +}; + +op.dynOut.onLinkChanged = function () +{ + if (op.dynOut.isLinked()) + { + const otherPort = op.dynOut.links[0].getOtherPort(op.dynOut); + op.dynOut.removeLinks(); + otherPort.removeLinkTo(op.dynOut); + + const newName = op.addNewOutPort(otherPort); + + gui.scene().link( + otherPort.parent, + otherPort.getName(), + op, + newName + ); + + dataLoaded = true; + saveData(); + } + else + { + setTimeout(function () + { + op.dynOut.removeLinks(); + }, 100); + + op.log("dynOut unlinked..."); + } +}; + +function getSubPatchOutputOp() +{ + let patchOutputOP = op.patch.getSubPatchOp(op.patchId.get(), "Ops.Ui.PatchOutput"); + + if (!patchOutputOP) + { + op.patch.addOp("Ops.Ui.PatchOutput", { "subPatch": op.patchId.get(), "translate": { "x": 0, "y": 0 } }); + patchOutputOP = op.patch.getSubPatchOp(op.patchId.get(), "Ops.Ui.PatchOutput"); + if (!patchOutputOP) op.warn("no patchoutput!"); + } + return patchOutputOP; +} + +function getSubPatchInputOp() +{ + let patchInputOP = op.patch.getSubPatchOp(op.patchId.get(), "Ops.Ui.PatchInput"); + + if (!patchInputOP) + { + op.patch.addOp("Ops.Ui.PatchInput", { "subPatch": op.patchId.get(), "translate": { "x": 0, "y": 0 } }); + patchInputOP = op.patch.getSubPatchOp(op.patchId.get(), "Ops.Ui.PatchInput"); + if (!patchInputOP) op.warn("no patchinput2!"); + } + + return patchInputOP; +} + +op.addSubLink = function (p, p2) +{ + const num = data.ports.length; + const sublPortname = "in" + (num - 1) + " " + p2.parent.name + " " + p2.name; + + if (p.direction == CABLES.PORT_DIR_IN) + { + gui.scene().link( + p.parent, + p.getName(), + getSubPatchInputOp(), + sublPortname + ); + } + else + { + const numOut = data.portsOut.length; + gui.scene().link( + p.parent, + p.getName(), + getSubPatchOutputOp(), + "out" + (numOut - 1) + " " + p2.parent.name + " " + p2.name + ); + } + + const bounds = gui.patchView.getSubPatchBounds(op.patchId.get()); + + getSubPatchInputOp().uiAttr( + { + "translate": + { + "x": bounds.minx, + "y": bounds.miny - 100 + } + }); + + getSubPatchOutputOp().uiAttr( + { + "translate": + { + "x": bounds.minx, + "y": bounds.maxy + 100 + } + }); + saveData(); + return sublPortname; +}; + +op.onDelete = function () +{ + for (let i = op.patch.ops.length - 1; i >= 0; i--) + { + if (op.patch.ops[i] && op.patch.ops[i].uiAttribs && op.patch.ops[i].uiAttribs.subPatch == op.patchId.get()) + { + op.patch.deleteOp(op.patch.ops[i].id); + } + } +}; + +function makeBlueprint() +{ + const bpOp = op.patch.addOp(CABLES.UI.DEFAULTOPNAMES.blueprint); + + bpOp.getPortByName("externalPatchId").set(gui.patchId); + bpOp.getPortByName("subPatchId").set(op.patchId.get()); + bpOp.getPortByName("active").set(true); + + bpOp.uiAttr( + { + "translate": + { + "x": op.uiAttribs.translate.x - 150, + "y": op.uiAttribs.translate.y + } + }); +} + +op.rebuildListeners = () => +{ + op.log("rebuild listeners..."); + + const outop = getSubPatchOutputOp(); + for (let i = 0; i < outop.portsIn.length; i++) + { + if (outop.portsIn[i].isLinked()) + { + addPortListener(outop.portsIn[i], this.portsOut[i]); + } + } +}; + + +}; + +Ops.Ui.SubPatch.prototype = new CABLES.Op(); +CABLES.OPS["84d9a6f0-ed7a-466d-b386-225ed9e89c60"]={f:Ops.Ui.SubPatch,objName:"Ops.Ui.SubPatch"}; + + + + +// ************************************************************** +// +// Ops.Ui.VizArrayChart +// +// ************************************************************** + +Ops.Ui.VizArrayChart = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array Numbers"), + inArrTitles = op.inArray("Titles"); + // inStyle = op.inSwitch("Style", ["Pie", "Graph"], "Pie"); + +op.setUiAttrib({ "height": 100, "width": 200, "resizable": true }); + +let max = -Number.MAX_VALUE; +let min = Number.MAX_VALUE; +const padding = 10; + +op.renderVizLayer = (ctx, layer) => +{ + ctx.fillStyle = "#222"; + ctx.fillRect( + layer.x, layer.y, + layer.width, layer.height); + + const arr = inArr.get(); + const arrNames = inArrTitles.get(); + if (!arr) + { + return; + } + + const colors = ["#7AC4E0", "#D183BF", "#9091D6", "#FFC395", "#F0D165", "#63A8E8", "#CF5D9D", "#66C984", "#D66AA6", "#515151"]; + + let size = layer.height / 2; + if (size != size || size < 0) return; + let currentAngle = 0; + let total = 0; + for (let i = 0; i < arr.length; i++) + { + total += parseFloat(Math.abs(arr[i])); + } + + let style = 0; + // if (inStyle.get() === "Graph")style = 1; + + if (style == 0) // PIE + { + const fontSize = size / 10; + ctx.font = "normal " + fontSize + "px sourceCodePro"; + + ctx.fillStyle = "#fff"; + ctx.fillText("total sum:" + Math.round(total * 100) / 100, layer.x + (size * 2) + padding * 2, layer.y + fontSize); + + for (let i = 0; i < arr.length; i++) + { + let name = ""; + if (arrNames && arrNames[i])name = arrNames[i]; + let perc = (Math.abs(arr[i]) / total); + let portionAngle = perc * 2 * Math.PI; + + ctx.beginPath(); + ctx.arc(layer.x + size, layer.y + size, Math.max(0, size - (padding * 2)), currentAngle, currentAngle + portionAngle); + currentAngle += portionAngle; + ctx.lineTo(layer.x + size, layer.y + size); + + ctx.fillStyle = colors[i % (colors.length - 1)]; + ctx.fill(); + + ctx.fillText(i + ": " + name + " " + Math.round(perc * 1000) / 10 + "%", layer.x + (size * 2) + padding * 2, layer.y + fontSize * (i + 1 + 1)); + } + + ctx.beginPath(); + ctx.fillStyle = "#222"; + ctx.arc(layer.x + size, layer.y + size, size / 5, 0, 2 * Math.PI); + ctx.fill(); + } + else if (style == 1) + { + let posy = 0; + for (let i = 0; i < arr.length; i++) + { + const perc = (Math.abs(arr[i]) / total); + const h = perc * layer.height; + + ctx.fillStyle = colors[i % (colors.length - 1)]; + ctx.fillRect( + layer.x + 21, layer.y + posy, + 12, h); + posy += h; + } + } +}; + + +}; + +Ops.Ui.VizArrayChart.prototype = new CABLES.Op(); +CABLES.OPS["04ff8596-d35a-4ad5-86d6-db6a8c2ce8f0"]={f:Ops.Ui.VizArrayChart,objName:"Ops.Ui.VizArrayChart"}; + + + + +// ************************************************************** +// +// Ops.Ui.VizArrayTable +// +// ************************************************************** + +Ops.Ui.VizArrayTable = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inArr = op.inArray("Array"), + inOffset = op.inInt("Start Row", 0); + +op.setUiAttrib({ "height": 200, "width": 400, "resizable": true }); + +op.renderVizLayer = (ctx, layer) => +{ + ctx.fillStyle = "#222"; + ctx.fillRect(layer.x, layer.y, layer.width, layer.height); + + ctx.save(); + ctx.scale(layer.scale, layer.scale); + + ctx.font = "normal 10px sourceCodePro"; + ctx.fillStyle = "#ccc"; + + const arr = inArr.get() || []; + let stride = 1; + + if (!arr) + { + op.setUiAttrib({ "extendTitle": "" }); + return; + } + + op.setUiAttrib({ "extendTitle": "length: " + arr.length }); + + if (inArr.links.length > 0 && inArr.links[0].getOtherPort(inArr)) + stride = inArr.links[0].getOtherPort(inArr).uiAttribs.stride || 1; + + let lines = Math.floor(layer.height / layer.scale / 10 - 1); + let padding = 4; + let offset = inOffset.get() * stride; + + for (let i = offset; i < offset + lines * stride; i += stride) + { + if (i < 0) continue; + if (i + stride > arr.length) continue; + + ctx.fillStyle = "#666"; + + const lineNum = (i) / stride; + + if (lineNum >= 0) + ctx.fillText(lineNum, + layer.x / layer.scale + padding, + layer.y / layer.scale + 10 + (i - offset) / stride * 10 + padding); + + for (let s = 0; s < stride; s++) + { + let str = ""; + const v = arr[i + s]; + + ctx.fillStyle = "#ccc"; + + if (typeof v == "string") str = "\"" + v + "\""; + else if (CABLES.UTILS.isNumeric(v)) str = String(Math.round(v * 10000) / 10000); + else if (Array.isArray(v)) + { + let preview = "..."; + if (v.length == 0) preview = ""; + str = "[" + preview + "] (" + v.length + ")"; + } + else if (typeof v == "object") + { + try + { + str = JSON.stringify(v, true, 1); + } + catch (e) + { + str = "{???}"; + } + } + else if (v != v || v === undefined) + { + ctx.fillStyle = "#f00"; + str += String(v); + } + else + { + str += String(v); + } + + ctx.fillText(str, + layer.x / layer.scale + s * 100 + 50, + layer.y / layer.scale + 10 + (i - offset) / stride * 10 + padding); + } + } + + const gradHeight = 30; + + if (offset > 0) + { + const radGrad = ctx.createLinearGradient(0, layer.y / layer.scale + 5, 0, layer.y / layer.scale + gradHeight); + radGrad.addColorStop(0, "#222"); + radGrad.addColorStop(1, "rgba(34,34,34,0.0)"); + ctx.fillStyle = radGrad; + ctx.fillRect(layer.x / layer.scale, layer.y / layer.scale, 200000, gradHeight); + } + + if (offset + lines * stride < arr.length) + { + const radGrad = ctx.createLinearGradient(0, layer.y / layer.scale + layer.height / layer.scale - gradHeight + 5, 0, layer.y / layer.scale + layer.height / layer.scale - gradHeight + gradHeight); + radGrad.addColorStop(1, "#222"); + radGrad.addColorStop(0, "rgba(34,34,34,0.0)"); + ctx.fillStyle = radGrad; + ctx.fillRect(layer.x / layer.scale, layer.y / layer.scale + layer.height / layer.scale - gradHeight, 200000, gradHeight); + } + + ctx.restore(); +}; + + +}; + +Ops.Ui.VizArrayTable.prototype = new CABLES.Op(); +CABLES.OPS["af2eeaaf-ff86-4bfb-9a27-42f05160a5d8"]={f:Ops.Ui.VizArrayTable,objName:"Ops.Ui.VizArrayTable"}; + + + + +// ************************************************************** +// +// Ops.Ui.VizBool +// +// ************************************************************** + +Ops.Ui.VizBool = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inNum = op.inBool("Boolean", 0), + outBool = op.outBoolNum("Bool"); + +op.setUiAttrib({ "height": 100, "width": 100, "resizable": true }); + +inNum.onChange = () => +{ + outBool.set(inNum.get()); +}; + +op.renderVizLayer = (ctx, layer) => +{ + ctx.fillStyle = "#222"; + ctx.fillRect( + layer.x, layer.y, + layer.width, layer.height); + + let isTrue = !!inNum.get(); + + let circle = new Path2D(); + let radius = Math.min(layer.height, layer.width) / 2.4 * 0.8; + if (radius < 0)radius = 0; + circle.arc(layer.x + layer.width / 2, layer.y + layer.height / 2, radius, 0, 2 * Math.PI, false); + + ctx.strokeStyle = "#555"; + ctx.lineWidth = 7 * layer.scale; + ctx.stroke(circle); + + if (isTrue) + { + if (op.uiAttribs.color)ctx.fillStyle = op.uiAttribs.color; + else ctx.fillStyle = "#ccc"; + + let circle = new Path2D(); + circle.arc(layer.x + layer.width / 2, layer.y + layer.height / 2, radius - (ctx.lineWidth / 2), 0, 2 * Math.PI, false); + ctx.fill(circle); + } +}; + + +}; + +Ops.Ui.VizBool.prototype = new CABLES.Op(); +CABLES.OPS["cf194306-175b-416a-b90e-31ff2192a190"]={f:Ops.Ui.VizBool,objName:"Ops.Ui.VizBool"}; + + + + +// ************************************************************** +// +// Ops.Ui.VizGraph +// +// ************************************************************** + +Ops.Ui.VizGraph = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inNum1 = op.inFloat("Number 1"), + inNum2 = op.inFloat("Number 2"), + inNum3 = op.inFloat("Number 3"), + inNum4 = op.inFloat("Number 4"), + inNum5 = op.inFloat("Number 5"), + inNum6 = op.inFloat("Number 6"), + inNum7 = op.inFloat("Number 7"), + inNum8 = op.inFloat("Number 8"), + inReset = op.inTriggerButton("Reset"); + +op.setUiAttrib({ "height": 150, "resizable": true }); + +let buff = []; + +let max = -Number.MAX_VALUE; +let min = Number.MAX_VALUE; + +inNum1.onLinkChanged = + inNum2.onLinkChanged = + inNum3.onLinkChanged = + inNum4.onLinkChanged = + inNum5.onLinkChanged = + inNum6.onLinkChanged = + inNum7.onLinkChanged = + inNum8.onLinkChanged = + inReset.onTriggered = () => + { + max = -Number.MAX_VALUE; + min = Number.MAX_VALUE; + buff = []; + }; + +op.renderVizLayer = (ctx, layer) => +{ + const perf = CABLES.UI.uiProfiler.start("previewlayer graph"); + + const colors = [ + "#00ffff", + "#ffff00", + "#ff00ff", + "#0000ff", + "#00ff00", + "#ff0000", + "#ffffff", + "#888888", + ]; + + ctx.fillStyle = "#222"; + ctx.fillRect(layer.x, layer.y, layer.width, layer.height); + + for (let p = 0; p < op.portsIn.length; p++) + { + if (!op.portsIn[p].isLinked()) continue; + const newVal = op.portsIn[p].get(); + + max = Math.max(op.portsIn[p].get(), max); + min = Math.min(op.portsIn[p].get(), min); + + if (!buff[p]) buff[p] = []; + buff[p].push(newVal); + if (buff[p].length > 60) buff[p].shift(); + + const texSlot = 5; + const mulX = layer.width / 60; + + ctx.lineWidth = 2; + ctx.strokeStyle = "#555555"; + + ctx.beginPath(); + ctx.moveTo(layer.x, CABLES.map(0, min, max, layer.height, 0) + layer.y); + ctx.lineTo(layer.x + layer.width, CABLES.map(0, min, max, layer.height, 0) + layer.y); + ctx.stroke(); + + ctx.strokeStyle = colors[p]; + + ctx.beginPath(); + + for (let i = 0; i < buff[p].length; i++) + { + let y = buff[p][i]; + + y = CABLES.map(y, min, max, layer.height, 0); + y += layer.y; + if (i === 0)ctx.moveTo(layer.x, y); + else ctx.lineTo(layer.x + i * mulX, y); + } + + ctx.stroke(); + } + + ctx.fillStyle = "#888"; + ctx.fillText("max:" + Math.round(max * 100) / 100, layer.x + 10, layer.y + layer.height - 10); + ctx.fillText("min:" + Math.round(min * 100) / 100, layer.x + 10, layer.y + layer.height - 30); + + perf.finish(); +}; + + +}; + +Ops.Ui.VizGraph.prototype = new CABLES.Op(); +CABLES.OPS["13c54eb4-60ef-4b9c-8425-d52a431f5c87"]={f:Ops.Ui.VizGraph,objName:"Ops.Ui.VizGraph"}; + + + + +// ************************************************************** +// +// Ops.Ui.VizLogger +// +// ************************************************************** + +Ops.Ui.VizLogger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inNum = op.inFloat("Number", 0); +const inString = op.inString("String", ""); +const inClear = op.inTriggerButton("Clear"); + +let lines = 10; +const arr = []; + +inClear.onTriggered = () => +{ + arr.length = 0; +}; + +inString.onChange = () => +{ + arr.push("" + inString.get()); +}; + +inNum.onChange = () => +{ + arr.push("" + inNum.get()); +}; + +op.setUiAttrib({ "height": 200, "width": 400, "resizable": true }); + +op.renderVizLayer = (ctx, layer) => +{ + ctx.fillStyle = "#222"; + ctx.fillRect( + layer.x, layer.y, + layer.width, layer.height); + + ctx.save(); + ctx.scale(layer.scale, layer.scale); + + ctx.font = "normal 10px sourceCodePro"; + ctx.fillStyle = "#ccc"; + + if (lines > 0) while (arr.length - 1 > lines) arr.shift(); + + lines = Math.floor(layer.height / layer.scale / 10 - 1); + let padding = 4; + + ctx.fillStyle = "#ccc"; + + for (let i = Math.min(lines, arr.length - 1); i > 0; i--) + { + ctx.fillText(arr[i], layer.x / layer.scale + padding, layer.y / layer.scale + 10 * i + padding); + } + + ctx.restore(); +}; + + +}; + +Ops.Ui.VizLogger.prototype = new CABLES.Op(); +CABLES.OPS["22b731fe-bc97-42fe-a550-92cf0cedb133"]={f:Ops.Ui.VizLogger,objName:"Ops.Ui.VizLogger"}; + + + + +// ************************************************************** +// +// Ops.Ui.VizNumber +// +// ************************************************************** + +Ops.Ui.VizNumber = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inNum = op.inFloat("Number", 0); +const outNum = op.outNumber("Result"); + +op.setUiAttrib({ "widthOnlyGrow": true }); + +inNum.onChange = () => +{ + let n = inNum.get(); + if (op.patch.isEditorMode()) + { + let str = ""; + if (n === null)str = "null"; + else if (n === undefined)str = "undefined"; + else + { + str = "" + Math.round(n * 10000) / 10000; + + if (str[0] != "-")str = " " + str; + } + + op.setUiAttribs({ "extendTitle": str }); + } + + outNum.set(n); +}; + + +}; + +Ops.Ui.VizNumber.prototype = new CABLES.Op(); +CABLES.OPS["2b60d12d-2884-4ad0-bda4-0caeb6882f5c"]={f:Ops.Ui.VizNumber,objName:"Ops.Ui.VizNumber"}; + + + + +// ************************************************************** +// +// Ops.Ui.VizNumberBar +// +// ************************************************************** + +Ops.Ui.VizNumberBar = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inNum = op.inFloat("Number", 0); + // inDrawBar=op.inBool("Draw Bar",true), + // inDrawNUm=op.inBool("Draw Number",true); + +op.setUiAttrib({ "height": 100, "width": 200, "resizable": true }); + +let max = -Number.MAX_VALUE; +let min = Number.MAX_VALUE; + +inNum.onLinkChanged = () => +{ + max = -Number.MAX_VALUE; + min = Number.MAX_VALUE; +}; + +op.renderVizLayer = (ctx, layer) => +{ + ctx.fillStyle = "#222"; + ctx.fillRect( + layer.x, layer.y, + layer.width, layer.height); + + // if(inDrawBar.get()) + { + max = Math.max(max, inNum.get()); + min = Math.min(min, inNum.get()); + + if (op.uiAttribs.color)ctx.fillStyle = op.uiAttribs.color; + else ctx.fillStyle = "#555"; + + let a = CABLES.map(0, min, max, 0, layer.width); + let b = CABLES.map(inNum.get(), min, max, 0, layer.width); + + let xMin = Math.min(a, b); + let xMax = Math.max(a, b); + + ctx.fillRect( + xMin + layer.x, layer.y, + xMax - xMin, layer.height); + } + + // if(inDrawNUm.get()) + { + const padding = 10; + if (op.uiAttribs.color)ctx.fillStyle = "#fff"; + else ctx.fillStyle = "#ccc"; + + const fontSize = layer.height * 0.7; + ctx.font = "normal " + fontSize + "px sourceCodePro"; + ctx.fillText(Math.round(inNum.get() * 10000) / 10000, layer.x + padding, layer.y + fontSize); + } +}; + + +}; + +Ops.Ui.VizNumberBar.prototype = new CABLES.Op(); +CABLES.OPS["37575d2e-4ba6-4d2b-b00c-c503666867c5"]={f:Ops.Ui.VizNumberBar,objName:"Ops.Ui.VizNumberBar"}; + + + + +// ************************************************************** +// +// Ops.Ui.VizObject +// +// ************************************************************** + +Ops.Ui.VizObject = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inObj = op.inObject("Object"), + inConsole = op.inTriggerButton("console log"); + +inConsole.setUiAttribs({ "hidePort": true }); + +op.setUiAttrib({ "height": 200, "width": 400, "resizable": true }); + +inObj.onLinkChanged = () => +{ + if (inObj.isLinked()) + { + const p = inObj.links[0].getOtherPort(inObj); + + op.setUiAttrib({ "extendTitle": p.uiAttribs.objType }); + } +}; + +inConsole.onTriggered = () => +{ + console.log(inObj.get()); +}; + +op.renderVizLayer = (ctx, layer) => +{ + ctx.fillStyle = "#222"; + ctx.fillRect(layer.x, layer.y, layer.width, layer.height); + + ctx.save(); + ctx.scale(layer.scale, layer.scale); + + ctx.font = "normal 10px sourceCodePro"; + ctx.fillStyle = "#ccc"; + const padding = 10; + + let obj = inObj.get(); + + let str = "???"; + + if (obj && obj.getInfo) + { + obj = obj.getInfo(); + } + + if (obj instanceof Element) + { + const o = {}; + + o.id = obj.getAttribute("id"); + o.classes = obj.classList.value; + o.innerText = obj.innerText; + o.tagName = obj.tagName; + + obj = o; + } + + if (obj && obj.constructor && obj.constructor.name != "Object") + { + // str = + "()\n" + str; + op.setUiAttribs({ "extendTitle": obj.constructor.name }); + } + + try + { + str = JSON.stringify(obj, false, 4); + + if (str == "{}" && obj && obj.constructor && obj.constructor.name != "Object") + { + str = "could not stringify object: " + obj.constructor.name + "\n"; + + if (obj) for (let i in obj) + { + str += "\n" + i + " (" + typeof obj[i] + ")"; + // console.log(i) + } + } + } + catch (e) + { + str = "object can not be displayed as string"; + } + + if (str === undefined)str = "undefined"; + if (str === null)str = "null"; + str = String(str); + let lines = str.split("\n"); + + for (let j = 0; j < lines.length; j++) + ctx.fillText(lines[j], layer.x / layer.scale + padding, layer.y / layer.scale + ((j + 1) * 12)); + + ctx.restore(); +}; + + +}; + +Ops.Ui.VizObject.prototype = new CABLES.Op(); +CABLES.OPS["d09bc53e-9f52-4872-94c7-4ef777512222"]={f:Ops.Ui.VizObject,objName:"Ops.Ui.VizObject"}; + + + + +// ************************************************************** +// +// Ops.Ui.VizString +// +// ************************************************************** + +Ops.Ui.VizString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inStr = op.inString("String", ""); +const outNum = op.outString("Result"); + +op.setUiAttrib({ "widthOnlyGrow": true }); + +inStr.onChange = () => +{ + let str = inStr.get(); + if (op.patch.isEditorMode()) + { + if (str === null)str = "null"; + else if (str === undefined)str = "undefined"; + else str = "\"" + (String(str) || "") + "\""; + op.setTitle(str); + } + + outNum.set(inStr.get()); +}; + + +}; + +Ops.Ui.VizString.prototype = new CABLES.Op(); +CABLES.OPS["b04ff547-f557-4a54-a3ad-8a668fe1303d"]={f:Ops.Ui.VizString,objName:"Ops.Ui.VizString"}; + + + + +// ************************************************************** +// +// Ops.Ui.VizStringLong +// +// ************************************************************** + +Ops.Ui.VizStringLong = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr = op.inStringEditor("String"), + inPos = op.inFloatSlider("Scroll", 0); + +op.setUiAttrib({ "height": 200, "width": 400, "resizable": true }); +inStr.ignoreValueSerialize = true; + +let lines = []; + +inStr.onLinkChanged = () => +{ + if (!inStr.isLinked()) + { + lines = []; + inStr.set(null); + } +}; + +inStr.onChange = () => +{ + if (inStr.get()) lines = inStr.get().split("\n"); + else lines = []; +}; + +op.renderVizLayer = (ctx, layer) => +{ + ctx.fillStyle = "#222"; + ctx.fillRect(layer.x, layer.y, layer.width, layer.height); + + if (!inStr.get()) return; + + ctx.save(); + ctx.scale(layer.scale, layer.scale); + + ctx.font = "normal 10px sourceCodePro"; + ctx.fillStyle = "#ccc"; + + let padding = 4; + + const lineHeight = 10; + + const numLines = Math.floor(layer.height / layer.scale / lineHeight); + + let offset = Math.floor(inPos.get() * lines.length); + + offset = Math.max(offset, 0); + offset = Math.min(offset, lines.length - numLines); + if (lines.length < numLines)offset = 0; + + const offsetLeft = ((offset + numLines + " ").length - 1) * 9.5; + + let indent = ""; + for (let i = 0; i < (offset + numLines + " ").length; i++) indent += " "; + + for (let i = offset; i < offset + numLines; i += 1) + { + if (i >= lines.length || i < 0) continue; + + ctx.fillStyle = "#888"; + + ctx.fillText(i, + layer.x / layer.scale + padding, + layer.y / layer.scale + lineHeight + (i - offset) * lineHeight + padding); + + ctx.fillStyle = "#ccc"; + + ctx.fillText(indent + lines[i], + layer.x / layer.scale + padding, + layer.y / layer.scale + lineHeight + (i - offset) * lineHeight + padding); + } + + const gradHeight = 30; + + if (offset > 0) + { + const radGrad = ctx.createLinearGradient(0, layer.y / layer.scale + 5, 0, layer.y / layer.scale + gradHeight); + radGrad.addColorStop(0, "#222"); + radGrad.addColorStop(1, "rgba(34,34,34,0.0)"); + ctx.fillStyle = radGrad; + ctx.fillRect(layer.x / layer.scale, layer.y / layer.scale, 200000, gradHeight); + } + + if (offset + numLines < lines.length) + { + const radGrad = ctx.createLinearGradient(0, layer.y / layer.scale + layer.height / layer.scale - gradHeight + 5, 0, layer.y / layer.scale + layer.height / layer.scale - gradHeight + gradHeight); + radGrad.addColorStop(1, "#222"); + radGrad.addColorStop(0, "rgba(34,34,34,0.0)"); + ctx.fillStyle = radGrad; + ctx.fillRect(layer.x / layer.scale, layer.y / layer.scale + layer.height / layer.scale - gradHeight, 200000, gradHeight); + } + + ctx.restore(); +}; + + +}; + +Ops.Ui.VizStringLong.prototype = new CABLES.Op(); +CABLES.OPS["b4c93fde-85c6-4c7e-9962-a6463a84838b"]={f:Ops.Ui.VizStringLong,objName:"Ops.Ui.VizStringLong"}; + + + + +// ************************************************************** +// +// Ops.Ui.VizTexture +// +// ************************************************************** + +Ops.Ui.VizTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"viztex_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI samplerCube cubeMap;\nUNI float width;\nUNI float height;\nUNI float type;\nUNI float time;\n\nfloat LinearizeDepth(float d,float zNear,float zFar)\n{\n float z_n = 2.0 * d - 1.0;\n return 2.0 * zNear / (zFar + zNear - z_n * (zFar - zNear));\n}\n\nvoid main()\n{\n vec4 col=vec4(vec3(0.),0.0);\n\n vec4 colTex=texture(tex,texCoord);\n\n\n\n if(type==1.0)\n {\n vec4 depth=vec4(0.);\n vec2 localST=texCoord;\n localST.y = 1. - localST.y;\n\n localST.t = mod(localST.t*3.,1.);\n localST.s = mod(localST.s*4.,1.);\n\n #ifdef WEBGL2\n #define texCube texture\n #endif\n #ifdef WEBGL1\n #define texCube textureCube\n #endif\n\n// //Due to the way my depth-cubeMap is rendered, objects to the -x,y,z side is projected to the positive x,y,z side\n// //Inside where top/bottom is to be drawn?\n if (texCoord.s*4.> 1. && texCoord.s*4.<2.)\n {\n //Bottom (-y) quad\n if (texCoord.t*3. < 1.)\n {\n vec3 dir=vec3(localST.s*2.-1.,-1.,-localST.t*2.+1.);//Due to the (arbitrary) way I choose as up in my depth-viewmatrix, i her emultiply the latter coordinate with -1\n depth = texCube(cubeMap, dir);\n }\n //top (+y) quad\n else if (texCoord.t*3. > 2.)\n {\n vec3 dir=vec3(localST.s*2.-1.,1.,localST.t*2.-1.);//Get lower y texture, which is projected to the +y part of my cubeMap\n depth = texCube(cubeMap, dir);\n }\n else//Front (-z) quad\n {\n vec3 dir=vec3(localST.s*2.-1.,-localST.t*2.+1.,1.);\n depth = texCube(cubeMap, dir);\n }\n }\n// //If not, only these ranges should be drawn\n else if (texCoord.t*3. > 1. && texCoord.t*3. < 2.)\n {\n if (texCoord.x*4. < 1.)//left (-x) quad\n {\n vec3 dir=vec3(-1.,-localST.t*2.+1.,localST.s*2.-1.);\n depth = texCube(cubeMap, dir);\n }\n else if (texCoord.x*4. < 3.)//right (+x) quad (front was done above)\n {\n vec3 dir=vec3(1,-localST.t*2.+1.,-localST.s*2.+1.);\n depth = texCube(cubeMap, dir);\n }\n else //back (+z) quad\n {\n vec3 dir=vec3(-localST.s*2.+1.,-localST.t*2.+1.,-1.);\n depth = texCube(cubeMap, dir);\n }\n }\n // colTex = vec4(vec3(depth),1.);\n colTex = vec4(depth);\n }\n\n if(type==2.0)\n {\n float near = 0.1;\n float far = 50.;\n float depth = LinearizeDepth(colTex.r, near, far);\n colTex.rgb = vec3(depth);\n }\n\n if(colTex.r>1.0 || colTex.r<0.0)\n {\n float r=mod( time+colTex.r,1.0)*0.5+0.5;\n colTex.r=r;\n }\n if(colTex.g>1.0 || colTex.g<0.0)\n {\n float r=mod( time+colTex.g,1.0)*0.5+0.5;\n colTex.g=r;\n }\n if(colTex.b>1.0 || colTex.b<0.0)\n {\n float r=mod( time+colTex.b,1.0)*0.5+0.5;\n colTex.b=r;\n }\n\n\n outColor = mix(col,colTex,colTex.a);\n}\n\n","viztex_vert":"IN vec3 vPosition;\nIN vec2 attrTexCoord;\nOUT vec2 texCoord;\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\n\nvoid main()\n{\n texCoord=vec2(attrTexCoord.x,1.0-attrTexCoord.y);\n vec4 pos = vec4( vPosition, 1. );\n mat4 mvMatrix=viewMatrix * modelMatrix;\n gl_Position = projMatrix * mvMatrix * pos;\n}",}; +const + inTex = op.inTexture("Texture In"), + inShowInfo = op.inBool("Show Info", false), + outTex = op.outTexture("Texture Out"), + outInfo = op.outString("Info"); + +op.setUiAttrib({ "height": 150, "resizable": true }); + +const timer = new CABLES.Timer(); +timer.play(); + +inTex.onChange = () => +{ + const t = inTex.get(); + + outTex.set(CGL.Texture.getEmptyTexture(op.patch.cgl)); + outTex.set(t); +}; + +op.renderVizLayer = (ctx, layer) => +{ + const port = inTex; + const texSlot = 5; + const texSlotCubemap = texSlot + 1; + + const perf = CABLES.UI.uiProfiler.start("previewlayer texture"); + const cgl = port.parent.patch.cgl; + + if (!this._emptyCubemap) this._emptyCubemap = CGL.Texture.getEmptyCubemapTexture(cgl); + port.parent.patch.cgl.profileData.profileTexPreviews++; + + const portTex = port.get() || CGL.Texture.getEmptyTexture(cgl); + + if (!this._mesh) + { + const geom = new CGL.Geometry("preview op rect"); + geom.vertices = [1.0, 1.0, 0.0, -1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -1.0, -1.0, 0.0]; + geom.texCoords = [ + 1.0, 1.0, + 0.0, 1.0, + 1.0, 0.0, + 0.0, 0.0]; + geom.verticesIndices = [0, 1, 2, 3, 1, 2]; + this._mesh = new CGL.Mesh(cgl, geom); + } + if (!this._shader) + { + this._shader = new CGL.Shader(cgl, "glpreviewtex"); + this._shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); + this._shader.setSource(attachments.viztex_vert, attachments.viztex_frag); + this._shaderTexUniform = new CGL.Uniform(this._shader, "t", "tex", texSlot); + this._shaderTexCubemapUniform = new CGL.Uniform(this._shader, "tc", "cubeMap", texSlotCubemap); + + this._shaderTexUniformW = new CGL.Uniform(this._shader, "f", "width", portTex.width); + this._shaderTexUniformH = new CGL.Uniform(this._shader, "f", "height", portTex.height); + this._shaderTypeUniform = new CGL.Uniform(this._shader, "f", "type", 0); + this._shaderTimeUniform = new CGL.Uniform(this._shader, "f", "time", 0); + } + + cgl.pushPMatrix(); + const sizeTex = [portTex.width, portTex.height]; + const small = port.parent.patch.cgl.canvasWidth > sizeTex[0] && port.parent.patch.cgl.canvasHeight > sizeTex[1]; + + if (small) + { + mat4.ortho(cgl.pMatrix, 0, port.parent.patch.cgl.canvasWidth, port.parent.patch.cgl.canvasHeight, 0, 0.001, 11); + } + else mat4.ortho(cgl.pMatrix, -1, 1, 1, -1, 0.001, 11); + + const oldTex = cgl.getTexture(texSlot); + const oldTexCubemap = cgl.getTexture(texSlotCubemap); + + let texType = 0; + if (!portTex) return; + if (portTex.cubemap) texType = 1; + if (portTex.textureType == CGL.Texture.TYPE_DEPTH) texType = 2; + + if (texType == 0 || texType == 2) + { + cgl.setTexture(texSlot, portTex.tex); + cgl.setTexture(texSlotCubemap, this._emptyCubemap.cubemap, cgl.gl.TEXTURE_CUBE_MAP); + } + else if (texType == 1) + { + cgl.setTexture(texSlotCubemap, portTex.cubemap, cgl.gl.TEXTURE_CUBE_MAP); + } + + timer.update(); + this._shaderTimeUniform.setValue(timer.get()); + + this._shaderTypeUniform.setValue(texType); + let s = [port.parent.patch.cgl.canvasWidth, port.parent.patch.cgl.canvasHeight]; + + cgl.gl.clearColor(0, 0, 0, 0); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); + + cgl.pushModelMatrix(); + if (small) + { + s = sizeTex; + mat4.translate(cgl.mMatrix, cgl.mMatrix, [sizeTex[0] / 2, sizeTex[1] / 2, 0]); + mat4.scale(cgl.mMatrix, cgl.mMatrix, [sizeTex[0] / 2, sizeTex[1] / 2, 0]); + } + this._mesh.render(this._shader); + cgl.popModelMatrix(); + + if (texType == 0) cgl.setTexture(texSlot, oldTex); + if (texType == 1) cgl.setTexture(texSlotCubemap, oldTexCubemap); + + cgl.popPMatrix(); + cgl.resetViewPort(); + + const sizeImg = [layer.width, layer.height]; + + const stretch = false; + if (!stretch) + { + if (portTex.width > portTex.height) sizeImg[1] = layer.width * sizeTex[1] / sizeTex[0]; + else + { + sizeImg[1] = layer.width * (sizeTex[1] / sizeTex[0]); + + if (sizeImg[1] > layer.height) + { + const r = layer.height / sizeImg[1]; + sizeImg[0] *= r; + sizeImg[1] *= r; + } + } + } + + const scaledDown = sizeImg[0] > sizeTex[0] && sizeImg[1] > sizeTex[1]; + + ctx.imageSmoothingEnabled = !small || !scaledDown; + + if (!ctx.imageSmoothingEnabled) + { + ctx.fillStyle = "#ffffff"; + ctx.fillRect(layer.x, layer.y - 10, 10, 10); + ctx.fillStyle = "#000000"; + ctx.fillRect(layer.x, layer.y - 10, 5, 5); + ctx.fillRect(layer.x + 5, layer.y - 10 + 5, 5, 5); + } + + let numX = (10 * layer.width / layer.height); + let stepY = (layer.height / 10); + let stepX = (layer.width / numX); + for (let x = 0; x < numX; x++) + for (let y = 0; y < 10; y++) + { + if ((x + y) % 2 == 0)ctx.fillStyle = "#333333"; + else ctx.fillStyle = "#393939"; + ctx.fillRect(layer.x + stepX * x, layer.y + stepY * y, stepX, stepY); + } + + ctx.fillStyle = "#222"; + const borderLeft = (layer.width - sizeImg[0]) / 2; + const borderTop = (layer.height - sizeImg[1]) / 2; + ctx.fillRect( + layer.x, layer.y, + borderLeft, (layer.height) + ); + ctx.fillRect( + layer.x + sizeImg[0] + borderLeft, layer.y, + borderLeft, (layer.height) + ); + ctx.fillRect( + layer.x, layer.y, + layer.width, borderTop + ); + ctx.fillRect( + layer.x, layer.y + sizeImg[1] + borderTop, + layer.width, borderTop + ); + + if (sizeTex[1] == 1) + ctx.drawImage(cgl.canvas, + 0, 0, + s[0], s[1], + layer.x, layer.y, + layer.width, layer.height * 5);// workaround filtering problems + if (sizeTex[0] == 1) + ctx.drawImage(cgl.canvas, + 0, 0, + s[0], s[1], + layer.x, layer.y, + layer.width * 5, layer.height); // workaround filtering problems + else + ctx.drawImage(cgl.canvas, + 0, 0, + s[0], s[1], + layer.x + (layer.width - sizeImg[0]) / 2, layer.y + (layer.height - sizeImg[1]) / 2, + sizeImg[0], sizeImg[1]); + + let info = "unknown"; + + if (port.get() && port.get().getInfoOneLine) info = port.get().getInfoOneLine(); + + if (inShowInfo.get()) + { + ctx.save(); + ctx.scale(layer.scale, layer.scale); + ctx.font = "normal 10px sourceCodePro"; + ctx.fillStyle = "#000"; + ctx.fillText(info, layer.x / layer.scale + 5 + 0.75, (layer.y + layer.height) / layer.scale - 5 + 0.75); + ctx.fillStyle = "#fff"; + ctx.fillText(info, layer.x / layer.scale + 5, (layer.y + layer.height) / layer.scale - 5); + ctx.restore(); + } + + outInfo.set(info); + + cgl.gl.clearColor(0, 0, 0, 0); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); + + perf.finish(); +}; + + +}; + +Ops.Ui.VizTexture.prototype = new CABLES.Op(); +CABLES.OPS["4ea2d7b0-ca74-45db-962b-4d1965ac20c0"]={f:Ops.Ui.VizTexture,objName:"Ops.Ui.VizTexture"}; + + + + +// ************************************************************** +// +// Ops.Ui.VizTextureTable +// +// ************************************************************** + +Ops.Ui.VizTextureTable = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inTex = op.inTexture("Texture"); + +op.setUiAttrib({ "height": 200, "width": 380, "resizable": true }); + +let pixelData = null; +let lastWidth; +let lastHeight; +let fb; +let lastFloatingPoint; +let lastRead = 0; +const arr = []; + +inTex.onLinkChanged = () => +{ + op.setUiAttrib({ "extendTitle": "" }); +}; + +op.renderVizLayer = (ctx, layer) => +{ + const + realTexture = inTex.get(), + gl = op.patch.cgl.gl; + + ctx.fillStyle = "#222"; + ctx.fillRect(layer.x, layer.y, layer.width, layer.height); + + if (!realTexture) return; + + let lines = Math.floor(layer.height / layer.scale / 10 - 1); + + ctx.save(); + ctx.scale(layer.scale, layer.scale); + + ctx.font = "normal 10px sourceCodePro"; + ctx.fillStyle = "#ccc"; + + if (!fb) fb = gl.createFramebuffer(); + + let channels = gl.RGBA; + let numChannels = 4; + + let texChanged = true; + let channelType = gl.UNSIGNED_BYTE; + + if (texChanged) + { + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + gl.framebufferTexture2D( + gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, + gl.TEXTURE_2D, realTexture.tex, 0 + ); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + let isFloatingPoint = realTexture.isFloatingPoint(); + if (isFloatingPoint) channelType = gl.FLOAT; + + if ( + lastFloatingPoint != isFloatingPoint || + lastWidth != realTexture.width || + lastHeight != realTexture.height) + { + const size = realTexture.width * realTexture.height * numChannels; + if (isFloatingPoint) pixelData = new Float32Array(size); + else pixelData = new Uint8Array(size); + + lastFloatingPoint = isFloatingPoint; + lastWidth = realTexture.width; + lastHeight = realTexture.height; + } + + texChanged = false; + } + + let texRows = Math.max(1, Math.ceil(lines / realTexture.width)); + texRows = Math.min(texRows, realTexture.height); + let readW = realTexture.width; + if (lines / realTexture.width < 1)readW = realTexture.width * lines / realTexture.width; + const readH = texRows; + let readPixels = false; + + if (performance.now() - lastRead > 100)readPixels = true; + + if (readPixels) + { + lastRead = performance.now(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + + gl.readPixels( + 0, + realTexture.height - texRows, + readW, + readH, + channels, + channelType, + pixelData + ); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + } + + arr.length = pixelData.length; + let stride = 4; + let padding = 4; + let lineHeight = 10; + let isFp = realTexture.isFloatingPoint(); + + for (let x = 0; x < readW; x++) + for (let y = 0; y < readH; y++) + for (let s = 0; s < stride; s++) + arr[(x + (y * readW)) * stride + s] = pixelData[((x) + ((readH - y - 1) * readW)) * stride + s]; + + if (realTexture && realTexture.getInfoOneLine) + op.setUiAttrib({ "extendTitle": realTexture.getInfoOneLine() }); + + for (let y = 0; y < readH; y++) + for (let x = 0; x < readW; x++) + { + const count = x + y * readW; + + const i = x * stride + (y * readW * stride); + + ctx.fillStyle = "#666"; + + ctx.fillText(i / stride, + layer.x / layer.scale + padding, + layer.y / layer.scale + lineHeight + i / stride * lineHeight + padding); + + const idx = count * stride; + + if (inTex.get().isFloatingPoint()) ctx.fillStyle = "rgba(" + arr[idx + 0] * 255 + "," + arr[idx + 1] * 255 + "," + arr[idx + 2] * 255 + "," + arr[idx + 3] * 255 + ")"; + else ctx.fillStyle = "rgba(" + arr[idx + 0] + "," + arr[idx + 1] + "," + arr[idx + 2] + "," + arr[idx + 3] + ")"; + + ctx.fillRect( + layer.x / layer.scale + padding + 25, + layer.y / layer.scale + lineHeight + count * lineHeight + padding - 7, + 15, 8); + + ctx.fillStyle = "#ccc"; + + for (let s = 0; s < stride; s++) + { + let v = arr[i + s]; + let str = "" + v; + + if (!isFp)v /= 255; + str = String(Math.round(v * 10000) / 10000); + + ctx.fillText(str, layer.x / layer.scale + s * 60 + 70, layer.y / layer.scale + 10 + (i / stride) * 10 + padding); + } + } + + const gradHeight = 30; + + if (lines < readH * readW) + { + const radGrad = ctx.createLinearGradient(0, layer.y / layer.scale + layer.height / layer.scale - gradHeight + 5, 0, layer.y / layer.scale + layer.height / layer.scale - gradHeight + gradHeight); + radGrad.addColorStop(1, "#222"); + radGrad.addColorStop(0, "rgba(34,34,34,0.0)"); + ctx.fillStyle = radGrad; + ctx.fillRect(layer.x / layer.scale, layer.y / layer.scale + layer.height / layer.scale - gradHeight, 200000, gradHeight); + } + + ctx.restore(); +}; + + +}; + +Ops.Ui.VizTextureTable.prototype = new CABLES.Op(); +CABLES.OPS["0e5cde34-35cd-440d-b8cd-f78e1b5b7722"]={f:Ops.Ui.VizTextureTable,objName:"Ops.Ui.VizTextureTable"}; + + + + +// ************************************************************** +// +// Ops.Value.Boolean +// +// ************************************************************** + +Ops.Value.Boolean = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + v = op.inValueBool("value", false), + result = op.outBoolNum("result"); + +result.set(false); +v.onChange = exec; + +function exec() +{ + if (result.get() != v.get()) result.set(v.get()); +} + + +}; + +Ops.Value.Boolean.prototype = new CABLES.Op(); +CABLES.OPS["83e2d74c-9741-41aa-a4d7-1bda4ef55fb3"]={f:Ops.Value.Boolean,objName:"Ops.Value.Boolean"}; + + + + +// ************************************************************** +// +// Ops.Value.ColorValue +// +// ************************************************************** + +Ops.Value.ColorValue = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const r = op.inValueSlider("r", Math.random()); +const g = op.inValueSlider("g", Math.random()); +const b = op.inValueSlider("b", Math.random()); +r.setUiAttribs({ "colorPick": true }); +const a = op.inValueSlider("a"); + +const outR = op.outNumber("outr"); +const outG = op.outNumber("outg"); +const outB = op.outNumber("outb"); +const outA = op.outNumber("outa"); +const outHex = op.outNumber("Hex", "000000"); +const arrOut = op.outArray("Array"); + +r.onChange = g.onChange = b.onChange = a.onChange = exec; + +/** + * Float [0..1] -> Hex String [00..FF] + */ +function floatToHex(f) +{ + let s = Math.round(f * 255).toString(16); + if (s.length === 1) + { + s = "0" + s; + } + return s.toUpperCase(); +} + +function exec() +{ + outR.set(r.get()); + outG.set(g.get()); + outB.set(b.get()); + outA.set(a.get()); + + let hex = floatToHex(r.get()) + floatToHex(g.get()) + floatToHex(b.get()); + outHex.set(hex); + + arrOut.set([r.get(), g.get(), b.get()]); +} + +exec(); + + +}; + +Ops.Value.ColorValue.prototype = new CABLES.Op(); +CABLES.OPS["7caa37c8-f2a7-49f2-a29c-96af362abca0"]={f:Ops.Value.ColorValue,objName:"Ops.Value.ColorValue"}; + + + + +// ************************************************************** +// +// Ops.Value.DelayBooleanSimple +// +// ************************************************************** + +Ops.Value.DelayBooleanSimple = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + val = op.inFloat("Value"), + delTrue = op.inFloat("Delay True", 1), + delFalse = op.inFloat("Delay False", 1), + outVal = op.outBoolNum("Out Value"); + +let timeout = -1; + +val.onChange = + delFalse.onChange = + delTrue.onChange = update; + +function update() +{ + clearTimeout(timeout); + let v = val.get(); + + let delay = 1; + if (v) delay = delTrue.get() * 1000; + else delay = delFalse.get() * 1000; + + timeout = setTimeout(function () + { + outVal.set(v); + }, delay); +} + + +}; + +Ops.Value.DelayBooleanSimple.prototype = new CABLES.Op(); +CABLES.OPS["4516be54-9077-490f-a094-83696b9011ba"]={f:Ops.Value.DelayBooleanSimple,objName:"Ops.Value.DelayBooleanSimple"}; + + + + +// ************************************************************** +// +// Ops.Value.DelayNumberSimple +// +// ************************************************************** + +Ops.Value.DelayNumberSimple = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + val = op.inValue("Value"), + de = op.inValue("Delay", 1), + outVal = op.outNumber("Out Value"); + +let timeout = -1; + +val.onChange = update; +de.onChange = update; + +function update() +{ + clearTimeout(timeout); + let v = val.get(); + timeout = setTimeout(function () + { + outVal.set(v); + }, de.get() * 1000); +} + + +}; + +Ops.Value.DelayNumberSimple.prototype = new CABLES.Op(); +CABLES.OPS["89ea7e9c-0dfb-4e1e-8e61-4e79112ee533"]={f:Ops.Value.DelayNumberSimple,objName:"Ops.Value.DelayNumberSimple"}; + + + + +// ************************************************************** +// +// Ops.Value.DelayStringSimple +// +// ************************************************************** + +Ops.Value.DelayStringSimple = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + val=op.inString("Value"), + de=op.inValue("Delay",1), + outVal=op.outString("Out Value"); + +let timeout=-1; + +val.onChange= + de.onChange=update; + +function update() +{ + clearTimeout(timeout); + var v=val.get(); + timeout=setTimeout(function() + { + outVal.set(v); + },de.get()*1000); + +} + + +}; + +Ops.Value.DelayStringSimple.prototype = new CABLES.Op(); +CABLES.OPS["0e3c0986-071e-4c98-be84-7f17306490c6"]={f:Ops.Value.DelayStringSimple,objName:"Ops.Value.DelayStringSimple"}; + + + + +// ************************************************************** +// +// Ops.Value.DelayedValue +// +// ************************************************************** + +Ops.Value.DelayedValue = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("Update"), + v = op.inValue("Value", 0), + delay = op.inValue("Delay", 0.5), + result = op.outNumber("Result", 0), + clear = op.inValueBool("Clear on Change", false); + +const anim = new CABLES.Anim(); +anim.createPort(op, "easing", function () {}).set("absolute"); + +exe.onTriggered = function () +{ + result.set(anim.getValue(op.patch.freeTimer.get()) || 0); +}; + +v.onChange = function () +{ + const current = anim.getValue(op.patch.freeTimer.get()); + const t = op.patch.freeTimer.get(); + + if (clear.get()) anim.clear(t); + + anim.setValue(t + delay.get(), v.get()); + + let lastKey = 0; + for (let i = 0; i < anim.keys.length; i++) + { + if (anim.keys[i].time < t)lastKey = i; + } + if (lastKey > 2) anim.keys.splice(0, lastKey); +}; + + +}; + +Ops.Value.DelayedValue.prototype = new CABLES.Op(); +CABLES.OPS["8e7741e0-0b1b-40f3-a62c-ac8a8828dffb"]={f:Ops.Value.DelayedValue,objName:"Ops.Value.DelayedValue"}; + + + + +// ************************************************************** +// +// Ops.Value.FileInput_v2 +// +// ************************************************************** + +Ops.Value.FileInput_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inFile = op.inUrl("File"); +const outPath = op.outString("URL"); + +inFile.onChange = function () +{ + const url = op.patch.getFilePath(String(inFile.get())); + outPath.set(url); +}; + + +}; + +Ops.Value.FileInput_v2.prototype = new CABLES.Op(); +CABLES.OPS["3f20a79f-a35f-4a4d-b2f3-c46973a4531f"]={f:Ops.Value.FileInput_v2,objName:"Ops.Value.FileInput_v2"}; + + + + +// ************************************************************** +// +// Ops.Value.FilterValidNumber +// +// ************************************************************** + +Ops.Value.FilterValidNumber = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inNumber=op.inFloat("Number",0), + inZero=op.inBool("Invalid when 0",false), + inSmaller=op.inBool("Invalid when <0",false), + + outNum=op.outNumber("Last Valid Number"), + outValid=op.outBool("Is Valid"); + +inZero.onChange= +inSmaller.onChange= +inNumber.onChange= + update; + + +function update() +{ + const num=inNumber.get(); + + var r=true; + + if(num===null || num===undefined || num!=num) r=false; + if(inZero.get() && num===0) r=false; + if(inSmaller.get() && num<0) r=false; + + if(r) outNum.set(num); + + outValid.set(r); +} + +}; + +Ops.Value.FilterValidNumber.prototype = new CABLES.Op(); +CABLES.OPS["5a4db4ef-33d2-4131-9825-aa926f1f5a98"]={f:Ops.Value.FilterValidNumber,objName:"Ops.Value.FilterValidNumber"}; + + + + +// ************************************************************** +// +// Ops.Value.GateNumber +// +// ************************************************************** + +Ops.Value.GateNumber = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const valueInPort = op.inValue("Value In", 0); +const passThroughPort = op.inValueBool("Pass Through"); +const valueOutPort = op.outNumber("Value Out"); + +valueInPort.onChange = update; +passThroughPort.onChange = update; + +valueInPort.changeAlways = true; +valueOutPort.changeAlways = true; + +function update() +{ + if (passThroughPort.get()) + { + valueOutPort.set(valueInPort.get()); + } +} + + +}; + +Ops.Value.GateNumber.prototype = new CABLES.Op(); +CABLES.OPS["594105c8-1fdb-4f3c-bbd5-29b9ad6b33e0"]={f:Ops.Value.GateNumber,objName:"Ops.Value.GateNumber"}; + + + + +// ************************************************************** +// +// Ops.Value.Integer +// +// ************************************************************** + +Ops.Value.Integer = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + input = op.inInt("Integer",0), + output = op.outNumber("Number out"); + +input.onChange=function() +{ + output.set(Math.floor(input.get())); +} + +}; + +Ops.Value.Integer.prototype = new CABLES.Op(); +CABLES.OPS["17bc01d7-04ad-4aab-b88b-bb09744c4a69"]={f:Ops.Value.Integer,objName:"Ops.Value.Integer"}; + + + + +// ************************************************************** +// +// Ops.Value.MaximumSafeInteger +// +// ************************************************************** + +Ops.Value.MaximumSafeInteger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +op.outNumber("Max Int", Number.MAX_SAFE_INTEGER); + + +}; + +Ops.Value.MaximumSafeInteger.prototype = new CABLES.Op(); +CABLES.OPS["0efefbb7-461c-4a34-b7fd-28b89b0ceb3f"]={f:Ops.Value.MaximumSafeInteger,objName:"Ops.Value.MaximumSafeInteger"}; + + + + +// ************************************************************** +// +// Ops.Value.MinimumSafeInteger +// +// ************************************************************** + +Ops.Value.MinimumSafeInteger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +op.outNumber("Min Int", Number.MIN_SAFE_INTEGER); + + +}; + +Ops.Value.MinimumSafeInteger.prototype = new CABLES.Op(); +CABLES.OPS["d74e5528-8049-4cbc-984b-1221532a2fd4"]={f:Ops.Value.MinimumSafeInteger,objName:"Ops.Value.MinimumSafeInteger"}; + + + + +// ************************************************************** +// +// Ops.Value.Number +// +// ************************************************************** + +Ops.Value.Number = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + v = op.inValueFloat("value"), + result = op.outNumber("result"); + +v.onChange = exec; + +function exec() +{ + result.set(Number(v.get())); +} + + +}; + +Ops.Value.Number.prototype = new CABLES.Op(); +CABLES.OPS["8fb2bb5d-665a-4d0a-8079-12710ae453be"]={f:Ops.Value.Number,objName:"Ops.Value.Number"}; + + + + +// ************************************************************** +// +// Ops.Value.NumberSequence +// +// ************************************************************** + +Ops.Value.NumberSequence = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const NUM_PORTS = 4; +const inPort = op.inValue("In Value"); +const outTrigger = op.outTrigger("Value Changed"); + +const outPorts = []; +for (let i = 0; i < NUM_PORTS; i++) +{ + outPorts.push(op.outNumber("Out Value " + i)); +} + +// change listener +inPort.onChange = function () +{ + const inValue = inPort.get(); + for (let i = 0; i < NUM_PORTS; i++) + { + outPorts[i].set(inValue); + } + outTrigger.trigger(); +}; + + +}; + +Ops.Value.NumberSequence.prototype = new CABLES.Op(); +CABLES.OPS["33b08c9a-639a-4edc-8908-fa4df58a4b51"]={f:Ops.Value.NumberSequence,objName:"Ops.Value.NumberSequence"}; + + + + +// ************************************************************** +// +// Ops.Value.NumberSwitchBoolean +// +// ************************************************************** + +Ops.Value.NumberSwitchBoolean = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inBool = op.inValueBool("Boolean"), + valFalse = op.inValue("Value false", 0), + valTrue = op.inValue("Value true", 1), + outVal = op.outNumber("Result"); + +inBool.onChange = + valTrue.onChange = + valFalse.onChange = update; + +op.setPortGroup("Output Values", [valTrue, valFalse]); + +function update() +{ + if (inBool.get()) outVal.set(valTrue.get()); + else outVal.set(valFalse.get()); +} + + +}; + +Ops.Value.NumberSwitchBoolean.prototype = new CABLES.Op(); +CABLES.OPS["637c5fa8-840d-4535-96ab-3d27b458a8ba"]={f:Ops.Value.NumberSwitchBoolean,objName:"Ops.Value.NumberSwitchBoolean"}; + + + + +// ************************************************************** +// +// Ops.Value.Preset +// +// ************************************************************** + +Ops.Value.Preset = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + dataPort = op.inString("data", ""), + setsPort = op.inString("sets", ""), + id = op.inString("presetid", CABLES.shortId()), + + inInterPolate = op.inSwitch("Interpolation", ["None", "xfade", "a-b"], "None"), // "a..b","a..c" + + presetA = op.inFloat("Preset A", "0"), + presetB = op.inFloat("Preset B", "1"), + presetFade = op.inFloatSlider("Fade", 0.0), + + presetNames = op.inDropDown("Preset", []), + presetCreate = op.inTriggerButton("Create new"), + presetUpdate = op.inTriggerButton("Update"), + move = op.inUiTriggerButtons("move", ["↑", "↓"]), + + presetDelete = op.inTriggerButton("Delete"), + presetRename = op.inTriggerButton("Rename"), + + addPort = op.addOutPort(new CABLES.Port(op, "Create Variable", CABLES.OP_PORT_TYPE_DYNAMIC)), + outNum = op.outNumber("Num Presets", 0), + outNumCurrentPreset = op.outNumber("current Preset", 0), + outDbgData = op.outArray("dbg_data"), + outDbgSets = op.outArray("dbg_sets"); +let data = []; +let presets = []; +const valuePorts = []; +let interpolate = 0; + +presetB.changeAlways = true; +presetA.changeAlways = true; + +op.setPortGroup("Manage Presets", [presetCreate, presetUpdate, presetDelete, presetNames, move, presetRename]); +dataPort.setUiAttribs({ "hideParam": true, "hidePort": true }); +id.setUiAttribs({ "hideParam": true, "hidePort": true }); +setsPort.setUiAttribs({ "hideParam": true, "hidePort": true }); +presetCreate.setUiAttribs({ "hidePort": true }); +presetUpdate.setUiAttribs({ "hidePort": true }); +presetDelete.setUiAttribs({ "hidePort": true }); +presetRename.setUiAttribs({ "hidePort": true }); +presetNames.setUiAttribs({ "showIndex": true }); +presetCreate.setUiAttribs({ "buttonTitle": "Create New Preset" }); +presetDelete.setUiAttribs({ "buttonTitleClass": "button-small" }); +presetRename.setUiAttribs({ "buttonTitleClass": "button-small" }); + +presetNames.onChange = updatePreset; +inInterPolate.onChange = updateInterpolation; +presetA.onChange = + presetB.onChange = + presetFade.onChange = updateFade; + +updateInterpolation(); +updateDropdown(); +updatePreset(); +updateButtons(); + +function movePreset(from, to) +{ + const f = presets.splice(from, 1)[0]; + presets.splice(to, 0, f); +} + +move.onTriggered = function (which) +{ + const current = presetNames.get(); + const idx = presetNames.uiAttribs.values.indexOf(current); + + if (which == "↓") movePreset(idx, idx + 1); + if (which == "↑") movePreset(idx, Math.max(0, idx - 1)); + + updateDropdown(); + updatePreset(); +}; + +op.init = function () +{ + if (presets.length > 0 && data.length == 0) + { + op.logError("it happened again!!"); + + // this happened only once for now, find out how to reproduce it!!! + const keys = Object.keys(presets[0].values); + + for (let i = 0; i < keys.length; i++) + { + data.push( + { + "varname": keys[i], + "type": 0, + "title": keys[i] + + }); + } + saveData(); + } +}; + +function updateInterpolation() +{ + const ip = inInterPolate.get(); + if (ip === "None") + { + interpolate = 0; + presetA.setUiAttribs({ "greyout": true }); + presetB.setUiAttribs({ "greyout": true }); + presetFade.setUiAttribs({ "greyout": true }); + } + else if (ip === "xfade") + { + interpolate = 1; + presetA.setUiAttribs({ "greyout": false }); + presetB.setUiAttribs({ "greyout": false }); + presetFade.setUiAttribs({ "greyout": false }); + } + else if (ip === "a-b") + { + interpolate = 2; + presetA.setUiAttribs({ "greyout": false }); + presetB.setUiAttribs({ "greyout": true }); + presetFade.setUiAttribs({ "greyout": true }); + } + + op.setUiAttrib({ "extendTitle": ip }); + + if (interpolate !== 0) updateFade(); + else updatePreset(); +} + +function updateFade() +{ + if (interpolate === 0) return; + + let fade = 0; + let idxa = 0; + let idxb = 0; + + if (interpolate === 2) // a-b + { + const pr = presetA.get(); + idxa = Math.floor(pr); + idxb = Math.ceil(pr); + fade = pr % 1; + + if (idxa >= presets.length) idxa = presets.length - 1; + if (idxb >= presets.length) idxb = presets.length - 1; + } + else if (interpolate === 1) // xfade + { + fade = presetFade.get(); + idxa = Math.floor(presetA.get()); + idxb = Math.floor(presetB.get()); + } + + const a = presets[idxa]; + const b = presets[idxb]; + + if (!a || !b) + { + op.warn("preset not found"); + return; + } + + // todo: cache variable, so no string lookup needed every time... + + for (const i in a.values) + { + const ip = a.values[i] + (b.values[i] - a.values[i]) * fade; + op.patch.setVarValue(i, ip); + } +} + +function saveData() +{ + savePresets(); +} + +function savePresets() +{ + dataPort.set(JSON.stringify(data)); + + setsPort.set(JSON.stringify(presets)); + outNum.set(presets.length); + setDebugOutput(); +} + +function setPresetValues(preset) +{ + preset.values = preset.values || {}; + + for (let i = 0; i < valuePorts.length; i++) + preset.values[valuePorts[i].name] = valuePorts[i].value; + + return preset; +} + +function updateButtons() +{ + presetDelete.setUiAttribs({ "greyout": presetNames.uiAttribs.values.length == 0 }); + presetUpdate.setUiAttribs({ "greyout": presetNames.uiAttribs.values.length == 0 }); + presetRename.setUiAttribs({ "greyout": presetNames.uiAttribs.values.length == 0 }); + + move.setUiAttribs({ "greyout": presetNames.uiAttribs.values.length == 0 }); + + const preset = getPreset(presetNames.get()); + if (preset) + { + presetDelete.setUiAttribs({ "buttonTitle": "Delete " + preset.name }); + presetUpdate.setUiAttribs({ "buttonTitle": "Update " + preset.name }); + presetRename.setUiAttribs({ "buttonTitle": "Rename " + preset.name }); + } +} + +function updateDropdown() +{ + presetNames.uiAttribs.values.length = 0; + for (let i = 0; i < presets.length; i++) + presetNames.uiAttribs.values.push(presets[i].name); + + updateButtons(); + savePresets(); + setDebugOutput(); +} + +function getPreset(name) +{ + for (let i = 0; i < presets.length; i++) + if (presets[i] && presets[i].name == name) + return presets[i]; +} + +setsPort.onChange = function () +{ + presets = JSON.parse(setsPort.get()); + outNum.set(presets.length); + updateDropdown(); + setsPort.onChange = null; +}; + +function updatePreset() +{ + const preset = getPreset(presetNames.get()); + + if (!preset) return; + + const varnames = Object.keys(preset.values); + + for (let i = 0; i < varnames.length; i++) + { + const p = op.getPort(varnames[i]); + if (p) + { + p.set(preset.values[varnames[i]]); + if (interpolate === 0)p.forceChange(); + } + } + + if (interpolate !== 0) updateFade(); + + updateButtons(); + op.refreshParams(); +} + +presetUpdate.onTriggered = function () +{ + let preset = getPreset(presetNames.get()); + preset = setPresetValues(preset); + savePresets(); +}; + +presetCreate.onTriggered = function () +{ + if (!op.patch.isEditorMode()) return; + + + new CABLES.UI.ModalDialog({ + "prompt": true, + "title": "New Preset", + "text": "Enter a new preset name", + "promptValue": "", + "promptOk": (str) => + { + op.refreshParams(); + presetNames.set(str); + let preset = { "name": str }; + preset = setPresetValues(preset); + presets.push(preset); + updateDropdown(); + savePresets(); + } }); +}; + +presetDelete.onTriggered = function () +{ + if (!CABLES.UI) return; + const current = presetNames.get(); + const idx = presetNames.uiAttribs.values.indexOf(current); + presets.splice(idx, 1); + saveData(); + + if (presets.length > 0) + presetNames.set(presets[0].name); + + op.refreshParams(); + updateDropdown(); + updateButtons(); +}; + +presetRename.onTriggered = function () +{ + if (!CABLES.UI) return; + + new CABLES.UI.ModalDialog({ + "prompt": true, + "title": "New Preset", + "text": "Enter a new preset name", + "promptValue": "", + "promptOk": (str) => + { + if (!str) return; + const current = presetNames.get(); + const idx = presetNames.uiAttribs.values.indexOf(current); + presets[idx].name = str; + presetNames.set(str); + saveData(); + updateDropdown(); + op.refreshParams(); + } + }); +}; + +dataPort.onChange = function () +{ + data = JSON.parse(dataPort.get()); + + for (let i = 0; i < data.length; i++) + { + const portObject = data[i]; + + const varname = portObject.varname; + + if (!op.getPort(varname)) + { + if (portObject.type == CABLES.OP_PORT_TYPE_VALUE) + { + const val = op.patch.getVarValue(varname); + const port = op.inFloat(varname, val); + + port.setUiAttribs({ + "editableTitle": true, + "title": portObject.title }); + + listenPortChange(port, varname); + + port.set(val); + port.forceChange(); + } + } + } + + setDebugOutput(); + // dataPort.onChange=null; +}; + +function listenPortChange(port, varname) +{ + valuePorts.push(port); + port.onChange = function () + { + op.patch.setVarValue(varname, port.get()); + }; + + port.addEventListener("onUiAttrChange", (attribs) => + { + if (attribs.title) + { + const thePort = data.find((p) => { return p.varname === varname; }); + if (thePort) + { + thePort.title = attribs.title; + saveData(); + } + } + }); +} + +op.patch.addEventListener("onOpDelete", (optodelete) => +{ + if (optodelete.objName.indexOf("VarGet") == -1) return; + + const newData = []; + for (let i = 0; i < data.length; i++) + { + let found = false; + + for (let oi = 0; oi < op.patch.ops.length; oi++) + { + const opt = op.patch.ops[oi]; + + if (opt != optodelete && + opt.objName.indexOf("VarGet" > -1) && + opt.varName && + opt.varName.get && + opt.varName.get() == data[i].varname) + { + found = true; + break; + } + } + + if (found) + { + newData.push(data[i]); + } + else + { + op.removePort(op.getPort(data[i].varname)); + } + } + + data = newData; + saveData(); + + op.refreshParams(); + setTimeout(op.refreshParams.bind(this), 1000); +}); + +function setDebugOutput() +{ + outDbgData.set(data); + outDbgSets.set(presets); +} + +addPort.onLinkChanged = function () +{ + if (addPort.links.length === 0) + { + op.log("no links!"); + return; + } + + const link = addPort.links[0]; + const otherPort = link.getOtherPort(addPort); + + const varname = ".preset_" + otherPort.name + "_" + id.get() + "_" + CABLES.shortId(); + + op.log("pilength", op.portsIn.length); + + data.push( + { + "varname": varname, + "title": otherPort.parent.name + " " + otherPort.name, + "type": otherPort.type + }); + + const oldValue = otherPort.get(); + + op.patch.setVarValue(varname, oldValue); + op.patch.getVar(varname).type = "preset"; + + addPort.removeLinks(); + saveData(); + op.refreshParams(); + + otherPort.setVariable(varname); +}; + +op.onDelete = (reloading) => +{ + if (reloading) return; + for (let i = 0; i < data.length; i++) + op.patch.deleteVar(data[i].varname); +}; + + +}; + +Ops.Value.Preset.prototype = new CABLES.Op(); +CABLES.OPS["ffe981a5-67df-4da5-a6a9-7fcb910fc982"]={f:Ops.Value.Preset,objName:"Ops.Value.Preset"}; + + + + +// ************************************************************** +// +// Ops.Value.PreviousValueStore +// +// ************************************************************** + +Ops.Value.PreviousValueStore = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + val = op.inValueFloat("Value"), + outCurrent = op.outNumber("Current Value"), + outOldVal = op.outNumber("Previous Value"); + +let oldValue = 0; + +val.onChange = function () +{ + outOldVal.set(oldValue); + oldValue = val.get(); + outCurrent.set(val.get()); +}; + + +}; + +Ops.Value.PreviousValueStore.prototype = new CABLES.Op(); +CABLES.OPS["01716872-67bd-4b31-a4a2-e0ccadf48411"]={f:Ops.Value.PreviousValueStore,objName:"Ops.Value.PreviousValueStore"}; + + + + +// ************************************************************** +// +// Ops.Value.RouteNumber +// +// ************************************************************** + +Ops.Value.RouteNumber = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// constants and variables +const NUM_PORTS = 10; +const DEFAULT_VALUE_DEFAULT = 0; +let lastIdx = null; + +// input +const indexPort = op.inValue("Index", 0); +const valuePort = op.inValue("Value", 0); +const defaultValuePort = op.inValue("Default Value", DEFAULT_VALUE_DEFAULT); +const onlyOnePort = op.inBool("Set inactive to default", false); + +// output +const valuePorts = createOutPorts(DEFAULT_VALUE_DEFAULT); + +// change listeners +indexPort.onChange = update; +valuePort.onChange = update; // TODO: Maybe only one update needed!? +defaultValuePort.onChange = setDefaultValues; +onlyOnePort.onChange = onlyOnePortChange; + +setDefaultValues(); + +// functions + +/** + * creates the output-port array + */ +function createOutPorts() +{ + let arr = []; + for (let i = 0; i < NUM_PORTS; i++) + { + let port = op.outNumber("Index " + i + " Value"); + arr.push(port); + } + return arr; +} + +/** + * Sets all value ports to the default value + */ +function setDefaultValues() +{ + const defaultValue = defaultValuePort.get(); + valuePorts.forEach((valuePort) => + { + valuePort.set(defaultValue); + }); +} + +/** + * Update + */ +function update() +{ + let index = indexPort.get(); + index = Math.round(index); + index = clamp(index, 0, NUM_PORTS - 1); + + if (onlyOnePort.get() && lastIdx !== null && lastIdx != index) + { + valuePorts[lastIdx].set(defaultValuePort.get()); + } + + const value = valuePort.get(); + valuePorts[index].set(value); + + lastIdx = index; +} + +/** + * Returns a number whose value is limited to the given range. + */ +function clamp(value, min, max) +{ + return Math.min(Math.max(value, min), max); +} + +/** + * Reset all ports to default value and set current index + * or let have several ports with old value + */ +function onlyOnePortChange() +{ + if (onlyOnePort.get()) + { + setDefaultValues(); + update(); + } +} + + +}; + +Ops.Value.RouteNumber.prototype = new CABLES.Op(); +CABLES.OPS["e3b1fc2d-a813-4d9b-8cb0-595fc95af4e2"]={f:Ops.Value.RouteNumber,objName:"Ops.Value.RouteNumber"}; + + + + +// ************************************************************** +// +// Ops.Value.SwitchFile_v2 +// +// ************************************************************** + +Ops.Value.SwitchFile_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let idx = op.inValueInt("Index"); +let valuePorts = []; +let result = op.outString("Result"); + +idx.onChange = update; + +for (let i = 0; i < 10; i++) +{ + let p = op.inUrl("File " + i); + valuePorts.push(p); + p.onChange = update; +} + +function update() +{ + const index = idx.get(); + if (index >= 0 && valuePorts[index]) + { + result.set(valuePorts[index].get()); + } +} + + +}; + +Ops.Value.SwitchFile_v2.prototype = new CABLES.Op(); +CABLES.OPS["250c8d79-2b83-419f-8c23-910d95936f2c"]={f:Ops.Value.SwitchFile_v2,objName:"Ops.Value.SwitchFile_v2"}; + + + + +// ************************************************************** +// +// Ops.Value.SwitchNumber +// +// ************************************************************** + +Ops.Value.SwitchNumber = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const idx = op.inValueInt("Index"); +const valuePorts = []; +const result = op.outNumber("Result"); + +idx.onChange = update; + +for (let i = 0; i < 16; i++) +{ + let p = op.inValue("Value " + i); + valuePorts.push(p); + p.onChange = update; +} + +function update() +{ + if (idx.get() >= 0 && valuePorts[idx.get()]) + { + result.set(valuePorts[idx.get()].get()); + } +} + + +}; + +Ops.Value.SwitchNumber.prototype = new CABLES.Op(); +CABLES.OPS["fbb89f72-f2e3-4d34-ad01-7d884a1bcdc0"]={f:Ops.Value.SwitchNumber,objName:"Ops.Value.SwitchNumber"}; + + + + +// ************************************************************** +// +// Ops.Value.SwitchNumberOnTrigger +// +// ************************************************************** + +Ops.Value.SwitchNumberOnTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + currentVal = op.outNumber("Value"), + oldVal = op.outNumber("Last Value"), + triggered = op.outTrigger("Triggered"); + +let triggers = []; +let inVals = []; +let inExes = []; + +function onTrigger() +{ + oldVal.set(currentVal.get()); + currentVal.set(inVals[this.slot].get()); + triggered.trigger(); +} + +let num = 8; +for (let i = 0; i < num; i++) +{ + let newExe = op.addInPort(new CABLES.Port(op, "Trigger " + i, CABLES.OP_PORT_TYPE_FUNCTION)); + newExe.slot = i; + newExe.onTriggered = onTrigger.bind(newExe); + let newVal = op.addInPort(new CABLES.Port(op, "Value " + i, CABLES.OP_PORT_TYPE_VALUE)); + inVals.push(newVal); +} + +let defaultVal = op.inValueString("Default Value"); + +currentVal.set(defaultVal.get()); +oldVal.set(defaultVal.get()); + +defaultVal.onChange = function () +{ + oldVal.set(currentVal.get()); + currentVal.set(defaultVal.get()); +}; + + +}; + +Ops.Value.SwitchNumberOnTrigger.prototype = new CABLES.Op(); +CABLES.OPS["338032c5-bf47-454b-8ae1-cd91f17e5c5b"]={f:Ops.Value.SwitchNumberOnTrigger,objName:"Ops.Value.SwitchNumberOnTrigger"}; + + + + +// ************************************************************** +// +// Ops.Value.ToggleNumber +// +// ************************************************************** + +Ops.Value.ToggleNumber = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + useValue1Port = op.inValueBool("Use Value 1", false), + value0port = op.inValue("Value 0", 0), + value1port = op.inValue("Value 1", 1), + outValuePort = op.outNumber("Out Value", 0); + +value0port.onChange = + value1port.onChange = + useValue1Port.onChange = setOutput; + +function setOutput() +{ + const useValue1 = useValue1Port.get(); + if (useValue1) + { + outValuePort.set(value1port.get()); + } + else + { + outValuePort.set(value0port.get()); + } +} + + +}; + +Ops.Value.ToggleNumber.prototype = new CABLES.Op(); +CABLES.OPS["400eea7d-5a68-4dda-a94d-2bb2ee7c2331"]={f:Ops.Value.ToggleNumber,objName:"Ops.Value.ToggleNumber"}; + + + + +// ************************************************************** +// +// Ops.Value.Trigger3Numbers +// +// ************************************************************** + +Ops.Value.Trigger3Numbers = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + x = op.inValueFloat("value x"), + y = op.inValueFloat("value y"), + z = op.inValueFloat("value z"), + resultX = op.outNumber("result x"), + resultY = op.outNumber("result y"), + resultZ = op.outNumber("result z"); + +exe.onTriggered = + x.onChange = + y.onChange = + z.onChange = exec; + +function frame(time) +{ + exec(); +} + +function exec() +{ + if (resultX.get() != x.get()) resultX.set(x.get()); + if (resultY.get() != y.get()) resultY.set(y.get()); + if (resultZ.get() != z.get()) resultZ.set(z.get()); +} + + +}; + +Ops.Value.Trigger3Numbers.prototype = new CABLES.Op(); +CABLES.OPS["d56326a2-6351-4261-898a-635ca0636dd0"]={f:Ops.Value.Trigger3Numbers,objName:"Ops.Value.Trigger3Numbers"}; + + + + +// ************************************************************** +// +// Ops.Value.TriggerOnChangeNumber +// +// ************************************************************** + +Ops.Value.TriggerOnChangeNumber = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inval = op.inFloat("Value"), + next = op.outTrigger("Next"), + number = op.outNumber("Number"); + +inval.onChange = function () +{ + number.set(inval.get()); + next.trigger(); +}; + + +}; + +Ops.Value.TriggerOnChangeNumber.prototype = new CABLES.Op(); +CABLES.OPS["f5c8c433-ce13-49c4-9a33-74e98f110ed0"]={f:Ops.Value.TriggerOnChangeNumber,objName:"Ops.Value.TriggerOnChangeNumber"}; + + + + +// ************************************************************** +// +// Ops.Value.TypeOf_v2 +// +// ************************************************************** + +Ops.Value.TypeOf_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const input = op.inValue("input"); +const result = op.outString("result"); + +input.onChange = update; + +function update() +{ + result.set(typeof (input.get())); +} + + +}; + +Ops.Value.TypeOf_v2.prototype = new CABLES.Op(); +CABLES.OPS["50fd0008-7bcb-4ab3-8a8c-82fc55a3e7a9"]={f:Ops.Value.TypeOf_v2,objName:"Ops.Value.TypeOf_v2"}; + + + + +// ************************************************************** +// +// Ops.Value.Value2d +// +// ************************************************************** + +Ops.Value.Value2d = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + x = op.inValueFloat("value x"), + y = op.inValueFloat("value y"), + resultX = op.outNumber("result x"), + resultY = op.outNumber("result y"); + +exe.onTriggered = exec; + +x.onChange = exec; +y.onChange = exec; + +function frame(time) +{ + updateAnims(); + exec(); +} + +function exec() +{ + if (resultX.get() != x.get()) resultX.set(x.get()); + if (resultY.get() != y.get()) resultY.set(y.get()); +} + + +}; + +Ops.Value.Value2d.prototype = new CABLES.Op(); +CABLES.OPS["ef4fa87b-a075-4f29-9628-b4f26ce41533"]={f:Ops.Value.Value2d,objName:"Ops.Value.Value2d"}; + + + + +// ************************************************************** +// +// Ops.Value.ValueChangeCounter +// +// ************************************************************** + +Ops.Value.ValueChangeCounter = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inVal = op.inValue("Value"), + inReset = op.inTriggerButton("Reset"), + outResult = op.outNumber("Result"); + +let count = 0; + +inReset.onTriggered = function () +{ + count = 0; +}; + +inVal.onChange = function () +{ + count++; + outResult.set(count); +}; + + +}; + +Ops.Value.ValueChangeCounter.prototype = new CABLES.Op(); +CABLES.OPS["cbd50d32-bfc1-45c8-ba02-a6afa1fdd0e1"]={f:Ops.Value.ValueChangeCounter,objName:"Ops.Value.ValueChangeCounter"}; + + + + +// ************************************************************** +// +// Ops.Value.ValueChangedTrigger +// +// ************************************************************** + +Ops.Value.ValueChangedTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + val = op.inFloat("Value", 0), + exe = op.inTrigger("Execute"), + trigger = op.outTrigger("trigger"); + +let changed = false; + +exe.onTriggered = function () +{ + if (changed) + { + changed = false; + trigger.trigger(); + } +}; + +val.onChange = function () +{ + changed = true; +}; + + +}; + +Ops.Value.ValueChangedTrigger.prototype = new CABLES.Op(); +CABLES.OPS["9f353fcc-da0b-4af8-ae5c-4edd256fc9e3"]={f:Ops.Value.ValueChangedTrigger,objName:"Ops.Value.ValueChangedTrigger"}; + + + + +// ************************************************************** +// +// Ops.Values.FreezeArray +// +// ************************************************************** + +Ops.Values.FreezeArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr = op.inArray("Number"), + inFreeze = op.inTriggerButton("Button"), + inHidden = op.inString("storedJson"), + outArr = op.outArray("Frozen Array"); + +inFreeze.onTriggered = +inHidden.onTriggered = update; + +inHidden.setUiAttribs({ "hideParam": true, "hidePort": true, "ignoreBigPort": true }); + +function update() +{ + inHidden.set(JSON.stringify(inStr.get())); +} + +outArr.onLinkChanged = () => +{ + outArr.set(JSON.parse(inHidden.get())); +}; + +inHidden.onChange = () => +{ + outArr.set(null); + try + { + outArr.set(JSON.parse(inHidden.get())); + } + catch (e) {} +}; + + +}; + +Ops.Values.FreezeArray.prototype = new CABLES.Op(); +CABLES.OPS["340fb9e2-27ab-47f0-b3cc-2ef001f485c5"]={f:Ops.Values.FreezeArray,objName:"Ops.Values.FreezeArray"}; + + + + +// ************************************************************** +// +// Ops.Values.FreezeNumber +// +// ************************************************************** + +Ops.Values.FreezeNumber = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr = op.inFloat("Number", 0), + inFreeze = op.inTriggerButton("Button"), + inHidden = op.inFloat("StoredNumber"), + outNum = op.outNumber("Frozen Number"); + +inFreeze.onTriggered = +inHidden.onTriggered = update; + +inHidden.setUiAttribs({ "hideParam": true, "hidePort": true }); + +outNum.onLinkChanged = () => +{ + outNum.set(inHidden.get()); +}; + +function update() +{ + inHidden.set(inStr.get()); + outNum.set(inHidden.get()); +} + + +}; + +Ops.Values.FreezeNumber.prototype = new CABLES.Op(); +CABLES.OPS["97dea923-f00f-44cf-bef9-808a2556105b"]={f:Ops.Values.FreezeNumber,objName:"Ops.Values.FreezeNumber"}; + + + + +// ************************************************************** +// +// Ops.Values.FreezeString +// +// ************************************************************** + +Ops.Values.FreezeString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inStr = op.inString("String", "default"), + inFreeze = op.inTriggerButton("Button"), + inHidden = op.inString("StoredString"), + outString = op.outString("Frozen String"); + +inFreeze.onTriggered = +inHidden.onTriggered = update; + +inHidden.setUiAttribs({ "hideParam": true, "hidePort": true, "ignoreBigPort": true }); + +outString.onLinkChanged = () => +{ + outString.set(inHidden.get()); +}; + +function update() +{ + inHidden.set(inStr.get()); + outString.set(inHidden.get()); +} + + +}; + +Ops.Values.FreezeString.prototype = new CABLES.Op(); +CABLES.OPS["9ae2598f-8b5a-4749-aff3-a507c9957225"]={f:Ops.Values.FreezeString,objName:"Ops.Values.FreezeString"}; + + + + +// ************************************************************** +// +// Ops.Values.SequenceNumbers +// +// ************************************************************** + +Ops.Values.SequenceNumbers = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; + +const outputs=[]; +const inputs=[]; + +for(let i=0;i<16;i++) +{ + const inp=op.inFloat("Number "+i,0); + const out=op.outNumber("Output "+i); + + inp.changeAlways=true; + + outputs.push(out); + inputs.push(inp); +}; + + +for(let i=0;i= 0.5) x = 1.0 - texCoord.x;\n\n x *= (1. - width) * 2.0;\n\n col = texture(tex, vec2(x, texCoord.y));\n\n outColor = col;\n}",}; +const cgl = op.patch.cgl; + +const inRefresh = op.inTrigger("Refresh"); +const inFFTArray = op.inArray("FFT Array"); + +const inMirrorActive = op.inBool("Mirror Active", false); +const inMirrorWidth = op.inFloatSlider("Mirror Width", 0.5); + +const inTextureSize = op.inSwitch("Texture Size", [64, 128, 256, 512, 1024, 2048], 512); + +op.setPortGroup("Texture Options", [inTextureSize]); +op.setPortGroup("Mirror Options", [inMirrorActive, inMirrorWidth]); + +const outTexture = op.outTexture("Texture Out", null, "texture"); +const outPosition = op.outNumber("Position"); + +let updateTextureSize = false; +inTextureSize.onChange = () => +{ + updateTextureSize = true; +}; + +inMirrorActive.onChange = () => +{ + inMirrorWidth.setUiAttribs({ "greyout": !inMirrorActive.get() }); +}; + +const texFFT = new CGL.Texture(cgl, + { + "name": "AnalyzerTexture - FFT Texture " + op.id, + "wrap": CGL.Texture.CLAMP_TO_EDGE, + "filter": CGL.Texture.FILTER_LINEAR, + }); + +const texDefault = new CGL.Texture(cgl, + { + "name": "AnalyzerTexture - Render Texture " + op.id, + "wrap": CGL.Texture.CLAMP_TO_EDGE, + "filter": CGL.Texture.FILTER_LINEAR, + "width": Number(inTextureSize.get()), + "height": Number(inTextureSize.get()), + }); + +let data = []; + +let line = 0; +let height = 256; + +let buffer = new Uint8Array(); + +function updateFFT() +{ + const arr = inFFTArray.get(); + if (!arr) return; + + const width = arr.length; + // height = width; + if (!width) return; + + if (data.length === 0 || data.length !== width * 4) + { + data.length = width * 4; + buffer = new Uint8Array(width * height * 4); + } + + line++; + + if (line >= height) line = 0; + + outPosition.set(line / height); + + for (let i = 0; i < width; i++) + { + data[i * 4 + 0] = arr[i]; + data[i * 4 + 1] = arr[i]; + data[i * 4 + 2] = arr[i]; + data[i * 4 + 3] = 255; + } + + buffer.set(data, line * width * 4); + + if (texFFT.width != width || texFFT.height != height) + { + texFFT.setSize( + width, height + ); + // effect.setSourceTexture(texFFT); + } + + texFFT.initFromData( + buffer, + width, height, + // Number(inTextureSize.get()), + // Number(inTextureSize.get()), + CGL.Texture.FILTER_LINEAR, + CGL.Texture.WRAP_CLAMP_TO_EDGE + ); +} + +let effect = new CGL.TextureEffect(cgl, + { + // "isFloatingPointTexture": true, + "filter": CGL.Texture.FILTER_LINEAR, + "wrap": CGL.Texture.WRAP_CLAMP_TO_EDGE, + "width": Number(inTextureSize.get()), + "height": Number(inTextureSize.get()), + } +); + +let prevViewPort = [0, 0, 0, 0]; + +// ------------------ + +const shaderDefault = new CGL.Shader(cgl, "AnalyzerTexture - defaultShader"); +shaderDefault.setSource(shaderDefault.getDefaultVertexShader(), attachments.default_frag); +const texUniformDefault = new CGL.Uniform(shaderDefault, "t", "texFFT", 1); + +const shaderMirror = new CGL.Shader(cgl, "AnalyzerTexture mirror"); + +shaderMirror.setSource(shaderMirror.getDefaultVertexShader(), attachments.mirror_frag); + +const textureUniformMirror = new CGL.Uniform(shaderMirror, "t", "tex", 0); +const uniWidthMirror = new CGL.Uniform(shaderMirror, "f", "width", inMirrorWidth); + +function mirrorTexture() +{ + cgl.pushShader(shaderMirror); + + effect.startEffect(); + effect.setSourceTexture(effect.getCurrentSourceTexture()); + + effect.bind(); + + cgl.setTexture(0, texFFT.tex); + + effect.finish(); + effect.endEffect(); + + cgl.popShader(); +} + +inRefresh.onTriggered = () => +{ + if (!inFFTArray.get()) return; + + updateFFT(); + + if (updateTextureSize) + { + texDefault.setSize( + Number(inTextureSize.get()), + Number(inTextureSize.get()), + ); + + effect.setSourceTexture(texDefault); + updateTextureSize = false; + } + + if (texFFT) + { + cgl.pushShader(shaderDefault); + effect.startEffect(); + effect.setSourceTexture(texDefault); + effect.bind(); + + cgl.setTexture(1, texFFT.tex); + + effect.finish(); + effect.endEffect(); + + cgl.popShader(); + } + + if (inMirrorActive.get()) mirrorTexture(); + + outTexture.set(null); + outTexture.set(effect.getCurrentSourceTexture()); +}; + + +}; + +Ops.WebAudio.AnalyzerTexture_v2.prototype = new CABLES.Op(); +CABLES.OPS["decba955-636b-41c5-bfb8-c2506cbcabd2"]={f:Ops.WebAudio.AnalyzerTexture_v2,objName:"Ops.WebAudio.AnalyzerTexture_v2"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.AudioAnalyzer_v2 +// +// ************************************************************** + +Ops.WebAudio.AudioAnalyzer_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const clamp = (val, min, max) => Math.min(Math.max(val, min), max); +const MAX_DBFS_RANGE_24_BIT = -144; +const MAX_DBFS_RANGE_26_BIT = -96; + +let audioCtx = CABLES.WEBAUDIO.createAudioContext(op); + +const inTrigger = op.inTrigger("Trigger In"); + +const analyser = audioCtx.createAnalyser(); +analyser.smoothingTimeConstant = 0.3; +analyser.fftSize = 256; + +const FFT_BUFFER_SIZES = [32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768]; + +const audioIn = op.inObject("Audio In", null, "audioNode"); +const inFFTSize = op.inDropDown("FFT size", FFT_BUFFER_SIZES, 256); +const inSmoothing = op.inFloatSlider("Smoothing", 0.3); + +const inRangeMin = op.inFloat("Min", -90); +const inRangeMax = op.inFloat("Max", 0); + +op.setPortGroup("Inputs", [inTrigger, audioIn]); +op.setPortGroup("FFT Options", [inFFTSize, inSmoothing]); +op.setPortGroup("Range (in dBFS)", [inRangeMin, inRangeMax]); +const outTrigger = op.outTrigger("Trigger Out"); +const audioOut = op.outObject("Audio Out", null, "audioNode"); +const fftOut = op.outArray("FFT Array"); +const ampOut = op.outArray("Waveform Array"); +const frequencyOut = op.outArray("Frequencies by Index Array"); +const fftLength = op.outNumber("Array Length"); +const avgVolumePeak = op.outNumber("Average Volume"); +const avgVolumeAmp = op.outNumber("Average Volume Time-Domain"); +const avgVolumeRMS = op.outNumber("RMS Volume"); +let updating = false; + +let fftBufferLength = analyser.frequencyBinCount; +let fftDataArray = new Uint8Array(fftBufferLength); +let ampDataArray = new Uint8Array(fftBufferLength); +let frequencyArray = []; +frequencyArray.length = fftBufferLength; +let oldAudioIn = null; + +audioIn.onChange = () => +{ + if (audioIn.get()) + { + const audioNode = audioIn.get(); + if (audioNode.connect) + { + audioNode.connect(analyser); + audioOut.set(analyser); + } + } + else + { + if (oldAudioIn) + { + if (oldAudioIn.disconnect) oldAudioIn.disconnect(analyser); + audioOut.set(null); + } + } + + oldAudioIn = audioIn.get(); +}; + +function updateAnalyser() +{ + try + { + const fftSize = Number(inFFTSize.get()); + analyser.smoothingTimeConstant = clamp(inSmoothing.get(), 0.0, 1.0); + analyser.fftSize = fftSize; + const minDecibels = clamp(inRangeMin.get(), MAX_DBFS_RANGE_24_BIT, -0.0001); + const maxDecibels = Math.max(inRangeMax.get(), analyser.minDecibels + 0.0001); + analyser.minDecibels = minDecibels; + analyser.maxDecibels = maxDecibels; + + if (minDecibels < MAX_DBFS_RANGE_24_BIT) + { + op.setUiError("maxDbRangeMin", + "Your minimum is below the lowest possible dBFS value: " + + MAX_DBFS_RANGE_24_BIT + + "dBFS. To make sure your analyser data is correct, try increasing the minimum.", + 1 + ); + } + else + { + op.setUiError("maxDbRangeMin", null); + } + + if (maxDecibels > 0) + { + op.setUiError("maxDbRangeMax", "Your maximum is above 0 dBFS. As digital signals only go to 0 dBFS and not above, you should use 0 as your maximum.", 1); + } + else + { + op.setUiError("maxDbRangeMax", null); + } + + if (FFT_BUFFER_SIZES.indexOf(fftSize) >= 6) + { + op.setUiError("highFftSize", "Please be careful with high FFT sizes as they can slow down rendering. Check the profiler to see if performance is impacted.", 1); + } + else + { + op.setUiError("highFftSize", null); + } + } + catch (e) + { + op.log(e); + } +} + +inFFTSize.onChange = inSmoothing.onChange += inRangeMin.onChange = inRangeMax.onChange = () => + { + if (inTrigger.isLinked()) updating = true; + else updateAnalyser(); + }; + +inTrigger.onTriggered = function () +{ + if (updating) + { + updateAnalyser(); + updating = false; + } + + if (fftBufferLength != analyser.frequencyBinCount) + { + fftBufferLength = analyser.frequencyBinCount; + fftDataArray = new Uint8Array(fftBufferLength); + ampDataArray = new Uint8Array(fftBufferLength); + + frequencyArray = []; + frequencyArray.length = fftBufferLength; + + for (let index = 0; index < fftBufferLength; index += 1) + { + frequencyArray[index] = Math.round(index * audioCtx.sampleRate / (analyser.fftSize * 2)); + } + + frequencyOut.set(null); + frequencyOut.set(frequencyArray); + } + + if (!fftDataArray) return; + if (!ampDataArray) return; + + const fftSize = Number(inFFTSize.get()); + + try + { + analyser.getByteFrequencyData(fftDataArray); + analyser.getByteTimeDomainData(ampDataArray); + + let values = 0; + let peakValues = 0; + let ampPeakValues = 0; + for (let i = 0; i < analyser.frequencyBinCount; i++) + { + values += ampDataArray[i] * ampDataArray[i]; + peakValues += fftDataArray[i]; + ampPeakValues += ampDataArray[i]; + } + + const peakAverage = peakValues / analyser.frequencyBinCount; + const peakAmpAverage = ampPeakValues / analyser.frequencyBinCount; + + avgVolumePeak.set(peakAverage / 128); + avgVolumeAmp.set(peakAmpAverage / 256); + + let rms = Math.sqrt(values / analyser.frequencyBinCount); + rms = Math.max(rms, rms * inSmoothing.get()); + avgVolumeRMS.set(rms / 256); + } + catch (e) { op.log(e); } + + fftOut.set(null); + fftOut.set(fftDataArray); + + ampOut.set(null); + ampOut.set(ampDataArray); + + fftLength.set(fftDataArray.length); + outTrigger.trigger(); +}; + + +}; + +Ops.WebAudio.AudioAnalyzer_v2.prototype = new CABLES.Op(); +CABLES.OPS["ff9bf46c-676f-4aa1-95bf-5595a6813ed7"]={f:Ops.WebAudio.AudioAnalyzer_v2,objName:"Ops.WebAudio.AudioAnalyzer_v2"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.AudioBufferPlayer_v2 +// +// ************************************************************** + +Ops.WebAudio.AudioBufferPlayer_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// input ports +const audioBufferPort = op.inObject("Audio Buffer", null, "audioBuffer"); +const playPort = op.inBool("Start / Stop", false); + +const loopPort = op.inBool("Loop", false); +const inResetStart = op.inTriggerButton("Restart"); +const offsetPort = op.inFloat("Offset", 0); +const playbackRatePort = op.inFloat("Playback Rate", 1); +const detunePort = op.inFloat("Detune", 0); + +op.setPortGroup("Playback Controls", [playPort, loopPort, inResetStart]); +op.setPortGroup("Time Controls", [offsetPort]); +op.setPortGroup("Miscellaneous", [playbackRatePort, detunePort]); + +// output ports +const audioOutPort = op.outObject("Audio Out", null, "audioNode"); +const outPlaying = op.outBool("Is Playing", false); +const outLoading = op.outBool("Loading", false); + +// vars +let source = null; +let isPlaying = false; +let hasEnded = false; +let pausedAt = null; +let startedAt = null; +let isLoading = false; + +const audioCtx = CABLES.WEBAUDIO.createAudioContext(op); + +const gainNode = audioCtx.createGain(); + +if (!audioBufferPort.isLinked()) +{ + op.setUiError("inputNotConnected", "To be able to play back sound, you need to connect an AudioBuffer to this op.", 0); +} +else +{ + op.setUiError("inputNotConnected", null); +} + +audioBufferPort.onLinkChanged = () => +{ + if (!audioBufferPort.isLinked()) + { + op.setUiError("inputNotConnected", "To be able to play back sound, you need to connect an AudioBuffer to this op.", 0); + } + else + { + op.setUiError("inputNotConnected", null); + } +}; + +if (!audioOutPort.isLinked()) +{ + op.setUiError("outputNotConnected", "To be able to hear sound playing, you need to connect this op to an Output op.", 0); +} +else +{ + op.setUiError("outputNotConnected", null); +} + +audioOutPort.onLinkChanged = () => +{ + if (!audioOutPort.isLinked()) + { + op.setUiError("outputNotConnected", "To be able to hear sound playing, you need to connect this op to an Output op.", 0); + } + else + { + op.setUiError("outputNotConnected", null); + } +}; + +// change listeners +audioBufferPort.onChange = function () +{ + if (audioBufferPort.get()) createAudioBufferSource(); + else + { + if (isLoading) + { + isLoading = false; + outLoading.set(isLoading); + } + + if (isPlaying) + { + stop(0); + source.buffer = null; + source = null; + } + } +}; + +playPort.onChange = function () +{ + if (!audioBufferPort.get()) return; + + if (!source) + { + if (!isLoading) createAudioBufferSource(); + } + + if (playPort.get()) + { + const startTime = 0; + start(startTime); + } + else + { + const stopTime = 0; + stop(stopTime); + } +}; + +loopPort.onChange = function () +{ + if (source) + { + source.loop = !!loopPort.get(); + } +}; + +detunePort.onChange = setDetune; + +function setDetune() +{ + if (!source) return; + + const detune = detunePort.get() || 0; + if (source.detune) + { + source.detune.setValueAtTime( + detune, + audioCtx.currentTime + ); + } +} + +playbackRatePort.onChange = setPlaybackRate; + +function setPlaybackRate() +{ + if (!source) return; + + const playbackRate = playbackRatePort.get() || 0; + if (playbackRate >= source.playbackRate.minValue && playbackRate <= source.playbackRate.maxValue) + { + source.playbackRate.setValueAtTime( + playbackRate, + audioCtx.currentTime + ); + } +} + +let resetTriggered = false; +inResetStart.onTriggered = function () +{ + if (!source) return; + if (!audioBufferPort.get()) return; + else + { + if (!(audioBufferPort.get() instanceof AudioBuffer)) return; + } + + if (playPort.get()) + { + if (isPlaying) + { + resetTriggered = true; + stop(0); + } + else + { + start(0); + } + } +}; + +// functions +function createAudioBufferSource(dontStart = false) +{ + if (isLoading) return; + if (!(audioBufferPort.get() instanceof AudioBuffer)) return; + + isLoading = true; + outLoading.set(isLoading); + + if (source) + { + source.onended = null; + + if (source.buffer) + { + stop(0); + source.disconnect(gainNode); + source.buffer = null; + } + + source = null; + } + + source = audioCtx.createBufferSource(); + + const buffer = audioBufferPort.get(); + + if (!buffer) + { + isLoading = false; + outLoading.set(isLoading); + return; + } + + source.buffer = buffer; + source.onended = onPlaybackEnded; + source.loop = loopPort.get(); + + source.connect(gainNode); + setPlaybackRate(); + setDetune(); + audioOutPort.set(gainNode); + + isLoading = false; + outLoading.set(isLoading); + + if (resetTriggered) + { + start(0); + resetTriggered = false; + return; + } + + if (playPort.get() && !dontStart) + { + // if (!isPlaying) + start(0); + } +} + +let timeOuting = false; +let timerId = null; + +offsetPort.onChange = () => +{ + if (offsetPort.get() >= 0) op.setUiError("offsetNegative", null); + else + { + op.setUiError("offsetNegative", "Offset cannot be negative. Setting to 0.", 1); + } + + if (source) + { + if (source.buffer) + { + if (offsetPort.get() > source.buffer.duration) + { + op.setUiError("offsetTooLong", "Your offset value is higher than the total time of your audio file. Please decrease the duration to be able to hear sound when playing back your buffer.", 1); + } + else + { + op.setUiError("offsetTooLong", null); + } + } + } +}; + +function start(time) +{ + try + { + if (source) + { + let offset = Math.max(0, offsetPort.get()); + source.start(time, offset); // 0 = now + + isPlaying = true; + hasEnded = false; + outPlaying.set(true); + } + else + { + op.log("start() but no src..."); + } + } + catch (e) + { + op.log("Error on start: ", e.message); + outPlaying.set(false); + + isPlaying = false; + } +} + +function recreateBuffer() +{ + let dontStart = !loopPort.get(); + createAudioBufferSource(dontStart); +} + +function stop(time) +{ + try + { + if (source) + { + source.stop(); + if (!resetTriggered) recreateBuffer(); + } + + isPlaying = false; + outPlaying.set(false); + } + catch (e) + { + op.setUiError(e); + outPlaying.set(false); + } +} + +function onPlaybackEnded() +{ + if (loopPort.get()) + { + isPlaying = true; + hasEnded = false; + } + else + { + isPlaying = false; + hasEnded = true; + } + outPlaying.set(isPlaying); + + recreateBuffer(); +} + + +}; + +Ops.WebAudio.AudioBufferPlayer_v2.prototype = new CABLES.Op(); +CABLES.OPS["3abd0dbb-eeee-4c65-ae31-b8bc2345e2d5"]={f:Ops.WebAudio.AudioBufferPlayer_v2,objName:"Ops.WebAudio.AudioBufferPlayer_v2"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.AudioBufferToSplineArray +// +// ************************************************************** + +Ops.WebAudio.AudioBufferToSplineArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// currently only uses mono, if we want to extract stereo data some changes in extractPeaks are needed + +// constants +const SAMPLES_PER_PIXEL_MIN = 100; // might crash when this is too low + +function findMinMax(array) +{ + let min = Infinity; + let max = -Infinity; + let i = 0; + let len = array.length; + let curr; + + for (; i < len; i++) + { + curr = array[i]; + if (min > curr) + { + min = curr; + } + if (max < curr) + { + max = curr; + } + } + + return { + "min": min, + "max": max + }; +} + +const cgl = op.patch.cgl; + +// input +const renderPort = op.inTrigger("Render"); +const audioBufferPort = op.inObject("Audio Buffer", null, "audioBuffer"); +const inWidth = op.inFloat("Width", 1); +const inHeight = op.inFloat("Height", 0.5); +const samplesPerPixelPort = op.inInt("Samples Per Pixel", 10000); + +op.setPortGroup("Waveform Settings", [inWidth, inHeight, samplesPerPixelPort]); +// output +const nextPort = op.outTrigger("Next"); +const outArray = op.outArray("Array Out"); + +// change listeners +let updating = true; +audioBufferPort.onChange = samplesPerPixelPort.onChange += inWidth.onChange = inHeight.onChange = () => + { + if (audioBufferPort.get()) + { + if (!renderPort.isLinked()) + { + const audioBuffer = audioBufferPort.get(); + if (!(audioBuffer instanceof AudioBuffer)) return; + } + } + + updating = true; + }; + +renderPort.onTriggered = () => +{ + if (updating) + { + extractPeaks(); + updating = false; + } + nextPort.trigger(); +}; + +function extractPeaks() +{ + const audioBuffer = audioBufferPort.get(); + if (audioBuffer) + { + op.setUiError("noBuffer", null); + + if (!(audioBuffer instanceof AudioBuffer)) return; + } + else + { + op.setUiError("noBuffer", "You need to connect the \"Audio Buffer\" input for this op to work!", 0); + } + + if (audioBuffer) + { + let samplesPerPixel = samplesPerPixelPort.get(); + if (samplesPerPixel < SAMPLES_PER_PIXEL_MIN) + { + op.setUiError("minSamples", "The value for \"Samples Per Pixel\" is lower than the minimum value " + SAMPLES_PER_PIXEL_MIN + ". Therefore the value has been set to " + SAMPLES_PER_PIXEL_MIN + ".", 1); + samplesPerPixel = SAMPLES_PER_PIXEL_MIN; + } + else + { + op.setUiError("minSamples", null); + } + + let makeMono = audioBuffer.numberOfChannels < 2; // TODO: If we make this a parameter, we have to check if the audio actually is stereo + + const peaks = webaudioPeaks(audioBuffer, samplesPerPixel, makeMono); + + // because we extract mono peaks we just access [0] here + const typedArr = peaks.data[0]; + const regularArr = Array.prototype.slice.call(typedArr); + const minMax = findMinMax(regularArr); + const normalizedArray = []; + for (let i = 0; i < regularArr.length; i += 1) + { + normalizedArray.push( + CABLES.map(i, 0, regularArr.length - 1, -inWidth.get(), inWidth.get()) + ); + normalizedArray.push( + CABLES.map(regularArr[i], minMax.min, minMax.max, -inHeight.get(), inHeight.get()) + ); + normalizedArray.push(0); + } + + outArray.set(null); + outArray.set(normalizedArray); + } + else + { + outArray.set(null); + } +} + + +}; + +Ops.WebAudio.AudioBufferToSplineArray.prototype = new CABLES.Op(); +CABLES.OPS["0a573407-f1af-4580-ba37-1604108151bd"]={f:Ops.WebAudio.AudioBufferToSplineArray,objName:"Ops.WebAudio.AudioBufferToSplineArray"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.AudioBuffer_v2 +// +// ************************************************************** + +Ops.WebAudio.AudioBuffer_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const cgl = op.patch.cgl; + +const + audioCtx = CABLES.WEBAUDIO.createAudioContext(op), + inUrlPort = op.inUrl("URL", "audio"), + inLoadingTask = op.inBool("Create Loading Task", true), + audioBufferPort = op.outObject("Audio Buffer", null, "audioBuffer"), + finishedLoadingPort = op.outBoolNum("Finished Loading", false), + sampleRatePort = op.outNumber("Sample Rate", 0), + lengthPort = op.outNumber("Length", 0), + durationPort = op.outNumber("Duration", 0), + numberOfChannelsPort = op.outNumber("Number of Channels", 0), + outLoading = op.outBool("isLoading", 0); + +let currentBuffer = null; +let isLoading = false; +let currentFileUrl = null; +let urlToLoadNext = null; +let clearAfterLoad = false; +let fromData = false; +let fromDataNew = false; +let fileReader = new FileReader(); +let arrayBuffer = null; +let loadingIdDataURL = 0; + +if (!audioBufferPort.isLinked()) +{ + op.setUiError("notConnected", "To play back sound, connect this op to a playback operator such as SamplePlayer or AudioBufferPlayer.", 0); +} +else +{ + op.setUiError("notConnected", null); +} + +audioBufferPort.onLinkChanged = () => +{ + if (audioBufferPort.isLinked()) + { + op.setUiError("notConnected", null); + } + else + { + op.setUiError("notConnected", "To play back sound, connect this op to a playback operator such as SamplePlayer or AudioBufferPlayer.", 0); + } +}; + +function loadAudioFile(url, loadFromData) +{ + currentFileUrl = url; + isLoading = true; + outLoading.set(isLoading); + + if (!loadFromData) + { + const ext = url.substr(url.lastIndexOf(".") + 1); + if (ext === "wav") + { + op.setUiError("wavFormat", "You are using a .wav file. Make sure the .wav file is 16 bit to be supported by all browsers. Safari does not support 24 bit .wav files.", 1); + } + else + { + op.setUiError("wavFormat", null); + } + + CABLES.WEBAUDIO.loadAudioFile(op.patch, url, onLoadFinished, onLoadFailed, inLoadingTask.get()); + } + else + { + let fileBlob = dataURItoBlob(url); + + if (fileBlob.type === "audio/wav") + { + op.setUiError("wavFormat", "You are using a .wav file. Make sure the .wav file is 16 bit to be supported by all browsers. Safari does not support 24 bit .wav files.", 1); + } + else + { + op.setUiError("wavFormat", null); + } + + if (inLoadingTask.get()) + { + loadingIdDataURL = cgl.patch.loading.start("audiobuffer from data-url " + op.id, ""); + if (cgl.patch.isEditorMode()) gui.jobs().start({ "id": "loadaudio" + loadingIdDataURL, "title": " loading audio data url (" + op.id + ")" }); + } + + fileReader.readAsArrayBuffer(fileBlob); + } +} + +function dataURItoBlob(dataURI) +{ + // convert base64 to raw binary data held in a string + // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this + let byteString = atob(dataURI.split(",")[1]); + + // separate out the mime component + let mimeString = dataURI.split(",")[0].split(":")[1].split(";")[0]; + + // write the bytes of the string to an ArrayBuffer + let ab = new ArrayBuffer(byteString.length); + + // create a view into the buffer + let ia = new Uint8Array(ab); + + // set the bytes of the buffer to the correct values + for (let i = 0; i < byteString.length; i++) + { + ia[i] = byteString.charCodeAt(i); + } + + // write the ArrayBuffer to a blob, and you're done + let blob = new Blob([ab], { "type": mimeString }); + return blob; +} + +// change listeners +inUrlPort.onChange = function () +{ + if (inUrlPort.get()) + { + fromData = String(inUrlPort.get()).indexOf("data:") == 0; + + if (isLoading) + { + fromDataNew = String(inUrlPort.get()).indexOf("data:") == 0; + const newUrl = fromDataNew ? inUrlPort.get() : op.patch.getFilePath(inUrlPort.get()); + if (newUrl !== currentFileUrl) + { + urlToLoadNext = newUrl; + } + else + { + urlToLoadNext = null; + } + + clearAfterLoad = false; + return; + } + + invalidateOutPorts(); + const url = fromData ? inUrlPort.get() : op.patch.getFilePath(inUrlPort.get()); + + loadAudioFile(url, fromData); + } + else + { + if (isLoading) + { + clearAfterLoad = true; + return; + } + invalidateOutPorts(); + op.setUiError("wavFormat", null); + op.setUiError("failedLoading", null); + } +}; + +fileReader.onloadend = () => +{ + arrayBuffer = fileReader.result; + cgl.patch.loading.finished(loadingIdDataURL); + if (cgl.patch.isEditorMode()) gui.jobs().finish("loadaudio" + loadingIdDataURL); + loadFromDataURL(); +}; + +function loadFromDataURL() +{ + if (arrayBuffer) audioCtx.decodeAudioData(arrayBuffer, onLoadFinished, onLoadFailed); +} + +function onLoadFinished(buffer) +{ + isLoading = false; + outLoading.set(isLoading); + + if (clearAfterLoad) + { + invalidateOutPorts(); + clearAfterLoad = false; + return; + } + + if (urlToLoadNext) + { + loadAudioFile(urlToLoadNext, fromDataNew); + urlToLoadNext = null; + } + else + { + currentBuffer = buffer; + lengthPort.set(buffer.length); + durationPort.set(buffer.duration); + numberOfChannelsPort.set(buffer.numberOfChannels); + sampleRatePort.set(buffer.sampleRate); + audioBufferPort.set(buffer); + op.setUiError("failedLoading", null); + finishedLoadingPort.set(true); + fromData = false; + fromDataNew = false; + } +} + +function onLoadFailed(e) +{ + op.logError("Error: Loading audio file failed: ", e); + op.setUiError("failedLoading", "The audio file could not be loaded. Make sure the right file URL is used.", 2); + isLoading = false; + invalidateOutPorts(); + outLoading.set(isLoading); + currentBuffer = null; + + if (urlToLoadNext) + { + loadAudioFile(urlToLoadNext, fromDataNew); + urlToLoadNext = null; + } +} + +function invalidateOutPorts() +{ + lengthPort.set(0); + durationPort.set(0); + numberOfChannelsPort.set(0); + sampleRatePort.set(0); + + audioBufferPort.set(null); + + finishedLoadingPort.set(false); +} + + +}; + +Ops.WebAudio.AudioBuffer_v2.prototype = new CABLES.Op(); +CABLES.OPS["5f1d6a2f-1c04-4744-b0fb-910825beceee"]={f:Ops.WebAudio.AudioBuffer_v2,objName:"Ops.WebAudio.AudioBuffer_v2"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.AudioPanner +// +// ************************************************************** + +Ops.WebAudio.AudioPanner = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +function clamp(val, min, max) +{ + return Math.min(Math.max(val, min), max); +} + +const audioIn = op.inObject("audio in", null, "audioNode"); +const pan = op.inFloat("Pan", 0); +pan.onChange = updateGain; +const audioOut = op.outObject("audio out", null, "audioNode"); + +let audioContext = CABLES.WEBAUDIO.createAudioContext(op); + +let isIOS = false; +let panNode = null; +if (audioContext.createStereoPanner) +{ + panNode = audioContext.createStereoPanner(); +} +else +{ + panNode = audioContext.createPanner(); + panNode.panningModel = "equalpower"; + isIOS = true; +} + +function updateGain() +{ + const panning = clamp(pan.get(), -1, 1); + + if (!isIOS) panNode.pan.setValueAtTime(panning, audioContext.currentTime); + else + { + panNode.setPosition(panning, 0, 1 - Math.abs(panning)); + } +} + +let oldAudioIn = null; + +audioIn.onChange = function () +{ + if (!audioIn.get()) + { + if (oldAudioIn) + { + try + { + if (oldAudioIn.disconnect) + { + oldAudioIn.disconnect(panNode); + } + } + catch (e) + { + op.log(e); + } + } + + audioOut.set(null); + } + else + { + if (audioIn.get().connect) + { + audioIn.get().connect(panNode); + audioOut.set(panNode); + } + } + oldAudioIn = audioIn.get(); +}; + + +}; + +Ops.WebAudio.AudioPanner.prototype = new CABLES.Op(); +CABLES.OPS["313ebceb-fa16-4400-aa2b-20859614c7c6"]={f:Ops.WebAudio.AudioPanner,objName:"Ops.WebAudio.AudioPanner"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.AudioRecorder +// +// ************************************************************** + +Ops.WebAudio.AudioRecorder = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"inc_mediarecorder_js":"\nclass IOSMediaRecorder {\n /**\n * @param {MediaStream} stream The audio stream to record.\n */\n constructor (stream, config = null) {\n /**\n * The `MediaStream` passed into the constructor.\n * @type {MediaStream}\n */\n this.stream = stream\n this.config = config\n /**\n * The current state of recording process.\n * @type {\"inactive\"|\"recording\"|\"paused\"}\n */\n this.state = 'inactive'\n\n this.em = document.createDocumentFragment()\n const blob = new Blob([attachments.waveencoder_js], { \"type\": \"text/javascript\" });\n const fileURL = URL.createObjectURL(blob);\n this.blob = blob;\n this.fileURL = fileURL;\n this.encoder = new Worker(this.fileURL, { \"name\": \"AudioRecorder Encoder with op-id: \" + op.id });\n this.encoder.onmessage = e => {\n let event = new Event('dataavailable');\n\n event.data = new Blob([e.data], { type: this.mimeType });\n this.em.dispatchEvent(event);\n\n // clean up worker after recording\n this.encoder.terminate();\n this.encoder = null;\n\n if (this.state === 'inactive') {\n this.em.dispatchEvent(new Event('stop'))\n }\n };\n\n }\n\n error(method) {\n let event = new Event('error')\n event.data = new Error('Wrong state for ' + method)\n return event\n }\n\n terminateWorker() {\n if (this.encoder) {\n this.encoder.terminate();\n this.encoder = null;\n }\n }\n /**\n * Begins recording media.\n *\n * @param {number} [timeslice] The milliseconds to record into each `Blob`.\n * If this parameter isn’t included, single `Blob`\n * will be recorded.\n *\n * @return {undefined}\n *\n * @example\n * recordButton.addEventListener('click', () => {\n * recorder.start()\n * })\n */\n start (timeslice) {\n\n\n if (!this.encoder) {\n this.encoder = new Worker(this.fileURL, { \"name\": \"AudioRecorder Encoder with op-id: \" + op.id });\n this.encoder.onmessage = e => {\n let event = new Event('dataavailable');\n\n event.data = new Blob([e.data], { type: this.mimeType });\n this.em.dispatchEvent(event);\n\n // clean up worker after recording\n this.encoder.terminate();\n this.encoder = null;\n if (this.state === 'inactive') {\n this.em.dispatchEvent(new Event('stop'))\n }\n };\n }\n\n if (this.state !== 'inactive') {\n return this.em.dispatchEvent(this.error('start'))\n }\n\n this.state = 'recording'\n\n\n\n this.clone = this.stream.clone()\n this.input = audioCtx.createMediaStreamSource(this.clone)\n\n this.numberOfChannels = this.input.channelCount;\n\n this.processor = audioCtx.createScriptProcessor(2048, this.numberOfChannels, this.numberOfChannels);\n\n this.encoder.postMessage(['init', audioCtx.sampleRate])\n\n this.processor.onaudioprocess = e => {\n if (this.state === 'recording') {\n this.encoder.postMessage([\n 'encode',\n [\n [e.inputBuffer.getChannelData(0), e.inputBuffer.getChannelData(1)],\n this.numberOfChannels\n ],\n ]);\n }\n }\n\n this.input.connect(this.processor)\n this.processor.connect(audioCtx.destination)\n\n this.em.dispatchEvent(new Event('start'))\n\n if (timeslice) {\n this.slicing = setInterval(() => {\n if (this.state === 'recording') this.requestData()\n }, timeslice)\n }\n return undefined\n }\n\n /**\n * Stop media capture and raise `dataavailable` event with recorded data.\n *\n * @return {undefined}\n *\n * @example\n * finishButton.addEventListener('click', () => {\n * recorder.stop()\n * })\n */\n stop () {\n if (this.state === 'inactive') {\n return this.em.dispatchEvent(this.error('stop'))\n }\n\n this.requestData()\n this.state = 'inactive'\n this.clone.getTracks().forEach(track => {\n track.stop()\n })\n this.processor.disconnect()\n this.input.disconnect()\n return clearInterval(this.slicing)\n }\n\n /**\n * Pauses recording of media streams.\n *\n * @return {undefined}\n *\n * @example\n * pauseButton.addEventListener('click', () => {\n * recorder.pause()\n * })\n */\n pause () {\n if (this.state !== 'recording') {\n return this.em.dispatchEvent(this.error('pause'))\n }\n\n this.state = 'paused'\n return this.em.dispatchEvent(new Event('pause'))\n }\n\n /**\n * Resumes media recording when it has been previously paused.\n *\n * @return {undefined}\n *\n * @example\n * resumeButton.addEventListener('click', () => {\n * recorder.resume()\n * })\n */\n resume () {\n if (this.state !== 'paused') {\n return this.em.dispatchEvent(this.error('resume'))\n }\n\n this.state = 'recording'\n return this.em.dispatchEvent(new Event('resume'))\n }\n\n /**\n * Raise a `dataavailable` event containing the captured media.\n *\n * @return {undefined}\n *\n * @example\n * this.on('nextData', () => {\n * recorder.requestData()\n * })\n */\n requestData () {\n if (this.state === 'inactive') {\n return this.em.dispatchEvent(this.error('requestData'))\n }\n\n return this.encoder.postMessage([\n 'dump',\n [audioCtx.sampleRate, this.numberOfChannels],\n ]);\n }\n\n /**\n * Add listener for specified event type.\n *\n * @param {\"start\"|\"stop\"|\"pause\"|\"resume\"|\"dataavailable\"|\"error\"}\n * type Event type.\n * @param {function} listener The listener function.\n *\n * @return {undefined}\n *\n * @example\n * recorder.addEventListener('dataavailable', e => {\n * audio.src = URL.createObjectURL(e.data)\n * })\n */\n addEventListener (...args) {\n this.em.addEventListener(...args)\n }\n\n /**\n * Remove event listener.\n *\n * @param {\"start\"|\"stop\"|\"pause\"|\"resume\"|\"dataavailable\"|\"error\"}\n * type Event type.\n * @param {function} listener The same function used in `addEventListener`.\n *\n * @return {undefined}\n */\n removeEventListener (...args) {\n this.em.removeEventListener(...args)\n }\n\n /**\n * Calls each of the listeners registered for a given event.\n *\n * @param {Event} event The event object.\n *\n * @return {boolean} Is event was no canceled by any listener.\n */\n dispatchEvent (...args) {\n this.em.dispatchEvent(...args)\n }\n}\n\n/**\n * The MIME type that is being used for recording.\n * @type {string}\n */\nIOSMediaRecorder.prototype.mimeType = 'audio/wav'\n\n/**\n * Returns `true` if the MIME type specified is one the polyfill can record.\n *\n * This polyfill supports `audio/wav` and `audio/mpeg`.\n *\n * @param {string} mimeType The mimeType to check.\n *\n * @return {boolean} `true` on `audio/wav` and `audio/mpeg` MIME type.\n */\nIOSMediaRecorder.isTypeSupported = mimeType => {\n return IOSMediaRecorder.prototype.mimeType === mimeType\n}\n\n/**\n * `true` if MediaRecorder can not be polyfilled in the current browser.\n * @type {boolean}\n *\n * @example\n * if (IOSMediaRecorder.notSupported) {\n * showWarning('Audio recording is not supported in this browser')\n * }\n */\nIOSMediaRecorder.notSupported = !navigator.mediaDevices || !AudioContext\n\n/**\n * Converts RAW audio buffer to compressed audio files.\n * It will be loaded to Web Worker.\n * By default, WAVE encoder will be used.\n * @type {function}\n *\n * @example\n * IOSMediaRecorder.prototype.mimeType = 'audio/ogg'\n * IOSMediaRecorder.encoder = oggEncoder\n */","waveencoder_js":"function clamp(val, min, max)\n{\n return Math.min(Math.max(val, min), max);\n}\n\nlet BYTES_PER_SAMPLE = 2\n\n let recorded = []\n\n function encode ([buffers, numberOfChannels]) {\n let length = buffers[0].length\n let data = new Uint8Array(length * numberOfChannels * BYTES_PER_SAMPLE)\n // Interleave\n for (let i = 0; i < length; i++ ) {\n\n for (let channel = 0; channel < numberOfChannels; channel++ ) {\n const outputIndex = ( i * numberOfChannels + channel ) * BYTES_PER_SAMPLE;\n\n // clip the signal if it exceeds [-1, 1]\n let sample = clamp(buffers[channel][i], -1, 1);\n sample = sample * 32767.5 - 0.5;\n data[ outputIndex] = sample;\n data[ outputIndex + 1 ] = sample >> 8;\n }\n }\n recorded.push(data)\n }\n\n function dump ([sampleRate, numberOfChannels]) {\n let bufferLength = recorded.length ? recorded[0].length : 0\n let length = recorded.length * bufferLength\n let wav = new Uint8Array(44 + length)\n let view = new DataView(wav.buffer)\n\n // RIFF identifier 'RIFF'\n view.setUint32(0, 1380533830, false)\n // file length minus RIFF identifier length and file description length\n view.setUint32(4, 36 + length, true)\n // RIFF type 'WAVE'\n view.setUint32(8, 1463899717, false)\n // format chunk identifier 'fmt '\n view.setUint32(12, 1718449184, false)\n // format chunk length\n view.setUint32(16, 16, true)\n // sample format (raw)\n view.setUint16(20, 1, true)\n // channel count\n view.setUint16(22, numberOfChannels, true)\n // sample rate\n view.setUint32(24, sampleRate, true)\n // byte rate (sample rate * block align)\n view.setUint32(28, sampleRate * BYTES_PER_SAMPLE * numberOfChannels, true)\n // block align (channel count * bytes per sample)\n view.setUint16(32, BYTES_PER_SAMPLE * numberOfChannels, true)\n // bits per sample\n view.setUint16(34, 8 * BYTES_PER_SAMPLE, true)\n // data chunk identifier 'data'\n view.setUint32(36, 1684108385, false)\n // data chunk length\n view.setUint32(40, length, true)\n\n for (let i = 0; i < recorded.length; i++) {\n wav.set(recorded[i], i * bufferLength + 44)\n }\n\n recorded = []\n postMessage(wav.buffer, [wav.buffer])\n }\n\n onmessage = e => {\n if (e.data[0] === 'encode') {\n encode(e.data[1])\n } else if (e.data[0] === 'dump') {\n dump(e.data[1])\n }\n }",}; + +class IOSMediaRecorder { + /** + * @param {MediaStream} stream The audio stream to record. + */ + constructor (stream, config = null) { + /** + * The `MediaStream` passed into the constructor. + * @type {MediaStream} + */ + this.stream = stream + this.config = config + /** + * The current state of recording process. + * @type {"inactive"|"recording"|"paused"} + */ + this.state = 'inactive' + + this.em = document.createDocumentFragment() + const blob = new Blob([attachments.waveencoder_js], { "type": "text/javascript" }); + const fileURL = URL.createObjectURL(blob); + this.blob = blob; + this.fileURL = fileURL; + this.encoder = new Worker(this.fileURL, { "name": "AudioRecorder Encoder with op-id: " + op.id }); + this.encoder.onmessage = e => { + let event = new Event('dataavailable'); + + event.data = new Blob([e.data], { type: this.mimeType }); + this.em.dispatchEvent(event); + + // clean up worker after recording + this.encoder.terminate(); + this.encoder = null; + + if (this.state === 'inactive') { + this.em.dispatchEvent(new Event('stop')) + } + }; + + } + + error(method) { + let event = new Event('error') + event.data = new Error('Wrong state for ' + method) + return event + } + + terminateWorker() { + if (this.encoder) { + this.encoder.terminate(); + this.encoder = null; + } + } + /** + * Begins recording media. + * + * @param {number} [timeslice] The milliseconds to record into each `Blob`. + * If this parameter isn’t included, single `Blob` + * will be recorded. + * + * @return {undefined} + * + * @example + * recordButton.addEventListener('click', () => { + * recorder.start() + * }) + */ + start (timeslice) { + + + if (!this.encoder) { + this.encoder = new Worker(this.fileURL, { "name": "AudioRecorder Encoder with op-id: " + op.id }); + this.encoder.onmessage = e => { + let event = new Event('dataavailable'); + + event.data = new Blob([e.data], { type: this.mimeType }); + this.em.dispatchEvent(event); + + // clean up worker after recording + this.encoder.terminate(); + this.encoder = null; + if (this.state === 'inactive') { + this.em.dispatchEvent(new Event('stop')) + } + }; + } + + if (this.state !== 'inactive') { + return this.em.dispatchEvent(this.error('start')) + } + + this.state = 'recording' + + + + this.clone = this.stream.clone() + this.input = audioCtx.createMediaStreamSource(this.clone) + + this.numberOfChannels = this.input.channelCount; + + this.processor = audioCtx.createScriptProcessor(2048, this.numberOfChannels, this.numberOfChannels); + + this.encoder.postMessage(['init', audioCtx.sampleRate]) + + this.processor.onaudioprocess = e => { + if (this.state === 'recording') { + this.encoder.postMessage([ + 'encode', + [ + [e.inputBuffer.getChannelData(0), e.inputBuffer.getChannelData(1)], + this.numberOfChannels + ], + ]); + } + } + + this.input.connect(this.processor) + this.processor.connect(audioCtx.destination) + + this.em.dispatchEvent(new Event('start')) + + if (timeslice) { + this.slicing = setInterval(() => { + if (this.state === 'recording') this.requestData() + }, timeslice) + } + return undefined + } + + /** + * Stop media capture and raise `dataavailable` event with recorded data. + * + * @return {undefined} + * + * @example + * finishButton.addEventListener('click', () => { + * recorder.stop() + * }) + */ + stop () { + if (this.state === 'inactive') { + return this.em.dispatchEvent(this.error('stop')) + } + + this.requestData() + this.state = 'inactive' + this.clone.getTracks().forEach(track => { + track.stop() + }) + this.processor.disconnect() + this.input.disconnect() + return clearInterval(this.slicing) + } + + /** + * Pauses recording of media streams. + * + * @return {undefined} + * + * @example + * pauseButton.addEventListener('click', () => { + * recorder.pause() + * }) + */ + pause () { + if (this.state !== 'recording') { + return this.em.dispatchEvent(this.error('pause')) + } + + this.state = 'paused' + return this.em.dispatchEvent(new Event('pause')) + } + + /** + * Resumes media recording when it has been previously paused. + * + * @return {undefined} + * + * @example + * resumeButton.addEventListener('click', () => { + * recorder.resume() + * }) + */ + resume () { + if (this.state !== 'paused') { + return this.em.dispatchEvent(this.error('resume')) + } + + this.state = 'recording' + return this.em.dispatchEvent(new Event('resume')) + } + + /** + * Raise a `dataavailable` event containing the captured media. + * + * @return {undefined} + * + * @example + * this.on('nextData', () => { + * recorder.requestData() + * }) + */ + requestData () { + if (this.state === 'inactive') { + return this.em.dispatchEvent(this.error('requestData')) + } + + return this.encoder.postMessage([ + 'dump', + [audioCtx.sampleRate, this.numberOfChannels], + ]); + } + + /** + * Add listener for specified event type. + * + * @param {"start"|"stop"|"pause"|"resume"|"dataavailable"|"error"} + * type Event type. + * @param {function} listener The listener function. + * + * @return {undefined} + * + * @example + * recorder.addEventListener('dataavailable', e => { + * audio.src = URL.createObjectURL(e.data) + * }) + */ + addEventListener (...args) { + this.em.addEventListener(...args) + } + + /** + * Remove event listener. + * + * @param {"start"|"stop"|"pause"|"resume"|"dataavailable"|"error"} + * type Event type. + * @param {function} listener The same function used in `addEventListener`. + * + * @return {undefined} + */ + removeEventListener (...args) { + this.em.removeEventListener(...args) + } + + /** + * Calls each of the listeners registered for a given event. + * + * @param {Event} event The event object. + * + * @return {boolean} Is event was no canceled by any listener. + */ + dispatchEvent (...args) { + this.em.dispatchEvent(...args) + } +} + +/** + * The MIME type that is being used for recording. + * @type {string} + */ +IOSMediaRecorder.prototype.mimeType = 'audio/wav' + +/** + * Returns `true` if the MIME type specified is one the polyfill can record. + * + * This polyfill supports `audio/wav` and `audio/mpeg`. + * + * @param {string} mimeType The mimeType to check. + * + * @return {boolean} `true` on `audio/wav` and `audio/mpeg` MIME type. + */ +IOSMediaRecorder.isTypeSupported = mimeType => { + return IOSMediaRecorder.prototype.mimeType === mimeType +} + +/** + * `true` if MediaRecorder can not be polyfilled in the current browser. + * @type {boolean} + * + * @example + * if (IOSMediaRecorder.notSupported) { + * showWarning('Audio recording is not supported in this browser') + * } + */ +IOSMediaRecorder.notSupported = !navigator.mediaDevices || !AudioContext + +/** + * Converts RAW audio buffer to compressed audio files. + * It will be loaded to Web Worker. + * By default, WAVE encoder will be used. + * @type {function} + * + * @example + * IOSMediaRecorder.prototype.mimeType = 'audio/ogg' + * IOSMediaRecorder.encoder = oggEncoder + */// inspired by: https://github.com/kaliatech/web-audio-recording-tests/blob/master/src/shared/RecorderService.js + +const audioCtx = CABLES.WEBAUDIO.createAudioContext(op); + +const inAudio = op.inObject("Audio In", null, "audioNode"); +const inStartRecording = op.inTriggerButton("Start Recording"); +const inStopRecording = op.inTriggerButton("Stop Recording"); +const inRecordGain = op.inFloatSlider("Input Gain", 1); +op.setPortGroup("Recording", [inStartRecording, inStopRecording, inRecordGain]); + +const inStartPlayback = op.inTriggerButton("Start Playback"); +const inStopPlayback = op.inTriggerButton("Stop Playback"); +const inClearBuffer = op.inTriggerButton("Clear Buffer"); +const inPlaybackGain = op.inFloatSlider("Playback Gain", 1); +const inLoop = op.inBool("Loop Playback", false); +op.setPortGroup("Playback", [inStartPlayback, inStopPlayback, inLoop, inClearBuffer, inPlaybackGain]); +const inDownloadButton = op.inTriggerButton("Download .wav File"); + +const outOriginal = op.outObject("Audio Out", null, "audioNode"); +const outRecorded = op.outObject("Recorded Audio Out", null, "audioNode"); +const outIsRecording = op.outBool("Is Recording"); +const outIsPlayingBack = op.outBool("Is Playing Back"); +const outState = op.outString("State"); +const outBuffer = op.outObject("AudioBuffer Out", null, "audioBuffer"); +const outDataUrl = op.outString("Data URL"); + +inDownloadButton.setUiAttribs({ "greyout": true }); +outDataUrl.ignoreValueSerialize = true; + +const inputGain = audioCtx.createGain(); +const outputGain = audioCtx.createGain(); + +let isIOS = !navigator.hasOwnProperty("MediaRecorder"); + +const STATES = { + "RECORDING": "recording", + "PROCESSING": "processing", + "READY": "ready", + "PLAYING": "playing", + "IDLING": "idling" +}; + +let state = STATES.IDLING; +outState.set(state); + +const inputStream = audioCtx.createMediaStreamDestination(); + +let mediaRecorder = null; +let fileReader = null; +let blob = null; + +if (isIOS) +{ + mediaRecorder = new IOSMediaRecorder(inputStream.stream); + fileReader = new FileReader(); +} +else +{ + mediaRecorder = new MediaRecorder(inputStream.stream); +} + +mediaRecorder.addEventListener("dataavailable", (e) => +{ + blob = e.data; + if (blob) + { + inDownloadButton.setUiAttribs({ "greyout": !blob }); + let reader = new FileReader(); + reader.onload = function (e) + { + outDataUrl.set(e.target.result); + }; + reader.readAsDataURL(blob); + } + + if (!isIOS) + { + e.data.arrayBuffer() // its a blob + .then((buffer) => + { + arrayBuffer = buffer; + audioCtx.decodeAudioData(arrayBuffer, (buffer) => + { + audioBuffer = buffer; + outBuffer.set(audioBuffer); + createAudioBufferSource(); + }); + }) + .catch((e) => op.log(e)); + } + else + { + fileReader.onload = () => + { + arrayBuffer = fileReader.result; + audioCtx.decodeAudioData(arrayBuffer, (buffer) => + { + audioBuffer = buffer; + outBuffer.set(audioBuffer); + createAudioBufferSource(); + }); + }; + fileReader.readAsArrayBuffer(e.data); + } +}); + +let oldAudioIn = null; + +let isRecording = false; +let isPlayingBack = false; +let bufferReady = false; + +inStartRecording.onTriggered = () => +{ + switch (state) + { + case STATES.RECORDING: + return; + case STATES.PROCESSING: + return; + case STATES.PLAYING: + return; + case STATES.READY: + break; + case STATES.IDLING: + break; + } + + if (!inAudio.get()) + { + op.setUiError("noAudioInput", "No audio input is connected. Recording aborted.", 2); + state = STATES.IDLING; + return; + } + op.setUiError("noAudioInput", null); + op.setUiError("recording", "Recoding audio...", 0); + + mediaRecorder.start(); + state = STATES.RECORDING; + + isRecording = true; + outIsRecording.set(isRecording); + outState.set(state); +}; + +inStopRecording.onTriggered = () => +{ + switch (state) + { + case STATES.RECORDING: + break; + case STATES.PROCESSING: + return; + case STATES.PLAYING: + return; + case STATES.READY: + return; + case STATES.IDLING: + return; + } + + op.setUiError("recording", null); + state = STATES.PROCESSING; + isRecording = false; + outState.set(state); + + mediaRecorder.stop(); + outIsRecording.set(isRecording); + op.setUiError("stopRecording", "Recording stopped. Preparing...", 0); +}; + +inStartPlayback.onTriggered = () => +{ + switch (state) + { + case STATES.RECORDING: + return; + case STATES.PROCESSING: + return; + case STATES.PLAYING: + return; + case STATES.READY: + break; + case STATES.IDLING: + // if (loopSource) break; + return; + } + + op.setUiError("readyPlayback", null); + loopSource.start(); + isPlayingBack = true; + state = STATES.PLAYING; + outState.set(state); + outIsPlayingBack.set(isPlayingBack); + op.setUiError("playingLoop", "Loop is playing...", 0); +}; + +inStopPlayback.onTriggered = () => +{ + switch (state) + { + case STATES.RECORDING: + return; + case STATES.PROCESSING: + return; + case STATES.PLAYING: + break; + case STATES.READY: + return; + case STATES.IDLING: + return; + } + + op.setUiError("playingLoop", null); + loopSource.stop(); + isPlayingBack = false; + outIsPlayingBack.set(isPlayingBack); + state = STATES.IDLING; + outState.set(state); + createAudioBufferSource(); +}; + +inPlaybackGain.onChange = () => +{ + outputGain.gain.linearRampToValueAtTime(inPlaybackGain.get(), audioCtx.currentTime + 0.01); +}; + +let arrayBuffer = null; +let audioBuffer = null; +let loopSource = null; + +inLoop.onChange = () => +{ + if (loopSource) loopSource.loop = inLoop.get(); +}; + +function createAudioBufferSource() +{ + if (loopSource) + { + if (state === STATES.PLAYING) + { + loopSource.stop(); + isPlayingBack = false; + outIsPlayingBack.set(isPlayingBack); + loopSource.disconnect(outputGain); + } + } + + if (!audioBuffer) return; + + loopSource = audioCtx.createBufferSource(); + loopSource.buffer = audioBuffer; + + loopSource.onended = () => + { + if (!state !== STATES.IDLING) createAudioBufferSource(); + }; + loopSource.loop = inLoop.get(); + + loopSource.connect(outputGain); + outRecorded.set(outputGain); + bufferReady = true; + state = STATES.READY; + outState.set(state); + op.setUiError("stopRecording", null); +} + +inClearBuffer.onTriggered = () => +{ + switch (state) + { + case STATES.RECORDING: + return; + case STATES.PROCESSING: + return; + case STATES.PLAYING: + op.setUiError("playingLoop", null); + break; + case STATES.READY: + break; + case STATES.IDLING: + break; + } + + if (!audioBuffer) return; + + state = STATES.IDLING; + outState.set(state); + + if (isPlayingBack) + { + loopSource.stop(); + isPlayingBack = false; + outIsPlayingBack.set(isPlayingBack); + } + + audioBuffer = null; + outBuffer.set(audioBuffer); + blob = null; + inDownloadButton.setUiAttribs({ "greyout": true }); + outDataUrl.set(null); +}; + +inDownloadButton.onTriggered = () => +{ + if (!blob) return; + + const anchor = document.createElement("a"); + + anchor.download = "AudioRecorder " + op.id + ".wav"; + anchor.href = URL.createObjectURL(blob); + + setTimeout(function () + { + anchor.click(); + }, 100); +}; + +inAudio.onLinkChanged = () => +{ + if (!inAudio.isLinked()) + { + switch (state) + { + case STATES.RECORDING: + break; + case STATES.PROCESSING: + return; + case STATES.PLAYING: + return; + case STATES.READY: + return; + case STATES.IDLING: + return; + } + + mediaRecorder.stop(); + if (isIOS) mediaRecorder.terminateWorker(); + state = STATES.IDLING; + outState.set(state); + } +}; + +op.onDelete = () => +{ + switch (state) + { + case STATES.RECORDING: + mediaRecorder.stop(); + break; + case STATES.PROCESSING: + break; + case STATES.PLAYING: + break; + case STATES.READY: + break; + case STATES.IDLING: + break; + } + if (isIOS) mediaRecorder.terminateWorker(); +}; + +inAudio.onChange = () => +{ + if (!inAudio.get()) + { + if (oldAudioIn) + { + try + { + if (oldAudioIn.disconnect) + { + oldAudioIn.disconnect(inputGain); + oldAudioIn.disconnect(inputStream); + } + } + catch (e) + { + op.log(e); + } + } + + outOriginal.set(null); + } + else + { + if (inAudio.get().connect) + { + inAudio.get().connect(inputGain); + inAudio.get().connect(inputStream); + } + + outOriginal.set(inputGain); + } + + oldAudioIn = inAudio.get(); +}; + +op.onDelete = () => +{ + if (loopSource) + { + loopSource.disconnect(); + } +}; + + +}; + +Ops.WebAudio.AudioRecorder.prototype = new CABLES.Op(); +CABLES.OPS["b4d46521-a8f8-4d54-abdb-98f1bfb80edd"]={f:Ops.WebAudio.AudioRecorder,objName:"Ops.WebAudio.AudioRecorder"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.BiquadFilter_v2 +// +// ************************************************************** + +Ops.WebAudio.BiquadFilter_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +function clamp(val, min, max) +{ + return Math.min(Math.max(val, min), max); +} + +const audioContext = CABLES.WEBAUDIO.createAudioContext(op); + +// default values + min and max +const FREQUENCY_MIN = 10; +const FREQUENCY_MAX = audioContext.sampleRate / 2; // Nyquist frequency. +const Q_MIN = 0.0001; +const Q_MAX = 1000; +const GAIN_MIN = -40; +const GAIN_MAX = 40; + +const filterNode = audioContext.createBiquadFilter(); + +const inAudio = op.inObject("Audio In", null, "audioNode"); +const inFilterType = op.inDropDown("Type", ["peaking", "lowpass", "highpass", "bandpass", "lowshelf", "highshelf", "notch", "allpass"], "peaking"); + +const inFrequency = op.inFloat("Frequency", 2000); +const inQ = op.inFloat("Q", 0.0001); +const inGain = op.inFloat("Gain", 0); + +const inDetune = op.inInt("Detune", 0); +const inFrequencyArray = op.inArray("Frequency Array"); + +op.setPortGroup("Filter Settings", [inFilterType, inFrequency, inQ, inGain]); +op.setPortGroup("Detune (in cents)", [inDetune]); +op.setPortGroup("Filter Response Input", [inFrequencyArray]); +const outAudio = op.outObject("Audio Out", null, "audioNode"); +const outMagnitudeResponseArray = op.outArray("Magnitude Response Array"); +const outPhaseResponseArray = op.outArray("Phase Response Array"); +const responseArraysLength = op.outNumber("Response Arrays Length"); + +let oldAudioIn = null; +filterNode.type = inFilterType.get(); + +let oldLength = 0; +let frequencyArray = null; +let phaseResponseArray = null; +let magnitudeResponseArray = null; + +function updateFrequencyResponse() +{ + const frequencies = inFrequencyArray.get(); + + if (!frequencies) return; + + if (inAudio.get()) + { + if (oldLength !== frequencies.length) + { + frequencyArray = new Float32Array(frequencies); + phaseResponseArray = new Float32Array(frequencies.length); + magnitudeResponseArray = new Float32Array(frequencies.length); + oldLength = frequencies.length; + } + + if (oldLength) + { + filterNode.getFrequencyResponse(frequencyArray, phaseResponseArray, magnitudeResponseArray); + + outMagnitudeResponseArray.set(null); + outMagnitudeResponseArray.set(magnitudeResponseArray); + + outPhaseResponseArray.set(null); + outPhaseResponseArray.set(phaseResponseArray); + + responseArraysLength.set(frequencies.length); + } + else + { + outMagnitudeResponseArray.set(null); + outPhaseResponseArray.set(null); + responseArraysLength.set(0); + } + } +} + +inFrequencyArray.onChange = () => updateFrequencyResponse(); +inAudio.onChange = function () +{ + if (!inAudio.get()) + { + if (oldAudioIn) + { + try + { + if (oldAudioIn.disconnect) oldAudioIn.disconnect(filterNode); + } + catch (e) + { + op.log(e); + } + } + + outAudio.set(null); + } + else + { + if (inAudio.get().connect) inAudio.get().connect(filterNode); + } + oldAudioIn = inAudio.get(); + outAudio.set(filterNode); +}; + +inFilterType.onChange = () => +{ + const type = inFilterType.get(); + inGain.setUiAttribs({ + "greyout": ["lowpass", "highpass", "bandpass", "notch", "allpass"].includes(type) + }); + + inQ.setUiAttribs({ + "greyout": ["lowshelf", "highshelf"].includes(type) + }); + + filterNode.type = type; + updateFrequencyResponse(); +}; + +inFrequency.onChange = () => +{ + const freq = inFrequency.get(); + if (freq) + { + if (freq >= FREQUENCY_MIN && freq <= FREQUENCY_MAX) + { + filterNode.frequency.setValueAtTime(clamp(freq, FREQUENCY_MIN, FREQUENCY_MAX), audioContext.currentTime); + op.setUiError("freqRange", null); + } + if (freq < FREQUENCY_MIN) + { + op.setUiError("freqRange", "The frequency you selected is lower than the possible frequency of " + FREQUENCY_MIN + " Hz.", 1); + } + else if (freq > FREQUENCY_MAX) + { + op.setUiError("freqRange", "The frequency you selected is higher than the possible frequency of " + FREQUENCY_MAX + " Hz.", 1); + } + } + updateFrequencyResponse(); +}; + +inDetune.onChange = () => +{ + filterNode.detune.setValueAtTime(inDetune.get(), audioContext.currentTime); + updateFrequencyResponse(); +}; + +inQ.onChange = () => +{ + const q = inQ.get(); + filterNode.Q.setValueAtTime(clamp(q, Q_MIN, Q_MAX), audioContext.currentTime); + + if (q < Q_MIN) op.setUiError("qRange", "Your Q value is below the minimum possible value of " + Q_MIN + ".", 1); + else if (q > Q_MAX) op.setUiError("qRange", "Your Q value is above the maximum possible value of " + Q_MAX + ".", 1); + else + { + op.setUiError("qRange", null); + } + updateFrequencyResponse(); +}; + +inGain.onChange = () => +{ + const gain = inGain.get(); + filterNode.gain.setValueAtTime(clamp(gain, GAIN_MIN, GAIN_MAX), audioContext.currentTime); + if (gain < GAIN_MIN) op.setUiError("gainRange", "Your gain value is below the minimum possible value of " + GAIN_MIN + " dB.", 1); + else if (gain > GAIN_MAX) op.setUiError("gainRange", "Your gain value is above the maximum possible value of " + GAIN_MAX + " dB.", 1); + else + { + op.setUiError("gainRange", null); + } + updateFrequencyResponse(); +}; + + +}; + +Ops.WebAudio.BiquadFilter_v2.prototype = new CABLES.Op(); +CABLES.OPS["a7b30545-6db3-47b5-8ffc-f659accd0eb6"]={f:Ops.WebAudio.BiquadFilter_v2,objName:"Ops.WebAudio.BiquadFilter_v2"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.ClockSequencer +// +// ************************************************************** + +Ops.WebAudio.ClockSequencer = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"worker_js":"let timerIDs = [];\nlet timerID = null;\nconst LOOKAHEAD_IN_MS = 25.;\nonmessage = (e) => {\n if (e.data === \"start\") {\n timerID = setInterval(() => postMessage(\"tick\"), LOOKAHEAD_IN_MS);\n return;\n }\n\n if (e.data === \"stop\") {\n clearInterval(timerID);\n timerID = null;\n console.log(\"stopped\");\n }\n};\n\nonerror = (e) => {\n console.log(\"worker error\", e);\n}\n",}; +const audioCtx = CABLES.WEBAUDIO.createAudioContext(op); + +const inBPM = op.inInt("BPM", 100); +const inStart = op.inTriggerButton("Start"); +const inStop = op.inTriggerButton("Stop"); +const inReset = op.inTriggerButton("Reset"); + +const outTriggers = []; +for (let i = 0; i < 7 * 3; i += 1) +{ + const noteValue = Math.pow(2, i % 7); + let string = "1/" + noteValue; + if (i > 6 && i < 14) + { + string = "1/" + noteValue + " Triplet"; + } + else if (i > 13) + { + string = "1/" + noteValue + " Dotted"; + } + outTriggers[i] = op.outTrigger(string + " Note Trigger"); +} + +const outRunning = op.outBool("Sequencer Running"); +const outBPM = op.outNumber("BPM Out"); +const outStart = op.outTrigger("Start Out"); +const outStop = op.outTrigger("Stop Out"); +const outReset = op.outTrigger("Reset Out"); + +const MIN_BPM = 20; + +const NOTE_QUEUE = []; +const LOOKAHEAD_IN_MS = 25.0; +const SCHEDULEAHEAD_IN_S = 0.1; + +const MULTIPLIERS = [ + 4, 2, 1, 1 / 2, 1 / 4, 1 / 8, 1 / 16, + 8 / 3, 4 / 3, 2 / 3, 1 / 3, 1 / 6, 1 / 12, 1 / 24, // triplet + 6, 3, 3 / 2, 3 / 4, 3 / 8, 3 / 16, 3 / 32 // dotted +]; + +const MODULO_PER_NOTE = MULTIPLIERS.map((val) => Math.floor(val * 48 / 2)); +const TICK_INDEX = 7 * 2 - 1; // 1/64 triplet fastest note +const MAX_ENUMERATOR = 288; +let NOTES_IN_S = []; +let QUARTER_NOTE_S = 60 / inBPM.get(); +NOTES_IN_S = MULTIPLIERS.map((multiplier) => multiplier * QUARTER_NOTE_S); +let TICK_S = NOTES_IN_S[TICK_INDEX] / 2; + +outBPM.set(inBPM.get()); + +let resetTickCount = false; +let changeWhileRunning = false; +inBPM.onChange = updateBpm; + +let worker = null; +let isPlaying = false; +let currentNote = 0; +let nextNoteTime = null; +let tickCount = 0; +let workerRunning = false; +let waitForSchedule = false; +updateBpm(); + +function updateBpm() +{ + outBPM.set(inBPM.get()); + + if (workerRunning) + { + changeWhileRunning = true; + return; + } + QUARTER_NOTE_S = 60 / inBPM.get(); + NOTES_IN_S = MULTIPLIERS.map((multiplier) => multiplier * QUARTER_NOTE_S); + TICK_S = NOTES_IN_S[TICK_INDEX]; +} + +function nextNote() +{ + nextNoteTime += TICK_S; + tickCount = (tickCount + 1) % MAX_ENUMERATOR; +} + +function scheduleNote() +{ + if (waitForSchedule) + { // code block to swallow initial hickup when starting the sequencer + let compareValue = 8; + if (inBPM.get() > 140) compareValue = 12; + if (inBPM.get() > 160) compareValue = 20; + if (tickCount === compareValue) + { // half of highest value + resetTickCount = true; + waitForSchedule = false; + } + else + { + return; + } + } + + if (resetTickCount) + { + tickCount = 0; + resetTickCount = false; + } + for (let i = 0, len = MODULO_PER_NOTE.length; i < len; i += 1) + { + if (tickCount % MODULO_PER_NOTE[i] === 0) outTriggers[i].trigger(); + } +} +function startScheduling() +{ + if (changeWhileRunning) + { + QUARTER_NOTE_S = 60 / inBPM.get(); + NOTES_IN_S = MULTIPLIERS.map((multiplier) => multiplier * QUARTER_NOTE_S); + TICK_S = NOTES_IN_S[TICK_INDEX]; + changeWhileRunning = false; + } + while (nextNoteTime < audioCtx.currentTime + SCHEDULEAHEAD_IN_S) + { + scheduleNote(); + nextNote(); + } +} + +inStart.onTriggered = () => +{ + if (workerRunning) return; + + if (!worker) + { + const blob = new Blob([attachments.worker_js], { "type": "text/javascript" }); + const fileURL = URL.createObjectURL(blob); + + worker = new Worker(fileURL, { "name": "ClockSequencer with op-id: " + op.id }); + worker.addEventListener("message", (e) => + { + if (e.data === "tick") startScheduling(); + if (e.data === "stopped") workerRunning = false; + }, + false); + + nextNoteTime = audioCtx.currentTime; + /* dummy buffer source for time */ + const audioBuffer = audioCtx.createBufferSource(); + audioBuffer.start(0); + workerRunning = true; + tickCount = 0; + worker.postMessage("start"); + waitForSchedule = true; + outRunning.set(workerRunning); + } + + outStart.trigger(); +}; + +inStop.onTriggered = () => +{ + if (worker) + { + worker.postMessage("stop"); + worker.terminate(); + worker = null; + workerRunning = false; + outRunning.set(workerRunning); + } + + outStop.trigger(); +}; + +inReset.onTriggered = () => +{ + resetTickCount = true; + outReset.trigger(); +}; + +op.onDelete = () => +{ + if (!inStart.isLinked()) + { + if (worker) + { + worker.postMessage("stop"); + worker.terminate(); + worker = null; + workerRunning = false; + } + } +}; +inStart.onLinkChanged = () => +{ + if (!inStart.isLinked()) + { + if (worker) + { + worker.postMessage("stop"); + worker.terminate(); + worker = null; + workerRunning = false; + outRunning.set(workerRunning); + } + } +}; + + +}; + +Ops.WebAudio.ClockSequencer.prototype = new CABLES.Op(); +CABLES.OPS["7994c33f-d4ca-455b-af72-83dcbf5ae83f"]={f:Ops.WebAudio.ClockSequencer,objName:"Ops.WebAudio.ClockSequencer"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.ClockSequencerPattern +// +// ************************************************************** + +Ops.WebAudio.ClockSequencerPattern = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const STEPS = Array(32).fill().map((_, i) => 1 + i); + +const inTrigger = op.inTrigger("Clock Trigger Input"); +const inSequenceArray = op.inArray("Sequence Array"); +const inSteps = op.inDropDown("Steps", STEPS, "16"); +const inReset = op.inTriggerButton("Reset"); + +const outTrigger = op.outTrigger("Sequence Trigger Output"); +const outValue = op.outNumber("Sequenced Value"); +const outTickCount = op.outNumber("Current Step"); + +let updateParameters = false; +let arrayChanged = false; +let hasArray = false; + +let COUNT_MODULO = Number(inSteps.get()); +let tickCount = 0; +inSteps.onChange = () => +{ + if (inTrigger.isLinked()) + { + updateParameters = true; + return; + } + COUNT_MODULO = Number(inSteps.get()); +}; + +inSequenceArray.onChange = () => arrayChanged = true; +let resetCount = false; +inReset.onTriggered = () => resetCount = true; + +inTrigger.onTriggered = () => +{ + if (updateParameters) + { + COUNT_MODULO = Number(inSteps.get()); + updateParameters = false; + } + + if (resetCount) + { + tickCount = 0; + resetCount = false; + } + const arr = inSequenceArray.get(); + + if (arrayChanged) + { + if (!arr) + { + op.setUiError("noArr", "No array connected. Passing through clock.", 1); + hasArray = false; + } + else + { + op.setUiError("noArr", null); + hasArray = true; + } + arrayChanged = false; + } + + if (hasArray) + { + if (arr[tickCount]) + { + outTrigger.trigger(); + outValue.set(arr[tickCount]); + } + else + { + outValue.set(0); + } + } + else + { + outTrigger.trigger(); + } + outTickCount.set(tickCount); + tickCount = (tickCount + 1) % COUNT_MODULO; +}; + + +}; + +Ops.WebAudio.ClockSequencerPattern.prototype = new CABLES.Op(); +CABLES.OPS["3b9b9ff5-4c25-42e3-9897-262b11c9cb94"]={f:Ops.WebAudio.ClockSequencerPattern,objName:"Ops.WebAudio.ClockSequencerPattern"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.Convolver_v2 +// +// ************************************************************** + +Ops.WebAudio.Convolver_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +function clamp(val, min, max) +{ + return Math.min(Math.max(val, min), max); +} + +const MAX_DELAY_TIME_IN_SECONDS = 179.999; + +const cgl = op.patch.cgl; +const audioContext = CABLES.WEBAUDIO.createAudioContext(op); + +const audioIn = op.inObject("Audio In", null, "audioNode"); + +const impulseResponse = op.inUrl("Impulse Response"); +const normalize = op.inBool("Normalize", true); +const inConvolverGain = op.inFloatSlider("IR Gain", 0.7); +const inPreDelayMS = op.inFloat("Predelay (MS)", 0); + +const inDryWet = op.inFloatSlider("Dry/Wet", 0.5); +const inOutputGain = op.inFloatSlider("Output Gain", 1); + +const audioOut = op.outObject("Audio Out", null, "audioNode"); +const wetOut = op.outObject("Wet Out", null, "audioNode"); + +op.setPortGroup("IR Options", [impulseResponse, inConvolverGain, normalize, inPreDelayMS]); +op.setPortGroup("Output", [inDryWet, inOutputGain]); + +const convolver = audioContext.createConvolver(); +const convolverGain = audioContext.createGain(); +const predelayNode = audioContext.createDelay(MAX_DELAY_TIME_IN_SECONDS); +const dryNode = audioContext.createGain(); +const wetNode = audioContext.createGain(); +const inputNode = audioContext.createGain(); +const outputNode = audioContext.createGain(); + +wetNode.gain.value = parseFloat(inDryWet.get()); +dryNode.gain.value = 1.0 - parseFloat(inDryWet.get()); + +wetNode.connect(outputNode); +dryNode.connect(outputNode); +inputNode.connect(dryNode); + +inputNode.connect(predelayNode); +predelayNode.connect(convolverGain); +convolverGain.connect(convolver); +convolver.connect(wetNode); + +let oldAudioIn = null; +let myImpulseBuffer = null; +let impulseResponseLoaded = false; +let scheduleConnection = false; +let loadingId = null; + +impulseResponse.onChange = () => +{ + loadingId = cgl.patch.loading.start("IR convolver", ""); + const impulseUrl = impulseResponse.get(); + + const ajaxRequest = new XMLHttpRequest(); + + if (impulseUrl) + { + const url = op.patch.getFilePath(impulseUrl); + const ext = url.substr(url.lastIndexOf(".") + 1); + + if (ext === "wav") + { + op.setUiError("wavExt", "Even though impulse responses are .wav files most of the time, if you plan on using WebAudio in Safari, make sure you use a .wav file that is 16bit or use an .mp3 file instead.", 1); + } + else + { + op.setUiError("wavExt", null); + } + + impulseResponseLoaded = false; + ajaxRequest.open("GET", url, true); + ajaxRequest.responseType = "arraybuffer"; + ajaxRequest.onload = function () + { + const impulseData = ajaxRequest.response; + + audioContext.decodeAudioData(impulseData, function (buffer) + { + if (buffer.sampleRate != audioContext.sampleRate) + { + op.log("[impulse response] Sample rate of the impulse response does not match! Should be " + audioContext.sampleRate); + op.setUiError("wrongSampleRate", "Sample rate of the impulse response does not match! Should be " + audioContext.sampleRate, 2); + return; + } + else + { + op.setUiError("wrongSampleRate", null); + } + myImpulseBuffer = buffer; + convolver.buffer = myImpulseBuffer; + convolver.loop = false; + convolver.normalize = normalize.get(); + convolverGain.gain.value = inConvolverGain.get(); + + audioOut.set(null); + + try + { + if (audioIn.get()) + { + audioIn.get().connect(inputNode); + audioOut.set(outputNode); + wetOut.set(convolver); + } + else + { + scheduleConnection = true; + } + } + catch (e) + { + op.log("[audio in] Could not connect audio in to convolver" + e); + } + + op.log("[impulse response] Impulse Response (" + impulseUrl + ") loaded"); + + impulseResponseLoaded = true; + cgl.patch.loading.finished(loadingId); + op.setUiError("noIR", null); + }, function (e) + { + op.log("[impulse response] Error decoding audio data" + e.err); + impulseResponseLoaded = false; + cgl.patch.loading.finished(loadingId); + }); + }; + + ajaxRequest.send(); + } + else + { + impulseResponseLoaded = false; + op.setUiError("noIR", "No impulse response loaded. Original audio will be passed through the Audio Out output.", 1); + op.setUiError("wavExt", null); + + convolver.buffer = null; + audioOut.set(outputNode); + } +}; + +inConvolverGain.onChange = () => +{ + convolverGain.gain.linearRampToValueAtTime(Number(inConvolverGain.get()) || 0, audioContext.currentTime + 0.01); +}; + +inDryWet.onChange = () => +{ + wetNode.gain.linearRampToValueAtTime(Number(inDryWet.get()), audioContext.currentTime + 0.01); + dryNode.gain.linearRampToValueAtTime(1 - Number(inDryWet.get()), audioContext.currentTime + 0.01); +}; + +inOutputGain.onChange = () => +{ + outputNode.gain.linearRampToValueAtTime(inOutputGain.get(), audioContext.currentTime + 0.01); +}; + +inPreDelayMS.onChange = () => +{ + if (inPreDelayMS.get() < 0) op.setUiError("delayTime", "Pre-Delay should be between 0 ms and " + MAX_DELAY_TIME_IN_SECONDS * 1000 + " ms. Setting to 0.", 1); + else if (inPreDelayMS.get() > MAX_DELAY_TIME_IN_SECONDS * 1000) op.setUiError("delayTime", "Pre-Delay should be between 0 ms and " + MAX_DELAY_TIME_IN_SECONDS * 1000 + " ms. Setting to " + MAX_DELAY_TIME_IN_SECONDS * 1000 + ".", 1); + else op.setUiError("delayTime", null); + + const predelayMS = clamp(inPreDelayMS.get(), 0.0, MAX_DELAY_TIME_IN_SECONDS) / 1000; + predelayNode.delayTime.linearRampToValueAtTime(predelayMS, audioContext.currentTime + 0.05); +}; + +audioIn.onChange = function () +{ + if (audioIn.get()) + { + if (!audioIn.get().connect) + { + oldAudioIn = null; + return; + } + + op.log("[audio in] connected"); + + try + { + audioIn.get().connect(inputNode); + + oldAudioIn = audioIn.get(); + } + catch (e) + { + op.log("[audio in] Could not connect" + e); + } + + if (!impulseResponseLoaded) + { + op.setUiError("noIR", "No impulse response loaded. Original audio will be passed through the Audio Out output.", 1); + audioOut.set(outputNode); + } + else + { + op.setUiError("noIR", null); + audioOut.set(outputNode); + wetOut.set(convolver); + } + } + else + { + if (impulseResponseLoaded) + { + op.setUiError("noIR", null); + } + + if (oldAudioIn) + { + oldAudioIn.disconnect(inputNode); + } + audioOut.set(null); + wetOut.set(null); + + oldAudioIn = null; + } +}; + +normalize.onChange = function () +{ + convolver.normalize = normalize.get(); +}; + +op.onDelete = () => +{ + wetNode.disconnect(); + dryNode.disconnect(); + inputNode.disconnect(); + predelayNode.disconnect(); + convolverGain.disconnect(); + convolver.disconnect(); +}; + + +}; + +Ops.WebAudio.Convolver_v2.prototype = new CABLES.Op(); +CABLES.OPS["63c619be-2256-4bbe-a83f-36b2bb6faa52"]={f:Ops.WebAudio.Convolver_v2,objName:"Ops.WebAudio.Convolver_v2"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.CutFilter +// +// ************************************************************** + +Ops.WebAudio.CutFilter = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +function clamp(val, min, max) +{ + return Math.min(Math.max(val, min), max); +} + +let audioContext = CABLES.WEBAUDIO.createAudioContext(op); + +// default values + min and max +const FREQUENCY_MIN = 10; +const FREQUENCY_MAX = audioContext.sampleRate / 2; // Nyquist frequency. +const Q_MIN = 0.0001; +const Q_MAX = 1000; +const GAIN_MIN = -40; +const GAIN_MAX = 40; +const SLOPES = [12, 24, 36, 48]; +const inAudio = op.inObject("Audio In", null, "audioNode"); + +const inLowActive = op.inBool("Highpass active ", true); +const inLowSlope = op.inSwitch("Highpass Slope (in dB)", SLOPES, 12); +const inLowFrequency = op.inFloat("Low Frequency", 250); +const inLowQ = op.inFloat("Low Q", 0.0001); +op.setPortGroup("Highpass / Lowcut", [inLowActive, inLowSlope, inLowFrequency, inLowQ]); + +const inHighActive = op.inBool("Lowpass active ", true); +const inHighSlope = op.inSwitch("Lowpass Slope (in dB)", SLOPES, 12); +const inHighFrequency = op.inFloat("High Frequency", 5000); +const inHighQ = op.inFloat("High Q", 0.0001); +op.setPortGroup("Lowpass / Highcut", [inHighActive, inHighSlope, inHighFrequency, inHighQ]); + +const lowFilterNodes = SLOPES.map(entry => audioContext.createBiquadFilter()); +const highFilterNodes = SLOPES.map(() => audioContext.createBiquadFilter()); + +/* instantiation */ +lowFilterNodes.forEach((node, index) => +{ + if (index === 0) node.type = "highpass"; + else node.type = "peaking"; + + const freq = inLowFrequency.get(); + node.frequency.setValueAtTime(clamp(freq, FREQUENCY_MIN, FREQUENCY_MAX), audioContext.currentTime); + node.gain.setValueAtTime(clamp(0, GAIN_MIN, GAIN_MAX), audioContext.currentTime); + node.Q.setValueAtTime(clamp(Number(inLowQ.get()), Q_MIN, Q_MAX), audioContext.currentTime); + + if (index < SLOPES.length - 1) node.connect(lowFilterNodes[index + 1]); + else node.connect(highFilterNodes[0]); +}); + +highFilterNodes.forEach((node, index) => +{ + if (index === 0) node.type = "lowpass"; + else node.type = "peaking"; + + const freq = inHighFrequency.get(); + node.frequency.setValueAtTime(clamp(freq, FREQUENCY_MIN, FREQUENCY_MAX), audioContext.currentTime); + node.gain.setValueAtTime(clamp(0, GAIN_MIN, GAIN_MAX), audioContext.currentTime); + node.Q.setValueAtTime(clamp(Number(inHighQ.get()), Q_MIN, Q_MAX), audioContext.currentTime); + + if (index < SLOPES.length - 1) node.connect(highFilterNodes[index + 1]); +}); + +/* onChange handlers */ + +let lastHighState = highFilterNodes.map(node => node.type); + +inHighActive.onChange = () => +{ + inHighSlope.setUiAttribs({ "greyout": !inHighActive.get() }); + inHighFrequency.setUiAttribs({ "greyout": !inHighActive.get() }); + inHighQ.setUiAttribs({ "greyout": !inHighActive.get() }); + + if (inHighActive.get()) + { + for (let i = 0; i < SLOPES.length; i += 1) + { + const node = highFilterNodes[i]; + node.type = lastHighState[i]; + } + } + else + { + lastHighState = highFilterNodes.map(node => node.type); + + for (let i = 0; i < SLOPES.length; i += 1) + { + const node = highFilterNodes[i]; + node.type = "peaking"; + } + } +}; + +let lastLowState = lowFilterNodes.map(node => node.type); + +inLowActive.onChange = () => +{ + inLowSlope.setUiAttribs({ "greyout": !inLowActive.get() }); + inLowFrequency.setUiAttribs({ "greyout": !inLowActive.get() }); + inLowQ.setUiAttribs({ "greyout": !inLowActive.get() }); + + if (inLowActive.get()) + { + for (let i = 0; i < SLOPES.length; i += 1) + { + const node = lowFilterNodes[i]; + node.type = lastLowState[i]; + } + } + else + { + lastLowState = lowFilterNodes.map(node => node.type); + + for (let i = 0; i < SLOPES.length; i += 1) + { + const node = lowFilterNodes[i]; + node.type = "peaking"; + } + } +}; + +inHighFrequency.onChange = () => +{ + if (inHighActive.get()) + { + const freq = inHighFrequency.get(); + + if (freq >= FREQUENCY_MIN && freq <= FREQUENCY_MAX) op.setUiError("freqRangeHigh", null); + + if (freq < FREQUENCY_MIN) + { + op.setUiError("freqRangeHigh", "The frequency you selected for the lowpass filter is lower than the possible frequency of " + FREQUENCY_MIN + " Hz.", 1); + } + else if (freq > FREQUENCY_MAX) + { + op.setUiError("freqRangeHigh", "The frequency you selected for the lowpass filter is higher than the possible frequency of " + FREQUENCY_MAX + " Hz.", 1); + } + + for (let i = 0; i < SLOPES.length; i += 1) + { + const node = highFilterNodes[i]; + node.frequency.setValueAtTime(clamp(freq, FREQUENCY_MIN, FREQUENCY_MAX), audioContext.currentTime); + } + } +}; + +inLowFrequency.onChange = () => +{ + if (inLowActive.get()) + { + const freq = inLowFrequency.get(); + + if (freq >= FREQUENCY_MIN && freq <= FREQUENCY_MAX) op.setUiError("freqRangeLow", null); + + if (freq < FREQUENCY_MIN) + { + op.setUiError("freqRangeLow", "The frequency you selected for the highpass filter is lower than the possible frequency of " + FREQUENCY_MIN + " Hz.", 1); + } + else if (freq > FREQUENCY_MAX) + { + op.setUiError("freqRangeLow", "The frequency you selected for the highpass filter is higher than the possible frequency of " + FREQUENCY_MAX + " Hz.", 1); + } + + for (let i = 0; i < SLOPES.length; i += 1) + { + const node = lowFilterNodes[i]; + node.frequency.setValueAtTime(clamp(freq, FREQUENCY_MIN, FREQUENCY_MAX), audioContext.currentTime); + } + } +}; + +inHighSlope.onChange = () => +{ + if (inHighActive.get()) + { + const cascadeAmount = SLOPES.indexOf(Number(inHighSlope.get())); + if (cascadeAmount < 0) return; + + for (let i = 0; i < SLOPES.length; i += 1) + { + const node = highFilterNodes[i]; + if (i <= cascadeAmount) node.type = "lowpass"; + else node.type = "peaking"; + } + } +}; + +inLowSlope.onChange = () => +{ + if (inLowActive.get()) + { + const cascadeAmount = SLOPES.indexOf(Number(inLowSlope.get())); + + if (cascadeAmount < 0) return; + + for (let i = 0; i < SLOPES.length; i += 1) + { + const node = lowFilterNodes[i]; + if (i <= cascadeAmount) node.type = "highpass"; + else node.type = "peaking"; + } + } +}; + +inHighQ.onChange = () => +{ + if (inHighActive.get()) + { + const q = inHighQ.get(); + + if (q < Q_MIN) op.setUiError("qRangeHigh", "Your Q value for the lowpass filter is below the minimum possible value of " + Q_MIN + ".", 1); + else if (q > Q_MAX) op.setUiError("qRangeHigh", "Your Q value for lowpass filter is above the maximum possible value of " + Q_MAX + ".", 1); + else op.setUiError("qRangeHigh", null); + + for (let i = 0; i < SLOPES.length; i += 1) + { + const node = highFilterNodes[i]; + node.Q.setValueAtTime(clamp(q, Q_MIN, Q_MAX), audioContext.currentTime); + } + } +}; + +inLowQ.onChange = () => +{ + if (inLowActive.get()) + { + const q = inLowQ.get(); + + if (q < Q_MIN) op.setUiError("qRangeLow", "Your Q value for the highpass filter is below the minimum possible value of " + Q_MIN + ".", 1); + else if (q > Q_MAX) op.setUiError("qRangeLow", "Your Q value for highpass filter is above the maximum possible value of " + Q_MAX + ".", 1); + else op.setUiError("qRangeLow", null); + + for (let i = 0; i < SLOPES.length; i += 1) + { + const node = lowFilterNodes[i]; + node.Q.setValueAtTime(clamp(q, Q_MIN, Q_MAX), audioContext.currentTime); + } + } +}; + +const outAudio = op.outObject("Audio Out", null, "audioNode"); + +let oldAudioIn = null; + +inAudio.onChange = function () +{ + if (!inAudio.get()) + { + if (oldAudioIn) + { + try + { + if (oldAudioIn.disconnect) + { + oldAudioIn.disconnect(lowFilterNodes[0]); + } + } + catch (e) + { + op.log(e); + } + } + outAudio.set(null); + } + else + { + if (inAudio.get().connect) inAudio.get().connect(lowFilterNodes[0]); + } + + oldAudioIn = inAudio.get(); + outAudio.set(highFilterNodes[SLOPES.length - 1]); +}; + +op.onDelete = () => +{ + lowFilterNodes.forEach((node, index) => + { + node.disconnect(); + }); + + highFilterNodes.forEach((node, index) => + { + if (index < SLOPES.length - 1) node.disconnect(); + }); +}; + + +}; + +Ops.WebAudio.CutFilter.prototype = new CABLES.Op(); +CABLES.OPS["de1f1d82-49b3-47e3-840e-2ab75ffc0045"]={f:Ops.WebAudio.CutFilter,objName:"Ops.WebAudio.CutFilter"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.Delay +// +// ************************************************************** + +Ops.WebAudio.Delay = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +function clamp(val, min, max) +{ + return Math.min(Math.max(val, min), max); +} + +const audioCtx = CABLES.WEBAUDIO.createAudioContext(op); +const NOTE_NAMES = []; +const MAX_DELAY_TIME = 179.999; + +for (let i = 0; i < 7 * 3; i += 1) +{ + const noteValue = Math.pow(2, i % 7); + let string = "1/" + noteValue; + if (i > 6 && i < 14) + { + string = "1/" + noteValue + " Triplet"; + } + else if (i > 13) + { + string = "1/" + noteValue + " Dotted"; + } + NOTE_NAMES.push(string + " Note"); +} + +const audioIn = op.inObject("Audio In", null, "audioNode"); +const inDryWet = op.inFloatSlider("Dry/Wet", 0.4); +const inFeedback = op.inFloatSlider("Feedback", 0.4); +const inDelayMS = op.inFloat("Delay Time (MS)", 100); +const inDelayShift = op.inFloat("Delay Shift (MS)", 0); +const inBpmSync = op.inBool("BPM based delay time", false); +const inBPM = op.inFloat("BPM", 120); +const inDelayNotes = op.inDropDown("Delay Time (note value) ", NOTE_NAMES, "1/8 Dotted Note"); +const inUseModulation = op.inBool("Use Filter & Modulation", false); +const inHighpassFrequency = op.inFloat("Highpass Frequency", 300); +const inHighpassQ = op.inFloat("Highpass Q", 2); +const inLowpassFrequency = op.inFloat("Lowpass Frequency", 9000); +const inLowpassQ = op.inFloat("Lowpass Q", 2); +const inLfoSpeed = op.inFloat("LFO Speed (Hz) ", 3.14); +const inLfoIntensity = op.inFloatSlider("LFO Intensity", 0.4); +const inLfoWave = op.inDropDown("LFO Waveform", ["sine", "triangle"], "sine"); +inLowpassFrequency.setUiAttribs({ "greyout": !inUseModulation.get() }); +inLowpassQ.setUiAttribs({ "greyout": !inUseModulation.get() }); +inHighpassFrequency.setUiAttribs({ "greyout": !inUseModulation.get() }); +inHighpassQ.setUiAttribs({ "greyout": !inUseModulation.get() }); +inLfoSpeed.setUiAttribs({ "greyout": !inUseModulation.get() }); +inLfoIntensity.setUiAttribs({ "greyout": !inUseModulation.get() }); +inLfoWave.setUiAttribs({ "greyout": !inUseModulation.get() }); +op.setPortGroup("Filters & Modulation", [inLowpassFrequency, inLowpassQ, inHighpassFrequency, inHighpassQ, inLfoSpeed, inLfoIntensity, inLfoWave]); + +const audioOut = op.outObject("Mix Out", null, "audioNode"); +const delayOut = op.outObject("Wet Out", null, "audioNode"); + +const MULTIPLIERS = [ + 4, 2, 1, 1 / 2, 1 / 4, 1 / 8, 1 / 16, + 8 / 3, 4 / 3, 2 / 3, 1 / 3, 1 / 6, 1 / 12, 1 / 24, + 6, 3, 3 / 2, 3 / 4, 3 / 8, 3 / 16, 3 / 32 // dotted +]; + +const MIN_BPM = 20; +let QUARTER_NOTE_S = 60 / Math.max(20, inBPM.get()); +let NOTES_IN_S = MULTIPLIERS.map((multiplier) => multiplier * QUARTER_NOTE_S); + +const calculateDelayTime = () => +{ + if (inBpmSync.get()) + { + const timeIndex = NOTE_NAMES.indexOf(inDelayNotes.get()); + + const timeValue = NOTES_IN_S[timeIndex] + (parseFloat(inDelayShift.get()) / 1000); + clamp(timeValue, 0, MAX_DELAY_TIME); + return timeValue; + } + + const unsyncedTime = (parseFloat(inDelayMS.get()) + parseFloat(inDelayShift.get())) / 1000.0; + + if (unsyncedTime < 0) op.setUiError("minDelayTime", "The delay time is lower than 0 ms. Setting to 0.", 1); + else op.setUiError("minDelayTime", null); + + return Math.max(0, unsyncedTime); +}; + +op.setPortGroup("Main Controls", [inDryWet, inFeedback, inDelayMS, inDelayShift]); +op.setPortGroup("Synced Controls", [inBPM, inDelayNotes]); + +inBPM.setUiAttribs({ "greyout": !inBpmSync.get() }); +inDelayNotes.setUiAttribs({ "greyout": !inBpmSync.get() }); +inDelayMS.setUiAttribs({ "greyout": inBpmSync.get() }); + +inBpmSync.onChange = () => +{ + inBPM.setUiAttribs({ "greyout": !inBpmSync.get() }); + inDelayNotes.setUiAttribs({ "greyout": !inBpmSync.get() }); + inDelayMS.setUiAttribs({ "greyout": inBpmSync.get() }); + + delayNode.delayTime.linearRampToValueAtTime(calculateDelayTime(), audioCtx.currentTime + 0.2); + + if (inBPM.get() < MIN_BPM) op.setUiError("minBPM", "The minimum BPM value is " + MIN_BPM + " BPM.", 1); + else op.setUiError("minBPM", null); +}; + +const inputNode = audioCtx.createGain(); // we create an input node so we can change the delay without requiring the input signal +const delayNode = audioCtx.createDelay(MAX_DELAY_TIME); +const dryNode = audioCtx.createGain(); +const wetNode = audioCtx.createGain(); + +const feedbackNode = audioCtx.createGain(); +const outputNode = audioCtx.createGain(); + +const filterHighpassNode = audioCtx.createBiquadFilter(); +const filterLowpassNode = audioCtx.createBiquadFilter(); +filterLowpassNode.type = "lowpass"; +filterLowpassNode.frequency.value = inLowpassFrequency.get(); +filterLowpassNode.Q.value = inLowpassQ.get(); + +filterHighpassNode.connect(filterLowpassNode); +filterHighpassNode.type = "highpass"; +filterHighpassNode.frequency.value = inHighpassFrequency.get(); +filterHighpassNode.Q.value = inHighpassQ.get(); + +const lfoNode = audioCtx.createOscillator(); +lfoNode.frequency.value = inLfoSpeed.get(); // Freq. in Hz +const lfoGainNode = audioCtx.createGain(); +lfoGainNode.gain.value = inLfoIntensity.get() / 800; +lfoNode.connect(lfoGainNode); +lfoNode.start(); + +delayNode.delayTime.value = calculateDelayTime(); +feedbackNode.gain.value = parseFloat(inFeedback.get()); +wetNode.gain.value = parseFloat(inDryWet.get()); +dryNode.gain.value = 1.0 - parseFloat(inDryWet.get()); + +delayNode.connect(feedbackNode); +feedbackNode.connect(delayNode); + +inputNode.connect(dryNode); +inputNode.connect(delayNode); + +dryNode.connect(outputNode); +delayNode.connect(wetNode); + +wetNode.connect(outputNode); + +inUseModulation.onChange = () => +{ + inLowpassFrequency.setUiAttribs({ "greyout": !inUseModulation.get() }); + inLowpassQ.setUiAttribs({ "greyout": !inUseModulation.get() }); + inHighpassFrequency.setUiAttribs({ "greyout": !inUseModulation.get() }); + inHighpassQ.setUiAttribs({ "greyout": !inUseModulation.get() }); + inLfoSpeed.setUiAttribs({ "greyout": !inUseModulation.get() }); + inLfoIntensity.setUiAttribs({ "greyout": !inUseModulation.get() }); + inLfoWave.setUiAttribs({ "greyout": !inUseModulation.get() }); + + if (inUseModulation.get()) + { + lfoGainNode.connect(delayNode.delayTime); + + inputNode.disconnect(delayNode); + + inputNode.connect(filterHighpassNode); + filterLowpassNode.connect(delayNode); + } + else + { + lfoGainNode.disconnect(delayNode.delayTime); + + inputNode.disconnect(filterHighpassNode); + filterLowpassNode.disconnect(delayNode); + + inputNode.connect(delayNode); + } +}; + +inLfoIntensity.onChange = () => +{ + lfoGainNode.gain.linearRampToValueAtTime(inLfoIntensity.get() / 800, audioCtx.currentTime + 0.1); +}; + +inLfoSpeed.onChange = () => +{ + lfoNode.frequency.linearRampToValueAtTime(inLfoSpeed.get(), audioCtx.currentTime + 0.1); +}; + +inLfoWave.onChange = () => +{ + lfoNode.type = inLfoWave.get(); +}; +inDelayMS.onChange = inDelayShift.onChange = inDelayNotes.onChange = () => +{ + if (inBPM.get() < MIN_BPM) op.setUiError("minBPM", "The minimum BPM value is " + MIN_BPM + " BPM.", 1); + else op.setUiError("minBPM", null); + + delayNode.delayTime.linearRampToValueAtTime(calculateDelayTime(), audioCtx.currentTime + 0.2); +}; + +inBPM.onChange = () => +{ + QUARTER_NOTE_S = 60 / Math.max(MIN_BPM, inBPM.get()); + NOTES_IN_S = MULTIPLIERS.map((multiplier) => multiplier * QUARTER_NOTE_S); + + delayNode.delayTime.linearRampToValueAtTime(calculateDelayTime(), audioCtx.currentTime + 0.1); + + if (inBPM.get() < MIN_BPM) op.setUiError("minBPM", "The minimum BPM value is " + MIN_BPM + " BPM.", 1); + else op.setUiError("minBPM", null); +}; + +inDryWet.onChange = () => +{ + wetNode.gain.linearRampToValueAtTime(Number(inDryWet.get()), audioCtx.currentTime + 0.01); + dryNode.gain.linearRampToValueAtTime((1 - Number(inDryWet.get())), audioCtx.currentTime + 0.01); +}; + +inFeedback.onChange = () => +{ + feedbackNode.gain.linearRampToValueAtTime(Number(inFeedback.get()), audioCtx.currentTime + 0.01); +}; + +const FREQUENCY_MIN = 10; +const FREQUENCY_MAX = audioCtx.sampleRate / 2; // Nyquist frequency. +const Q_MIN = 0.0001; +const Q_MAX = 1000; + +inHighpassFrequency.onChange = () => +{ + const freq = inHighpassFrequency.get(); + if (freq) + { + if (freq >= FREQUENCY_MIN && freq <= FREQUENCY_MAX) + { + filterHighpassNode.frequency.linearRampToValueAtTime(clamp(freq, FREQUENCY_MIN, FREQUENCY_MAX), audioContext.currentTime, +0.01); + op.setUiError("freqRangeHighpass", null); + } + if (freq < FREQUENCY_MIN) + { + op.setUiError("freqRangeHighpass", "The highpass frequency you selected is lower than the possible frequency of " + FREQUENCY_MIN + " Hz.", 1); + } + else if (freq > FREQUENCY_MAX) + { + op.setUiError("freqRangeHighpass", "The highpass frequency you selected is higher than the possible frequency of " + FREQUENCY_MAX + " Hz.", 1); + } + } +}; + +inHighpassQ.onChange = () => +{ + const q = inHighpassQ.get(); + filterHighpassNode.Q.linearRampToValueAtTime(clamp(q, Q_MIN, Q_MAX), audioContext.currentTime + 0.01); + + if (q < Q_MIN) op.setUiError("qRangeHighpass", "Your highpass Q value is below the minimum possible value of " + Q_MIN + ".", 1); + else if (q > Q_MAX) op.setUiError("qRangeHighpass", "Your highpass Q value is above the maximum possible value of " + Q_MAX + ".", 1); + else + { + op.setUiError("qRangeHighpass", null); + } +}; + +inLowpassFrequency.onChange = () => +{ + const freq = inLowpassFrequency.get(); + if (freq) + { + if (freq >= FREQUENCY_MIN && freq <= FREQUENCY_MAX) + { + filterLowpassNode.frequency.linearRampToValueAtTime(clamp(freq, FREQUENCY_MIN, FREQUENCY_MAX), audioContext.currentTime, +0.01); + op.setUiError("freqRangeLowpass", null); + } + if (freq < FREQUENCY_MIN) + { + op.setUiError("freqRangeLowpass", "The lowpass frequency you selected is lower than the possible frequency of " + FREQUENCY_MIN + " Hz.", 1); + } + else if (freq > FREQUENCY_MAX) + { + op.setUiError("freqRangeLowpass", "The lowpass frequency you selected is higher than the possible frequency of " + FREQUENCY_MAX + " Hz.", 1); + } + } +}; + +inLowpassQ.onChange = () => +{ + const q = inLowpassQ.get(); + filterLowpassNode.Q.linearRampToValueAtTime(clamp(q, Q_MIN, Q_MAX), audioContext.currentTime + 0.01); + + if (q < Q_MIN) op.setUiError("qRangeLowpass", "Your lowpass Q value is below the minimum possible value of " + Q_MIN + ".", 1); + else if (q > Q_MAX) op.setUiError("qRangeLowpass", "Your lowpass Q value is above the maximum possible value of " + Q_MAX + ".", 1); + else + { + op.setUiError("qRangeLowpass", null); + } +}; + +let oldAudioIn = null; +audioIn.onChange = function () +{ + if (!audioIn.get()) + { + if (oldAudioIn) + { + try + { + if (oldAudioIn.disconnect) + { + oldAudioIn.disconnect(inputNode); + } + } + catch (e) + { + op.log(e); + } + } + audioOut.set(null); + } + else + { + if (audioIn.get().connect) audioIn.get().connect(inputNode); + } + + oldAudioIn = audioIn.get(); + audioOut.set(outputNode); + delayOut.set(delayNode); +}; + +op.onDelete = () => +{ + lfoNode.disconnect(); + delayNode.disconnect(); + feedbackNode.disconnect(); + + inputNode.disconnect(); + + dryNode.disconnect(); + delayNode.disconnect(); + + wetNode.disconnect(); + filterHighpassNode.disconnect(); + + if (inUseModulation.get()) + { + lfoGainNode.disconnect(); + filterLowpassNode.disconnect(); + } +}; + + +}; + +Ops.WebAudio.Delay.prototype = new CABLES.Op(); +CABLES.OPS["60a557be-109a-494d-aba7-fcc61bbad033"]={f:Ops.WebAudio.Delay,objName:"Ops.WebAudio.Delay"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.FFTAreaAverage_v2 +// +// ************************************************************** + +Ops.WebAudio.FFTAreaAverage_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const cgl = op.patch.cgl; +const TEX_SIZES = [128, 256, 512, 1024, 2048]; +const + refresh = op.inTriggerButton("Refresh"), + fftArr = op.inArray("FFT Array"), + x = op.inValueSlider("X Position"), + y = op.inValueSlider("Y Position"), + w = op.inValueSlider("Width", 0.2), + h = op.inValueSlider("Height", 0.2), + drawTex = op.inValueBool("Create Texture", true), + inCanvasSize = op.inSwitch("Texture Size", TEX_SIZES, 128), + texOut = op.outTexture("Texture Out", null, "texture"), + value = op.outNumber("Area Average Volume"); + +op.setPortGroup("Area Settings", [x, y, w, h]); +op.setPortGroup("Texture Settings", [drawTex, inCanvasSize]); + +let updateTexture = false; +inCanvasSize.onChange = () => +{ + updateTexture = true; +}; +const data = []; +const line = 0; +let size = Number(inCanvasSize.get()); + +const canvas = document.createElement("canvas"); +canvas.id = "fft_" + CABLES.uuid(); +canvas.width = canvas.height = size; +canvas.style.display = "none"; +const body = document.getElementsByTagName("body")[0]; +body.appendChild(canvas); +const ctx = canvas.getContext("2d"); + +const MULTIPLIERS = [0.5, 1, 2, 4, 8]; +let multiplier = 1; + +let areaX = 0; +let areaY = 0; +let areaW = 20; +let areaH = 20; +let amount = 0; + +refresh.onTriggered = function () +{ + const arr = fftArr.get(); + if (!arr) + { + return; + } + + const width = arr.length; + + const draw = drawTex.get(); + + if (updateTexture) + { + size = Number(inCanvasSize.get()); + canvas.width = canvas.height = size; + + const indexOfSize = TEX_SIZES.indexOf(Number(inCanvasSize.get())); + multiplier = MULTIPLIERS[indexOfSize]; + + updateTexture = false; + } + + if (draw) + { + ctx.beginPath(); + ctx.fillStyle = "#000"; + ctx.strokeStyle = "#ff0"; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + ctx.fillStyle = "#888"; + for (let i = 0; i < arr.length; i++) + ctx.fillRect(i, size - arr[i] * multiplier, 1, arr[i] * multiplier); + } + + areaX = x.get() * canvas.width; + areaY = y.get() * canvas.height; + + areaW = w.get() * size / 2; + areaH = h.get() * size / 2; + + if (draw)ctx.rect(areaX, areaY, areaW, areaH); + if (draw) + { + ctx.lineWidth = 2 * multiplier; + ctx.stroke(); + } + + const val = 0; + let count = 0; + for (let xc = areaX; xc < areaX + areaW; xc++) + for (let yc = areaY; yc < areaY + areaH; yc++) + if (arr[Math.round(xc)] * multiplier > size - yc)count++; + + if (amount != amount)amount = 0; + amount += count / (areaW * areaH); + amount /= 2; + value.set(amount); + + if (draw) + { + ctx.fillStyle = "#ff0"; + ctx.fillRect(0, 0, amount * canvas.width, 6 * multiplier); + + if (texOut.get()) texOut.get().initTexture(canvas, CGL.Texture.FILTER_NEAREST); + else + { + texOut.set(new CGL.Texture.createFromImage(cgl, canvas, { "filter": CGL.Texture.FILTER_NEAREST })); + } + } +}; + + +}; + +Ops.WebAudio.FFTAreaAverage_v2.prototype = new CABLES.Op(); +CABLES.OPS["8dd14fde-57d1-408c-a3ef-441a65bfe53a"]={f:Ops.WebAudio.FFTAreaAverage_v2,objName:"Ops.WebAudio.FFTAreaAverage_v2"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.Gain +// +// ************************************************************** + +Ops.WebAudio.Gain = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const audioIn = op.inObject("audio in", null, "audioNode"); +const gain = op.inFloatSlider("gain", 1); +const inMute = op.inBool("Mute", false); +const audioOut = op.outObject("audio out", null, "audioNode"); + +const audioCtx = CABLES.WEBAUDIO.createAudioContext(op); +const gainNode = audioContext.createGain(); + +gain.onChange = () => +{ + if (inMute.get()) return; + + gainNode.gain.setValueAtTime(Number(gain.get()) || 0, audioCtx.currentTime); +}; + +inMute.onChange = () => +{ + if (inMute.get()) + { + gainNode.gain.linearRampToValueAtTime(0, audioCtx.currentTime + 0.01); + } + else + { + gainNode.gain.linearRampToValueAtTime(Number(gain.get()) || 0, audioCtx.currentTime + 0.01); + } +}; +let oldAudioIn = null; + +audioIn.onChange = function () +{ + if (!audioIn.get()) + { + if (oldAudioIn) + { + try + { + if (oldAudioIn.disconnect) oldAudioIn.disconnect(gainNode); + } + catch (e) + { + op.log(e); + } + } + audioOut.set(null); + } + else + { + if (audioIn.get().connect) audioIn.get().connect(gainNode); + } + oldAudioIn = audioIn.get(); + audioOut.set(gainNode); +}; + + +}; + +Ops.WebAudio.Gain.prototype = new CABLES.Op(); +CABLES.OPS["29402bba-48ee-4f28-94f0-bdc345e6bb67"]={f:Ops.WebAudio.Gain,objName:"Ops.WebAudio.Gain"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.KeyPiano +// +// ************************************************************** + +Ops.WebAudio.KeyPiano = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let c_on = this.addInPort(new CABLES.Port(this, "c note on", CABLES.OP_PORT_TYPE_FUNCTION)); +let c_off = this.addInPort(new CABLES.Port(this, "c note off", CABLES.OP_PORT_TYPE_FUNCTION)); +let cis_on = this.addInPort(new CABLES.Port(this, "cis note on", CABLES.OP_PORT_TYPE_FUNCTION)); +let cis_off = this.addInPort(new CABLES.Port(this, "cis note off", CABLES.OP_PORT_TYPE_FUNCTION)); +let d_on = this.addInPort(new CABLES.Port(this, "d note on", CABLES.OP_PORT_TYPE_FUNCTION)); +let d_off = this.addInPort(new CABLES.Port(this, "d note off", CABLES.OP_PORT_TYPE_FUNCTION)); +let dis_on = this.addInPort(new CABLES.Port(this, "dis note on", CABLES.OP_PORT_TYPE_FUNCTION)); +let dis_off = this.addInPort(new CABLES.Port(this, "dis note off", CABLES.OP_PORT_TYPE_FUNCTION)); +let e_on = this.addInPort(new CABLES.Port(this, "e note on", CABLES.OP_PORT_TYPE_FUNCTION)); +let e_off = this.addInPort(new CABLES.Port(this, "e note off", CABLES.OP_PORT_TYPE_FUNCTION)); +let f_on = this.addInPort(new CABLES.Port(this, "f note on", CABLES.OP_PORT_TYPE_FUNCTION)); +let f_off = this.addInPort(new CABLES.Port(this, "f note off", CABLES.OP_PORT_TYPE_FUNCTION)); +let fis_on = this.addInPort(new CABLES.Port(this, "fis note on", CABLES.OP_PORT_TYPE_FUNCTION)); +let fis_off = this.addInPort(new CABLES.Port(this, "fis note off", CABLES.OP_PORT_TYPE_FUNCTION)); +let g_on = this.addInPort(new CABLES.Port(this, "g note on", CABLES.OP_PORT_TYPE_FUNCTION)); +let g_off = this.addInPort(new CABLES.Port(this, "g note off", CABLES.OP_PORT_TYPE_FUNCTION)); +let gis_on = this.addInPort(new CABLES.Port(this, "gis note ons", CABLES.OP_PORT_TYPE_FUNCTION)); +let gis_off = this.addInPort(new CABLES.Port(this, "gis note off", CABLES.OP_PORT_TYPE_FUNCTION)); +let a_on = this.addInPort(new CABLES.Port(this, "a note on", CABLES.OP_PORT_TYPE_FUNCTION)); +let a_off = this.addInPort(new CABLES.Port(this, "a note off", CABLES.OP_PORT_TYPE_FUNCTION)); +let ais_on = this.addInPort(new CABLES.Port(this, "ais note on", CABLES.OP_PORT_TYPE_FUNCTION)); +let ais_off = this.addInPort(new CABLES.Port(this, "ais note off", CABLES.OP_PORT_TYPE_FUNCTION)); +let b_on = this.addInPort(new CABLES.Port(this, "b note on", CABLES.OP_PORT_TYPE_FUNCTION)); +let b_off = this.addInPort(new CABLES.Port(this, "b note off", CABLES.OP_PORT_TYPE_FUNCTION)); + +let frequency = this.addOutPort(new CABLES.Port(this, "frequency", CABLES.OP_PORT_TYPE_VALUE)); +let isPressed = this.addOutPort(new CABLES.Port(this, "is pressed", CABLES.OP_PORT_TYPE_VALUE)); + +let OCTAVE_MIN = 1; +let OCTAVE_MAX = 7; + +let toneFreqMap = []; + +for (let i = OCTAVE_MIN; i <= OCTAVE_MAX; i++) +{ + toneFreqMap[i] = {}; +} + +// octave 1 +toneFreqMap[1].c = 32.7032; +toneFreqMap[1].cis = 34.6478; +toneFreqMap[1].d = 36.7081; +toneFreqMap[1].dis = 38.8909; +toneFreqMap[1].e = 41.2034; +toneFreqMap[1].f = 43.6535; +toneFreqMap[1].fis = 46.2493; +toneFreqMap[1].g = 48.9994; +toneFreqMap[1].gis = 51.9131; +toneFreqMap[1].a = 55.0000; +toneFreqMap[1].ais = 58.2705; +toneFreqMap[1].b = 61.7354; +// octave 2 +toneFreqMap[2].c = 65.4064; +toneFreqMap[2].cis = 69.2957; +toneFreqMap[2].d = 73.4162; +toneFreqMap[2].dis = 77.7817; +toneFreqMap[2].e = 82.4069; +toneFreqMap[2].f = 87.3071; +toneFreqMap[2].fis = 92.4986; +toneFreqMap[2].g = 97.9989; +toneFreqMap[2].gis = 103.826; +toneFreqMap[2].a = 110.000; +toneFreqMap[2].ais = 116.541; +toneFreqMap[2].b = 123.471; +// octave 3 +toneFreqMap[3].c = 130.813; +toneFreqMap[3].cis = 138.591; +toneFreqMap[3].d = 146.832; +toneFreqMap[3].dis = 155.563; +toneFreqMap[3].e = 164.814; +toneFreqMap[3].f = 174.614; +toneFreqMap[3].fis = 184.997; +toneFreqMap[3].g = 195.998; +toneFreqMap[3].gis = 207.652; +toneFreqMap[3].a = 220.000; +toneFreqMap[3].ais = 233.082; +toneFreqMap[3].b = 246.942; +// octave 4 +toneFreqMap[4].c = 261.626; +toneFreqMap[4].cis = 277.183; +toneFreqMap[4].d = 293.665; +toneFreqMap[4].dis = 311.127; +toneFreqMap[4].e = 329.628; +toneFreqMap[4].f = 349.228; +toneFreqMap[4].fis = 369.994; +toneFreqMap[4].g = 391.995; +toneFreqMap[4].gis = 415.305; +toneFreqMap[4].a = 440.000; +toneFreqMap[4].ais = 466.164; +toneFreqMap[4].b = 493.883; +// octave 5 +toneFreqMap[5].c = 523.251; +toneFreqMap[5].cis = 554.365; +toneFreqMap[5].d = 587.330; +toneFreqMap[5].dis = 622.254; +toneFreqMap[5].e = 659.255; +toneFreqMap[5].f = 698.456; +toneFreqMap[5].fis = 739.989; +toneFreqMap[5].g = 783.991; +toneFreqMap[5].gis = 830.609; +toneFreqMap[5].a = 880.000; +toneFreqMap[5].ais = 932.328; +toneFreqMap[5].b = 987.767; +// octave 6 +toneFreqMap[6].c = 1046.50; +toneFreqMap[6].cis = 1108.73; +toneFreqMap[6].d = 1174.66; +toneFreqMap[6].dis = 1244.51; +toneFreqMap[6].e = 1318.51; +toneFreqMap[6].f = 1396.91; +toneFreqMap[6].fis = 1479.98; +toneFreqMap[6].g = 1567.98; +toneFreqMap[6].gis = 1661.22; +toneFreqMap[6].a = 1760.00; +toneFreqMap[6].ais = 1864.66; +toneFreqMap[6].b = 1975.53; +// octave 7 +toneFreqMap[7].c = 2093.00; +toneFreqMap[7].cis = 2217.46; +toneFreqMap[7].d = 2349.32; +toneFreqMap[7].dis = 2489.02; +toneFreqMap[7].e = 2637.02; +toneFreqMap[7].f = 2793.83; +toneFreqMap[7].fis = 2959.96; +toneFreqMap[7].g = 3135.96; +toneFreqMap[7].gis = 3322.44; +toneFreqMap[7].a = 3520.00; +toneFreqMap[7].ais = 3729.31; +toneFreqMap[7].b = 3951.07; + +function octaveInRange(oct) +{ + return oct >= OCTAVE_MIN && oct <= OCTAVE_MAX; +} + +function handleNoteOn(tone) +{ + let oct = parseInt(octave.get()); + if (octaveInRange(oct)) + { + let freq = (toneFreqMap[oct][tone]); + frequency.set(freq); + isPressed.set(1.0); + op.log("[note on] " + tone + oct + " (" + freq + "Hz)"); + } +} + +c_on.onTriggered = function () { handleNoteOn("c"); }; +cis_on.onTriggered = function () { handleNoteOn("cis"); }; +d_on.onTriggered = function () { handleNoteOn("d"); }; +dis_on.onTriggered = function () { handleNoteOn("dis"); }; +e_on.onTriggered = function () { handleNoteOn("e"); }; +f_on.onTriggered = function () { handleNoteOn("f"); }; +fis_on.onTriggered = function () { handleNoteOn("fis"); }; +g_on.onTriggered = function () { handleNoteOn("g"); }; +gis_on.onTriggered = function () { handleNoteOn("gis"); }; +a_on.onTriggered = function () { handleNoteOn("a"); }; +ais_on.onTriggered = function () { handleNoteOn("ais"); }; +b_on.onTriggered = function () { handleNoteOn("b"); }; + +function handleNoteOff(tone) +{ + let oct = parseInt(octave.get()); + if (octaveInRange(oct)) + { + let freq = (toneFreqMap[oct][tone]); + frequency.set(freq); + isPressed.set(0.0); + op.log("[note on] " + tone + oct + " (" + freq + "Hz)"); + } +} + +c_off.onTriggered = function () { handleNoteOff("c"); }; +cis_off.onTriggered = function () { handleNoteOff("cis"); }; +d_off.onTriggered = function () { handleNoteOff("d"); }; +dis_off.onTriggered = function () { handleNoteOff("dis"); }; +e_off.onTriggered = function () { handleNoteOff("e"); }; +f_off.onTriggered = function () { handleNoteOff("f"); }; +fis_off.onTriggered = function () { handleNoteOff("fis"); }; +g_off.onTriggered = function () { handleNoteOff("g"); }; +gis_off.onTriggered = function () { handleNoteOff("gis"); }; +a_off.onTriggered = function () { handleNoteOff("a"); }; +ais_off.onTriggered = function () { handleNoteOff("ais"); }; +b_off.onTriggered = function () { handleNoteOff("b"); }; + +let octave = this.addInPort(new CABLES.Port(this, "octave", CABLES.OP_PORT_TYPE_)); + +octave.set(4); +frequency.set(0); + + +}; + +Ops.WebAudio.KeyPiano.prototype = new CABLES.Op(); +CABLES.OPS["9f7d2411-ed87-45be-95a7-e6759d51582d"]={f:Ops.WebAudio.KeyPiano,objName:"Ops.WebAudio.KeyPiano"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.MicrophoneIn_v2 +// +// ************************************************************** + +Ops.WebAudio.MicrophoneIn_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const cgl = op.patch.cgl; + +let microphone = null; +const audioCtx = CABLES.WEBAUDIO.createAudioContext(op); + +const inInit = op.inTriggerButton("Start"); +const inInputDevices = op.inDropDown("Audio Input", ["None"]); +const inGain = op.inFloatSlider("Volume", 1); +const inMute = op.inBool("Mute", false); +const audioOut = op.outObject("Audio Out", null, "audioNode"); +const recording = op.outBool("Listening", false); +const outDevices = op.outArray("List of Input Devices"); + +op.setPortGroup("Volume Settings", [inGain, inMute]); +let audioInputsLoaded = false; +let loadingId = null; + +const gainNode = audioCtx.createGain(); + +function streamAudio(stream) +{ + microphone = audioCtx.createMediaStreamSource(stream); + microphone.connect(gainNode); + audioOut.set(gainNode); + op.log("[microphoneIn] streaming mic audio!", stream, microphone); + recording.set(true); +} + +inGain.onChange = () => +{ + if (inMute.get()) return; + gainNode.gain.setValueAtTime(Number(inGain.get()) || 0, audioCtx.currentTime); +}; + +inMute.onChange = () => +{ + if (inMute.get()) + { + gainNode.gain.setValueAtTime(0, audioCtx.currentTime); + } + else + { + gainNode.gain.setValueAtTime(Number(inGain.get()) || 0, audioCtx.currentTime); + } +}; + +inInit.onTriggered = function () +{ + if (!audioCtx) + { + op.log("[microphoneIn] no audiocontext!"); + return; + } + + if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) + { + op.log("[microphoneIn] new micro"); + + if (audioInputsLoaded) + { + op.setUiError("noAudioInputs", null); + + const device = inInputDevices.get(); + + if (device === "None") + { + op.setUiError("noDeviceSelected", "No audio device selected!", 1); + return; + } + else + { + op.setUiError("noDeviceSelected", null); + } + const constraints = { + "audio": { "deviceId": device }, + }; + + navigator.mediaDevices.getUserMedia(constraints) + .then((stream) => + { + microphone = audioCtx.createMediaStreamSource(stream); + microphone.connect(gainNode); + audioOut.set(gainNode); + op.log("streaming mic audio!", stream, microphone, gainNode); + recording.set(true); + op.setUiError("devicesLoaded", null); + }) + .catch((e) => + { + op.log("ERROR STREAMNG", e); + }); + } + else + { + op.setUiError("noAudioInputs", "There are no audio inputs to use the MicrophoneIn op with.", 2); + } + } + else + { + // old method + navigator.getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia || navigator.mozGetUserMedia); + + if (navigator.getUserMedia) + { + navigator.getUserMedia( + { "audio": true }, + streamAudio, + function (e) + { + op.log("[microphoneIn]No live audio input " + e); + recording.set(false); + } + ); + } + else + { + op.log("[op microphone] could not get usermedia"); + recording.set(false); + } + } +}; + +/* INIT FUNCTION */ +loadingId = cgl.patch.loading.start("MIC inputs", ""); +navigator.mediaDevices.getUserMedia({ "audio": true }) + .then((res) => + navigator.mediaDevices.enumerateDevices()) + .then((devices) => + { + const audioInputDevices = devices + .filter((device) => device.kind === "audioinput") + .map((deviceInfo, index) => deviceInfo.label || `microphone ${index + 1}`); + + inInputDevices.uiAttribs.values = audioInputDevices; + op.setUiError("devicesLoaded", "Input devices have been loaded. Please choose a device from the dropdown menu and click the \"Start\" button to activate the microphone input.", 0); + cgl.patch.loading.finished(loadingId); + audioInputsLoaded = true; + outDevices.set(null); + outDevices.set(audioInputDevices); + }) + .catch((e) => + { + op.log("error", e); + cgl.patch.loading.finished(loadingId); + audioInputsLoaded = false; + }); + + +}; + +Ops.WebAudio.MicrophoneIn_v2.prototype = new CABLES.Op(); +CABLES.OPS["cbfbbffd-a5a8-4b21-bcb5-5d031cc5e11a"]={f:Ops.WebAudio.MicrophoneIn_v2,objName:"Ops.WebAudio.MicrophoneIn_v2"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.MidiValueToFrequency +// +// ************************************************************** + +Ops.WebAudio.MidiValueToFrequency = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + midiValuePort = op.inValue("MIDI Value"), + tuningPort = op.inValue("Tuning", 440), + frequencyPort = op.outNumber("Frequency"); + +midiValuePort.onChange = + tuningPort.onChange = setFrequency; + +function setFrequency() +{ + let frequency = freq(tuningPort.get(), midiValuePort.get()); + frequencyPort.set(frequency); +} + +// Taken from danigb - https://github.com/danigb/midi-freq +function freq(tuning, midi) +{ + tuning = tuning || 440; + if (arguments.length > 1) return freq(tuning)(midi); + + return function (m) + { + return m === 0 || (m > 0 && m < 128) ? Math.pow(2, (m - 69) / 12) * tuning : null; + }; +} + + +}; + +Ops.WebAudio.MidiValueToFrequency.prototype = new CABLES.Op(); +CABLES.OPS["751c0067-e015-4f73-90b1-2d265b6e6d72"]={f:Ops.WebAudio.MidiValueToFrequency,objName:"Ops.WebAudio.MidiValueToFrequency"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.Mixer +// +// ************************************************************** + +Ops.WebAudio.Mixer = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +function clamp(val, min, max) +{ + return Math.min(Math.max(val, min), max); +} + +const audioCtx = CABLES.WEBAUDIO.createAudioContext(op); + +const inAudio0 = op.inObject("Audio In 0", null, "audioNode"); +const inAudio1 = op.inObject("Audio In 1", null, "audioNode"); +const inAudio2 = op.inObject("Audio In 2", null, "audioNode"); +const inAudio3 = op.inObject("Audio In 3", null, "audioNode"); +const inAudio4 = op.inObject("Audio In 4", null, "audioNode"); +const inAudio5 = op.inObject("Audio In 5", null, "audioNode"); +const inAudio6 = op.inObject("Audio In 6", null, "audioNode"); +const inAudio7 = op.inObject("Audio In 7", null, "audioNode"); + +const inAudio0Gain = op.inFloatSlider("In 0 Gain", 1); +const inAudio1Gain = op.inFloatSlider("In 1 Gain", 1); +const inAudio2Gain = op.inFloatSlider("In 2 Gain", 1); +const inAudio3Gain = op.inFloatSlider("In 3 Gain", 1); +const inAudio4Gain = op.inFloatSlider("In 4 Gain", 1); +const inAudio5Gain = op.inFloatSlider("In 5 Gain", 1); +const inAudio6Gain = op.inFloatSlider("In 6 Gain", 1); +const inAudio7Gain = op.inFloatSlider("In 7 Gain", 1); + +const inAudio0Pan = op.inFloat("In 0 Pan", 0); +const inAudio1Pan = op.inFloat("In 1 Pan", 0); +const inAudio2Pan = op.inFloat("In 2 Pan", 0); +const inAudio3Pan = op.inFloat("In 3 Pan", 0); +const inAudio4Pan = op.inFloat("In 4 Pan", 0); +const inAudio5Pan = op.inFloat("In 5 Pan", 0); +const inAudio6Pan = op.inFloat("In 6 Pan", 0); +const inAudio7Pan = op.inFloat("In 7 Pan", 0); + +const inMasterGain = op.inFloatSlider("Output Gain", 1); + +let isIOS = false; +let panNode = null; + +let createPanner = () => {}; +if (audioCtx.createStereoPanner) +{ + isIOS = false; +} +else +{ + isIOS = true; +} + +const audioOut = op.outObject("Audio Out", null, "audioNode"); + +const gain = audioCtx.createGain(); +audioOut.set(gain); + +const N_PORTS = 8; + +const audioIns = [inAudio0, inAudio1, inAudio2, inAudio3, inAudio4, inAudio5, inAudio6, inAudio7]; +const audioInGains = [inAudio0Gain, inAudio1Gain, inAudio2Gain, inAudio3Gain, inAudio4Gain, inAudio5Gain, inAudio6Gain, inAudio7Gain]; +const audioInPans = [inAudio0Pan, inAudio1Pan, inAudio2Pan, inAudio3Pan, inAudio4Pan, inAudio5Pan, inAudio6Pan, inAudio7Pan]; +op.setPortGroup("Audio Inputs", audioIns); +op.setPortGroup("Input", audioInGains); +op.setPortGroup("Panning", audioInPans); +op.setPortGroup("Output ", [inMasterGain]); +const oldAudioIns = audioIns.map(() => ({ "node": null, "isConnected": false })); + +audioInGains.forEach((port, index) => +{ + port.gainNode = audioCtx.createGain(); + port.onChange = () => port.gainNode.gain.linearRampToValueAtTime((audioInGains[index].get() || 0), audioCtx.currentTime + 0.01); +}); + +audioInPans.forEach((port, index) => +{ + if (isIOS) + { + port.panNode = audioCtx.createPanner(); + port.panNode.panningModel = "equalpower"; + } + else + { + port.panNode = audioCtx.createStereoPanner(); + } + + port.panNode.connect(audioInGains[index].gainNode); + + port.onChange = () => + { + const panning = clamp(audioInPans[index].get(), -1, 1); + if (!isIOS) port.panNode.pan.linearRampToValueAtTime(panning, audioCtx.currentTime + 0.01); + else port.panNode.setPosition(panning, 0, 1 - Math.abs(panning)); + }; +}); + +audioIns.forEach((port, index) => +{ + port.onChange = () => + { + const audioNode = audioIns[index].get(); + try + { + if (audioNode) + { + if (audioNode.connect) + { + const bufferedNode = oldAudioIns[index]; + bufferedNode.node = audioNode; + const gainNodePort = audioInGains[index].gainNode; + const panNodePort = audioInPans[index].panNode; + + if (!bufferedNode.isConnected) + { + bufferedNode.node.connect(panNodePort); + gainNodePort.connect(gain); + bufferedNode.isConnected = true; + } + } + } + else + { + const bufferedNode = oldAudioIns[index]; + const gainNodePort = audioInGains[index].gainNode; + const panNodePort = audioInPans[index].panNode; + + if (bufferedNode.isConnected) + { + bufferedNode.node.disconnect(panNodePort); + gainNodePort.disconnect(gain); + bufferedNode.isConnected = false; + } + } + } + catch (e) + { + op.log(e); + } + }; + + port.audioInPortNr = index; +}); + +inMasterGain.onChange = () => gain.gain.linearRampToValueAtTime((inMasterGain.get() || 0), audioCtx.currentTime + 0.01); + +op.onDelete = () => +{ + for (let i = 0; i < audioInPans.length; i += 1) + { + audioInPans[i].panNode.disconnect(); + } +}; + + +}; + +Ops.WebAudio.Mixer.prototype = new CABLES.Op(); +CABLES.OPS["363980dc-39b8-4690-8b8d-bff954f65d49"]={f:Ops.WebAudio.Mixer,objName:"Ops.WebAudio.Mixer"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.MusicalScales +// +// ************************************************************** + +Ops.WebAudio.MusicalScales = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +function clamp(val, min, max) +{ + return Math.min(Math.max(val, min), max); +} + +// constants +const NOTE_NUMBERS = [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; + +const BASE_TONES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]; +const BASE_TONE_DEFAULT = "C"; +const SCALE_TYPE_DEFAULT = "Minor"; +const APPEND_OCTAVE_DEFAULT = true; +const OCTAVE_DEFAULT = 4; +const OCTAVE_MIN = -1; +const OCTAVE_MAX = 9; +const INCLUDE_HIGH_BASE_TONE_DEFAULT = false; + +// scale types taken from: https://github.com/stagas/scales/blob/master/index.js +const SCALE_TYPES = { + "Major": [0, 2, 4, 5, 7, 9, 11], + "Minor": [0, 2, 3, 5, 7, 8, 10], + "Ionian": [0, 2, 4, 5, 7, 9, 11], + "Aeolian": [0, 2, 3, 5, 7, 8, 10], + "Dorian": [0, 2, 3, 5, 7, 9, 10], + "Mixolydian": [0, 2, 4, 5, 7, 9, 10], + "Lydian": [0, 2, 4, 6, 7, 9, 11], + "Phrygian": [0, 1, 3, 5, 7, 8, 10], + "Locrian": [0, 1, 3, 5, 6, 8, 10], + "Diminished": [0, 1, 3, 4, 6, 7, 9, 10], + "Whole Half": [0, 2, 3, 5, 6, 8, 9, 11], + "Whole Tone": [0, 2, 4, 6, 8, 10], + "Minor Blues": [0, 3, 5, 6, 7, 10], + "Minor Pentatonic": [0, 3, 5, 7, 10], + "Major Pentatonic": [0, 2, 4, 7, 9], + "Harmonic Minor": [0, 2, 3, 5, 7, 8, 11], + "Melodic Minor": [0, 2, 3, 5, 7, 9, 11], + "Super Locrian": [0, 1, 3, 4, 6, 8, 10], + "Bhairav": [0, 1, 4, 5, 7, 8, 11], + "Hungarian Minor": [0, 2, 3, 6, 7, 8, 11], + "Minor Gypsy": [0, 1, 4, 5, 7, 8, 10], + "Hirojoshi": [0, 2, 3, 7, 8], + "In Sen": [0, 1, 5, 7, 10], + "Iwato": [0, 1, 5, 6, 10], + "Kumoi": [0, 2, 3, 7, 9], + "Pelog": [0, 1, 3, 4, 7, 8], + "Spanish": [0, 1, 3, 4, 5, 6, 8, 10], + "Ion Aeol": [0, 2, 3, 4, 5, 7, 8, 9, 10, 11] +}; + +// input +const baseTonePort = op.inDropDown("Root Note", BASE_TONES, BASE_TONE_DEFAULT); +const scaleTypePort = op.inDropDown("Scale Type", Object.keys(SCALE_TYPES), SCALE_TYPE_DEFAULT); +const includeHighBaseTonePort = op.inBool("Include Upper Root Note", INCLUDE_HIGH_BASE_TONE_DEFAULT); +const octavePort = op.inInt("Octave", OCTAVE_DEFAULT); +const appendOctavePort = op.inBool("Append Octave To Names", APPEND_OCTAVE_DEFAULT); + +op.setPortGroup("Scale Settings", [baseTonePort, scaleTypePort, includeHighBaseTonePort, octavePort, appendOctavePort]); + +// output +const outNoteNames = op.outArray("Note Names Array"); +const outNoteSteps = op.outArray("Note Step Number Array"); +const outMidiNotes = op.outArray("Midi Note Array"); +const outCurrentScale = op.outString("Current Scale"); +// change listeners +baseTonePort.onChange = scaleTypePort.onChange = octavePort.onChange += appendOctavePort.onChange = includeHighBaseTonePort.onChange = setOutput; + +// functions +function getToneAt(index, offset) +{ + let i = index + offset; + if (i >= BASE_TONES.length) + { + i -= BASE_TONES.length; + } + return BASE_TONES[i]; +} + +function getToneIndex(tone) +{ + for (let i = 0; i < BASE_TONES.length; i++) + { + if (BASE_TONES[i] === tone) + { + return i; + } + } + return -1; +} + +function setOutput() +{ + const baseTone = baseTonePort.get(); + const baseToneIndex = getToneIndex(baseTone); + const scaleType = scaleTypePort.get(); + + if (SCALE_TYPES.hasOwnProperty(scaleType) && BASE_TONES.indexOf(baseTone) > -1) + { + const scale = SCALE_TYPES[scaleType]; + const noteNamesArray = []; + const noteStepsArray = []; + const appendOctave = appendOctavePort.get(); + let octave = octavePort.get(); + + if (octave > OCTAVE_MAX) op.setUiError("octave", "Octave value higher than " + OCTAVE_MAX + ". Setting to " + OCTAVE_MAX + ". Highest midi note is 127.", 1); + else if (octave < OCTAVE_MIN) op.setUiError("octave", "Octave value lower than " + OCTAVE_MIN + ". Setting to " + OCTAVE_MIN + ". Lowest midi note is 0.", 1); + else op.setUiError("octave", null); + + octave = clamp(Math.round(octave), OCTAVE_MIN, OCTAVE_MAX); + + for (let i = 0; i < scale.length; i++) + { + noteNamesArray.push(getToneAt(scale[i], baseToneIndex) + (appendOctave ? octave : "")); + noteStepsArray.push(scale[i]); + } + + // append the base tone in the next octave + if (includeHighBaseTonePort.get()) + { + noteStepsArray.push(scale[0] + 12); + noteNamesArray.push(getToneAt(scale[0], baseToneIndex) + (appendOctave ? octave + 1 : "")); + } + + const midiNotes = NOTE_NUMBERS + .filter((nr) => noteStepsArray.includes(nr - 12)) // only get scale notes + .map((nr) => nr + BASE_TONES.indexOf(baseTone) + 12 * octave) // map to midi note number + .filter((midiNote) => midiNote <= 127); // only use values <= 127 (highest possible midi note) + + outNoteNames.set(null); + outNoteNames.set(noteNamesArray); + + outNoteSteps.set(null); + outNoteSteps.set(noteStepsArray); + + outMidiNotes.set(null); + outMidiNotes.set(midiNotes); + + outCurrentScale.set(scaleTypePort.get()); + } +} + +setOutput(); + + +}; + +Ops.WebAudio.MusicalScales.prototype = new CABLES.Op(); +CABLES.OPS["9e8c08d9-8c9a-4cff-8e5b-05c72d1f8522"]={f:Ops.WebAudio.MusicalScales,objName:"Ops.WebAudio.MusicalScales"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.Output_v2 +// +// ************************************************************** + +Ops.WebAudio.Output_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inAudio = op.inObject("Audio In", null, "audioNode"), + inGain = op.inFloatSlider("Volume", 1), + inMute = op.inBool("Mute", false), + inShowSusp = op.inBool("Show Audio Suspended Button", true), + outVol = op.outNumber("Current Volume", 0), + outState = op.outString("Context State", "unknown"); + +op.setPortGroup("Volume Settings", [inMute, inGain]); + +let isSuspended = false; +let audioCtx = CABLES.WEBAUDIO.createAudioContext(op); +let gainNode = audioCtx.createGain(); +const destinationNode = audioCtx.destination; +let oldAudioIn = null; +let connectedToOut = false; +// let fsElement = null; + +inMute.onChange = () => +{ + mute(inMute.get()); +}; + +inGain.onChange = setVolume; +op.onMasterVolumeChanged = setVolume; + +let pauseId = op.patch.on("pause", setVolume); +let resumeId = op.patch.on("resume", setVolume); + +audioCtx.addEventListener("statechange", updateStateError); +inShowSusp.onChange = updateAudioStateButton; + +updateStateError(); +updateAudioStateButton(); + +op.onDelete = () => +{ + if (gainNode) gainNode.disconnect(); + gainNode = null; + CABLES.interActionNeededButton.remove("audiosuspended"); + if (pauseId) op.patch.off(pauseId); + if (resumeId) op.patch.off(resumeId); +}; + +inAudio.onChange = function () +{ + if (!inAudio.get()) + { + if (oldAudioIn) + { + try + { + if (oldAudioIn.disconnect) + { + oldAudioIn.disconnect(gainNode); + } + } + catch (e) + { + op.logError(e); + } + } + + op.setUiError("multipleInputs", null); + + if (connectedToOut) + { + if (gainNode)gainNode.disconnect(destinationNode); + connectedToOut = false; + } + } + else + { + if (inAudio.links.length > 1) op.setUiError("multipleInputs", "You have connected multiple inputs. It is possible that you experience unexpected behaviour. Please use a Mixer op to connect multiple audio streams.", 1); + else op.setUiError("multipleInputs", null); + + if (inAudio.get().connect) inAudio.get().connect(gainNode); + } + + oldAudioIn = inAudio.get(); + + if (!connectedToOut) + { + if (gainNode)gainNode.connect(destinationNode); + connectedToOut = true; + } + + setVolume(); +}; + +function setVolume(fromMute) +{ + const masterVolume = op.patch.config.masterVolume || 0; + + let volume = inGain.get() * masterVolume; + + if (op.patch._paused || inMute.get()) volume = 0; + + let addTime = 0.05; + if (fromMute) addTime = 0.2; + + volume = CABLES.clamp(volume, 0, 1); + + if (!gainNode) + op.logError("gainNode undefined"); + + if (gainNode) gainNode.gain.linearRampToValueAtTime(volume, audioCtx.currentTime + addTime); + + outVol.set(volume); +} + +function mute(b) +{ + if (b) + { + if (audioCtx.state === "suspended") + { // make sure that when audio context is suspended node will also be muted + // this prevents the initial short sound burst being heard when context is suspended + // and started from user interaction + // also note, we have to cancle the already scheduled values as we have no influence over + // the order in which onchange handlers are executed + + if (gainNode) + { + gainNode.gain.cancelScheduledValues(audioCtx.currentTime); + gainNode.gain.value = 0; + gainNode.gain.setValueAtTime(0, audioCtx.currentTime); + } + + outVol.set(0); + + return; + } + } + + setVolume(true); +} + +function updateStateError() +{ + outState.set(audioCtx.state); + op.logVerbose("audioCtx.state change", audioCtx.state); + + if (audioCtx.state == "suspended") op.setUiError("ctxSusp", "Your Browser suspended audio context, use playButton op to play audio after a user interaction"); + else op.setUiError("ctxSusp", null); + + updateAudioStateButton(); +} + +function updateAudioStateButton() +{ + if (audioCtx.state == "suspended") + { + mute(true); + if (inShowSusp.get()) + { + isSuspended = true; + + CABLES.interActionNeededButton.add(op.patch, "audiosuspended", () => + { + if (audioCtx && audioCtx.state == "suspended") + { + audioCtx.resume(); + CABLES.interActionNeededButton.remove("audiosuspended"); + } + }); + } + else + { + CABLES.interActionNeededButton.remove("audiosuspended"); + } + } + else + { + CABLES.interActionNeededButton.remove("audiosuspended"); + + if (isSuspended) + { + op.log("was suspended - set vol"); + setVolume(true); + } + } +} + + +}; + +Ops.WebAudio.Output_v2.prototype = new CABLES.Op(); +CABLES.OPS["90b95403-b0c4-4980-ab3b-b6c354771c81"]={f:Ops.WebAudio.Output_v2,objName:"Ops.WebAudio.Output_v2"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.SamplePlayer +// +// ************************************************************** + +Ops.WebAudio.SamplePlayer = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +function clamp(value, min, max) +{ + return Math.min(Math.max(value, min), max); +} + +const audioCtx = CABLES.WEBAUDIO.createAudioContext(op); + +// input ports +const audioBufferPort = op.inObject("Audio Buffer", null, "audioBuffer"); +const inTrigger = op.inTriggerButton("Play Sample"); +const inTriggerStop = op.inTriggerButton("Stop Playback"); +const offsetPort = op.inValue("Offset", 0); +const maxSamples = op.inInt("Buffer Size", 32); +const playbackRatePort = op.inValue("Playback Rate", 1); +const detunePort = op.inValue("Detune", 0); + +op.setPortGroup("Time Controls", [offsetPort]); +op.setPortGroup("Miscellaneous", [playbackRatePort, detunePort]); +// output ports +const audioOutPort = op.outObject("Audio Out", null, "audioNode"); +const outPlaying = op.outBool("Is Playing", false); + +if (!audioBufferPort.isLinked()) +{ + op.setUiError("inputNotConnected", "To be able to play back sound, you need to connect an AudioBuffer to this op.", 0); +} +else +{ + op.setUiError("inputNotConnected", null); +} + +audioBufferPort.onLinkChanged = () => +{ + if (!audioBufferPort.isLinked()) + { + op.setUiError("inputNotConnected", "To be able to play back sound, you need to connect an AudioBuffer to this op.", 0); + } + else + { + op.setUiError("inputNotConnected", null); + } +}; + +if (!audioOutPort.isLinked()) +{ + op.setUiError("outputNotConnected", "To be able to hear sound playing, you need to connect this op to an Output op.", 0); +} +else +{ + op.setUiError("outputNotConnected", null); +} + +audioOutPort.onLinkChanged = () => +{ + if (!audioOutPort.isLinked()) + { + op.setUiError("outputNotConnected", "To be able to hear sound playing, you need to connect this op to an Output op.", 0); + } + else + { + op.setUiError("outputNotConnected", null); + } +}; + +// vars +let isPlaying = false; + +const gainNode = audioCtx.createGain(); + +let sourceSize = maxSamples.get() || 32; +let SOURCES = new Array(sourceSize).fill(0).map(() => + ({ + "bufferSource": audioCtx.createBufferSource(), + "isPlaying": false, + "gainNode": audioCtx.createGain(), + "isGainNodeConnected": false + })); +let SOURCES_LENGTH = SOURCES.length; + +maxSamples.onChange = () => +{ + op.setUiError("maxSamples", null); + if (!maxSamples.get() || maxSamples.get < 1 || maxSamples.get() > 32) + { + op.setUiError("maxSamples", "Buffer Size needs to be a number (1-32)"); + } + sourceSize = maxSamples.get() || 32; + SOURCES = new Array(sourceSize).fill(0).map(() => + ({ + "bufferSource": audioCtx.createBufferSource(), + "isPlaying": false, + "gainNode": audioCtx.createGain(), + "isGainNodeConnected": false + })); + SOURCES_LENGTH = SOURCES.length; + currentSample = 0; + createAudioBufferSources(); +}; + +detunePort.onChange = playbackRatePort.onChange = () => +{ + op.setUiError("playbackRate", null); + if (playbackRatePort.get() < 0) + { + op.setUiError("playbackRate", "Playback Rate needs to be a positive number"); + } + try + { + SOURCES.forEach((src) => + { + /* playback rate */ + const playbackRate = clamp(playbackRatePort.get(), 0.01, 4); + if ( + playbackRate >= src.bufferSource.playbackRate.minValue + && playbackRate <= src.bufferSource.playbackRate.maxValue + ) + { + src.bufferSource.playbackRate.setValueAtTime( + playbackRate, + audioCtx.currentTime + 0.01 + ); + } + + /* detune */ + const detune = detunePort.get(); + if (src.bufferSource.detune) + { + src.bufferSource.detune.setValueAtTime( + detune, + audioCtx.currentTime + 0.01 + ); + } + }); + } + catch (e) + { + op.log("err in param change", e); + } +}; + +function createAudioBufferSources() +{ + const buffer = audioBufferPort.get(); + if (!buffer) return; + + for (let i = 0; i < SOURCES_LENGTH; i += 1) + { + const src = SOURCES[i]; + createSingleSource(src); + } + + audioOutPort.set(gainNode); +} + +function createSingleSource(src) +{ + const buffer = audioBufferPort.get(); + if (!buffer) return; + if (src.isPlaying) return; + + if (src.isGainNodeConnected) src.bufferSource.disconnect(src.gainNode); + + src.bufferSource = audioCtx.createBufferSource(); + + /* end callback */ + src.bufferSource.onended = () => + { + src.isPlaying = false; + outPlaying.set(SOURCES.some((src) => src.isPlaying === true)); + createSingleSource(src); + }; + + src.bufferSource.buffer = buffer; + src.bufferSource.loop = false; + + /* playback rate */ + const playbackRate = clamp(playbackRatePort.get(), 0.01, 4); + if ( + playbackRate >= src.bufferSource.playbackRate.minValue + && playbackRate <= src.bufferSource.playbackRate.maxValue + ) + { + src.bufferSource.playbackRate.setValueAtTime( + playbackRate, + audioCtx.currentTime + ); + } + + /* detune */ + const detune = detunePort.get(); + if (src.bufferSource.detune) + { + src.bufferSource.detune.setValueAtTime( + detune, + audioCtx.currentTime + ); + } + + src.bufferSource.connect(src.gainNode); + src.gainNode.gain.setValueAtTime(0, audioCtx.currentTime); + src.gainNode.connect(gainNode); + src.isGainNodeConnected = true; +} + +let currentSample = 0; +inTrigger.onTriggered = () => +{ + if (!maxSamples.get() || maxSamples.get < 1 || maxSamples.get() > 32) return; + if (playbackRatePort.get() < 0) return; + + if (!audioBufferPort.get() || !(audioBufferPort.get() instanceof AudioBuffer)) return; + try + { + const time = 0; + const offset = Number(offsetPort.get()); + + if (!SOURCES[currentSample].isPlaying) + { + SOURCES[currentSample].bufferSource.start(Math.max(0, time), Math.max(0, offset)); + SOURCES[currentSample].gainNode.gain.linearRampToValueAtTime(1.0, audioCtx.currentTime + 0.01); + SOURCES[currentSample].isPlaying = true; + outPlaying.set(true); + } + + currentSample += 1; + currentSample %= SOURCES_LENGTH; + } + catch (e) + { + op.setUiError(e); + op.log("Error: ", e); + outPlaying.set(false); + } +}; + +inTriggerStop.onTriggered = () => +{ + SOURCES.forEach((src, index) => + { + if (src.isPlaying && src.bufferSource) src.bufferSource.stop(); + src.isPlaying = false; + }); + outPlaying.set(false); +}; + +inTrigger.onLinkChanged = () => +{ + if (!inTrigger.isLinked()) + { + SOURCES.forEach((src, index) => + { + if (src.isPlaying && src.bufferSource) src.bufferSource.stop(); + src.isPlaying = false; + }); + outPlaying.set(false); + } +}; +// change listeners +audioBufferPort.onChange = function () +{ + if (audioBufferPort.get()) + { + if ((audioBufferPort.get() instanceof AudioBuffer)) + { + createAudioBufferSources(); + } + } + else + { + SOURCES.forEach((src) => + { + if (src.bufferSource && src.isGainNodeConnected) + { + src.bufferSource.disconnect(src.gainNode); + src.gainNode.disconnect(gainNode); + src.isGainNodeConnected = false; + } + src.bufferSource = null; + }); + + outPlaying.set(false); + } +}; + + +}; + +Ops.WebAudio.SamplePlayer.prototype = new CABLES.Op(); +CABLES.OPS["47796760-f211-47f5-9d6b-cc9cd6944897"]={f:Ops.WebAudio.SamplePlayer,objName:"Ops.WebAudio.SamplePlayer"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.TextToSpeech.Say_v2 +// +// ************************************************************** + +Ops.WebAudio.TextToSpeech.Say_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; + +// default / min /max values +let PITCH_DEFAULT = 1; +let PITCH_MIN = 0; +let PITCH_MAX = 2; +let RATE_DEFAULT = 1; +let RATE_MIN = 0.1; +let RATE_MAX = 10; +let VOLUME_DEFAULT = 1; +let VOLUME_MIN = 0; +let VOLUME_MAX = 1; + +// vars +let synth = window.speechSynthesis; +let voiceMap = getVoiceMap(synth.getVoices()); +let voiceMapKeys = Object.keys(voiceMap); + +// inputs +let updateStatePort = op.inTrigger("Update State"); +let textPort = op.inString("Text", "Wazzup"); +let triggerPort = op.inTriggerButton("Say"); +let voicePort = op.inDropDown("Voice", voiceMapKeys); +let pitchPort = op.inFloatSlider("Pitch", PITCH_DEFAULT, PITCH_MIN, PITCH_MAX); +let ratePort = op.inFloatSlider("Rate", RATE_DEFAULT, RATE_MIN, RATE_MAX); +let volumePort = op.inFloatSlider("Volume", VOLUME_DEFAULT, VOLUME_MIN, VOLUME_MAX); + +let sayOnTextChangePort = op.inBool("Say on Text Change", false); +let pausePort = op.inTriggerButton("Pause"); +let resumePort = op.inTriggerButton("Resume"); +let cancelPort = op.inTriggerButton("Cancel"); + +// outputs +let nextPort = op.outTrigger("Next"); +let speakingPort = op.outBoolNum("Speaking", false); +let pendingPort = op.outBoolNum("Pending", false); +let pausedPort = op.outBoolNum("Paused", false); + +// change listeners +updateStatePort.onTriggered = updateState; +triggerPort.onTriggered = say; +sayOnTextChangePort.onChange = function () +{ + if (sayOnTextChangePort.get()) + { + textPort.onChange = say; + } + else + { + textPort.onChange = function () {}; // don't do anything + } +}; +pausePort.onTriggered = function () +{ + synth.pause(); +}; +resumePort.onTriggered = function () +{ + synth.resume(); +}; +cancelPort.onTriggered = function () +{ + synth.cancel(); +}; + +// voices loaded callback (async) +window.speechSynthesis.onvoiceschanged = function () +{ + voiceMap = getVoiceMap(synth.getVoices()); + voiceMapKeys = Object.keys(voiceMap); + if (CABLES.UI) + { + voicePort.uiAttribs.values = voiceMapKeys; // update dropdown values + op.refreshParams(); // update visible dropdown menu + } +}; + +/** + * Updates the state output ports + */ +function updateState() +{ + speakingPort.set(synth.speaking); + pendingPort.set(synth.pending); + pausedPort.set(synth.paused); + nextPort.trigger(); +} + +/** + * says the text from text-port using voice voice + */ +function say() +{ + let text = textPort.get(); + let voice; + let voiceDisplayName = voicePort.get(); + if (voiceDisplayName && voiceMap.hasOwnProperty(voiceDisplayName)) + { // voices are loaded async, at start it may not be there + voice = voiceMap[voiceDisplayName]; + } + let utterance = new SpeechSynthesisUtterance(text); + if (voice) + { + utterance.voice = voice; + } + let pitch = pitchPort.get(); + if (pitch < PITCH_MIN) { pitch = PITCH_MIN; } + else if (pitch > PITCH_MAX) { pitch = PITCH_MAX; } + utterance.pitch = pitch; + let rate = ratePort.get(); + if (rate < RATE_MIN) { rate = RATE_MIN; } + else if (rate > RATE_MAX) { rate = RATE_MAX; } + utterance.rate = rate; + let volume = volumePort.get(); + if (volume < VOLUME_MIN) { volume = VOLUME_MIN; } + else if (volume > VOLUME_MAX) { volume = VOLUME_MAX; } + utterance.volume = volume; + synth.speak(utterance); +} + +/** + * Returns a map of voices + * e.g. { "Alex (de-DE)": { voice object }, ...} + */ +function getVoiceMap(voices) +{ + let ret = {}; + if (!voices || voices.length === 0) { return ret; } + + voices.forEach(function (voice) + { + let key = voice.name + " (" + voice.lang + ")"; + ret[key] = voice; + }); + return ret; +} + + +}; + +Ops.WebAudio.TextToSpeech.Say_v2.prototype = new CABLES.Op(); +CABLES.OPS["eb71ad36-9756-449b-89e6-54bf5c944d81"]={f:Ops.WebAudio.TextToSpeech.Say_v2,objName:"Ops.WebAudio.TextToSpeech.Say_v2"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.ThreeBandEqualizer +// +// ************************************************************** + +Ops.WebAudio.ThreeBandEqualizer = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +function clamp(val, min, max) +{ + return Math.min(Math.max(val, min), max); +} + +let audioContext = CABLES.WEBAUDIO.createAudioContext(op); + +// default values + min and max +const FREQUENCY_MIN = 10; +const FREQUENCY_MAX = audioContext.sampleRate / 2; // Nyquist frequency. +const Q_MIN = 0.0001; +const Q_MAX = 1000; +const GAIN_MIN = -40; +const GAIN_MAX = 40; + +const inAudio = op.inObject("Audio In", null, "audioNode"); + +const inLowFilterType = op.inDropDown("Low Filter Type", ["peaking", "lowshelf"], "lowshelf"); +const inLowFrequency = op.inFloat("Low Frequency", 250); +const inLowQ = op.inFloat("Low Q", 0.0001); +const inLowGain = op.inFloat("Low Gain", 0); +op.setPortGroup("Low", [inLowFilterType, inLowFrequency, inLowQ, inLowGain]); + +const inMidFilterType = op.inDropDown("Mid Filter Type", ["peaking", "notch"], "peaking"); +const inMidFrequency = op.inFloat("Mid Frequency", 1000); +const inMidQ = op.inFloat("Mid Q", 0.0001); +const inMidGain = op.inFloat("Mid Gain", 0); +op.setPortGroup("Mid", [inMidFilterType, inMidFrequency, inMidQ, inMidGain]); + +const inHighFilterType = op.inDropDown("High Filter Type", ["peaking", "highshelf"], "highshelf"); +const inHighFrequency = op.inFloat("High Frequency", 5000); +const inHighQ = op.inFloat("High Q", 0.0001); +const inHighGain = op.inFloat("High Gain", 0); +op.setPortGroup("High", [inHighFilterType, inHighFrequency, inHighQ, inHighGain]); + +const lowFilterNode = audioContext.createBiquadFilter(); +const midFilterNode = audioContext.createBiquadFilter(); +const highFilterNode = audioContext.createBiquadFilter(); +lowFilterNode.connect(midFilterNode); +midFilterNode.connect(highFilterNode); + +lowFilterNode.type = inLowFilterType.get(); +midFilterNode.type = inMidFilterType.get(); +highFilterNode.type = inHighFilterType.get(); +const FILTER_TYPES = [ + { "node": lowFilterNode, "port": inLowFilterType }, + { "node": midFilterNode, "port": inMidFilterType }, + { "node": highFilterNode, "port": inHighFilterType } +]; + +const FILTER_FREQUENCIES = [ + { "node": lowFilterNode, "port": inLowFrequency, "name": "low" }, + { "node": midFilterNode, "port": inMidFrequency, "name": "mid" }, + { "node": highFilterNode, "port": inHighFrequency, "name": "high" } +]; + +const FILTER_QS = [ + { "node": lowFilterNode, "port": inLowQ, "name": "low" }, + { "node": midFilterNode, "port": inMidQ, "name": "mid" }, + { "node": highFilterNode, "port": inHighQ, "name": "high" } +]; + +const FILTER_GAINS = [ + { "node": lowFilterNode, "port": inLowGain, "name": "low" }, + { "node": midFilterNode, "port": inMidGain, "name": "mid" }, + { "node": highFilterNode, "port": inHighGain, "name": "high" } +]; + +FILTER_TYPES.forEach((obj, index) => +{ + /* initial greyout-ing */ + const type = obj.port.get(); + + FILTER_GAINS[index].port.setUiAttribs({ + "greyout": ["lowpass", "highpass", "bandpass", "notch", "allpass"].includes(type) + }); + + FILTER_QS[index].port.setUiAttribs({ + "greyout": ["lowshelf", "highshelf"].includes(type) + }); + + /* onChange handler */ + obj.port.onChange = () => + { + const type = obj.port.get(); + FILTER_GAINS[index].port.setUiAttribs({ + "greyout": ["lowpass", "highpass", "bandpass", "notch", "allpass"].includes(type) + }); + + FILTER_QS[index].port.setUiAttribs({ + "greyout": ["lowshelf", "highshelf"].includes(type) + }); + + obj.node.type = type; + }; +}); + +FILTER_FREQUENCIES.forEach((obj, index) => +{ + obj.port.onChange = () => + { + const freq = obj.port.get(); + if (freq) + { + if (freq >= FREQUENCY_MIN && freq <= FREQUENCY_MAX) + { + obj.node.frequency.setValueAtTime(clamp(freq, FREQUENCY_MIN, FREQUENCY_MAX), audioContext.currentTime); + op.setUiError("freqRange", null); + } + if (freq < FREQUENCY_MIN) + { + op.setUiError("freqRange", "The frequency you selected for the " + obj.name + " band is lower than the possible frequency of " + FREQUENCY_MIN + " Hz.", 1); + } + else if (freq > FREQUENCY_MAX) + { + op.setUiError("freqRange", "The frequency you selected for the " + obj.name + " band is higher than the possible frequency of " + FREQUENCY_MAX + " Hz.", 1); + } + } + }; +}); + +FILTER_QS.forEach((obj, index) => +{ + obj.port.onChange = () => + { + const q = obj.port.get(); + obj.node.Q.setValueAtTime(clamp(q, Q_MIN, Q_MAX), audioContext.currentTime); + + if (q < Q_MIN) op.setUiError(obj.name + "_qRange", "Your Q value for the " + obj.name + " band is below the minimum possible value of " + Q_MIN + ".", 1); + else if (q > Q_MAX) op.setUiError(obj.name + "_qRange", "Your Q value for the " + obj.name + " band is above the maximum possible value of " + Q_MAX + ".", 1); + else + { + op.setUiError(obj.name + "_qRange", null); + } + }; +}); + +FILTER_GAINS.forEach((obj, index) => +{ + obj.port.onChange = () => + { + const gain = obj.port.get(); + + obj.node.gain.setValueAtTime(clamp(gain, GAIN_MIN, GAIN_MAX), audioContext.currentTime); + + if (gain < GAIN_MIN) op.setUiError(obj.name + "GainRange", "Your gain value for the " + obj.name + " band is below the minimum possible value of " + GAIN_MIN + " dB.", 1); + else if (gain > GAIN_MAX) op.setUiError(obj.name + "GainRange", "Your gain value for the " + obj.name + " band is above the maximum possible value of " + GAIN_MAX + " dB.", 1); + else + { + op.setUiError(obj.name + "GainRange", null); + } + }; +}); + +const outAudio = op.outObject("Audio Out", null, "audioNode"); + +let oldAudioIn = null; + +inAudio.onChange = function () +{ + if (!inAudio.get()) + { + if (oldAudioIn) + { + try + { + if (oldAudioIn.disconnect) + { + oldAudioIn.disconnect(lowFilterNode); + } + } + catch (e) + { + op.log(e); + } + } + outAudio.set(null); + } + else + { + if (inAudio.get().connect) inAudio.get().connect(lowFilterNode); + } + oldAudioIn = inAudio.get(); + outAudio.set(highFilterNode); +}; + +op.onDelete = () => +{ + lowFilterNode.disconnect(); + midFilterNode.disconnect(); +}; + + +}; + +Ops.WebAudio.ThreeBandEqualizer.prototype = new CABLES.Op(); +CABLES.OPS["eb875ed3-335b-4709-82ab-3d6514ae2ae6"]={f:Ops.WebAudio.ThreeBandEqualizer,objName:"Ops.WebAudio.ThreeBandEqualizer"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.WaveformMesh +// +// ************************************************************** + +Ops.WebAudio.WaveformMesh = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +// currently only uses mono, if we want to extract stereo data some changes in extractPeaks are needed + +// constants +const SAMPLES_PER_PIXEL_MIN = 100; // might crash when this is too low + +function findMinMax(array) +{ + let min = Infinity; + let max = -Infinity; + let i = 0; + let len = array.length; + let curr; + + for (; i < len; i++) + { + curr = array[i]; + if (min > curr) + { + min = curr; + } + if (max < curr) + { + max = curr; + } + } + + return { + "min": min, + "max": max + }; +} + +// vars +const geom = new CGL.Geometry("Waveform"); +let mesh = null; +const cgl = op.patch.cgl; + +// input +const renderPort = op.inTrigger("Render"); +const audioBufferPort = op.inObject("Audio Buffer", null, "audioBuffer"); +const renderActivePort = op.inBool("Render Active", true); +const showBottomHalfPort = op.inBool("Show bottom half", true); +const centerPort = op.inBool("Center Origin", true); +const widthPort = op.inValue("Width", 30); +const samplesPerPixelPort = op.inInt("Samples Per Pixel", 10000); +const inCalculateUV = op.inBool("Calculate Tex Coords", true); + +op.setPortGroup("Render Options", [renderActivePort, showBottomHalfPort, centerPort]); +op.setPortGroup("Waveform Settings", [widthPort, samplesPerPixelPort]); +op.setPortGroup("Mesh Options", [inCalculateUV]); +// output +const nextPort = op.outTrigger("Next"); +const geometryPort = op.outObject("Geometry", null, "geometry"); + +// change listeners +let updating = true; +audioBufferPort.onChange = samplesPerPixelPort.onChange += showBottomHalfPort.onChange = centerPort.onChange += widthPort.onChange = inCalculateUV.onChange = () => + { + updating = true; + }; + +renderPort.onTriggered = () => +{ + if (updating) + { + extractPeaks(); + updating = false; + } + if (mesh && renderActivePort.get()) + { + mesh.render(cgl.getShader()); + } + nextPort.trigger(); +}; + +// functions +function calculateUV(meshPoints) +{ + const texCoordsNew = []; + const xTex = []; + const yTex = []; + + for (let i = 0; i < meshPoints.length; i += 3) + { + xTex.push(meshPoints[i + 0]); + yTex.push(meshPoints[i + 1]); + } + + const minMaxX = findMinMax(xTex); + const minMaxY = findMinMax(yTex); + + const normalizedTexX = xTex.map((val) => mapRange(val, minMaxX.min, minMaxX.max, 0, 1)); + const normalizedTexY = yTex.map((val) => mapRange(val, minMaxY.min, minMaxY.max, 0, 1)); + + const finalTexCoords = []; + + for (let i = 0; i < normalizedTexX.length; i += 1) + { + finalTexCoords.push(normalizedTexX[i], 1.0 - normalizedTexY[i]); + } + + return finalTexCoords; +} + +function createMesh(meshPoints) +{ + geom.clear(); + geom.vertices = meshPoints; + + if (inCalculateUV.get()) + { + const texCoords = calculateUV(meshPoints); + geom.setTexCoords(texCoords); + } + else + { + geom.setTexCoords([]); + } + + geom.calculateNormals(); + + for (let i = 0; i < geom.vertexNormals.length; i += 3) + { + geom.vertexNormals[i + 2] *= -1; + } + + mesh = new CGL.Mesh(cgl, geom); + geometryPort.set(null); + geometryPort.set(geom); +} + +/* + * Add to triangles to the mesh + * z-coordinate is assumed to be 0. + * @param meshPoints The mesh to add triangles to, [x0, y0, z0, x1, y1, z1, ...] + * @param splinePoints The source for the traingle coordinates, [x0, y0, z0, x1, y1, z1, ...] + @ param i The index of the first x-coordinate in splinePoints array + */ +function addTrianglesToMesh(meshPoints, splinePoints, i) +{ + // first triangle + meshPoints.push(splinePoints[i], splinePoints[i + 1], 0); // point a + meshPoints.push(splinePoints[i + 3], splinePoints[i + 4], 0); // point b + meshPoints.push(splinePoints[i + 3], 0, 0); // point b (y=0) + // second triangle + meshPoints.push(splinePoints[i], splinePoints[i + 1], 0); // point a + meshPoints.push(splinePoints[i + 3], 0, 0); // point b (y=0) + meshPoints.push(splinePoints[i], 0, 0); // point a (y=0) +} + +/** + * Creates triangles in the form [ax, ay, az, bx, by, bz, cx, cy, cz, ...] + * based on all points in splinePoints + */ +function createMeshPoints(splinePoints) +{ + // TODO: calc indices ? optimize mesh poitns + if (!splinePoints) { return []; } + let meshPoints = []; + // if we only draw one half, we can just go over all points + if (!showBottomHalfPort.get()) + { + for (var i = 0; i < splinePoints.length - 5; i += 3) + { + addTrianglesToMesh(meshPoints, splinePoints, i); + } + } + // if both sides are drawn, we need to handle the end point differently + else + { + // add top half + for (var i = 0; i < (splinePoints.length / 2) - 5; i += 3) + { + addTrianglesToMesh(meshPoints, splinePoints, i); + } + // add bottom half + for (var i = (splinePoints.length / 2); i < splinePoints.length - 5; i += 3) + { + addTrianglesToMesh(meshPoints, splinePoints, i); + } + } + return meshPoints; +} + +function extractPeaks() +{ + const audioBuffer = audioBufferPort.get(); + if (audioBuffer) + { + op.setUiError("noBuffer", null); + + if (!(audioBuffer instanceof AudioBuffer)) return; + } + else op.setUiError("noBuffer", "You need to connect the \"Audio Buffer\" input for this op to work!", 0); + + if (audioBuffer) + { + let samplesPerPixel = samplesPerPixelPort.get(); + if (samplesPerPixel < SAMPLES_PER_PIXEL_MIN) + { + op.setUiError("minSamples", "The value for \"Samples Per Pixel\" is lower than the minimum value " + SAMPLES_PER_PIXEL_MIN + ". Therefore the value has been set to " + SAMPLES_PER_PIXEL_MIN + ".", 1); + samplesPerPixel = SAMPLES_PER_PIXEL_MIN; + } + else + { + op.setUiError("minSamples", null); + } + + let makeMono = audioBuffer.numberOfChannels < 2; // TODO: If we make this a parameter, we have to check if the audio actually is stereo + + const peaks = webaudioPeaks(audioBuffer, samplesPerPixel, makeMono); + + // because we extract mono peaks we just access [0] here + const typedArr = peaks.data[0]; + const regularArr = Array.prototype.slice.call(typedArr); + + const normalizedArray = []; + normalizedArray.length = regularArr.length; + + const minMax = findMinMax(regularArr); + + for (let i = 0; i < regularArr.length; i += 1) + { + normalizedArray[i] = mapRange(regularArr[i], minMax.min, minMax.max, -1, 1); + } + + // currently the array contains values like this: [y1top, y1bottom, y2top, ...] + // we want it to be: [y1top, y2top, ..., y2bottom, y1bottom] + + const resortedArr = []; + + // to center the waveform around the corrdinate origin, we need to offset its position + + let offset = 0; + let width = widthPort.get(); + + if (centerPort.get()) offset = 1; + + for (var i = 1; i < normalizedArray.length; i += 2) + { + const xCoord = i / normalizedArray.length; + const yCoord = normalizedArray[i]; + + resortedArr.push(xCoord - offset, yCoord, 0); + } + + const minX = resortedArr[0]; + const maxX = resortedArr[resortedArr.length - 3]; + + if (showBottomHalfPort.get()) + { + for (var i = normalizedArray.length - 2; i >= 0; i -= 2) + { + const xCoord = i / regularArr.length; + const yCoord = normalizedArray[i]; + resortedArr.push(xCoord - offset, yCoord, 0); + } + } + + // re-map range of x-coordinates + let toMin = 0; + let toMax = width; + + if (centerPort.get()) + { + toMin = -width / 2; + toMax = width / 2; + } + + for (let i = 0; i < resortedArr.length; i += 3) + { + resortedArr[i] = mapRange(resortedArr[i], minX, maxX, toMin, toMax); + } + + // resortedArr now looks like: [yTop0, yTop1, ..., yBottom1, yBottom0] + const meshPoints = createMeshPoints(resortedArr); + createMesh(meshPoints); + } + else + { + geometryPort.set(null); + if (geom) geom.clear(); + if (mesh) + { + mesh.dispose(); + mesh = null; + } + } +} + +function mapRange(value, inMin, inMax, outMin, outMax) +{ + return (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; +} + + +}; + +Ops.WebAudio.WaveformMesh.prototype = new CABLES.Op(); +CABLES.OPS["9f61a958-90b1-46df-a893-de48a5844583"]={f:Ops.WebAudio.WaveformMesh,objName:"Ops.WebAudio.WaveformMesh"}; + + + + +// ************************************************************** +// +// Ops.WebAudio.Waveshaper +// +// ************************************************************** + +Ops.WebAudio.Waveshaper = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +let audioContext = CABLES.WEBAUDIO.createAudioContext(op); + +const inAudio = op.inObject("audio in", null, "audioNode"); +const inDryWet = op.inFloatSlider("Dry/Wet", 1); +const inOversampling = op.inSwitch("Oversampling", ["none", "2x", "4x"], "4x"); +const inDistortionAmount = op.inInt("Distortion Amount", 15); + +const inWaveshapeArray = op.inArray("Waveshape Array In"); +const inOutputGain = op.inFloatSlider("Output Gain", 0.5); + +op.setPortGroup("Waveshape Settings", [inOversampling, inDistortionAmount, inWaveshapeArray]); +const audioOut = op.outObject("audio out", null, "audioNode"); +const outCurve = op.outArray("Curve Out"); +const outCurveLength = op.outNumber("Curve Length"); + +// * webaudio nodes * // +const inputNode = audioContext.createGain(); +const dryNode = audioContext.createGain(); +const wetNode = audioContext.createGain(); +const outputNode = audioContext.createGain(); +wetNode.gain.value = parseFloat(inDryWet.get()); +dryNode.gain.value = 1.0 - parseFloat(inDryWet.get()); + +const waveshaperNode = audioContext.createWaveShaper(); + +function makeDefaultDistortionCurve(amount) +{ + let n_samples = 256, curve = new Float32Array(n_samples); + for (let i = 0; i < n_samples; ++i) + { + // normalize [-1,1]; + let x = i * 2 / n_samples - 1; + // transfer function + curve[i] = (Math.PI + amount) * x / (Math.PI + amount * Math.abs(x)); + } + return curve; +} + +waveshaperNode.curve = makeDefaultDistortionCurve(400); +waveshaperNode.oversample = inOversampling.get(); +outCurve.set(waveshaperNode.curve); +outCurve.set(waveshaperNode.curve.length); +inputNode.connect(dryNode); +inputNode.connect(waveshaperNode); + +dryNode.connect(outputNode); +waveshaperNode.connect(wetNode); + +wetNode.connect(outputNode); + +changeDistortion(); + +function changeDistortion() +{ + if (inWaveshapeArray.get()) + { + inDistortionAmount.setUiAttribs({ "greyout": true }); + waveshaperNode.curve = Float32Array.from(inWaveshapeArray.get()); + } + else + { + inDistortionAmount.setUiAttribs({ "greyout": false }); + if (inDistortionAmount.get() < 0) + { + op.setUiError("distAmountOutOfRange", "The minimum amount of possible distortion is 0. Choosing values lower than 0 will set them to 0.", 1); + } + else + { + op.setUiError("distAmountOutOfRange", null); + } + waveshaperNode.curve = makeDefaultDistortionCurve(Math.max(0, inDistortionAmount.get())); + } + + outCurve.set(Array.from(waveshaperNode.curve)); + outCurveLength.set(waveshaperNode.curve.length); +} + +// * onChange handlers * // +inDryWet.onChange = () => +{ + wetNode.gain.linearRampToValueAtTime(Number(inDryWet.get()), audioContext.currentTime + 0.01); + dryNode.gain.linearRampToValueAtTime((1 - Number(inDryWet.get())), audioContext.currentTime + 0.01); +}; + +inWaveshapeArray.onChange = inDistortionAmount.onChange = changeDistortion; + +inOversampling.onChange = updateOversampling; + +function updateOversampling() +{ + waveshaperNode.oversample = inOversampling.get(); +} + +inOutputGain.onChange = updateGain; + +function updateGain() +{ + outputNode.gain.linearRampToValueAtTime(Number(inOutputGain.get()), audioContext.currentTime + 0.01); +} + +let oldAudioIn = null; +inAudio.onChange = function () +{ + if (!inAudio.get()) + { + if (oldAudioIn) + { + try + { + if (oldAudioIn.disconnect) + { + oldAudioIn.disconnect(inputNode); + } + } + catch (e) + { + op.log(e); + } + } + + audioOut.set(null); + } + else + { + if (inAudio.get().connect) + { + inAudio.get().connect(inputNode); + audioOut.set(outputNode); + updateGain(); + updateOversampling(); + } + } + oldAudioIn = inAudio.get(); +}; + + +}; + +Ops.WebAudio.Waveshaper.prototype = new CABLES.Op(); +CABLES.OPS["c7c957a7-4531-4909-8721-172e568ee076"]={f:Ops.WebAudio.Waveshaper,objName:"Ops.WebAudio.Waveshaper"}; + + + + +// ************************************************************** +// +// Ops.WebXr.Vr.Vr +// +// ************************************************************** + +Ops.WebXr.Vr.Vr = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"icon_svg":"%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20245.82%20141.73%22%3E%3Cdefs%3E%3Cstyle%3E.a%7Bfill%3A%23fff%3Bfill-rule%3Aevenodd%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%3Ctitle%3Emask%3C%2Ftitle%3E%3Cpath%20class%3D%22a%22%20d%3D%22M175.56%2C111.37c-22.52%2C0-40.77-18.84-40.77-42.07S153%2C27.24%2C175.56%2C27.24s40.77%2C18.84%2C40.77%2C42.07S198.08%2C111.37%2C175.56%2C111.37ZM26.84%2C69.31c0-23.23%2C18.25-42.07%2C40.77-42.07s40.77%2C18.84%2C40.77%2C42.07-18.26%2C42.07-40.77%2C42.07S26.84%2C92.54%2C26.84%2C69.31ZM27.27%2C0C11.54%2C0%2C0%2C12.34%2C0%2C28.58V110.9c0%2C16.24%2C11.54%2C30.83%2C27.27%2C30.83H99.57c2.17%2C0%2C4.19-1.83%2C5.4-3.7L116.47%2C118a8%2C8%2C0%2C0%2C1%2C12.52-.18l11.51%2C20.34c1.2%2C1.86%2C3.22%2C3.61%2C5.39%2C3.61h72.29c15.74%2C0%2C27.63-14.6%2C27.63-30.83V28.58C245.82%2C12.34%2C233.93%2C0%2C218.19%2C0H27.27Z%22%2F%3E%3C%2Fsvg%3E","present_frag":"UNI sampler2D tex;\nIN vec2 texCoord;\n\nvoid main()\n{\n outColor= texture(tex,texCoord);\n // outColor=vec4(texCoord.x,texCoord.y,0.0,1.0);\n}\n\n","present_vert":"{{MODULES_HEAD}}\nIN vec3 vPosition;\nIN vec2 attrTexCoord;\n\nIN float attrVertIndex;\n\nOUT vec2 texCoord;\nOUT vec3 norm;\nUNI mat4 projMatrix;\nUNI mat4 viewMatrix;\nUNI mat4 modelMatrix;\n\nvoid main()\n{\n texCoord=vec2(attrTexCoord.x,1.0-attrTexCoord.y);\n vec4 pos=vec4(vPosition, 1.0);\n mat4 mMatrix=modelMatrix;\n {{MODULE_VERTEX_POSITION}}\n gl_Position = projMatrix * (viewMatrix*mMatrix) * pos;\n}\n",}; +/* +https://web.dev/vr-comes-to-the-web-pt-ii/ +*/ + +const + inMainloop = op.inTrigger("Mainloop"), + inStop = op.inTriggerButton("Stop"), + inShowButton = op.inBool("Show Button", true), + inButtonStyle = op.inStringEditor("Button Style", "padding:10px;\nposition:absolute;\nleft:50%;\ntop:50%;\ntransform: translate(-50%,-50%);\nwidth:50px;\nheight:50px;\ncursor:pointer;\nborder-radius:40px;\nbackground:#444;\nbackground-repeat:no-repeat;\nbackground-size:70%;\nbackground-position:center center;\nz-index:9999;\nbackground-image:url(data:image/svg+xml," + attachments.icon_svg + ");", "inline-css"), + inRender2Tex = op.inBool("Render to texture", false), + inShader = op.inObject("Shader", null, "shader"), + msaa = op.inSwitch("MSAA", ["none", "2x", "4x", "8x"], "none"), + next = op.outTrigger("Next"), + nextPre = op.outTrigger("Render After Eyes"), + outPose = op.outObject("Viewer Pose"), + outEyeIndex = op.outNumber("Eye Index"), + outVr = op.outBoolNum("VR Support"), + outMat = op.outArray("Matrix"), + outElement = op.outObject("DOM Overlay Ele", null, "element"), + outSession = op.outBoolNum("In Session"), + outMs = op.outArray("Ms per eye"), + outTex = op.outTexture("Texture"), + outDepth = op.outTexture("Texture Depth"); + +const cgl = op.patch.cgl; +const canvas = op.patch.cgl.canvas.parentElement; + +op.setPortGroup("Startbutton", [inButtonStyle, inShowButton]); +op.setPortGroup("Texture", [inRender2Tex, msaa]); + +let msEyes = [0, 0]; +let xr = navigator.xr; +let fb = null; + +let hadError = false; +let buttonEle = null; +let glLayer = null; +let xrSession = null; +let webGLRenContext = null; +let xrReferenceSpace = null; +let vmat = mat4.create(); +let xrViewerPose = null; + +inStop.onTriggered = stopVr; +inButtonStyle.onChange = () => { if (buttonEle)buttonEle.style = inButtonStyle.get(); }; + +if (xr) xr.isSessionSupported("immersive-vr").then( + (r) => + { + outVr.set(true); + + if (r) initButton(); + else removeButton(); + }); +else removeButton(); + +op.onDelete = () => +{ + removeButton(); +}; + +inShowButton.onChange = () => +{ + if (!inShowButton.get())removeButton(); + else initButton(); +}; + +function stopVr() +{ + if (xrSession)xrSession.end(); + xrSession = null; + outSession.set(false); + + cgl.frameStore.xrSession = null; + cgl.frameStore.xrFrame = null; + cgl.frameStore.xrViewerPose = null; + cgl.frameStore.xrReferenceSpace = null; +} + +function startVr() +{ + if (xrSession) + { + stopVr(); + return; + } + + xr.requestSession("immersive-vr", {}) + .then( + async (session) => + { + xrSession = session; + outSession.set(true); + + xrSession.requestReferenceSpace("local").then( + (refSpace) => + { + xrReferenceSpace = refSpace; + }); + + if (xrSession) + { + await cgl.gl.makeXRCompatible(); + + let canvas = cgl.canvas; + webGLRenContext = canvas.getContext("webgl2", { "xrCompatible": true }); + + xrSession.updateRenderState({ "baseLayer": new XRWebGLLayer(xrSession, webGLRenContext) }); + xrSession.requestAnimationFrame(onXRFrame); + } + }, + (err) => + { + // error.... + op.error(err); + }); +} + +function onXRFrame(hrTime, xrFrame) +{ + if (hadError) return; + + let xrSession = xrFrame.session; + xrSession.requestAnimationFrame(onXRFrame); + + try + { + xrViewerPose = xrFrame.getViewerPose(xrReferenceSpace); + + cgl.frameStore.xrSession = xrSession; + cgl.frameStore.xrFrame = xrFrame; + cgl.frameStore.xrViewerPose = xrViewerPose; + cgl.frameStore.xrReferenceSpace = xrReferenceSpace; + + outMat.set(xrViewerPose.transform.matrix); + + outPose.set(null); + outPose.set(xrViewerPose); + + if (xrViewerPose) + { + glLayer = xrSession.renderState.baseLayer; + webGLRenContext.bindFramebuffer(webGLRenContext.FRAMEBUFFER, glLayer.framebuffer); + } + + CABLES.patch.emitOnAnimFrameEvent(); + + cgl.renderStart(cgl); + + if (inRender2Tex.get()) r2texStart(); + + cgl.gl.clearColor(0, 0, 0, 1); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); + + op.patch.cg = cgl; + + for (let i = 0; i < xrViewerPose.views.length; i++) + { + let start = performance.now(); + outEyeIndex.set(i); + renderPre(); + renderEye(xrViewerPose.views[i]); + + msEyes[i] = performance.now() - start; + renderPost(); + + if (CGL.MESH.lastMesh)CGL.MESH.lastMesh.unBind(); + } + + if (CGL.MESH.lastMesh)CGL.MESH.lastMesh.unBind(); + + if (inRender2Tex.get()) r2texEnd(); + + cgl.gl.bindFramebuffer(cgl.gl.FRAMEBUFFER, glLayer.framebuffer); // gllayer has a default framebuffer.... interferes with cables fb stack... + + nextPre.trigger(); + + if (inRender2Tex.get()) + { + cgl.gl.clearColor(0, 0, 1, 1); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); + + cgl.pushPMatrix(); + cgl.pushViewMatrix(); + + mat4.ortho(cgl.pMatrix, 0, glLayer.framebufferWidth, glLayer.framebufferHeight, 0, -10, 10); + cgl.gl.viewport(0, 0, glLayer.framebufferWidth, glLayer.framebufferHeight); + + if (!mesh)rebuildRectangle(); + + cgl.setTexture(0, outTex.get().tex); + + if (inShader.isLinked())mesh.render(inShader.get()); + else mesh.render(shader); + + cgl.popPMatrix(); + cgl.popViewMatrix(); + } + + cgl.renderEnd(cgl); + + outMs.set(msEyes); + + CGL.MESH.lastShader = null; + CGL.MESH.lastMesh = null; + op.patch.cg = null; + } + catch (e) + { + op.error(e); + hadError = true; + } +} + +inMainloop.onTriggered = () => +{ + if (!xrSession) + { + next.trigger(); + } +}; + +function renderPre() +{ + cgl.pushDepthTest(true); + cgl.pushDepthWrite(true); + cgl.pushDepthFunc(cgl.gl.LEQUAL); + + CGL.MESH.lastShader = null; + CGL.MESH.lastMesh = null; +} + +function renderPost() +{ + cgl.popDepthTest(); + cgl.popDepthWrite(); + cgl.popDepthFunc(); +} + +function renderEye(view) +{ + cgl.pushBlend(true); + cgl.gl.blendEquationSeparate(cgl.gl.FUNC_ADD, cgl.gl.FUNC_ADD); + cgl.gl.blendFuncSeparate(cgl.gl.SRC_ALPHA, cgl.gl.ONE_MINUS_SRC_ALPHA, cgl.gl.ONE, cgl.gl.ONE_MINUS_SRC_ALPHA); + + cgl.pushPMatrix(); + + cgl.pMatrix = view.projectionMatrix; + + cgl.pushViewMatrix(); + + mat4.invert(cgl.vMatrix, xrViewerPose.transform.matrix); + + let viewport = glLayer.getViewport(view); + cgl.gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); + + next.trigger(); + + cgl.popViewMatrix(); + cgl.popPMatrix(); + cgl.popBlend(); +} + +function initButton() +{ + if (buttonEle) + { + removeButton(); + buttonEle = null; + } + + buttonEle = document.createElement("div"); + let container = op.patch.cgl.canvas.parentElement; + if (container)container.appendChild(buttonEle); + buttonEle.addEventListener("click", startVr); + buttonEle.addEventListener("touchstart", startVr); + buttonEle.style = inButtonStyle.get(); +} + +function removeButton() +{ + if (buttonEle)buttonEle.remove(); +} + +msaa.onChange = () => +{ + if (fb) fb.delete(); + fb = null; +}; + +function r2texStart() +{ + const w = glLayer.framebufferWidth; + const h = glLayer.framebufferHeight; + + if (!fb) + { + if (fb) fb.delete(); + + let selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + let selectFilter = CGL.Texture.FILTER_NEAREST; + + let ms = true; + let msSamples = 4; + + if (msaa.get() == "none") + { + msSamples = 0; + ms = false; + } + if (msaa.get() == "2x") msSamples = 2; + if (msaa.get() == "4x") msSamples = 4; + if (msaa.get() == "8x") msSamples = 8; + + fb = new CGL.Framebuffer2(cgl, w, h, + { + "name": "render2texture " + op.id, + "isFloatingPointTexture": false, + "multisampling": ms, + "wrap": selectedWrap, + "filter": selectFilter, + "depth": true, + "multisamplingSamples": msSamples, + "clear": true + }); + + outDepth.set(fb.getTextureDepth()); + } + + if (fb.getWidth() != Math.ceil(w) || fb.getHeight() != Math.ceil(h)) fb.setSize(w, h); + + fb.renderStart(cgl); +} + +function r2texEnd() +{ + fb.renderEnd(cgl); + + outTex.set(CGL.Texture.getEmptyTexture(op.patch.cgl)); + outTex.set(fb.getTextureColor()); +} + +let geom = new CGL.Geometry("webxr final texture draw rectangle"); +let mesh = null; +const shader = new CGL.Shader(cgl, "fullscreenrectangle"); +shader.fullscreenRectUniform = new CGL.Uniform(shader, "t", "tex", 0); +shader.setSource(attachments.present_vert, attachments.present_frag); + +function rebuildRectangle() +{ + // const currentViewPort = cgl.getViewPort(); + + // if (currentViewPort[2] == w && currentViewPort[3] == h && mesh) return; + + let xx = 0, xy = 0; + + const w = glLayer.framebufferWidth; + const h = glLayer.framebufferHeight; + + geom.vertices = new Float32Array([ + xx + w, xy + h, 0, + xx, xy + h, 0, + xx + w, xy, 0, + xx, xy, 0 + ]); + + let tc = null; + + // if (flipY.get()) + // tc = new Float32Array([ + // 1.0, 0.0, + // 0.0, 0.0, + // 1.0, 1.0, + // 0.0, 1.0 + // ]); + // else + tc = new Float32Array([ + 1.0, 1.0, + 0.0, 1.0, + 1.0, 0.0, + 0.0, 0.0 + ]); + + // if (flipX.get()) + // { + // tc[0] = 0.0; + // tc[2] = 1.0; + // tc[4] = 0.0; + // tc[6] = 1.0; + // } + + geom.setTexCoords(tc); + + geom.verticesIndices = new Uint16Array([2, 1, 0, 3, 1, 2]); + geom.vertexNormals = new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,]); + geom.tangents = new Float32Array([-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0]); + geom.biTangents == new Float32Array([0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0]); + + if (!mesh) mesh = new CGL.Mesh(cgl, geom); + else mesh.setGeom(geom); +} + + +}; + +Ops.WebXr.Vr.Vr.prototype = new CABLES.Op(); +CABLES.OPS["884b3def-9bb3-422a-8e1c-c85dcc346f5e"]={f:Ops.WebXr.Vr.Vr,objName:"Ops.WebXr.Vr.Vr"}; + + + + +// ************************************************************** +// +// Ops.WebXr.Vr.VrController +// +// ************************************************************** + +Ops.WebXr.Vr.VrController = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inUpdate = op.inTrigger("Update"), + inHand = op.inSwitch("Handedness", ["left", "right"], "right"), + next = op.outTrigger("Next"), + + outAxis1 = op.outNumber("Axis 1"), + outAxis2 = op.outNumber("Axis 2"), + outAxis3 = op.outNumber("Axis 3"), + outAxis4 = op.outNumber("Axis 4"), + outButton1 = op.outBoolNum("Button 1 Pressed"), + outButton2 = op.outBoolNum("Button 2 Pressed"), + outButton3 = op.outBoolNum("Button 3 Pressed"), + outButton4 = op.outBoolNum("Button 4 Pressed"), + outButton5 = op.outBoolNum("Button 5 Pressed"), + outButton6 = op.outBoolNum("Button 6 Pressed"), + outButton7 = op.outBoolNum("Button 7 Pressed"), + outButton1Touch = op.outBoolNum("Button 1 Touched"), + outButton2Touch = op.outBoolNum("Button 2 Touched"), + outButton3Touch = op.outBoolNum("Button 3 Touched"), + outButton4Touch = op.outBoolNum("Button 4 Touched"), + outButton5Touch = op.outBoolNum("Button 5 Touched"), + outButton6Touch = op.outBoolNum("Button 6 Touched"), + outButton7Touch = op.outBoolNum("Button 7 Touched"), + + outX = op.outNumber("Position X"), + outY = op.outNumber("Position Y"), + outZ = op.outNumber("Position Z"), + + outGp = op.outObject("Gamepad Values"), + + outTransformed = op.outTrigger("Transformed Position"), + + outFound = op.outBoolNum("Found"); + +const cgl = op.patch.cgl; + +op.setPortGroup("Gamepad", [ + outButton1, outButton2, outButton3, outButton4, outButton5, outButton6, outButton7, + outButton1Touch, outButton2Touch, outButton3Touch, outButton4Touch, outButton5Touch, outButton6Touch, outButton7Touch, + outAxis1, outAxis2, outAxis3, outAxis4]); + +inUpdate.onTriggered = () => +{ + outGp.set(null); + + if (op.patch.cgl.frameStore.xrSession) + { + let found = false; + let xrSession = op.patch.cgl.frameStore.xrSession; + + const inputSources = xrSession.inputSources; + + for (let i = 0; i < inputSources.length; i++) + { + if (inputSources[i].handedness === inHand.get()) + { + found = true; + + if (inputSources[i].gamepad)setGamepadValues(inputSources[i].gamepad); + + let controlPose = cgl.frameStore.xrFrame.getPose(inputSources[i].gripSpace, cgl.frameStore.xrReferenceSpace); + if (controlPose && controlPose.transform) + { + cgl.pushModelMatrix(); + + mat4.multiply(cgl.mMatrix, cgl.mMatrix, controlPose.transform.matrix); + outX.set(controlPose.transform.position.x); + outY.set(controlPose.transform.position.y); + outZ.set(controlPose.transform.position.z); + + outTransformed.trigger(); + + cgl.popModelMatrix(); + } + else op.log("vr controller: no controlpose transform?!"); + + break; + } + } + + outFound.set(found); + } + + next.trigger(); +}; + +function setGamepadValues(gp) +{ + outAxis1.set(gp.axes[0]); + outAxis2.set(gp.axes[1]); + + outButton1.set(gp.buttons[0].pressed); + outButton2.set(gp.buttons[1].pressed); + outButton3.set(gp.buttons[2].pressed); + outButton4.set(gp.buttons[3].pressed); + outButton5.set(gp.buttons[4].pressed); + outButton6.set(gp.buttons[5].pressed); + outButton7.set(gp.buttons[6].pressed); + + outButton1Touch.set(gp.buttons[0].touched); + outButton2Touch.set(gp.buttons[1].touched); + outButton3Touch.set(gp.buttons[2].touched); + outButton4Touch.set(gp.buttons[3].touched); + outButton5Touch.set(gp.buttons[4].touched); + outButton6Touch.set(gp.buttons[5].touched); + outButton7Touch.set(gp.buttons[6].touched); + + const g = { "buttons": gp.buttons, + "axes": gp.axes, + "connected": gp.connected, + "mapping": gp.mapping, + "axes": gp.axes + }; + + outGp.set(g); +} + + +}; + +Ops.WebXr.Vr.VrController.prototype = new CABLES.Op(); +CABLES.OPS["6959b43a-8c64-4aa1-a0f0-d4d5b7e2b1c3"]={f:Ops.WebXr.Vr.VrController,objName:"Ops.WebXr.Vr.VrController"}; + + + + +// ************************************************************** +// +// Ops.Website.Cookie +// +// ************************************************************** + +Ops.Website.Cookie = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + outCookie = op.outObject("Cookie"), + outString = op.outString("Cookie String"); + +update(); + +function str_obj(str) +{ + str = str.split(";"); + const result = {}; + + for (let i = 0; i < str.length; i++) + { + const cur = str[i].split("="); + if (cur.length > 1) result[cur[0].trim()] = cur[1].trim(); + } + return result; +} + +function update() +{ + outCookie.set(str_obj(document.cookie)); + outString.set(document.cookie); +} + + +}; + +Ops.Website.Cookie.prototype = new CABLES.Op(); +CABLES.OPS["a02b3bbe-eace-4a2e-b02b-1bf1e398d78a"]={f:Ops.Website.Cookie,objName:"Ops.Website.Cookie"}; + + + + +// ************************************************************** +// +// Ops.Website.FilenameInfo +// +// ************************************************************** + +Ops.Website.FilenameInfo = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inUrl=op.inString("URL",""), + outProtocol=op.outString("Protocol"), + outHost=op.outString("Host"), + outFullPath=op.outString("Full Path"), + outFilename=op.outString("Filename"), + outIsURL=op.outString("Is URL"), + outExt=op.outString("Suffix"); + +function isValidUrl(string) +{ + try { new URL(string); } + catch (_) { return false; } + + return true; +} + +inUrl.onChange=()=> +{ + const url=inUrl.get(); + const isUrl=isValidUrl(url); + outIsURL.set(isUrl); + + if(url.indexOf(":")>-1) + { + const pathArray = url.split( ':' ); + outProtocol.set(pathArray[0]); + } + + if(url.indexOf("/")>-1) + { + const hostArr = url.split( '/' ); + outHost.set(hostArr[2]); + } + + if(url.indexOf(".")>-1) + { + const fnArray=url.split("."); + outExt.set(fnArray[fnArray.length-1]); + } + else outExt.set(""); + + if(url.indexOf("/")>-1 ) + { + const hostArr = url.split( '/' ); + outFilename.set(hostArr[hostArr.length-1]); + + hostArr.length=hostArr.length-1; + const fullPath=hostArr.join("/"); + outFullPath.set(fullPath); + } + else + { + if(!isUrl)outFilename.set(url); + } +}; + + +}; + +Ops.Website.FilenameInfo.prototype = new CABLES.Op(); +CABLES.OPS["0a349745-20c8-44c4-8a70-214c7ccf87e9"]={f:Ops.Website.FilenameInfo,objName:"Ops.Website.FilenameInfo"}; + + + + +// ************************************************************** +// +// Ops.Website.ForceHttps +// +// ************************************************************** + +Ops.Website.ForceHttps = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; + +if (location.href.indexOf("http://localhost")) + if (location.protocol !== "https:") location.protocol = "https:"; + + +}; + +Ops.Website.ForceHttps.prototype = new CABLES.Op(); +CABLES.OPS["63eb8aad-4700-4760-ac0b-ae712ac01fd7"]={f:Ops.Website.ForceHttps,objName:"Ops.Website.ForceHttps"}; + + + + +// ************************************************************** +// +// Ops.Website.InfoURL +// +// ************************************************************** + +Ops.Website.InfoURL = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + outUrl = op.outString("URL"), + outHost = op.outString("Host"), + outHash = op.outString("Hash"), + outPathname = op.outString("Pathname"), + outProtocol = op.outString("Protocol"), + outPort = op.outString("Port"), + outChangeHash = op.outTrigger("Hash Changed"); + +op.onDelete = () => +{ + window.removeEventListener("hashchange", hashChange); +}; + +window.addEventListener("hashchange", hashChange); + +const l = document.location; +outUrl.set(l.href); +outHost.set(l.host); +outHash.set(l.hash); +outPathname.set(l.pathname); +outProtocol.set(l.protocol); +outPort.set(l.port); + +function hashChange() +{ + const l = document.location; + outHash.set(l.hash); + + outChangeHash.trigger(); +} + + +}; + +Ops.Website.InfoURL.prototype = new CABLES.Op(); +CABLES.OPS["e72fbd80-f9c7-4572-8b6d-a485ef474b74"]={f:Ops.Website.InfoURL,objName:"Ops.Website.InfoURL"}; + + + + +// ************************************************************** +// +// Ops.Website.LocalStorageNumber +// +// ************************************************************** + +Ops.Website.LocalStorageNumber = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inKey = op.inString("Key"), + inValue = op.inFloat("Number"), + inStore = op.inTriggerButton("Store"), + outValue = op.outNumber("Stored Number"), + outSupported = op.outBoolNum("Storage Support", true); + +inKey.onChange = updateOutput; +inStore.onTriggered = storeValue; + +const localStorageSupport = !!window.localStorage; +if (!localStorageSupport) +{ + op.logError("your browser does not support or blocks access to localStorage, output will be inValue!"); + outSupported.set(false); +} + +updateOutput(); +op.onLoaded = updateOutput; + +function parse(val) +{ + if (val === "true" || val === true)val = 1; + if (val === "false" || val === false)val = 0; + val = parseFloat(val); + if (val != val)val = 0; + return val; +} + +op.patch.on("localstorageStored", (key, val) => +{ + if (key == inKey.get()) outValue.set(parse(val)); +}); + +function getKey() +{ + return (op.patch.namespace || "") + inKey.get(); +} + +function updateOutput() +{ + if (localStorageSupport) + { + outValue.set(parse(window.localStorage.getItem(getKey()))); + } + else + { + outValue.set(inValue.get()); + } +} + +function storeValue() +{ + let val = parse(inValue.get()); + + if (localStorageSupport) + { + window.localStorage.setItem(getKey(), val); + } + else + { + op.warn("not storing to localstorage, missing browsersupport!"); + } + outValue.set(val); + op.patch.emitEvent("localstorageStored", inKey.get(), val); +} + + +}; + +Ops.Website.LocalStorageNumber.prototype = new CABLES.Op(); +CABLES.OPS["2894cca0-0c06-4034-9d38-04b72afad277"]={f:Ops.Website.LocalStorageNumber,objName:"Ops.Website.LocalStorageNumber"}; + + + + +// ************************************************************** +// +// Ops.Website.LocalStorageString +// +// ************************************************************** + +Ops.Website.LocalStorageString = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inKey = op.inString("Key"), + inValue = op.inString("String", ""), + inStore = op.inTriggerButton("Store"), + outValue = op.outString("Stored String"), + outSupported = op.outBool("Storage Support", true); + +const localStorageSupport = !!window.localStorage; +if (!localStorageSupport) +{ + op.logError("your browser does not support or blocks access to localStorage, output will be inValue!"); + outSupported.set(false); +} + +updateOutput(); +inKey.onChange = updateOutput; +inStore.onTriggered = storeValue; + +function getKey() +{ + return (op.patch.namespace || "") + inKey.get(); +} + +function updateOutput() +{ + if (localStorageSupport) + { + outValue.set(window.localStorage.getItem(getKey())); + } + else + { + outValue.set(inValue.get()); + } +} + +function storeValue() +{ + const val = inValue.get(); + if (localStorageSupport) + { + window.localStorage.setItem(getKey(), val); + } + else + { + op.warn("not storing to localstorage, missing browsersupport!"); + } + outValue.set(val); +} + + +}; + +Ops.Website.LocalStorageString.prototype = new CABLES.Op(); +CABLES.OPS["f908fc2e-70b6-4ca4-8afd-4302b35ff570"]={f:Ops.Website.LocalStorageString,objName:"Ops.Website.LocalStorageString"}; + + + + +// ************************************************************** +// +// Ops.Website.LocationHashRoute +// +// ************************************************************** + +Ops.Website.LocationHashRoute = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const routeIn = op.inString("Route"); +const parsedOut = op.outObject("Values", {}); +const changedOut = op.outTrigger("Changed"); +const outMatching = op.outBool("Matching"); + +let router = null; +let lastHref = null; +let hashChangeListener = null; + +op.onLoaded, op.onCreate = init; + +function init() +{ + if ("onhashchange" in window) + { + router = new Navigo("/", { "hash": true, "noMatchWarning": true }); + const eventWrapper = (event) => + { + event.internal = true; + hashChange(event); + }; + + if (hashChangeListener) + { + op.patch.removeEventListener(hashChangeListener); + hashChangeListener = null; + } + hashChangeListener = op.patch.addEventListener("LocationHashChange", eventWrapper); + window.removeEventListener("hashchange", hashChangeFromBrowser); + window.addEventListener("hashchange", hashChangeFromBrowser); + hashChange({ "newURL": window.location.href }); + } + else + { + op.setUiError("unsupported", "Your browser does not support listening to hashchanges!"); + } +} + +function hashChangeFromBrowser(event) +{ + hashChange(event); +} + +op.onDelete = function () +{ + if (hashChangeListener) + { + op.patch.removeEventListener(hashChangeListener); + hashChangeListener = null; + } + window.removeEventListener("hashchange", hashChangeFromBrowser); +}; + +routeIn.onChange = function () +{ + if (router) + { + hashChange({ "newURL": window.location.href }, true); + } +}; + +function hashChange(event, forceUpdate) +{ + let hash = ""; + if (!forceUpdate && (event.newURL === lastHref)) + { + return; + } + lastHref = event.newURL; + op.setUiError("unsupported", null); + let values = {}; + const fields = event.newURL.split("#"); + let hasMatch = false; + if (routeIn.get()) + { + if (router && fields.length > 1) + { + hasMatch = false; + for (let i = 1; i < fields.length; i++) + { + let route = routeIn.get(); + let match = fields[i]; + hash += "#" + fields[i]; + const matched = router.matchLocation(route, match); + if (matched) + { + if (matched.data) + { + const keys = Object.keys(matched.data); + keys.forEach((key) => + { + matched.data[key] = getTypedValue(matched.data[key]); + }); + values = Object.assign(values, matched.data); + } + if (matched.params) + { + const keys = Object.keys(matched.params); + keys.forEach((key) => + { + matched.params[key] = getTypedValue(matched.params[key]); + }); + values = Object.assign(values, matched.params); + } + hasMatch = true; + } + } + } + } + else + { + const all = event.newURL.split("#", 2); + hash = all[1] || ""; + hasMatch = true; + } + + if (hasMatch) + { + let paramStr = hash.split("?", 2); + let params = parseQuery(paramStr[1]); + let keys = Object.keys(params); + keys.forEach((key) => + { + if (!values.hasOwnProperty(key)) values[key] = params[key]; + }); + } + + outMatching.set(hasMatch); + + if (!(parsedOut.get().length === 0 && values.length === 0)) + { + parsedOut.set(values); + } + + if (hasMatch && !event.silent) + { + changedOut.trigger(); + } +} + +function getTypedValue(val) +{ + let value = decodeURIComponent(val || ""); + if (value !== "") + { + switch (value) + { + case "true": + value = true; + break; + + case "false": + value = false; + break; + + default: + if (!isNaN(value)) + { + value = Number(value); + } + } + } + return value; +} + +function parseQuery(str) +{ + if (typeof str != "string" || str.length == 0) return {}; + let s = str.split("&"); + let s_length = s.length; + let bit, query = {}, first, second; + for (let i = 0; i < s_length; i++) + { + bit = s[i].split("="); + first = decodeURIComponent(bit[0]); + if (first.length == 0) continue; + second = decodeURIComponent(bit[1]); + if (typeof query[first] == "undefined") query[first] = second; + else if (query[first] instanceof Array) query[first].push(second); + else query[first] = [query[first], second]; + } + return query; +} + + +}; + +Ops.Website.LocationHashRoute.prototype = new CABLES.Op(); +CABLES.OPS["1e76f92b-1eed-4575-96e1-fcff6ed08c04"]={f:Ops.Website.LocationHashRoute,objName:"Ops.Website.LocationHashRoute"}; + + + + +// ************************************************************** +// +// Ops.Website.SetLocationHash +// +// ************************************************************** + +Ops.Website.SetLocationHash = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + hashIn = op.inString("Hash", ""), + inUpdate = op.inTriggerButton("Update"), + activeIn = op.inBool("Active", false), + silentIn = op.inBool("Silent", true), + reloadIn = op.inBool("Allow Empty", false); + +inUpdate.onTriggered = update; + +function update() +{ + if (!activeIn.get()) return; + + let hash = ""; + if (hashIn.get()) + { + hash = "#" + hashIn.get(); + } + + if (window.location.hash == hash) + { + return; + } + + try + { + op.setUiError("overload", null); + const event = new Event("hashchange"); + event.oldURL = window.location.href; + if (silentIn.get()) event.silent = true; + + if (hash) + { + history.replaceState(null, null, window.location.pathname + hash); + } + else if (reloadIn.get()) + { + history.replaceState(null, null, window.location.pathname); + } + event.newURL = window.location.href; + op.patch.emitEvent("LocationHashChange", event); + window.dispatchEvent(event); + } + catch (e) + { + op.setUiError("overload", "too many changes to the location hash, throttle down"); + op.log(e.message); + } +} + + +}; + +Ops.Website.SetLocationHash.prototype = new CABLES.Op(); +CABLES.OPS["82492357-c11d-4b76-bd57-b296d3b79b83"]={f:Ops.Website.SetLocationHash,objName:"Ops.Website.SetLocationHash"}; + + + + +// ************************************************************** +// +// Ops.Website.UrlQueryParams_v2 +// +// ************************************************************** + +Ops.Website.UrlQueryParams_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + paramName = op.inString("parameter"), + def = op.inString("Default"), + result = op.outString("result"); + +def.onChange = update; +paramName.onChange = updateParam; + +const query = {}; +const a = window.location.search.substr(1).split("&"); + +update(); + +for (let i = 0; i < a.length; i++) +{ + const b = a[i].split("="); + query[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || ""); +} + +function updateParam() +{ + op.setUiAttrib({ "extendTitle": paramName.get() }); + update(); +} + +function update() +{ + if (!query.hasOwnProperty(paramName.get())) + { + const value = def.get() || null; + result.set(value); + } + else + { + let v = query[paramName.get()]; + if (v === "true")v = true; + else if (v === "false")v = false; + + result.set(v); + } +} + + +}; + +Ops.Website.UrlQueryParams_v2.prototype = new CABLES.Op(); +CABLES.OPS["2e1b645c-c463-465d-abec-bf06ee4b970c"]={f:Ops.Website.UrlQueryParams_v2,objName:"Ops.Website.UrlQueryParams_v2"}; + + diff --git a/survey_dashboard/hmc_layout/static/en_files/dataBG.png b/survey_dashboard/hmc_layout/static/en_files/dataBG.png new file mode 100644 index 0000000..5e9b8a4 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/dataBG.png differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-bold.woff b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-bold.woff new file mode 100644 index 0000000..1a9ed2f Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-bold.woff differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-bold.woff.license b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-bold.woff.license new file mode 100644 index 0000000..e5512ae --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-bold.woff.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Datto Inc. + +SPDX-License-Identifier: OFL-1.1-RFN diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-bold.woff2 b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-bold.woff2 new file mode 100644 index 0000000..79ea1de Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-bold.woff2 differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-bold.woff2.license b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-bold.woff2.license new file mode 100644 index 0000000..e5512ae --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-bold.woff2.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Datto Inc. + +SPDX-License-Identifier: OFL-1.1-RFN diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed-bold.woff b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed-bold.woff new file mode 100644 index 0000000..38ac024 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed-bold.woff differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed-bold.woff.license b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed-bold.woff.license new file mode 100644 index 0000000..e5512ae --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed-bold.woff.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Datto Inc. + +SPDX-License-Identifier: OFL-1.1-RFN diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed-bold.woff2 b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed-bold.woff2 new file mode 100644 index 0000000..a769947 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed-bold.woff2 differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed-bold.woff2.license b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed-bold.woff2.license new file mode 100644 index 0000000..e5512ae --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed-bold.woff2.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Datto Inc. + +SPDX-License-Identifier: OFL-1.1-RFN diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed.woff b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed.woff new file mode 100644 index 0000000..d11c112 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed.woff differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed.woff.license b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed.woff.license new file mode 100644 index 0000000..e5512ae --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed.woff.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Datto Inc. + +SPDX-License-Identifier: OFL-1.1-RFN diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed.woff2 b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed.woff2 new file mode 100644 index 0000000..a1fe4b4 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed.woff2 differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed.woff2.license b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed.woff2.license new file mode 100644 index 0000000..e5512ae --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-condensed.woff2.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Datto Inc. + +SPDX-License-Identifier: OFL-1.1-RFN diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-bold.woff b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-bold.woff new file mode 100644 index 0000000..4d07a62 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-bold.woff differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-bold.woff.license b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-bold.woff.license new file mode 100644 index 0000000..e5512ae --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-bold.woff.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Datto Inc. + +SPDX-License-Identifier: OFL-1.1-RFN diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-bold.woff2 b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-bold.woff2 new file mode 100644 index 0000000..d52314c Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-bold.woff2 differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-bold.woff2.license b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-bold.woff2.license new file mode 100644 index 0000000..e5512ae --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-bold.woff2.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Datto Inc. + +SPDX-License-Identifier: OFL-1.1-RFN diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-italic.woff b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-italic.woff new file mode 100644 index 0000000..66a2ec1 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-italic.woff differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-italic.woff.license b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-italic.woff.license new file mode 100644 index 0000000..e5512ae --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-italic.woff.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Datto Inc. + +SPDX-License-Identifier: OFL-1.1-RFN diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-italic.woff2 b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-italic.woff2 new file mode 100644 index 0000000..d560bc2 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-italic.woff2 differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-italic.woff2.license b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-italic.woff2.license new file mode 100644 index 0000000..e5512ae --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp-italic.woff2.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Datto Inc. + +SPDX-License-Identifier: OFL-1.1-RFN diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp.woff b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp.woff new file mode 100644 index 0000000..08e17bf Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp.woff differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp.woff.license b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp.woff.license new file mode 100644 index 0000000..e5512ae --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp.woff.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Datto Inc. + +SPDX-License-Identifier: OFL-1.1-RFN diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp.woff2 b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp.woff2 new file mode 100644 index 0000000..2343c96 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp.woff2 differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp.woff2.license b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp.woff2.license new file mode 100644 index 0000000..e5512ae --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-exp.woff2.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Datto Inc. + +SPDX-License-Identifier: OFL-1.1-RFN diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-italic.woff b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-italic.woff new file mode 100644 index 0000000..62b3838 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-italic.woff differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-italic.woff.license b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-italic.woff.license new file mode 100644 index 0000000..e5512ae --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-italic.woff.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Datto Inc. + +SPDX-License-Identifier: OFL-1.1-RFN diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-italic.woff2 b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-italic.woff2 new file mode 100644 index 0000000..be59ab0 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-italic.woff2 differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-italic.woff2.license b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-italic.woff2.license new file mode 100644 index 0000000..e5512ae --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din-italic.woff2.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Datto Inc. + +SPDX-License-Identifier: OFL-1.1-RFN diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din.woff b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din.woff new file mode 100644 index 0000000..18c7e06 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din.woff differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din.woff.license b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din.woff.license new file mode 100644 index 0000000..e5512ae --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din.woff.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Datto Inc. + +SPDX-License-Identifier: OFL-1.1-RFN diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din.woff2 b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din.woff2 new file mode 100644 index 0000000..d6e8aa3 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din.woff2 differ diff --git a/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din.woff2.license b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din.woff2.license new file mode 100644 index 0000000..e5512ae --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/fonts/hifis-din.woff2.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Datto Inc. + +SPDX-License-Identifier: OFL-1.1-RFN diff --git a/survey_dashboard/hmc_layout/static/en_files/github-mark-white.png b/survey_dashboard/hmc_layout/static/en_files/github-mark-white.png new file mode 100644 index 0000000..50b8175 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/github-mark-white.png differ diff --git a/survey_dashboard/hmc_layout/static/en_files/lang.js b/survey_dashboard/hmc_layout/static/en_files/lang.js new file mode 100644 index 0000000..abf243a --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/lang.js @@ -0,0 +1 @@ +window.i18n = {en:{"app":{"read-more":"read more","glossary":"Glossary","to-offer":"to offer","job-offers":"Job Offers","expires-at":"Expires at","contacts":"contacts","link-to-tool":"Link to Tool","detailsLinkText":"details","overviewLinkText":"back to overview","no-hits":"No results were found for your input.","search":"Search for keywords","categories":{"hmc":"Open Positions at HMC","hmc-projects":"Open Positions at HMC projects","incubator":"Open positions at other incubator platforms","fdm":"Open positions in the field of RDM"}},"auth":{"failed":"These credentials do not match our records.","throttle":"Too many login attempts. Please try again in :seconds seconds."},"pagination":{"previous":"« Previous","next":"Next »"},"passwords":{"reset":"Your password has been reset!","sent":"We have emailed your password reset link!","throttled":"Please wait before retrying.","token":"This password reset token is invalid.","user":"We can't find a user with that email address."},"routes":{"pages":"pages","hmc-office":"hmc-office","aeronautics":"aeronautics","ap2":"ap2","earth-and-environment":"earth-and-environment","energy":"energy","health":"health","information":"information","matter":"matter","news":"news","events":"events","communities":"communities","glossary":"glossary","jobs":"job-offers","contact":"contact","tools":"tools","inf-projects":"inf-projects","training-materials":"training-materials","use-cases":"use-cases"},"validation":{"accepted":"The :attribute must be accepted.","active_url":"The :attribute is not a valid URL.","after":"The :attribute must be a date after :date.","after_or_equal":"The :attribute must be a date after or equal to :date.","alpha":"The :attribute may only contain letters.","alpha_dash":"The :attribute may only contain letters, numbers, dashes and underscores.","alpha_num":"The :attribute may only contain letters and numbers.","array":"The :attribute must be an array.","before":"The :attribute must be a date before :date.","before_or_equal":"The :attribute must be a date before or equal to :date.","between":{"numeric":"The :attribute must be between :min and :max.","file":"The :attribute must be between :min and :max kilobytes.","string":"The :attribute must be between :min and :max characters.","array":"The :attribute must have between :min and :max items."},"boolean":"The :attribute field must be true or false.","confirmed":"The :attribute confirmation does not match.","date":"The :attribute is not a valid date.","date_equals":"The :attribute must be a date equal to :date.","date_format":"The :attribute does not match the format :format.","different":"The :attribute and :other must be different.","digits":"The :attribute must be :digits digits.","digits_between":"The :attribute must be between :min and :max digits.","dimensions":"The :attribute has invalid image dimensions.","distinct":"The :attribute field has a duplicate value.","email":"The :attribute must be a valid email address.","ends_with":"The :attribute must end with one of the following: :values.","exists":"The selected :attribute is invalid.","file":"The :attribute must be a file.","filled":"The :attribute field must have a value.","gt":{"numeric":"The :attribute must be greater than :value.","file":"The :attribute must be greater than :value kilobytes.","string":"The :attribute must be greater than :value characters.","array":"The :attribute must have more than :value items."},"gte":{"numeric":"The :attribute must be greater than or equal :value.","file":"The :attribute must be greater than or equal :value kilobytes.","string":"The :attribute must be greater than or equal :value characters.","array":"The :attribute must have :value items or more."},"image":"The :attribute must be an image.","in":"The selected :attribute is invalid.","in_array":"The :attribute field does not exist in :other.","integer":"The :attribute must be an integer.","ip":"The :attribute must be a valid IP address.","ipv4":"The :attribute must be a valid IPv4 address.","ipv6":"The :attribute must be a valid IPv6 address.","json":"The :attribute must be a valid JSON string.","lt":{"numeric":"The :attribute must be less than :value.","file":"The :attribute must be less than :value kilobytes.","string":"The :attribute must be less than :value characters.","array":"The :attribute must have less than :value items."},"lte":{"numeric":"The :attribute must be less than or equal :value.","file":"The :attribute must be less than or equal :value kilobytes.","string":"The :attribute must be less than or equal :value characters.","array":"The :attribute must not have more than :value items."},"max":{"numeric":"The :attribute may not be greater than :max.","file":"The :attribute may not be greater than :max kilobytes.","string":"The :attribute may not be greater than :max characters.","array":"The :attribute may not have more than :max items."},"mimes":"The :attribute must be a file of type: :values.","mimetypes":"The :attribute must be a file of type: :values.","min":{"numeric":"The :attribute must be at least :min.","file":"The :attribute must be at least :min kilobytes.","string":"The :attribute must be at least :min characters.","array":"The :attribute must have at least :min items."},"not_in":"The selected :attribute is invalid.","not_regex":"The :attribute format is invalid.","numeric":"The :attribute must be a number.","password":"The password is incorrect.","present":"The :attribute field must be present.","regex":"The :attribute format is invalid.","required":"The :attribute field is required.","required_if":"The :attribute field is required when :other is :value.","required_unless":"The :attribute field is required unless :other is in :values.","required_with":"The :attribute field is required when :values is present.","required_with_all":"The :attribute field is required when :values are present.","required_without":"The :attribute field is required when :values is not present.","required_without_all":"The :attribute field is required when none of :values are present.","same":"The :attribute and :other must match.","size":{"numeric":"The :attribute must be :size.","file":"The :attribute must be :size kilobytes.","string":"The :attribute must be :size characters.","array":"The :attribute must contain :size items."},"starts_with":"The :attribute must start with one of the following: :values.","string":"The :attribute must be a string.","timezone":"The :attribute must be a valid zone.","unique":"The :attribute has already been taken.","uploaded":"The :attribute failed to upload.","url":"The :attribute format is invalid.","uuid":"The :attribute must be a valid UUID.","custom":{"attribute-name":{"rule-name":"custom-message"}},"attributes":[]}}}; \ No newline at end of file diff --git a/survey_dashboard/hmc_layout/static/en_files/libs(1).js b/survey_dashboard/hmc_layout/static/en_files/libs(1).js new file mode 100644 index 0000000..e69de29 diff --git a/survey_dashboard/hmc_layout/static/en_files/libs.core.min(1).js b/survey_dashboard/hmc_layout/static/en_files/libs.core.min(1).js new file mode 100644 index 0000000..af46eda --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/libs.core.min(1).js @@ -0,0 +1,44 @@ +/*! +@fileoverview gl-matrix - High performance matrix and vector operations +@author Brandon Jones +@author Colin MacKenzie IV +@version 3.1.0 + +Copyright (c) 2015-2019, Brandon Jones, Colin MacKenzie IV. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t=t||self).glMatrix={})}(this,function(t){"use strict";var n=1e-6,a="undefined"!=typeof Float32Array?Float32Array:Array,r=Math.random;var u=Math.PI/180;Math.hypot||(Math.hypot=function(){for(var t=0,n=arguments.length;n--;)t+=arguments[n]*arguments[n];return Math.sqrt(t)});var e=Object.freeze({EPSILON:n,get ARRAY_TYPE(){return a},RANDOM:r,setMatrixArrayType:function(t){a=t},toRadian:function(t){return t*u},equals:function(t,a){return Math.abs(t-a)<=n*Math.max(1,Math.abs(t),Math.abs(a))}});function o(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],c=a[1],h=a[2],s=a[3];return t[0]=r*i+e*c,t[1]=u*i+o*c,t[2]=r*h+e*s,t[3]=u*h+o*s,t}function i(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t}var c=o,h=i,s=Object.freeze({create:function(){var t=new a(4);return a!=Float32Array&&(t[1]=0,t[2]=0),t[0]=1,t[3]=1,t},clone:function(t){var n=new a(4);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n},copy:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t},identity:function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t},fromValues:function(t,n,r,u){var e=new a(4);return e[0]=t,e[1]=n,e[2]=r,e[3]=u,e},set:function(t,n,a,r,u){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t},transpose:function(t,n){if(t===n){var a=n[1];t[1]=n[2],t[2]=a}else t[0]=n[0],t[1]=n[2],t[2]=n[1],t[3]=n[3];return t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a*e-u*r;return o?(o=1/o,t[0]=e*o,t[1]=-r*o,t[2]=-u*o,t[3]=a*o,t):null},adjoint:function(t,n){var a=n[0];return t[0]=n[3],t[1]=-n[1],t[2]=-n[2],t[3]=a,t},determinant:function(t){return t[0]*t[3]-t[2]*t[1]},multiply:o,rotate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),c=Math.cos(a);return t[0]=r*c+e*i,t[1]=u*c+o*i,t[2]=r*-i+e*c,t[3]=u*-i+o*c,t},scale:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],c=a[1];return t[0]=r*i,t[1]=u*i,t[2]=e*c,t[3]=o*c,t},fromRotation:function(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=a,t[2]=-a,t[3]=r,t},fromScaling:function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=n[1],t},str:function(t){return"mat2("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},frob:function(t){return Math.hypot(t[0],t[1],t[2],t[3])},LDU:function(t,n,a,r){return t[2]=r[2]/r[0],a[0]=r[0],a[1]=r[1],a[3]=r[3]-t[2]*a[1],[t,n,a]},add:function(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t},subtract:i,exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=a[0],c=a[1],h=a[2],s=a[3];return Math.abs(r-i)<=n*Math.max(1,Math.abs(r),Math.abs(i))&&Math.abs(u-c)<=n*Math.max(1,Math.abs(u),Math.abs(c))&&Math.abs(e-h)<=n*Math.max(1,Math.abs(e),Math.abs(h))&&Math.abs(o-s)<=n*Math.max(1,Math.abs(o),Math.abs(s))},multiplyScalar:function(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t},multiplyScalarAndAdd:function(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t},mul:c,sub:h});function M(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=a[0],s=a[1],M=a[2],f=a[3],l=a[4],v=a[5];return t[0]=r*h+e*s,t[1]=u*h+o*s,t[2]=r*M+e*f,t[3]=u*M+o*f,t[4]=r*l+e*v+i,t[5]=u*l+o*v+c,t}function f(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t[4]=n[4]-a[4],t[5]=n[5]-a[5],t}var l=M,v=f,b=Object.freeze({create:function(){var t=new a(6);return a!=Float32Array&&(t[1]=0,t[2]=0,t[4]=0,t[5]=0),t[0]=1,t[3]=1,t},clone:function(t){var n=new a(6);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n},copy:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t},identity:function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t},fromValues:function(t,n,r,u,e,o){var i=new a(6);return i[0]=t,i[1]=n,i[2]=r,i[3]=u,i[4]=e,i[5]=o,i},set:function(t,n,a,r,u,e,o){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],c=a*e-r*u;return c?(c=1/c,t[0]=e*c,t[1]=-r*c,t[2]=-u*c,t[3]=a*c,t[4]=(u*i-e*o)*c,t[5]=(r*o-a*i)*c,t):null},determinant:function(t){return t[0]*t[3]-t[1]*t[2]},multiply:M,rotate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=Math.sin(a),s=Math.cos(a);return t[0]=r*s+e*h,t[1]=u*s+o*h,t[2]=r*-h+e*s,t[3]=u*-h+o*s,t[4]=i,t[5]=c,t},scale:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=a[0],s=a[1];return t[0]=r*h,t[1]=u*h,t[2]=e*s,t[3]=o*s,t[4]=i,t[5]=c,t},translate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=a[0],s=a[1];return t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=r*h+e*s+i,t[5]=u*h+o*s+c,t},fromRotation:function(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=a,t[2]=-a,t[3]=r,t[4]=0,t[5]=0,t},fromScaling:function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=n[1],t[4]=0,t[5]=0,t},fromTranslation:function(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=n[0],t[5]=n[1],t},str:function(t){return"mat2d("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+")"},frob:function(t){return Math.hypot(t[0],t[1],t[2],t[3],t[4],t[5],1)},add:function(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t[4]=n[4]+a[4],t[5]=n[5]+a[5],t},subtract:f,multiplyScalar:function(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*a,t[5]=n[5]*a,t},multiplyScalarAndAdd:function(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t[4]=n[4]+a[4]*r,t[5]=n[5]+a[5]*r,t},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=t[4],c=t[5],h=a[0],s=a[1],M=a[2],f=a[3],l=a[4],v=a[5];return Math.abs(r-h)<=n*Math.max(1,Math.abs(r),Math.abs(h))&&Math.abs(u-s)<=n*Math.max(1,Math.abs(u),Math.abs(s))&&Math.abs(e-M)<=n*Math.max(1,Math.abs(e),Math.abs(M))&&Math.abs(o-f)<=n*Math.max(1,Math.abs(o),Math.abs(f))&&Math.abs(i-l)<=n*Math.max(1,Math.abs(i),Math.abs(l))&&Math.abs(c-v)<=n*Math.max(1,Math.abs(c),Math.abs(v))},mul:l,sub:v});function m(){var t=new a(9);return a!=Float32Array&&(t[1]=0,t[2]=0,t[3]=0,t[5]=0,t[6]=0,t[7]=0),t[0]=1,t[4]=1,t[8]=1,t}function d(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=n[6],s=n[7],M=n[8],f=a[0],l=a[1],v=a[2],b=a[3],m=a[4],d=a[5],x=a[6],p=a[7],y=a[8];return t[0]=f*r+l*o+v*h,t[1]=f*u+l*i+v*s,t[2]=f*e+l*c+v*M,t[3]=b*r+m*o+d*h,t[4]=b*u+m*i+d*s,t[5]=b*e+m*c+d*M,t[6]=x*r+p*o+y*h,t[7]=x*u+p*i+y*s,t[8]=x*e+p*c+y*M,t}function x(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t[4]=n[4]-a[4],t[5]=n[5]-a[5],t[6]=n[6]-a[6],t[7]=n[7]-a[7],t[8]=n[8]-a[8],t}var p=d,y=x,q=Object.freeze({create:m,fromMat4:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[4],t[4]=n[5],t[5]=n[6],t[6]=n[8],t[7]=n[9],t[8]=n[10],t},clone:function(t){var n=new a(9);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n},copy:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t},fromValues:function(t,n,r,u,e,o,i,c,h){var s=new a(9);return s[0]=t,s[1]=n,s[2]=r,s[3]=u,s[4]=e,s[5]=o,s[6]=i,s[7]=c,s[8]=h,s},set:function(t,n,a,r,u,e,o,i,c,h){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t[6]=i,t[7]=c,t[8]=h,t},identity:function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},transpose:function(t,n){if(t===n){var a=n[1],r=n[2],u=n[5];t[1]=n[3],t[2]=n[6],t[3]=a,t[5]=n[7],t[6]=r,t[7]=u}else t[0]=n[0],t[1]=n[3],t[2]=n[6],t[3]=n[1],t[4]=n[4],t[5]=n[7],t[6]=n[2],t[7]=n[5],t[8]=n[8];return t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],c=n[6],h=n[7],s=n[8],M=s*o-i*h,f=-s*e+i*c,l=h*e-o*c,v=a*M+r*f+u*l;return v?(v=1/v,t[0]=M*v,t[1]=(-s*r+u*h)*v,t[2]=(i*r-u*o)*v,t[3]=f*v,t[4]=(s*a-u*c)*v,t[5]=(-i*a+u*e)*v,t[6]=l*v,t[7]=(-h*a+r*c)*v,t[8]=(o*a-r*e)*v,t):null},adjoint:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],c=n[6],h=n[7],s=n[8];return t[0]=o*s-i*h,t[1]=u*h-r*s,t[2]=r*i-u*o,t[3]=i*c-e*s,t[4]=a*s-u*c,t[5]=u*e-a*i,t[6]=e*h-o*c,t[7]=r*c-a*h,t[8]=a*o-r*e,t},determinant:function(t){var n=t[0],a=t[1],r=t[2],u=t[3],e=t[4],o=t[5],i=t[6],c=t[7],h=t[8];return n*(h*e-o*c)+a*(-h*u+o*i)+r*(c*u-e*i)},multiply:d,translate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=n[6],s=n[7],M=n[8],f=a[0],l=a[1];return t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=i,t[5]=c,t[6]=f*r+l*o+h,t[7]=f*u+l*i+s,t[8]=f*e+l*c+M,t},rotate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=n[6],s=n[7],M=n[8],f=Math.sin(a),l=Math.cos(a);return t[0]=l*r+f*o,t[1]=l*u+f*i,t[2]=l*e+f*c,t[3]=l*o-f*r,t[4]=l*i-f*u,t[5]=l*c-f*e,t[6]=h,t[7]=s,t[8]=M,t},scale:function(t,n,a){var r=a[0],u=a[1];return t[0]=r*n[0],t[1]=r*n[1],t[2]=r*n[2],t[3]=u*n[3],t[4]=u*n[4],t[5]=u*n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t},fromTranslation:function(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=n[0],t[7]=n[1],t[8]=1,t},fromRotation:function(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=a,t[2]=0,t[3]=-a,t[4]=r,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},fromScaling:function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=0,t[4]=n[1],t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},fromMat2d:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=0,t[3]=n[2],t[4]=n[3],t[5]=0,t[6]=n[4],t[7]=n[5],t[8]=1,t},fromQuat:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a+a,i=r+r,c=u+u,h=a*o,s=r*o,M=r*i,f=u*o,l=u*i,v=u*c,b=e*o,m=e*i,d=e*c;return t[0]=1-M-v,t[3]=s-d,t[6]=f+m,t[1]=s+d,t[4]=1-h-v,t[7]=l-b,t[2]=f-m,t[5]=l+b,t[8]=1-h-M,t},normalFromMat4:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],c=n[6],h=n[7],s=n[8],M=n[9],f=n[10],l=n[11],v=n[12],b=n[13],m=n[14],d=n[15],x=a*i-r*o,p=a*c-u*o,y=a*h-e*o,q=r*c-u*i,g=r*h-e*i,A=u*h-e*c,w=s*b-M*v,R=s*m-f*v,z=s*d-l*v,P=M*m-f*b,j=M*d-l*b,I=f*d-l*m,S=x*I-p*j+y*P+q*z-g*R+A*w;return S?(S=1/S,t[0]=(i*I-c*j+h*P)*S,t[1]=(c*z-o*I-h*R)*S,t[2]=(o*j-i*z+h*w)*S,t[3]=(u*j-r*I-e*P)*S,t[4]=(a*I-u*z+e*R)*S,t[5]=(r*z-a*j-e*w)*S,t[6]=(b*A-m*g+d*q)*S,t[7]=(m*y-v*A-d*p)*S,t[8]=(v*g-b*y+d*x)*S,t):null},projection:function(t,n,a){return t[0]=2/n,t[1]=0,t[2]=0,t[3]=0,t[4]=-2/a,t[5]=0,t[6]=-1,t[7]=1,t[8]=1,t},str:function(t){return"mat3("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+")"},frob:function(t){return Math.hypot(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8])},add:function(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t[4]=n[4]+a[4],t[5]=n[5]+a[5],t[6]=n[6]+a[6],t[7]=n[7]+a[7],t[8]=n[8]+a[8],t},subtract:x,multiplyScalar:function(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*a,t[5]=n[5]*a,t[6]=n[6]*a,t[7]=n[7]*a,t[8]=n[8]*a,t},multiplyScalarAndAdd:function(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t[4]=n[4]+a[4]*r,t[5]=n[5]+a[5]*r,t[6]=n[6]+a[6]*r,t[7]=n[7]+a[7]*r,t[8]=n[8]+a[8]*r,t},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=t[4],c=t[5],h=t[6],s=t[7],M=t[8],f=a[0],l=a[1],v=a[2],b=a[3],m=a[4],d=a[5],x=a[6],p=a[7],y=a[8];return Math.abs(r-f)<=n*Math.max(1,Math.abs(r),Math.abs(f))&&Math.abs(u-l)<=n*Math.max(1,Math.abs(u),Math.abs(l))&&Math.abs(e-v)<=n*Math.max(1,Math.abs(e),Math.abs(v))&&Math.abs(o-b)<=n*Math.max(1,Math.abs(o),Math.abs(b))&&Math.abs(i-m)<=n*Math.max(1,Math.abs(i),Math.abs(m))&&Math.abs(c-d)<=n*Math.max(1,Math.abs(c),Math.abs(d))&&Math.abs(h-x)<=n*Math.max(1,Math.abs(h),Math.abs(x))&&Math.abs(s-p)<=n*Math.max(1,Math.abs(s),Math.abs(p))&&Math.abs(M-y)<=n*Math.max(1,Math.abs(M),Math.abs(y))},mul:p,sub:y});function g(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}function A(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=n[6],s=n[7],M=n[8],f=n[9],l=n[10],v=n[11],b=n[12],m=n[13],d=n[14],x=n[15],p=a[0],y=a[1],q=a[2],g=a[3];return t[0]=p*r+y*i+q*M+g*b,t[1]=p*u+y*c+q*f+g*m,t[2]=p*e+y*h+q*l+g*d,t[3]=p*o+y*s+q*v+g*x,p=a[4],y=a[5],q=a[6],g=a[7],t[4]=p*r+y*i+q*M+g*b,t[5]=p*u+y*c+q*f+g*m,t[6]=p*e+y*h+q*l+g*d,t[7]=p*o+y*s+q*v+g*x,p=a[8],y=a[9],q=a[10],g=a[11],t[8]=p*r+y*i+q*M+g*b,t[9]=p*u+y*c+q*f+g*m,t[10]=p*e+y*h+q*l+g*d,t[11]=p*o+y*s+q*v+g*x,p=a[12],y=a[13],q=a[14],g=a[15],t[12]=p*r+y*i+q*M+g*b,t[13]=p*u+y*c+q*f+g*m,t[14]=p*e+y*h+q*l+g*d,t[15]=p*o+y*s+q*v+g*x,t}function w(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=r+r,c=u+u,h=e+e,s=r*i,M=r*c,f=r*h,l=u*c,v=u*h,b=e*h,m=o*i,d=o*c,x=o*h;return t[0]=1-(l+b),t[1]=M+x,t[2]=f-d,t[3]=0,t[4]=M-x,t[5]=1-(s+b),t[6]=v+m,t[7]=0,t[8]=f+d,t[9]=v-m,t[10]=1-(s+l),t[11]=0,t[12]=a[0],t[13]=a[1],t[14]=a[2],t[15]=1,t}function R(t,n){return t[0]=n[12],t[1]=n[13],t[2]=n[14],t}function z(t,n){var a=n[0],r=n[1],u=n[2],e=n[4],o=n[5],i=n[6],c=n[8],h=n[9],s=n[10];return t[0]=Math.hypot(a,r,u),t[1]=Math.hypot(e,o,i),t[2]=Math.hypot(c,h,s),t}function P(t,n){var r=new a(3);z(r,n);var u=1/r[0],e=1/r[1],o=1/r[2],i=n[0]*u,c=n[1]*e,h=n[2]*o,s=n[4]*u,M=n[5]*e,f=n[6]*o,l=n[8]*u,v=n[9]*e,b=n[10]*o,m=i+M+b,d=0;return m>0?(d=2*Math.sqrt(m+1),t[3]=.25*d,t[0]=(f-v)/d,t[1]=(l-h)/d,t[2]=(c-s)/d):i>M&&i>b?(d=2*Math.sqrt(1+i-M-b),t[3]=(f-v)/d,t[0]=.25*d,t[1]=(c+s)/d,t[2]=(l+h)/d):M>b?(d=2*Math.sqrt(1+M-i-b),t[3]=(l-h)/d,t[0]=(c+s)/d,t[1]=.25*d,t[2]=(f+v)/d):(d=2*Math.sqrt(1+b-i-M),t[3]=(c-s)/d,t[0]=(l+h)/d,t[1]=(f+v)/d,t[2]=.25*d),t}function j(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t[4]=n[4]-a[4],t[5]=n[5]-a[5],t[6]=n[6]-a[6],t[7]=n[7]-a[7],t[8]=n[8]-a[8],t[9]=n[9]-a[9],t[10]=n[10]-a[10],t[11]=n[11]-a[11],t[12]=n[12]-a[12],t[13]=n[13]-a[13],t[14]=n[14]-a[14],t[15]=n[15]-a[15],t}var I=A,S=j,E=Object.freeze({create:function(){var t=new a(16);return a!=Float32Array&&(t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0),t[0]=1,t[5]=1,t[10]=1,t[15]=1,t},clone:function(t){var n=new a(16);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n[9]=t[9],n[10]=t[10],n[11]=t[11],n[12]=t[12],n[13]=t[13],n[14]=t[14],n[15]=t[15],n},copy:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],t},fromValues:function(t,n,r,u,e,o,i,c,h,s,M,f,l,v,b,m){var d=new a(16);return d[0]=t,d[1]=n,d[2]=r,d[3]=u,d[4]=e,d[5]=o,d[6]=i,d[7]=c,d[8]=h,d[9]=s,d[10]=M,d[11]=f,d[12]=l,d[13]=v,d[14]=b,d[15]=m,d},set:function(t,n,a,r,u,e,o,i,c,h,s,M,f,l,v,b,m){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t[6]=i,t[7]=c,t[8]=h,t[9]=s,t[10]=M,t[11]=f,t[12]=l,t[13]=v,t[14]=b,t[15]=m,t},identity:g,transpose:function(t,n){if(t===n){var a=n[1],r=n[2],u=n[3],e=n[6],o=n[7],i=n[11];t[1]=n[4],t[2]=n[8],t[3]=n[12],t[4]=a,t[6]=n[9],t[7]=n[13],t[8]=r,t[9]=e,t[11]=n[14],t[12]=u,t[13]=o,t[14]=i}else t[0]=n[0],t[1]=n[4],t[2]=n[8],t[3]=n[12],t[4]=n[1],t[5]=n[5],t[6]=n[9],t[7]=n[13],t[8]=n[2],t[9]=n[6],t[10]=n[10],t[11]=n[14],t[12]=n[3],t[13]=n[7],t[14]=n[11],t[15]=n[15];return t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],c=n[6],h=n[7],s=n[8],M=n[9],f=n[10],l=n[11],v=n[12],b=n[13],m=n[14],d=n[15],x=a*i-r*o,p=a*c-u*o,y=a*h-e*o,q=r*c-u*i,g=r*h-e*i,A=u*h-e*c,w=s*b-M*v,R=s*m-f*v,z=s*d-l*v,P=M*m-f*b,j=M*d-l*b,I=f*d-l*m,S=x*I-p*j+y*P+q*z-g*R+A*w;return S?(S=1/S,t[0]=(i*I-c*j+h*P)*S,t[1]=(u*j-r*I-e*P)*S,t[2]=(b*A-m*g+d*q)*S,t[3]=(f*g-M*A-l*q)*S,t[4]=(c*z-o*I-h*R)*S,t[5]=(a*I-u*z+e*R)*S,t[6]=(m*y-v*A-d*p)*S,t[7]=(s*A-f*y+l*p)*S,t[8]=(o*j-i*z+h*w)*S,t[9]=(r*z-a*j-e*w)*S,t[10]=(v*g-b*y+d*x)*S,t[11]=(M*y-s*g-l*x)*S,t[12]=(i*R-o*P-c*w)*S,t[13]=(a*P-r*R+u*w)*S,t[14]=(b*p-v*q-m*x)*S,t[15]=(s*q-M*p+f*x)*S,t):null},adjoint:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],c=n[6],h=n[7],s=n[8],M=n[9],f=n[10],l=n[11],v=n[12],b=n[13],m=n[14],d=n[15];return t[0]=i*(f*d-l*m)-M*(c*d-h*m)+b*(c*l-h*f),t[1]=-(r*(f*d-l*m)-M*(u*d-e*m)+b*(u*l-e*f)),t[2]=r*(c*d-h*m)-i*(u*d-e*m)+b*(u*h-e*c),t[3]=-(r*(c*l-h*f)-i*(u*l-e*f)+M*(u*h-e*c)),t[4]=-(o*(f*d-l*m)-s*(c*d-h*m)+v*(c*l-h*f)),t[5]=a*(f*d-l*m)-s*(u*d-e*m)+v*(u*l-e*f),t[6]=-(a*(c*d-h*m)-o*(u*d-e*m)+v*(u*h-e*c)),t[7]=a*(c*l-h*f)-o*(u*l-e*f)+s*(u*h-e*c),t[8]=o*(M*d-l*b)-s*(i*d-h*b)+v*(i*l-h*M),t[9]=-(a*(M*d-l*b)-s*(r*d-e*b)+v*(r*l-e*M)),t[10]=a*(i*d-h*b)-o*(r*d-e*b)+v*(r*h-e*i),t[11]=-(a*(i*l-h*M)-o*(r*l-e*M)+s*(r*h-e*i)),t[12]=-(o*(M*m-f*b)-s*(i*m-c*b)+v*(i*f-c*M)),t[13]=a*(M*m-f*b)-s*(r*m-u*b)+v*(r*f-u*M),t[14]=-(a*(i*m-c*b)-o*(r*m-u*b)+v*(r*c-u*i)),t[15]=a*(i*f-c*M)-o*(r*f-u*M)+s*(r*c-u*i),t},determinant:function(t){var n=t[0],a=t[1],r=t[2],u=t[3],e=t[4],o=t[5],i=t[6],c=t[7],h=t[8],s=t[9],M=t[10],f=t[11],l=t[12],v=t[13],b=t[14],m=t[15];return(n*o-a*e)*(M*m-f*b)-(n*i-r*e)*(s*m-f*v)+(n*c-u*e)*(s*b-M*v)+(a*i-r*o)*(h*m-f*l)-(a*c-u*o)*(h*b-M*l)+(r*c-u*i)*(h*v-s*l)},multiply:A,translate:function(t,n,a){var r,u,e,o,i,c,h,s,M,f,l,v,b=a[0],m=a[1],d=a[2];return n===t?(t[12]=n[0]*b+n[4]*m+n[8]*d+n[12],t[13]=n[1]*b+n[5]*m+n[9]*d+n[13],t[14]=n[2]*b+n[6]*m+n[10]*d+n[14],t[15]=n[3]*b+n[7]*m+n[11]*d+n[15]):(r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=n[6],s=n[7],M=n[8],f=n[9],l=n[10],v=n[11],t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=i,t[5]=c,t[6]=h,t[7]=s,t[8]=M,t[9]=f,t[10]=l,t[11]=v,t[12]=r*b+i*m+M*d+n[12],t[13]=u*b+c*m+f*d+n[13],t[14]=e*b+h*m+l*d+n[14],t[15]=o*b+s*m+v*d+n[15]),t},scale:function(t,n,a){var r=a[0],u=a[1],e=a[2];return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=n[3]*r,t[4]=n[4]*u,t[5]=n[5]*u,t[6]=n[6]*u,t[7]=n[7]*u,t[8]=n[8]*e,t[9]=n[9]*e,t[10]=n[10]*e,t[11]=n[11]*e,t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],t},rotate:function(t,a,r,u){var e,o,i,c,h,s,M,f,l,v,b,m,d,x,p,y,q,g,A,w,R,z,P,j,I=u[0],S=u[1],E=u[2],O=Math.hypot(I,S,E);return O0?(r[0]=2*(c*i+M*u+h*o-s*e)/f,r[1]=2*(h*i+M*e+s*u-c*o)/f,r[2]=2*(s*i+M*o+c*e-h*u)/f):(r[0]=2*(c*i+M*u+h*o-s*e),r[1]=2*(h*i+M*e+s*u-c*o),r[2]=2*(s*i+M*o+c*e-h*u)),w(t,n,r),t},getTranslation:R,getScaling:z,getRotation:P,fromRotationTranslationScale:function(t,n,a,r){var u=n[0],e=n[1],o=n[2],i=n[3],c=u+u,h=e+e,s=o+o,M=u*c,f=u*h,l=u*s,v=e*h,b=e*s,m=o*s,d=i*c,x=i*h,p=i*s,y=r[0],q=r[1],g=r[2];return t[0]=(1-(v+m))*y,t[1]=(f+p)*y,t[2]=(l-x)*y,t[3]=0,t[4]=(f-p)*q,t[5]=(1-(M+m))*q,t[6]=(b+d)*q,t[7]=0,t[8]=(l+x)*g,t[9]=(b-d)*g,t[10]=(1-(M+v))*g,t[11]=0,t[12]=a[0],t[13]=a[1],t[14]=a[2],t[15]=1,t},fromRotationTranslationScaleOrigin:function(t,n,a,r,u){var e=n[0],o=n[1],i=n[2],c=n[3],h=e+e,s=o+o,M=i+i,f=e*h,l=e*s,v=e*M,b=o*s,m=o*M,d=i*M,x=c*h,p=c*s,y=c*M,q=r[0],g=r[1],A=r[2],w=u[0],R=u[1],z=u[2],P=(1-(b+d))*q,j=(l+y)*q,I=(v-p)*q,S=(l-y)*g,E=(1-(f+d))*g,O=(m+x)*g,T=(v+p)*A,D=(m-x)*A,F=(1-(f+b))*A;return t[0]=P,t[1]=j,t[2]=I,t[3]=0,t[4]=S,t[5]=E,t[6]=O,t[7]=0,t[8]=T,t[9]=D,t[10]=F,t[11]=0,t[12]=a[0]+w-(P*w+S*R+T*z),t[13]=a[1]+R-(j*w+E*R+D*z),t[14]=a[2]+z-(I*w+O*R+F*z),t[15]=1,t},fromQuat:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a+a,i=r+r,c=u+u,h=a*o,s=r*o,M=r*i,f=u*o,l=u*i,v=u*c,b=e*o,m=e*i,d=e*c;return t[0]=1-M-v,t[1]=s+d,t[2]=f-m,t[3]=0,t[4]=s-d,t[5]=1-h-v,t[6]=l+b,t[7]=0,t[8]=f+m,t[9]=l-b,t[10]=1-h-M,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},frustum:function(t,n,a,r,u,e,o){var i=1/(a-n),c=1/(u-r),h=1/(e-o);return t[0]=2*e*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=2*e*c,t[6]=0,t[7]=0,t[8]=(a+n)*i,t[9]=(u+r)*c,t[10]=(o+e)*h,t[11]=-1,t[12]=0,t[13]=0,t[14]=o*e*2*h,t[15]=0,t},perspective:function(t,n,a,r,u){var e,o=1/Math.tan(n/2);return t[0]=o/a,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=o,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=-1,t[12]=0,t[13]=0,t[15]=0,null!=u&&u!==1/0?(e=1/(r-u),t[10]=(u+r)*e,t[14]=2*u*r*e):(t[10]=-1,t[14]=-2*r),t},perspectiveFromFieldOfView:function(t,n,a,r){var u=Math.tan(n.upDegrees*Math.PI/180),e=Math.tan(n.downDegrees*Math.PI/180),o=Math.tan(n.leftDegrees*Math.PI/180),i=Math.tan(n.rightDegrees*Math.PI/180),c=2/(o+i),h=2/(u+e);return t[0]=c,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=h,t[6]=0,t[7]=0,t[8]=-(o-i)*c*.5,t[9]=(u-e)*h*.5,t[10]=r/(a-r),t[11]=-1,t[12]=0,t[13]=0,t[14]=r*a/(a-r),t[15]=0,t},ortho:function(t,n,a,r,u,e,o){var i=1/(n-a),c=1/(r-u),h=1/(e-o);return t[0]=-2*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*c,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*h,t[11]=0,t[12]=(n+a)*i,t[13]=(u+r)*c,t[14]=(o+e)*h,t[15]=1,t},lookAt:function(t,a,r,u){var e,o,i,c,h,s,M,f,l,v,b=a[0],m=a[1],d=a[2],x=u[0],p=u[1],y=u[2],q=r[0],A=r[1],w=r[2];return Math.abs(b-q)0&&(s*=l=1/Math.sqrt(l),M*=l,f*=l);var v=c*f-h*M,b=h*s-i*f,m=i*M-c*s;return(l=v*v+b*b+m*m)>0&&(v*=l=1/Math.sqrt(l),b*=l,m*=l),t[0]=v,t[1]=b,t[2]=m,t[3]=0,t[4]=M*m-f*b,t[5]=f*v-s*m,t[6]=s*b-M*v,t[7]=0,t[8]=s,t[9]=M,t[10]=f,t[11]=0,t[12]=u,t[13]=e,t[14]=o,t[15]=1,t},str:function(t){return"mat4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+", "+t[9]+", "+t[10]+", "+t[11]+", "+t[12]+", "+t[13]+", "+t[14]+", "+t[15]+")"},frob:function(t){return Math.hypot(t[0],t[1],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15])},add:function(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t[4]=n[4]+a[4],t[5]=n[5]+a[5],t[6]=n[6]+a[6],t[7]=n[7]+a[7],t[8]=n[8]+a[8],t[9]=n[9]+a[9],t[10]=n[10]+a[10],t[11]=n[11]+a[11],t[12]=n[12]+a[12],t[13]=n[13]+a[13],t[14]=n[14]+a[14],t[15]=n[15]+a[15],t},subtract:j,multiplyScalar:function(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*a,t[5]=n[5]*a,t[6]=n[6]*a,t[7]=n[7]*a,t[8]=n[8]*a,t[9]=n[9]*a,t[10]=n[10]*a,t[11]=n[11]*a,t[12]=n[12]*a,t[13]=n[13]*a,t[14]=n[14]*a,t[15]=n[15]*a,t},multiplyScalarAndAdd:function(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t[4]=n[4]+a[4]*r,t[5]=n[5]+a[5]*r,t[6]=n[6]+a[6]*r,t[7]=n[7]+a[7]*r,t[8]=n[8]+a[8]*r,t[9]=n[9]+a[9]*r,t[10]=n[10]+a[10]*r,t[11]=n[11]+a[11]*r,t[12]=n[12]+a[12]*r,t[13]=n[13]+a[13]*r,t[14]=n[14]+a[14]*r,t[15]=n[15]+a[15]*r,t},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]&&t[9]===n[9]&&t[10]===n[10]&&t[11]===n[11]&&t[12]===n[12]&&t[13]===n[13]&&t[14]===n[14]&&t[15]===n[15]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=t[4],c=t[5],h=t[6],s=t[7],M=t[8],f=t[9],l=t[10],v=t[11],b=t[12],m=t[13],d=t[14],x=t[15],p=a[0],y=a[1],q=a[2],g=a[3],A=a[4],w=a[5],R=a[6],z=a[7],P=a[8],j=a[9],I=a[10],S=a[11],E=a[12],O=a[13],T=a[14],D=a[15];return Math.abs(r-p)<=n*Math.max(1,Math.abs(r),Math.abs(p))&&Math.abs(u-y)<=n*Math.max(1,Math.abs(u),Math.abs(y))&&Math.abs(e-q)<=n*Math.max(1,Math.abs(e),Math.abs(q))&&Math.abs(o-g)<=n*Math.max(1,Math.abs(o),Math.abs(g))&&Math.abs(i-A)<=n*Math.max(1,Math.abs(i),Math.abs(A))&&Math.abs(c-w)<=n*Math.max(1,Math.abs(c),Math.abs(w))&&Math.abs(h-R)<=n*Math.max(1,Math.abs(h),Math.abs(R))&&Math.abs(s-z)<=n*Math.max(1,Math.abs(s),Math.abs(z))&&Math.abs(M-P)<=n*Math.max(1,Math.abs(M),Math.abs(P))&&Math.abs(f-j)<=n*Math.max(1,Math.abs(f),Math.abs(j))&&Math.abs(l-I)<=n*Math.max(1,Math.abs(l),Math.abs(I))&&Math.abs(v-S)<=n*Math.max(1,Math.abs(v),Math.abs(S))&&Math.abs(b-E)<=n*Math.max(1,Math.abs(b),Math.abs(E))&&Math.abs(m-O)<=n*Math.max(1,Math.abs(m),Math.abs(O))&&Math.abs(d-T)<=n*Math.max(1,Math.abs(d),Math.abs(T))&&Math.abs(x-D)<=n*Math.max(1,Math.abs(x),Math.abs(D))},mul:I,sub:S});function O(){var t=new a(3);return a!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t}function T(t){var n=t[0],a=t[1],r=t[2];return Math.hypot(n,a,r)}function D(t,n,r){var u=new a(3);return u[0]=t,u[1]=n,u[2]=r,u}function F(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t}function L(t,n,a){return t[0]=n[0]*a[0],t[1]=n[1]*a[1],t[2]=n[2]*a[2],t}function V(t,n,a){return t[0]=n[0]/a[0],t[1]=n[1]/a[1],t[2]=n[2]/a[2],t}function Q(t,n){var a=n[0]-t[0],r=n[1]-t[1],u=n[2]-t[2];return Math.hypot(a,r,u)}function Y(t,n){var a=n[0]-t[0],r=n[1]-t[1],u=n[2]-t[2];return a*a+r*r+u*u}function X(t){var n=t[0],a=t[1],r=t[2];return n*n+a*a+r*r}function Z(t,n){var a=n[0],r=n[1],u=n[2],e=a*a+r*r+u*u;return e>0&&(e=1/Math.sqrt(e)),t[0]=n[0]*e,t[1]=n[1]*e,t[2]=n[2]*e,t}function _(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function B(t,n,a){var r=n[0],u=n[1],e=n[2],o=a[0],i=a[1],c=a[2];return t[0]=u*c-e*i,t[1]=e*o-r*c,t[2]=r*i-u*o,t}var N,k=F,U=L,W=V,C=Q,G=Y,H=T,J=X,K=(N=O(),function(t,n,a,r,u,e){var o,i;for(n||(n=3),a||(a=0),i=r?Math.min(r*n+a,t.length):t.length,o=a;o1?0:u<-1?Math.PI:Math.acos(u)},zero:function(t){return t[0]=0,t[1]=0,t[2]=0,t},str:function(t){return"vec3("+t[0]+", "+t[1]+", "+t[2]+")"},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=a[0],i=a[1],c=a[2];return Math.abs(r-o)<=n*Math.max(1,Math.abs(r),Math.abs(o))&&Math.abs(u-i)<=n*Math.max(1,Math.abs(u),Math.abs(i))&&Math.abs(e-c)<=n*Math.max(1,Math.abs(e),Math.abs(c))},sub:k,mul:U,div:W,dist:C,sqrDist:G,len:H,sqrLen:J,forEach:K});function tt(){var t=new a(4);return a!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0,t[3]=0),t}function nt(t){var n=new a(4);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n}function at(t,n,r,u){var e=new a(4);return e[0]=t,e[1]=n,e[2]=r,e[3]=u,e}function rt(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t}function ut(t,n,a,r,u){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t}function et(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t}function ot(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t}function it(t,n,a){return t[0]=n[0]*a[0],t[1]=n[1]*a[1],t[2]=n[2]*a[2],t[3]=n[3]*a[3],t}function ct(t,n,a){return t[0]=n[0]/a[0],t[1]=n[1]/a[1],t[2]=n[2]/a[2],t[3]=n[3]/a[3],t}function ht(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t}function st(t,n){var a=n[0]-t[0],r=n[1]-t[1],u=n[2]-t[2],e=n[3]-t[3];return Math.hypot(a,r,u,e)}function Mt(t,n){var a=n[0]-t[0],r=n[1]-t[1],u=n[2]-t[2],e=n[3]-t[3];return a*a+r*r+u*u+e*e}function ft(t){var n=t[0],a=t[1],r=t[2],u=t[3];return Math.hypot(n,a,r,u)}function lt(t){var n=t[0],a=t[1],r=t[2],u=t[3];return n*n+a*a+r*r+u*u}function vt(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a*a+r*r+u*u+e*e;return o>0&&(o=1/Math.sqrt(o)),t[0]=a*o,t[1]=r*o,t[2]=u*o,t[3]=e*o,t}function bt(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]+t[3]*n[3]}function mt(t,n,a,r){var u=n[0],e=n[1],o=n[2],i=n[3];return t[0]=u+r*(a[0]-u),t[1]=e+r*(a[1]-e),t[2]=o+r*(a[2]-o),t[3]=i+r*(a[3]-i),t}function dt(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]}function xt(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=a[0],c=a[1],h=a[2],s=a[3];return Math.abs(r-i)<=n*Math.max(1,Math.abs(r),Math.abs(i))&&Math.abs(u-c)<=n*Math.max(1,Math.abs(u),Math.abs(c))&&Math.abs(e-h)<=n*Math.max(1,Math.abs(e),Math.abs(h))&&Math.abs(o-s)<=n*Math.max(1,Math.abs(o),Math.abs(s))}var pt=ot,yt=it,qt=ct,gt=st,At=Mt,wt=ft,Rt=lt,zt=function(){var t=tt();return function(n,a,r,u,e,o){var i,c;for(a||(a=4),r||(r=0),c=u?Math.min(u*a+r,n.length):n.length,i=r;i=1);do{c=(e=2*r()-1)*e+(o=2*r()-1)*o}while(c>=1);var h=Math.sqrt((1-i)/c);return t[0]=n*a,t[1]=n*u,t[2]=n*e*h,t[3]=n*o*h,t},transformMat4:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3];return t[0]=a[0]*r+a[4]*u+a[8]*e+a[12]*o,t[1]=a[1]*r+a[5]*u+a[9]*e+a[13]*o,t[2]=a[2]*r+a[6]*u+a[10]*e+a[14]*o,t[3]=a[3]*r+a[7]*u+a[11]*e+a[15]*o,t},transformQuat:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=a[0],i=a[1],c=a[2],h=a[3],s=h*r+i*e-c*u,M=h*u+c*r-o*e,f=h*e+o*u-i*r,l=-o*r-i*u-c*e;return t[0]=s*h+l*-o+M*-c-f*-i,t[1]=M*h+l*-i+f*-o-s*-c,t[2]=f*h+l*-c+s*-i-M*-o,t[3]=n[3],t},zero:function(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=0,t},str:function(t){return"vec4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},exactEquals:dt,equals:xt,sub:pt,mul:yt,div:qt,dist:gt,sqrDist:At,len:wt,sqrLen:Rt,forEach:zt});function jt(){var t=new a(4);return a!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t[3]=1,t}function It(t,n,a){a*=.5;var r=Math.sin(a);return t[0]=r*n[0],t[1]=r*n[1],t[2]=r*n[2],t[3]=Math.cos(a),t}function St(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],c=a[1],h=a[2],s=a[3];return t[0]=r*s+o*i+u*h-e*c,t[1]=u*s+o*c+e*i-r*h,t[2]=e*s+o*h+r*c-u*i,t[3]=o*s-r*i-u*c-e*h,t}function Et(t,n,a){a*=.5;var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),c=Math.cos(a);return t[0]=r*c+o*i,t[1]=u*c+e*i,t[2]=e*c-u*i,t[3]=o*c-r*i,t}function Ot(t,n,a){a*=.5;var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),c=Math.cos(a);return t[0]=r*c-e*i,t[1]=u*c+o*i,t[2]=e*c+r*i,t[3]=o*c-u*i,t}function Tt(t,n,a){a*=.5;var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),c=Math.cos(a);return t[0]=r*c+u*i,t[1]=u*c-r*i,t[2]=e*c+o*i,t[3]=o*c-e*i,t}function Dt(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=Math.sqrt(a*a+r*r+u*u),i=Math.exp(e),c=o>0?i*Math.sin(o)/o:0;return t[0]=a*c,t[1]=r*c,t[2]=u*c,t[3]=i*Math.cos(o),t}function Ft(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=Math.sqrt(a*a+r*r+u*u),i=o>0?Math.atan2(o,e)/o:0;return t[0]=a*i,t[1]=r*i,t[2]=u*i,t[3]=.5*Math.log(a*a+r*r+u*u+e*e),t}function Lt(t,a,r,u){var e,o,i,c,h,s=a[0],M=a[1],f=a[2],l=a[3],v=r[0],b=r[1],m=r[2],d=r[3];return(o=s*v+M*b+f*m+l*d)<0&&(o=-o,v=-v,b=-b,m=-m,d=-d),1-o>n?(e=Math.acos(o),i=Math.sin(e),c=Math.sin((1-u)*e)/i,h=Math.sin(u*e)/i):(c=1-u,h=u),t[0]=c*s+h*v,t[1]=c*M+h*b,t[2]=c*f+h*m,t[3]=c*l+h*d,t}function Vt(t,n){var a,r=n[0]+n[4]+n[8];if(r>0)a=Math.sqrt(r+1),t[3]=.5*a,a=.5/a,t[0]=(n[5]-n[7])*a,t[1]=(n[6]-n[2])*a,t[2]=(n[1]-n[3])*a;else{var u=0;n[4]>n[0]&&(u=1),n[8]>n[3*u+u]&&(u=2);var e=(u+1)%3,o=(u+2)%3;a=Math.sqrt(n[3*u+u]-n[3*e+e]-n[3*o+o]+1),t[u]=.5*a,a=.5/a,t[3]=(n[3*e+o]-n[3*o+e])*a,t[e]=(n[3*e+u]+n[3*u+e])*a,t[o]=(n[3*o+u]+n[3*u+o])*a}return t}var Qt,Yt,Xt,Zt,_t,Bt,Nt=nt,kt=at,Ut=rt,Wt=ut,Ct=et,Gt=St,Ht=ht,Jt=bt,Kt=mt,$t=ft,tn=$t,nn=lt,an=nn,rn=vt,un=dt,en=xt,on=(Qt=O(),Yt=D(1,0,0),Xt=D(0,1,0),function(t,n,a){var r=_(n,a);return r<-.999999?(B(Qt,Yt,n),H(Qt)<1e-6&&B(Qt,Xt,n),Z(Qt,Qt),It(t,Qt,Math.PI),t):r>.999999?(t[0]=0,t[1]=0,t[2]=0,t[3]=1,t):(B(Qt,n,a),t[0]=Qt[0],t[1]=Qt[1],t[2]=Qt[2],t[3]=1+r,rn(t,t))}),cn=(Zt=jt(),_t=jt(),function(t,n,a,r,u,e){return Lt(Zt,n,u,e),Lt(_t,a,r,e),Lt(t,Zt,_t,2*e*(1-e)),t}),hn=(Bt=m(),function(t,n,a,r){return Bt[0]=a[0],Bt[3]=a[1],Bt[6]=a[2],Bt[1]=r[0],Bt[4]=r[1],Bt[7]=r[2],Bt[2]=-n[0],Bt[5]=-n[1],Bt[8]=-n[2],rn(t,Vt(t,Bt))}),sn=Object.freeze({create:jt,identity:function(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t},setAxisAngle:It,getAxisAngle:function(t,a){var r=2*Math.acos(a[3]),u=Math.sin(r/2);return u>n?(t[0]=a[0]/u,t[1]=a[1]/u,t[2]=a[2]/u):(t[0]=1,t[1]=0,t[2]=0),r},getAngle:function(t,n){var a=Jt(t,n);return Math.acos(2*a*a-1)},multiply:St,rotateX:Et,rotateY:Ot,rotateZ:Tt,calculateW:function(t,n){var a=n[0],r=n[1],u=n[2];return t[0]=a,t[1]=r,t[2]=u,t[3]=Math.sqrt(Math.abs(1-a*a-r*r-u*u)),t},exp:Dt,ln:Ft,pow:function(t,n,a){return Ft(t,n),Ht(t,t,a),Dt(t,t),t},slerp:Lt,random:function(t){var n=r(),a=r(),u=r(),e=Math.sqrt(1-n),o=Math.sqrt(n);return t[0]=e*Math.sin(2*Math.PI*a),t[1]=e*Math.cos(2*Math.PI*a),t[2]=o*Math.sin(2*Math.PI*u),t[3]=o*Math.cos(2*Math.PI*u),t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a*a+r*r+u*u+e*e,i=o?1/o:0;return t[0]=-a*i,t[1]=-r*i,t[2]=-u*i,t[3]=e*i,t},conjugate:function(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t[3]=n[3],t},fromMat3:Vt,fromEuler:function(t,n,a,r){var u=.5*Math.PI/180;n*=u,a*=u,r*=u;var e=Math.sin(n),o=Math.cos(n),i=Math.sin(a),c=Math.cos(a),h=Math.sin(r),s=Math.cos(r);return t[0]=e*c*s-o*i*h,t[1]=o*i*s+e*c*h,t[2]=o*c*h-e*i*s,t[3]=o*c*s+e*i*h,t},str:function(t){return"quat("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},clone:Nt,fromValues:kt,copy:Ut,set:Wt,add:Ct,mul:Gt,scale:Ht,dot:Jt,lerp:Kt,length:$t,len:tn,squaredLength:nn,sqrLen:an,normalize:rn,exactEquals:un,equals:en,rotationTo:on,sqlerp:cn,setAxes:hn});function Mn(t,n,a){var r=.5*a[0],u=.5*a[1],e=.5*a[2],o=n[0],i=n[1],c=n[2],h=n[3];return t[0]=o,t[1]=i,t[2]=c,t[3]=h,t[4]=r*h+u*c-e*i,t[5]=u*h+e*o-r*c,t[6]=e*h+r*i-u*o,t[7]=-r*o-u*i-e*c,t}function fn(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t}var ln=Ut;var vn=Ut;function bn(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[4],c=a[5],h=a[6],s=a[7],M=n[4],f=n[5],l=n[6],v=n[7],b=a[0],m=a[1],d=a[2],x=a[3];return t[0]=r*x+o*b+u*d-e*m,t[1]=u*x+o*m+e*b-r*d,t[2]=e*x+o*d+r*m-u*b,t[3]=o*x-r*b-u*m-e*d,t[4]=r*s+o*i+u*h-e*c+M*x+v*b+f*d-l*m,t[5]=u*s+o*c+e*i-r*h+f*x+v*m+l*b-M*d,t[6]=e*s+o*h+r*c-u*i+l*x+v*d+M*m-f*b,t[7]=o*s-r*i-u*c-e*h+v*x-M*b-f*m-l*d,t}var mn=bn;var dn=Jt;var xn=$t,pn=xn,yn=nn,qn=yn;var gn=Object.freeze({create:function(){var t=new a(8);return a!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0,t[4]=0,t[5]=0,t[6]=0,t[7]=0),t[3]=1,t},clone:function(t){var n=new a(8);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n},fromValues:function(t,n,r,u,e,o,i,c){var h=new a(8);return h[0]=t,h[1]=n,h[2]=r,h[3]=u,h[4]=e,h[5]=o,h[6]=i,h[7]=c,h},fromRotationTranslationValues:function(t,n,r,u,e,o,i){var c=new a(8);c[0]=t,c[1]=n,c[2]=r,c[3]=u;var h=.5*e,s=.5*o,M=.5*i;return c[4]=h*u+s*r-M*n,c[5]=s*u+M*t-h*r,c[6]=M*u+h*n-s*t,c[7]=-h*t-s*n-M*r,c},fromRotationTranslation:Mn,fromTranslation:function(t,n){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t[4]=.5*n[0],t[5]=.5*n[1],t[6]=.5*n[2],t[7]=0,t},fromRotation:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=0,t[5]=0,t[6]=0,t[7]=0,t},fromMat4:function(t,n){var r=jt();P(r,n);var u=new a(3);return R(u,n),Mn(t,r,u),t},copy:fn,identity:function(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t[6]=0,t[7]=0,t},set:function(t,n,a,r,u,e,o,i,c){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t[6]=i,t[7]=c,t},getReal:ln,getDual:function(t,n){return t[0]=n[4],t[1]=n[5],t[2]=n[6],t[3]=n[7],t},setReal:vn,setDual:function(t,n){return t[4]=n[0],t[5]=n[1],t[6]=n[2],t[7]=n[3],t},getTranslation:function(t,n){var a=n[4],r=n[5],u=n[6],e=n[7],o=-n[0],i=-n[1],c=-n[2],h=n[3];return t[0]=2*(a*h+e*o+r*c-u*i),t[1]=2*(r*h+e*i+u*o-a*c),t[2]=2*(u*h+e*c+a*i-r*o),t},translate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=.5*a[0],c=.5*a[1],h=.5*a[2],s=n[4],M=n[5],f=n[6],l=n[7];return t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=o*i+u*h-e*c+s,t[5]=o*c+e*i-r*h+M,t[6]=o*h+r*c-u*i+f,t[7]=-r*i-u*c-e*h+l,t},rotateX:function(t,n,a){var r=-n[0],u=-n[1],e=-n[2],o=n[3],i=n[4],c=n[5],h=n[6],s=n[7],M=i*o+s*r+c*e-h*u,f=c*o+s*u+h*r-i*e,l=h*o+s*e+i*u-c*r,v=s*o-i*r-c*u-h*e;return Et(t,n,a),r=t[0],u=t[1],e=t[2],o=t[3],t[4]=M*o+v*r+f*e-l*u,t[5]=f*o+v*u+l*r-M*e,t[6]=l*o+v*e+M*u-f*r,t[7]=v*o-M*r-f*u-l*e,t},rotateY:function(t,n,a){var r=-n[0],u=-n[1],e=-n[2],o=n[3],i=n[4],c=n[5],h=n[6],s=n[7],M=i*o+s*r+c*e-h*u,f=c*o+s*u+h*r-i*e,l=h*o+s*e+i*u-c*r,v=s*o-i*r-c*u-h*e;return Ot(t,n,a),r=t[0],u=t[1],e=t[2],o=t[3],t[4]=M*o+v*r+f*e-l*u,t[5]=f*o+v*u+l*r-M*e,t[6]=l*o+v*e+M*u-f*r,t[7]=v*o-M*r-f*u-l*e,t},rotateZ:function(t,n,a){var r=-n[0],u=-n[1],e=-n[2],o=n[3],i=n[4],c=n[5],h=n[6],s=n[7],M=i*o+s*r+c*e-h*u,f=c*o+s*u+h*r-i*e,l=h*o+s*e+i*u-c*r,v=s*o-i*r-c*u-h*e;return Tt(t,n,a),r=t[0],u=t[1],e=t[2],o=t[3],t[4]=M*o+v*r+f*e-l*u,t[5]=f*o+v*u+l*r-M*e,t[6]=l*o+v*e+M*u-f*r,t[7]=v*o-M*r-f*u-l*e,t},rotateByQuatAppend:function(t,n,a){var r=a[0],u=a[1],e=a[2],o=a[3],i=n[0],c=n[1],h=n[2],s=n[3];return t[0]=i*o+s*r+c*e-h*u,t[1]=c*o+s*u+h*r-i*e,t[2]=h*o+s*e+i*u-c*r,t[3]=s*o-i*r-c*u-h*e,i=n[4],c=n[5],h=n[6],s=n[7],t[4]=i*o+s*r+c*e-h*u,t[5]=c*o+s*u+h*r-i*e,t[6]=h*o+s*e+i*u-c*r,t[7]=s*o-i*r-c*u-h*e,t},rotateByQuatPrepend:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],c=a[1],h=a[2],s=a[3];return t[0]=r*s+o*i+u*h-e*c,t[1]=u*s+o*c+e*i-r*h,t[2]=e*s+o*h+r*c-u*i,t[3]=o*s-r*i-u*c-e*h,i=a[4],c=a[5],h=a[6],s=a[7],t[4]=r*s+o*i+u*h-e*c,t[5]=u*s+o*c+e*i-r*h,t[6]=e*s+o*h+r*c-u*i,t[7]=o*s-r*i-u*c-e*h,t},rotateAroundAxis:function(t,a,r,u){if(Math.abs(u)0){a=Math.sqrt(a);var r=n[0]/a,u=n[1]/a,e=n[2]/a,o=n[3]/a,i=n[4],c=n[5],h=n[6],s=n[7],M=r*i+u*c+e*h+o*s;t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=(i-r*M)/a,t[5]=(c-u*M)/a,t[6]=(h-e*M)/a,t[7]=(s-o*M)/a}return t},str:function(t){return"quat2("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+")"},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=t[4],c=t[5],h=t[6],s=t[7],M=a[0],f=a[1],l=a[2],v=a[3],b=a[4],m=a[5],d=a[6],x=a[7];return Math.abs(r-M)<=n*Math.max(1,Math.abs(r),Math.abs(M))&&Math.abs(u-f)<=n*Math.max(1,Math.abs(u),Math.abs(f))&&Math.abs(e-l)<=n*Math.max(1,Math.abs(e),Math.abs(l))&&Math.abs(o-v)<=n*Math.max(1,Math.abs(o),Math.abs(v))&&Math.abs(i-b)<=n*Math.max(1,Math.abs(i),Math.abs(b))&&Math.abs(c-m)<=n*Math.max(1,Math.abs(c),Math.abs(m))&&Math.abs(h-d)<=n*Math.max(1,Math.abs(h),Math.abs(d))&&Math.abs(s-x)<=n*Math.max(1,Math.abs(s),Math.abs(x))}});function An(){var t=new a(2);return a!=Float32Array&&(t[0]=0,t[1]=0),t}function wn(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t}function Rn(t,n,a){return t[0]=n[0]*a[0],t[1]=n[1]*a[1],t}function zn(t,n,a){return t[0]=n[0]/a[0],t[1]=n[1]/a[1],t}function Pn(t,n){var a=n[0]-t[0],r=n[1]-t[1];return Math.hypot(a,r)}function jn(t,n){var a=n[0]-t[0],r=n[1]-t[1];return a*a+r*r}function In(t){var n=t[0],a=t[1];return Math.hypot(n,a)}function Sn(t){var n=t[0],a=t[1];return n*n+a*a}var En=In,On=wn,Tn=Rn,Dn=zn,Fn=Pn,Ln=jn,Vn=Sn,Qn=function(){var t=An();return function(n,a,r,u,e,o){var i,c;for(a||(a=2),r||(r=0),c=u?Math.min(u*a+r,n.length):n.length,i=r;i0&&(u=1/Math.sqrt(u)),t[0]=n[0]*u,t[1]=n[1]*u,t},dot:function(t,n){return t[0]*n[0]+t[1]*n[1]},cross:function(t,n,a){var r=n[0]*a[1]-n[1]*a[0];return t[0]=t[1]=0,t[2]=r,t},lerp:function(t,n,a,r){var u=n[0],e=n[1];return t[0]=u+r*(a[0]-u),t[1]=e+r*(a[1]-e),t},random:function(t,n){n=n||1;var a=2*r()*Math.PI;return t[0]=Math.cos(a)*n,t[1]=Math.sin(a)*n,t},transformMat2:function(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[2]*u,t[1]=a[1]*r+a[3]*u,t},transformMat2d:function(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[2]*u+a[4],t[1]=a[1]*r+a[3]*u+a[5],t},transformMat3:function(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[3]*u+a[6],t[1]=a[1]*r+a[4]*u+a[7],t},transformMat4:function(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[4]*u+a[12],t[1]=a[1]*r+a[5]*u+a[13],t},rotate:function(t,n,a,r){var u=n[0]-a[0],e=n[1]-a[1],o=Math.sin(r),i=Math.cos(r);return t[0]=u*i-e*o+a[0],t[1]=u*o+e*i+a[1],t},angle:function(t,n){var a=t[0],r=t[1],u=n[0],e=n[1],o=a*a+r*r;o>0&&(o=1/Math.sqrt(o));var i=u*u+e*e;i>0&&(i=1/Math.sqrt(i));var c=(a*u+r*e)*o*i;return c>1?0:c<-1?Math.PI:Math.acos(c)},zero:function(t){return t[0]=0,t[1]=0,t},str:function(t){return"vec2("+t[0]+", "+t[1]+")"},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]},equals:function(t,a){var r=t[0],u=t[1],e=a[0],o=a[1];return Math.abs(r-e)<=n*Math.max(1,Math.abs(r),Math.abs(e))&&Math.abs(u-o)<=n*Math.max(1,Math.abs(u),Math.abs(o))},len:En,sub:On,mul:Tn,div:Dn,dist:Fn,sqrDist:Ln,sqrLen:Vn,forEach:Qn});t.glMatrix=e,t.mat2=s,t.mat2d=b,t.mat3=q,t.mat4=E,t.quat=sn,t.quat2=gn,t.vec2=Yn,t.vec3=$,t.vec4=Pt,Object.defineProperty(t,"__esModule",{value:!0})}); + +// ["glMatrix", "mat2", "mat2d", "mat3", "mat4", "quat", "quat2", "vec2", "vec3", "vec4"] +window.glMatrix = glMatrix; +window.mat2 = glMatrix.mat2; +window.mat2d = glMatrix.mat2d; +window.mat3 = glMatrix.mat3; +window.mat4 = glMatrix.mat4; +window.quat = glMatrix.quat; +window.quat2 = glMatrix.quat2; +window.vec2 = glMatrix.vec2; +window.vec3 = glMatrix.vec3; +window.vec4 = glMatrix.vec4; + + + +var CABLES = CABLES || {}; CABLES.build = {"timestamp":1671442325495,"created":"2022-12-19T09:32:05.495Z","git":{"branch":"master","commit":"9aa5acdd3f463ec28e2abce3963ff31d3eaf3926","date":null,"message":null}}; \ No newline at end of file diff --git a/survey_dashboard/hmc_layout/static/en_files/libs.core.min.js b/survey_dashboard/hmc_layout/static/en_files/libs.core.min.js new file mode 100644 index 0000000..af46eda --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/libs.core.min.js @@ -0,0 +1,44 @@ +/*! +@fileoverview gl-matrix - High performance matrix and vector operations +@author Brandon Jones +@author Colin MacKenzie IV +@version 3.1.0 + +Copyright (c) 2015-2019, Brandon Jones, Colin MacKenzie IV. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t=t||self).glMatrix={})}(this,function(t){"use strict";var n=1e-6,a="undefined"!=typeof Float32Array?Float32Array:Array,r=Math.random;var u=Math.PI/180;Math.hypot||(Math.hypot=function(){for(var t=0,n=arguments.length;n--;)t+=arguments[n]*arguments[n];return Math.sqrt(t)});var e=Object.freeze({EPSILON:n,get ARRAY_TYPE(){return a},RANDOM:r,setMatrixArrayType:function(t){a=t},toRadian:function(t){return t*u},equals:function(t,a){return Math.abs(t-a)<=n*Math.max(1,Math.abs(t),Math.abs(a))}});function o(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],c=a[1],h=a[2],s=a[3];return t[0]=r*i+e*c,t[1]=u*i+o*c,t[2]=r*h+e*s,t[3]=u*h+o*s,t}function i(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t}var c=o,h=i,s=Object.freeze({create:function(){var t=new a(4);return a!=Float32Array&&(t[1]=0,t[2]=0),t[0]=1,t[3]=1,t},clone:function(t){var n=new a(4);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n},copy:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t},identity:function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t},fromValues:function(t,n,r,u){var e=new a(4);return e[0]=t,e[1]=n,e[2]=r,e[3]=u,e},set:function(t,n,a,r,u){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t},transpose:function(t,n){if(t===n){var a=n[1];t[1]=n[2],t[2]=a}else t[0]=n[0],t[1]=n[2],t[2]=n[1],t[3]=n[3];return t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a*e-u*r;return o?(o=1/o,t[0]=e*o,t[1]=-r*o,t[2]=-u*o,t[3]=a*o,t):null},adjoint:function(t,n){var a=n[0];return t[0]=n[3],t[1]=-n[1],t[2]=-n[2],t[3]=a,t},determinant:function(t){return t[0]*t[3]-t[2]*t[1]},multiply:o,rotate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),c=Math.cos(a);return t[0]=r*c+e*i,t[1]=u*c+o*i,t[2]=r*-i+e*c,t[3]=u*-i+o*c,t},scale:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],c=a[1];return t[0]=r*i,t[1]=u*i,t[2]=e*c,t[3]=o*c,t},fromRotation:function(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=a,t[2]=-a,t[3]=r,t},fromScaling:function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=n[1],t},str:function(t){return"mat2("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},frob:function(t){return Math.hypot(t[0],t[1],t[2],t[3])},LDU:function(t,n,a,r){return t[2]=r[2]/r[0],a[0]=r[0],a[1]=r[1],a[3]=r[3]-t[2]*a[1],[t,n,a]},add:function(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t},subtract:i,exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=a[0],c=a[1],h=a[2],s=a[3];return Math.abs(r-i)<=n*Math.max(1,Math.abs(r),Math.abs(i))&&Math.abs(u-c)<=n*Math.max(1,Math.abs(u),Math.abs(c))&&Math.abs(e-h)<=n*Math.max(1,Math.abs(e),Math.abs(h))&&Math.abs(o-s)<=n*Math.max(1,Math.abs(o),Math.abs(s))},multiplyScalar:function(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t},multiplyScalarAndAdd:function(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t},mul:c,sub:h});function M(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=a[0],s=a[1],M=a[2],f=a[3],l=a[4],v=a[5];return t[0]=r*h+e*s,t[1]=u*h+o*s,t[2]=r*M+e*f,t[3]=u*M+o*f,t[4]=r*l+e*v+i,t[5]=u*l+o*v+c,t}function f(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t[4]=n[4]-a[4],t[5]=n[5]-a[5],t}var l=M,v=f,b=Object.freeze({create:function(){var t=new a(6);return a!=Float32Array&&(t[1]=0,t[2]=0,t[4]=0,t[5]=0),t[0]=1,t[3]=1,t},clone:function(t){var n=new a(6);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n},copy:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t},identity:function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t},fromValues:function(t,n,r,u,e,o){var i=new a(6);return i[0]=t,i[1]=n,i[2]=r,i[3]=u,i[4]=e,i[5]=o,i},set:function(t,n,a,r,u,e,o){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],c=a*e-r*u;return c?(c=1/c,t[0]=e*c,t[1]=-r*c,t[2]=-u*c,t[3]=a*c,t[4]=(u*i-e*o)*c,t[5]=(r*o-a*i)*c,t):null},determinant:function(t){return t[0]*t[3]-t[1]*t[2]},multiply:M,rotate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=Math.sin(a),s=Math.cos(a);return t[0]=r*s+e*h,t[1]=u*s+o*h,t[2]=r*-h+e*s,t[3]=u*-h+o*s,t[4]=i,t[5]=c,t},scale:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=a[0],s=a[1];return t[0]=r*h,t[1]=u*h,t[2]=e*s,t[3]=o*s,t[4]=i,t[5]=c,t},translate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=a[0],s=a[1];return t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=r*h+e*s+i,t[5]=u*h+o*s+c,t},fromRotation:function(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=a,t[2]=-a,t[3]=r,t[4]=0,t[5]=0,t},fromScaling:function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=n[1],t[4]=0,t[5]=0,t},fromTranslation:function(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=n[0],t[5]=n[1],t},str:function(t){return"mat2d("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+")"},frob:function(t){return Math.hypot(t[0],t[1],t[2],t[3],t[4],t[5],1)},add:function(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t[4]=n[4]+a[4],t[5]=n[5]+a[5],t},subtract:f,multiplyScalar:function(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*a,t[5]=n[5]*a,t},multiplyScalarAndAdd:function(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t[4]=n[4]+a[4]*r,t[5]=n[5]+a[5]*r,t},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=t[4],c=t[5],h=a[0],s=a[1],M=a[2],f=a[3],l=a[4],v=a[5];return Math.abs(r-h)<=n*Math.max(1,Math.abs(r),Math.abs(h))&&Math.abs(u-s)<=n*Math.max(1,Math.abs(u),Math.abs(s))&&Math.abs(e-M)<=n*Math.max(1,Math.abs(e),Math.abs(M))&&Math.abs(o-f)<=n*Math.max(1,Math.abs(o),Math.abs(f))&&Math.abs(i-l)<=n*Math.max(1,Math.abs(i),Math.abs(l))&&Math.abs(c-v)<=n*Math.max(1,Math.abs(c),Math.abs(v))},mul:l,sub:v});function m(){var t=new a(9);return a!=Float32Array&&(t[1]=0,t[2]=0,t[3]=0,t[5]=0,t[6]=0,t[7]=0),t[0]=1,t[4]=1,t[8]=1,t}function d(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=n[6],s=n[7],M=n[8],f=a[0],l=a[1],v=a[2],b=a[3],m=a[4],d=a[5],x=a[6],p=a[7],y=a[8];return t[0]=f*r+l*o+v*h,t[1]=f*u+l*i+v*s,t[2]=f*e+l*c+v*M,t[3]=b*r+m*o+d*h,t[4]=b*u+m*i+d*s,t[5]=b*e+m*c+d*M,t[6]=x*r+p*o+y*h,t[7]=x*u+p*i+y*s,t[8]=x*e+p*c+y*M,t}function x(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t[4]=n[4]-a[4],t[5]=n[5]-a[5],t[6]=n[6]-a[6],t[7]=n[7]-a[7],t[8]=n[8]-a[8],t}var p=d,y=x,q=Object.freeze({create:m,fromMat4:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[4],t[4]=n[5],t[5]=n[6],t[6]=n[8],t[7]=n[9],t[8]=n[10],t},clone:function(t){var n=new a(9);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n},copy:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t},fromValues:function(t,n,r,u,e,o,i,c,h){var s=new a(9);return s[0]=t,s[1]=n,s[2]=r,s[3]=u,s[4]=e,s[5]=o,s[6]=i,s[7]=c,s[8]=h,s},set:function(t,n,a,r,u,e,o,i,c,h){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t[6]=i,t[7]=c,t[8]=h,t},identity:function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},transpose:function(t,n){if(t===n){var a=n[1],r=n[2],u=n[5];t[1]=n[3],t[2]=n[6],t[3]=a,t[5]=n[7],t[6]=r,t[7]=u}else t[0]=n[0],t[1]=n[3],t[2]=n[6],t[3]=n[1],t[4]=n[4],t[5]=n[7],t[6]=n[2],t[7]=n[5],t[8]=n[8];return t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],c=n[6],h=n[7],s=n[8],M=s*o-i*h,f=-s*e+i*c,l=h*e-o*c,v=a*M+r*f+u*l;return v?(v=1/v,t[0]=M*v,t[1]=(-s*r+u*h)*v,t[2]=(i*r-u*o)*v,t[3]=f*v,t[4]=(s*a-u*c)*v,t[5]=(-i*a+u*e)*v,t[6]=l*v,t[7]=(-h*a+r*c)*v,t[8]=(o*a-r*e)*v,t):null},adjoint:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],c=n[6],h=n[7],s=n[8];return t[0]=o*s-i*h,t[1]=u*h-r*s,t[2]=r*i-u*o,t[3]=i*c-e*s,t[4]=a*s-u*c,t[5]=u*e-a*i,t[6]=e*h-o*c,t[7]=r*c-a*h,t[8]=a*o-r*e,t},determinant:function(t){var n=t[0],a=t[1],r=t[2],u=t[3],e=t[4],o=t[5],i=t[6],c=t[7],h=t[8];return n*(h*e-o*c)+a*(-h*u+o*i)+r*(c*u-e*i)},multiply:d,translate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=n[6],s=n[7],M=n[8],f=a[0],l=a[1];return t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=i,t[5]=c,t[6]=f*r+l*o+h,t[7]=f*u+l*i+s,t[8]=f*e+l*c+M,t},rotate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=n[6],s=n[7],M=n[8],f=Math.sin(a),l=Math.cos(a);return t[0]=l*r+f*o,t[1]=l*u+f*i,t[2]=l*e+f*c,t[3]=l*o-f*r,t[4]=l*i-f*u,t[5]=l*c-f*e,t[6]=h,t[7]=s,t[8]=M,t},scale:function(t,n,a){var r=a[0],u=a[1];return t[0]=r*n[0],t[1]=r*n[1],t[2]=r*n[2],t[3]=u*n[3],t[4]=u*n[4],t[5]=u*n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t},fromTranslation:function(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=n[0],t[7]=n[1],t[8]=1,t},fromRotation:function(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=a,t[2]=0,t[3]=-a,t[4]=r,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},fromScaling:function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=0,t[4]=n[1],t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},fromMat2d:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=0,t[3]=n[2],t[4]=n[3],t[5]=0,t[6]=n[4],t[7]=n[5],t[8]=1,t},fromQuat:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a+a,i=r+r,c=u+u,h=a*o,s=r*o,M=r*i,f=u*o,l=u*i,v=u*c,b=e*o,m=e*i,d=e*c;return t[0]=1-M-v,t[3]=s-d,t[6]=f+m,t[1]=s+d,t[4]=1-h-v,t[7]=l-b,t[2]=f-m,t[5]=l+b,t[8]=1-h-M,t},normalFromMat4:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],c=n[6],h=n[7],s=n[8],M=n[9],f=n[10],l=n[11],v=n[12],b=n[13],m=n[14],d=n[15],x=a*i-r*o,p=a*c-u*o,y=a*h-e*o,q=r*c-u*i,g=r*h-e*i,A=u*h-e*c,w=s*b-M*v,R=s*m-f*v,z=s*d-l*v,P=M*m-f*b,j=M*d-l*b,I=f*d-l*m,S=x*I-p*j+y*P+q*z-g*R+A*w;return S?(S=1/S,t[0]=(i*I-c*j+h*P)*S,t[1]=(c*z-o*I-h*R)*S,t[2]=(o*j-i*z+h*w)*S,t[3]=(u*j-r*I-e*P)*S,t[4]=(a*I-u*z+e*R)*S,t[5]=(r*z-a*j-e*w)*S,t[6]=(b*A-m*g+d*q)*S,t[7]=(m*y-v*A-d*p)*S,t[8]=(v*g-b*y+d*x)*S,t):null},projection:function(t,n,a){return t[0]=2/n,t[1]=0,t[2]=0,t[3]=0,t[4]=-2/a,t[5]=0,t[6]=-1,t[7]=1,t[8]=1,t},str:function(t){return"mat3("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+")"},frob:function(t){return Math.hypot(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8])},add:function(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t[4]=n[4]+a[4],t[5]=n[5]+a[5],t[6]=n[6]+a[6],t[7]=n[7]+a[7],t[8]=n[8]+a[8],t},subtract:x,multiplyScalar:function(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*a,t[5]=n[5]*a,t[6]=n[6]*a,t[7]=n[7]*a,t[8]=n[8]*a,t},multiplyScalarAndAdd:function(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t[4]=n[4]+a[4]*r,t[5]=n[5]+a[5]*r,t[6]=n[6]+a[6]*r,t[7]=n[7]+a[7]*r,t[8]=n[8]+a[8]*r,t},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=t[4],c=t[5],h=t[6],s=t[7],M=t[8],f=a[0],l=a[1],v=a[2],b=a[3],m=a[4],d=a[5],x=a[6],p=a[7],y=a[8];return Math.abs(r-f)<=n*Math.max(1,Math.abs(r),Math.abs(f))&&Math.abs(u-l)<=n*Math.max(1,Math.abs(u),Math.abs(l))&&Math.abs(e-v)<=n*Math.max(1,Math.abs(e),Math.abs(v))&&Math.abs(o-b)<=n*Math.max(1,Math.abs(o),Math.abs(b))&&Math.abs(i-m)<=n*Math.max(1,Math.abs(i),Math.abs(m))&&Math.abs(c-d)<=n*Math.max(1,Math.abs(c),Math.abs(d))&&Math.abs(h-x)<=n*Math.max(1,Math.abs(h),Math.abs(x))&&Math.abs(s-p)<=n*Math.max(1,Math.abs(s),Math.abs(p))&&Math.abs(M-y)<=n*Math.max(1,Math.abs(M),Math.abs(y))},mul:p,sub:y});function g(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}function A(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=n[6],s=n[7],M=n[8],f=n[9],l=n[10],v=n[11],b=n[12],m=n[13],d=n[14],x=n[15],p=a[0],y=a[1],q=a[2],g=a[3];return t[0]=p*r+y*i+q*M+g*b,t[1]=p*u+y*c+q*f+g*m,t[2]=p*e+y*h+q*l+g*d,t[3]=p*o+y*s+q*v+g*x,p=a[4],y=a[5],q=a[6],g=a[7],t[4]=p*r+y*i+q*M+g*b,t[5]=p*u+y*c+q*f+g*m,t[6]=p*e+y*h+q*l+g*d,t[7]=p*o+y*s+q*v+g*x,p=a[8],y=a[9],q=a[10],g=a[11],t[8]=p*r+y*i+q*M+g*b,t[9]=p*u+y*c+q*f+g*m,t[10]=p*e+y*h+q*l+g*d,t[11]=p*o+y*s+q*v+g*x,p=a[12],y=a[13],q=a[14],g=a[15],t[12]=p*r+y*i+q*M+g*b,t[13]=p*u+y*c+q*f+g*m,t[14]=p*e+y*h+q*l+g*d,t[15]=p*o+y*s+q*v+g*x,t}function w(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=r+r,c=u+u,h=e+e,s=r*i,M=r*c,f=r*h,l=u*c,v=u*h,b=e*h,m=o*i,d=o*c,x=o*h;return t[0]=1-(l+b),t[1]=M+x,t[2]=f-d,t[3]=0,t[4]=M-x,t[5]=1-(s+b),t[6]=v+m,t[7]=0,t[8]=f+d,t[9]=v-m,t[10]=1-(s+l),t[11]=0,t[12]=a[0],t[13]=a[1],t[14]=a[2],t[15]=1,t}function R(t,n){return t[0]=n[12],t[1]=n[13],t[2]=n[14],t}function z(t,n){var a=n[0],r=n[1],u=n[2],e=n[4],o=n[5],i=n[6],c=n[8],h=n[9],s=n[10];return t[0]=Math.hypot(a,r,u),t[1]=Math.hypot(e,o,i),t[2]=Math.hypot(c,h,s),t}function P(t,n){var r=new a(3);z(r,n);var u=1/r[0],e=1/r[1],o=1/r[2],i=n[0]*u,c=n[1]*e,h=n[2]*o,s=n[4]*u,M=n[5]*e,f=n[6]*o,l=n[8]*u,v=n[9]*e,b=n[10]*o,m=i+M+b,d=0;return m>0?(d=2*Math.sqrt(m+1),t[3]=.25*d,t[0]=(f-v)/d,t[1]=(l-h)/d,t[2]=(c-s)/d):i>M&&i>b?(d=2*Math.sqrt(1+i-M-b),t[3]=(f-v)/d,t[0]=.25*d,t[1]=(c+s)/d,t[2]=(l+h)/d):M>b?(d=2*Math.sqrt(1+M-i-b),t[3]=(l-h)/d,t[0]=(c+s)/d,t[1]=.25*d,t[2]=(f+v)/d):(d=2*Math.sqrt(1+b-i-M),t[3]=(c-s)/d,t[0]=(l+h)/d,t[1]=(f+v)/d,t[2]=.25*d),t}function j(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t[4]=n[4]-a[4],t[5]=n[5]-a[5],t[6]=n[6]-a[6],t[7]=n[7]-a[7],t[8]=n[8]-a[8],t[9]=n[9]-a[9],t[10]=n[10]-a[10],t[11]=n[11]-a[11],t[12]=n[12]-a[12],t[13]=n[13]-a[13],t[14]=n[14]-a[14],t[15]=n[15]-a[15],t}var I=A,S=j,E=Object.freeze({create:function(){var t=new a(16);return a!=Float32Array&&(t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0),t[0]=1,t[5]=1,t[10]=1,t[15]=1,t},clone:function(t){var n=new a(16);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n[9]=t[9],n[10]=t[10],n[11]=t[11],n[12]=t[12],n[13]=t[13],n[14]=t[14],n[15]=t[15],n},copy:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],t},fromValues:function(t,n,r,u,e,o,i,c,h,s,M,f,l,v,b,m){var d=new a(16);return d[0]=t,d[1]=n,d[2]=r,d[3]=u,d[4]=e,d[5]=o,d[6]=i,d[7]=c,d[8]=h,d[9]=s,d[10]=M,d[11]=f,d[12]=l,d[13]=v,d[14]=b,d[15]=m,d},set:function(t,n,a,r,u,e,o,i,c,h,s,M,f,l,v,b,m){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t[6]=i,t[7]=c,t[8]=h,t[9]=s,t[10]=M,t[11]=f,t[12]=l,t[13]=v,t[14]=b,t[15]=m,t},identity:g,transpose:function(t,n){if(t===n){var a=n[1],r=n[2],u=n[3],e=n[6],o=n[7],i=n[11];t[1]=n[4],t[2]=n[8],t[3]=n[12],t[4]=a,t[6]=n[9],t[7]=n[13],t[8]=r,t[9]=e,t[11]=n[14],t[12]=u,t[13]=o,t[14]=i}else t[0]=n[0],t[1]=n[4],t[2]=n[8],t[3]=n[12],t[4]=n[1],t[5]=n[5],t[6]=n[9],t[7]=n[13],t[8]=n[2],t[9]=n[6],t[10]=n[10],t[11]=n[14],t[12]=n[3],t[13]=n[7],t[14]=n[11],t[15]=n[15];return t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],c=n[6],h=n[7],s=n[8],M=n[9],f=n[10],l=n[11],v=n[12],b=n[13],m=n[14],d=n[15],x=a*i-r*o,p=a*c-u*o,y=a*h-e*o,q=r*c-u*i,g=r*h-e*i,A=u*h-e*c,w=s*b-M*v,R=s*m-f*v,z=s*d-l*v,P=M*m-f*b,j=M*d-l*b,I=f*d-l*m,S=x*I-p*j+y*P+q*z-g*R+A*w;return S?(S=1/S,t[0]=(i*I-c*j+h*P)*S,t[1]=(u*j-r*I-e*P)*S,t[2]=(b*A-m*g+d*q)*S,t[3]=(f*g-M*A-l*q)*S,t[4]=(c*z-o*I-h*R)*S,t[5]=(a*I-u*z+e*R)*S,t[6]=(m*y-v*A-d*p)*S,t[7]=(s*A-f*y+l*p)*S,t[8]=(o*j-i*z+h*w)*S,t[9]=(r*z-a*j-e*w)*S,t[10]=(v*g-b*y+d*x)*S,t[11]=(M*y-s*g-l*x)*S,t[12]=(i*R-o*P-c*w)*S,t[13]=(a*P-r*R+u*w)*S,t[14]=(b*p-v*q-m*x)*S,t[15]=(s*q-M*p+f*x)*S,t):null},adjoint:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],c=n[6],h=n[7],s=n[8],M=n[9],f=n[10],l=n[11],v=n[12],b=n[13],m=n[14],d=n[15];return t[0]=i*(f*d-l*m)-M*(c*d-h*m)+b*(c*l-h*f),t[1]=-(r*(f*d-l*m)-M*(u*d-e*m)+b*(u*l-e*f)),t[2]=r*(c*d-h*m)-i*(u*d-e*m)+b*(u*h-e*c),t[3]=-(r*(c*l-h*f)-i*(u*l-e*f)+M*(u*h-e*c)),t[4]=-(o*(f*d-l*m)-s*(c*d-h*m)+v*(c*l-h*f)),t[5]=a*(f*d-l*m)-s*(u*d-e*m)+v*(u*l-e*f),t[6]=-(a*(c*d-h*m)-o*(u*d-e*m)+v*(u*h-e*c)),t[7]=a*(c*l-h*f)-o*(u*l-e*f)+s*(u*h-e*c),t[8]=o*(M*d-l*b)-s*(i*d-h*b)+v*(i*l-h*M),t[9]=-(a*(M*d-l*b)-s*(r*d-e*b)+v*(r*l-e*M)),t[10]=a*(i*d-h*b)-o*(r*d-e*b)+v*(r*h-e*i),t[11]=-(a*(i*l-h*M)-o*(r*l-e*M)+s*(r*h-e*i)),t[12]=-(o*(M*m-f*b)-s*(i*m-c*b)+v*(i*f-c*M)),t[13]=a*(M*m-f*b)-s*(r*m-u*b)+v*(r*f-u*M),t[14]=-(a*(i*m-c*b)-o*(r*m-u*b)+v*(r*c-u*i)),t[15]=a*(i*f-c*M)-o*(r*f-u*M)+s*(r*c-u*i),t},determinant:function(t){var n=t[0],a=t[1],r=t[2],u=t[3],e=t[4],o=t[5],i=t[6],c=t[7],h=t[8],s=t[9],M=t[10],f=t[11],l=t[12],v=t[13],b=t[14],m=t[15];return(n*o-a*e)*(M*m-f*b)-(n*i-r*e)*(s*m-f*v)+(n*c-u*e)*(s*b-M*v)+(a*i-r*o)*(h*m-f*l)-(a*c-u*o)*(h*b-M*l)+(r*c-u*i)*(h*v-s*l)},multiply:A,translate:function(t,n,a){var r,u,e,o,i,c,h,s,M,f,l,v,b=a[0],m=a[1],d=a[2];return n===t?(t[12]=n[0]*b+n[4]*m+n[8]*d+n[12],t[13]=n[1]*b+n[5]*m+n[9]*d+n[13],t[14]=n[2]*b+n[6]*m+n[10]*d+n[14],t[15]=n[3]*b+n[7]*m+n[11]*d+n[15]):(r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],c=n[5],h=n[6],s=n[7],M=n[8],f=n[9],l=n[10],v=n[11],t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=i,t[5]=c,t[6]=h,t[7]=s,t[8]=M,t[9]=f,t[10]=l,t[11]=v,t[12]=r*b+i*m+M*d+n[12],t[13]=u*b+c*m+f*d+n[13],t[14]=e*b+h*m+l*d+n[14],t[15]=o*b+s*m+v*d+n[15]),t},scale:function(t,n,a){var r=a[0],u=a[1],e=a[2];return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=n[3]*r,t[4]=n[4]*u,t[5]=n[5]*u,t[6]=n[6]*u,t[7]=n[7]*u,t[8]=n[8]*e,t[9]=n[9]*e,t[10]=n[10]*e,t[11]=n[11]*e,t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],t},rotate:function(t,a,r,u){var e,o,i,c,h,s,M,f,l,v,b,m,d,x,p,y,q,g,A,w,R,z,P,j,I=u[0],S=u[1],E=u[2],O=Math.hypot(I,S,E);return O0?(r[0]=2*(c*i+M*u+h*o-s*e)/f,r[1]=2*(h*i+M*e+s*u-c*o)/f,r[2]=2*(s*i+M*o+c*e-h*u)/f):(r[0]=2*(c*i+M*u+h*o-s*e),r[1]=2*(h*i+M*e+s*u-c*o),r[2]=2*(s*i+M*o+c*e-h*u)),w(t,n,r),t},getTranslation:R,getScaling:z,getRotation:P,fromRotationTranslationScale:function(t,n,a,r){var u=n[0],e=n[1],o=n[2],i=n[3],c=u+u,h=e+e,s=o+o,M=u*c,f=u*h,l=u*s,v=e*h,b=e*s,m=o*s,d=i*c,x=i*h,p=i*s,y=r[0],q=r[1],g=r[2];return t[0]=(1-(v+m))*y,t[1]=(f+p)*y,t[2]=(l-x)*y,t[3]=0,t[4]=(f-p)*q,t[5]=(1-(M+m))*q,t[6]=(b+d)*q,t[7]=0,t[8]=(l+x)*g,t[9]=(b-d)*g,t[10]=(1-(M+v))*g,t[11]=0,t[12]=a[0],t[13]=a[1],t[14]=a[2],t[15]=1,t},fromRotationTranslationScaleOrigin:function(t,n,a,r,u){var e=n[0],o=n[1],i=n[2],c=n[3],h=e+e,s=o+o,M=i+i,f=e*h,l=e*s,v=e*M,b=o*s,m=o*M,d=i*M,x=c*h,p=c*s,y=c*M,q=r[0],g=r[1],A=r[2],w=u[0],R=u[1],z=u[2],P=(1-(b+d))*q,j=(l+y)*q,I=(v-p)*q,S=(l-y)*g,E=(1-(f+d))*g,O=(m+x)*g,T=(v+p)*A,D=(m-x)*A,F=(1-(f+b))*A;return t[0]=P,t[1]=j,t[2]=I,t[3]=0,t[4]=S,t[5]=E,t[6]=O,t[7]=0,t[8]=T,t[9]=D,t[10]=F,t[11]=0,t[12]=a[0]+w-(P*w+S*R+T*z),t[13]=a[1]+R-(j*w+E*R+D*z),t[14]=a[2]+z-(I*w+O*R+F*z),t[15]=1,t},fromQuat:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a+a,i=r+r,c=u+u,h=a*o,s=r*o,M=r*i,f=u*o,l=u*i,v=u*c,b=e*o,m=e*i,d=e*c;return t[0]=1-M-v,t[1]=s+d,t[2]=f-m,t[3]=0,t[4]=s-d,t[5]=1-h-v,t[6]=l+b,t[7]=0,t[8]=f+m,t[9]=l-b,t[10]=1-h-M,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},frustum:function(t,n,a,r,u,e,o){var i=1/(a-n),c=1/(u-r),h=1/(e-o);return t[0]=2*e*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=2*e*c,t[6]=0,t[7]=0,t[8]=(a+n)*i,t[9]=(u+r)*c,t[10]=(o+e)*h,t[11]=-1,t[12]=0,t[13]=0,t[14]=o*e*2*h,t[15]=0,t},perspective:function(t,n,a,r,u){var e,o=1/Math.tan(n/2);return t[0]=o/a,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=o,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=-1,t[12]=0,t[13]=0,t[15]=0,null!=u&&u!==1/0?(e=1/(r-u),t[10]=(u+r)*e,t[14]=2*u*r*e):(t[10]=-1,t[14]=-2*r),t},perspectiveFromFieldOfView:function(t,n,a,r){var u=Math.tan(n.upDegrees*Math.PI/180),e=Math.tan(n.downDegrees*Math.PI/180),o=Math.tan(n.leftDegrees*Math.PI/180),i=Math.tan(n.rightDegrees*Math.PI/180),c=2/(o+i),h=2/(u+e);return t[0]=c,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=h,t[6]=0,t[7]=0,t[8]=-(o-i)*c*.5,t[9]=(u-e)*h*.5,t[10]=r/(a-r),t[11]=-1,t[12]=0,t[13]=0,t[14]=r*a/(a-r),t[15]=0,t},ortho:function(t,n,a,r,u,e,o){var i=1/(n-a),c=1/(r-u),h=1/(e-o);return t[0]=-2*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*c,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*h,t[11]=0,t[12]=(n+a)*i,t[13]=(u+r)*c,t[14]=(o+e)*h,t[15]=1,t},lookAt:function(t,a,r,u){var e,o,i,c,h,s,M,f,l,v,b=a[0],m=a[1],d=a[2],x=u[0],p=u[1],y=u[2],q=r[0],A=r[1],w=r[2];return Math.abs(b-q)0&&(s*=l=1/Math.sqrt(l),M*=l,f*=l);var v=c*f-h*M,b=h*s-i*f,m=i*M-c*s;return(l=v*v+b*b+m*m)>0&&(v*=l=1/Math.sqrt(l),b*=l,m*=l),t[0]=v,t[1]=b,t[2]=m,t[3]=0,t[4]=M*m-f*b,t[5]=f*v-s*m,t[6]=s*b-M*v,t[7]=0,t[8]=s,t[9]=M,t[10]=f,t[11]=0,t[12]=u,t[13]=e,t[14]=o,t[15]=1,t},str:function(t){return"mat4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+", "+t[9]+", "+t[10]+", "+t[11]+", "+t[12]+", "+t[13]+", "+t[14]+", "+t[15]+")"},frob:function(t){return Math.hypot(t[0],t[1],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15])},add:function(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t[4]=n[4]+a[4],t[5]=n[5]+a[5],t[6]=n[6]+a[6],t[7]=n[7]+a[7],t[8]=n[8]+a[8],t[9]=n[9]+a[9],t[10]=n[10]+a[10],t[11]=n[11]+a[11],t[12]=n[12]+a[12],t[13]=n[13]+a[13],t[14]=n[14]+a[14],t[15]=n[15]+a[15],t},subtract:j,multiplyScalar:function(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*a,t[5]=n[5]*a,t[6]=n[6]*a,t[7]=n[7]*a,t[8]=n[8]*a,t[9]=n[9]*a,t[10]=n[10]*a,t[11]=n[11]*a,t[12]=n[12]*a,t[13]=n[13]*a,t[14]=n[14]*a,t[15]=n[15]*a,t},multiplyScalarAndAdd:function(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t[4]=n[4]+a[4]*r,t[5]=n[5]+a[5]*r,t[6]=n[6]+a[6]*r,t[7]=n[7]+a[7]*r,t[8]=n[8]+a[8]*r,t[9]=n[9]+a[9]*r,t[10]=n[10]+a[10]*r,t[11]=n[11]+a[11]*r,t[12]=n[12]+a[12]*r,t[13]=n[13]+a[13]*r,t[14]=n[14]+a[14]*r,t[15]=n[15]+a[15]*r,t},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]&&t[9]===n[9]&&t[10]===n[10]&&t[11]===n[11]&&t[12]===n[12]&&t[13]===n[13]&&t[14]===n[14]&&t[15]===n[15]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=t[4],c=t[5],h=t[6],s=t[7],M=t[8],f=t[9],l=t[10],v=t[11],b=t[12],m=t[13],d=t[14],x=t[15],p=a[0],y=a[1],q=a[2],g=a[3],A=a[4],w=a[5],R=a[6],z=a[7],P=a[8],j=a[9],I=a[10],S=a[11],E=a[12],O=a[13],T=a[14],D=a[15];return Math.abs(r-p)<=n*Math.max(1,Math.abs(r),Math.abs(p))&&Math.abs(u-y)<=n*Math.max(1,Math.abs(u),Math.abs(y))&&Math.abs(e-q)<=n*Math.max(1,Math.abs(e),Math.abs(q))&&Math.abs(o-g)<=n*Math.max(1,Math.abs(o),Math.abs(g))&&Math.abs(i-A)<=n*Math.max(1,Math.abs(i),Math.abs(A))&&Math.abs(c-w)<=n*Math.max(1,Math.abs(c),Math.abs(w))&&Math.abs(h-R)<=n*Math.max(1,Math.abs(h),Math.abs(R))&&Math.abs(s-z)<=n*Math.max(1,Math.abs(s),Math.abs(z))&&Math.abs(M-P)<=n*Math.max(1,Math.abs(M),Math.abs(P))&&Math.abs(f-j)<=n*Math.max(1,Math.abs(f),Math.abs(j))&&Math.abs(l-I)<=n*Math.max(1,Math.abs(l),Math.abs(I))&&Math.abs(v-S)<=n*Math.max(1,Math.abs(v),Math.abs(S))&&Math.abs(b-E)<=n*Math.max(1,Math.abs(b),Math.abs(E))&&Math.abs(m-O)<=n*Math.max(1,Math.abs(m),Math.abs(O))&&Math.abs(d-T)<=n*Math.max(1,Math.abs(d),Math.abs(T))&&Math.abs(x-D)<=n*Math.max(1,Math.abs(x),Math.abs(D))},mul:I,sub:S});function O(){var t=new a(3);return a!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t}function T(t){var n=t[0],a=t[1],r=t[2];return Math.hypot(n,a,r)}function D(t,n,r){var u=new a(3);return u[0]=t,u[1]=n,u[2]=r,u}function F(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t}function L(t,n,a){return t[0]=n[0]*a[0],t[1]=n[1]*a[1],t[2]=n[2]*a[2],t}function V(t,n,a){return t[0]=n[0]/a[0],t[1]=n[1]/a[1],t[2]=n[2]/a[2],t}function Q(t,n){var a=n[0]-t[0],r=n[1]-t[1],u=n[2]-t[2];return Math.hypot(a,r,u)}function Y(t,n){var a=n[0]-t[0],r=n[1]-t[1],u=n[2]-t[2];return a*a+r*r+u*u}function X(t){var n=t[0],a=t[1],r=t[2];return n*n+a*a+r*r}function Z(t,n){var a=n[0],r=n[1],u=n[2],e=a*a+r*r+u*u;return e>0&&(e=1/Math.sqrt(e)),t[0]=n[0]*e,t[1]=n[1]*e,t[2]=n[2]*e,t}function _(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function B(t,n,a){var r=n[0],u=n[1],e=n[2],o=a[0],i=a[1],c=a[2];return t[0]=u*c-e*i,t[1]=e*o-r*c,t[2]=r*i-u*o,t}var N,k=F,U=L,W=V,C=Q,G=Y,H=T,J=X,K=(N=O(),function(t,n,a,r,u,e){var o,i;for(n||(n=3),a||(a=0),i=r?Math.min(r*n+a,t.length):t.length,o=a;o1?0:u<-1?Math.PI:Math.acos(u)},zero:function(t){return t[0]=0,t[1]=0,t[2]=0,t},str:function(t){return"vec3("+t[0]+", "+t[1]+", "+t[2]+")"},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=a[0],i=a[1],c=a[2];return Math.abs(r-o)<=n*Math.max(1,Math.abs(r),Math.abs(o))&&Math.abs(u-i)<=n*Math.max(1,Math.abs(u),Math.abs(i))&&Math.abs(e-c)<=n*Math.max(1,Math.abs(e),Math.abs(c))},sub:k,mul:U,div:W,dist:C,sqrDist:G,len:H,sqrLen:J,forEach:K});function tt(){var t=new a(4);return a!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0,t[3]=0),t}function nt(t){var n=new a(4);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n}function at(t,n,r,u){var e=new a(4);return e[0]=t,e[1]=n,e[2]=r,e[3]=u,e}function rt(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t}function ut(t,n,a,r,u){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t}function et(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t}function ot(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t}function it(t,n,a){return t[0]=n[0]*a[0],t[1]=n[1]*a[1],t[2]=n[2]*a[2],t[3]=n[3]*a[3],t}function ct(t,n,a){return t[0]=n[0]/a[0],t[1]=n[1]/a[1],t[2]=n[2]/a[2],t[3]=n[3]/a[3],t}function ht(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t}function st(t,n){var a=n[0]-t[0],r=n[1]-t[1],u=n[2]-t[2],e=n[3]-t[3];return Math.hypot(a,r,u,e)}function Mt(t,n){var a=n[0]-t[0],r=n[1]-t[1],u=n[2]-t[2],e=n[3]-t[3];return a*a+r*r+u*u+e*e}function ft(t){var n=t[0],a=t[1],r=t[2],u=t[3];return Math.hypot(n,a,r,u)}function lt(t){var n=t[0],a=t[1],r=t[2],u=t[3];return n*n+a*a+r*r+u*u}function vt(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a*a+r*r+u*u+e*e;return o>0&&(o=1/Math.sqrt(o)),t[0]=a*o,t[1]=r*o,t[2]=u*o,t[3]=e*o,t}function bt(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]+t[3]*n[3]}function mt(t,n,a,r){var u=n[0],e=n[1],o=n[2],i=n[3];return t[0]=u+r*(a[0]-u),t[1]=e+r*(a[1]-e),t[2]=o+r*(a[2]-o),t[3]=i+r*(a[3]-i),t}function dt(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]}function xt(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=a[0],c=a[1],h=a[2],s=a[3];return Math.abs(r-i)<=n*Math.max(1,Math.abs(r),Math.abs(i))&&Math.abs(u-c)<=n*Math.max(1,Math.abs(u),Math.abs(c))&&Math.abs(e-h)<=n*Math.max(1,Math.abs(e),Math.abs(h))&&Math.abs(o-s)<=n*Math.max(1,Math.abs(o),Math.abs(s))}var pt=ot,yt=it,qt=ct,gt=st,At=Mt,wt=ft,Rt=lt,zt=function(){var t=tt();return function(n,a,r,u,e,o){var i,c;for(a||(a=4),r||(r=0),c=u?Math.min(u*a+r,n.length):n.length,i=r;i=1);do{c=(e=2*r()-1)*e+(o=2*r()-1)*o}while(c>=1);var h=Math.sqrt((1-i)/c);return t[0]=n*a,t[1]=n*u,t[2]=n*e*h,t[3]=n*o*h,t},transformMat4:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3];return t[0]=a[0]*r+a[4]*u+a[8]*e+a[12]*o,t[1]=a[1]*r+a[5]*u+a[9]*e+a[13]*o,t[2]=a[2]*r+a[6]*u+a[10]*e+a[14]*o,t[3]=a[3]*r+a[7]*u+a[11]*e+a[15]*o,t},transformQuat:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=a[0],i=a[1],c=a[2],h=a[3],s=h*r+i*e-c*u,M=h*u+c*r-o*e,f=h*e+o*u-i*r,l=-o*r-i*u-c*e;return t[0]=s*h+l*-o+M*-c-f*-i,t[1]=M*h+l*-i+f*-o-s*-c,t[2]=f*h+l*-c+s*-i-M*-o,t[3]=n[3],t},zero:function(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=0,t},str:function(t){return"vec4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},exactEquals:dt,equals:xt,sub:pt,mul:yt,div:qt,dist:gt,sqrDist:At,len:wt,sqrLen:Rt,forEach:zt});function jt(){var t=new a(4);return a!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t[3]=1,t}function It(t,n,a){a*=.5;var r=Math.sin(a);return t[0]=r*n[0],t[1]=r*n[1],t[2]=r*n[2],t[3]=Math.cos(a),t}function St(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],c=a[1],h=a[2],s=a[3];return t[0]=r*s+o*i+u*h-e*c,t[1]=u*s+o*c+e*i-r*h,t[2]=e*s+o*h+r*c-u*i,t[3]=o*s-r*i-u*c-e*h,t}function Et(t,n,a){a*=.5;var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),c=Math.cos(a);return t[0]=r*c+o*i,t[1]=u*c+e*i,t[2]=e*c-u*i,t[3]=o*c-r*i,t}function Ot(t,n,a){a*=.5;var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),c=Math.cos(a);return t[0]=r*c-e*i,t[1]=u*c+o*i,t[2]=e*c+r*i,t[3]=o*c-u*i,t}function Tt(t,n,a){a*=.5;var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),c=Math.cos(a);return t[0]=r*c+u*i,t[1]=u*c-r*i,t[2]=e*c+o*i,t[3]=o*c-e*i,t}function Dt(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=Math.sqrt(a*a+r*r+u*u),i=Math.exp(e),c=o>0?i*Math.sin(o)/o:0;return t[0]=a*c,t[1]=r*c,t[2]=u*c,t[3]=i*Math.cos(o),t}function Ft(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=Math.sqrt(a*a+r*r+u*u),i=o>0?Math.atan2(o,e)/o:0;return t[0]=a*i,t[1]=r*i,t[2]=u*i,t[3]=.5*Math.log(a*a+r*r+u*u+e*e),t}function Lt(t,a,r,u){var e,o,i,c,h,s=a[0],M=a[1],f=a[2],l=a[3],v=r[0],b=r[1],m=r[2],d=r[3];return(o=s*v+M*b+f*m+l*d)<0&&(o=-o,v=-v,b=-b,m=-m,d=-d),1-o>n?(e=Math.acos(o),i=Math.sin(e),c=Math.sin((1-u)*e)/i,h=Math.sin(u*e)/i):(c=1-u,h=u),t[0]=c*s+h*v,t[1]=c*M+h*b,t[2]=c*f+h*m,t[3]=c*l+h*d,t}function Vt(t,n){var a,r=n[0]+n[4]+n[8];if(r>0)a=Math.sqrt(r+1),t[3]=.5*a,a=.5/a,t[0]=(n[5]-n[7])*a,t[1]=(n[6]-n[2])*a,t[2]=(n[1]-n[3])*a;else{var u=0;n[4]>n[0]&&(u=1),n[8]>n[3*u+u]&&(u=2);var e=(u+1)%3,o=(u+2)%3;a=Math.sqrt(n[3*u+u]-n[3*e+e]-n[3*o+o]+1),t[u]=.5*a,a=.5/a,t[3]=(n[3*e+o]-n[3*o+e])*a,t[e]=(n[3*e+u]+n[3*u+e])*a,t[o]=(n[3*o+u]+n[3*u+o])*a}return t}var Qt,Yt,Xt,Zt,_t,Bt,Nt=nt,kt=at,Ut=rt,Wt=ut,Ct=et,Gt=St,Ht=ht,Jt=bt,Kt=mt,$t=ft,tn=$t,nn=lt,an=nn,rn=vt,un=dt,en=xt,on=(Qt=O(),Yt=D(1,0,0),Xt=D(0,1,0),function(t,n,a){var r=_(n,a);return r<-.999999?(B(Qt,Yt,n),H(Qt)<1e-6&&B(Qt,Xt,n),Z(Qt,Qt),It(t,Qt,Math.PI),t):r>.999999?(t[0]=0,t[1]=0,t[2]=0,t[3]=1,t):(B(Qt,n,a),t[0]=Qt[0],t[1]=Qt[1],t[2]=Qt[2],t[3]=1+r,rn(t,t))}),cn=(Zt=jt(),_t=jt(),function(t,n,a,r,u,e){return Lt(Zt,n,u,e),Lt(_t,a,r,e),Lt(t,Zt,_t,2*e*(1-e)),t}),hn=(Bt=m(),function(t,n,a,r){return Bt[0]=a[0],Bt[3]=a[1],Bt[6]=a[2],Bt[1]=r[0],Bt[4]=r[1],Bt[7]=r[2],Bt[2]=-n[0],Bt[5]=-n[1],Bt[8]=-n[2],rn(t,Vt(t,Bt))}),sn=Object.freeze({create:jt,identity:function(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t},setAxisAngle:It,getAxisAngle:function(t,a){var r=2*Math.acos(a[3]),u=Math.sin(r/2);return u>n?(t[0]=a[0]/u,t[1]=a[1]/u,t[2]=a[2]/u):(t[0]=1,t[1]=0,t[2]=0),r},getAngle:function(t,n){var a=Jt(t,n);return Math.acos(2*a*a-1)},multiply:St,rotateX:Et,rotateY:Ot,rotateZ:Tt,calculateW:function(t,n){var a=n[0],r=n[1],u=n[2];return t[0]=a,t[1]=r,t[2]=u,t[3]=Math.sqrt(Math.abs(1-a*a-r*r-u*u)),t},exp:Dt,ln:Ft,pow:function(t,n,a){return Ft(t,n),Ht(t,t,a),Dt(t,t),t},slerp:Lt,random:function(t){var n=r(),a=r(),u=r(),e=Math.sqrt(1-n),o=Math.sqrt(n);return t[0]=e*Math.sin(2*Math.PI*a),t[1]=e*Math.cos(2*Math.PI*a),t[2]=o*Math.sin(2*Math.PI*u),t[3]=o*Math.cos(2*Math.PI*u),t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a*a+r*r+u*u+e*e,i=o?1/o:0;return t[0]=-a*i,t[1]=-r*i,t[2]=-u*i,t[3]=e*i,t},conjugate:function(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t[3]=n[3],t},fromMat3:Vt,fromEuler:function(t,n,a,r){var u=.5*Math.PI/180;n*=u,a*=u,r*=u;var e=Math.sin(n),o=Math.cos(n),i=Math.sin(a),c=Math.cos(a),h=Math.sin(r),s=Math.cos(r);return t[0]=e*c*s-o*i*h,t[1]=o*i*s+e*c*h,t[2]=o*c*h-e*i*s,t[3]=o*c*s+e*i*h,t},str:function(t){return"quat("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},clone:Nt,fromValues:kt,copy:Ut,set:Wt,add:Ct,mul:Gt,scale:Ht,dot:Jt,lerp:Kt,length:$t,len:tn,squaredLength:nn,sqrLen:an,normalize:rn,exactEquals:un,equals:en,rotationTo:on,sqlerp:cn,setAxes:hn});function Mn(t,n,a){var r=.5*a[0],u=.5*a[1],e=.5*a[2],o=n[0],i=n[1],c=n[2],h=n[3];return t[0]=o,t[1]=i,t[2]=c,t[3]=h,t[4]=r*h+u*c-e*i,t[5]=u*h+e*o-r*c,t[6]=e*h+r*i-u*o,t[7]=-r*o-u*i-e*c,t}function fn(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t}var ln=Ut;var vn=Ut;function bn(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[4],c=a[5],h=a[6],s=a[7],M=n[4],f=n[5],l=n[6],v=n[7],b=a[0],m=a[1],d=a[2],x=a[3];return t[0]=r*x+o*b+u*d-e*m,t[1]=u*x+o*m+e*b-r*d,t[2]=e*x+o*d+r*m-u*b,t[3]=o*x-r*b-u*m-e*d,t[4]=r*s+o*i+u*h-e*c+M*x+v*b+f*d-l*m,t[5]=u*s+o*c+e*i-r*h+f*x+v*m+l*b-M*d,t[6]=e*s+o*h+r*c-u*i+l*x+v*d+M*m-f*b,t[7]=o*s-r*i-u*c-e*h+v*x-M*b-f*m-l*d,t}var mn=bn;var dn=Jt;var xn=$t,pn=xn,yn=nn,qn=yn;var gn=Object.freeze({create:function(){var t=new a(8);return a!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0,t[4]=0,t[5]=0,t[6]=0,t[7]=0),t[3]=1,t},clone:function(t){var n=new a(8);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n},fromValues:function(t,n,r,u,e,o,i,c){var h=new a(8);return h[0]=t,h[1]=n,h[2]=r,h[3]=u,h[4]=e,h[5]=o,h[6]=i,h[7]=c,h},fromRotationTranslationValues:function(t,n,r,u,e,o,i){var c=new a(8);c[0]=t,c[1]=n,c[2]=r,c[3]=u;var h=.5*e,s=.5*o,M=.5*i;return c[4]=h*u+s*r-M*n,c[5]=s*u+M*t-h*r,c[6]=M*u+h*n-s*t,c[7]=-h*t-s*n-M*r,c},fromRotationTranslation:Mn,fromTranslation:function(t,n){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t[4]=.5*n[0],t[5]=.5*n[1],t[6]=.5*n[2],t[7]=0,t},fromRotation:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=0,t[5]=0,t[6]=0,t[7]=0,t},fromMat4:function(t,n){var r=jt();P(r,n);var u=new a(3);return R(u,n),Mn(t,r,u),t},copy:fn,identity:function(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t[6]=0,t[7]=0,t},set:function(t,n,a,r,u,e,o,i,c){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t[6]=i,t[7]=c,t},getReal:ln,getDual:function(t,n){return t[0]=n[4],t[1]=n[5],t[2]=n[6],t[3]=n[7],t},setReal:vn,setDual:function(t,n){return t[4]=n[0],t[5]=n[1],t[6]=n[2],t[7]=n[3],t},getTranslation:function(t,n){var a=n[4],r=n[5],u=n[6],e=n[7],o=-n[0],i=-n[1],c=-n[2],h=n[3];return t[0]=2*(a*h+e*o+r*c-u*i),t[1]=2*(r*h+e*i+u*o-a*c),t[2]=2*(u*h+e*c+a*i-r*o),t},translate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=.5*a[0],c=.5*a[1],h=.5*a[2],s=n[4],M=n[5],f=n[6],l=n[7];return t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=o*i+u*h-e*c+s,t[5]=o*c+e*i-r*h+M,t[6]=o*h+r*c-u*i+f,t[7]=-r*i-u*c-e*h+l,t},rotateX:function(t,n,a){var r=-n[0],u=-n[1],e=-n[2],o=n[3],i=n[4],c=n[5],h=n[6],s=n[7],M=i*o+s*r+c*e-h*u,f=c*o+s*u+h*r-i*e,l=h*o+s*e+i*u-c*r,v=s*o-i*r-c*u-h*e;return Et(t,n,a),r=t[0],u=t[1],e=t[2],o=t[3],t[4]=M*o+v*r+f*e-l*u,t[5]=f*o+v*u+l*r-M*e,t[6]=l*o+v*e+M*u-f*r,t[7]=v*o-M*r-f*u-l*e,t},rotateY:function(t,n,a){var r=-n[0],u=-n[1],e=-n[2],o=n[3],i=n[4],c=n[5],h=n[6],s=n[7],M=i*o+s*r+c*e-h*u,f=c*o+s*u+h*r-i*e,l=h*o+s*e+i*u-c*r,v=s*o-i*r-c*u-h*e;return Ot(t,n,a),r=t[0],u=t[1],e=t[2],o=t[3],t[4]=M*o+v*r+f*e-l*u,t[5]=f*o+v*u+l*r-M*e,t[6]=l*o+v*e+M*u-f*r,t[7]=v*o-M*r-f*u-l*e,t},rotateZ:function(t,n,a){var r=-n[0],u=-n[1],e=-n[2],o=n[3],i=n[4],c=n[5],h=n[6],s=n[7],M=i*o+s*r+c*e-h*u,f=c*o+s*u+h*r-i*e,l=h*o+s*e+i*u-c*r,v=s*o-i*r-c*u-h*e;return Tt(t,n,a),r=t[0],u=t[1],e=t[2],o=t[3],t[4]=M*o+v*r+f*e-l*u,t[5]=f*o+v*u+l*r-M*e,t[6]=l*o+v*e+M*u-f*r,t[7]=v*o-M*r-f*u-l*e,t},rotateByQuatAppend:function(t,n,a){var r=a[0],u=a[1],e=a[2],o=a[3],i=n[0],c=n[1],h=n[2],s=n[3];return t[0]=i*o+s*r+c*e-h*u,t[1]=c*o+s*u+h*r-i*e,t[2]=h*o+s*e+i*u-c*r,t[3]=s*o-i*r-c*u-h*e,i=n[4],c=n[5],h=n[6],s=n[7],t[4]=i*o+s*r+c*e-h*u,t[5]=c*o+s*u+h*r-i*e,t[6]=h*o+s*e+i*u-c*r,t[7]=s*o-i*r-c*u-h*e,t},rotateByQuatPrepend:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],c=a[1],h=a[2],s=a[3];return t[0]=r*s+o*i+u*h-e*c,t[1]=u*s+o*c+e*i-r*h,t[2]=e*s+o*h+r*c-u*i,t[3]=o*s-r*i-u*c-e*h,i=a[4],c=a[5],h=a[6],s=a[7],t[4]=r*s+o*i+u*h-e*c,t[5]=u*s+o*c+e*i-r*h,t[6]=e*s+o*h+r*c-u*i,t[7]=o*s-r*i-u*c-e*h,t},rotateAroundAxis:function(t,a,r,u){if(Math.abs(u)0){a=Math.sqrt(a);var r=n[0]/a,u=n[1]/a,e=n[2]/a,o=n[3]/a,i=n[4],c=n[5],h=n[6],s=n[7],M=r*i+u*c+e*h+o*s;t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=(i-r*M)/a,t[5]=(c-u*M)/a,t[6]=(h-e*M)/a,t[7]=(s-o*M)/a}return t},str:function(t){return"quat2("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+")"},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=t[4],c=t[5],h=t[6],s=t[7],M=a[0],f=a[1],l=a[2],v=a[3],b=a[4],m=a[5],d=a[6],x=a[7];return Math.abs(r-M)<=n*Math.max(1,Math.abs(r),Math.abs(M))&&Math.abs(u-f)<=n*Math.max(1,Math.abs(u),Math.abs(f))&&Math.abs(e-l)<=n*Math.max(1,Math.abs(e),Math.abs(l))&&Math.abs(o-v)<=n*Math.max(1,Math.abs(o),Math.abs(v))&&Math.abs(i-b)<=n*Math.max(1,Math.abs(i),Math.abs(b))&&Math.abs(c-m)<=n*Math.max(1,Math.abs(c),Math.abs(m))&&Math.abs(h-d)<=n*Math.max(1,Math.abs(h),Math.abs(d))&&Math.abs(s-x)<=n*Math.max(1,Math.abs(s),Math.abs(x))}});function An(){var t=new a(2);return a!=Float32Array&&(t[0]=0,t[1]=0),t}function wn(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t}function Rn(t,n,a){return t[0]=n[0]*a[0],t[1]=n[1]*a[1],t}function zn(t,n,a){return t[0]=n[0]/a[0],t[1]=n[1]/a[1],t}function Pn(t,n){var a=n[0]-t[0],r=n[1]-t[1];return Math.hypot(a,r)}function jn(t,n){var a=n[0]-t[0],r=n[1]-t[1];return a*a+r*r}function In(t){var n=t[0],a=t[1];return Math.hypot(n,a)}function Sn(t){var n=t[0],a=t[1];return n*n+a*a}var En=In,On=wn,Tn=Rn,Dn=zn,Fn=Pn,Ln=jn,Vn=Sn,Qn=function(){var t=An();return function(n,a,r,u,e,o){var i,c;for(a||(a=2),r||(r=0),c=u?Math.min(u*a+r,n.length):n.length,i=r;i0&&(u=1/Math.sqrt(u)),t[0]=n[0]*u,t[1]=n[1]*u,t},dot:function(t,n){return t[0]*n[0]+t[1]*n[1]},cross:function(t,n,a){var r=n[0]*a[1]-n[1]*a[0];return t[0]=t[1]=0,t[2]=r,t},lerp:function(t,n,a,r){var u=n[0],e=n[1];return t[0]=u+r*(a[0]-u),t[1]=e+r*(a[1]-e),t},random:function(t,n){n=n||1;var a=2*r()*Math.PI;return t[0]=Math.cos(a)*n,t[1]=Math.sin(a)*n,t},transformMat2:function(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[2]*u,t[1]=a[1]*r+a[3]*u,t},transformMat2d:function(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[2]*u+a[4],t[1]=a[1]*r+a[3]*u+a[5],t},transformMat3:function(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[3]*u+a[6],t[1]=a[1]*r+a[4]*u+a[7],t},transformMat4:function(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[4]*u+a[12],t[1]=a[1]*r+a[5]*u+a[13],t},rotate:function(t,n,a,r){var u=n[0]-a[0],e=n[1]-a[1],o=Math.sin(r),i=Math.cos(r);return t[0]=u*i-e*o+a[0],t[1]=u*o+e*i+a[1],t},angle:function(t,n){var a=t[0],r=t[1],u=n[0],e=n[1],o=a*a+r*r;o>0&&(o=1/Math.sqrt(o));var i=u*u+e*e;i>0&&(i=1/Math.sqrt(i));var c=(a*u+r*e)*o*i;return c>1?0:c<-1?Math.PI:Math.acos(c)},zero:function(t){return t[0]=0,t[1]=0,t},str:function(t){return"vec2("+t[0]+", "+t[1]+")"},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]},equals:function(t,a){var r=t[0],u=t[1],e=a[0],o=a[1];return Math.abs(r-e)<=n*Math.max(1,Math.abs(r),Math.abs(e))&&Math.abs(u-o)<=n*Math.max(1,Math.abs(u),Math.abs(o))},len:En,sub:On,mul:Tn,div:Dn,dist:Fn,sqrDist:Ln,sqrLen:Vn,forEach:Qn});t.glMatrix=e,t.mat2=s,t.mat2d=b,t.mat3=q,t.mat4=E,t.quat=sn,t.quat2=gn,t.vec2=Yn,t.vec3=$,t.vec4=Pt,Object.defineProperty(t,"__esModule",{value:!0})}); + +// ["glMatrix", "mat2", "mat2d", "mat3", "mat4", "quat", "quat2", "vec2", "vec3", "vec4"] +window.glMatrix = glMatrix; +window.mat2 = glMatrix.mat2; +window.mat2d = glMatrix.mat2d; +window.mat3 = glMatrix.mat3; +window.mat4 = glMatrix.mat4; +window.quat = glMatrix.quat; +window.quat2 = glMatrix.quat2; +window.vec2 = glMatrix.vec2; +window.vec3 = glMatrix.vec3; +window.vec4 = glMatrix.vec4; + + + +var CABLES = CABLES || {}; CABLES.build = {"timestamp":1671442325495,"created":"2022-12-19T09:32:05.495Z","git":{"branch":"master","commit":"9aa5acdd3f463ec28e2abce3963ff31d3eaf3926","date":null,"message":null}}; \ No newline at end of file diff --git a/survey_dashboard/hmc_layout/static/en_files/libs.js b/survey_dashboard/hmc_layout/static/en_files/libs.js new file mode 100644 index 0000000..e69de29 diff --git a/survey_dashboard/hmc_layout/static/en_files/libs.min.js b/survey_dashboard/hmc_layout/static/en_files/libs.min.js new file mode 100644 index 0000000..e604f8e --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/libs.min.js @@ -0,0 +1,36 @@ +/*! For license information please see colorrick.js.LICENSE.txt */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ColorRick=e():t.ColorRick=e()}(self,(function(){return t={10:(t,e,n)=>{const r=n(792);t.exports=class{constructor(t){if(this._elements=[],this.options=t,this._areaWidth=256,this._areaHeight=150,this._elContainer=document.createElement("div"),this._elContainer.classList.add("colorRick_dialog"),document.body.appendChild(this._elContainer),this._elements.push(this._elContainer),this._elContainer.style.setProperty("--width",this._areaWidth+"px"),this._elContainer.style.setProperty("--height",this._areaHeight+"px"),this._elArea=document.createElement("div"),this._elArea.classList.add("colorRick_area"),this._elContainer.appendChild(this._elArea),this._elements.push(this._elArea),this._elAreaCursor=document.createElement("div"),this._elAreaCursor.classList.add("colorRick_cursor"),this._elArea.appendChild(this._elAreaCursor),this._elements.push(this._elAreaCursor),this._elBrightness=document.createElement("div"),this._elBrightness.classList.add("colorRick_brightness"),this._elArea.appendChild(this._elBrightness),this._elements.push(this._elBrightness),this._elHue=document.createElement("div"),this._elHue.classList.add("colorRick_hue"),this._elContainer.appendChild(this._elHue),this._elements.push(this._elHue),this._elHueCursor=document.createElement("div"),this._elHueCursor.classList.add("colorRick_cursor_hue"),this._elHue.appendChild(this._elHueCursor),this._elements.push(this._elHueCursor),this._elColorBox=document.createElement("div"),this._elColorBox.classList.add("colorRick_preview"),this._elContainer.appendChild(this._elColorBox),this._elements.push(this._elColorBox),this._elColorBoxOrig=document.createElement("div"),this._elColorBoxOrig.classList.add("colorRick_preview"),this._elColorBoxOrig.classList.add("colorRick_preview_orig"),this._elContainer.appendChild(this._elColorBoxOrig),this._elements.push(this._elColorBoxOrig),this._elInputContainer=document.createElement("div"),this._elInputContainer.classList.add("colorRick_inputcontainer"),this._elContainer.appendChild(this._elInputContainer),this._elements.push(this._elInputContainer),this._elInputContainer.innerHTML='
HEX
RGB
HSV
',this._inputHex=document.getElementById("colorRick_input_hex"),this._inputR=document.getElementById("colorRick_input_r"),this._inputG=document.getElementById("colorRick_input_g"),this._inputB=document.getElementById("colorRick_input_b"),this._inputH=document.getElementById("colorRick_input_h"),this._inputS=document.getElementById("colorRick_input_s"),this._inputV=document.getElementById("colorRick_input_v"),this._elements.push(this._inputHex),this._elements.push(this._inputR,this._inputG,this._inputB),this._elements.push(this._inputH,this._inputS,this._inputV),this._color=r("white"),this.options.color&&this.setColor(this.options.color),this._elColorBoxOrig.style.backgroundColor=this._color.hex(),this.updateColorField(),this._inputR.addEventListener("input",t=>{this._setColorFromRgbInputs()}),this._inputG.addEventListener("input",t=>{this._setColorFromRgbInputs()}),this._inputB.addEventListener("input",t=>{this._setColorFromRgbInputs()}),this._inputH.addEventListener("input",t=>{this._setColorFromHsvInputs()}),this._inputS.addEventListener("input",t=>{this._setColorFromHsvInputs()}),this._inputV.addEventListener("input",t=>{this._setColorFromHsvInputs()}),this._inputHex.addEventListener("input",t=>{this.validateHexInput()&&this.setColor(this.validateHexInput())}),this._inputHex.addEventListener("blur",t=>{this.validateHexInput()||(this._inputHex.classList.remove("colorRick_invalid"),this._inputHex.value=this._color.hex())}),this._elHue.addEventListener("pointerdown",this._onHueMouse.bind(this)),this._elHue.addEventListener("pointermove",this._onHueMouse.bind(this)),this._elHue.addEventListener("wheel",t=>{t.deltaY>0?this._hue-=.2:this._hue+=.2,this.updateColorField(),t.preventDefault()}),this.options.ele){const t=this.options.ele.getBoundingClientRect(),e=30,n=this._elContainer.getBoundingClientRect(),r=t.x+e>window.innerWidth-n.width;this._elContainer.style.left=r?t.x-n.width+"px":t.x+e+"px",t.y+n.height>window.innerHeight?this._elContainer.style.top=window.innerHeight-n.height-10+"px":this._elContainer.style.top=t.y+"px"}this._elHue.addEventListener("pointerdown",t=>{this._elHue.setPointerCapture(t.pointerId)}),this._elHue.addEventListener("pointerup",t=>{this._elHue.releasePointerCapture(t.pointerId)}),this._elArea.addEventListener("pointerdown",this._onAreaMouse.bind(this)),this._elArea.addEventListener("pointermove",this._onAreaMouse.bind(this)),this._elArea.addEventListener("wheel",t=>{t.deltaY>0?this._hueV-=.001:this._hueV+=.001,this.updateColorField(),t.preventDefault()}),this._elArea.addEventListener("pointerdown",t=>{this._elArea.setPointerCapture(t.pointerId)}),this._elArea.addEventListener("pointerup",t=>{this._elArea.releasePointerCapture(t.pointerId)}),document.addEventListener("pointerdown",this._clickOutside.bind(this)),this._elColorBoxOrig.addEventListener("click",()=>{this.setColor(this._elColorBoxOrig.style.backgroundColor)})}_clickOutside(t){if(this._elContainer.contains(t.target))return!0;this.close()}validateHexInput(){let t=this._inputHex.value;if(-1==t.indexOf("#")&&(t="#"+t),7==t.length)return this._inputHex.classList.remove("colorRick_invalid"),t;this._inputHex.classList.add("colorRick_invalid")}_setColorFromHsvInputs(){this._color=r(this._inputH.value,this._inputS.value,this._inputV.value,"hsv"),this._hue=this._inputH.value,this._hueS=this._inputS.value,this._hueV=this._inputV.value,this.updateColorField()}_setColorFromRgbInputs(){this.setColor([parseInt(this._inputR.value),parseInt(this._inputG.value),parseInt(this._inputB.value)])}setColor(t){this._color=r(t),this._hue=this._color.hsv()[0],this._hueS=this._color.hsv()[1],this._hueV=this._color.hsv()[2],this._inputH.value=this._color.hsv()[0],this._inputS.value=this._color.hsv()[1],this._inputV.value=this._color.hsv()[2],this.updateColorField()}updateCursors(){this._color.luminance()>.55?this._elAreaCursor.style.backgroundColor="black":this._elAreaCursor.style.backgroundColor="white",this._elHueCursor.style.top=this._areaHeight-this._hue/360*this._areaHeight+"px",this._elAreaCursor.style.marginLeft=this._color.hsv()[1]*this._areaWidth-3+"px",this._elAreaCursor.style.marginTop=this._areaHeight-this._color.hsv()[2]*this._areaHeight-3+"px"}updateColorField(){this._hue!=this._hue&&(this._hue=0),this._hue<0&&(this._hue=0),this._hue>360&&(this._hue=360),this._hueV!=this._hueV&&(this._hueV=1e-4),this._hueV<0&&(this._hueV=1e-4),this._hueV>1&&(this._hueV=1),this._hueS!=this._hueS&&(this._hueS=1e-4),this._hueS<0&&(this._hueS=1e-4),this._hueS>1&&(this._hueS=1),this._color=r(this._hue,this._hueS,this._hueV,"hsv"),this.options.onChange&&this._currentHex!=this._color.hex()&&this.options.onChange(this._color),this._currentHex=this._color.hex();const t=r(this._hue,1,1,"hsv").rgb();this._elArea.style.background="linear-gradient(to right, rgb(255, 255, 255), rgb("+t[0]+", "+t[1]+", "+t[2]+"))",this._elColorBox.style.backgroundColor=this._color.hex(),this._inputHex.value=this._color.hex(),this._inputR.value=this._color.rgb()[0],this._inputG.value=this._color.rgb()[1],this._inputB.value=this._color.rgb()[2],this.updateCursors()}close(){document.removeEventListener("pointerdown",this._clickOutside.bind(this));for(let t=0;tn?n:t},e={},n=0,r=["Boolean","Number","String","Function","Array","Date","RegExp","Undefined","Null"];n255)&&(e._clipped=!0),e[n]=t(e[n],0,255)):3===n&&(e[n]=t(e[n],0,1));return e},limit:t,type:o,unpack:function(t,e){return void 0===e&&(e=null),t.length>=3?Array.prototype.slice.call(t):"object"==o(t[0])&&e?e.split("").filter((function(e){return void 0!==t[0][e]})).map((function(e){return t[0][e]})):t[0]},last:function(t){if(t.length<2)return null;var e=t.length-1;return"string"==o(t[e])?t[e].toLowerCase():null},PI:s,TWOPI:2*s,PITHIRD:s/3,DEG2RAD:s/180,RAD2DEG:180/s},l={format:{},autodetect:[]},u=a.last,h=a.clip_rgb,c=a.type,f=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n=this;if("object"===c(t[0])&&t[0].constructor&&t[0].constructor===this.constructor)return t[0];var r=u(t),i=!1;if(!r){i=!0,l.sorted||(l.autodetect=l.autodetect.sort((function(t,e){return e.p-t.p})),l.sorted=!0);for(var o=0,s=l.autodetect;o4?t[4]:1;return 1===o?[0,0,0,s]:[n>=1?0:255*(1-n)*(1-o),r>=1?0:255*(1-r)*(1-o),i>=1?0:255*(1-i)*(1-o),s]},l.autodetect.push({p:2,test:function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];if(t=y(t,"cmyk"),"array"===_(t)&&4===t.length)return"cmyk"}});var k=a.unpack,w=a.last,S=function(t){return Math.round(100*t)/100},x=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n=k(t,"hsla"),r=w(t)||"lsa";return n[0]=S(n[0]||0),n[1]=S(100*n[1])+"%",n[2]=S(100*n[2])+"%","hsla"===r||n.length>3&&n[3]<1?(n[3]=n.length>3?n[3]:1,r="hsla"):n.length=3,r+"("+n.join(",")+")"},M=a.unpack,C=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n=(t=M(t,"rgba"))[0],r=t[1],i=t[2];n/=255,r/=255,i/=255;var o,s,a=Math.min(n,r,i),l=Math.max(n,r,i),u=(l+a)/2;return l===a?(o=0,s=Number.NaN):o=u<.5?(l-a)/(l+a):(l-a)/(2-l-a),n==l?s=(r-i)/(l-a):r==l?s=2+(i-n)/(l-a):i==l&&(s=4+(n-r)/(l-a)),(s*=60)<0&&(s+=360),t.length>3&&void 0!==t[3]?[s,o,u,t[3]]:[s,o,u]},E=a.unpack,P=a.last,O=Math.round,D=a.unpack,I=Math.round,L=function(){for(var t,e=[],n=arguments.length;n--;)e[n]=arguments[n];var r,i,o,s=(e=D(e,"hsl"))[0],a=e[1],l=e[2];if(0===a)r=i=o=255*l;else{var u=[0,0,0],h=[0,0,0],c=l<.5?l*(1+a):l+a-l*a,f=2*l-c,p=s/360;u[0]=p+1/3,u[1]=p,u[2]=p-1/3;for(var d=0;d<3;d++)u[d]<0&&(u[d]+=1),u[d]>1&&(u[d]-=1),6*u[d]<1?h[d]=f+6*(c-f)*u[d]:2*u[d]<1?h[d]=c:3*u[d]<2?h[d]=f+(c-f)*(2/3-u[d])*6:h[d]=f;r=(t=[I(255*h[0]),I(255*h[1]),I(255*h[2])])[0],i=t[1],o=t[2]}return e.length>3?[r,i,o,e[3]]:[r,i,o,1]},T=/^rgb\(\s*(-?\d+),\s*(-?\d+)\s*,\s*(-?\d+)\s*\)$/,A=/^rgba\(\s*(-?\d+),\s*(-?\d+)\s*,\s*(-?\d+)\s*,\s*([01]|[01]?\.\d+)\)$/,B=/^rgb\(\s*(-?\d+(?:\.\d+)?)%,\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*\)$/,R=/^rgba\(\s*(-?\d+(?:\.\d+)?)%,\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,N=/^hsl\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*\)$/,H=/^hsla\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,F=Math.round,Y=function(t){var e;if(t=t.toLowerCase().trim(),l.format.named)try{return l.format.named(t)}catch(t){}if(e=t.match(T)){for(var n=e.slice(1,4),r=0;r<3;r++)n[r]=+n[r];return n[3]=1,n}if(e=t.match(A)){for(var i=e.slice(1,5),o=0;o<4;o++)i[o]=+i[o];return i}if(e=t.match(B)){for(var s=e.slice(1,4),a=0;a<3;a++)s[a]=F(2.55*s[a]);return s[3]=1,s}if(e=t.match(R)){for(var u=e.slice(1,5),h=0;h<3;h++)u[h]=F(2.55*u[h]);return u[3]=+u[3],u}if(e=t.match(N)){var c=e.slice(1,4);c[1]*=.01,c[2]*=.01;var f=L(c);return f[3]=1,f}if(e=t.match(H)){var p=e.slice(1,4);p[1]*=.01,p[2]*=.01;var d=L(p);return d[3]=+e[4],d}};Y.test=function(t){return T.test(t)||A.test(t)||B.test(t)||R.test(t)||N.test(t)||H.test(t)};var W=Y,$=a.type;p.prototype.css=function(t){return function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n=E(t,"rgba"),r=P(t)||"rgb";return"hsl"==r.substr(0,3)?x(C(n),r):(n[0]=O(n[0]),n[1]=O(n[1]),n[2]=O(n[2]),("rgba"===r||n.length>3&&n[3]<1)&&(n[3]=n.length>3?n[3]:1,r="rgba"),r+"("+n.slice(0,"rgb"===r?3:4).join(",")+")")}(this._rgb,t)},g.css=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return new(Function.prototype.bind.apply(p,[null].concat(t,["css"])))},l.format.css=W,l.autodetect.push({p:5,test:function(t){for(var e=[],n=arguments.length-1;n-- >0;)e[n]=arguments[n+1];if(!e.length&&"string"===$(t)&&W.test(t))return"css"}});var j=a.unpack;l.format.gl=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n=j(t,"rgba");return n[0]*=255,n[1]*=255,n[2]*=255,n},g.gl=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return new(Function.prototype.bind.apply(p,[null].concat(t,["gl"])))},p.prototype.gl=function(){var t=this._rgb;return[t[0]/255,t[1]/255,t[2]/255,t[3]]};var z=a.unpack,G=a.unpack,U=Math.floor,q=a.unpack,V=a.type;p.prototype.hcg=function(){return function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n,r=z(t,"rgb"),i=r[0],o=r[1],s=r[2],a=Math.min(i,o,s),l=Math.max(i,o,s),u=l-a,h=100*u/255,c=a/(255-u)*100;return 0===u?n=Number.NaN:(i===l&&(n=(o-s)/u),o===l&&(n=2+(s-i)/u),s===l&&(n=4+(i-o)/u),(n*=60)<0&&(n+=360)),[n,h,c]}(this._rgb)},g.hcg=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return new(Function.prototype.bind.apply(p,[null].concat(t,["hcg"])))},l.format.hcg=function(){for(var t,e,n,r,i,o,s=[],a=arguments.length;a--;)s[a]=arguments[a];var l,u,h,c=(s=G(s,"hcg"))[0],f=s[1],p=s[2];p*=255;var d=255*f;if(0===f)l=u=h=p;else{360===c&&(c=0),c>360&&(c-=360),c<0&&(c+=360);var g=U(c/=60),m=c-g,v=p*(1-f),b=v+d*(1-m),y=v+d*m,_=v+d;switch(g){case 0:l=(t=[_,y,v])[0],u=t[1],h=t[2];break;case 1:l=(e=[b,_,v])[0],u=e[1],h=e[2];break;case 2:l=(n=[v,_,y])[0],u=n[1],h=n[2];break;case 3:l=(r=[v,b,_])[0],u=r[1],h=r[2];break;case 4:l=(i=[y,v,_])[0],u=i[1],h=i[2];break;case 5:l=(o=[_,v,b])[0],u=o[1],h=o[2]}}return[l,u,h,s.length>3?s[3]:1]},l.autodetect.push({p:1,test:function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];if(t=q(t,"hcg"),"array"===V(t)&&3===t.length)return"hcg"}});var K=a.unpack,X=a.last,Q=Math.round,J=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n=K(t,"rgba"),r=n[0],i=n[1],o=n[2],s=n[3],a=X(t)||"auto";void 0===s&&(s=1),"auto"===a&&(a=s<1?"rgba":"rgb");var l="000000"+((r=Q(r))<<16|(i=Q(i))<<8|(o=Q(o))).toString(16);l=l.substr(l.length-6);var u="0"+Q(255*s).toString(16);switch(u=u.substr(u.length-2),a.toLowerCase()){case"rgba":return"#"+l+u;case"argb":return"#"+u+l;default:return"#"+l}},Z=/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,tt=/^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$/,et=function(t){if(t.match(Z)){4!==t.length&&7!==t.length||(t=t.substr(1)),3===t.length&&(t=(t=t.split(""))[0]+t[0]+t[1]+t[1]+t[2]+t[2]);var e=parseInt(t,16);return[e>>16,e>>8&255,255&e,1]}if(t.match(tt)){5!==t.length&&9!==t.length||(t=t.substr(1)),4===t.length&&(t=(t=t.split(""))[0]+t[0]+t[1]+t[1]+t[2]+t[2]+t[3]+t[3]);var n=parseInt(t,16);return[n>>24&255,n>>16&255,n>>8&255,Math.round((255&n)/255*100)/100]}throw new Error("unknown hex color: "+t)},nt=a.type;p.prototype.hex=function(t){return J(this._rgb,t)},g.hex=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return new(Function.prototype.bind.apply(p,[null].concat(t,["hex"])))},l.format.hex=et,l.autodetect.push({p:4,test:function(t){for(var e=[],n=arguments.length-1;n-- >0;)e[n]=arguments[n+1];if(!e.length&&"string"===nt(t)&&[3,4,5,6,7,8,9].indexOf(t.length)>=0)return"hex"}});var rt=a.unpack,it=a.TWOPI,ot=Math.min,st=Math.sqrt,at=Math.acos,lt=a.unpack,ut=a.limit,ht=a.TWOPI,ct=a.PITHIRD,ft=Math.cos,pt=a.unpack,dt=a.type;p.prototype.hsi=function(){return function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n,r=rt(t,"rgb"),i=r[0],o=r[1],s=r[2],a=ot(i/=255,o/=255,s/=255),l=(i+o+s)/3,u=l>0?1-a/l:0;return 0===u?n=NaN:(n=(i-o+(i-s))/2,n/=st((i-o)*(i-o)+(i-s)*(o-s)),n=at(n),s>o&&(n=it-n),n/=it),[360*n,u,l]}(this._rgb)},g.hsi=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return new(Function.prototype.bind.apply(p,[null].concat(t,["hsi"])))},l.format.hsi=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n,r,i,o=(t=lt(t,"hsi"))[0],s=t[1],a=t[2];return isNaN(o)&&(o=0),isNaN(s)&&(s=0),o>360&&(o-=360),o<0&&(o+=360),(o/=360)<1/3?r=1-((i=(1-s)/3)+(n=(1+s*ft(ht*o)/ft(ct-ht*o))/3)):o<2/3?i=1-((n=(1-s)/3)+(r=(1+s*ft(ht*(o-=1/3))/ft(ct-ht*o))/3)):n=1-((r=(1-s)/3)+(i=(1+s*ft(ht*(o-=2/3))/ft(ct-ht*o))/3)),[255*(n=ut(a*n*3)),255*(r=ut(a*r*3)),255*(i=ut(a*i*3)),t.length>3?t[3]:1]},l.autodetect.push({p:2,test:function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];if(t=pt(t,"hsi"),"array"===dt(t)&&3===t.length)return"hsi"}});var gt=a.unpack,mt=a.type;p.prototype.hsl=function(){return C(this._rgb)},g.hsl=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return new(Function.prototype.bind.apply(p,[null].concat(t,["hsl"])))},l.format.hsl=L,l.autodetect.push({p:2,test:function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];if(t=gt(t,"hsl"),"array"===mt(t)&&3===t.length)return"hsl"}});var vt=a.unpack,bt=Math.min,yt=Math.max,_t=a.unpack,kt=Math.floor,wt=a.unpack,St=a.type;p.prototype.hsv=function(){return function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n,r,i,o=(t=vt(t,"rgb"))[0],s=t[1],a=t[2],l=bt(o,s,a),u=yt(o,s,a),h=u-l;return i=u/255,0===u?(n=Number.NaN,r=0):(r=h/u,o===u&&(n=(s-a)/h),s===u&&(n=2+(a-o)/h),a===u&&(n=4+(o-s)/h),(n*=60)<0&&(n+=360)),[n,r,i]}(this._rgb)},g.hsv=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return new(Function.prototype.bind.apply(p,[null].concat(t,["hsv"])))},l.format.hsv=function(){for(var t,e,n,r,i,o,s=[],a=arguments.length;a--;)s[a]=arguments[a];var l,u,h,c=(s=_t(s,"hsv"))[0],f=s[1],p=s[2];if(p*=255,0===f)l=u=h=p;else{360===c&&(c=0),c>360&&(c-=360),c<0&&(c+=360);var d=kt(c/=60),g=c-d,m=p*(1-f),v=p*(1-f*g),b=p*(1-f*(1-g));switch(d){case 0:l=(t=[p,b,m])[0],u=t[1],h=t[2];break;case 1:l=(e=[v,p,m])[0],u=e[1],h=e[2];break;case 2:l=(n=[m,p,b])[0],u=n[1],h=n[2];break;case 3:l=(r=[m,v,p])[0],u=r[1],h=r[2];break;case 4:l=(i=[b,m,p])[0],u=i[1],h=i[2];break;case 5:l=(o=[p,m,v])[0],u=o[1],h=o[2]}}return[l,u,h,s.length>3?s[3]:1]},l.autodetect.push({p:2,test:function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];if(t=wt(t,"hsv"),"array"===St(t)&&3===t.length)return"hsv"}});var xt=.95047,Mt=1.08883,Ct=.137931034,Et=.12841855,Pt=a.unpack,Ot=Math.pow,Dt=function(t){return(t/=255)<=.04045?t/12.92:Ot((t+.055)/1.055,2.4)},It=function(t){return t>.008856452?Ot(t,1/3):t/Et+Ct},Lt=function(t,e,n){return t=Dt(t),e=Dt(e),n=Dt(n),[It((.4124564*t+.3575761*e+.1804375*n)/xt),It((.2126729*t+.7151522*e+.072175*n)/1),It((.0193339*t+.119192*e+.9503041*n)/Mt)]},Tt=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n=Pt(t,"rgb"),r=n[0],i=n[1],o=n[2],s=Lt(r,i,o),a=s[0],l=s[1],u=116*l-16;return[u<0?0:u,500*(a-l),200*(l-s[2])]},At=a.unpack,Bt=Math.pow,Rt=function(t){return 255*(t<=.00304?12.92*t:1.055*Bt(t,1/2.4)-.055)},Nt=function(t){return t>.206896552?t*t*t:Et*(t-Ct)},Ht=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n,r,i,o=(t=At(t,"lab"))[0],s=t[1],a=t[2];return r=(o+16)/116,n=isNaN(s)?r:r+s/500,i=isNaN(a)?r:r-a/200,r=1*Nt(r),n=xt*Nt(n),i=Mt*Nt(i),[Rt(3.2404542*n-1.5371385*r-.4985314*i),Rt(-.969266*n+1.8760108*r+.041556*i),Rt(.0556434*n-.2040259*r+1.0572252*i),t.length>3?t[3]:1]},Ft=a.unpack,Yt=a.type;p.prototype.lab=function(){return Tt(this._rgb)},g.lab=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return new(Function.prototype.bind.apply(p,[null].concat(t,["lab"])))},l.format.lab=Ht,l.autodetect.push({p:2,test:function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];if(t=Ft(t,"lab"),"array"===Yt(t)&&3===t.length)return"lab"}});var Wt=a.unpack,$t=a.RAD2DEG,jt=Math.sqrt,zt=Math.atan2,Gt=Math.round,Ut=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n=Wt(t,"lab"),r=n[0],i=n[1],o=n[2],s=jt(i*i+o*o),a=(zt(o,i)*$t+360)%360;return 0===Gt(1e4*s)&&(a=Number.NaN),[r,s,a]},qt=a.unpack,Vt=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n=qt(t,"rgb"),r=n[0],i=n[1],o=n[2],s=Tt(r,i,o),a=s[0],l=s[1],u=s[2];return Ut(a,l,u)},Kt=a.unpack,Xt=a.DEG2RAD,Qt=Math.sin,Jt=Math.cos,Zt=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n=Kt(t,"lch"),r=n[0],i=n[1],o=n[2];return isNaN(o)&&(o=0),[r,Jt(o*=Xt)*i,Qt(o)*i]},te=a.unpack,ee=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n=(t=te(t,"lch"))[0],r=t[1],i=t[2],o=Zt(n,r,i),s=o[0],a=o[1],l=o[2],u=Ht(s,a,l);return[u[0],u[1],u[2],t.length>3?t[3]:1]},ne=a.unpack,re=a.unpack,ie=a.type;p.prototype.lch=function(){return Vt(this._rgb)},p.prototype.hcl=function(){return Vt(this._rgb).reverse()},g.lch=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return new(Function.prototype.bind.apply(p,[null].concat(t,["lch"])))},g.hcl=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return new(Function.prototype.bind.apply(p,[null].concat(t,["hcl"])))},l.format.lch=ee,l.format.hcl=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n=ne(t,"hcl").reverse();return ee.apply(void 0,n)},["lch","hcl"].forEach((function(t){return l.autodetect.push({p:2,test:function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];if(e=re(e,t),"array"===ie(e)&&3===e.length)return t}})}));var oe={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflower:"#6495ed",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",laserlemon:"#ffff54",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrod:"#fafad2",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",maroon2:"#7f0000",maroon3:"#b03060",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",purple2:"#7f007f",purple3:"#a020f0",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"},se=a.type;p.prototype.name=function(){for(var t=J(this._rgb,"rgb"),e=0,n=Object.keys(oe);e0;)e[n]=arguments[n+1];if(!e.length&&"string"===se(t)&&oe[t.toLowerCase()])return"named"}});var ae=a.unpack,le=a.type,ue=a.type;p.prototype.num=function(){return function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n=ae(t,"rgb");return(n[0]<<16)+(n[1]<<8)+n[2]}(this._rgb)},g.num=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return new(Function.prototype.bind.apply(p,[null].concat(t,["num"])))},l.format.num=function(t){if("number"==le(t)&&t>=0&&t<=16777215)return[t>>16,t>>8&255,255&t,1];throw new Error("unknown num color: "+t)},l.autodetect.push({p:5,test:function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];if(1===t.length&&"number"===ue(t[0])&&t[0]>=0&&t[0]<=16777215)return"num"}});var he=a.unpack,ce=a.type,fe=Math.round;p.prototype.rgb=function(t){return void 0===t&&(t=!0),!1===t?this._rgb.slice(0,3):this._rgb.slice(0,3).map(fe)},p.prototype.rgba=function(t){return void 0===t&&(t=!0),this._rgb.slice(0,4).map((function(e,n){return n<3?!1===t?e:fe(e):e}))},g.rgb=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return new(Function.prototype.bind.apply(p,[null].concat(t,["rgb"])))},l.format.rgb=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var n=he(t,"rgba");return void 0===n[3]&&(n[3]=1),n},l.autodetect.push({p:3,test:function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];if(t=he(t,"rgba"),"array"===ce(t)&&(3===t.length||4===t.length&&"number"==ce(t[3])&&t[3]>=0&&t[3]<=1))return"rgb"}});var pe=Math.log,de=function(t){var e,n,r,i=t/100;return i<66?(e=255,n=-155.25485562709179-.44596950469579133*(n=i-2)+104.49216199393888*pe(n),r=i<20?0:.8274096064007395*(r=i-10)-254.76935184120902+115.67994401066147*pe(r)):(e=351.97690566805693+.114206453784165*(e=i-55)-40.25366309332127*pe(e),n=325.4494125711974+.07943456536662342*(n=i-50)-28.0852963507957*pe(n),r=255),[e,n,r,1]},ge=a.unpack,me=Math.round;p.prototype.temp=p.prototype.kelvin=p.prototype.temperature=function(){return function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];for(var n,r=ge(t,"rgb"),i=r[0],o=r[2],s=1e3,a=4e4,l=.4;a-s>l;){var u=de(n=.5*(a+s));u[2]/u[0]>=o/i?a=n:s=n}return me(n)}(this._rgb)},g.temp=g.kelvin=g.temperature=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return new(Function.prototype.bind.apply(p,[null].concat(t,["temp"])))},l.format.temp=l.format.kelvin=l.format.temperature=de;var ve=a.type;p.prototype.alpha=function(t,e){return void 0===e&&(e=!1),void 0!==t&&"number"===ve(t)?e?(this._rgb[3]=t,this):new p([this._rgb[0],this._rgb[1],this._rgb[2],t],"rgb"):this._rgb[3]},p.prototype.clipped=function(){return this._rgb._clipped||!1},p.prototype.darken=function(t){void 0===t&&(t=1);var e=this.lab();return e[0]-=18*t,new p(e,"lab").alpha(this.alpha(),!0)},p.prototype.brighten=function(t){return void 0===t&&(t=1),this.darken(-t)},p.prototype.darker=p.prototype.darken,p.prototype.brighter=p.prototype.brighten,p.prototype.get=function(t){var e=t.split("."),n=e[0],r=e[1],i=this[n]();if(r){var o=n.indexOf(r);if(o>-1)return i[o];throw new Error("unknown channel "+r+" in mode "+n)}return i};var be=a.type,ye=Math.pow;p.prototype.luminance=function(t){if(void 0!==t&&"number"===be(t)){if(0===t)return new p([0,0,0,this._rgb[3]],"rgb");if(1===t)return new p([255,255,255,this._rgb[3]],"rgb");var e=this.luminance(),n=20,r=function(e,i){var o=e.interpolate(i,.5,"rgb"),s=o.luminance();return Math.abs(t-s)<1e-7||!n--?o:s>t?r(e,o):r(o,i)},i=(e>t?r(new p([0,0,0]),this):r(this,new p([255,255,255]))).rgb();return new p(i.concat([this._rgb[3]]))}return _e.apply(void 0,this._rgb.slice(0,3))};var _e=function(t,e,n){return.2126*(t=ke(t))+.7152*(e=ke(e))+.0722*ke(n)},ke=function(t){return(t/=255)<=.03928?t/12.92:ye((t+.055)/1.055,2.4)},we={},Se=a.type,xe=function(t,e,n){void 0===n&&(n=.5);for(var r=[],i=arguments.length-3;i-- >0;)r[i]=arguments[i+3];var o=r[0]||"lrgb";if(we[o]||r.length||(o=Object.keys(we)[0]),!we[o])throw new Error("interpolation mode "+o+" is not defined");return"object"!==Se(t)&&(t=new p(t)),"object"!==Se(e)&&(e=new p(e)),we[o](t,e,n).alpha(t.alpha()+n*(e.alpha()-t.alpha()))};p.prototype.mix=p.prototype.interpolate=function(t,e){void 0===e&&(e=.5);for(var n=[],r=arguments.length-2;r-- >0;)n[r]=arguments[r+2];return xe.apply(void 0,[this,t,e].concat(n))},p.prototype.premultiply=function(t){void 0===t&&(t=!1);var e=this._rgb,n=e[3];return t?(this._rgb=[e[0]*n,e[1]*n,e[2]*n,n],this):new p([e[0]*n,e[1]*n,e[2]*n,n],"rgb")},p.prototype.saturate=function(t){void 0===t&&(t=1);var e=this.lch();return e[1]+=18*t,e[1]<0&&(e[1]=0),new p(e,"lch").alpha(this.alpha(),!0)},p.prototype.desaturate=function(t){return void 0===t&&(t=1),this.saturate(-t)};var Me=a.type;p.prototype.set=function(t,e,n){void 0===n&&(n=!1);var r=t.split("."),i=r[0],o=r[1],s=this[i]();if(o){var a=i.indexOf(o);if(a>-1){if("string"==Me(e))switch(e.charAt(0)){case"+":case"-":s[a]+=+e;break;case"*":s[a]*=+e.substr(1);break;case"/":s[a]/=+e.substr(1);break;default:s[a]=+e}else{if("number"!==Me(e))throw new Error("unsupported value for Color.set");s[a]=e}var l=new p(s,i);return n?(this._rgb=l._rgb,this):l}throw new Error("unknown channel "+o+" in mode "+i)}return s},we.rgb=function(t,e,n){var r=t._rgb,i=e._rgb;return new p(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),"rgb")};var Ce=Math.sqrt,Ee=Math.pow;we.lrgb=function(t,e,n){var r=t._rgb,i=r[0],o=r[1],s=r[2],a=e._rgb,l=a[0],u=a[1],h=a[2];return new p(Ce(Ee(i,2)*(1-n)+Ee(l,2)*n),Ce(Ee(o,2)*(1-n)+Ee(u,2)*n),Ce(Ee(s,2)*(1-n)+Ee(h,2)*n),"rgb")},we.lab=function(t,e,n){var r=t.lab(),i=e.lab();return new p(r[0]+n*(i[0]-r[0]),r[1]+n*(i[1]-r[1]),r[2]+n*(i[2]-r[2]),"lab")};var Pe=function(t,e,n,r){var i,o,s,a,l,u,h,c,f,d,g,m;return"hsl"===r?(s=t.hsl(),a=e.hsl()):"hsv"===r?(s=t.hsv(),a=e.hsv()):"hcg"===r?(s=t.hcg(),a=e.hcg()):"hsi"===r?(s=t.hsi(),a=e.hsi()):"lch"!==r&&"hcl"!==r||(r="hcl",s=t.hcl(),a=e.hcl()),"h"===r.substr(0,1)&&(l=(i=s)[0],h=i[1],f=i[2],u=(o=a)[0],c=o[1],d=o[2]),isNaN(l)||isNaN(u)?isNaN(l)?isNaN(u)?m=Number.NaN:(m=u,1!=f&&0!=f||"hsv"==r||(g=c)):(m=l,1!=d&&0!=d||"hsv"==r||(g=h)):m=l+n*(u>l&&u-l>180?u-(l+360):u180?u+360-l:u-l),void 0===g&&(g=h+n*(c-h)),new p([m,g,f+n*(d-f)],r)},Oe=function(t,e,n){return Pe(t,e,n,"lch")};we.lch=Oe,we.hcl=Oe,we.num=function(t,e,n){var r=t.num(),i=e.num();return new p(r+n*(i-r),"num")},we.hcg=function(t,e,n){return Pe(t,e,n,"hcg")},we.hsi=function(t,e,n){return Pe(t,e,n,"hsi")},we.hsl=function(t,e,n){return Pe(t,e,n,"hsl")},we.hsv=function(t,e,n){return Pe(t,e,n,"hsv")};var De=a.clip_rgb,Ie=Math.pow,Le=Math.sqrt,Te=Math.PI,Ae=Math.cos,Be=Math.sin,Re=Math.atan2,Ne=a.type,He=Math.pow,Fe=function(t){var e="rgb",n=g("#ccc"),r=0,i=[0,1],o=[],s=[0,0],a=!1,l=[],u=!1,h=0,c=1,f=!1,p={},d=!0,m=1,v=function(t){if((t=t||["#fff","#000"])&&"string"===Ne(t)&&g.brewer&&g.brewer[t.toLowerCase()]&&(t=g.brewer[t.toLowerCase()]),"array"===Ne(t)){1===t.length&&(t=[t[0],t[0]]),t=t.slice(0);for(var e=0;e2?function(t){if(null!=a){for(var e=a.length-1,n=0;n=a[n];)n++;return n-1}return 0}(t)/(a.length-2):c!==h?(t-h)/(c-h):1,u=y(u),r||(u=b(u)),1!==m&&(u=He(u,m)),u=s[0]+u*(1-s[0]-s[1]),u=Math.min(1,Math.max(0,u));var f=Math.floor(1e4*u);if(d&&p[f])i=p[f];else{if("array"===Ne(l))for(var v=0;v=_&&v===o.length-1){i=l[v];break}if(u>_&&u2){var u=t.map((function(e,n){return n/(t.length-1)})),f=t.map((function(t){return(t-h)/(c-h)}));f.every((function(t,e){return u[e]===t}))||(y=function(t){if(t<=0||t>=1)return t;for(var e=0;t>=f[e+1];)e++;var n=(t-f[e])/(f[e+1]-f[e]);return u[e]+n*(u[e+1]-u[e])})}}return i=[h,c],w},w.mode=function(t){return arguments.length?(e=t,k(),w):e},w.range=function(t,e){return v(t),w},w.out=function(t){return u=t,w},w.spread=function(t){return arguments.length?(r=t,w):r},w.correctLightness=function(t){return null==t&&(t=!0),f=t,k(),b=f?function(t){for(var e=_(0,!0).lab()[0],n=_(1,!0).lab()[0],r=e>n,i=_(t,!0).lab()[0],o=e+(n-e)*t,s=i-o,a=0,l=1,u=20;Math.abs(s)>.01&&u-- >0;)r&&(s*=-1),s<0?(a=t,t+=.5*(l-t)):(l=t,t+=.5*(a-t)),s=(i=_(t,!0).lab()[0])-o;return t}:function(t){return t},w},w.padding=function(t){return null!=t?("number"===Ne(t)&&(t=[t,t]),s=t,w):s},w.colors=function(e,n){arguments.length<2&&(n="hex");var r=[];if(0===arguments.length)r=l.slice(0);else if(1===e)r=[w(.5)];else if(e>1){var o=i[0],s=i[1]-o;r=Ye(0,e,!1).map((function(t){return w(o+t/(e-1)*s)}))}else{t=[];var u=[];if(a&&a.length>2)for(var h=1,c=a.length,f=1<=c;f?hc;f?h++:h--)u.push(.5*(a[h-1]+a[h]));else u=i;r=u.map((function(t){return w(t)}))}return g[n]&&(r=r.map((function(t){return t[n]()}))),r},w.cache=function(t){return null!=t?(d=t,w):d},w.gamma=function(t){return null!=t?(m=t,w):m},w.nodata=function(t){return null!=t?(n=g(t),w):n},w};function Ye(t,e,n){for(var r=[],i=to;i?s++:s--)r.push(s);return r}var We=function(t){var e,n,r,i,o,s,a;if(2===(t=t.map((function(t){return new p(t)}))).length)e=t.map((function(t){return t.lab()})),o=e[0],s=e[1],i=function(t){var e=[0,1,2].map((function(e){return o[e]+t*(s[e]-o[e])}));return new p(e,"lab")};else if(3===t.length)n=t.map((function(t){return t.lab()})),o=n[0],s=n[1],a=n[2],i=function(t){var e=[0,1,2].map((function(e){return(1-t)*(1-t)*o[e]+2*(1-t)*t*s[e]+t*t*a[e]}));return new p(e,"lab")};else if(4===t.length){var l;r=t.map((function(t){return t.lab()})),o=r[0],s=r[1],a=r[2],l=r[3],i=function(t){var e=[0,1,2].map((function(e){return(1-t)*(1-t)*(1-t)*o[e]+3*(1-t)*(1-t)*t*s[e]+3*(1-t)*t*t*a[e]+t*t*t*l[e]}));return new p(e,"lab")}}else if(5===t.length){var u=We(t.slice(0,3)),h=We(t.slice(2,5));i=function(t){return t<.5?u(2*t):h(2*(t-.5))}}return i},$e=function(t,e,n){if(!$e[n])throw new Error("unknown blend mode "+n);return $e[n](t,e)},je=function(t){return function(e,n){var r=g(n).rgb(),i=g(e).rgb();return g.rgb(t(r,i))}},ze=function(t){return function(e,n){var r=[];return r[0]=t(e[0],n[0]),r[1]=t(e[1],n[1]),r[2]=t(e[2],n[2]),r}};$e.normal=je(ze((function(t){return t}))),$e.multiply=je(ze((function(t,e){return t*e/255}))),$e.screen=je(ze((function(t,e){return 255*(1-(1-t/255)*(1-e/255))}))),$e.overlay=je(ze((function(t,e){return e<128?2*t*e/255:255*(1-2*(1-t/255)*(1-e/255))}))),$e.darken=je(ze((function(t,e){return t>e?e:t}))),$e.lighten=je(ze((function(t,e){return t>e?t:e}))),$e.dodge=je(ze((function(t,e){return 255===t||(t=e/255*255/(1-t/255))>255?255:t}))),$e.burn=je(ze((function(t,e){return 255*(1-(1-e/255)/(t/255))})));for(var Ge=$e,Ue=a.type,qe=a.clip_rgb,Ve=a.TWOPI,Ke=Math.pow,Xe=Math.sin,Qe=Math.cos,Je=Math.floor,Ze=Math.random,tn=Math.log,en=Math.pow,nn=Math.floor,rn=Math.abs,on=function(t,e){void 0===e&&(e=null);var n={min:Number.MAX_VALUE,max:-1*Number.MAX_VALUE,sum:0,values:[],count:0};return"object"===o(t)&&(t=Object.values(t)),t.forEach((function(t){e&&"object"===o(t)&&(t=t[e]),null==t||isNaN(t)||(n.values.push(t),n.sum+=t,tn.max&&(n.max=t),n.count+=1)})),n.domain=[n.min,n.max],n.limits=function(t,e){return sn(n,t,e)},n},sn=function(t,e,n){void 0===e&&(e="equal"),void 0===n&&(n=7),"array"==o(t)&&(t=on(t));var r=t.min,i=t.max,s=t.values.sort((function(t,e){return t-e}));if(1===n)return[r,i];var a=[];if("c"===e.substr(0,1)&&(a.push(r),a.push(i)),"e"===e.substr(0,1)){a.push(r);for(var l=1;l 0");var u=Math.LOG10E*tn(r),h=Math.LOG10E*tn(i);a.push(r);for(var c=1;c200&&(_=!1)}for(var R={},N=0;N.9999999&&(r[3]=1),new p(De(r))}(t,n);for(var o=t.shift(),s=o.get(e),a=[],l=0,u=0,h=0;h=360;)g-=360;s[d]=g}else s[d]=s[d]/a[d];return f/=r,new p(s,e).alpha(f>.99999?1:f,!0)},g.bezier=function(t){var e=We(t);return e.scale=function(){return Fe(e)},e},g.blend=Ge,g.cubehelix=function(t,e,n,r,i){void 0===t&&(t=300),void 0===e&&(e=-1.5),void 0===n&&(n=1),void 0===r&&(r=1),void 0===i&&(i=[0,1]);var o,s=0;"array"===Ue(i)?o=i[1]-i[0]:(o=0,i=[i,i]);var a=function(a){var l=Ve*((t+120)/360+e*a),u=Ke(i[0]+o*a,r),h=(0!==s?n[0]+a*s:n)*u*(1-u)/2,c=Qe(l),f=Xe(l);return g(qe([255*(u+h*(-.14861*c+1.78277*f)),255*(u+h*(-.29227*c-.90649*f)),255*(u+h*(1.97294*c)),1]))};return a.start=function(e){return null==e?t:(t=e,a)},a.rotations=function(t){return null==t?e:(e=t,a)},a.gamma=function(t){return null==t?r:(r=t,a)},a.hue=function(t){return null==t?n:("array"===Ue(n=t)?0==(s=n[1]-n[0])&&(n=n[1]):s=0,a)},a.lightness=function(t){return null==t?i:("array"===Ue(t)?(i=t,o=t[1]-t[0]):(i=[t,t],o=0),a)},a.scale=function(){return g.scale(a)},a.hue(n),a},g.mix=g.interpolate=xe,g.random=function(){for(var t="#",e=0;e<6;e++)t+="0123456789abcdef".charAt(Je(16*Ze()));return new p(t,"hex")},g.scale=Fe,g.analyze=an.analyze,g.contrast=function(t,e){t=new p(t),e=new p(e);var n=t.luminance(),r=e.luminance();return n>r?(n+.05)/(r+.05):(r+.05)/(n+.05)},g.deltaE=function(t,e,n,r){void 0===n&&(n=1),void 0===r&&(r=1),t=new p(t),e=new p(e);for(var i=Array.from(t.lab()),o=i[0],s=i[1],a=i[2],l=Array.from(e.lab()),u=l[0],h=l[1],c=l[2],f=ln(s*s+a*a),d=ln(h*h+c*c),g=o<16?.511:.040975*o/(1+.01765*o),m=.0638*f/(1+.0131*f)+.638,v=f<1e-6?0:180*un(a,s)/fn;v<0;)v+=360;for(;v>=360;)v-=360;var b=v>=164&&v<=345?.56+hn(.2*cn(fn*(v+168)/180)):.36+hn(.4*cn(fn*(v+35)/180)),y=f*f*f*f,_=ln(y/(y+1900)),k=m*(_*b+1-_),w=f-d,S=s-h,x=a-c,M=(o-u)/(n*g),C=w/(r*m);return ln(M*M+C*C+(S*S+x*x-w*w)/(k*k))},g.distance=function(t,e,n){void 0===n&&(n="lab"),t=new p(t),e=new p(e);var r=t.get(n),i=e.get(n),o=0;for(var s in r){var a=(r[s]||0)-(i[s]||0);o+=a*a}return Math.sqrt(o)},g.limits=an.limits,g.valid=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];try{return new(Function.prototype.bind.apply(p,[null].concat(t))),!0}catch(t){return!1}},g.scales=pn,g.colors=oe,g.brewer=bn,g}()}},e={},function n(r){var i=e[r];if(void 0!==i)return i.exports;var o=e[r]={exports:{}};return t[r].call(o.exports,o,o.exports,n),o.exports}(10);var t,e})), +/**! + + @license + handlebars v4.5.3 + +Copyright (C) 2011-2017 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Handlebars=e():t.Handlebars=e()}(this,(function(){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={exports:{},id:r,loaded:!1};return t[r].call(i.exports,i,i.exports,n),i.loaded=!0,i.exports}return n.m=t,n.c=e,n.p="",n(0)}([function(t,e,n){"use strict";var r=n(1).default;e.__esModule=!0;var i=r(n(2)),o=r(n(40)),s=n(41),a=n(46),l=r(n(49)),u=r(n(44)),h=r(n(39)),c=i.default.create;function f(){var t=c();return t.compile=function(e,n){return a.compile(e,n,t)},t.precompile=function(e,n){return a.precompile(e,n,t)},t.AST=o.default,t.Compiler=a.Compiler,t.JavaScriptCompiler=l.default,t.Parser=s.parser,t.parse=s.parse,t.parseWithoutProcessing=s.parseWithoutProcessing,t}var p=f();p.create=f,h.default(p),p.Visitor=u.default,p.default=p,e.default=p,t.exports=e.default},function(t,e){"use strict";e.default=function(t){return t&&t.__esModule?t:{default:t}},e.__esModule=!0},function(t,e,n){"use strict";var r=n(3).default,i=n(1).default;e.__esModule=!0;var o=r(n(4)),s=i(n(33)),a=i(n(6)),l=r(n(5)),u=r(n(34)),h=i(n(39));function c(){var t=new o.HandlebarsEnvironment;return l.extend(t,o),t.SafeString=s.default,t.Exception=a.default,t.Utils=l,t.escapeExpression=l.escapeExpression,t.VM=u,t.template=function(e){return u.template(e,t)},t}var f=c();f.create=c,h.default(f),f.default=f,e.default=f,t.exports=e.default},function(t,e){"use strict";e.default=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e},e.__esModule=!0},function(t,e,n){"use strict";var r=n(1).default;e.__esModule=!0,e.HandlebarsEnvironment=u;var i=n(5),o=r(n(6)),s=n(10),a=n(30),l=r(n(32));e.VERSION="4.5.3";e.COMPILER_REVISION=8;e.LAST_COMPATIBLE_COMPILER_REVISION=7;e.REVISION_CHANGES={1:"<= 1.0.rc.2",2:"== 1.0.0-rc.3",3:"== 1.0.0-rc.4",4:"== 1.x.x",5:"== 2.0.0-alpha.x",6:">= 2.0.0-beta.1",7:">= 4.0.0 <4.3.0",8:">= 4.3.0"};function u(t,e,n){this.helpers=t||{},this.partials=e||{},this.decorators=n||{},s.registerDefaultHelpers(this),a.registerDefaultDecorators(this)}u.prototype={constructor:u,logger:l.default,log:l.default.log,registerHelper:function(t,e){if("[object Object]"===i.toString.call(t)){if(e)throw new o.default("Arg not supported with multiple helpers");i.extend(this.helpers,t)}else this.helpers[t]=e},unregisterHelper:function(t){delete this.helpers[t]},registerPartial:function(t,e){if("[object Object]"===i.toString.call(t))i.extend(this.partials,t);else{if(void 0===e)throw new o.default('Attempting to register a partial called "'+t+'" as undefined');this.partials[t]=e}},unregisterPartial:function(t){delete this.partials[t]},registerDecorator:function(t,e){if("[object Object]"===i.toString.call(t)){if(e)throw new o.default("Arg not supported with multiple decorators");i.extend(this.decorators,t)}else this.decorators[t]=e},unregisterDecorator:function(t){delete this.decorators[t]}};var h=l.default.log;e.log=h,e.createFrame=i.createFrame,e.logger=l.default},function(t,e){"use strict";e.__esModule=!0,e.extend=s,e.indexOf=function(t,e){for(var n=0,r=t.length;n":">",'"':""","'":"'","`":"`","=":"="},r=/[&<>"'`=]/g,i=/[&<>"'`=]/;function o(t){return n[t]}function s(t){for(var e=1;e0?(n.ids&&(n.ids=[n.name]),t.helpers.each(e,n)):i(this);if(n.data&&n.ids){var s=r.createFrame(n.data);s.contextPath=r.appendContextPath(n.data.contextPath,n.name),n={data:s}}return o(e,n)}))},t.exports=e.default},function(t,e,n){(function(r){"use strict";var i=n(13).default,o=n(1).default;e.__esModule=!0;var s=n(5),a=o(n(6));e.default=function(t){t.registerHelper("each",(function(t,e){if(!e)throw new a.default("Must pass iterator to #each");var n,o=e.fn,l=e.inverse,u=0,h="",c=void 0,f=void 0;function p(e,n,r){c&&(c.key=e,c.index=n,c.first=0===n,c.last=!!r,f&&(c.contextPath=f+e)),h+=o(t[e],{data:c,blockParams:s.blockParams([t[e],e],[f+e,null])})}if(e.data&&e.ids&&(f=s.appendContextPath(e.data.contextPath,e.ids[0])+"."),s.isFunction(t)&&(t=t.call(this)),e.data&&(c=s.createFrame(e.data)),t&&"object"==typeof t)if(s.isArray(t))for(var d=t.length;u=0?e:parseInt(t,10)}return t},log:function(t){if(t=i.lookupLevel(t),"undefined"!=typeof console&&i.lookupLevel(i.level)<=t){var e=i.methodMap[t];console[e]||(e="log");for(var n=arguments.length,r=Array(n>1?n-1:0),o=1;o=l.LAST_COMPATIBLE_COMPILER_REVISION&&e<=l.COMPILER_REVISION)return;if(e2&&_.push("'"+this.terminals_[v]+"'");S=this.lexer.showPosition?"Parse error on line "+(a+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+_.join(", ")+", got '"+(this.terminals_[f]||f)+"'":"Parse error on line "+(a+1)+": Unexpected "+(1==f?"end of input":"'"+(this.terminals_[f]||f)+"'"),this.parseError(S,{text:this.lexer.match,token:this.terminals_[f]||f,line:this.lexer.yylineno,loc:h,expected:_})}}if(g[0]instanceof Array&&g.length>1)throw new Error("Parse Error: multiple actions possible at state: "+d+", token: "+f);switch(g[0]){case 1:n.push(f),r.push(this.lexer.yytext),i.push(this.lexer.yylloc),n.push(g[1]),f=null,p?(f=p,p=null):(l=this.lexer.yyleng,s=this.lexer.yytext,a=this.lexer.yylineno,h=this.lexer.yylloc,u>0&&u--);break;case 2:if(b=this.productions_[g[1]][1],w.$=r[r.length-b],w._$={first_line:i[i.length-(b||1)].first_line,last_line:i[i.length-1].last_line,first_column:i[i.length-(b||1)].first_column,last_column:i[i.length-1].last_column},c&&(w._$.range=[i[i.length-(b||1)].range[0],i[i.length-1].range[1]]),void 0!==(m=this.performAction.call(w,s,l,a,this.yy,g[1],r,i)))return m;b&&(n=n.slice(0,-1*b*2),r=r.slice(0,-1*b),i=i.slice(0,-1*b)),n.push(this.productions_[g[1]][0]),r.push(w.$),i.push(w._$),y=o[n[n.length-2]][n[n.length-1]],n.push(y);break;case 3:return!0}}return!0}},e=function(){var t={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t){return this._input=t,this._more=this._less=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e-1),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this},more:function(){return this._more=!0,this},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},next:function(){if(this.done)return this.EOF;var t,e,n,r,i;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var o=this._currentRules(),s=0;se[0].length)||(e=n,r=s,this.options.flex));s++);return e?((i=e[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=i.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:i?i[i.length-1].length-i[i.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+e[0].length},this.yytext+=e[0],this.match+=e[0],this.matches=e,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._input=this._input.slice(e[0].length),this.matched+=e[0],t=this.performAction.call(this,this.yy,this,o[r],this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),t||void 0):""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var t=this.next();return void 0!==t?t:this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.pop()},_currentRules:function(){return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules},topState:function(){return this.conditionStack[this.conditionStack.length-2]},pushState:function(t){this.begin(t)},options:{},performAction:function(t,e,n,r){function i(t,n){return e.yytext=e.yytext.substring(t,e.yyleng-n+t)}switch(n){case 0:if("\\\\"===e.yytext.slice(-2)?(i(0,1),this.begin("mu")):"\\"===e.yytext.slice(-1)?(i(0,1),this.begin("emu")):this.begin("mu"),e.yytext)return 15;break;case 1:return 15;case 2:return this.popState(),15;case 3:return this.begin("raw"),15;case 4:return this.popState(),"raw"===this.conditionStack[this.conditionStack.length-1]?15:(i(5,9),"END_RAW_BLOCK");case 5:return 15;case 6:return this.popState(),14;case 7:return 65;case 8:return 68;case 9:return 19;case 10:return this.popState(),this.begin("raw"),23;case 11:return 55;case 12:return 60;case 13:return 29;case 14:return 47;case 15:case 16:return this.popState(),44;case 17:return 34;case 18:return 39;case 19:return 51;case 20:return 48;case 21:this.unput(e.yytext),this.popState(),this.begin("com");break;case 22:return this.popState(),14;case 23:return 48;case 24:return 73;case 25:case 26:return 72;case 27:return 87;case 28:break;case 29:return this.popState(),54;case 30:return this.popState(),33;case 31:return e.yytext=i(1,2).replace(/\\"/g,'"'),80;case 32:return e.yytext=i(1,2).replace(/\\'/g,"'"),80;case 33:return 85;case 34:case 35:return 82;case 36:return 83;case 37:return 84;case 38:return 81;case 39:return 75;case 40:return 77;case 41:return 72;case 42:return e.yytext=e.yytext.replace(/\\([\\\]])/g,"$1"),72;case 43:return"INVALID";case 44:return 5}},rules:[/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:\{\{\{\{(?=[^\/]))/,/^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/,/^(?:[^\x00]+?(?=(\{\{\{\{)))/,/^(?:[\s\S]*?--(~)?\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{\{\{)/,/^(?:\}\}\}\})/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#>)/,/^(?:\{\{(~)?#\*?)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^\s*(~)?\}\})/,/^(?:\{\{(~)?\s*else\s*(~)?\}\})/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{(~)?!--)/,/^(?:\{\{(~)?![\s\S]*?\}\})/,/^(?:\{\{(~)?\*?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)|])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s)])))/,/^(?:false(?=([~}\s)])))/,/^(?:undefined(?=([~}\s)])))/,/^(?:null(?=([~}\s)])))/,/^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/,/^(?:as\s+\|)/,/^(?:\|)/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/,/^(?:\[(\\\]|[^\]])*\])/,/^(?:.)/,/^(?:$)/],conditions:{mu:{rules:[7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44],inclusive:!1},emu:{rules:[2],inclusive:!1},com:{rules:[6],inclusive:!1},raw:{rules:[3,4,5],inclusive:!1},INITIAL:{rules:[0,1,44],inclusive:!0}}};return t}();function n(){this.yy={}}return t.lexer=e,n.prototype=t,t.Parser=n,new n}();e.default=n,t.exports=e.default},function(t,e,n){"use strict";var r=n(1).default;e.__esModule=!0;var i=r(n(44));function o(){var t=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];this.options=t}function s(t,e,n){void 0===e&&(e=t.length);var r=t[e-1],i=t[e-2];return r?"ContentStatement"===r.type?(i||!n?/\r?\n\s*?$/:/(^|\r?\n)\s*?$/).test(r.original):void 0:n}function a(t,e,n){void 0===e&&(e=-1);var r=t[e+1],i=t[e+2];return r?"ContentStatement"===r.type?(i||!n?/^\s*?\r?\n/:/^\s*?(\r?\n|$)/).test(r.original):void 0:n}function l(t,e,n){var r=t[null==e?0:e+1];if(r&&"ContentStatement"===r.type&&(n||!r.rightStripped)){var i=r.value;r.value=r.value.replace(n?/^\s+/:/^[ \t]*\r?\n?/,""),r.rightStripped=r.value!==i}}function u(t,e,n){var r=t[null==e?t.length-1:e-1];if(r&&"ContentStatement"===r.type&&(n||!r.leftStripped)){var i=r.value;return r.value=r.value.replace(n?/\s+$/:/[ \t]+$/,""),r.leftStripped=r.value!==i,r.leftStripped}}o.prototype=new i.default,o.prototype.Program=function(t){var e=!this.options.ignoreStandalone,n=!this.isRootSeen;this.isRootSeen=!0;for(var r=t.body,i=0,o=r.length;i0)throw new i.default("Invalid path: "+r,{loc:n});".."===u&&s++}}return{type:"PathExpression",data:t,depth:s,parts:o,original:r,loc:n}},e.prepareMustache=function(t,e,n,r,i,o){var s=r.charAt(3)||r.charAt(2),a="{"!==s&&"&"!==s;return{type:/\*/.test(r)?"Decorator":"MustacheStatement",path:t,params:e,hash:n,escaped:a,strip:i,loc:this.locInfo(o)}},e.prepareRawBlock=function(t,e,n,r){o(t,n),r=this.locInfo(r);var i={type:"Program",body:e,strip:{},loc:r};return{type:"BlockStatement",path:t.path,params:t.params,hash:t.hash,program:i,openStrip:{},inverseStrip:{},closeStrip:{},loc:r}},e.prepareBlock=function(t,e,n,r,s,a){r&&r.path&&o(t,r);var l=/\*/.test(t.open);e.blockParams=t.blockParams;var u=void 0,h=void 0;if(n){if(l)throw new i.default("Unexpected inverse block on decorator",n);n.chain&&(n.program.body[0].closeStrip=r.strip),h=n.strip,u=n.program}s&&(s=u,u=e,e=s);return{type:l?"DecoratorBlock":"BlockStatement",path:t.path,params:t.params,hash:t.hash,program:e,inverse:u,openStrip:t.strip,inverseStrip:h,closeStrip:r&&r.strip,loc:this.locInfo(a)}},e.prepareProgram=function(t,e){if(!e&&t.length){var n=t[0].loc,r=t[t.length-1].loc;n&&r&&(e={source:n.source,start:{line:n.start.line,column:n.start.column},end:{line:r.end.line,column:r.end.column}})}return{type:"Program",body:t,strip:{},loc:e}},e.preparePartialBlock=function(t,e,n,r){return o(t,n),{type:"PartialBlockStatement",name:t.path,params:t.params,hash:t.hash,program:e,openStrip:t.strip,closeStrip:n&&n.strip,loc:this.locInfo(r)}};var i=r(n(6));function o(t,e){if(e=e.path?e.path.original:e,t.path.original!==e){var n={loc:t.path.loc};throw new i.default(t.path.original+" doesn't match "+e,n)}}},function(t,e,n){"use strict";var r=n(47).default,i=n(1).default;e.__esModule=!0,e.Compiler=u,e.precompile=function(t,e,n){if(null==t||"string"!=typeof t&&"Program"!==t.type)throw new o.default("You must pass a string or Handlebars AST to Handlebars.precompile. You passed "+t);"data"in(e=e||{})||(e.data=!0);e.compat&&(e.useDepths=!0);var r=n.parse(t,e),i=(new n.Compiler).compile(r,e);return(new n.JavaScriptCompiler).compile(i,e)},e.compile=function(t,e,n){void 0===e&&(e={});if(null==t||"string"!=typeof t&&"Program"!==t.type)throw new o.default("You must pass a string or Handlebars AST to Handlebars.compile. You passed "+t);"data"in(e=s.extend({},e))||(e.data=!0);e.compat&&(e.useDepths=!0);var r=void 0;function i(){var r=n.parse(t,e),i=(new n.Compiler).compile(r,e),o=(new n.JavaScriptCompiler).compile(i,e,void 0,!0);return n.template(o)}function a(t,e){return r||(r=i()),r.call(this,t,e)}return a._setup=function(t){return r||(r=i()),r._setup(t)},a._child=function(t,e,n,o){return r||(r=i()),r._child(t,e,n,o)},a};var o=i(n(6)),s=n(5),a=i(n(40)),l=[].slice;function u(){}function h(t,e){if(t===e)return!0;if(s.isArray(t)&&s.isArray(e)&&t.length===e.length){for(var n=0;n1)throw new o.default("Unsupported number of partial arguments: "+n.length,t);n.length||(this.options.explicitPartialContext?this.opcode("pushLiteral","undefined"):n.push({type:"PathExpression",parts:[],depth:0}));var r=t.name.original,i="SubExpression"===t.name.type;i&&this.accept(t.name),this.setupFullMustacheParams(t,e,void 0,!0);var s=t.indent||"";this.options.preventIndent&&s&&(this.opcode("appendContent",s),s=""),this.opcode("invokePartial",i,r,s),this.opcode("append")},PartialBlockStatement:function(t){this.PartialStatement(t)},MustacheStatement:function(t){this.SubExpression(t),t.escaped&&!this.options.noEscape?this.opcode("appendEscaped"):this.opcode("append")},Decorator:function(t){this.DecoratorBlock(t)},ContentStatement:function(t){t.value&&this.opcode("appendContent",t.value)},CommentStatement:function(){},SubExpression:function(t){c(t);var e=this.classifySexpr(t);"simple"===e?this.simpleSexpr(t):"helper"===e?this.helperSexpr(t):this.ambiguousSexpr(t)},ambiguousSexpr:function(t,e,n){var r=t.path,i=r.parts[0],o=null!=e||null!=n;this.opcode("getContext",r.depth),this.opcode("pushProgram",e),this.opcode("pushProgram",n),r.strict=!0,this.accept(r),this.opcode("invokeAmbiguous",i,o)},simpleSexpr:function(t){var e=t.path;e.strict=!0,this.accept(e),this.opcode("resolvePossibleLambda")},helperSexpr:function(t,e,n){var r=this.setupFullMustacheParams(t,e,n),i=t.path,s=i.parts[0];if(this.options.knownHelpers[s])this.opcode("invokeKnownHelper",r.length,s);else{if(this.options.knownHelpersOnly)throw new o.default("You specified knownHelpersOnly, but used the unknown helper "+s,t);i.strict=!0,i.falsy=!0,this.accept(i),this.opcode("invokeHelper",r.length,i.original,a.default.helpers.simpleId(i))}},PathExpression:function(t){this.addDepth(t.depth),this.opcode("getContext",t.depth);var e=t.parts[0],n=a.default.helpers.scopedId(t),r=!t.depth&&!n&&this.blockParamIndex(e);r?this.opcode("lookupBlockParam",r,t.parts):e?t.data?(this.options.data=!0,this.opcode("lookupData",t.depth,t.parts,t.strict)):this.opcode("lookupOnContext",t.parts,t.falsy,t.strict,n):this.opcode("pushContext")},StringLiteral:function(t){this.opcode("pushString",t.value)},NumberLiteral:function(t){this.opcode("pushLiteral",t.value)},BooleanLiteral:function(t){this.opcode("pushLiteral",t.value)},UndefinedLiteral:function(){this.opcode("pushLiteral","undefined")},NullLiteral:function(){this.opcode("pushLiteral","null")},Hash:function(t){var e=t.pairs,n=0,r=e.length;for(this.opcode("pushHash");n=0)return[e,i]}}}},function(t,e,n){t.exports={default:n(48),__esModule:!0}},function(t,e,n){var r=n(9);t.exports=function(t,e){return r.create(t,e)}},function(t,e,n){"use strict";var r=n(13).default,i=n(1).default;e.__esModule=!0;var o=n(4),s=i(n(6)),a=n(5),l=i(n(50)),u=n(28);function h(t){this.value=t}function c(){}c.prototype={nameLookup:function(t,e){return u.dangerousPropertyRegex.test(e)?["(",[this.aliasable("container.propertyIsEnumerable"),".call(",t,",",JSON.stringify(e),")"],"?",n()," : undefined)"]:n();function n(){return c.isValidJavaScriptVariableName(e)?[t,".",e]:[t,"[",JSON.stringify(e),"]"]}},depthedLookup:function(t){return[this.aliasable("container.lookup"),'(depths, "',t,'")']},compilerInfo:function(){var t=o.COMPILER_REVISION;return[t,o.REVISION_CHANGES[t]]},appendToBuffer:function(t,e,n){return a.isArray(t)||(t=[t]),t=this.source.wrap(t,e),this.environment.isSimple?["return ",t,";"]:n?["buffer += ",t,";"]:(t.appendToBuffer=!0,t)},initializeBuffer:function(){return this.quotedString("")},compile:function(t,e,n,r){this.environment=t,this.options=e,this.stringParams=this.options.stringParams,this.trackIds=this.options.trackIds,this.precompile=!r,this.name=this.environment.name,this.isChild=!!n,this.context=n||{decorators:[],programs:[],environments:[]},this.preamble(),this.stackSlot=0,this.stackVars=[],this.aliases={},this.registers={list:[]},this.hashes=[],this.compileStack=[],this.inlineStack=[],this.blockParams=[],this.compileChildren(t,e),this.useDepths=this.useDepths||t.useDepths||t.useDecorators||this.options.compat,this.useBlockParams=this.useBlockParams||t.useBlockParams;var i=t.opcodes,o=void 0,a=void 0,l=void 0,u=void 0;for(l=0,u=i.length;l0&&(n+=", "+i.join(", "));var o=0;r(this.aliases).forEach((function(t){var r=e.aliases[t];r.children&&r.referenceCount>1&&(n+=", alias"+ ++o+"="+t,r.children[0]="alias"+o)}));var s=["container","depth0","helpers","partials","data"];(this.useBlockParams||this.useDepths)&&s.push("blockParams"),this.useDepths&&s.push("depths");var a=this.mergeSource(n);return t?(s.push(a),Function.apply(this,s)):this.source.wrap(["function(",s.join(","),") {\n ",a,"}"])},mergeSource:function(t){var e=this.environment.isSimple,n=!this.forceBuffer,r=void 0,i=void 0,o=void 0,s=void 0;return this.source.each((function(t){t.appendToBuffer?(o?t.prepend(" + "):o=t,s=t):(o&&(i?o.prepend("buffer += "):r=!0,s.add(";"),o=s=void 0),i=!0,e||(n=!1))})),n?o?(o.prepend("return "),s.add(";")):i||this.source.push('return "";'):(t+=", buffer = "+(r?"":this.initializeBuffer()),o?(o.prepend("return buffer + "),s.add(";")):this.source.push("return buffer;")),t&&this.source.prepend("var "+t.substring(2)+(r?"":";\n")),this.source.merge()},blockValue:function(t){var e=this.aliasable("container.hooks.blockHelperMissing"),n=[this.contextName(0)];this.setupHelperArgs(t,0,n);var r=this.popStack();n.splice(1,0,r),this.push(this.source.functionCall(e,"call",n))},ambiguousBlockValue:function(){var t=this.aliasable("container.hooks.blockHelperMissing"),e=[this.contextName(0)];this.setupHelperArgs("",0,e,!0),this.flushInline();var n=this.topStack();e.splice(1,0,n),this.pushSource(["if (!",this.lastHelper,") { ",n," = ",this.source.functionCall(t,"call",e),"}"])},appendContent:function(t){this.pendingContent?t=this.pendingContent+t:this.pendingLocation=this.source.currentLocation,this.pendingContent=t},append:function(){if(this.isInline())this.replaceStack((function(t){return[" != null ? ",t,' : ""']})),this.pushSource(this.appendToBuffer(this.popStack()));else{var t=this.popStack();this.pushSource(["if (",t," != null) { ",this.appendToBuffer(t,void 0,!0)," }"]),this.environment.isSimple&&this.pushSource(["else { ",this.appendToBuffer("''",void 0,!0)," }"])}},appendEscaped:function(){this.pushSource(this.appendToBuffer([this.aliasable("container.escapeExpression"),"(",this.popStack(),")"]))},getContext:function(t){this.lastContext=t},pushContext:function(){this.pushStackLiteral(this.contextName(this.lastContext))},lookupOnContext:function(t,e,n,r){var i=0;r||!this.options.compat||this.lastContext?this.pushContext():this.push(this.depthedLookup(t[i++])),this.resolvePath("context",t,i,e,n)},lookupBlockParam:function(t,e){this.useBlockParams=!0,this.push(["blockParams[",t[0],"][",t[1],"]"]),this.resolvePath("context",e,1)},lookupData:function(t,e,n){t?this.pushStackLiteral("container.data(data, "+t+")"):this.pushStackLiteral("data"),this.resolvePath("data",e,0,!0,n)},resolvePath:function(t,e,n,r,i){var o=this;if(this.options.strict||this.options.assumeObjects)this.push(function(t,e,n,r){var i=e.popStack(),o=0,s=n.length;t&&s--;for(;othis.stackVars.length&&this.stackVars.push("stack"+this.stackSlot),this.topStackName()},topStackName:function(){return"stack"+this.stackSlot},flushInline:function(){var t=this.inlineStack;this.inlineStack=[];for(var e=0,n=t.length;e[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:l,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};function e(e){this.tokens=[],this.tokens.links={},this.options=e||h.defaults,this.rules=t.normal,this.options.gfm&&(this.options.tables?this.rules=t.tables:this.rules=t.gfm)}t.bullet=/(?:[*+-]|\d+\.)/,t.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/,t.item=a(t.item,"gm")(/bull/g,t.bullet)(),t.list=a(t.list)(/bull/g,t.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+t.def.source+")")(),t.blockquote=a(t.blockquote)("def",t.def)(),t._tag="(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b",t.html=a(t.html)("comment",//)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/])*?>/)(/tag/g,t._tag)(),t.paragraph=a(t.paragraph)("hr",t.hr)("heading",t.heading)("lheading",t.lheading)("blockquote",t.blockquote)("tag","<"+t._tag)("def",t.def)(),t.normal=u({},t),t.gfm=u({},t.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/}),t.gfm.paragraph=a(t.paragraph)("(?!","(?!"+t.gfm.fences.source.replace("\\1","\\2")+"|"+t.list.source.replace("\\1","\\3")+"|")(),t.tables=u({},t.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/}),e.rules=t,e.lex=function(t,n){return new e(n).lex(t)},e.prototype.lex=function(t){return t=t.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n"),this.token(t,!0)},e.prototype.token=function(e,n,r){var i,o,s,a,l,u,h,c,f;for(e=e.replace(/^ +$/gm,"");e;)if((s=this.rules.newline.exec(e))&&(e=e.substring(s[0].length),s[0].length>1&&this.tokens.push({type:"space"})),s=this.rules.code.exec(e))e=e.substring(s[0].length),s=s[0].replace(/^ {4}/gm,""),this.tokens.push({type:"code",text:this.options.pedantic?s:s.replace(/\n+$/,"")});else if(s=this.rules.fences.exec(e))e=e.substring(s[0].length),this.tokens.push({type:"code",lang:s[2],text:s[3]||""});else if(s=this.rules.heading.exec(e))e=e.substring(s[0].length),this.tokens.push({type:"heading",depth:s[1].length,text:s[2]});else if(n&&(s=this.rules.nptable.exec(e))){for(e=e.substring(s[0].length),u={type:"table",header:s[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:s[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:s[3].replace(/\n$/,"").split("\n")},c=0;c ?/gm,""),this.token(s,n,!0),this.tokens.push({type:"blockquote_end"});else if(s=this.rules.list.exec(e)){for(e=e.substring(s[0].length),a=s[2],this.tokens.push({type:"list_start",ordered:a.length>1}),i=!1,f=(s=s[0].match(this.rules.item)).length,c=0;c1&&l.length>1||(e=s.slice(c+1).join("\n")+e,c=f-1)),o=i||/\n\n(?!\s*$)/.test(u),c!==f-1&&(i="\n"===u.charAt(u.length-1),o||(o=i)),this.tokens.push({type:o?"loose_item_start":"list_item_start"}),this.token(u,!1,r),this.tokens.push({type:"list_item_end"});this.tokens.push({type:"list_end"})}else if(s=this.rules.html.exec(e))e=e.substring(s[0].length),this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:!this.options.sanitizer&&("pre"===s[1]||"script"===s[1]||"style"===s[1]),text:s[0]});else if(!r&&n&&(s=this.rules.def.exec(e)))e=e.substring(s[0].length),this.tokens.links[s[1].toLowerCase()]={href:s[2],title:s[3]};else if(n&&(s=this.rules.table.exec(e))){for(e=e.substring(s[0].length),u={type:"table",header:s[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:s[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:s[3].replace(/(?: *\| *)?\n$/,"").split("\n")},c=0;c])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:l,tag:/^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:l,text:/^[\s\S]+?(?=[\\/g,">").replace(/"/g,""").replace(/'/g,"'")}function a(t,e){return t=t.source,e=e||"",function n(r,i){return r?(i=(i=i.source||i).replace(/(^|[^\[])\^/g,"$1"),t=t.replace(r,i),n):new RegExp(t,e)}}function l(){}function u(t){for(var e,n,r=1;rAn error occured:

"+s(t.message+"",!0)+"
";throw t}}n._inside=/(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/,n._href=/\s*?(?:\s+['"]([\s\S]*?)['"])?\s*/,n.link=a(n.link)("inside",n._inside)("href",n._href)(),n.reflink=a(n.reflink)("inside",n._inside)(),n.normal=u({},n),n.pedantic=u({},n.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/}),n.gfm=u({},n.normal,{escape:a(n.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:a(n.text)("]|","~]|")("|","|https?://|")()}),n.breaks=u({},n.gfm,{br:a(n.br)("{2,}","*")(),text:a(n.gfm.text)("{2,}","*")()}),r.rules=n,r.output=function(t,e,n){return new r(e,n).output(t)},r.prototype.output=function(t){for(var e,n,r,i,o="";t;)if(i=this.rules.escape.exec(t))t=t.substring(i[0].length),o+=i[1];else if(i=this.rules.autolink.exec(t))t=t.substring(i[0].length),"@"===i[2]?(n=":"===i[1].charAt(6)?this.mangle(i[1].substring(7)):this.mangle(i[1]),r=this.mangle("mailto:")+n):r=n=s(i[1]),o+=this.renderer.link(r,null,n);else if(this.inLink||!(i=this.rules.url.exec(t))){if(i=this.rules.tag.exec(t))!this.inLink&&/^/i.test(i[0])&&(this.inLink=!1),t=t.substring(i[0].length),o+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(i[0]):s(i[0]):i[0];else if(i=this.rules.link.exec(t))t=t.substring(i[0].length),this.inLink=!0,o+=this.outputLink(i,{href:i[2],title:i[3]}),this.inLink=!1;else if((i=this.rules.reflink.exec(t))||(i=this.rules.nolink.exec(t))){if(t=t.substring(i[0].length),e=(i[2]||i[1]).replace(/\s+/g," "),!(e=this.links[e.toLowerCase()])||!e.href){o+=i[0].charAt(0),t=i[0].substring(1)+t;continue}this.inLink=!0,o+=this.outputLink(i,e),this.inLink=!1}else if(i=this.rules.strong.exec(t))t=t.substring(i[0].length),o+=this.renderer.strong(this.output(i[2]||i[1]));else if(i=this.rules.em.exec(t))t=t.substring(i[0].length),o+=this.renderer.em(this.output(i[2]||i[1]));else if(i=this.rules.code.exec(t))t=t.substring(i[0].length),o+=this.renderer.codespan(s(i[2],!0));else if(i=this.rules.br.exec(t))t=t.substring(i[0].length),o+=this.renderer.br();else if(i=this.rules.del.exec(t))t=t.substring(i[0].length),o+=this.renderer.del(this.output(i[1]));else if(i=this.rules.text.exec(t))t=t.substring(i[0].length),o+=this.renderer.text(s(this.smartypants(i[0])));else if(t)throw new Error("Infinite loop on byte: "+t.charCodeAt(0))}else t=t.substring(i[0].length),r=n=s(i[1]),o+=this.renderer.link(r,null,n);return o},r.prototype.outputLink=function(t,e){var n=s(e.href),r=e.title?s(e.title):null;return"!"!==t[0].charAt(0)?this.renderer.link(n,r,this.output(t[1])):this.renderer.image(n,r,s(t[1]))},r.prototype.smartypants=function(t){return this.options.smartypants?t.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…"):t},r.prototype.mangle=function(t){if(!this.options.mangle)return t;for(var e,n="",r=t.length,i=0;i.5&&(e="x"+e.toString(16)),n+="&#"+e+";";return n},i.prototype.code=function(t,e,n){if(this.options.highlight){var r=this.options.highlight(t,e);null!=r&&r!==t&&(n=!0,t=r)}return e?'
'+(n?t:s(t,!0))+"\n
\n":"
"+(n?t:s(t,!0))+"\n
"},i.prototype.blockquote=function(t){return"
\n"+t+"
\n"},i.prototype.html=function(t){return t},i.prototype.heading=function(t,e,n){return"'+t+"\n"},i.prototype.hr=function(){return this.options.xhtml?"
\n":"
\n"},i.prototype.list=function(t,e){var n=e?"ol":"ul";return"<"+n+">\n"+t+"\n"},i.prototype.listitem=function(t){return"
  • "+t+"
  • \n"},i.prototype.paragraph=function(t){return"

    "+t+"

    \n"},i.prototype.table=function(t,e){return"\n\n"+t+"\n\n"+e+"\n
    \n"},i.prototype.tablerow=function(t){return"\n"+t+"\n"},i.prototype.tablecell=function(t,e){var n=e.header?"th":"td";return(e.align?"<"+n+' style="text-align:'+e.align+'">':"<"+n+">")+t+"\n"},i.prototype.strong=function(t){return""+t+""},i.prototype.em=function(t){return""+t+""},i.prototype.codespan=function(t){return""+t+""},i.prototype.br=function(){return this.options.xhtml?"
    ":"
    "},i.prototype.del=function(t){return""+t+""},i.prototype.link=function(t,e,n){if(this.options.sanitize){try{var r=decodeURIComponent((i=t,i.replace(/&([#\w]+);/g,(function(t,e){return"colon"===(e=e.toLowerCase())?":":"#"===e.charAt(0)?"x"===e.charAt(1)?String.fromCharCode(parseInt(e.substring(2),16)):String.fromCharCode(+e.substring(1)):""})))).replace(/[^\w:]/g,"").toLowerCase()}catch(t){return""}if(0===r.indexOf("javascript:")||0===r.indexOf("vbscript:"))return""}var i,o='
    "},i.prototype.image=function(t,e,n){var r=''+n+'":">"},i.prototype.text=function(t){return t},o.parse=function(t,e,n){return new o(e,n).parse(t)},o.prototype.parse=function(t){this.inline=new r(t.links,this.options,this.renderer),this.tokens=t.reverse();for(var e="";this.next();)e+=this.tok();return e},o.prototype.next=function(){return this.token=this.tokens.pop()},o.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},o.prototype.parseText=function(){for(var t=this.token.text;"text"===this.peek().type;)t+="\n"+this.next().text;return this.inline.output(t)},o.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text);case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var t,e,n,r,i="",o="";for(n="",t=0;t'))}(e),!t)return!0;for(var o in t)r(o);return!0},{init:function(e){var o=Object.assign({},{openTrigger:"data-micromodal-trigger"},e),n=t(document.querySelectorAll("[".concat(o.openTrigger,"]"))),r=function(e,t){var o=[];return e.forEach((function(e){var n=e.attributes[t].value;void 0===o[n]&&(o[n]=[]),o[n].push(e)})),o}(n,o.openTrigger);if(!0!==o.debugMode||!1!==s(n,r))for(var l in r){var c=r[l];o.targetModal=l,o.triggers=t(c),a=new i(o)}},show:function(e,t){var o=t||{};o.targetModal=e,!0===o.debugMode&&!1===r(e)||(a&&a.removeEventListeners(),(a=new i(o)).showModal())},close:function(e){e?a.closeModalById(e):a.closeModal()}});return"undefined"!=typeof window&&(window.MicroModal=l),l})); diff --git a/survey_dashboard/hmc_layout/static/en_files/outline_description_white_48dp.png b/survey_dashboard/hmc_layout/static/en_files/outline_description_white_48dp.png new file mode 100644 index 0000000..c114310 Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/outline_description_white_48dp.png differ diff --git a/survey_dashboard/hmc_layout/static/en_files/peopleBG.png b/survey_dashboard/hmc_layout/static/en_files/peopleBG.png new file mode 100644 index 0000000..da901cd Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/peopleBG.png differ diff --git a/survey_dashboard/hmc_layout/static/en_files/projectops(1).js b/survey_dashboard/hmc_layout/static/en_files/projectops(1).js new file mode 100644 index 0000000..6b81b1b --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/projectops(1).js @@ -0,0 +1,4269 @@ +"use strict"; + +var CABLES=CABLES||{}; +CABLES.OPS=CABLES.OPS||{}; + +var Ops=Ops || {}; +Ops.Gl=Ops.Gl || {}; +Ops.Ui=Ops.Ui || {}; +Ops.Anim=Ops.Anim || {}; +Ops.Math=Ops.Math || {}; +Ops.Color=Ops.Color || {}; +Ops.Value=Ops.Value || {}; +Ops.String=Ops.String || {}; +Ops.Trigger=Ops.Trigger || {}; +Ops.Gl.Matrix=Ops.Gl.Matrix || {}; +Ops.Gl.Meshes=Ops.Gl.Meshes || {}; +Ops.Gl.Shader=Ops.Gl.Shader || {}; +Ops.Deprecated=Ops.Deprecated || {}; +Ops.Math.Compare=Ops.Math.Compare || {}; +Ops.Deprecated.Exp=Ops.Deprecated.Exp || {}; +Ops.Deprecated.Anim=Ops.Deprecated.Anim || {}; +Ops.Deprecated.Exp.Gl=Ops.Deprecated.Exp.Gl || {}; +Ops.Gl.TextureEffects=Ops.Gl.TextureEffects || {}; +Ops.Gl.TextureEffects.Noise=Ops.Gl.TextureEffects.Noise || {}; + + + +// ************************************************************** +// +// Ops.Gl.MainLoop +// +// ************************************************************** + +Ops.Gl.MainLoop = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + fpsLimit = op.inValue("FPS Limit", 0), + trigger = op.outTrigger("trigger"), + width = op.outNumber("width"), + height = op.outNumber("height"), + reduceFocusFPS = op.inValueBool("Reduce FPS not focussed", true), + reduceLoadingFPS = op.inValueBool("Reduce FPS loading"), + clear = op.inValueBool("Clear", true), + clearAlpha = op.inValueBool("ClearAlpha", true), + fullscreen = op.inValueBool("Fullscreen Button", false), + active = op.inValueBool("Active", true), + hdpi = op.inValueBool("Hires Displays", false), + inUnit = op.inSwitch("Pixel Unit", ["Display", "CSS"], "Display"); + +op.onAnimFrame = render; +hdpi.onChange = function () +{ + if (hdpi.get()) op.patch.cgl.pixelDensity = window.devicePixelRatio; + else op.patch.cgl.pixelDensity = 1; + + op.patch.cgl.updateSize(); + if (CABLES.UI) gui.setLayout(); + + // inUnit.setUiAttribs({ "greyout": !hdpi.get() }); + + // if (!hdpi.get())inUnit.set("CSS"); + // else inUnit.set("Display"); +}; + +active.onChange = function () +{ + op.patch.removeOnAnimFrame(op); + + if (active.get()) + { + op.setUiAttrib({ "extendTitle": "" }); + op.onAnimFrame = render; + op.patch.addOnAnimFrame(op); + op.log("adding again!"); + } + else + { + op.setUiAttrib({ "extendTitle": "Inactive" }); + } +}; + +const cgl = op.patch.cgl; +let rframes = 0; +let rframeStart = 0; + +if (!op.patch.cgl) op.uiAttr({ "error": "No webgl cgl context" }); + +const identTranslate = vec3.create(); +vec3.set(identTranslate, 0, 0, 0); +const identTranslateView = vec3.create(); +vec3.set(identTranslateView, 0, 0, -2); + +fullscreen.onChange = updateFullscreenButton; +setTimeout(updateFullscreenButton, 100); +let fsElement = null; + +let winhasFocus = true; +let winVisible = true; + +window.addEventListener("blur", () => { winhasFocus = false; }); +window.addEventListener("focus", () => { winhasFocus = true; }); +document.addEventListener("visibilitychange", () => { winVisible = !document.hidden; }); +testMultiMainloop(); + +inUnit.onChange = () => +{ + width.set(0); + height.set(0); +}; + +function getFpsLimit() +{ + if (reduceLoadingFPS.get() && op.patch.loading.getProgress() < 1.0) return 5; + + if (reduceFocusFPS.get()) + { + if (!winVisible) return 10; + if (!winhasFocus) return 30; + } + + return fpsLimit.get(); +} + +function updateFullscreenButton() +{ + function onMouseEnter() + { + if (fsElement)fsElement.style.display = "block"; + } + + function onMouseLeave() + { + if (fsElement)fsElement.style.display = "none"; + } + + op.patch.cgl.canvas.addEventListener("mouseleave", onMouseLeave); + op.patch.cgl.canvas.addEventListener("mouseenter", onMouseEnter); + + if (fullscreen.get()) + { + if (!fsElement) + { + fsElement = document.createElement("div"); + + const container = op.patch.cgl.canvas.parentElement; + if (container)container.appendChild(fsElement); + + fsElement.addEventListener("mouseenter", onMouseEnter); + fsElement.addEventListener("click", function (e) + { + if (CABLES.UI && !e.shiftKey) gui.cycleFullscreen(); + else cgl.fullScreen(); + }); + } + + fsElement.style.padding = "10px"; + fsElement.style.position = "absolute"; + fsElement.style.right = "5px"; + fsElement.style.top = "5px"; + fsElement.style.width = "20px"; + fsElement.style.height = "20px"; + fsElement.style.cursor = "pointer"; + fsElement.style["border-radius"] = "40px"; + fsElement.style.background = "#444"; + fsElement.style["z-index"] = "9999"; + fsElement.style.display = "none"; + fsElement.innerHTML = ""; + } + else + { + if (fsElement) + { + fsElement.style.display = "none"; + fsElement.remove(); + fsElement = null; + } + } +} + +op.onDelete = function () +{ + cgl.gl.clearColor(0, 0, 0, 0); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); +}; + +function render(time) +{ + if (!active.get()) return; + if (cgl.aborted || cgl.canvas.clientWidth === 0 || cgl.canvas.clientHeight === 0) return; + + op.patch.cg = cgl; + + const startTime = performance.now(); + + op.patch.config.fpsLimit = getFpsLimit(); + + if (cgl.canvasWidth == -1) + { + cgl.setCanvas(op.patch.config.glCanvasId); + return; + } + + if (cgl.canvasWidth != width.get() || cgl.canvasHeight != height.get()) + { + let div = 1; + if (inUnit.get() == "CSS")div = op.patch.cgl.pixelDensity; + + width.set(cgl.canvasWidth / div); + height.set(cgl.canvasHeight / div); + } + + if (CABLES.now() - rframeStart > 1000) + { + CGL.fpsReport = CGL.fpsReport || []; + if (op.patch.loading.getProgress() >= 1.0 && rframeStart !== 0)CGL.fpsReport.push(rframes); + rframes = 0; + rframeStart = CABLES.now(); + } + CGL.MESH.lastShader = null; + CGL.MESH.lastMesh = null; + + cgl.renderStart(cgl, identTranslate, identTranslateView); + + if (clear.get()) + { + cgl.gl.clearColor(0, 0, 0, 1); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); + } + + trigger.trigger(); + + if (CGL.MESH.lastMesh)CGL.MESH.lastMesh.unBind(); + + if (CGL.Texture.previewTexture) + { + if (!CGL.Texture.texturePreviewer) CGL.Texture.texturePreviewer = new CGL.Texture.texturePreview(cgl); + CGL.Texture.texturePreviewer.render(CGL.Texture.previewTexture); + } + cgl.renderEnd(cgl); + + op.patch.cg = null; + + if (clearAlpha.get()) + { + cgl.gl.clearColor(1, 1, 1, 1); + cgl.gl.colorMask(false, false, false, true); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT); + cgl.gl.colorMask(true, true, true, true); + } + + if (!cgl.frameStore.phong)cgl.frameStore.phong = {}; + rframes++; + + op.patch.cgl.profileData.profileMainloopMs = performance.now() - startTime; +} + +function testMultiMainloop() +{ + setTimeout( + () => + { + if (op.patch.getOpsByObjName(op.name).length > 1) + { + op.setUiError("multimainloop", "there should only be one mainloop op!"); + op.patch.addEventListener("onOpDelete", testMultiMainloop); + } + else op.setUiError("multimainloop", null, 1); + }, 500); +} + + +}; + +Ops.Gl.MainLoop.prototype = new CABLES.Op(); +CABLES.OPS["b0472a1d-db16-4ba6-8787-f300fbdc77bb"]={f:Ops.Gl.MainLoop,objName:"Ops.Gl.MainLoop"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.Transform +// +// ************************************************************** + +Ops.Gl.Matrix.Transform = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + posX = op.inValue("posX", 0), + posY = op.inValue("posY", 0), + posZ = op.inValue("posZ", 0), + scale = op.inValue("scale", 1), + rotX = op.inValue("rotX", 0), + rotY = op.inValue("rotY", 0), + rotZ = op.inValue("rotZ", 0), + trigger = op.outTrigger("trigger"); + +op.setPortGroup("Rotation", [rotX, rotY, rotZ]); +op.setPortGroup("Position", [posX, posY, posZ]); +op.setPortGroup("Scale", [scale]); +op.setUiAxisPorts(posX, posY, posZ); + +const vPos = vec3.create(); +const vScale = vec3.create(); +const transMatrix = mat4.create(); +mat4.identity(transMatrix); + +let + doScale = false, + doTranslate = false, + translationChanged = true, + scaleChanged = true, + rotChanged = true; + +rotX.onChange = rotY.onChange = rotZ.onChange = setRotChanged; +posX.onChange = posY.onChange = posZ.onChange = setTranslateChanged; +scale.onChange = setScaleChanged; + +render.onTriggered = function () +{ + // if(!CGL.TextureEffect.checkOpNotInTextureEffect(op)) return; + + let updateMatrix = false; + if (translationChanged) + { + updateTranslation(); + updateMatrix = true; + } + if (scaleChanged) + { + updateScale(); + updateMatrix = true; + } + if (rotChanged) updateMatrix = true; + + if (updateMatrix) doUpdateMatrix(); + + const cg = op.patch.cgl; + cg.pushModelMatrix(); + mat4.multiply(cg.mMatrix, cg.mMatrix, transMatrix); + + trigger.trigger(); + cg.popModelMatrix(); + + if (CABLES.UI && CABLES.UI.showCanvasTransforms) gui.setTransform(op.id, posX.get(), posY.get(), posZ.get()); + + if (op.isCurrentUiOp()) + gui.setTransformGizmo( + { + "posX": posX, + "posY": posY, + "posZ": posZ, + }); +}; + +op.transform3d = function () +{ + return { "pos": [posX, posY, posZ] }; +}; + +function doUpdateMatrix() +{ + mat4.identity(transMatrix); + if (doTranslate)mat4.translate(transMatrix, transMatrix, vPos); + + if (rotX.get() !== 0)mat4.rotateX(transMatrix, transMatrix, rotX.get() * CGL.DEG2RAD); + if (rotY.get() !== 0)mat4.rotateY(transMatrix, transMatrix, rotY.get() * CGL.DEG2RAD); + if (rotZ.get() !== 0)mat4.rotateZ(transMatrix, transMatrix, rotZ.get() * CGL.DEG2RAD); + + if (doScale)mat4.scale(transMatrix, transMatrix, vScale); + rotChanged = false; +} + +function updateTranslation() +{ + doTranslate = false; + if (posX.get() !== 0.0 || posY.get() !== 0.0 || posZ.get() !== 0.0) doTranslate = true; + vec3.set(vPos, posX.get(), posY.get(), posZ.get()); + translationChanged = false; +} + +function updateScale() +{ + // doScale=false; + // if(scale.get()!==0.0) + doScale = true; + vec3.set(vScale, scale.get(), scale.get(), scale.get()); + scaleChanged = false; +} + +function setTranslateChanged() +{ + translationChanged = true; +} + +function setScaleChanged() +{ + scaleChanged = true; +} + +function setRotChanged() +{ + rotChanged = true; +} + +doUpdateMatrix(); + + +}; + +Ops.Gl.Matrix.Transform.prototype = new CABLES.Op(); +CABLES.OPS["650baeb1-db2d-4781-9af6-ab4e9d4277be"]={f:Ops.Gl.Matrix.Transform,objName:"Ops.Gl.Matrix.Transform"}; + + + + +// ************************************************************** +// +// Ops.Math.Multiply +// +// ************************************************************** + +Ops.Math.Multiply = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number1 = op.inValueFloat("number1", 1), + number2 = op.inValueFloat("number2", 2), + result = op.outNumber("result"); + +op.setTitle("*"); + +number1.onChange = number2.onChange = update; +update(); + +function update() +{ + const n1 = number1.get(); + const n2 = number2.get(); + + result.set(n1 * n2); +} + + +}; + +Ops.Math.Multiply.prototype = new CABLES.Op(); +CABLES.OPS["1bbdae06-fbb2-489b-9bcc-36c9d65bd441"]={f:Ops.Math.Multiply,objName:"Ops.Math.Multiply"}; + + + + +// ************************************************************** +// +// Ops.Deprecated.Exp.Gl.VectorFieldArray +// +// ************************************************************** + +Ops.Deprecated.Exp.Gl.VectorFieldArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const cgl = op.patch.cgl; + +let exe = op.inTrigger("exe"); +let geom = op.inObject("geom"); +geom.ignoreValueSerialize = true; + +let tex = op.inTexture("Texture"); + +let numColumns = op.inValue("Columns", 100); +let numRows = op.inValue("Rows", 100); +let spacingColumns = op.inValue("Spacing Columns", 1); +let spacingRows = op.inValue("Spacing Rows", 1); +let doCenter = op.inValueBool("Center", true); + +let transRotate = op.inValueBool("Rotate", true); +let transScale = op.inValueBool("Scale", false); +let transTransZ = op.inValueBool("Translate Z", false); + +transTransZ.onChange = updateTransforms; +transRotate.onChange = updateTransforms; +transScale.onChange = updateTransforms; + +function updateTransforms() +{ + if (!shader) return; + if (transRotate.get())shader.define("TRANS_ROTATE"); + else shader.removeDefine("TRANS_ROTATE"); + + if (transScale.get())shader.define("TRANS_SCALE"); + else shader.removeDefine("TRANS_SCALE"); + + if (transTransZ.get())shader.define("TRANS_TRANS_Z"); + else shader.removeDefine("TRANS_TRANS_Z"); +} + +let transformations = []; +let mod = null; +let mesh = null; +var shader = null; +let uniDoInstancing = null; +let uniSpaceX = null; +let uniSpaceY = null; +let recalc = true; + +numRows.onChange = reset; +numColumns.onChange = reset; +doCenter.onChange = reset; +spacingColumns.onChange = reset; +spacingRows.onChange = reset; + +geom.onChange = reset; +exe.onTriggered = doRender; +exe.onLinkChanged = removeModule; + +let srcHeadVert = "" + .endl() + "UNI float do_instancing;" + .endl() + "UNI sampler2D {{mod}}field;" + + .endl() + "UNI float {{mod}}spaceX;" + .endl() + "UNI float {{mod}}spaceY;" + .endl() + "UNI float {{mod}}rows;" + .endl() + "UNI float {{mod}}cols;" + + .endl() + "#ifdef INSTANCING" + .endl() + " IN mat4 instMat;" + .endl() + " OUT mat4 instModelMat;" + .endl() + "#endif" + + .endl() + "mat4 rotationMatrix(vec3 axis, float angle)" + .endl() + "{" + .endl() + " axis = normalize(axis);" + .endl() + " float s = sin(angle);" + .endl() + " float c = cos(angle);" + .endl() + " float oc = 1.0 - c;" + + .endl() + " return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0," + .endl() + " oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0," + .endl() + " oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0," + .endl() + " 0.0, 0.0, 0.0, 1.0);" + .endl() + "}"; + +let srcBodyVert = "" + .endl() + "#ifdef INSTANCING" + // .endl()+' if( do_instancing==1.0 )' + .endl() + " {" + .endl() + " instModelMat=instMat;" + .endl() + " float tx=(instModelMat[3][0]) / {{mod}}cols;" + .endl() + " float ty=(instModelMat[3][1]) / {{mod}}rows;" + .endl() + " instModelMat[3][0]*={{mod}}spaceX;" + .endl() + " instModelMat[3][1]*={{mod}}spaceY;" + .endl() + " vec4 instCol = texture2D( {{mod}}field, vec2(tx,ty) );" + + .endl() + " #ifdef TRANS_ROTATE" + .endl() + " instModelMat*=rotationMatrix(vec3(0.0,0.0,1.0),instCol.r*3.1415926535897932384626433832795*2.0);" + .endl() + " #endif" + + .endl() + " #ifdef TRANS_SCALE" + .endl() + " pos.rgb*=instCol.r;" + .endl() + " #endif" + + .endl() + " #ifdef TRANS_TRANS_Z" + .endl() + " pos.z+=instCol.r;" + .endl() + " #endif" + +// .endl()+' pos*=instCol.r;' + .endl() + " mMatrix=mMatrix * instModelMat;" + .endl() + " }" + .endl() + "#endif" + .endl(); + +function reset() +{ + recalc = true; +} + +function prepare() +{ + if (geom.get()) + { + calc(); + + let num = transformations.length; + let arrs = [].concat.apply([], transformations); + + let matrices = new Float32Array(arrs); + + mesh = new CGL.Mesh(cgl, geom.get()); + mesh.numInstances = num; + + mesh.addAttribute("instMat", matrices, 16); + + recalc = false; + } +} + +function removeModule() +{ + if (shader && mod) + { + shader.removeModule(mod); + shader = null; + } +} + +function doRender() +{ + if (recalc)prepare(); + if (mesh) + { + if (cgl.getShader() && cgl.getShader() != shader) + { + if (shader && mod) + { + shader.removeModule(mod); + shader = null; + } + + shader = cgl.getShader(); + if (!shader.hasDefine("INSTANCING")) + { + mod = shader.addModule( + { + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": srcHeadVert, + "srcBodyVert": srcBodyVert + }); + + shader.define("INSTANCING"); + op.uniDoInstancing = new CGL.Uniform(shader, "f", "do_instancing", 1); + op.uniSpaceX = new CGL.Uniform(shader, "f", mod.prefix + "spaceX", spacingColumns); + op.uniSpaceY = new CGL.Uniform(shader, "f", mod.prefix + "spaceY", spacingRows); + op.uniTexture = new CGL.Uniform(shader, "t", mod.prefix + "field", 5); + op.uniCols = new CGL.Uniform(shader, "f", mod.prefix + "cols", numColumns); + op.uniRows = new CGL.Uniform(shader, "f", mod.prefix + "rows", numRows); + + updateTransforms(); + } + else + { + op.uniDoInstancing = shader.getUniform("do_instancing"); + } + } + + // if(uniSpaceX) + // { + // uniSpaceY.setValue(spacingRows.get()); + // uniSpaceX.setValue(spacingColumns.get()); + + // uniCols.setValue(numColumns.get()); + // uniRows.setValue(numRows.get()); + + // } + + if (tex.get()) + cgl.setTexture(5, tex.get().tex); + + op.uniDoInstancing.setValue(1); + mesh.render(shader); + op.uniDoInstancing.setValue(0); + } + else + { + prepare(); + } +} + +function calc() +{ + let m = mat4.create(); + let cols = Math.round(numColumns.get()); + let rows = Math.round(numRows.get()); + if (cols <= 0)cols = 1; + if (rows <= 0)rows = 1; + + let distX = spacingColumns.get(); + let distY = spacingRows.get(); + + let centerX = 0; + let centerY = 0; + if (doCenter.get()) + { + centerX = cols * (spacingColumns.get() / 2); + centerY = rows * (spacingRows.get() / 2); + } + + transformations.length = cols * rows; + + for (let x = 0; x < cols; x++) + { + for (let y = 0; y < rows; y++) + { + mat4.identity(m); + mat4.translate(m, m, [x - centerX, y - centerY, 0]); + transformations[x + y * cols] = Array.prototype.slice.call(m); + } + } + + op.log("reset", transformations.length, cols, rows); +} + + +}; + +Ops.Deprecated.Exp.Gl.VectorFieldArray.prototype = new CABLES.Op(); +CABLES.OPS["fba86dad-f37f-482e-a8fb-2abc76723ecf"]={f:Ops.Deprecated.Exp.Gl.VectorFieldArray,objName:"Ops.Deprecated.Exp.Gl.VectorFieldArray"}; + + + + +// ************************************************************** +// +// Ops.Sequence +// +// ************************************************************** + +Ops.Sequence = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + cleanup = op.inTriggerButton("Clean up connections"); + +const + exes = [], + triggers = [], + num = 16; + +let updateTimeout = null; + +exe.onTriggered = triggerAll; +cleanup.onTriggered = clean; +cleanup.setUiAttribs({ "hidePort": true }); +cleanup.setUiAttribs({ "hideParam": true }); + +for (let i = 0; i < num; i++) +{ + const p = op.outTrigger("trigger " + i); + triggers.push(p); + p.onLinkChanged = updateButton; + + if (i < num - 1) + { + let newExe = op.inTrigger("exe " + i); + newExe.onTriggered = triggerAll; + exes.push(newExe); + } +} + +function updateButton() +{ + clearTimeout(updateTimeout); + updateTimeout = setTimeout(() => + { + let show = false; + for (let i = 0; i < triggers.length; i++) + if (triggers[i].links.length > 1) show = true; + + cleanup.setUiAttribs({ "hideParam": !show }); + + if (op.isCurrentUiOp()) op.refreshParams(); + }, 60); +} + +function triggerAll() +{ + for (let i = 0; i < triggers.length; i++) triggers[i].trigger(); +} + +function clean() +{ + let count = 0; + for (let i = 0; i < triggers.length; i++) + { + let removeLinks = []; + + if (triggers[i].links.length > 1) + for (let j = 1; j < triggers[i].links.length; j++) + { + while (triggers[count].links.length > 0) count++; + + removeLinks.push(triggers[i].links[j]); + const otherPort = triggers[i].links[j].getOtherPort(triggers[i]); + op.patch.link(op, "trigger " + count, otherPort.parent, otherPort.name); + count++; + } + + for (let j = 0; j < removeLinks.length; j++) removeLinks[j].remove(); + } + updateButton(); +} + + +}; + +Ops.Sequence.prototype = new CABLES.Op(); +CABLES.OPS["a466bc1f-06e9-4595-8849-bffb9fe22f99"]={f:Ops.Sequence,objName:"Ops.Sequence"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ImageCompose_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.ImageCompose_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"imgcomp_frag":"UNI float a;\nvoid main()\n{\n outColor= vec4(0.0,0.0,0.0,a);\n}\n",}; +const + render = op.inTrigger("Render"), + useVPSize = op.inBool("Use viewport size", true), + width = op.inValueInt("Width", 640), + height = op.inValueInt("Height", 480), + tfilter = op.inSwitch("Filter", ["nearest", "linear", "mipmap"], "linear"), + twrap = op.inValueSelect("Wrap", ["clamp to edge", "repeat", "mirrored repeat"], "repeat"), + fpTexture = op.inValueBool("HDR"), + inTransp = op.inValueBool("Transparent", false), + + trigger = op.outTrigger("Next"), + texOut = op.outTexture("texture_out"), + outRatio = op.outValue("Aspect Ratio"); + +const cgl = op.patch.cgl; +op.setPortGroup("Texture Size", [useVPSize, width, height]); +op.setPortGroup("Texture Settings", [twrap, tfilter, fpTexture, inTransp]); + +texOut.set(CGL.Texture.getEmptyTexture(cgl, fpTexture.get())); +let effect = null; +let tex = null; +let w = 8, h = 8; + +const prevViewPort = [0, 0, 0, 0]; +let reInitEffect = true; + +// const bgShader = new CGL.Shader(cgl, "imgcompose bg"); +// bgShader.setSource(bgShader.getDefaultVertexShader(), attachments.imgcomp_frag); + +// const uniAlpha = new CGL.Uniform(bgShader, "f", "a", !inTransp.get()); + +let selectedFilter = CGL.Texture.FILTER_LINEAR; +let selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + +const fps = 0; +const fpsStart = 0; + +twrap.onChange = onWrapChange; +tfilter.onChange = onFilterChange; + +render.onTriggered = op.preRender = doRender; + +onFilterChange(); +onWrapChange(); +updateSizePorts(); + +// inTransp.onChange = () => +// { +// uniAlpha.setValue(!inTransp.get()); +// }; + +function initEffect() +{ + if (effect)effect.delete(); + if (tex)tex.delete(); + + if (fpTexture.get() && tfilter.get() == "mipmap") op.setUiError("fpmipmap", "Don't use mipmap and HDR at the same time, many systems do not support this."); + else op.setUiError("fpmipmap", null); + + effect = new CGL.TextureEffect(cgl, { "isFloatingPointTexture": fpTexture.get() }); + + tex = new CGL.Texture(cgl, + { + "name": "image_compose_v2_" + op.id, + "isFloatingPointTexture": fpTexture.get(), + "filter": selectedFilter, + "wrap": selectedWrap, + "width": Math.ceil(width.get()), + "height": Math.ceil(height.get()), + }); + + effect.setSourceTexture(tex); + texOut.set(CGL.Texture.getEmptyTexture(cgl, fpTexture.get())); + + reInitEffect = false; +} + +fpTexture.onChange = function () +{ + reInitEffect = true; +}; + +function updateResolution() +{ + if (!effect)initEffect(); + + if (useVPSize.get()) + { + w = cgl.getViewPort()[2]; + h = cgl.getViewPort()[3]; + } + else + { + w = Math.ceil(width.get()); + h = Math.ceil(height.get()); + } + + outRatio.set(w / h); + + if ((w != tex.width || h != tex.height) && (w !== 0 && h !== 0)) + { + // height.set(h); + // width.set(w); + tex.setSize(w, h); + + effect.setSourceTexture(tex); + texOut.set(CGL.Texture.getEmptyTexture(cgl, fpTexture.get())); + texOut.set(tex); + } + + // if (texOut.get() && selectedFilter != CGL.Texture.FILTER_NEAREST) + // { + // if (!texOut.get().isPowerOfTwo()) op.setUiError("hintnpot", "texture dimensions not power of two! - texture filtering when scaling will not work on ios devices.", 0); + // else op.setUiError("hintnpot", null, 0); + // } + // else op.setUiError("hintnpot", null, 0); +} + +function updateSizePorts() +{ + width.setUiAttribs({ "greyout": useVPSize.get() }); + height.setUiAttribs({ "greyout": useVPSize.get() }); +} + +useVPSize.onChange = function () +{ + updateSizePorts(); +}; + +op.preRender = function () +{ + doRender(); + // bgShader.bind(); +}; + +function doRender() +{ + if (!effect || reInitEffect) initEffect(); + + const vp = cgl.getViewPort(); + prevViewPort[0] = vp[0]; + prevViewPort[1] = vp[1]; + prevViewPort[2] = vp[2]; + prevViewPort[3] = vp[3]; + + cgl.pushBlend(false); + + updateResolution(); + + const oldEffect = cgl.currentTextureEffect; + cgl.currentTextureEffect = effect; + cgl.currentTextureEffect.width = width.get(); + cgl.currentTextureEffect.height = height.get(); + effect.setSourceTexture(tex); + + let bgTex = CGL.Texture.getBlackTexture(cgl); + if (inTransp.get())bgTex = CGL.Texture.getEmptyTexture(cgl, fpTexture.get()); + + effect.startEffect(bgTex); + + // cgl.pushShader(bgShader); + // cgl.currentTextureEffect.bind(); + // cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + // cgl.currentTextureEffect.finish(); + // cgl.popShader(); + + trigger.trigger(); + + texOut.set(effect.getCurrentSourceTexture()); + + effect.endEffect(); + + cgl.setViewPort(prevViewPort[0], prevViewPort[1], prevViewPort[2], prevViewPort[3]); + + cgl.popBlend(false); + cgl.currentTextureEffect = oldEffect; +} + +function onWrapChange() +{ + if (twrap.get() == "repeat") selectedWrap = CGL.Texture.WRAP_REPEAT; + if (twrap.get() == "mirrored repeat") selectedWrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + if (twrap.get() == "clamp to edge") selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + reInitEffect = true; + // updateResolution(); +} + +function onFilterChange() +{ + if (tfilter.get() == "nearest") selectedFilter = CGL.Texture.FILTER_NEAREST; + if (tfilter.get() == "linear") selectedFilter = CGL.Texture.FILTER_LINEAR; + if (tfilter.get() == "mipmap") selectedFilter = CGL.Texture.FILTER_MIPMAP; + + reInitEffect = true; + // updateResolution(); +} + + +}; + +Ops.Gl.TextureEffects.ImageCompose_v2.prototype = new CABLES.Op(); +CABLES.OPS["a5b43d4c-a9ea-4eaf-9ed0-f257d222659d"]={f:Ops.Gl.TextureEffects.ImageCompose_v2,objName:"Ops.Gl.TextureEffects.ImageCompose_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.BasicMaterial_v3 +// +// ************************************************************** + +Ops.Gl.Shader.BasicMaterial_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"basicmaterial_frag":"{{MODULES_HEAD}}\n\nIN vec2 texCoord;\n\n#ifdef VERTEX_COLORS\nIN vec4 vertCol;\n#endif\n\n#ifdef HAS_TEXTURES\n IN vec2 texCoordOrig;\n #ifdef HAS_TEXTURE_DIFFUSE\n UNI sampler2D tex;\n #endif\n #ifdef HAS_TEXTURE_OPACITY\n UNI sampler2D texOpacity;\n #endif\n#endif\n\nvoid main()\n{\n {{MODULE_BEGIN_FRAG}}\n vec4 col=color;\n\n\n #ifdef HAS_TEXTURES\n vec2 uv=texCoord;\n\n #ifdef CROP_TEXCOORDS\n if(uv.x<0.0 || uv.x>1.0 || uv.y<0.0 || uv.y>1.0) discard;\n #endif\n\n #ifdef HAS_TEXTURE_DIFFUSE\n col=texture(tex,uv);\n\n #ifdef COLORIZE_TEXTURE\n col.r*=color.r;\n col.g*=color.g;\n col.b*=color.b;\n #endif\n #endif\n col.a*=color.a;\n #ifdef HAS_TEXTURE_OPACITY\n #ifdef TRANSFORMALPHATEXCOORDS\n uv=texCoordOrig;\n #endif\n #ifdef ALPHA_MASK_IALPHA\n col.a*=1.0-texture(texOpacity,uv).a;\n #endif\n #ifdef ALPHA_MASK_ALPHA\n col.a*=texture(texOpacity,uv).a;\n #endif\n #ifdef ALPHA_MASK_LUMI\n col.a*=dot(vec3(0.2126,0.7152,0.0722), texture(texOpacity,uv).rgb);\n #endif\n #ifdef ALPHA_MASK_R\n col.a*=texture(texOpacity,uv).r;\n #endif\n #ifdef ALPHA_MASK_G\n col.a*=texture(texOpacity,uv).g;\n #endif\n #ifdef ALPHA_MASK_B\n col.a*=texture(texOpacity,uv).b;\n #endif\n // #endif\n #endif\n #endif\n\n {{MODULE_COLOR}}\n\n #ifdef DISCARDTRANS\n if(col.a<0.2) discard;\n #endif\n\n #ifdef VERTEX_COLORS\n col*=vertCol;\n #endif\n\n outColor = col;\n}\n","basicmaterial_vert":"\n{{MODULES_HEAD}}\n\n// OUT vec3 norm;\nOUT vec2 texCoord;\nOUT vec2 texCoordOrig;\n\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\n\n#ifdef HAS_TEXTURES\n UNI float diffuseRepeatX;\n UNI float diffuseRepeatY;\n UNI float texOffsetX;\n UNI float texOffsetY;\n#endif\n\n#ifdef VERTEX_COLORS\n in vec4 attrVertColor;\n out vec4 vertCol;\n\n#endif\n\n\nvoid main()\n{\n mat4 mMatrix=modelMatrix;\n mat4 mvMatrix;\n\n norm=attrVertNormal;\n texCoordOrig=attrTexCoord;\n texCoord=attrTexCoord;\n #ifdef HAS_TEXTURES\n texCoord.x=texCoord.x*diffuseRepeatX+texOffsetX;\n texCoord.y=(1.0-texCoord.y)*diffuseRepeatY+texOffsetY;\n #endif\n\n #ifdef VERTEX_COLORS\n vertCol=attrVertColor;\n #endif\n\n vec4 pos = vec4(vPosition, 1.0);\n\n #ifdef BILLBOARD\n vec3 position=vPosition;\n mvMatrix=viewMatrix*modelMatrix;\n\n gl_Position = projMatrix * mvMatrix * vec4((\n position.x * vec3(\n mvMatrix[0][0],\n mvMatrix[1][0],\n mvMatrix[2][0] ) +\n position.y * vec3(\n mvMatrix[0][1],\n mvMatrix[1][1],\n mvMatrix[2][1]) ), 1.0);\n #endif\n\n {{MODULE_VERTEX_POSITION}}\n\n #ifndef BILLBOARD\n mvMatrix=viewMatrix * mMatrix;\n #endif\n\n\n #ifndef BILLBOARD\n // gl_Position = projMatrix * viewMatrix * modelMatrix * pos;\n gl_Position = projMatrix * mvMatrix * pos;\n #endif\n}\n",}; +const render = op.inTrigger("render"); + +const trigger = op.outTrigger("trigger"); +const shaderOut = op.outObject("shader", null, "shader"); + +shaderOut.ignoreValueSerialize = true; + +op.toWorkPortsNeedToBeLinked(render); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "basicmaterialnew"); +shader.addAttribute({ "type": "vec3", "name": "vPosition" }); +shader.addAttribute({ "type": "vec2", "name": "attrTexCoord" }); +shader.addAttribute({ "type": "vec3", "name": "attrVertNormal", "nameFrag": "norm" }); +shader.addAttribute({ "type": "float", "name": "attrVertIndex" }); + +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); + +shader.setSource(attachments.basicmaterial_vert, attachments.basicmaterial_frag); + +shaderOut.set(shader); + +render.onTriggered = doRender; + +// rgba colors +const r = op.inValueSlider("r", Math.random()); +const g = op.inValueSlider("g", Math.random()); +const b = op.inValueSlider("b", Math.random()); +const a = op.inValueSlider("a", 1); +r.setUiAttribs({ "colorPick": true }); + +// const uniColor=new CGL.Uniform(shader,'4f','color',r,g,b,a); +const colUni = shader.addUniformFrag("4f", "color", r, g, b, a); + +shader.uniformColorDiffuse = colUni; + +// diffuse outTexture + +const diffuseTexture = op.inTexture("texture"); +let diffuseTextureUniform = null; +diffuseTexture.onChange = updateDiffuseTexture; + +const colorizeTexture = op.inValueBool("colorizeTexture", false); +const vertexColors = op.inValueBool("Vertex Colors", false); + +// opacity texture +const textureOpacity = op.inTexture("textureOpacity"); +let textureOpacityUniform = null; + +const alphaMaskSource = op.inSwitch("Alpha Mask Source", ["Luminance", "R", "G", "B", "A", "1-A"], "Luminance"); +alphaMaskSource.setUiAttribs({ "greyout": true }); +textureOpacity.onChange = updateOpacity; + +const texCoordAlpha = op.inValueBool("Opacity TexCoords Transform", false); +const discardTransPxl = op.inValueBool("Discard Transparent Pixels"); + +// texture coords +const + diffuseRepeatX = op.inValue("diffuseRepeatX", 1), + diffuseRepeatY = op.inValue("diffuseRepeatY", 1), + diffuseOffsetX = op.inValue("Tex Offset X", 0), + diffuseOffsetY = op.inValue("Tex Offset Y", 0), + cropRepeat = op.inBool("Crop TexCoords", false); + +shader.addUniformFrag("f", "diffuseRepeatX", diffuseRepeatX); +shader.addUniformFrag("f", "diffuseRepeatY", diffuseRepeatY); +shader.addUniformFrag("f", "texOffsetX", diffuseOffsetX); +shader.addUniformFrag("f", "texOffsetY", diffuseOffsetY); + +const doBillboard = op.inValueBool("billboard", false); + +alphaMaskSource.onChange = + doBillboard.onChange = + discardTransPxl.onChange = + texCoordAlpha.onChange = + cropRepeat.onChange = + vertexColors.onChange = + colorizeTexture.onChange = updateDefines; + +op.setPortGroup("Color", [r, g, b, a]); +op.setPortGroup("Color Texture", [diffuseTexture, vertexColors, colorizeTexture]); +op.setPortGroup("Opacity", [textureOpacity, alphaMaskSource, discardTransPxl, texCoordAlpha]); +op.setPortGroup("Texture Transform", [diffuseRepeatX, diffuseRepeatY, diffuseOffsetX, diffuseOffsetY, cropRepeat]); + +updateOpacity(); +updateDiffuseTexture(); + +op.preRender = function () +{ + shader.bind(); + doRender(); +}; + +function doRender() +{ + if (!shader) return; + + cgl.pushShader(shader); + shader.popTextures(); + + if (diffuseTextureUniform && diffuseTexture.get()) shader.pushTexture(diffuseTextureUniform, diffuseTexture.get()); + if (textureOpacityUniform && textureOpacity.get()) shader.pushTexture(textureOpacityUniform, textureOpacity.get()); + + trigger.trigger(); + + cgl.popShader(); +} + +function updateOpacity() +{ + if (textureOpacity.get()) + { + if (textureOpacityUniform !== null) return; + shader.removeUniform("texOpacity"); + shader.define("HAS_TEXTURE_OPACITY"); + if (!textureOpacityUniform)textureOpacityUniform = new CGL.Uniform(shader, "t", "texOpacity"); + + alphaMaskSource.setUiAttribs({ "greyout": false }); + texCoordAlpha.setUiAttribs({ "greyout": false }); + } + else + { + shader.removeUniform("texOpacity"); + shader.removeDefine("HAS_TEXTURE_OPACITY"); + textureOpacityUniform = null; + + alphaMaskSource.setUiAttribs({ "greyout": true }); + texCoordAlpha.setUiAttribs({ "greyout": true }); + } + + updateDefines(); +} + +function updateDiffuseTexture() +{ + if (diffuseTexture.get()) + { + if (!shader.hasDefine("HAS_TEXTURE_DIFFUSE"))shader.define("HAS_TEXTURE_DIFFUSE"); + if (!diffuseTextureUniform)diffuseTextureUniform = new CGL.Uniform(shader, "t", "texDiffuse"); + + diffuseRepeatX.setUiAttribs({ "greyout": false }); + diffuseRepeatY.setUiAttribs({ "greyout": false }); + diffuseOffsetX.setUiAttribs({ "greyout": false }); + diffuseOffsetY.setUiAttribs({ "greyout": false }); + colorizeTexture.setUiAttribs({ "greyout": false }); + } + else + { + shader.removeUniform("texDiffuse"); + shader.removeDefine("HAS_TEXTURE_DIFFUSE"); + diffuseTextureUniform = null; + + diffuseRepeatX.setUiAttribs({ "greyout": true }); + diffuseRepeatY.setUiAttribs({ "greyout": true }); + diffuseOffsetX.setUiAttribs({ "greyout": true }); + diffuseOffsetY.setUiAttribs({ "greyout": true }); + colorizeTexture.setUiAttribs({ "greyout": true }); + } +} + +function updateDefines() +{ + shader.toggleDefine("VERTEX_COLORS", vertexColors.get()); + shader.toggleDefine("CROP_TEXCOORDS", cropRepeat.get()); + shader.toggleDefine("COLORIZE_TEXTURE", colorizeTexture.get()); + shader.toggleDefine("TRANSFORMALPHATEXCOORDS", texCoordAlpha.get()); + shader.toggleDefine("DISCARDTRANS", discardTransPxl.get()); + shader.toggleDefine("BILLBOARD", doBillboard.get()); + + shader.toggleDefine("ALPHA_MASK_ALPHA", alphaMaskSource.get() == "A"); + shader.toggleDefine("ALPHA_MASK_IALPHA", alphaMaskSource.get() == "1-A"); + shader.toggleDefine("ALPHA_MASK_LUMI", alphaMaskSource.get() == "Luminance"); + shader.toggleDefine("ALPHA_MASK_R", alphaMaskSource.get() == "R"); + shader.toggleDefine("ALPHA_MASK_G", alphaMaskSource.get() == "G"); + shader.toggleDefine("ALPHA_MASK_B", alphaMaskSource.get() == "B"); +} + + +}; + +Ops.Gl.Shader.BasicMaterial_v3.prototype = new CABLES.Op(); +CABLES.OPS["ec55d252-3843-41b1-b731-0482dbd9e72b"]={f:Ops.Gl.Shader.BasicMaterial_v3,objName:"Ops.Gl.Shader.BasicMaterial_v3"}; + + + + +// ************************************************************** +// +// Ops.Deprecated.Anim.RelativeTime +// +// ************************************************************** + +Ops.Deprecated.Anim.RelativeTime = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + mul = op.inValue("Multiply", 1), + outTrigger = op.outTrigger("Trigger out"), + result = op.outNumber("result"); + +exe.onTriggered = update; +update(); + +function update() +{ + result.set(op.patch.freeTimer.get() * mul.get()); + outTrigger.trigger(); +} + + +}; + +Ops.Deprecated.Anim.RelativeTime.prototype = new CABLES.Op(); +CABLES.OPS["917df27b-7cc3-465f-986d-bcf5a7e125a7"]={f:Ops.Deprecated.Anim.RelativeTime,objName:"Ops.Deprecated.Anim.RelativeTime"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Noise.FBMNoise +// +// ************************************************************** + +Ops.Gl.TextureEffects.Noise.FBMNoise = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"fbmnoise_frag":"UNI sampler2D tex;\nUNI float anim;\n\nUNI float scale;\nUNI float repeat;\n\nUNI float scrollX;\nUNI float scrollY;\n\nUNI float amount;\n\nUNI bool layer1;\nUNI bool layer2;\nUNI bool layer3;\nUNI bool layer4;\nUNI vec3 color;\nUNI float aspect;\n\nIN vec2 texCoord;\n\n\n{{CGL.BLENDMODES}}\n\n// csdcsdcds\n// adapted from warp shader by inigo quilez/iq\n// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.\n\n// See here for a tutorial on how to make this: http://www.iquilezles.org/www/articles/warp/warp.htm\n\nconst mat2 m = mat2( 0.80, 0.60, -0.60, 0.80 );\n\nfloat noise( in vec2 x )\n{\n\treturn sin(1.5*x.x)*sin(1.5*x.y);\n}\n\nfloat fbm4( vec2 p )\n{\n float f = 0.0;\n f += 0.5000*noise( p ); p = m*p*2.02;\n f += 0.2500*noise( p ); p = m*p*2.03;\n f += 0.1250*noise( p ); p = m*p*2.01;\n f += 0.0625*noise( p );\n return f/0.9375;\n}\n\nfloat fbm6( vec2 p )\n{\n float f = 0.0;\n f += 0.500000*(0.5+0.5*noise( p )); p = m*p*2.02;\n f += 0.250000*(0.5+0.5*noise( p )); p = m*p*2.03;\n f += 0.125000*(0.5+0.5*noise( p )); p = m*p*2.01;\n f += 0.062500*(0.5+0.5*noise( p )); p = m*p*2.04;\n f += 0.031250*(0.5+0.5*noise( p )); p = m*p*2.01;\n f += 0.015625*(0.5+0.5*noise( p ));\n return f/0.96875;\n}\n\nvoid main()\n{\n // vec4 col=texture(tex,texCoord+2.0*fbm4(texCoord+2.0*fbm6(texCoord+anim)));\n\n vec2 tc=texCoord;\n\t#ifdef DO_TILEABLE\n\t tc=abs(texCoord-0.5);\n\t#endif\n\n\n vec2 p=(tc-0.5)*scale;\n\n\n p.y/=aspect;\n vec2 q = vec2( fbm4( p + vec2(0.3+scrollX,0.20+scrollY) ),\n fbm4( p + vec2(3.1+scrollX,1.3+scrollY) ) );\n\n vec2 q2 = vec2( fbm4( p + vec2(2.0+scrollX,1.0+scrollY) ),\n fbm4( p + vec2(3.1+scrollX,1.3+scrollY) ) );\n\n vec2 q3 = vec2( fbm4( p + vec2(9.0+scrollX,4.0+scrollY) ),\n fbm4( p + vec2(3.1+scrollX,4.3+scrollY) ) );\n\n\n\n float v= fbm4( ( p + 4.0*q +anim*0.1)*repeat);\n float v2= fbm4( (p + 4.0*q2 +anim*0.1)*repeat );\n\n float v3= fbm6( (p + 4.0*q3 +anim*0.1)*repeat );\n float v4= fbm6( (p + 4.0*q2 +anim*0.1)*repeat );\n\n\n\n\n vec4 base=texture(tex,texCoord);\n\n vec4 finalColor;\n float colVal=0.0;\n float numLayers=0.0;\n\n if(layer1)\n {\n colVal+=v;\n numLayers++;\n }\n\n if(layer2)\n {\n colVal+=v2;\n numLayers++;\n }\n\n if(layer3)\n {\n colVal+=v3;\n numLayers++;\n }\n\n if(layer4)\n {\n colVal+=v4;\n numLayers++;\n }\n\n finalColor=vec4( color*vec3(colVal/numLayers),1.0);\n\n outColor = cgl_blend(base,finalColor,amount);;\n}\n",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + r = op.inValueSlider("r", 1.0), + g = op.inValueSlider("g", 1.0), + b = op.inValueSlider("b", 1.0), + trigger = op.outTrigger("trigger"); + +r.setUiAttribs({ "colorPick": true }); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "fbmnoise"); + +shader.setSource(shader.getDefaultVertexShader(), attachments.fbmnoise_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); + +const uniScale = new CGL.Uniform(shader, "f", "scale", op.inValue("scale", 2)); +const uniAnim = new CGL.Uniform(shader, "f", "anim", op.inValue("anim", 0)); +const uniScrollX = new CGL.Uniform(shader, "f", "scrollX", op.inValue("scrollX", 9)); +const uniScrollY = new CGL.Uniform(shader, "f", "scrollY", op.inValue("scrollY", 0)); +const uniRepeat = new CGL.Uniform(shader, "f", "repeat", op.inValue("repeat", 1)); +const uniAspect = new CGL.Uniform(shader, "f", "aspect", op.inValue("aspect", 1)); + +const uniLayer1 = new CGL.Uniform(shader, "b", "layer1", op.inValueBool("Layer 1", true)); +const uniLayer2 = new CGL.Uniform(shader, "b", "layer2", op.inValueBool("Layer 2", true)); +const uniLayer3 = new CGL.Uniform(shader, "b", "layer3", op.inValueBool("Layer 3", true)); +const uniLayer4 = new CGL.Uniform(shader, "b", "layer4", op.inValueBool("Layer 4", true)); + +const uniColor = new CGL.Uniform(shader, "3f", "color", r, g, b); + +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +const tile = op.inValueBool("Tileable", false); +tile.onChange = updateTileable; +function updateTileable() +{ + if (tile.get())shader.define("DO_TILEABLE"); + else shader.removeDefine("DO_TILEABLE"); +} + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + uniAspect.set(cgl.currentTextureEffect.getCurrentSourceTexture().width / cgl.currentTextureEffect.getCurrentSourceTexture().height); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Noise.FBMNoise.prototype = new CABLES.Op(); +CABLES.OPS["7073186c-b776-48c2-a01e-041df88ad88a"]={f:Ops.Gl.TextureEffects.Noise.FBMNoise,objName:"Ops.Gl.TextureEffects.Noise.FBMNoise"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ColorMap +// +// ************************************************************** + +Ops.Gl.TextureEffects.ColorMap = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"colormap_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D gradient;\nUNI float pos;\nUNI float amount;\nUNI float vmin;\nUNI float vmax;\n\n{{CGL.BLENDMODES}}\n\n\nfloat lumi(vec3 color)\n{\n return vec3(dot(vec3(0.2126,0.7152,0.0722), color)).r;\n}\n\nvoid main()\n{\n vec4 base=texture(tex,texCoord);\n\n base=clamp(base,vmin,vmax);\n\n #ifdef METH_LUMI\n vec4 color=texture(gradient,vec2(lumi(base.rgb),pos));\n #endif\n\n #ifdef METH_CHANNELS\n vec4 color=vec4(1.0);\n color.r=texture(gradient,vec2(base.r,pos)).r;\n color.g=texture(gradient,vec2(base.g,pos)).g;\n color.b=texture(gradient,vec2(base.b,pos)).b;\n #endif\n\n// outColor= vec4(color);\n outColor=cgl_blend(base,color,amount);\n\n}\n",}; +let render = op.inTrigger("render"); +let trigger = op.outTrigger("trigger"); + +const blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"); +const amount = op.inValueSlider("Amount", 1); + +let inGradient = op.inTexture("Gradient"); +let inMethod = op.inSwitch("Method", ["Luminance", "Channels"], "Luminance"); + +let inMin = op.inFloatSlider("Min", 0); +let inMax = op.inFloatSlider("Max", 1); + +let inPos = op.inValueSlider("Position", 0.5); + +op.setPortGroup("Vertical Position", [inMin, inMax, inPos]); + +let cgl = op.patch.cgl; +let shader = new CGL.Shader(cgl, op.name); +shader.define("METH_LUMI"); + +shader.setSource(shader.getDefaultVertexShader(), attachments.colormap_frag); +var textureUniform = new CGL.Uniform(shader, "t", "tex", 0); + +var textureUniform = new CGL.Uniform(shader, "t", "gradient", 1); +let uniPos = new CGL.Uniform(shader, "f", "pos", inPos); + +let uniMin = new CGL.Uniform(shader, "f", "vmin", inMin); +let uniMax = new CGL.Uniform(shader, "f", "vmax", inMax); +let uniAmount = new CGL.Uniform(shader, "f", "amount", amount); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +inMethod.onChange = () => +{ + shader.toggleDefine("METH_LUMI", inMethod.get() == "Luminance"); + shader.toggleDefine("METH_CHANNELS", inMethod.get() == "Channels"); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + if (!inGradient.get()) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.setTexture(1, inGradient.get().tex); + // cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, inGradient.get().tex ); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.ColorMap.prototype = new CABLES.Op(); +CABLES.OPS["58e302d7-4b84-4077-aa13-4f3cf0885205"]={f:Ops.Gl.TextureEffects.ColorMap,objName:"Ops.Gl.TextureEffects.ColorMap"}; + + + + +// ************************************************************** +// +// Ops.Gl.Render2Texture +// +// ************************************************************** + +Ops.Gl.Render2Texture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const cgl = op.patch.cgl; + +const + render = op.inTrigger("render"), + useVPSize = op.inValueBool("use viewport size", true), + width = op.inValueInt("texture width", 512), + height = op.inValueInt("texture height", 512), + aspect = op.inBool("Auto Aspect", false), + tfilter = op.inSwitch("filter", ["nearest", "linear", "mipmap"], "linear"), + twrap = op.inSwitch("Wrap", ["Clamp", "Repeat", "Mirror"], "Repeat"), + msaa = op.inSwitch("MSAA", ["none", "2x", "4x", "8x"], "none"), + trigger = op.outTrigger("trigger"), + tex = op.outTexture("texture"), + texDepth = op.outTexture("textureDepth"), + fpTexture = op.inValueBool("HDR"), + depth = op.inValueBool("Depth", true), + clear = op.inValueBool("Clear", true); + +let fb = null; +let reInitFb = true; +tex.set(CGL.Texture.getEmptyTexture(cgl)); + +op.setPortGroup("Size", [useVPSize, width, height, aspect]); + +const prevViewPort = [0, 0, 0, 0]; + +fpTexture.setUiAttribs({ "title": "Pixelformat Float 32bit" }); + +fpTexture.onChange = + depth.onChange = + clear.onChange = + tfilter.onChange = + twrap.onChange = + msaa.onChange = initFbLater; + +useVPSize.onChange = updateVpSize; + +render.onTriggered = + op.preRender = doRender; + +updateVpSize(); + +function updateVpSize() +{ + width.setUiAttribs({ "greyout": useVPSize.get() }); + height.setUiAttribs({ "greyout": useVPSize.get() }); + aspect.setUiAttribs({ "greyout": useVPSize.get() }); +} + +function initFbLater() +{ + reInitFb = true; +} + +function doRender() +{ + const vp = cgl.getViewPort(); + prevViewPort[0] = vp[0]; + prevViewPort[1] = vp[1]; + prevViewPort[2] = vp[2]; + prevViewPort[3] = vp[3]; + + if (!fb || reInitFb) + { + if (fb) fb.delete(); + + let selectedWrap = CGL.Texture.WRAP_REPEAT; + if (twrap.get() == "Clamp") selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + else if (twrap.get() == "Mirror") selectedWrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + + let selectFilter = CGL.Texture.FILTER_NEAREST; + if (tfilter.get() == "nearest") selectFilter = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "linear") selectFilter = CGL.Texture.FILTER_LINEAR; + else if (tfilter.get() == "mipmap") selectFilter = CGL.Texture.FILTER_MIPMAP; + + if (fpTexture.get() && tfilter.get() == "mipmap") op.setUiError("fpmipmap", "Don't use mipmap and HDR at the same time, many systems do not support this."); + else op.setUiError("fpmipmap", null); + + if (cgl.glVersion >= 2) + { + let ms = true; + let msSamples = 4; + + if (msaa.get() == "none") + { + msSamples = 0; + ms = false; + } + if (msaa.get() == "2x") msSamples = 2; + if (msaa.get() == "4x") msSamples = 4; + if (msaa.get() == "8x") msSamples = 8; + + fb = new CGL.Framebuffer2(cgl, 8, 8, + { + "name": "render2texture " + op.id, + "isFloatingPointTexture": fpTexture.get(), + "multisampling": ms, + "wrap": selectedWrap, + "filter": selectFilter, + "depth": depth.get(), + "multisamplingSamples": msSamples, + "clear": clear.get() + }); + } + else + { + fb = new CGL.Framebuffer(cgl, 8, 8, { "isFloatingPointTexture": fpTexture.get(), "clear": clear.get() }); + } + + texDepth.set(fb.getTextureDepth()); + reInitFb = false; + } + + if (useVPSize.get()) + { + width.set(cgl.getViewPort()[2]); + height.set(cgl.getViewPort()[3]); + } + + if (fb.getWidth() != Math.ceil(width.get()) || fb.getHeight() != Math.ceil(height.get())) + { + fb.setSize( + Math.max(1, Math.ceil(width.get())), + Math.max(1, Math.ceil(height.get()))); + } + + fb.renderStart(cgl); + + if (aspect.get()) mat4.perspective(cgl.pMatrix, 45, width.get() / height.get(), 0.1, 1000.0); + + trigger.trigger(); + fb.renderEnd(cgl); + + // cgl.resetViewPort(); + cgl.setViewPort(prevViewPort[0], prevViewPort[1], prevViewPort[2], prevViewPort[3]); + + tex.set(CGL.Texture.getEmptyTexture(op.patch.cgl)); + tex.set(fb.getTextureColor()); +} + + +}; + +Ops.Gl.Render2Texture.prototype = new CABLES.Op(); +CABLES.OPS["d01fa820-396c-4cb5-9d78-6b14762852af"]={f:Ops.Gl.Render2Texture,objName:"Ops.Gl.Render2Texture"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.DrawImage_v3 +// +// ************************************************************** + +Ops.Gl.TextureEffects.DrawImage_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"drawimage_frag":"#ifdef HAS_TEXTURES\n IN vec2 texCoord;\n UNI sampler2D tex;\n UNI sampler2D image;\n#endif\n\n#ifdef TEX_TRANSFORM\n IN mat3 transform;\n#endif\n// UNI float rotate;\n\n{{CGL.BLENDMODES}}\n\n#ifdef HAS_TEXTUREALPHA\n UNI sampler2D imageAlpha;\n#endif\n\nUNI float amount;\n\n#ifdef ASPECT_RATIO\n UNI float aspectTex;\n UNI float aspectPos;\n#endif\n\nvoid main()\n{\n vec4 blendRGBA=vec4(0.0,0.0,0.0,1.0);\n\n #ifdef HAS_TEXTURES\n vec2 tc=texCoord;\n\n #ifdef TEX_FLIP_X\n tc.x=1.0-tc.x;\n #endif\n #ifdef TEX_FLIP_Y\n tc.y=1.0-tc.y;\n #endif\n\n #ifdef ASPECT_RATIO\n #ifdef ASPECT_AXIS_X\n tc.y=(1.0-aspectPos)-(((1.0-aspectPos)-tc.y)*aspectTex);\n #endif\n #ifdef ASPECT_AXIS_Y\n tc.x=(1.0-aspectPos)-(((1.0-aspectPos)-tc.x)/aspectTex);\n #endif\n #endif\n\n #ifdef TEX_TRANSFORM\n vec3 coordinates=vec3(tc.x, tc.y,1.0);\n tc=(transform * coordinates ).xy;\n #endif\n\n blendRGBA=texture(image,tc);\n\n vec3 blend=blendRGBA.rgb;\n vec4 baseRGBA=texture(tex,texCoord);\n vec3 base=baseRGBA.rgb;\n\n\n #ifdef PREMUL\n blend.rgb = (blend.rgb) + (base.rgb * (1.0 - blendRGBA.a));\n #endif\n\n vec3 colNew=_blend(base,blend);\n\n\n\n\n #ifdef REMOVE_ALPHA_SRC\n blendRGBA.a=1.0;\n #endif\n\n #ifdef HAS_TEXTUREALPHA\n vec4 colImgAlpha=texture(imageAlpha,tc);\n float colImgAlphaAlpha=colImgAlpha.a;\n\n #ifdef ALPHA_FROM_LUMINANCE\n vec3 gray = vec3(dot(vec3(0.2126,0.7152,0.0722), colImgAlpha.rgb ));\n colImgAlphaAlpha=(gray.r+gray.g+gray.b)/3.0;\n #endif\n\n #ifdef ALPHA_FROM_INV_UMINANCE\n vec3 gray = vec3(dot(vec3(0.2126,0.7152,0.0722), colImgAlpha.rgb ));\n colImgAlphaAlpha=1.0-(gray.r+gray.g+gray.b)/3.0;\n #endif\n\n #ifdef INVERT_ALPHA\n colImgAlphaAlpha=clamp(colImgAlphaAlpha,0.0,1.0);\n colImgAlphaAlpha=1.0-colImgAlphaAlpha;\n #endif\n\n blendRGBA.a=colImgAlphaAlpha*blendRGBA.a;\n #endif\n #endif\n\n float am=amount;\n\n #ifdef CLIP_REPEAT\n if(tc.y>1.0 || tc.y<0.0 || tc.x>1.0 || tc.x<0.0)\n {\n // colNew.rgb=vec3(0.0);\n am=0.0;\n }\n #endif\n\n #ifdef ASPECT_RATIO\n #ifdef ASPECT_CROP\n if(tc.y>1.0 || tc.y<0.0 || tc.x>1.0 || tc.x<0.0)\n {\n colNew.rgb=base.rgb;\n am=0.0;\n }\n\n #endif\n #endif\n\n\n\n #ifndef PREMUL\n blendRGBA.rgb=mix(colNew,base,1.0-(am*blendRGBA.a));\n blendRGBA.a=clamp(baseRGBA.a+(blendRGBA.a*am),0.,1.);\n #endif\n\n #ifdef PREMUL\n // premultiply\n // blendRGBA.rgb = (blendRGBA.rgb) + (baseRGBA.rgb * (1.0 - blendRGBA.a));\n blendRGBA=vec4(\n mix(colNew.rgb,base,1.0-(am*blendRGBA.a)),\n blendRGBA.a*am+baseRGBA.a\n );\n #endif\n\n #ifdef ALPHA_MASK\n blendRGBA.a=baseRGBA.a;\n #endif\n\n outColor=blendRGBA;\n}\n\n\n\n\n\n\n\n","drawimage_vert":"IN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\n\nUNI mat4 projMatrix;\nUNI mat4 mvMatrix;\n\nOUT vec2 texCoord;\n// OUT vec3 norm;\n\n#ifdef TEX_TRANSFORM\n UNI float posX;\n UNI float posY;\n UNI float scaleX;\n UNI float scaleY;\n UNI float rotate;\n OUT mat3 transform;\n#endif\n\nvoid main()\n{\n texCoord=attrTexCoord;\n// norm=attrVertNormal;\n\n #ifdef TEX_TRANSFORM\n vec3 coordinates=vec3(attrTexCoord.x, attrTexCoord.y,1.0);\n float angle = radians( rotate );\n vec2 scale= vec2(scaleX,scaleY);\n vec2 translate= vec2(posX,posY);\n\n transform = mat3( scale.x * cos( angle ), scale.x * sin( angle ), 0.0,\n - scale.y * sin( angle ), scale.y * cos( angle ), 0.0,\n - 0.5 * scale.x * cos( angle ) + 0.5 * scale.y * sin( angle ) - 0.5 * translate.x*2.0 + 0.5, - 0.5 * scale.x * sin( angle ) - 0.5 * scale.y * cos( angle ) - 0.5 * translate.y*2.0 + 0.5, 1.0);\n #endif\n\n gl_Position = projMatrix * mvMatrix * vec4(vPosition, 1.0);\n}\n",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "blendMode"), + amount = op.inValueSlider("amount", 1), + + image = op.inTexture("Image"), + inAlphaPremul = op.inValueBool("Premultiplied", false), + inAlphaMask = op.inValueBool("Alpha Mask", false), + removeAlphaSrc = op.inValueBool("removeAlphaSrc", false), + + imageAlpha = op.inTexture("Mask"), + alphaSrc = op.inValueSelect("Mask Src", ["alpha channel", "luminance", "luminance inv"], "luminance"), + invAlphaChannel = op.inValueBool("Invert alpha channel"), + + inAspect = op.inValueBool("Aspect Ratio", false), + inAspectAxis = op.inValueSelect("Stretch Axis", ["X", "Y"], "X"), + inAspectPos = op.inValueSlider("Position", 0.0), + inAspectCrop = op.inValueBool("Crop", false), + + trigger = op.outTrigger("trigger"); + +blendMode.set("normal"); +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "drawimage"); + +imageAlpha.onLinkChanged = updateAlphaPorts; + +op.setPortGroup("Mask", [imageAlpha, alphaSrc, invAlphaChannel]); +op.setPortGroup("Aspect Ratio", [inAspect, inAspectPos, inAspectCrop, inAspectAxis]); + +function updateAlphaPorts() +{ + if (imageAlpha.isLinked()) + { + removeAlphaSrc.setUiAttribs({ "greyout": true }); + alphaSrc.setUiAttribs({ "greyout": false }); + invAlphaChannel.setUiAttribs({ "greyout": false }); + } + else + { + removeAlphaSrc.setUiAttribs({ "greyout": false }); + alphaSrc.setUiAttribs({ "greyout": true }); + invAlphaChannel.setUiAttribs({ "greyout": true }); + } +} + +op.toWorkPortsNeedToBeLinked(image); + +shader.setSource(attachments.drawimage_vert, attachments.drawimage_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + textureImaghe = new CGL.Uniform(shader, "t", "image", 1), + textureAlpha = new CGL.Uniform(shader, "t", "imageAlpha", 2), + uniTexAspect = new CGL.Uniform(shader, "f", "aspectTex", 1), + uniAspectPos = new CGL.Uniform(shader, "f", "aspectPos", inAspectPos); + +inAspect.onChange = + inAspectCrop.onChange = + inAspectAxis.onChange = updateAspectRatio; + +function updateAspectRatio() +{ + shader.removeDefine("ASPECT_AXIS_X"); + shader.removeDefine("ASPECT_AXIS_Y"); + shader.removeDefine("ASPECT_CROP"); + + inAspectPos.setUiAttribs({ "greyout": !inAspect.get() }); + inAspectCrop.setUiAttribs({ "greyout": !inAspect.get() }); + inAspectAxis.setUiAttribs({ "greyout": !inAspect.get() }); + + if (inAspect.get()) + { + shader.define("ASPECT_RATIO"); + + if (inAspectCrop.get()) shader.define("ASPECT_CROP"); + + if (inAspectAxis.get() == "X") shader.define("ASPECT_AXIS_X"); + if (inAspectAxis.get() == "Y") shader.define("ASPECT_AXIS_Y"); + } + else + { + shader.removeDefine("ASPECT_RATIO"); + if (inAspectCrop.get()) shader.define("ASPECT_CROP"); + + if (inAspectAxis.get() == "X") shader.define("ASPECT_AXIS_X"); + if (inAspectAxis.get() == "Y") shader.define("ASPECT_AXIS_Y"); + } +} + +alphaSrc.set("alpha channel"); + +// +// texture flip +// +const flipX = op.inValueBool("flip x"); +const flipY = op.inValueBool("flip y"); + +// +// texture transform +// + +let doTransform = op.inValueBool("Transform"); + +let scaleX = op.inValueSlider("Scale X", 1); +let scaleY = op.inValueSlider("Scale Y", 1); + +let posX = op.inValue("Position X", 0); +let posY = op.inValue("Position Y", 0); + +let rotate = op.inValue("Rotation", 0); + +const inClipRepeat = op.inValueBool("Clip Repeat", false); + +const uniScaleX = new CGL.Uniform(shader, "f", "scaleX", scaleX); +const uniScaleY = new CGL.Uniform(shader, "f", "scaleY", scaleY); +const uniPosX = new CGL.Uniform(shader, "f", "posX", posX); +const uniPosY = new CGL.Uniform(shader, "f", "posY", posY); +const uniRotate = new CGL.Uniform(shader, "f", "rotate", rotate); + +doTransform.onChange = updateTransformPorts; + +function updateTransformPorts() +{ + shader.toggleDefine("TEX_TRANSFORM", doTransform.get()); + + scaleX.setUiAttribs({ "greyout": !doTransform.get() }); + scaleY.setUiAttribs({ "greyout": !doTransform.get() }); + posX.setUiAttribs({ "greyout": !doTransform.get() }); + posY.setUiAttribs({ "greyout": !doTransform.get() }); + rotate.setUiAttribs({ "greyout": !doTransform.get() }); +} + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +render.onTriggered = doRender; + +inClipRepeat.onChange = + imageAlpha.onChange = + inAlphaPremul.onChange = + inAlphaMask.onChange = + invAlphaChannel.onChange = + flipY.onChange = + flipX.onChange = + removeAlphaSrc.onChange = + alphaSrc.onChange = updateDefines; + +updateTransformPorts(); +updateAlphaPorts(); +updateAspectRatio(); +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("REMOVE_ALPHA_SRC", removeAlphaSrc.get()); + shader.toggleDefine("ALPHA_MASK", inAlphaMask.get()); + + shader.toggleDefine("CLIP_REPEAT", inClipRepeat.get()); + + shader.toggleDefine("HAS_TEXTUREALPHA", imageAlpha.get() && imageAlpha.get().tex); + + shader.toggleDefine("TEX_FLIP_X", flipX.get()); + shader.toggleDefine("TEX_FLIP_Y", flipY.get()); + + shader.toggleDefine("INVERT_ALPHA", invAlphaChannel.get()); + + shader.toggleDefine("ALPHA_FROM_LUMINANCE", alphaSrc.get() == "luminance"); + shader.toggleDefine("ALPHA_FROM_INV_UMINANCE", alphaSrc.get() == "luminance_inv"); + shader.toggleDefine("PREMUL", inAlphaPremul.get()); +} + +function doRender() +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + const tex = image.get(); + if (tex && tex.tex && amount.get() > 0.0) + { + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + const imgTex = cgl.currentTextureEffect.getCurrentSourceTexture(); + cgl.setTexture(0, imgTex.tex); + + if (imgTex && tex) + { + if (tex.textureType != imgTex.textureType && (tex.textureType != CGL.Texture.TYPE_FLOAT || imgTex.textureType != CGL.Texture.TYPE_FLOAT)) + op.setUiError("textypediff", "Drawing 32bit texture into an 8 bit can result in data/precision loss", 1); + else + op.setUiError("textypediff", null); + } + + const asp = 1 / (cgl.currentTextureEffect.getWidth() / cgl.currentTextureEffect.getHeight()) * (tex.width / tex.height); + // uniTexAspect.setValue(1 / (tex.height / tex.width * imgTex.width / imgTex.height)); + + uniTexAspect.setValue(asp); + + cgl.setTexture(1, tex.tex); + // cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, image.get().tex ); + + if (imageAlpha.get() && imageAlpha.get().tex) + { + cgl.setTexture(2, imageAlpha.get().tex); + // cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, imageAlpha.get().tex ); + } + + // cgl.pushBlend(false); + + cgl.pushBlendMode(CGL.BLEND_NONE, true); + + cgl.currentTextureEffect.finish(); + cgl.popBlendMode(); + + // cgl.popBlend(); + + cgl.popShader(); + } + + trigger.trigger(); +} + + +}; + +Ops.Gl.TextureEffects.DrawImage_v3.prototype = new CABLES.Op(); +CABLES.OPS["8f6b2f15-fcb0-4597-90c0-e5173f2969fe"]={f:Ops.Gl.TextureEffects.DrawImage_v3,objName:"Ops.Gl.TextureEffects.DrawImage_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.GradientTexture +// +// ************************************************************** + +Ops.Gl.GradientTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inGrad = op.inGradient("Gradient"), + inDir = op.inValueSelect("Direction", ["X", "Y", "Radial"], "X"), + inSmoothstep = op.inValueBool("Smoothstep", false), + inStep = op.inBool("Step", false), + inFlip = op.inBool("Flip", false), + inSRGB = op.inBool("sRGB", false), + inOklab = op.inBool("Oklab", false), + inSize = op.inValueInt("Size", 256), + tfilter = op.inSwitch("filter", ["nearest", "linear", "mipmap"], "linear"), + twrap = op.inValueSelect("wrap", ["clamp to edge", "repeat", "mirrored repeat"], "clamp to edge"), + inGradArray = op.inArray("Gradient Array"), + inRandom = op.inTriggerButton("Randomize Colors"), + outTex = op.outTexture("Texture"), + outColors = op.outArray("Colors", null, 3), + outColorPos = op.outArray("Colors Pos", null, 1); + +const cgl = op.patch.cgl; + +twrap.onChange = + tfilter.onChange = + inStep.onChange = + inFlip.onChange = + inSRGB.onChange = + inOklab.onChange = + inSize.onChange = inGrad.onChange = inSmoothstep.onChange = inDir.onChange = inGradArray.onChange = update; + +inGrad.set("{\"keys\" : [{\"pos\":0,\"r\":0,\"g\":0,\"b\":0},{\"pos\":0.25,\"r\":0,\"g\":0,\"b\":0},{\"pos\":0.75,\"r\":1,\"g\":1,\"b\":1},{\"pos\":1,\"r\":1,\"g\":1,\"b\":1}]}"); + +op.onLoaded = update; + +inRandom.onTriggered = () => +{ + const keys = parseKeys(); + if (keys) + { + keys.forEach((key) => + { + key.r = Math.random(); + key.g = Math.random(); + key.b = Math.random(); + }); + const newKeys = JSON.stringify({ "keys": keys }); + inGrad.set(newKeys); + } +}; + +function rgbToOklab(r, g, b) +{ + let l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b; + let m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b; + let s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b; + l = Math.cbrt(l); m = Math.cbrt(m); s = Math.cbrt(s); + return [ + l * +0.2104542553 + m * +0.7936177850 + s * -0.0040720468, + l * +1.9779984951 + m * -2.4285922050 + s * +0.4505937099, + l * +0.0259040371 + m * +0.7827717662 + s * -0.8086757660 + ]; +} + +function clamp(value, min, max) +{ + return Math.max(Math.min(value, max), min); +} + +function oklabToRGB(L, a, b) +{ + let l = L + a * +0.3963377774 + b * +0.2158037573; + let m = L + a * -0.1055613458 + b * -0.0638541728; + let s = L + a * -0.0894841775 + b * -1.2914855480; + l **= 3; m **= 3; s **= 3; + let r = l * +4.0767416621 + m * -3.3077115913 + s * +0.2309699292; + let g = l * -1.2684380046 + m * +2.6097574011 + s * -0.3413193965; + var b = l * -0.0041960863 + m * -0.7034186147 + s * +1.7076147010; + r = clamp(r, 0, 1); g = clamp(g, 0, 1); b = clamp(b, 0, 1); + return [r, g, b]; +} + +function lin2srgb(r, g, b) +{ + r /= 255; + + const thr = 0.0031308; + + let c_loR = 12.92 * r; + + let c_hiR = 1.055 * Math.pow(r, 0.41666) - 0.055; + return ((r < thr) ? c_loR : c_hiR) * 255; +} + +function update() +{ + const keys = parseKeys(); + if (keys) updateGradient(keys); +} + +function parseKeys() +{ + let keys = null; + op.setUiError("nodata", null); + op.setUiError("parse", null); + + if (Array.isArray(inGradArray.get())) + { + keys = inGradArray.get(); + } + else + { + let grad = null; + if (!inGrad.get() || inGrad.get() === "") + { + op.setUiError("nodata", "gradient no data"); + return null; + } + + try + { + grad = JSON.parse(inGrad.get()); + } + catch (e) + { + op.setUiError("parse", "could not parse gradient data"); + } + + if (!grad || !grad.keys) + { + op.setUiError("nodata", "gradient no data"); + return null; + } + keys = grad.keys; + } + return keys; +} + +function updateGradient(keys) +{ + let width = Math.round(inSize.get()); + if (width < 4) width = 4; + + let selectedWrap = 0; + let selectedFilter = 0; + if (twrap.get() == "repeat") selectedWrap = CGL.Texture.WRAP_REPEAT; + else if (twrap.get() == "mirrored repeat") selectedWrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + else if (twrap.get() == "clamp to edge") selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + if (tfilter.get() == "nearest") selectedFilter = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "linear") selectedFilter = CGL.Texture.FILTER_LINEAR; + else if (tfilter.get() == "mipmap") selectedFilter = CGL.Texture.FILTER_MIPMAP; + + const tex = new CGL.Texture(cgl); + + if (inDir.get() == "X" || inDir.get() == "Y") + { + const pixels = new Uint8Array(width * 4); + + for (let i = 0; i < keys.length - 1; i++) + { + const keyA = keys[i]; + const keyB = keys[i + 1]; + + for (let x = keyA.pos * width; x < keyB.pos * width; x++) + { + let p = CABLES.map(x, keyA.pos * width, keyB.pos * width, 0, 1); + if (inStep.get())p = Math.round(p); + if (inSmoothstep.get()) p = CABLES.smoothStep(p); + x = Math.round(x); + + let xx = x; + if (inFlip.get())xx = width - x - 1; + + if (inOklab.get()) + { + const klabA = rgbToOklab(keyA.r, keyA.g, keyA.b); + const labA_r = klabA[0]; + const labA_g = klabA[1]; + const labA_b = klabA[2]; + + const klabB = rgbToOklab(keyB.r, keyB.g, keyB.b); + const labB_r = klabB[0]; + const labB_g = klabB[1]; + const labB_b = klabB[2]; + + const l = ((p * labB_r + (1.0 - p) * labA_r)); + const a = ((p * labB_g + (1.0 - p) * labA_g)); + const b = ((p * labB_b + (1.0 - p) * labA_b)); + + const pixCol = oklabToRGB(l, a, b); + pixels[xx * 4 + 0] = Math.round(pixCol[0] * 255); + pixels[xx * 4 + 1] = Math.round(pixCol[1] * 255); + pixels[xx * 4 + 2] = Math.round(pixCol[2] * 255); + } + else + { + pixels[xx * 4 + 0] = Math.round((p * keyB.r + (1.0 - p) * keyA.r) * 255); + pixels[xx * 4 + 1] = Math.round((p * keyB.g + (1.0 - p) * keyA.g) * 255); + pixels[xx * 4 + 2] = Math.round((p * keyB.b + (1.0 - p) * keyA.b) * 255); + } + + if (typeof keyA.a !== "undefined" && typeof keyB.a !== "undefined") + { + const alpha = Math.round((p * keyB.a + (1.0 - p) * keyA.a) * 255); + pixels[xx * 4 + 3] = alpha; + } + else + { + pixels[xx * 4 + 3] = Math.round(255); + } + } + } + + if (inSRGB.get()) + for (let i = 0; i < pixels.length; i += 4) + { + pixels[i + 0] = lin2srgb(pixels[i + 0]); + pixels[i + 1] = lin2srgb(pixels[i + 1]); + pixels[i + 2] = lin2srgb(pixels[i + 2]); + } + + if (inDir.get() == "X") tex.initFromData(pixels, width, 1, selectedFilter, selectedWrap); + if (inDir.get() == "Y") tex.initFromData(pixels, 1, width, selectedFilter, selectedWrap); + } + + if (inDir.get() == "Radial") + { + const pixels = new Uint8Array(width * width * 4); + + const animR = new CABLES.Anim(); + const animG = new CABLES.Anim(); + const animB = new CABLES.Anim(); + + for (let i = 0; i < keys.length - 1; i++) + { + animR.setValue(keys[i].pos, keys[i].r); + animG.setValue(keys[i].pos, keys[i].g); + animB.setValue(keys[i].pos, keys[i].b); + } + + for (let x = 0; x < width; x++) + { + for (let y = 0; y < width; y++) + { + const dx = x - (width - 1) / 2; + const dy = y - (width - 1) / 2; + let pos = Math.sqrt(dx * dx + dy * dy) / (width) * 2; + + if (inSmoothstep.get()) pos = CABLES.smoothStep(pos); + + pixels[(x * 4) + (y * 4 * width) + 0] = animR.getValue(pos) * 255; + pixels[(x * 4) + (y * 4 * width) + 1] = animG.getValue(pos) * 255; + pixels[(x * 4) + (y * 4 * width) + 2] = animB.getValue(pos) * 255; + pixels[(x * 4) + (y * 4 * width) + 3] = Math.round(255); + } + } + + if (inSRGB.get()) + for (let i = 0; i < pixels.length; i += 4) + { + pixels[i + 0] = lin2srgb(pixels[i + 0]); + pixels[i + 1] = lin2srgb(pixels[i + 1]); + pixels[i + 2] = lin2srgb(pixels[i + 2]); + } + + tex.initFromData(pixels, width, width, selectedFilter, selectedWrap); + } + + const colorArr = []; + for (let i = 0; i < keys.length - 1; i++) + { + colorArr.push(keys[i].r, keys[i].g, keys[i].b); + } + + const colorPosArr = []; + for (let i = 0; i < keys.length - 1; i++) + { + colorPosArr.push(keys[i].pos); + } + + outColors.set(colorArr); + outColorPos.set(colorPosArr); + + outTex.set(null); + outTex.set(tex); +} + + +}; + +Ops.Gl.GradientTexture.prototype = new CABLES.Op(); +CABLES.OPS["01380a50-2dbb-4465-ae80-86349b0b717a"]={f:Ops.Gl.GradientTexture,objName:"Ops.Gl.GradientTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.OrbitControls +// +// ************************************************************** + +Ops.Gl.Matrix.OrbitControls = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + minDist = op.inValueFloat("min distance"), + maxDist = op.inValueFloat("max distance"), + + minRotY = op.inValue("min rot y", 0), + maxRotY = op.inValue("max rot y", 0), + + initialRadius = op.inValue("initial radius", 0), + initialAxis = op.inValueSlider("initial axis y"), + initialX = op.inValueSlider("initial axis x"), + + mul = op.inValueFloat("mul"), + smoothness = op.inValueSlider("Smoothness", 1.0), + speedX = op.inValue("Speed X", 1), + speedY = op.inValue("Speed Y", 1), + + active = op.inValueBool("Active", true), + + allowPanning = op.inValueBool("Allow Panning", true), + allowZooming = op.inValueBool("Allow Zooming", true), + allowRotation = op.inValueBool("Allow Rotation", true), + restricted = op.inValueBool("restricted", true), + + trigger = op.outTrigger("trigger"), + outRadius = op.outNumber("radius"), + outXDeg = op.outNumber("Rot X"), + outYDeg = op.outNumber("Rot Y"), + + inReset = op.inTriggerButton("Reset"); + +op.setPortGroup("Initial Values", [initialAxis, initialX, initialRadius]); +op.setPortGroup("Interaction", [mul, smoothness, speedX, speedY]); +op.setPortGroup("Boundaries", [minRotY, maxRotY, minDist, maxDist]); + +mul.set(1); +minDist.set(0.05); +maxDist.set(99999); + +inReset.onTriggered = reset; + +let eye = vec3.create(); +const vUp = vec3.create(); +const vCenter = vec3.create(); +const viewMatrix = mat4.create(); +const tempViewMatrix = mat4.create(); +const vOffset = vec3.create(); +const finalEyeAbs = vec3.create(); + +initialAxis.set(0.5); + +let mouseDown = false; +let radius = 5; +outRadius.set(radius); + +let lastMouseX = 0, lastMouseY = 0; +let percX = 0, percY = 0; + +vec3.set(vCenter, 0, 0, 0); +vec3.set(vUp, 0, 1, 0); + +const tempEye = vec3.create(); +const finalEye = vec3.create(); +const tempCenter = vec3.create(); +const finalCenter = vec3.create(); + +let px = 0; +let py = 0; + +let divisor = 1; +let element = null; +updateSmoothness(); + +op.onDelete = unbind; + +const halfCircle = Math.PI; +const fullCircle = Math.PI * 2; + +function reset() +{ + let off = 0; + + if (px % fullCircle < -halfCircle) + { + off = -fullCircle; + px %= -fullCircle; + } + else + if (px % fullCircle > halfCircle) + { + off = fullCircle; + px %= fullCircle; + } + else px %= fullCircle; + + py %= (Math.PI); + + vec3.set(vOffset, 0, 0, 0); + vec3.set(vCenter, 0, 0, 0); + vec3.set(vUp, 0, 1, 0); + + percX = (initialX.get() * Math.PI * 2 + off); + percY = (initialAxis.get() - 0.5); + + radius = initialRadius.get(); + eye = circlePos(percY); +} + +function updateSmoothness() +{ + divisor = smoothness.get() * 10 + 1.0; +} + +smoothness.onChange = updateSmoothness; + +let initializing = true; + +function ip(val, goal) +{ + if (initializing) return goal; + return val + (goal - val) / divisor; +} + +let lastPy = 0; +const lastPx = 0; + +render.onTriggered = function () +{ + const cgl = op.patch.cg; + + if (!element) + { + setElement(cgl.canvas); + bind(); + } + + cgl.pushViewMatrix(); + + px = ip(px, percX); + py = ip(py, percY); + + let degY = (py + 0.5) * 180; + + if (minRotY.get() !== 0 && degY < minRotY.get()) + { + degY = minRotY.get(); + py = lastPy; + } + else if (maxRotY.get() !== 0 && degY > maxRotY.get()) + { + degY = maxRotY.get(); + py = lastPy; + } + else + { + lastPy = py; + } + + const degX = (px) * CGL.RAD2DEG; + + outYDeg.set(degY); + outXDeg.set(degX); + + circlePosi(eye, py); + + vec3.add(tempEye, eye, vOffset); + vec3.add(tempCenter, vCenter, vOffset); + + finalEye[0] = ip(finalEye[0], tempEye[0]); + finalEye[1] = ip(finalEye[1], tempEye[1]); + finalEye[2] = ip(finalEye[2], tempEye[2]); + + finalCenter[0] = ip(finalCenter[0], tempCenter[0]); + finalCenter[1] = ip(finalCenter[1], tempCenter[1]); + finalCenter[2] = ip(finalCenter[2], tempCenter[2]); + + const empty = vec3.create(); + + mat4.lookAt(viewMatrix, finalEye, finalCenter, vUp); + mat4.rotate(viewMatrix, viewMatrix, px, vUp); + + // finaly multiply current scene viewmatrix + mat4.multiply(cgl.vMatrix, cgl.vMatrix, viewMatrix); + + trigger.trigger(); + cgl.popViewMatrix(); + initializing = false; +}; + +function circlePosi(vec, perc) +{ + const mmul = mul.get(); + if (radius < minDist.get() * mmul) radius = minDist.get() * mmul; + if (radius > maxDist.get() * mmul) radius = maxDist.get() * mmul; + + outRadius.set(radius * mmul); + + let i = 0, degInRad = 0; + + degInRad = 360 * perc / 2 * CGL.DEG2RAD; + vec3.set(vec, + Math.cos(degInRad) * radius * mmul, + Math.sin(degInRad) * radius * mmul, + 0); + return vec; +} + +function circlePos(perc) +{ + const mmul = mul.get(); + if (radius < minDist.get() * mmul)radius = minDist.get() * mmul; + if (radius > maxDist.get() * mmul)radius = maxDist.get() * mmul; + + outRadius.set(radius * mmul); + + let i = 0, degInRad = 0; + const vec = vec3.create(); + degInRad = 360 * perc / 2 * CGL.DEG2RAD; + vec3.set(vec, + Math.cos(degInRad) * radius * mmul, + Math.sin(degInRad) * radius * mmul, + 0); + return vec; +} + +function onmousemove(event) +{ + if (!mouseDown) return; + + const x = event.clientX; + const y = event.clientY; + + let movementX = (x - lastMouseX); + let movementY = (y - lastMouseY); + + movementX *= speedX.get(); + movementY *= speedY.get(); + + if (event.buttons == 2 && allowPanning.get()) + { + vOffset[2] += movementX * 0.01 * mul.get(); + vOffset[1] += movementY * 0.01 * mul.get(); + } + else + if (event.buttons == 4 && allowZooming.get()) + { + radius += movementY * 0.05; + eye = circlePos(percY); + } + else + { + if (allowRotation.get()) + { + percX += movementX * 0.003; + percY += movementY * 0.002; + + if (restricted.get()) + { + if (percY > 0.5)percY = 0.5; + if (percY < -0.5)percY = -0.5; + } + } + } + + lastMouseX = x; + lastMouseY = y; +} + +function onMouseDown(event) +{ + lastMouseX = event.clientX; + lastMouseY = event.clientY; + mouseDown = true; + + try { element.setPointerCapture(event.pointerId); } + catch (e) {} +} + +function onMouseUp(e) +{ + mouseDown = false; + // cgl.canvas.style.cursor='url(/ui/img/rotate.png),pointer'; + + try { element.releasePointerCapture(e.pointerId); } + catch (e) {} +} + +function lockChange() +{ + const el = op.patch.cg.canvas; + + if (document.pointerLockElement === el || document.mozPointerLockElement === el || document.webkitPointerLockElement === el) + { + document.addEventListener("mousemove", onmousemove, false); + } +} + +function onMouseEnter(e) +{ + // cgl.canvas.style.cursor='url(/ui/img/rotate.png),pointer'; +} + +initialRadius.onChange = function () +{ + radius = initialRadius.get(); + reset(); +}; + +initialX.onChange = function () +{ + px = percX = (initialX.get() * Math.PI * 2); +}; + +initialAxis.onChange = function () +{ + py = percY = (initialAxis.get() - 0.5); + eye = circlePos(percY); +}; + +const onMouseWheel = function (event) +{ + if (allowZooming.get()) + { + const delta = CGL.getWheelSpeed(event) * 0.06; + radius += (parseFloat(delta)) * 1.2; + + eye = circlePos(percY); + } +}; + +const ontouchstart = function (event) +{ + if (event.touches && event.touches.length > 0) onMouseDown(event.touches[0]); +}; + +const ontouchend = function (event) +{ + onMouseUp(); +}; + +const ontouchmove = function (event) +{ + if (event.touches && event.touches.length > 0) onmousemove(event.touches[0]); +}; + +active.onChange = function () +{ + if (active.get())bind(); + else unbind(); +}; + +function setElement(ele) +{ + unbind(); + element = ele; + bind(); +} + +function bind() +{ + if (!element) return; + + element.addEventListener("pointermove", onmousemove); + element.addEventListener("pointerdown", onMouseDown); + element.addEventListener("pointerup", onMouseUp); + element.addEventListener("pointerleave", onMouseUp); + element.addEventListener("pointerenter", onMouseEnter); + element.addEventListener("contextmenu", function (e) { e.preventDefault(); }); + element.addEventListener("wheel", onMouseWheel, { "passive": true }); +} + +function unbind() +{ + if (!element) return; + + element.removeEventListener("pointermove", onmousemove); + element.removeEventListener("pointerdown", onMouseDown); + element.removeEventListener("pointerup", onMouseUp); + element.removeEventListener("pointerleave", onMouseUp); + element.removeEventListener("pointerenter", onMouseUp); + element.removeEventListener("wheel", onMouseWheel); +} + +eye = circlePos(0); + +initialX.set(0.25); +initialRadius.set(0.05); + + +}; + +Ops.Gl.Matrix.OrbitControls.prototype = new CABLES.Op(); +CABLES.OPS["eaf4f7ce-08a3-4d1b-b9f4-ebc0b7b1cde1"]={f:Ops.Gl.Matrix.OrbitControls,objName:"Ops.Gl.Matrix.OrbitControls"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Vibrance +// +// ************************************************************** + +Ops.Gl.TextureEffects.Vibrance = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"vibrance_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\n\nconst vec4 lumcoeff = vec4(0.299,0.587,0.114, 0.);\n\nvoid main()\n{\n vec4 col=vec4(1.0,0.0,0.0,1.0);\n col=texture(tex,texCoord);\n\n float luma = dot(col, lumcoeff);\n vec4 mask = (col - vec4(luma));\n mask = clamp(mask, 0.0, 1.0);\n float lumaMask = dot(lumcoeff, mask);\n lumaMask = 1.0 - lumaMask;\n vec4 vibrance = mix(vec4(luma), col, 1.0 + amount * lumaMask);\n outColor= vibrance;\n}",}; +const render = op.inTrigger("Render"); +const trigger = op.outTrigger("Trigger"); +const amount = op.inValue("amount", 2); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.vibrance_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Vibrance.prototype = new CABLES.Op(); +CABLES.OPS["9c71c980-e439-4397-9c2b-c2ae085eaed9"]={f:Ops.Gl.TextureEffects.Vibrance,objName:"Ops.Gl.TextureEffects.Vibrance"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.FullscreenRectangle +// +// ************************************************************** + +Ops.Gl.Meshes.FullscreenRectangle = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"shader_frag":"UNI sampler2D tex;\nIN vec2 texCoord;\n\nvoid main()\n{\n outColor= texture(tex,texCoord);\n}\n\n","shader_vert":"{{MODULES_HEAD}}\n\nIN vec3 vPosition;\nUNI mat4 projMatrix;\nUNI mat4 mvMatrix;\n\nOUT vec2 texCoord;\nIN vec2 attrTexCoord;\n\nvoid main()\n{\n vec4 pos=vec4(vPosition, 1.0);\n\n texCoord=vec2(attrTexCoord.x,(1.0-attrTexCoord.y));\n\n gl_Position = projMatrix * mvMatrix * pos;\n}\n",}; +const + render = op.inTrigger("render"), + inScale = op.inSwitch("Scale", ["Stretch", "Fit"], "Fit"), + flipY = op.inValueBool("Flip Y"), + flipX = op.inValueBool("Flip X"), + inTexture = op.inTexture("Texture"), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +let mesh = null; +let geom = new CGL.Geometry("fullscreen rectangle"); +let x = 0, y = 0, z = 0, w = 0, h = 0; + +flipX.onChange = rebuildFlip; +flipY.onChange = rebuildFlip; +render.onTriggered = doRender; +inTexture.onLinkChanged = updateUi; +op.toWorkPortsNeedToBeLinked(render); + +const shader = new CGL.Shader(cgl, "fullscreenrectangle"); +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); + +shader.setSource(attachments.shader_vert, attachments.shader_frag); +shader.fullscreenRectUniform = new CGL.Uniform(shader, "t", "tex", 0); +shader.aspectUni = new CGL.Uniform(shader, "f", "aspectTex", 0); + +let useShader = false; +let updateShaderLater = true; +let fitImageAspect = false; +let oldVp = []; + +updateUi(); + +inTexture.onChange = function () +{ + updateShaderLater = true; +}; + +function updateUi() +{ + if (!CABLES.UI) return; + flipY.setUiAttribs({ "greyout": !inTexture.isLinked() }); + flipX.setUiAttribs({ "greyout": !inTexture.isLinked() }); + inScale.setUiAttribs({ "greyout": !inTexture.isLinked() }); +} + +function updateShader() +{ + let tex = inTexture.get(); + if (tex) useShader = true; + else useShader = false; +} + +op.preRender = function () +{ + updateShader(); + shader.bind(); + if (mesh)mesh.render(shader); + doRender(); +}; + +inScale.onChange = () => +{ + fitImageAspect = inScale.get() == "Fit"; +}; + +function doRender() +{ + if (cgl.getViewPort()[2] != w || cgl.getViewPort()[3] != h || !mesh) rebuild(); + + if (updateShaderLater) updateShader(); + + cgl.pushPMatrix(); + mat4.identity(cgl.pMatrix); + mat4.ortho(cgl.pMatrix, 0, w, h, 0, -10.0, 1000); + + cgl.pushModelMatrix(); + mat4.identity(cgl.mMatrix); + + cgl.pushViewMatrix(); + mat4.identity(cgl.vMatrix); + + if (fitImageAspect && inTexture.get()) + { + const rat = inTexture.get().width / inTexture.get().height; + + let _h = h; + let _w = h * rat; + + if (_w > w) + { + _h = w * 1 / rat; + _w = w; + } + + oldVp[0] = cgl.getViewPort()[0]; + oldVp[1] = cgl.getViewPort()[1]; + oldVp[2] = cgl.getViewPort()[2]; + oldVp[3] = cgl.getViewPort()[3]; + + cgl.setViewPort((w - _w) / 2, (h - _h) / 2, _w, _h); + // cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); + } + + if (useShader) + { + if (inTexture.get()) + cgl.setTexture(0, inTexture.get().tex); + + mesh.render(shader); + } + else + { + mesh.render(cgl.getShader()); + } + + cgl.gl.clear(cgl.gl.DEPTH_BUFFER_BIT); + + cgl.popPMatrix(); + cgl.popModelMatrix(); + cgl.popViewMatrix(); + + if (fitImageAspect && inTexture.get()) + cgl.setViewPort(oldVp[0], oldVp[1], oldVp[2], oldVp[3]); + + trigger.trigger(); +} + +function rebuildFlip() +{ + mesh = null; +} + +function rebuild() +{ + const currentViewPort = cgl.getViewPort(); + + if (currentViewPort[2] == w && currentViewPort[3] == h && mesh) return; + + let xx = 0, xy = 0; + + w = currentViewPort[2]; + h = currentViewPort[3]; + + geom.vertices = new Float32Array([ + xx + w, xy + h, 0.0, + xx, xy + h, 0.0, + xx + w, xy, 0.0, + xx, xy, 0.0 + ]); + + let tc = null; + + if (flipY.get()) + tc = new Float32Array([ + 1.0, 0.0, + 0.0, 0.0, + 1.0, 1.0, + 0.0, 1.0 + ]); + else + tc = new Float32Array([ + 1.0, 1.0, + 0.0, 1.0, + 1.0, 0.0, + 0.0, 0.0 + ]); + + if (flipX.get()) + { + tc[0] = 0.0; + tc[2] = 1.0; + tc[4] = 0.0; + tc[6] = 1.0; + } + + geom.setTexCoords(tc); + + geom.verticesIndices = new Uint16Array([ + 2, 1, 0, + 3, 1, 2 + ]); + + geom.vertexNormals = new Float32Array([ + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + ]); + geom.tangents = new Float32Array([ + -1, 0, 0, + -1, 0, 0, + -1, 0, 0, + -1, 0, 0]); + geom.biTangents == new Float32Array([ + 0, -1, 0, + 0, -1, 0, + 0, -1, 0, + 0, -1, 0]); + + if (!mesh) mesh = new CGL.Mesh(cgl, geom); + else mesh.setGeom(geom); +} + + +}; + +Ops.Gl.Meshes.FullscreenRectangle.prototype = new CABLES.Op(); +CABLES.OPS["255bd15b-cc91-4a12-9b4e-53c710cbb282"]={f:Ops.Gl.Meshes.FullscreenRectangle,objName:"Ops.Gl.Meshes.FullscreenRectangle"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.TranslateView +// +// ************************************************************** + +Ops.Gl.Matrix.TranslateView = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render=op.inTrigger('render'), + x=op.inValueFloat("x"), + y=op.inValueFloat("y"), + z=op.inValueFloat("z"), + trigger=op.outTrigger('trigger'); + +const cgl=op.patch.cgl; +const vec=vec3.create(); + +render.onTriggered=function() +{ + vec3.set(vec, x.get(),y.get(),z.get()); + cgl.pushViewMatrix(); + mat4.translate(cgl.vMatrix,cgl.vMatrix, vec); + trigger.trigger(); + cgl.popViewMatrix(); +}; + + +}; + +Ops.Gl.Matrix.TranslateView.prototype = new CABLES.Op(); +CABLES.OPS["b15472e2-b895-4dde-95c3-239fa5e08afc"]={f:Ops.Gl.Matrix.TranslateView,objName:"Ops.Gl.Matrix.TranslateView"}; + + + + +// ************************************************************** +// +// Ops.Gl.Texture_v2 +// +// ************************************************************** + +Ops.Gl.Texture_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + filename = op.inUrl("File", [".jpg", ".png", ".webp", ".jpeg", ".avif"]), + tfilter = op.inSwitch("Filter", ["nearest", "linear", "mipmap"]), + wrap = op.inValueSelect("Wrap", ["repeat", "mirrored repeat", "clamp to edge"], "clamp to edge"), + aniso = op.inSwitch("Anisotropic", [0, 1, 2, 4, 8, 16], 0), + flip = op.inValueBool("Flip", false), + unpackAlpha = op.inValueBool("Pre Multiplied Alpha", false), + active = op.inValueBool("Active", true), + inFreeMemory = op.inBool("Save Memory", true), + textureOut = op.outTexture("Texture"), + width = op.outNumber("Width"), + height = op.outNumber("Height"), + ratio = op.outNumber("Aspect Ratio"), + loaded = op.outNumber("Loaded", false), + loading = op.outNumber("Loading", false); + +op.setPortGroup("Size", [width, height]); + +unpackAlpha.setUiAttribs({ "hidePort": true }); + +op.toWorkPortsNeedToBeLinked(textureOut); + +const cgl = op.patch.cgl; + +let loadedFilename = null; +let loadingId = null; +let tex = null; +let cgl_filter = CGL.Texture.FILTER_MIPMAP; +let cgl_wrap = CGL.Texture.WRAP_REPEAT; +let cgl_aniso = 0; +let timedLoader = 0; + +filename.onChange = flip.onChange = function () { reloadSoon(); }; +aniso.onChange = tfilter.onChange = onFilterChange; +wrap.onChange = onWrapChange; +unpackAlpha.onChange = function () { reloadSoon(); }; + +tfilter.set("mipmap"); +wrap.set("repeat"); + +textureOut.set(CGL.Texture.getEmptyTexture(cgl)); + +active.onChange = function () +{ + if (active.get()) + { + if (loadedFilename != filename.get() || !tex) reloadSoon(); + else textureOut.set(tex); + } + else + { + textureOut.set(CGL.Texture.getEmptyTexture(cgl)); + width.set(CGL.Texture.getEmptyTexture(cgl).width); + height.set(CGL.Texture.getEmptyTexture(cgl).height); + if (tex)tex.delete(); + tex = null; + } +}; + +const setTempTexture = function () +{ + const t = CGL.Texture.getTempTexture(cgl); + textureOut.set(t); +}; + +function reloadSoon(nocache) +{ + clearTimeout(timedLoader); + timedLoader = setTimeout(function () + { + realReload(nocache); + }, 30); +} + +function realReload(nocache) +{ + if (!active.get()) return; + // if (filename.get() === null) return; + if (!loadingId)loadingId = cgl.patch.loading.start("textureOp", filename.get()); + + let url = op.patch.getFilePath(String(filename.get())); + + if (nocache)url += "?rnd=" + CABLES.uuid(); + + if (String(filename.get()).indexOf("data:") == 0) url = filename.get(); + + let needsRefresh = false; + if (loadedFilename != filename.get()) needsRefresh = true; + loadedFilename = filename.get(); + + if ((filename.get() && filename.get().length > 1)) + { + loaded.set(false); + loading.set(true); + + const fileToLoad = filename.get(); + + op.setUiAttrib({ "extendTitle": CABLES.basename(url) }); + if (needsRefresh) op.refreshParams(); + + cgl.patch.loading.addAssetLoadingTask(() => + { + op.setUiError("urlerror", null); + + CGL.Texture.load(cgl, url, + function (err, newTex) + { + if (filename.get() != fileToLoad) + { + cgl.patch.loading.finished(loadingId); + loadingId = null; + return; + } + + if (err) + { + setTempTexture(); + op.setUiError("urlerror", "could not load texture: \"" + filename.get() + "\"", 2); + cgl.patch.loading.finished(loadingId); + return; + } + + textureOut.set(newTex); + + width.set(newTex.width); + height.set(newTex.height); + ratio.set(newTex.width / newTex.height); + + // if (!newTex.isPowerOfTwo()) op.setUiError("npot", "Texture dimensions not power of two! - Texture filtering will not work in WebGL 1.", 0); + // else op.setUiError("npot", null); + + if (tex)tex.delete(); + tex = newTex; + textureOut.set(null); + textureOut.set(tex); + + loading.set(false); + loaded.set(true); + + if (inFreeMemory.get()) tex.image = null; + + cgl.patch.loading.finished(loadingId); + }, { + "anisotropic": cgl_aniso, + "wrap": cgl_wrap, + "flip": flip.get(), + "unpackAlpha": unpackAlpha.get(), + "filter": cgl_filter + }); + + // textureOut.set(null); + // textureOut.set(tex); + }); + } + else + { + cgl.patch.loading.finished(loadingId); + setTempTexture(); + } +} + +function onFilterChange() +{ + if (tfilter.get() == "nearest") cgl_filter = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "linear") cgl_filter = CGL.Texture.FILTER_LINEAR; + else if (tfilter.get() == "mipmap") cgl_filter = CGL.Texture.FILTER_MIPMAP; + else if (tfilter.get() == "Anisotropic") cgl_filter = CGL.Texture.FILTER_ANISOTROPIC; + + cgl_aniso = parseFloat(aniso.get()); + + reloadSoon(); +} + +function onWrapChange() +{ + if (wrap.get() == "repeat") cgl_wrap = CGL.Texture.WRAP_REPEAT; + if (wrap.get() == "mirrored repeat") cgl_wrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + if (wrap.get() == "clamp to edge") cgl_wrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + reloadSoon(); +} + +op.onFileChanged = function (fn) +{ + if (filename.get() && filename.get().indexOf(fn) > -1) + { + textureOut.set(CGL.Texture.getEmptyTexture(op.patch.cgl)); + textureOut.set(CGL.Texture.getTempTexture(cgl)); + realReload(true); + } +}; + + +}; + +Ops.Gl.Texture_v2.prototype = new CABLES.Op(); +CABLES.OPS["790f3702-9833-464e-8e37-6f0f813f7e16"]={f:Ops.Gl.Texture_v2,objName:"Ops.Gl.Texture_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Rectangle_v2 +// +// ************************************************************** + +Ops.Gl.Meshes.Rectangle_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + width = op.inValue("width", 1), + height = op.inValue("height", 1), + pivotX = op.inSwitch("pivot x", ["left", "center", "right"]), + pivotY = op.inSwitch("pivot y", ["top", "center", "bottom"]), + nColumns = op.inValueInt("num columns", 1), + nRows = op.inValueInt("num rows", 1), + axis = op.inSwitch("axis", ["xy", "xz"], "xy"), + active = op.inValueBool("Active", true), + geomOut = op.outObject("geometry", null, "geometry"); + +geomOut.ignoreValueSerialize = true; + +const cgl = op.patch.cgl; +axis.set("xy"); +pivotX.set("center"); +pivotY.set("center"); + +op.setPortGroup("Pivot", [pivotX, pivotY]); +op.setPortGroup("Size", [width, height]); +op.setPortGroup("Structure", [nColumns, nRows]); +op.toWorkPortsNeedToBeLinked(render); + +const geom = new CGL.Geometry("rectangle"); +let mesh = null; +let needsRebuild = false; + +axis.onChange = + pivotX.onChange = + pivotY.onChange = + width.onChange = + height.onChange = + nRows.onChange = + nColumns.onChange = rebuildLater; +rebuild(); + +function rebuildLater() +{ + needsRebuild = true; +} + +op.preRender = +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpNotInTextureEffect(op)) return; + if (needsRebuild)rebuild(); + if (active.get() && mesh) mesh.render(cgl.getShader()); + trigger.trigger(); +}; + +function rebuild() +{ + let w = width.get(); + let h = parseFloat(height.get()); + let x = 0; + let y = 0; + + if (typeof w == "string")w = parseFloat(w); + if (typeof h == "string")h = parseFloat(h); + + if (pivotX.get() == "center") x = 0; + else if (pivotX.get() == "right") x = -w / 2; + else if (pivotX.get() == "left") x = +w / 2; + + if (pivotY.get() == "center") y = 0; + else if (pivotY.get() == "top") y = -h / 2; + else if (pivotY.get() == "bottom") y = +h / 2; + + const verts = []; + const tc = []; + const norms = []; + const tangents = []; + const biTangents = []; + const indices = []; + + const numRows = Math.round(nRows.get()); + const numColumns = Math.round(nColumns.get()); + + const stepColumn = w / numColumns; + const stepRow = h / numRows; + + let c, r, a; + a = axis.get(); + for (r = 0; r <= numRows; r++) + { + for (c = 0; c <= numColumns; c++) + { + verts.push(c * stepColumn - width.get() / 2 + x); + if (a == "xz") verts.push(0.0); + verts.push(r * stepRow - height.get() / 2 + y); + if (a == "xy") verts.push(0.0); + + tc.push(c / numColumns); + tc.push(1.0 - r / numRows); + + if (a == "xz") + { + norms.push(0, 1, 0); + tangents.push(1, 0, 0); + biTangents.push(0, 0, 1); + } + else if (a == "xy") + { + norms.push(0, 0, 1); + tangents.push(-1, 0, 0); + biTangents.push(0, -1, 0); + } + } + } + + for (c = 0; c < numColumns; c++) + { + for (r = 0; r < numRows; r++) + { + const ind = c + (numColumns + 1) * r; + const v1 = ind; + const v2 = ind + 1; + const v3 = ind + numColumns + 1; + const v4 = ind + 1 + numColumns + 1; + + indices.push(v1); + indices.push(v3); + indices.push(v2); + + indices.push(v2); + indices.push(v3); + indices.push(v4); + } + } + + geom.clear(); + geom.vertices = verts; + geom.texCoords = tc; + geom.verticesIndices = indices; + geom.vertexNormals = norms; + geom.tangents = tangents; + geom.biTangents = biTangents; + + if (numColumns * numRows > 64000)geom.unIndex(); + + if (!mesh) mesh = new CGL.Mesh(cgl, geom); + else mesh.setGeom(geom); + + geomOut.set(null); + geomOut.set(geom); + needsRebuild = false; +} + +op.onDelete = function () +{ + if (mesh)mesh.dispose(); +}; + + +}; + +Ops.Gl.Meshes.Rectangle_v2.prototype = new CABLES.Op(); +CABLES.OPS["fc5718d6-11a5-496e-8f16-1c78b1a2824c"]={f:Ops.Gl.Meshes.Rectangle_v2,objName:"Ops.Gl.Meshes.Rectangle_v2"}; + + + + +// ************************************************************** +// +// Ops.Anim.Timer_v2 +// +// ************************************************************** + +Ops.Anim.Timer_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inSpeed = op.inValue("Speed", 1), + playPause = op.inValueBool("Play", true), + reset = op.inTriggerButton("Reset"), + inSyncTimeline = op.inValueBool("Sync to timeline", false), + outTime = op.outNumber("Time"); + +op.setPortGroup("Controls", [playPause, reset, inSpeed]); + +const timer = new CABLES.Timer(); +let lastTime = null; +let time = 0; +let syncTimeline = false; + +playPause.onChange = setState; +setState(); + +function setState() +{ + if (playPause.get()) + { + timer.play(); + op.patch.addOnAnimFrame(op); + } + else + { + timer.pause(); + op.patch.removeOnAnimFrame(op); + } +} + +reset.onTriggered = doReset; + +function doReset() +{ + time = 0; + lastTime = null; + timer.setTime(0); + outTime.set(0); +} + +inSyncTimeline.onChange = function () +{ + syncTimeline = inSyncTimeline.get(); + playPause.setUiAttribs({ "greyout": syncTimeline }); + reset.setUiAttribs({ "greyout": syncTimeline }); +}; + +op.onAnimFrame = function (tt) +{ + if (timer.isPlaying()) + { + if (CABLES.overwriteTime !== undefined) + { + outTime.set(CABLES.overwriteTime * inSpeed.get()); + } + else + + if (syncTimeline) + { + outTime.set(tt * inSpeed.get()); + } + else + { + timer.update(); + const timerVal = timer.get(); + + if (lastTime === null) + { + lastTime = timerVal; + return; + } + + const t = Math.abs(timerVal - lastTime); + lastTime = timerVal; + + time += t * inSpeed.get(); + if (time != time)time = 0; + outTime.set(time); + } + } +}; + + +}; + +Ops.Anim.Timer_v2.prototype = new CABLES.Op(); +CABLES.OPS["aac7f721-208f-411a-adb3-79adae2e471a"]={f:Ops.Anim.Timer_v2,objName:"Ops.Anim.Timer_v2"}; + + + + +// ************************************************************** +// +// Ops.Math.MapRange +// +// ************************************************************** + +Ops.Math.MapRange = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + v = op.inValueFloat("value", 0), + old_min = op.inValueFloat("old min", 0), + old_max = op.inValueFloat("old max", 1), + new_min = op.inValueFloat("new min", -1), + new_max = op.inValueFloat("new max", 1), + easing = op.inValueSelect("Easing", ["Linear", "Smoothstep", "Smootherstep"], "Linear"), + result = op.outNumber("result", 0); + +op.setPortGroup("Input Range", [old_min, old_max]); +op.setPortGroup("Output Range", [new_min, new_max]); + +let ease = 0; +let r = 0; + +v.onChange = + old_min.onChange = + old_max.onChange = + new_min.onChange = + new_max.onChange = exec; + +exec(); + +easing.onChange = function () +{ + if (easing.get() == "Smoothstep") ease = 1; + else if (easing.get() == "Smootherstep") ease = 2; + else ease = 0; +}; + +function exec() +{ + const nMin = new_min.get(); + const nMax = new_max.get(); + const oMin = old_min.get(); + const oMax = old_max.get(); + let x = v.get(); + + if (x >= Math.max(oMax, oMin)) + { + result.set(nMax); + return; + } + else + if (x <= Math.min(oMax, oMin)) + { + result.set(nMin); + return; + } + + let reverseInput = false; + const oldMin = Math.min(oMin, oMax); + const oldMax = Math.max(oMin, oMax); + if (oldMin != oMin) reverseInput = true; + + let reverseOutput = false; + const newMin = Math.min(nMin, nMax); + const newMax = Math.max(nMin, nMax); + if (newMin != nMin) reverseOutput = true; + + let portion = 0; + + if (reverseInput) portion = (oldMax - x) * (newMax - newMin) / (oldMax - oldMin); + else portion = (x - oldMin) * (newMax - newMin) / (oldMax - oldMin); + + if (reverseOutput) r = newMax - portion; + else r = portion + newMin; + + if (ease === 0) + { + result.set(r); + } + else + if (ease == 1) + { + x = Math.max(0, Math.min(1, (r - nMin) / (nMax - nMin))); + result.set(nMin + x * x * (3 - 2 * x) * (nMax - nMin)); // smoothstep + } + else + if (ease == 2) + { + x = Math.max(0, Math.min(1, (r - nMin) / (nMax - nMin))); + result.set(nMin + x * x * x * (x * (x * 6 - 15) + 10) * (nMax - nMin)); // smootherstep + } +} + + +}; + +Ops.Math.MapRange.prototype = new CABLES.Op(); +CABLES.OPS["2617b407-60a0-4ff6-b4a7-18136cfa7817"]={f:Ops.Math.MapRange,objName:"Ops.Math.MapRange"}; + + + + +// ************************************************************** +// +// Ops.Math.Compare.IfBetweenThen +// +// ************************************************************** + +Ops.Math.Compare.IfBetweenThen = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + number = op.inValue("number", 0), + min = op.inValue("min", 0), + max = op.inValue("max", 1), + triggerThen = op.outTrigger("then"), + triggerElse = op.outTrigger("else"), + outBetween = op.outBoolNum("bs between"); + +exe.onTriggered = function () +{ + if (number.get() >= min.get() && number.get() < max.get()) + { + outBetween.set(true); + triggerThen.trigger(); + } + else + { + outBetween.set(false); + triggerElse.trigger(); + } +}; + + +}; + +Ops.Math.Compare.IfBetweenThen.prototype = new CABLES.Op(); +CABLES.OPS["c80437f0-f0e1-465c-9cea-8a044aa2feaa"]={f:Ops.Math.Compare.IfBetweenThen,objName:"Ops.Math.Compare.IfBetweenThen"}; + + + + +// ************************************************************** +// +// Ops.Gl.ViewPortSize +// +// ************************************************************** + +Ops.Gl.ViewPortSize = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Exec"), + next = op.outTrigger("Next"), + outX = op.outNumber("X"), + outY = op.outNumber("Y"), + outW = op.outNumber("Width"), + outH = op.outNumber("Height"); + +exec.onTriggered = function () +{ + const vp = op.patch.cgl.getViewPort(); + + outX.set(vp[0]); + outY.set(vp[1]); + outW.set(vp[2]); + outH.set(vp[3]); + + next.trigger(); +}; + + +}; + +Ops.Gl.ViewPortSize.prototype = new CABLES.Op(); +CABLES.OPS["7cb99d8f-d7ef-478e-902b-54e054e387a0"]={f:Ops.Gl.ViewPortSize,objName:"Ops.Gl.ViewPortSize"}; + + + + +// ************************************************************** +// +// Ops.Trigger.SetNumberOnTrigger +// +// ************************************************************** + +Ops.Trigger.SetNumberOnTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + setValuePort = op.inTriggerButton("Set"), + valuePort = op.inValueFloat("Number"), + outNext = op.outTrigger("Next"), + outValuePort = op.outNumber("Out Value"); + +outValuePort.changeAlways = true; + +setValuePort.onTriggered = function () +{ + outValuePort.set(valuePort.get()); + outNext.trigger(); +}; + + +}; + +Ops.Trigger.SetNumberOnTrigger.prototype = new CABLES.Op(); +CABLES.OPS["9989b1c0-1073-4d5f-bfa0-36dd98b66e27"]={f:Ops.Trigger.SetNumberOnTrigger,objName:"Ops.Trigger.SetNumberOnTrigger"}; + + + + +// ************************************************************** +// +// Ops.Color.HexToRGB_v2 +// +// ************************************************************** + +Ops.Color.HexToRGB_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + hex = op.inString("Hex", "#ff0000"), + asBytes = op.inValueBool("Bytes"), + outR = op.outNumber("R"), + outG = op.outNumber("G"), + outB = op.outNumber("B"); + +function hexToR(h) +{ + return parseInt((cutHex(h)).substring(0, 2), 16) || 0; +} +function hexToG(h) +{ + return parseInt((cutHex(h)).substring(2, 4), 16) || 0; +} +function hexToB(h) +{ + return parseInt((cutHex(h)).substring(4, 6), 16) || 0; +} +function cutHex(h) +{ + return (h.charAt(0) == "#") ? h.substring(1, 7) : h; +} + +hex.onChange = parse; +asBytes.onChange = parse; + +function parse() +{ + let str = hex.get() || ""; + let r = hexToR(str); + let g = hexToG(str); + let b = hexToB(str); + + if (!asBytes.get()) + { + r /= 255; + g /= 255; + b /= 255; + } + + outR.set(r); + outB.set(b); + outG.set(g); +} + + +}; + +Ops.Color.HexToRGB_v2.prototype = new CABLES.Op(); +CABLES.OPS["9877f198-8dac-48e5-9310-244ef1a8dec5"]={f:Ops.Color.HexToRGB_v2,objName:"Ops.Color.HexToRGB_v2"}; + + + + +// ************************************************************** +// +// Ops.String.String_v2 +// +// ************************************************************** + +Ops.String.String_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + v=op.inString("value",""), + result=op.outString("String"); + +v.onChange=function() +{ + result.set(v.get()); +}; + + + +}; + +Ops.String.String_v2.prototype = new CABLES.Op(); +CABLES.OPS["d697ff82-74fd-4f31-8f54-295bc64e713d"]={f:Ops.String.String_v2,objName:"Ops.String.String_v2"}; + + + + +// ************************************************************** +// +// Ops.Value.Number +// +// ************************************************************** + +Ops.Value.Number = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + v = op.inValueFloat("value"), + result = op.outNumber("result"); + +v.onChange = exec; + +function exec() +{ + result.set(Number(v.get())); +} + + +}; + +Ops.Value.Number.prototype = new CABLES.Op(); +CABLES.OPS["8fb2bb5d-665a-4d0a-8079-12710ae453be"]={f:Ops.Value.Number,objName:"Ops.Value.Number"}; + + + + +// ************************************************************** +// +// Ops.Ui.PatchInput +// +// ************************************************************** + +Ops.Ui.PatchInput = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const dyn = op.addOutPort(new CABLES.Port(op, "create port", CABLES.OP_PORT_TYPE_DYNAMIC)); + +function getPatchOp() +{ + for (let i in op.patch.ops) + { + if (op.patch.ops[i].patchId) + { + if (op.patch.ops[i].patchId.get() == op.uiAttribs.subPatch) + { + return op.patch.ops[i]; + } + } + } +} + +dyn.onLinkChanged = () => +{ + const mySubPatchOp = getPatchOp(); + + if (!dyn.links.length) return; + + const otherPort = dyn.links[0].getOtherPort(dyn); + dyn.removeLinks(); + + const newPortName = mySubPatchOp.addNewInPort(otherPort); + + const l = gui.scene().link( + otherPort.parent, + otherPort.getName(), + op, + newPortName); + + mySubPatchOp.saveData(); +}; + + +}; + +Ops.Ui.PatchInput.prototype = new CABLES.Op(); +CABLES.OPS["e3f68bc3-892a-4c78-9974-aca25c27025d"]={f:Ops.Ui.PatchInput,objName:"Ops.Ui.PatchInput"}; + + + + +// ************************************************************** +// +// Ops.Ui.PatchOutput +// +// ************************************************************** + +Ops.Ui.PatchOutput = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const dyn = op.addInPort(new CABLES.Port(op, "create port", CABLES.OP_PORT_TYPE_DYNAMIC)); + +function getPatchOp() +{ + for (let i in op.patch.ops) + { + if (op.patch.ops[i].patchId) + { + if (op.patch.ops[i].patchId.get() == op.uiAttribs.subPatch) + { + return op.patch.ops[i]; + } + } + } +} + +dyn.onLinkChanged = () => +{ + const mySubPatchOp = getPatchOp(); + + if (!dyn.links.length) return; + + const otherPort = dyn.links[0].getOtherPort(dyn); + dyn.removeLinks(); + + const newPortName = mySubPatchOp.addNewOutPort(otherPort); + + const l = gui.scene().link( + otherPort.parent, + otherPort.getName(), + op, + newPortName); + + mySubPatchOp.saveData(); +}; + + +}; + +Ops.Ui.PatchOutput.prototype = new CABLES.Op(); +CABLES.OPS["851b44cb-5667-4140-9800-5aeb7031f1d7"]={f:Ops.Ui.PatchOutput,objName:"Ops.Ui.PatchOutput"}; + + + + +// ************************************************************** +// +// Ops.Ui.SubPatch +// +// ************************************************************** + +Ops.Ui.SubPatch = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +op.dyn = op.addInPort(new CABLES.Port(op, "create port", CABLES.OP_PORT_TYPE_DYNAMIC)); +op.dynOut = op.addOutPort(new CABLES.Port(op, "create port out", CABLES.OP_PORT_TYPE_DYNAMIC)); + +const dataStr = op.addInPort(new CABLES.Port(op, "dataStr", CABLES.OP_PORT_TYPE_VALUE, { "display": "readonly" })); +op.patchId = op.addInPort(new CABLES.Port(op, "patchId", CABLES.OP_PORT_TYPE_VALUE, { "display": "readonly" })); + +if (CABLES.UI && CABLES.sandbox.isDevEnv()) +{ + const inMakeBp = op.inTriggerButton("Create Blueprint"); + inMakeBp.setUiAttribs({ "hidePort": true }); + + inMakeBp.onTriggered = makeBlueprint; +} + +dataStr.setUiAttribs({ "hideParam": true }); +op.patchId.setUiAttribs({ "hideParam": true }); + +let data = { "ports": [], "portsOut": [] }; +let oldPatchId = CABLES.generateUUID(); +op.patchId.set(oldPatchId); +getSubPatchInputOp(); +getSubPatchOutputOp(); + +let dataLoaded = false; + +op.saveData = saveData; + +op.patchId.onChange = function () +{ + const oldPatchOps = op.patch.getSubPatchOps(oldPatchId); + + if (oldPatchOps.length == 2) + { + for (let i = 0; i < oldPatchOps.length; i++) + { + op.patch.deleteOp(oldPatchOps[i].id); + } + } + else + { + } +}; + +op.onLoaded = function () +{ +}; + +op.onLoadedValueSet = function () +{ + data = JSON.parse(dataStr.get()); + if (!data) + { + data = { "ports": [], "portsOut": [] }; + } + setupPorts(); +}; + +function loadData() +{ +} + +dataStr.onChange = function () +{ + if (dataLoaded) return; + + if (!dataStr.get()) return; + try + { + loadData(); + } + catch (e) + { + op.logError("cannot load subpatch data..."); + op.logError(e); + } +}; + +function saveData() +{ + dataStr.set(JSON.stringify(data)); +} + +op.addPortListener = addPortListener; +function addPortListener(newPort, newPortInPatch) +{ + if (!newPort.hasSubpatchLstener) + { + newPort.hasSubpatchLstener = true; + newPort.addEventListener("onUiAttrChange", function (attribs) + { + if (attribs.title) + { + let i = 0; + for (i = 0; i < data.portsOut.length; i++) + if (data.portsOut[i].name == newPort.name) + data.portsOut[i].title = attribs.title; + + for (i = 0; i < data.ports.length; i++) + if (data.ports[i].name == newPort.name) + data.ports[i].title = attribs.title; + + saveData(); + } + }); + } + + if (newPort.direction == CABLES.PORT_DIR_IN) + { + if (newPort.type == CABLES.OP_PORT_TYPE_FUNCTION) + { + newPort.onTriggered = function () + { + if (newPortInPatch.isLinked()) + newPortInPatch.trigger(); + }; + } + else + { + newPort.onChange = function () + { + newPortInPatch.set(newPort.get()); + if (!newPort.isLinked()) + { + for (let i = 0; i < data.ports.length; i++) + { + if (data.ports[i].name === newPort.name) + { + data.ports[i].value = newPort.get(); + } + } + saveData(); + } + }; + } + } +} + +op.setupPorts = setupPorts; +function setupPorts() +{ + if (!op.patchId.get()) return; + const ports = data.ports || []; + const portsOut = data.portsOut || []; + let i = 0; + + for (i = 0; i < ports.length; i++) + { + if (!op.getPortByName(ports[i].name)) + { + const newPort = op.addInPort(new CABLES.Port(op, ports[i].name, ports[i].type)); + + const patchInputOp = getSubPatchInputOp(); + const newPortInPatch = patchInputOp.addOutPort(new CABLES.Port(patchInputOp, ports[i].name, ports[i].type)); + + newPort.ignoreValueSerialize = true; + newPort.setUiAttribs({ "editableTitle": true }); + if (ports[i].title) + { + newPort.setUiAttribs({ "title": ports[i].title }); + newPortInPatch.setUiAttribs({ "title": ports[i].title }); + } + if (ports[i].objType) + { + newPort.setUiAttribs({ "objType": ports[i].objType }); + newPortInPatch.setUiAttribs({ "objType": ports[i].objType }); + } + if (ports[i].value) + { + newPort.set(ports[i].value); + newPortInPatch.set(ports[i].value); + } + addPortListener(newPort, newPortInPatch); + } + } + + for (i = 0; i < portsOut.length; i++) + { + if (!op.getPortByName(portsOut[i].name)) + { + const newPortOut = op.addOutPort(new CABLES.Port(op, portsOut[i].name, portsOut[i].type)); + const patchOutputOp = getSubPatchOutputOp(); + const newPortOutPatch = patchOutputOp.addInPort(new CABLES.Port(patchOutputOp, portsOut[i].name, portsOut[i].type)); + + newPortOut.ignoreValueSerialize = true; + newPortOut.setUiAttribs({ "editableTitle": true }); + + if (portsOut[i].title) + { + newPortOut.setUiAttribs({ "title": portsOut[i].title }); + newPortOutPatch.setUiAttribs({ "title": portsOut[i].title }); + } + if (portsOut[i].objType) + { + newPortOut.setUiAttribs({ "objType": portsOut[i].objType }); + newPortOutPatch.setUiAttribs({ "objType": portsOut[i].objType }); + } + + // addPortListener(newPortOut,newPortOutPatch); + addPortListener(newPortOutPatch, newPortOut); + } + } + + dataLoaded = true; +} + +op.addNewInPort = function (otherPort, type, objType) +{ + const newName = "in" + data.ports.length + " " + otherPort.parent.name + " " + otherPort.name; + + const o = { "name": newName, "type": otherPort.type }; + if (otherPort.uiAttribs.objType)o.objType = otherPort.uiAttribs.objType; + + data.ports.push(o); + setupPorts(); + return newName; +}; + +op.dyn.onLinkChanged = function () +{ + if (op.dyn.isLinked()) + { + const otherPort = op.dyn.links[0].getOtherPort(op.dyn); + op.dyn.removeLinks(); + otherPort.removeLinkTo(op.dyn); + + op.log("dyn link changed!!!"); + + // const newName = "in" + data.ports.length + " " + otherPort.parent.name + " " + otherPort.name; + + // const o = { "name": newName, "type": otherPort.type }; + // if (otherPort.uiAttribs.objType)o.objType = otherPort.uiAttribs.objType; + // data.ports.push(o); + + // setupPorts(); + + const newName = op.addNewInPort(otherPort); + + const l = gui.scene().link( + otherPort.parent, + otherPort.getName(), + op, + newName + ); + + dataLoaded = true; + saveData(); + } + else + { + setTimeout(function () + { + op.dyn.removeLinks(); + }, 100); + } +}; + +op.addNewOutPort = function (otherPort, type, objType) +{ + const newName = "out" + data.portsOut.length + " " + otherPort.parent.name + " " + otherPort.name; + + const o = { "name": newName, "type": otherPort.type }; + if (otherPort.uiAttribs.objType)o.objType = otherPort.uiAttribs.objType; + + data.portsOut.push(o); + setupPorts(); + return newName; +}; + +op.dynOut.onLinkChanged = function () +{ + if (op.dynOut.isLinked()) + { + const otherPort = op.dynOut.links[0].getOtherPort(op.dynOut); + op.dynOut.removeLinks(); + otherPort.removeLinkTo(op.dynOut); + + const newName = op.addNewOutPort(otherPort); + + gui.scene().link( + otherPort.parent, + otherPort.getName(), + op, + newName + ); + + dataLoaded = true; + saveData(); + } + else + { + setTimeout(function () + { + op.dynOut.removeLinks(); + }, 100); + + op.log("dynOut unlinked..."); + } +}; + +function getSubPatchOutputOp() +{ + let patchOutputOP = op.patch.getSubPatchOp(op.patchId.get(), "Ops.Ui.PatchOutput"); + + if (!patchOutputOP) + { + op.patch.addOp("Ops.Ui.PatchOutput", { "subPatch": op.patchId.get(), "translate": { "x": 0, "y": 0 } }); + patchOutputOP = op.patch.getSubPatchOp(op.patchId.get(), "Ops.Ui.PatchOutput"); + if (!patchOutputOP) op.warn("no patchoutput!"); + } + return patchOutputOP; +} + +function getSubPatchInputOp() +{ + let patchInputOP = op.patch.getSubPatchOp(op.patchId.get(), "Ops.Ui.PatchInput"); + + if (!patchInputOP) + { + op.patch.addOp("Ops.Ui.PatchInput", { "subPatch": op.patchId.get(), "translate": { "x": 0, "y": 0 } }); + patchInputOP = op.patch.getSubPatchOp(op.patchId.get(), "Ops.Ui.PatchInput"); + if (!patchInputOP) op.warn("no patchinput2!"); + } + + return patchInputOP; +} + +op.addSubLink = function (p, p2) +{ + const num = data.ports.length; + const sublPortname = "in" + (num - 1) + " " + p2.parent.name + " " + p2.name; + + if (p.direction == CABLES.PORT_DIR_IN) + { + gui.scene().link( + p.parent, + p.getName(), + getSubPatchInputOp(), + sublPortname + ); + } + else + { + const numOut = data.portsOut.length; + gui.scene().link( + p.parent, + p.getName(), + getSubPatchOutputOp(), + "out" + (numOut - 1) + " " + p2.parent.name + " " + p2.name + ); + } + + const bounds = gui.patchView.getSubPatchBounds(op.patchId.get()); + + getSubPatchInputOp().uiAttr( + { + "translate": + { + "x": bounds.minx, + "y": bounds.miny - 100 + } + }); + + getSubPatchOutputOp().uiAttr( + { + "translate": + { + "x": bounds.minx, + "y": bounds.maxy + 100 + } + }); + saveData(); + return sublPortname; +}; + +op.onDelete = function () +{ + for (let i = op.patch.ops.length - 1; i >= 0; i--) + { + if (op.patch.ops[i] && op.patch.ops[i].uiAttribs && op.patch.ops[i].uiAttribs.subPatch == op.patchId.get()) + { + op.patch.deleteOp(op.patch.ops[i].id); + } + } +}; + +function makeBlueprint() +{ + const bpOp = op.patch.addOp(CABLES.UI.DEFAULTOPNAMES.blueprint); + + bpOp.getPortByName("externalPatchId").set(gui.patchId); + bpOp.getPortByName("subPatchId").set(op.patchId.get()); + bpOp.getPortByName("active").set(true); + + bpOp.uiAttr( + { + "translate": + { + "x": op.uiAttribs.translate.x - 150, + "y": op.uiAttribs.translate.y + } + }); +} + +op.rebuildListeners = () => +{ + op.log("rebuild listeners..."); + + const outop = getSubPatchOutputOp(); + for (let i = 0; i < outop.portsIn.length; i++) + { + if (outop.portsIn[i].isLinked()) + { + addPortListener(outop.portsIn[i], this.portsOut[i]); + } + } +}; + + +}; + +Ops.Ui.SubPatch.prototype = new CABLES.Op(); +CABLES.OPS["84d9a6f0-ed7a-466d-b386-225ed9e89c60"]={f:Ops.Ui.SubPatch,objName:"Ops.Ui.SubPatch"}; + + + + +// ************************************************************** +// +// Ops.Math.Sum +// +// ************************************************************** + +Ops.Math.Sum = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number1 = op.inValueFloat("number1", 1), + number2 = op.inValueFloat("number2", 1), + result = op.outNumber("result"); + +op.setTitle("+"); + +number1.onChange = +number2.onChange = exec; +exec(); + +function exec() +{ + const v = number1.get() + number2.get(); + if (!isNaN(v)) + result.set(v); +} + + +}; + +Ops.Math.Sum.prototype = new CABLES.Op(); +CABLES.OPS["c8fb181e-0b03-4b41-9e55-06b6267bc634"]={f:Ops.Math.Sum,objName:"Ops.Math.Sum"}; + + diff --git a/survey_dashboard/hmc_layout/static/en_files/projectops.js b/survey_dashboard/hmc_layout/static/en_files/projectops.js new file mode 100644 index 0000000..6b81b1b --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/projectops.js @@ -0,0 +1,4269 @@ +"use strict"; + +var CABLES=CABLES||{}; +CABLES.OPS=CABLES.OPS||{}; + +var Ops=Ops || {}; +Ops.Gl=Ops.Gl || {}; +Ops.Ui=Ops.Ui || {}; +Ops.Anim=Ops.Anim || {}; +Ops.Math=Ops.Math || {}; +Ops.Color=Ops.Color || {}; +Ops.Value=Ops.Value || {}; +Ops.String=Ops.String || {}; +Ops.Trigger=Ops.Trigger || {}; +Ops.Gl.Matrix=Ops.Gl.Matrix || {}; +Ops.Gl.Meshes=Ops.Gl.Meshes || {}; +Ops.Gl.Shader=Ops.Gl.Shader || {}; +Ops.Deprecated=Ops.Deprecated || {}; +Ops.Math.Compare=Ops.Math.Compare || {}; +Ops.Deprecated.Exp=Ops.Deprecated.Exp || {}; +Ops.Deprecated.Anim=Ops.Deprecated.Anim || {}; +Ops.Deprecated.Exp.Gl=Ops.Deprecated.Exp.Gl || {}; +Ops.Gl.TextureEffects=Ops.Gl.TextureEffects || {}; +Ops.Gl.TextureEffects.Noise=Ops.Gl.TextureEffects.Noise || {}; + + + +// ************************************************************** +// +// Ops.Gl.MainLoop +// +// ************************************************************** + +Ops.Gl.MainLoop = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + fpsLimit = op.inValue("FPS Limit", 0), + trigger = op.outTrigger("trigger"), + width = op.outNumber("width"), + height = op.outNumber("height"), + reduceFocusFPS = op.inValueBool("Reduce FPS not focussed", true), + reduceLoadingFPS = op.inValueBool("Reduce FPS loading"), + clear = op.inValueBool("Clear", true), + clearAlpha = op.inValueBool("ClearAlpha", true), + fullscreen = op.inValueBool("Fullscreen Button", false), + active = op.inValueBool("Active", true), + hdpi = op.inValueBool("Hires Displays", false), + inUnit = op.inSwitch("Pixel Unit", ["Display", "CSS"], "Display"); + +op.onAnimFrame = render; +hdpi.onChange = function () +{ + if (hdpi.get()) op.patch.cgl.pixelDensity = window.devicePixelRatio; + else op.patch.cgl.pixelDensity = 1; + + op.patch.cgl.updateSize(); + if (CABLES.UI) gui.setLayout(); + + // inUnit.setUiAttribs({ "greyout": !hdpi.get() }); + + // if (!hdpi.get())inUnit.set("CSS"); + // else inUnit.set("Display"); +}; + +active.onChange = function () +{ + op.patch.removeOnAnimFrame(op); + + if (active.get()) + { + op.setUiAttrib({ "extendTitle": "" }); + op.onAnimFrame = render; + op.patch.addOnAnimFrame(op); + op.log("adding again!"); + } + else + { + op.setUiAttrib({ "extendTitle": "Inactive" }); + } +}; + +const cgl = op.patch.cgl; +let rframes = 0; +let rframeStart = 0; + +if (!op.patch.cgl) op.uiAttr({ "error": "No webgl cgl context" }); + +const identTranslate = vec3.create(); +vec3.set(identTranslate, 0, 0, 0); +const identTranslateView = vec3.create(); +vec3.set(identTranslateView, 0, 0, -2); + +fullscreen.onChange = updateFullscreenButton; +setTimeout(updateFullscreenButton, 100); +let fsElement = null; + +let winhasFocus = true; +let winVisible = true; + +window.addEventListener("blur", () => { winhasFocus = false; }); +window.addEventListener("focus", () => { winhasFocus = true; }); +document.addEventListener("visibilitychange", () => { winVisible = !document.hidden; }); +testMultiMainloop(); + +inUnit.onChange = () => +{ + width.set(0); + height.set(0); +}; + +function getFpsLimit() +{ + if (reduceLoadingFPS.get() && op.patch.loading.getProgress() < 1.0) return 5; + + if (reduceFocusFPS.get()) + { + if (!winVisible) return 10; + if (!winhasFocus) return 30; + } + + return fpsLimit.get(); +} + +function updateFullscreenButton() +{ + function onMouseEnter() + { + if (fsElement)fsElement.style.display = "block"; + } + + function onMouseLeave() + { + if (fsElement)fsElement.style.display = "none"; + } + + op.patch.cgl.canvas.addEventListener("mouseleave", onMouseLeave); + op.patch.cgl.canvas.addEventListener("mouseenter", onMouseEnter); + + if (fullscreen.get()) + { + if (!fsElement) + { + fsElement = document.createElement("div"); + + const container = op.patch.cgl.canvas.parentElement; + if (container)container.appendChild(fsElement); + + fsElement.addEventListener("mouseenter", onMouseEnter); + fsElement.addEventListener("click", function (e) + { + if (CABLES.UI && !e.shiftKey) gui.cycleFullscreen(); + else cgl.fullScreen(); + }); + } + + fsElement.style.padding = "10px"; + fsElement.style.position = "absolute"; + fsElement.style.right = "5px"; + fsElement.style.top = "5px"; + fsElement.style.width = "20px"; + fsElement.style.height = "20px"; + fsElement.style.cursor = "pointer"; + fsElement.style["border-radius"] = "40px"; + fsElement.style.background = "#444"; + fsElement.style["z-index"] = "9999"; + fsElement.style.display = "none"; + fsElement.innerHTML = ""; + } + else + { + if (fsElement) + { + fsElement.style.display = "none"; + fsElement.remove(); + fsElement = null; + } + } +} + +op.onDelete = function () +{ + cgl.gl.clearColor(0, 0, 0, 0); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); +}; + +function render(time) +{ + if (!active.get()) return; + if (cgl.aborted || cgl.canvas.clientWidth === 0 || cgl.canvas.clientHeight === 0) return; + + op.patch.cg = cgl; + + const startTime = performance.now(); + + op.patch.config.fpsLimit = getFpsLimit(); + + if (cgl.canvasWidth == -1) + { + cgl.setCanvas(op.patch.config.glCanvasId); + return; + } + + if (cgl.canvasWidth != width.get() || cgl.canvasHeight != height.get()) + { + let div = 1; + if (inUnit.get() == "CSS")div = op.patch.cgl.pixelDensity; + + width.set(cgl.canvasWidth / div); + height.set(cgl.canvasHeight / div); + } + + if (CABLES.now() - rframeStart > 1000) + { + CGL.fpsReport = CGL.fpsReport || []; + if (op.patch.loading.getProgress() >= 1.0 && rframeStart !== 0)CGL.fpsReport.push(rframes); + rframes = 0; + rframeStart = CABLES.now(); + } + CGL.MESH.lastShader = null; + CGL.MESH.lastMesh = null; + + cgl.renderStart(cgl, identTranslate, identTranslateView); + + if (clear.get()) + { + cgl.gl.clearColor(0, 0, 0, 1); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); + } + + trigger.trigger(); + + if (CGL.MESH.lastMesh)CGL.MESH.lastMesh.unBind(); + + if (CGL.Texture.previewTexture) + { + if (!CGL.Texture.texturePreviewer) CGL.Texture.texturePreviewer = new CGL.Texture.texturePreview(cgl); + CGL.Texture.texturePreviewer.render(CGL.Texture.previewTexture); + } + cgl.renderEnd(cgl); + + op.patch.cg = null; + + if (clearAlpha.get()) + { + cgl.gl.clearColor(1, 1, 1, 1); + cgl.gl.colorMask(false, false, false, true); + cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT); + cgl.gl.colorMask(true, true, true, true); + } + + if (!cgl.frameStore.phong)cgl.frameStore.phong = {}; + rframes++; + + op.patch.cgl.profileData.profileMainloopMs = performance.now() - startTime; +} + +function testMultiMainloop() +{ + setTimeout( + () => + { + if (op.patch.getOpsByObjName(op.name).length > 1) + { + op.setUiError("multimainloop", "there should only be one mainloop op!"); + op.patch.addEventListener("onOpDelete", testMultiMainloop); + } + else op.setUiError("multimainloop", null, 1); + }, 500); +} + + +}; + +Ops.Gl.MainLoop.prototype = new CABLES.Op(); +CABLES.OPS["b0472a1d-db16-4ba6-8787-f300fbdc77bb"]={f:Ops.Gl.MainLoop,objName:"Ops.Gl.MainLoop"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.Transform +// +// ************************************************************** + +Ops.Gl.Matrix.Transform = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + posX = op.inValue("posX", 0), + posY = op.inValue("posY", 0), + posZ = op.inValue("posZ", 0), + scale = op.inValue("scale", 1), + rotX = op.inValue("rotX", 0), + rotY = op.inValue("rotY", 0), + rotZ = op.inValue("rotZ", 0), + trigger = op.outTrigger("trigger"); + +op.setPortGroup("Rotation", [rotX, rotY, rotZ]); +op.setPortGroup("Position", [posX, posY, posZ]); +op.setPortGroup("Scale", [scale]); +op.setUiAxisPorts(posX, posY, posZ); + +const vPos = vec3.create(); +const vScale = vec3.create(); +const transMatrix = mat4.create(); +mat4.identity(transMatrix); + +let + doScale = false, + doTranslate = false, + translationChanged = true, + scaleChanged = true, + rotChanged = true; + +rotX.onChange = rotY.onChange = rotZ.onChange = setRotChanged; +posX.onChange = posY.onChange = posZ.onChange = setTranslateChanged; +scale.onChange = setScaleChanged; + +render.onTriggered = function () +{ + // if(!CGL.TextureEffect.checkOpNotInTextureEffect(op)) return; + + let updateMatrix = false; + if (translationChanged) + { + updateTranslation(); + updateMatrix = true; + } + if (scaleChanged) + { + updateScale(); + updateMatrix = true; + } + if (rotChanged) updateMatrix = true; + + if (updateMatrix) doUpdateMatrix(); + + const cg = op.patch.cgl; + cg.pushModelMatrix(); + mat4.multiply(cg.mMatrix, cg.mMatrix, transMatrix); + + trigger.trigger(); + cg.popModelMatrix(); + + if (CABLES.UI && CABLES.UI.showCanvasTransforms) gui.setTransform(op.id, posX.get(), posY.get(), posZ.get()); + + if (op.isCurrentUiOp()) + gui.setTransformGizmo( + { + "posX": posX, + "posY": posY, + "posZ": posZ, + }); +}; + +op.transform3d = function () +{ + return { "pos": [posX, posY, posZ] }; +}; + +function doUpdateMatrix() +{ + mat4.identity(transMatrix); + if (doTranslate)mat4.translate(transMatrix, transMatrix, vPos); + + if (rotX.get() !== 0)mat4.rotateX(transMatrix, transMatrix, rotX.get() * CGL.DEG2RAD); + if (rotY.get() !== 0)mat4.rotateY(transMatrix, transMatrix, rotY.get() * CGL.DEG2RAD); + if (rotZ.get() !== 0)mat4.rotateZ(transMatrix, transMatrix, rotZ.get() * CGL.DEG2RAD); + + if (doScale)mat4.scale(transMatrix, transMatrix, vScale); + rotChanged = false; +} + +function updateTranslation() +{ + doTranslate = false; + if (posX.get() !== 0.0 || posY.get() !== 0.0 || posZ.get() !== 0.0) doTranslate = true; + vec3.set(vPos, posX.get(), posY.get(), posZ.get()); + translationChanged = false; +} + +function updateScale() +{ + // doScale=false; + // if(scale.get()!==0.0) + doScale = true; + vec3.set(vScale, scale.get(), scale.get(), scale.get()); + scaleChanged = false; +} + +function setTranslateChanged() +{ + translationChanged = true; +} + +function setScaleChanged() +{ + scaleChanged = true; +} + +function setRotChanged() +{ + rotChanged = true; +} + +doUpdateMatrix(); + + +}; + +Ops.Gl.Matrix.Transform.prototype = new CABLES.Op(); +CABLES.OPS["650baeb1-db2d-4781-9af6-ab4e9d4277be"]={f:Ops.Gl.Matrix.Transform,objName:"Ops.Gl.Matrix.Transform"}; + + + + +// ************************************************************** +// +// Ops.Math.Multiply +// +// ************************************************************** + +Ops.Math.Multiply = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number1 = op.inValueFloat("number1", 1), + number2 = op.inValueFloat("number2", 2), + result = op.outNumber("result"); + +op.setTitle("*"); + +number1.onChange = number2.onChange = update; +update(); + +function update() +{ + const n1 = number1.get(); + const n2 = number2.get(); + + result.set(n1 * n2); +} + + +}; + +Ops.Math.Multiply.prototype = new CABLES.Op(); +CABLES.OPS["1bbdae06-fbb2-489b-9bcc-36c9d65bd441"]={f:Ops.Math.Multiply,objName:"Ops.Math.Multiply"}; + + + + +// ************************************************************** +// +// Ops.Deprecated.Exp.Gl.VectorFieldArray +// +// ************************************************************** + +Ops.Deprecated.Exp.Gl.VectorFieldArray = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const cgl = op.patch.cgl; + +let exe = op.inTrigger("exe"); +let geom = op.inObject("geom"); +geom.ignoreValueSerialize = true; + +let tex = op.inTexture("Texture"); + +let numColumns = op.inValue("Columns", 100); +let numRows = op.inValue("Rows", 100); +let spacingColumns = op.inValue("Spacing Columns", 1); +let spacingRows = op.inValue("Spacing Rows", 1); +let doCenter = op.inValueBool("Center", true); + +let transRotate = op.inValueBool("Rotate", true); +let transScale = op.inValueBool("Scale", false); +let transTransZ = op.inValueBool("Translate Z", false); + +transTransZ.onChange = updateTransforms; +transRotate.onChange = updateTransforms; +transScale.onChange = updateTransforms; + +function updateTransforms() +{ + if (!shader) return; + if (transRotate.get())shader.define("TRANS_ROTATE"); + else shader.removeDefine("TRANS_ROTATE"); + + if (transScale.get())shader.define("TRANS_SCALE"); + else shader.removeDefine("TRANS_SCALE"); + + if (transTransZ.get())shader.define("TRANS_TRANS_Z"); + else shader.removeDefine("TRANS_TRANS_Z"); +} + +let transformations = []; +let mod = null; +let mesh = null; +var shader = null; +let uniDoInstancing = null; +let uniSpaceX = null; +let uniSpaceY = null; +let recalc = true; + +numRows.onChange = reset; +numColumns.onChange = reset; +doCenter.onChange = reset; +spacingColumns.onChange = reset; +spacingRows.onChange = reset; + +geom.onChange = reset; +exe.onTriggered = doRender; +exe.onLinkChanged = removeModule; + +let srcHeadVert = "" + .endl() + "UNI float do_instancing;" + .endl() + "UNI sampler2D {{mod}}field;" + + .endl() + "UNI float {{mod}}spaceX;" + .endl() + "UNI float {{mod}}spaceY;" + .endl() + "UNI float {{mod}}rows;" + .endl() + "UNI float {{mod}}cols;" + + .endl() + "#ifdef INSTANCING" + .endl() + " IN mat4 instMat;" + .endl() + " OUT mat4 instModelMat;" + .endl() + "#endif" + + .endl() + "mat4 rotationMatrix(vec3 axis, float angle)" + .endl() + "{" + .endl() + " axis = normalize(axis);" + .endl() + " float s = sin(angle);" + .endl() + " float c = cos(angle);" + .endl() + " float oc = 1.0 - c;" + + .endl() + " return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0," + .endl() + " oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0," + .endl() + " oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0," + .endl() + " 0.0, 0.0, 0.0, 1.0);" + .endl() + "}"; + +let srcBodyVert = "" + .endl() + "#ifdef INSTANCING" + // .endl()+' if( do_instancing==1.0 )' + .endl() + " {" + .endl() + " instModelMat=instMat;" + .endl() + " float tx=(instModelMat[3][0]) / {{mod}}cols;" + .endl() + " float ty=(instModelMat[3][1]) / {{mod}}rows;" + .endl() + " instModelMat[3][0]*={{mod}}spaceX;" + .endl() + " instModelMat[3][1]*={{mod}}spaceY;" + .endl() + " vec4 instCol = texture2D( {{mod}}field, vec2(tx,ty) );" + + .endl() + " #ifdef TRANS_ROTATE" + .endl() + " instModelMat*=rotationMatrix(vec3(0.0,0.0,1.0),instCol.r*3.1415926535897932384626433832795*2.0);" + .endl() + " #endif" + + .endl() + " #ifdef TRANS_SCALE" + .endl() + " pos.rgb*=instCol.r;" + .endl() + " #endif" + + .endl() + " #ifdef TRANS_TRANS_Z" + .endl() + " pos.z+=instCol.r;" + .endl() + " #endif" + +// .endl()+' pos*=instCol.r;' + .endl() + " mMatrix=mMatrix * instModelMat;" + .endl() + " }" + .endl() + "#endif" + .endl(); + +function reset() +{ + recalc = true; +} + +function prepare() +{ + if (geom.get()) + { + calc(); + + let num = transformations.length; + let arrs = [].concat.apply([], transformations); + + let matrices = new Float32Array(arrs); + + mesh = new CGL.Mesh(cgl, geom.get()); + mesh.numInstances = num; + + mesh.addAttribute("instMat", matrices, 16); + + recalc = false; + } +} + +function removeModule() +{ + if (shader && mod) + { + shader.removeModule(mod); + shader = null; + } +} + +function doRender() +{ + if (recalc)prepare(); + if (mesh) + { + if (cgl.getShader() && cgl.getShader() != shader) + { + if (shader && mod) + { + shader.removeModule(mod); + shader = null; + } + + shader = cgl.getShader(); + if (!shader.hasDefine("INSTANCING")) + { + mod = shader.addModule( + { + "name": "MODULE_VERTEX_POSITION", + "srcHeadVert": srcHeadVert, + "srcBodyVert": srcBodyVert + }); + + shader.define("INSTANCING"); + op.uniDoInstancing = new CGL.Uniform(shader, "f", "do_instancing", 1); + op.uniSpaceX = new CGL.Uniform(shader, "f", mod.prefix + "spaceX", spacingColumns); + op.uniSpaceY = new CGL.Uniform(shader, "f", mod.prefix + "spaceY", spacingRows); + op.uniTexture = new CGL.Uniform(shader, "t", mod.prefix + "field", 5); + op.uniCols = new CGL.Uniform(shader, "f", mod.prefix + "cols", numColumns); + op.uniRows = new CGL.Uniform(shader, "f", mod.prefix + "rows", numRows); + + updateTransforms(); + } + else + { + op.uniDoInstancing = shader.getUniform("do_instancing"); + } + } + + // if(uniSpaceX) + // { + // uniSpaceY.setValue(spacingRows.get()); + // uniSpaceX.setValue(spacingColumns.get()); + + // uniCols.setValue(numColumns.get()); + // uniRows.setValue(numRows.get()); + + // } + + if (tex.get()) + cgl.setTexture(5, tex.get().tex); + + op.uniDoInstancing.setValue(1); + mesh.render(shader); + op.uniDoInstancing.setValue(0); + } + else + { + prepare(); + } +} + +function calc() +{ + let m = mat4.create(); + let cols = Math.round(numColumns.get()); + let rows = Math.round(numRows.get()); + if (cols <= 0)cols = 1; + if (rows <= 0)rows = 1; + + let distX = spacingColumns.get(); + let distY = spacingRows.get(); + + let centerX = 0; + let centerY = 0; + if (doCenter.get()) + { + centerX = cols * (spacingColumns.get() / 2); + centerY = rows * (spacingRows.get() / 2); + } + + transformations.length = cols * rows; + + for (let x = 0; x < cols; x++) + { + for (let y = 0; y < rows; y++) + { + mat4.identity(m); + mat4.translate(m, m, [x - centerX, y - centerY, 0]); + transformations[x + y * cols] = Array.prototype.slice.call(m); + } + } + + op.log("reset", transformations.length, cols, rows); +} + + +}; + +Ops.Deprecated.Exp.Gl.VectorFieldArray.prototype = new CABLES.Op(); +CABLES.OPS["fba86dad-f37f-482e-a8fb-2abc76723ecf"]={f:Ops.Deprecated.Exp.Gl.VectorFieldArray,objName:"Ops.Deprecated.Exp.Gl.VectorFieldArray"}; + + + + +// ************************************************************** +// +// Ops.Sequence +// +// ************************************************************** + +Ops.Sequence = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + cleanup = op.inTriggerButton("Clean up connections"); + +const + exes = [], + triggers = [], + num = 16; + +let updateTimeout = null; + +exe.onTriggered = triggerAll; +cleanup.onTriggered = clean; +cleanup.setUiAttribs({ "hidePort": true }); +cleanup.setUiAttribs({ "hideParam": true }); + +for (let i = 0; i < num; i++) +{ + const p = op.outTrigger("trigger " + i); + triggers.push(p); + p.onLinkChanged = updateButton; + + if (i < num - 1) + { + let newExe = op.inTrigger("exe " + i); + newExe.onTriggered = triggerAll; + exes.push(newExe); + } +} + +function updateButton() +{ + clearTimeout(updateTimeout); + updateTimeout = setTimeout(() => + { + let show = false; + for (let i = 0; i < triggers.length; i++) + if (triggers[i].links.length > 1) show = true; + + cleanup.setUiAttribs({ "hideParam": !show }); + + if (op.isCurrentUiOp()) op.refreshParams(); + }, 60); +} + +function triggerAll() +{ + for (let i = 0; i < triggers.length; i++) triggers[i].trigger(); +} + +function clean() +{ + let count = 0; + for (let i = 0; i < triggers.length; i++) + { + let removeLinks = []; + + if (triggers[i].links.length > 1) + for (let j = 1; j < triggers[i].links.length; j++) + { + while (triggers[count].links.length > 0) count++; + + removeLinks.push(triggers[i].links[j]); + const otherPort = triggers[i].links[j].getOtherPort(triggers[i]); + op.patch.link(op, "trigger " + count, otherPort.parent, otherPort.name); + count++; + } + + for (let j = 0; j < removeLinks.length; j++) removeLinks[j].remove(); + } + updateButton(); +} + + +}; + +Ops.Sequence.prototype = new CABLES.Op(); +CABLES.OPS["a466bc1f-06e9-4595-8849-bffb9fe22f99"]={f:Ops.Sequence,objName:"Ops.Sequence"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ImageCompose_v2 +// +// ************************************************************** + +Ops.Gl.TextureEffects.ImageCompose_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"imgcomp_frag":"UNI float a;\nvoid main()\n{\n outColor= vec4(0.0,0.0,0.0,a);\n}\n",}; +const + render = op.inTrigger("Render"), + useVPSize = op.inBool("Use viewport size", true), + width = op.inValueInt("Width", 640), + height = op.inValueInt("Height", 480), + tfilter = op.inSwitch("Filter", ["nearest", "linear", "mipmap"], "linear"), + twrap = op.inValueSelect("Wrap", ["clamp to edge", "repeat", "mirrored repeat"], "repeat"), + fpTexture = op.inValueBool("HDR"), + inTransp = op.inValueBool("Transparent", false), + + trigger = op.outTrigger("Next"), + texOut = op.outTexture("texture_out"), + outRatio = op.outValue("Aspect Ratio"); + +const cgl = op.patch.cgl; +op.setPortGroup("Texture Size", [useVPSize, width, height]); +op.setPortGroup("Texture Settings", [twrap, tfilter, fpTexture, inTransp]); + +texOut.set(CGL.Texture.getEmptyTexture(cgl, fpTexture.get())); +let effect = null; +let tex = null; +let w = 8, h = 8; + +const prevViewPort = [0, 0, 0, 0]; +let reInitEffect = true; + +// const bgShader = new CGL.Shader(cgl, "imgcompose bg"); +// bgShader.setSource(bgShader.getDefaultVertexShader(), attachments.imgcomp_frag); + +// const uniAlpha = new CGL.Uniform(bgShader, "f", "a", !inTransp.get()); + +let selectedFilter = CGL.Texture.FILTER_LINEAR; +let selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + +const fps = 0; +const fpsStart = 0; + +twrap.onChange = onWrapChange; +tfilter.onChange = onFilterChange; + +render.onTriggered = op.preRender = doRender; + +onFilterChange(); +onWrapChange(); +updateSizePorts(); + +// inTransp.onChange = () => +// { +// uniAlpha.setValue(!inTransp.get()); +// }; + +function initEffect() +{ + if (effect)effect.delete(); + if (tex)tex.delete(); + + if (fpTexture.get() && tfilter.get() == "mipmap") op.setUiError("fpmipmap", "Don't use mipmap and HDR at the same time, many systems do not support this."); + else op.setUiError("fpmipmap", null); + + effect = new CGL.TextureEffect(cgl, { "isFloatingPointTexture": fpTexture.get() }); + + tex = new CGL.Texture(cgl, + { + "name": "image_compose_v2_" + op.id, + "isFloatingPointTexture": fpTexture.get(), + "filter": selectedFilter, + "wrap": selectedWrap, + "width": Math.ceil(width.get()), + "height": Math.ceil(height.get()), + }); + + effect.setSourceTexture(tex); + texOut.set(CGL.Texture.getEmptyTexture(cgl, fpTexture.get())); + + reInitEffect = false; +} + +fpTexture.onChange = function () +{ + reInitEffect = true; +}; + +function updateResolution() +{ + if (!effect)initEffect(); + + if (useVPSize.get()) + { + w = cgl.getViewPort()[2]; + h = cgl.getViewPort()[3]; + } + else + { + w = Math.ceil(width.get()); + h = Math.ceil(height.get()); + } + + outRatio.set(w / h); + + if ((w != tex.width || h != tex.height) && (w !== 0 && h !== 0)) + { + // height.set(h); + // width.set(w); + tex.setSize(w, h); + + effect.setSourceTexture(tex); + texOut.set(CGL.Texture.getEmptyTexture(cgl, fpTexture.get())); + texOut.set(tex); + } + + // if (texOut.get() && selectedFilter != CGL.Texture.FILTER_NEAREST) + // { + // if (!texOut.get().isPowerOfTwo()) op.setUiError("hintnpot", "texture dimensions not power of two! - texture filtering when scaling will not work on ios devices.", 0); + // else op.setUiError("hintnpot", null, 0); + // } + // else op.setUiError("hintnpot", null, 0); +} + +function updateSizePorts() +{ + width.setUiAttribs({ "greyout": useVPSize.get() }); + height.setUiAttribs({ "greyout": useVPSize.get() }); +} + +useVPSize.onChange = function () +{ + updateSizePorts(); +}; + +op.preRender = function () +{ + doRender(); + // bgShader.bind(); +}; + +function doRender() +{ + if (!effect || reInitEffect) initEffect(); + + const vp = cgl.getViewPort(); + prevViewPort[0] = vp[0]; + prevViewPort[1] = vp[1]; + prevViewPort[2] = vp[2]; + prevViewPort[3] = vp[3]; + + cgl.pushBlend(false); + + updateResolution(); + + const oldEffect = cgl.currentTextureEffect; + cgl.currentTextureEffect = effect; + cgl.currentTextureEffect.width = width.get(); + cgl.currentTextureEffect.height = height.get(); + effect.setSourceTexture(tex); + + let bgTex = CGL.Texture.getBlackTexture(cgl); + if (inTransp.get())bgTex = CGL.Texture.getEmptyTexture(cgl, fpTexture.get()); + + effect.startEffect(bgTex); + + // cgl.pushShader(bgShader); + // cgl.currentTextureEffect.bind(); + // cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + // cgl.currentTextureEffect.finish(); + // cgl.popShader(); + + trigger.trigger(); + + texOut.set(effect.getCurrentSourceTexture()); + + effect.endEffect(); + + cgl.setViewPort(prevViewPort[0], prevViewPort[1], prevViewPort[2], prevViewPort[3]); + + cgl.popBlend(false); + cgl.currentTextureEffect = oldEffect; +} + +function onWrapChange() +{ + if (twrap.get() == "repeat") selectedWrap = CGL.Texture.WRAP_REPEAT; + if (twrap.get() == "mirrored repeat") selectedWrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + if (twrap.get() == "clamp to edge") selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + reInitEffect = true; + // updateResolution(); +} + +function onFilterChange() +{ + if (tfilter.get() == "nearest") selectedFilter = CGL.Texture.FILTER_NEAREST; + if (tfilter.get() == "linear") selectedFilter = CGL.Texture.FILTER_LINEAR; + if (tfilter.get() == "mipmap") selectedFilter = CGL.Texture.FILTER_MIPMAP; + + reInitEffect = true; + // updateResolution(); +} + + +}; + +Ops.Gl.TextureEffects.ImageCompose_v2.prototype = new CABLES.Op(); +CABLES.OPS["a5b43d4c-a9ea-4eaf-9ed0-f257d222659d"]={f:Ops.Gl.TextureEffects.ImageCompose_v2,objName:"Ops.Gl.TextureEffects.ImageCompose_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Shader.BasicMaterial_v3 +// +// ************************************************************** + +Ops.Gl.Shader.BasicMaterial_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"basicmaterial_frag":"{{MODULES_HEAD}}\n\nIN vec2 texCoord;\n\n#ifdef VERTEX_COLORS\nIN vec4 vertCol;\n#endif\n\n#ifdef HAS_TEXTURES\n IN vec2 texCoordOrig;\n #ifdef HAS_TEXTURE_DIFFUSE\n UNI sampler2D tex;\n #endif\n #ifdef HAS_TEXTURE_OPACITY\n UNI sampler2D texOpacity;\n #endif\n#endif\n\nvoid main()\n{\n {{MODULE_BEGIN_FRAG}}\n vec4 col=color;\n\n\n #ifdef HAS_TEXTURES\n vec2 uv=texCoord;\n\n #ifdef CROP_TEXCOORDS\n if(uv.x<0.0 || uv.x>1.0 || uv.y<0.0 || uv.y>1.0) discard;\n #endif\n\n #ifdef HAS_TEXTURE_DIFFUSE\n col=texture(tex,uv);\n\n #ifdef COLORIZE_TEXTURE\n col.r*=color.r;\n col.g*=color.g;\n col.b*=color.b;\n #endif\n #endif\n col.a*=color.a;\n #ifdef HAS_TEXTURE_OPACITY\n #ifdef TRANSFORMALPHATEXCOORDS\n uv=texCoordOrig;\n #endif\n #ifdef ALPHA_MASK_IALPHA\n col.a*=1.0-texture(texOpacity,uv).a;\n #endif\n #ifdef ALPHA_MASK_ALPHA\n col.a*=texture(texOpacity,uv).a;\n #endif\n #ifdef ALPHA_MASK_LUMI\n col.a*=dot(vec3(0.2126,0.7152,0.0722), texture(texOpacity,uv).rgb);\n #endif\n #ifdef ALPHA_MASK_R\n col.a*=texture(texOpacity,uv).r;\n #endif\n #ifdef ALPHA_MASK_G\n col.a*=texture(texOpacity,uv).g;\n #endif\n #ifdef ALPHA_MASK_B\n col.a*=texture(texOpacity,uv).b;\n #endif\n // #endif\n #endif\n #endif\n\n {{MODULE_COLOR}}\n\n #ifdef DISCARDTRANS\n if(col.a<0.2) discard;\n #endif\n\n #ifdef VERTEX_COLORS\n col*=vertCol;\n #endif\n\n outColor = col;\n}\n","basicmaterial_vert":"\n{{MODULES_HEAD}}\n\n// OUT vec3 norm;\nOUT vec2 texCoord;\nOUT vec2 texCoordOrig;\n\nUNI mat4 projMatrix;\nUNI mat4 modelMatrix;\nUNI mat4 viewMatrix;\n\n#ifdef HAS_TEXTURES\n UNI float diffuseRepeatX;\n UNI float diffuseRepeatY;\n UNI float texOffsetX;\n UNI float texOffsetY;\n#endif\n\n#ifdef VERTEX_COLORS\n in vec4 attrVertColor;\n out vec4 vertCol;\n\n#endif\n\n\nvoid main()\n{\n mat4 mMatrix=modelMatrix;\n mat4 mvMatrix;\n\n norm=attrVertNormal;\n texCoordOrig=attrTexCoord;\n texCoord=attrTexCoord;\n #ifdef HAS_TEXTURES\n texCoord.x=texCoord.x*diffuseRepeatX+texOffsetX;\n texCoord.y=(1.0-texCoord.y)*diffuseRepeatY+texOffsetY;\n #endif\n\n #ifdef VERTEX_COLORS\n vertCol=attrVertColor;\n #endif\n\n vec4 pos = vec4(vPosition, 1.0);\n\n #ifdef BILLBOARD\n vec3 position=vPosition;\n mvMatrix=viewMatrix*modelMatrix;\n\n gl_Position = projMatrix * mvMatrix * vec4((\n position.x * vec3(\n mvMatrix[0][0],\n mvMatrix[1][0],\n mvMatrix[2][0] ) +\n position.y * vec3(\n mvMatrix[0][1],\n mvMatrix[1][1],\n mvMatrix[2][1]) ), 1.0);\n #endif\n\n {{MODULE_VERTEX_POSITION}}\n\n #ifndef BILLBOARD\n mvMatrix=viewMatrix * mMatrix;\n #endif\n\n\n #ifndef BILLBOARD\n // gl_Position = projMatrix * viewMatrix * modelMatrix * pos;\n gl_Position = projMatrix * mvMatrix * pos;\n #endif\n}\n",}; +const render = op.inTrigger("render"); + +const trigger = op.outTrigger("trigger"); +const shaderOut = op.outObject("shader", null, "shader"); + +shaderOut.ignoreValueSerialize = true; + +op.toWorkPortsNeedToBeLinked(render); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "basicmaterialnew"); +shader.addAttribute({ "type": "vec3", "name": "vPosition" }); +shader.addAttribute({ "type": "vec2", "name": "attrTexCoord" }); +shader.addAttribute({ "type": "vec3", "name": "attrVertNormal", "nameFrag": "norm" }); +shader.addAttribute({ "type": "float", "name": "attrVertIndex" }); + +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); + +shader.setSource(attachments.basicmaterial_vert, attachments.basicmaterial_frag); + +shaderOut.set(shader); + +render.onTriggered = doRender; + +// rgba colors +const r = op.inValueSlider("r", Math.random()); +const g = op.inValueSlider("g", Math.random()); +const b = op.inValueSlider("b", Math.random()); +const a = op.inValueSlider("a", 1); +r.setUiAttribs({ "colorPick": true }); + +// const uniColor=new CGL.Uniform(shader,'4f','color',r,g,b,a); +const colUni = shader.addUniformFrag("4f", "color", r, g, b, a); + +shader.uniformColorDiffuse = colUni; + +// diffuse outTexture + +const diffuseTexture = op.inTexture("texture"); +let diffuseTextureUniform = null; +diffuseTexture.onChange = updateDiffuseTexture; + +const colorizeTexture = op.inValueBool("colorizeTexture", false); +const vertexColors = op.inValueBool("Vertex Colors", false); + +// opacity texture +const textureOpacity = op.inTexture("textureOpacity"); +let textureOpacityUniform = null; + +const alphaMaskSource = op.inSwitch("Alpha Mask Source", ["Luminance", "R", "G", "B", "A", "1-A"], "Luminance"); +alphaMaskSource.setUiAttribs({ "greyout": true }); +textureOpacity.onChange = updateOpacity; + +const texCoordAlpha = op.inValueBool("Opacity TexCoords Transform", false); +const discardTransPxl = op.inValueBool("Discard Transparent Pixels"); + +// texture coords +const + diffuseRepeatX = op.inValue("diffuseRepeatX", 1), + diffuseRepeatY = op.inValue("diffuseRepeatY", 1), + diffuseOffsetX = op.inValue("Tex Offset X", 0), + diffuseOffsetY = op.inValue("Tex Offset Y", 0), + cropRepeat = op.inBool("Crop TexCoords", false); + +shader.addUniformFrag("f", "diffuseRepeatX", diffuseRepeatX); +shader.addUniformFrag("f", "diffuseRepeatY", diffuseRepeatY); +shader.addUniformFrag("f", "texOffsetX", diffuseOffsetX); +shader.addUniformFrag("f", "texOffsetY", diffuseOffsetY); + +const doBillboard = op.inValueBool("billboard", false); + +alphaMaskSource.onChange = + doBillboard.onChange = + discardTransPxl.onChange = + texCoordAlpha.onChange = + cropRepeat.onChange = + vertexColors.onChange = + colorizeTexture.onChange = updateDefines; + +op.setPortGroup("Color", [r, g, b, a]); +op.setPortGroup("Color Texture", [diffuseTexture, vertexColors, colorizeTexture]); +op.setPortGroup("Opacity", [textureOpacity, alphaMaskSource, discardTransPxl, texCoordAlpha]); +op.setPortGroup("Texture Transform", [diffuseRepeatX, diffuseRepeatY, diffuseOffsetX, diffuseOffsetY, cropRepeat]); + +updateOpacity(); +updateDiffuseTexture(); + +op.preRender = function () +{ + shader.bind(); + doRender(); +}; + +function doRender() +{ + if (!shader) return; + + cgl.pushShader(shader); + shader.popTextures(); + + if (diffuseTextureUniform && diffuseTexture.get()) shader.pushTexture(diffuseTextureUniform, diffuseTexture.get()); + if (textureOpacityUniform && textureOpacity.get()) shader.pushTexture(textureOpacityUniform, textureOpacity.get()); + + trigger.trigger(); + + cgl.popShader(); +} + +function updateOpacity() +{ + if (textureOpacity.get()) + { + if (textureOpacityUniform !== null) return; + shader.removeUniform("texOpacity"); + shader.define("HAS_TEXTURE_OPACITY"); + if (!textureOpacityUniform)textureOpacityUniform = new CGL.Uniform(shader, "t", "texOpacity"); + + alphaMaskSource.setUiAttribs({ "greyout": false }); + texCoordAlpha.setUiAttribs({ "greyout": false }); + } + else + { + shader.removeUniform("texOpacity"); + shader.removeDefine("HAS_TEXTURE_OPACITY"); + textureOpacityUniform = null; + + alphaMaskSource.setUiAttribs({ "greyout": true }); + texCoordAlpha.setUiAttribs({ "greyout": true }); + } + + updateDefines(); +} + +function updateDiffuseTexture() +{ + if (diffuseTexture.get()) + { + if (!shader.hasDefine("HAS_TEXTURE_DIFFUSE"))shader.define("HAS_TEXTURE_DIFFUSE"); + if (!diffuseTextureUniform)diffuseTextureUniform = new CGL.Uniform(shader, "t", "texDiffuse"); + + diffuseRepeatX.setUiAttribs({ "greyout": false }); + diffuseRepeatY.setUiAttribs({ "greyout": false }); + diffuseOffsetX.setUiAttribs({ "greyout": false }); + diffuseOffsetY.setUiAttribs({ "greyout": false }); + colorizeTexture.setUiAttribs({ "greyout": false }); + } + else + { + shader.removeUniform("texDiffuse"); + shader.removeDefine("HAS_TEXTURE_DIFFUSE"); + diffuseTextureUniform = null; + + diffuseRepeatX.setUiAttribs({ "greyout": true }); + diffuseRepeatY.setUiAttribs({ "greyout": true }); + diffuseOffsetX.setUiAttribs({ "greyout": true }); + diffuseOffsetY.setUiAttribs({ "greyout": true }); + colorizeTexture.setUiAttribs({ "greyout": true }); + } +} + +function updateDefines() +{ + shader.toggleDefine("VERTEX_COLORS", vertexColors.get()); + shader.toggleDefine("CROP_TEXCOORDS", cropRepeat.get()); + shader.toggleDefine("COLORIZE_TEXTURE", colorizeTexture.get()); + shader.toggleDefine("TRANSFORMALPHATEXCOORDS", texCoordAlpha.get()); + shader.toggleDefine("DISCARDTRANS", discardTransPxl.get()); + shader.toggleDefine("BILLBOARD", doBillboard.get()); + + shader.toggleDefine("ALPHA_MASK_ALPHA", alphaMaskSource.get() == "A"); + shader.toggleDefine("ALPHA_MASK_IALPHA", alphaMaskSource.get() == "1-A"); + shader.toggleDefine("ALPHA_MASK_LUMI", alphaMaskSource.get() == "Luminance"); + shader.toggleDefine("ALPHA_MASK_R", alphaMaskSource.get() == "R"); + shader.toggleDefine("ALPHA_MASK_G", alphaMaskSource.get() == "G"); + shader.toggleDefine("ALPHA_MASK_B", alphaMaskSource.get() == "B"); +} + + +}; + +Ops.Gl.Shader.BasicMaterial_v3.prototype = new CABLES.Op(); +CABLES.OPS["ec55d252-3843-41b1-b731-0482dbd9e72b"]={f:Ops.Gl.Shader.BasicMaterial_v3,objName:"Ops.Gl.Shader.BasicMaterial_v3"}; + + + + +// ************************************************************** +// +// Ops.Deprecated.Anim.RelativeTime +// +// ************************************************************** + +Ops.Deprecated.Anim.RelativeTime = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + mul = op.inValue("Multiply", 1), + outTrigger = op.outTrigger("Trigger out"), + result = op.outNumber("result"); + +exe.onTriggered = update; +update(); + +function update() +{ + result.set(op.patch.freeTimer.get() * mul.get()); + outTrigger.trigger(); +} + + +}; + +Ops.Deprecated.Anim.RelativeTime.prototype = new CABLES.Op(); +CABLES.OPS["917df27b-7cc3-465f-986d-bcf5a7e125a7"]={f:Ops.Deprecated.Anim.RelativeTime,objName:"Ops.Deprecated.Anim.RelativeTime"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Noise.FBMNoise +// +// ************************************************************** + +Ops.Gl.TextureEffects.Noise.FBMNoise = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"fbmnoise_frag":"UNI sampler2D tex;\nUNI float anim;\n\nUNI float scale;\nUNI float repeat;\n\nUNI float scrollX;\nUNI float scrollY;\n\nUNI float amount;\n\nUNI bool layer1;\nUNI bool layer2;\nUNI bool layer3;\nUNI bool layer4;\nUNI vec3 color;\nUNI float aspect;\n\nIN vec2 texCoord;\n\n\n{{CGL.BLENDMODES}}\n\n// csdcsdcds\n// adapted from warp shader by inigo quilez/iq\n// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.\n\n// See here for a tutorial on how to make this: http://www.iquilezles.org/www/articles/warp/warp.htm\n\nconst mat2 m = mat2( 0.80, 0.60, -0.60, 0.80 );\n\nfloat noise( in vec2 x )\n{\n\treturn sin(1.5*x.x)*sin(1.5*x.y);\n}\n\nfloat fbm4( vec2 p )\n{\n float f = 0.0;\n f += 0.5000*noise( p ); p = m*p*2.02;\n f += 0.2500*noise( p ); p = m*p*2.03;\n f += 0.1250*noise( p ); p = m*p*2.01;\n f += 0.0625*noise( p );\n return f/0.9375;\n}\n\nfloat fbm6( vec2 p )\n{\n float f = 0.0;\n f += 0.500000*(0.5+0.5*noise( p )); p = m*p*2.02;\n f += 0.250000*(0.5+0.5*noise( p )); p = m*p*2.03;\n f += 0.125000*(0.5+0.5*noise( p )); p = m*p*2.01;\n f += 0.062500*(0.5+0.5*noise( p )); p = m*p*2.04;\n f += 0.031250*(0.5+0.5*noise( p )); p = m*p*2.01;\n f += 0.015625*(0.5+0.5*noise( p ));\n return f/0.96875;\n}\n\nvoid main()\n{\n // vec4 col=texture(tex,texCoord+2.0*fbm4(texCoord+2.0*fbm6(texCoord+anim)));\n\n vec2 tc=texCoord;\n\t#ifdef DO_TILEABLE\n\t tc=abs(texCoord-0.5);\n\t#endif\n\n\n vec2 p=(tc-0.5)*scale;\n\n\n p.y/=aspect;\n vec2 q = vec2( fbm4( p + vec2(0.3+scrollX,0.20+scrollY) ),\n fbm4( p + vec2(3.1+scrollX,1.3+scrollY) ) );\n\n vec2 q2 = vec2( fbm4( p + vec2(2.0+scrollX,1.0+scrollY) ),\n fbm4( p + vec2(3.1+scrollX,1.3+scrollY) ) );\n\n vec2 q3 = vec2( fbm4( p + vec2(9.0+scrollX,4.0+scrollY) ),\n fbm4( p + vec2(3.1+scrollX,4.3+scrollY) ) );\n\n\n\n float v= fbm4( ( p + 4.0*q +anim*0.1)*repeat);\n float v2= fbm4( (p + 4.0*q2 +anim*0.1)*repeat );\n\n float v3= fbm6( (p + 4.0*q3 +anim*0.1)*repeat );\n float v4= fbm6( (p + 4.0*q2 +anim*0.1)*repeat );\n\n\n\n\n vec4 base=texture(tex,texCoord);\n\n vec4 finalColor;\n float colVal=0.0;\n float numLayers=0.0;\n\n if(layer1)\n {\n colVal+=v;\n numLayers++;\n }\n\n if(layer2)\n {\n colVal+=v2;\n numLayers++;\n }\n\n if(layer3)\n {\n colVal+=v3;\n numLayers++;\n }\n\n if(layer4)\n {\n colVal+=v4;\n numLayers++;\n }\n\n finalColor=vec4( color*vec3(colVal/numLayers),1.0);\n\n outColor = cgl_blend(base,finalColor,amount);;\n}\n",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"), + amount = op.inValueSlider("Amount", 1), + r = op.inValueSlider("r", 1.0), + g = op.inValueSlider("g", 1.0), + b = op.inValueSlider("b", 1.0), + trigger = op.outTrigger("trigger"); + +r.setUiAttribs({ "colorPick": true }); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "fbmnoise"); + +shader.setSource(shader.getDefaultVertexShader(), attachments.fbmnoise_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); + +const uniScale = new CGL.Uniform(shader, "f", "scale", op.inValue("scale", 2)); +const uniAnim = new CGL.Uniform(shader, "f", "anim", op.inValue("anim", 0)); +const uniScrollX = new CGL.Uniform(shader, "f", "scrollX", op.inValue("scrollX", 9)); +const uniScrollY = new CGL.Uniform(shader, "f", "scrollY", op.inValue("scrollY", 0)); +const uniRepeat = new CGL.Uniform(shader, "f", "repeat", op.inValue("repeat", 1)); +const uniAspect = new CGL.Uniform(shader, "f", "aspect", op.inValue("aspect", 1)); + +const uniLayer1 = new CGL.Uniform(shader, "b", "layer1", op.inValueBool("Layer 1", true)); +const uniLayer2 = new CGL.Uniform(shader, "b", "layer2", op.inValueBool("Layer 2", true)); +const uniLayer3 = new CGL.Uniform(shader, "b", "layer3", op.inValueBool("Layer 3", true)); +const uniLayer4 = new CGL.Uniform(shader, "b", "layer4", op.inValueBool("Layer 4", true)); + +const uniColor = new CGL.Uniform(shader, "3f", "color", r, g, b); + +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +const tile = op.inValueBool("Tileable", false); +tile.onChange = updateTileable; +function updateTileable() +{ + if (tile.get())shader.define("DO_TILEABLE"); + else shader.removeDefine("DO_TILEABLE"); +} + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + uniAspect.set(cgl.currentTextureEffect.getCurrentSourceTexture().width / cgl.currentTextureEffect.getCurrentSourceTexture().height); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Noise.FBMNoise.prototype = new CABLES.Op(); +CABLES.OPS["7073186c-b776-48c2-a01e-041df88ad88a"]={f:Ops.Gl.TextureEffects.Noise.FBMNoise,objName:"Ops.Gl.TextureEffects.Noise.FBMNoise"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.ColorMap +// +// ************************************************************** + +Ops.Gl.TextureEffects.ColorMap = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"colormap_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI sampler2D gradient;\nUNI float pos;\nUNI float amount;\nUNI float vmin;\nUNI float vmax;\n\n{{CGL.BLENDMODES}}\n\n\nfloat lumi(vec3 color)\n{\n return vec3(dot(vec3(0.2126,0.7152,0.0722), color)).r;\n}\n\nvoid main()\n{\n vec4 base=texture(tex,texCoord);\n\n base=clamp(base,vmin,vmax);\n\n #ifdef METH_LUMI\n vec4 color=texture(gradient,vec2(lumi(base.rgb),pos));\n #endif\n\n #ifdef METH_CHANNELS\n vec4 color=vec4(1.0);\n color.r=texture(gradient,vec2(base.r,pos)).r;\n color.g=texture(gradient,vec2(base.g,pos)).g;\n color.b=texture(gradient,vec2(base.b,pos)).b;\n #endif\n\n// outColor= vec4(color);\n outColor=cgl_blend(base,color,amount);\n\n}\n",}; +let render = op.inTrigger("render"); +let trigger = op.outTrigger("trigger"); + +const blendMode = CGL.TextureEffect.AddBlendSelect(op, "Blend Mode", "normal"); +const amount = op.inValueSlider("Amount", 1); + +let inGradient = op.inTexture("Gradient"); +let inMethod = op.inSwitch("Method", ["Luminance", "Channels"], "Luminance"); + +let inMin = op.inFloatSlider("Min", 0); +let inMax = op.inFloatSlider("Max", 1); + +let inPos = op.inValueSlider("Position", 0.5); + +op.setPortGroup("Vertical Position", [inMin, inMax, inPos]); + +let cgl = op.patch.cgl; +let shader = new CGL.Shader(cgl, op.name); +shader.define("METH_LUMI"); + +shader.setSource(shader.getDefaultVertexShader(), attachments.colormap_frag); +var textureUniform = new CGL.Uniform(shader, "t", "tex", 0); + +var textureUniform = new CGL.Uniform(shader, "t", "gradient", 1); +let uniPos = new CGL.Uniform(shader, "f", "pos", inPos); + +let uniMin = new CGL.Uniform(shader, "f", "vmin", inMin); +let uniMax = new CGL.Uniform(shader, "f", "vmax", inMax); +let uniAmount = new CGL.Uniform(shader, "f", "amount", amount); + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +inMethod.onChange = () => +{ + shader.toggleDefine("METH_LUMI", inMethod.get() == "Luminance"); + shader.toggleDefine("METH_CHANNELS", inMethod.get() == "Channels"); +}; + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + if (!inGradient.get()) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.setTexture(1, inGradient.get().tex); + // cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, inGradient.get().tex ); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.ColorMap.prototype = new CABLES.Op(); +CABLES.OPS["58e302d7-4b84-4077-aa13-4f3cf0885205"]={f:Ops.Gl.TextureEffects.ColorMap,objName:"Ops.Gl.TextureEffects.ColorMap"}; + + + + +// ************************************************************** +// +// Ops.Gl.Render2Texture +// +// ************************************************************** + +Ops.Gl.Render2Texture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const cgl = op.patch.cgl; + +const + render = op.inTrigger("render"), + useVPSize = op.inValueBool("use viewport size", true), + width = op.inValueInt("texture width", 512), + height = op.inValueInt("texture height", 512), + aspect = op.inBool("Auto Aspect", false), + tfilter = op.inSwitch("filter", ["nearest", "linear", "mipmap"], "linear"), + twrap = op.inSwitch("Wrap", ["Clamp", "Repeat", "Mirror"], "Repeat"), + msaa = op.inSwitch("MSAA", ["none", "2x", "4x", "8x"], "none"), + trigger = op.outTrigger("trigger"), + tex = op.outTexture("texture"), + texDepth = op.outTexture("textureDepth"), + fpTexture = op.inValueBool("HDR"), + depth = op.inValueBool("Depth", true), + clear = op.inValueBool("Clear", true); + +let fb = null; +let reInitFb = true; +tex.set(CGL.Texture.getEmptyTexture(cgl)); + +op.setPortGroup("Size", [useVPSize, width, height, aspect]); + +const prevViewPort = [0, 0, 0, 0]; + +fpTexture.setUiAttribs({ "title": "Pixelformat Float 32bit" }); + +fpTexture.onChange = + depth.onChange = + clear.onChange = + tfilter.onChange = + twrap.onChange = + msaa.onChange = initFbLater; + +useVPSize.onChange = updateVpSize; + +render.onTriggered = + op.preRender = doRender; + +updateVpSize(); + +function updateVpSize() +{ + width.setUiAttribs({ "greyout": useVPSize.get() }); + height.setUiAttribs({ "greyout": useVPSize.get() }); + aspect.setUiAttribs({ "greyout": useVPSize.get() }); +} + +function initFbLater() +{ + reInitFb = true; +} + +function doRender() +{ + const vp = cgl.getViewPort(); + prevViewPort[0] = vp[0]; + prevViewPort[1] = vp[1]; + prevViewPort[2] = vp[2]; + prevViewPort[3] = vp[3]; + + if (!fb || reInitFb) + { + if (fb) fb.delete(); + + let selectedWrap = CGL.Texture.WRAP_REPEAT; + if (twrap.get() == "Clamp") selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + else if (twrap.get() == "Mirror") selectedWrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + + let selectFilter = CGL.Texture.FILTER_NEAREST; + if (tfilter.get() == "nearest") selectFilter = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "linear") selectFilter = CGL.Texture.FILTER_LINEAR; + else if (tfilter.get() == "mipmap") selectFilter = CGL.Texture.FILTER_MIPMAP; + + if (fpTexture.get() && tfilter.get() == "mipmap") op.setUiError("fpmipmap", "Don't use mipmap and HDR at the same time, many systems do not support this."); + else op.setUiError("fpmipmap", null); + + if (cgl.glVersion >= 2) + { + let ms = true; + let msSamples = 4; + + if (msaa.get() == "none") + { + msSamples = 0; + ms = false; + } + if (msaa.get() == "2x") msSamples = 2; + if (msaa.get() == "4x") msSamples = 4; + if (msaa.get() == "8x") msSamples = 8; + + fb = new CGL.Framebuffer2(cgl, 8, 8, + { + "name": "render2texture " + op.id, + "isFloatingPointTexture": fpTexture.get(), + "multisampling": ms, + "wrap": selectedWrap, + "filter": selectFilter, + "depth": depth.get(), + "multisamplingSamples": msSamples, + "clear": clear.get() + }); + } + else + { + fb = new CGL.Framebuffer(cgl, 8, 8, { "isFloatingPointTexture": fpTexture.get(), "clear": clear.get() }); + } + + texDepth.set(fb.getTextureDepth()); + reInitFb = false; + } + + if (useVPSize.get()) + { + width.set(cgl.getViewPort()[2]); + height.set(cgl.getViewPort()[3]); + } + + if (fb.getWidth() != Math.ceil(width.get()) || fb.getHeight() != Math.ceil(height.get())) + { + fb.setSize( + Math.max(1, Math.ceil(width.get())), + Math.max(1, Math.ceil(height.get()))); + } + + fb.renderStart(cgl); + + if (aspect.get()) mat4.perspective(cgl.pMatrix, 45, width.get() / height.get(), 0.1, 1000.0); + + trigger.trigger(); + fb.renderEnd(cgl); + + // cgl.resetViewPort(); + cgl.setViewPort(prevViewPort[0], prevViewPort[1], prevViewPort[2], prevViewPort[3]); + + tex.set(CGL.Texture.getEmptyTexture(op.patch.cgl)); + tex.set(fb.getTextureColor()); +} + + +}; + +Ops.Gl.Render2Texture.prototype = new CABLES.Op(); +CABLES.OPS["d01fa820-396c-4cb5-9d78-6b14762852af"]={f:Ops.Gl.Render2Texture,objName:"Ops.Gl.Render2Texture"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.DrawImage_v3 +// +// ************************************************************** + +Ops.Gl.TextureEffects.DrawImage_v3 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"drawimage_frag":"#ifdef HAS_TEXTURES\n IN vec2 texCoord;\n UNI sampler2D tex;\n UNI sampler2D image;\n#endif\n\n#ifdef TEX_TRANSFORM\n IN mat3 transform;\n#endif\n// UNI float rotate;\n\n{{CGL.BLENDMODES}}\n\n#ifdef HAS_TEXTUREALPHA\n UNI sampler2D imageAlpha;\n#endif\n\nUNI float amount;\n\n#ifdef ASPECT_RATIO\n UNI float aspectTex;\n UNI float aspectPos;\n#endif\n\nvoid main()\n{\n vec4 blendRGBA=vec4(0.0,0.0,0.0,1.0);\n\n #ifdef HAS_TEXTURES\n vec2 tc=texCoord;\n\n #ifdef TEX_FLIP_X\n tc.x=1.0-tc.x;\n #endif\n #ifdef TEX_FLIP_Y\n tc.y=1.0-tc.y;\n #endif\n\n #ifdef ASPECT_RATIO\n #ifdef ASPECT_AXIS_X\n tc.y=(1.0-aspectPos)-(((1.0-aspectPos)-tc.y)*aspectTex);\n #endif\n #ifdef ASPECT_AXIS_Y\n tc.x=(1.0-aspectPos)-(((1.0-aspectPos)-tc.x)/aspectTex);\n #endif\n #endif\n\n #ifdef TEX_TRANSFORM\n vec3 coordinates=vec3(tc.x, tc.y,1.0);\n tc=(transform * coordinates ).xy;\n #endif\n\n blendRGBA=texture(image,tc);\n\n vec3 blend=blendRGBA.rgb;\n vec4 baseRGBA=texture(tex,texCoord);\n vec3 base=baseRGBA.rgb;\n\n\n #ifdef PREMUL\n blend.rgb = (blend.rgb) + (base.rgb * (1.0 - blendRGBA.a));\n #endif\n\n vec3 colNew=_blend(base,blend);\n\n\n\n\n #ifdef REMOVE_ALPHA_SRC\n blendRGBA.a=1.0;\n #endif\n\n #ifdef HAS_TEXTUREALPHA\n vec4 colImgAlpha=texture(imageAlpha,tc);\n float colImgAlphaAlpha=colImgAlpha.a;\n\n #ifdef ALPHA_FROM_LUMINANCE\n vec3 gray = vec3(dot(vec3(0.2126,0.7152,0.0722), colImgAlpha.rgb ));\n colImgAlphaAlpha=(gray.r+gray.g+gray.b)/3.0;\n #endif\n\n #ifdef ALPHA_FROM_INV_UMINANCE\n vec3 gray = vec3(dot(vec3(0.2126,0.7152,0.0722), colImgAlpha.rgb ));\n colImgAlphaAlpha=1.0-(gray.r+gray.g+gray.b)/3.0;\n #endif\n\n #ifdef INVERT_ALPHA\n colImgAlphaAlpha=clamp(colImgAlphaAlpha,0.0,1.0);\n colImgAlphaAlpha=1.0-colImgAlphaAlpha;\n #endif\n\n blendRGBA.a=colImgAlphaAlpha*blendRGBA.a;\n #endif\n #endif\n\n float am=amount;\n\n #ifdef CLIP_REPEAT\n if(tc.y>1.0 || tc.y<0.0 || tc.x>1.0 || tc.x<0.0)\n {\n // colNew.rgb=vec3(0.0);\n am=0.0;\n }\n #endif\n\n #ifdef ASPECT_RATIO\n #ifdef ASPECT_CROP\n if(tc.y>1.0 || tc.y<0.0 || tc.x>1.0 || tc.x<0.0)\n {\n colNew.rgb=base.rgb;\n am=0.0;\n }\n\n #endif\n #endif\n\n\n\n #ifndef PREMUL\n blendRGBA.rgb=mix(colNew,base,1.0-(am*blendRGBA.a));\n blendRGBA.a=clamp(baseRGBA.a+(blendRGBA.a*am),0.,1.);\n #endif\n\n #ifdef PREMUL\n // premultiply\n // blendRGBA.rgb = (blendRGBA.rgb) + (baseRGBA.rgb * (1.0 - blendRGBA.a));\n blendRGBA=vec4(\n mix(colNew.rgb,base,1.0-(am*blendRGBA.a)),\n blendRGBA.a*am+baseRGBA.a\n );\n #endif\n\n #ifdef ALPHA_MASK\n blendRGBA.a=baseRGBA.a;\n #endif\n\n outColor=blendRGBA;\n}\n\n\n\n\n\n\n\n","drawimage_vert":"IN vec3 vPosition;\nIN vec2 attrTexCoord;\nIN vec3 attrVertNormal;\n\nUNI mat4 projMatrix;\nUNI mat4 mvMatrix;\n\nOUT vec2 texCoord;\n// OUT vec3 norm;\n\n#ifdef TEX_TRANSFORM\n UNI float posX;\n UNI float posY;\n UNI float scaleX;\n UNI float scaleY;\n UNI float rotate;\n OUT mat3 transform;\n#endif\n\nvoid main()\n{\n texCoord=attrTexCoord;\n// norm=attrVertNormal;\n\n #ifdef TEX_TRANSFORM\n vec3 coordinates=vec3(attrTexCoord.x, attrTexCoord.y,1.0);\n float angle = radians( rotate );\n vec2 scale= vec2(scaleX,scaleY);\n vec2 translate= vec2(posX,posY);\n\n transform = mat3( scale.x * cos( angle ), scale.x * sin( angle ), 0.0,\n - scale.y * sin( angle ), scale.y * cos( angle ), 0.0,\n - 0.5 * scale.x * cos( angle ) + 0.5 * scale.y * sin( angle ) - 0.5 * translate.x*2.0 + 0.5, - 0.5 * scale.x * sin( angle ) - 0.5 * scale.y * cos( angle ) - 0.5 * translate.y*2.0 + 0.5, 1.0);\n #endif\n\n gl_Position = projMatrix * mvMatrix * vec4(vPosition, 1.0);\n}\n",}; +const + render = op.inTrigger("render"), + blendMode = CGL.TextureEffect.AddBlendSelect(op, "blendMode"), + amount = op.inValueSlider("amount", 1), + + image = op.inTexture("Image"), + inAlphaPremul = op.inValueBool("Premultiplied", false), + inAlphaMask = op.inValueBool("Alpha Mask", false), + removeAlphaSrc = op.inValueBool("removeAlphaSrc", false), + + imageAlpha = op.inTexture("Mask"), + alphaSrc = op.inValueSelect("Mask Src", ["alpha channel", "luminance", "luminance inv"], "luminance"), + invAlphaChannel = op.inValueBool("Invert alpha channel"), + + inAspect = op.inValueBool("Aspect Ratio", false), + inAspectAxis = op.inValueSelect("Stretch Axis", ["X", "Y"], "X"), + inAspectPos = op.inValueSlider("Position", 0.0), + inAspectCrop = op.inValueBool("Crop", false), + + trigger = op.outTrigger("trigger"); + +blendMode.set("normal"); +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, "drawimage"); + +imageAlpha.onLinkChanged = updateAlphaPorts; + +op.setPortGroup("Mask", [imageAlpha, alphaSrc, invAlphaChannel]); +op.setPortGroup("Aspect Ratio", [inAspect, inAspectPos, inAspectCrop, inAspectAxis]); + +function updateAlphaPorts() +{ + if (imageAlpha.isLinked()) + { + removeAlphaSrc.setUiAttribs({ "greyout": true }); + alphaSrc.setUiAttribs({ "greyout": false }); + invAlphaChannel.setUiAttribs({ "greyout": false }); + } + else + { + removeAlphaSrc.setUiAttribs({ "greyout": false }); + alphaSrc.setUiAttribs({ "greyout": true }); + invAlphaChannel.setUiAttribs({ "greyout": true }); + } +} + +op.toWorkPortsNeedToBeLinked(image); + +shader.setSource(attachments.drawimage_vert, attachments.drawimage_frag); + +const + textureUniform = new CGL.Uniform(shader, "t", "tex", 0), + textureImaghe = new CGL.Uniform(shader, "t", "image", 1), + textureAlpha = new CGL.Uniform(shader, "t", "imageAlpha", 2), + uniTexAspect = new CGL.Uniform(shader, "f", "aspectTex", 1), + uniAspectPos = new CGL.Uniform(shader, "f", "aspectPos", inAspectPos); + +inAspect.onChange = + inAspectCrop.onChange = + inAspectAxis.onChange = updateAspectRatio; + +function updateAspectRatio() +{ + shader.removeDefine("ASPECT_AXIS_X"); + shader.removeDefine("ASPECT_AXIS_Y"); + shader.removeDefine("ASPECT_CROP"); + + inAspectPos.setUiAttribs({ "greyout": !inAspect.get() }); + inAspectCrop.setUiAttribs({ "greyout": !inAspect.get() }); + inAspectAxis.setUiAttribs({ "greyout": !inAspect.get() }); + + if (inAspect.get()) + { + shader.define("ASPECT_RATIO"); + + if (inAspectCrop.get()) shader.define("ASPECT_CROP"); + + if (inAspectAxis.get() == "X") shader.define("ASPECT_AXIS_X"); + if (inAspectAxis.get() == "Y") shader.define("ASPECT_AXIS_Y"); + } + else + { + shader.removeDefine("ASPECT_RATIO"); + if (inAspectCrop.get()) shader.define("ASPECT_CROP"); + + if (inAspectAxis.get() == "X") shader.define("ASPECT_AXIS_X"); + if (inAspectAxis.get() == "Y") shader.define("ASPECT_AXIS_Y"); + } +} + +alphaSrc.set("alpha channel"); + +// +// texture flip +// +const flipX = op.inValueBool("flip x"); +const flipY = op.inValueBool("flip y"); + +// +// texture transform +// + +let doTransform = op.inValueBool("Transform"); + +let scaleX = op.inValueSlider("Scale X", 1); +let scaleY = op.inValueSlider("Scale Y", 1); + +let posX = op.inValue("Position X", 0); +let posY = op.inValue("Position Y", 0); + +let rotate = op.inValue("Rotation", 0); + +const inClipRepeat = op.inValueBool("Clip Repeat", false); + +const uniScaleX = new CGL.Uniform(shader, "f", "scaleX", scaleX); +const uniScaleY = new CGL.Uniform(shader, "f", "scaleY", scaleY); +const uniPosX = new CGL.Uniform(shader, "f", "posX", posX); +const uniPosY = new CGL.Uniform(shader, "f", "posY", posY); +const uniRotate = new CGL.Uniform(shader, "f", "rotate", rotate); + +doTransform.onChange = updateTransformPorts; + +function updateTransformPorts() +{ + shader.toggleDefine("TEX_TRANSFORM", doTransform.get()); + + scaleX.setUiAttribs({ "greyout": !doTransform.get() }); + scaleY.setUiAttribs({ "greyout": !doTransform.get() }); + posX.setUiAttribs({ "greyout": !doTransform.get() }); + posY.setUiAttribs({ "greyout": !doTransform.get() }); + rotate.setUiAttribs({ "greyout": !doTransform.get() }); +} + +CGL.TextureEffect.setupBlending(op, shader, blendMode, amount); + +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +render.onTriggered = doRender; + +inClipRepeat.onChange = + imageAlpha.onChange = + inAlphaPremul.onChange = + inAlphaMask.onChange = + invAlphaChannel.onChange = + flipY.onChange = + flipX.onChange = + removeAlphaSrc.onChange = + alphaSrc.onChange = updateDefines; + +updateTransformPorts(); +updateAlphaPorts(); +updateAspectRatio(); +updateDefines(); + +function updateDefines() +{ + shader.toggleDefine("REMOVE_ALPHA_SRC", removeAlphaSrc.get()); + shader.toggleDefine("ALPHA_MASK", inAlphaMask.get()); + + shader.toggleDefine("CLIP_REPEAT", inClipRepeat.get()); + + shader.toggleDefine("HAS_TEXTUREALPHA", imageAlpha.get() && imageAlpha.get().tex); + + shader.toggleDefine("TEX_FLIP_X", flipX.get()); + shader.toggleDefine("TEX_FLIP_Y", flipY.get()); + + shader.toggleDefine("INVERT_ALPHA", invAlphaChannel.get()); + + shader.toggleDefine("ALPHA_FROM_LUMINANCE", alphaSrc.get() == "luminance"); + shader.toggleDefine("ALPHA_FROM_INV_UMINANCE", alphaSrc.get() == "luminance_inv"); + shader.toggleDefine("PREMUL", inAlphaPremul.get()); +} + +function doRender() +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + const tex = image.get(); + if (tex && tex.tex && amount.get() > 0.0) + { + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + const imgTex = cgl.currentTextureEffect.getCurrentSourceTexture(); + cgl.setTexture(0, imgTex.tex); + + if (imgTex && tex) + { + if (tex.textureType != imgTex.textureType && (tex.textureType != CGL.Texture.TYPE_FLOAT || imgTex.textureType != CGL.Texture.TYPE_FLOAT)) + op.setUiError("textypediff", "Drawing 32bit texture into an 8 bit can result in data/precision loss", 1); + else + op.setUiError("textypediff", null); + } + + const asp = 1 / (cgl.currentTextureEffect.getWidth() / cgl.currentTextureEffect.getHeight()) * (tex.width / tex.height); + // uniTexAspect.setValue(1 / (tex.height / tex.width * imgTex.width / imgTex.height)); + + uniTexAspect.setValue(asp); + + cgl.setTexture(1, tex.tex); + // cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, image.get().tex ); + + if (imageAlpha.get() && imageAlpha.get().tex) + { + cgl.setTexture(2, imageAlpha.get().tex); + // cgl.gl.bindTexture(cgl.gl.TEXTURE_2D, imageAlpha.get().tex ); + } + + // cgl.pushBlend(false); + + cgl.pushBlendMode(CGL.BLEND_NONE, true); + + cgl.currentTextureEffect.finish(); + cgl.popBlendMode(); + + // cgl.popBlend(); + + cgl.popShader(); + } + + trigger.trigger(); +} + + +}; + +Ops.Gl.TextureEffects.DrawImage_v3.prototype = new CABLES.Op(); +CABLES.OPS["8f6b2f15-fcb0-4597-90c0-e5173f2969fe"]={f:Ops.Gl.TextureEffects.DrawImage_v3,objName:"Ops.Gl.TextureEffects.DrawImage_v3"}; + + + + +// ************************************************************** +// +// Ops.Gl.GradientTexture +// +// ************************************************************** + +Ops.Gl.GradientTexture = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const inGrad = op.inGradient("Gradient"), + inDir = op.inValueSelect("Direction", ["X", "Y", "Radial"], "X"), + inSmoothstep = op.inValueBool("Smoothstep", false), + inStep = op.inBool("Step", false), + inFlip = op.inBool("Flip", false), + inSRGB = op.inBool("sRGB", false), + inOklab = op.inBool("Oklab", false), + inSize = op.inValueInt("Size", 256), + tfilter = op.inSwitch("filter", ["nearest", "linear", "mipmap"], "linear"), + twrap = op.inValueSelect("wrap", ["clamp to edge", "repeat", "mirrored repeat"], "clamp to edge"), + inGradArray = op.inArray("Gradient Array"), + inRandom = op.inTriggerButton("Randomize Colors"), + outTex = op.outTexture("Texture"), + outColors = op.outArray("Colors", null, 3), + outColorPos = op.outArray("Colors Pos", null, 1); + +const cgl = op.patch.cgl; + +twrap.onChange = + tfilter.onChange = + inStep.onChange = + inFlip.onChange = + inSRGB.onChange = + inOklab.onChange = + inSize.onChange = inGrad.onChange = inSmoothstep.onChange = inDir.onChange = inGradArray.onChange = update; + +inGrad.set("{\"keys\" : [{\"pos\":0,\"r\":0,\"g\":0,\"b\":0},{\"pos\":0.25,\"r\":0,\"g\":0,\"b\":0},{\"pos\":0.75,\"r\":1,\"g\":1,\"b\":1},{\"pos\":1,\"r\":1,\"g\":1,\"b\":1}]}"); + +op.onLoaded = update; + +inRandom.onTriggered = () => +{ + const keys = parseKeys(); + if (keys) + { + keys.forEach((key) => + { + key.r = Math.random(); + key.g = Math.random(); + key.b = Math.random(); + }); + const newKeys = JSON.stringify({ "keys": keys }); + inGrad.set(newKeys); + } +}; + +function rgbToOklab(r, g, b) +{ + let l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b; + let m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b; + let s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b; + l = Math.cbrt(l); m = Math.cbrt(m); s = Math.cbrt(s); + return [ + l * +0.2104542553 + m * +0.7936177850 + s * -0.0040720468, + l * +1.9779984951 + m * -2.4285922050 + s * +0.4505937099, + l * +0.0259040371 + m * +0.7827717662 + s * -0.8086757660 + ]; +} + +function clamp(value, min, max) +{ + return Math.max(Math.min(value, max), min); +} + +function oklabToRGB(L, a, b) +{ + let l = L + a * +0.3963377774 + b * +0.2158037573; + let m = L + a * -0.1055613458 + b * -0.0638541728; + let s = L + a * -0.0894841775 + b * -1.2914855480; + l **= 3; m **= 3; s **= 3; + let r = l * +4.0767416621 + m * -3.3077115913 + s * +0.2309699292; + let g = l * -1.2684380046 + m * +2.6097574011 + s * -0.3413193965; + var b = l * -0.0041960863 + m * -0.7034186147 + s * +1.7076147010; + r = clamp(r, 0, 1); g = clamp(g, 0, 1); b = clamp(b, 0, 1); + return [r, g, b]; +} + +function lin2srgb(r, g, b) +{ + r /= 255; + + const thr = 0.0031308; + + let c_loR = 12.92 * r; + + let c_hiR = 1.055 * Math.pow(r, 0.41666) - 0.055; + return ((r < thr) ? c_loR : c_hiR) * 255; +} + +function update() +{ + const keys = parseKeys(); + if (keys) updateGradient(keys); +} + +function parseKeys() +{ + let keys = null; + op.setUiError("nodata", null); + op.setUiError("parse", null); + + if (Array.isArray(inGradArray.get())) + { + keys = inGradArray.get(); + } + else + { + let grad = null; + if (!inGrad.get() || inGrad.get() === "") + { + op.setUiError("nodata", "gradient no data"); + return null; + } + + try + { + grad = JSON.parse(inGrad.get()); + } + catch (e) + { + op.setUiError("parse", "could not parse gradient data"); + } + + if (!grad || !grad.keys) + { + op.setUiError("nodata", "gradient no data"); + return null; + } + keys = grad.keys; + } + return keys; +} + +function updateGradient(keys) +{ + let width = Math.round(inSize.get()); + if (width < 4) width = 4; + + let selectedWrap = 0; + let selectedFilter = 0; + if (twrap.get() == "repeat") selectedWrap = CGL.Texture.WRAP_REPEAT; + else if (twrap.get() == "mirrored repeat") selectedWrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + else if (twrap.get() == "clamp to edge") selectedWrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + if (tfilter.get() == "nearest") selectedFilter = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "linear") selectedFilter = CGL.Texture.FILTER_LINEAR; + else if (tfilter.get() == "mipmap") selectedFilter = CGL.Texture.FILTER_MIPMAP; + + const tex = new CGL.Texture(cgl); + + if (inDir.get() == "X" || inDir.get() == "Y") + { + const pixels = new Uint8Array(width * 4); + + for (let i = 0; i < keys.length - 1; i++) + { + const keyA = keys[i]; + const keyB = keys[i + 1]; + + for (let x = keyA.pos * width; x < keyB.pos * width; x++) + { + let p = CABLES.map(x, keyA.pos * width, keyB.pos * width, 0, 1); + if (inStep.get())p = Math.round(p); + if (inSmoothstep.get()) p = CABLES.smoothStep(p); + x = Math.round(x); + + let xx = x; + if (inFlip.get())xx = width - x - 1; + + if (inOklab.get()) + { + const klabA = rgbToOklab(keyA.r, keyA.g, keyA.b); + const labA_r = klabA[0]; + const labA_g = klabA[1]; + const labA_b = klabA[2]; + + const klabB = rgbToOklab(keyB.r, keyB.g, keyB.b); + const labB_r = klabB[0]; + const labB_g = klabB[1]; + const labB_b = klabB[2]; + + const l = ((p * labB_r + (1.0 - p) * labA_r)); + const a = ((p * labB_g + (1.0 - p) * labA_g)); + const b = ((p * labB_b + (1.0 - p) * labA_b)); + + const pixCol = oklabToRGB(l, a, b); + pixels[xx * 4 + 0] = Math.round(pixCol[0] * 255); + pixels[xx * 4 + 1] = Math.round(pixCol[1] * 255); + pixels[xx * 4 + 2] = Math.round(pixCol[2] * 255); + } + else + { + pixels[xx * 4 + 0] = Math.round((p * keyB.r + (1.0 - p) * keyA.r) * 255); + pixels[xx * 4 + 1] = Math.round((p * keyB.g + (1.0 - p) * keyA.g) * 255); + pixels[xx * 4 + 2] = Math.round((p * keyB.b + (1.0 - p) * keyA.b) * 255); + } + + if (typeof keyA.a !== "undefined" && typeof keyB.a !== "undefined") + { + const alpha = Math.round((p * keyB.a + (1.0 - p) * keyA.a) * 255); + pixels[xx * 4 + 3] = alpha; + } + else + { + pixels[xx * 4 + 3] = Math.round(255); + } + } + } + + if (inSRGB.get()) + for (let i = 0; i < pixels.length; i += 4) + { + pixels[i + 0] = lin2srgb(pixels[i + 0]); + pixels[i + 1] = lin2srgb(pixels[i + 1]); + pixels[i + 2] = lin2srgb(pixels[i + 2]); + } + + if (inDir.get() == "X") tex.initFromData(pixels, width, 1, selectedFilter, selectedWrap); + if (inDir.get() == "Y") tex.initFromData(pixels, 1, width, selectedFilter, selectedWrap); + } + + if (inDir.get() == "Radial") + { + const pixels = new Uint8Array(width * width * 4); + + const animR = new CABLES.Anim(); + const animG = new CABLES.Anim(); + const animB = new CABLES.Anim(); + + for (let i = 0; i < keys.length - 1; i++) + { + animR.setValue(keys[i].pos, keys[i].r); + animG.setValue(keys[i].pos, keys[i].g); + animB.setValue(keys[i].pos, keys[i].b); + } + + for (let x = 0; x < width; x++) + { + for (let y = 0; y < width; y++) + { + const dx = x - (width - 1) / 2; + const dy = y - (width - 1) / 2; + let pos = Math.sqrt(dx * dx + dy * dy) / (width) * 2; + + if (inSmoothstep.get()) pos = CABLES.smoothStep(pos); + + pixels[(x * 4) + (y * 4 * width) + 0] = animR.getValue(pos) * 255; + pixels[(x * 4) + (y * 4 * width) + 1] = animG.getValue(pos) * 255; + pixels[(x * 4) + (y * 4 * width) + 2] = animB.getValue(pos) * 255; + pixels[(x * 4) + (y * 4 * width) + 3] = Math.round(255); + } + } + + if (inSRGB.get()) + for (let i = 0; i < pixels.length; i += 4) + { + pixels[i + 0] = lin2srgb(pixels[i + 0]); + pixels[i + 1] = lin2srgb(pixels[i + 1]); + pixels[i + 2] = lin2srgb(pixels[i + 2]); + } + + tex.initFromData(pixels, width, width, selectedFilter, selectedWrap); + } + + const colorArr = []; + for (let i = 0; i < keys.length - 1; i++) + { + colorArr.push(keys[i].r, keys[i].g, keys[i].b); + } + + const colorPosArr = []; + for (let i = 0; i < keys.length - 1; i++) + { + colorPosArr.push(keys[i].pos); + } + + outColors.set(colorArr); + outColorPos.set(colorPosArr); + + outTex.set(null); + outTex.set(tex); +} + + +}; + +Ops.Gl.GradientTexture.prototype = new CABLES.Op(); +CABLES.OPS["01380a50-2dbb-4465-ae80-86349b0b717a"]={f:Ops.Gl.GradientTexture,objName:"Ops.Gl.GradientTexture"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.OrbitControls +// +// ************************************************************** + +Ops.Gl.Matrix.OrbitControls = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + minDist = op.inValueFloat("min distance"), + maxDist = op.inValueFloat("max distance"), + + minRotY = op.inValue("min rot y", 0), + maxRotY = op.inValue("max rot y", 0), + + initialRadius = op.inValue("initial radius", 0), + initialAxis = op.inValueSlider("initial axis y"), + initialX = op.inValueSlider("initial axis x"), + + mul = op.inValueFloat("mul"), + smoothness = op.inValueSlider("Smoothness", 1.0), + speedX = op.inValue("Speed X", 1), + speedY = op.inValue("Speed Y", 1), + + active = op.inValueBool("Active", true), + + allowPanning = op.inValueBool("Allow Panning", true), + allowZooming = op.inValueBool("Allow Zooming", true), + allowRotation = op.inValueBool("Allow Rotation", true), + restricted = op.inValueBool("restricted", true), + + trigger = op.outTrigger("trigger"), + outRadius = op.outNumber("radius"), + outXDeg = op.outNumber("Rot X"), + outYDeg = op.outNumber("Rot Y"), + + inReset = op.inTriggerButton("Reset"); + +op.setPortGroup("Initial Values", [initialAxis, initialX, initialRadius]); +op.setPortGroup("Interaction", [mul, smoothness, speedX, speedY]); +op.setPortGroup("Boundaries", [minRotY, maxRotY, minDist, maxDist]); + +mul.set(1); +minDist.set(0.05); +maxDist.set(99999); + +inReset.onTriggered = reset; + +let eye = vec3.create(); +const vUp = vec3.create(); +const vCenter = vec3.create(); +const viewMatrix = mat4.create(); +const tempViewMatrix = mat4.create(); +const vOffset = vec3.create(); +const finalEyeAbs = vec3.create(); + +initialAxis.set(0.5); + +let mouseDown = false; +let radius = 5; +outRadius.set(radius); + +let lastMouseX = 0, lastMouseY = 0; +let percX = 0, percY = 0; + +vec3.set(vCenter, 0, 0, 0); +vec3.set(vUp, 0, 1, 0); + +const tempEye = vec3.create(); +const finalEye = vec3.create(); +const tempCenter = vec3.create(); +const finalCenter = vec3.create(); + +let px = 0; +let py = 0; + +let divisor = 1; +let element = null; +updateSmoothness(); + +op.onDelete = unbind; + +const halfCircle = Math.PI; +const fullCircle = Math.PI * 2; + +function reset() +{ + let off = 0; + + if (px % fullCircle < -halfCircle) + { + off = -fullCircle; + px %= -fullCircle; + } + else + if (px % fullCircle > halfCircle) + { + off = fullCircle; + px %= fullCircle; + } + else px %= fullCircle; + + py %= (Math.PI); + + vec3.set(vOffset, 0, 0, 0); + vec3.set(vCenter, 0, 0, 0); + vec3.set(vUp, 0, 1, 0); + + percX = (initialX.get() * Math.PI * 2 + off); + percY = (initialAxis.get() - 0.5); + + radius = initialRadius.get(); + eye = circlePos(percY); +} + +function updateSmoothness() +{ + divisor = smoothness.get() * 10 + 1.0; +} + +smoothness.onChange = updateSmoothness; + +let initializing = true; + +function ip(val, goal) +{ + if (initializing) return goal; + return val + (goal - val) / divisor; +} + +let lastPy = 0; +const lastPx = 0; + +render.onTriggered = function () +{ + const cgl = op.patch.cg; + + if (!element) + { + setElement(cgl.canvas); + bind(); + } + + cgl.pushViewMatrix(); + + px = ip(px, percX); + py = ip(py, percY); + + let degY = (py + 0.5) * 180; + + if (minRotY.get() !== 0 && degY < minRotY.get()) + { + degY = minRotY.get(); + py = lastPy; + } + else if (maxRotY.get() !== 0 && degY > maxRotY.get()) + { + degY = maxRotY.get(); + py = lastPy; + } + else + { + lastPy = py; + } + + const degX = (px) * CGL.RAD2DEG; + + outYDeg.set(degY); + outXDeg.set(degX); + + circlePosi(eye, py); + + vec3.add(tempEye, eye, vOffset); + vec3.add(tempCenter, vCenter, vOffset); + + finalEye[0] = ip(finalEye[0], tempEye[0]); + finalEye[1] = ip(finalEye[1], tempEye[1]); + finalEye[2] = ip(finalEye[2], tempEye[2]); + + finalCenter[0] = ip(finalCenter[0], tempCenter[0]); + finalCenter[1] = ip(finalCenter[1], tempCenter[1]); + finalCenter[2] = ip(finalCenter[2], tempCenter[2]); + + const empty = vec3.create(); + + mat4.lookAt(viewMatrix, finalEye, finalCenter, vUp); + mat4.rotate(viewMatrix, viewMatrix, px, vUp); + + // finaly multiply current scene viewmatrix + mat4.multiply(cgl.vMatrix, cgl.vMatrix, viewMatrix); + + trigger.trigger(); + cgl.popViewMatrix(); + initializing = false; +}; + +function circlePosi(vec, perc) +{ + const mmul = mul.get(); + if (radius < minDist.get() * mmul) radius = minDist.get() * mmul; + if (radius > maxDist.get() * mmul) radius = maxDist.get() * mmul; + + outRadius.set(radius * mmul); + + let i = 0, degInRad = 0; + + degInRad = 360 * perc / 2 * CGL.DEG2RAD; + vec3.set(vec, + Math.cos(degInRad) * radius * mmul, + Math.sin(degInRad) * radius * mmul, + 0); + return vec; +} + +function circlePos(perc) +{ + const mmul = mul.get(); + if (radius < minDist.get() * mmul)radius = minDist.get() * mmul; + if (radius > maxDist.get() * mmul)radius = maxDist.get() * mmul; + + outRadius.set(radius * mmul); + + let i = 0, degInRad = 0; + const vec = vec3.create(); + degInRad = 360 * perc / 2 * CGL.DEG2RAD; + vec3.set(vec, + Math.cos(degInRad) * radius * mmul, + Math.sin(degInRad) * radius * mmul, + 0); + return vec; +} + +function onmousemove(event) +{ + if (!mouseDown) return; + + const x = event.clientX; + const y = event.clientY; + + let movementX = (x - lastMouseX); + let movementY = (y - lastMouseY); + + movementX *= speedX.get(); + movementY *= speedY.get(); + + if (event.buttons == 2 && allowPanning.get()) + { + vOffset[2] += movementX * 0.01 * mul.get(); + vOffset[1] += movementY * 0.01 * mul.get(); + } + else + if (event.buttons == 4 && allowZooming.get()) + { + radius += movementY * 0.05; + eye = circlePos(percY); + } + else + { + if (allowRotation.get()) + { + percX += movementX * 0.003; + percY += movementY * 0.002; + + if (restricted.get()) + { + if (percY > 0.5)percY = 0.5; + if (percY < -0.5)percY = -0.5; + } + } + } + + lastMouseX = x; + lastMouseY = y; +} + +function onMouseDown(event) +{ + lastMouseX = event.clientX; + lastMouseY = event.clientY; + mouseDown = true; + + try { element.setPointerCapture(event.pointerId); } + catch (e) {} +} + +function onMouseUp(e) +{ + mouseDown = false; + // cgl.canvas.style.cursor='url(/ui/img/rotate.png),pointer'; + + try { element.releasePointerCapture(e.pointerId); } + catch (e) {} +} + +function lockChange() +{ + const el = op.patch.cg.canvas; + + if (document.pointerLockElement === el || document.mozPointerLockElement === el || document.webkitPointerLockElement === el) + { + document.addEventListener("mousemove", onmousemove, false); + } +} + +function onMouseEnter(e) +{ + // cgl.canvas.style.cursor='url(/ui/img/rotate.png),pointer'; +} + +initialRadius.onChange = function () +{ + radius = initialRadius.get(); + reset(); +}; + +initialX.onChange = function () +{ + px = percX = (initialX.get() * Math.PI * 2); +}; + +initialAxis.onChange = function () +{ + py = percY = (initialAxis.get() - 0.5); + eye = circlePos(percY); +}; + +const onMouseWheel = function (event) +{ + if (allowZooming.get()) + { + const delta = CGL.getWheelSpeed(event) * 0.06; + radius += (parseFloat(delta)) * 1.2; + + eye = circlePos(percY); + } +}; + +const ontouchstart = function (event) +{ + if (event.touches && event.touches.length > 0) onMouseDown(event.touches[0]); +}; + +const ontouchend = function (event) +{ + onMouseUp(); +}; + +const ontouchmove = function (event) +{ + if (event.touches && event.touches.length > 0) onmousemove(event.touches[0]); +}; + +active.onChange = function () +{ + if (active.get())bind(); + else unbind(); +}; + +function setElement(ele) +{ + unbind(); + element = ele; + bind(); +} + +function bind() +{ + if (!element) return; + + element.addEventListener("pointermove", onmousemove); + element.addEventListener("pointerdown", onMouseDown); + element.addEventListener("pointerup", onMouseUp); + element.addEventListener("pointerleave", onMouseUp); + element.addEventListener("pointerenter", onMouseEnter); + element.addEventListener("contextmenu", function (e) { e.preventDefault(); }); + element.addEventListener("wheel", onMouseWheel, { "passive": true }); +} + +function unbind() +{ + if (!element) return; + + element.removeEventListener("pointermove", onmousemove); + element.removeEventListener("pointerdown", onMouseDown); + element.removeEventListener("pointerup", onMouseUp); + element.removeEventListener("pointerleave", onMouseUp); + element.removeEventListener("pointerenter", onMouseUp); + element.removeEventListener("wheel", onMouseWheel); +} + +eye = circlePos(0); + +initialX.set(0.25); +initialRadius.set(0.05); + + +}; + +Ops.Gl.Matrix.OrbitControls.prototype = new CABLES.Op(); +CABLES.OPS["eaf4f7ce-08a3-4d1b-b9f4-ebc0b7b1cde1"]={f:Ops.Gl.Matrix.OrbitControls,objName:"Ops.Gl.Matrix.OrbitControls"}; + + + + +// ************************************************************** +// +// Ops.Gl.TextureEffects.Vibrance +// +// ************************************************************** + +Ops.Gl.TextureEffects.Vibrance = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"vibrance_frag":"IN vec2 texCoord;\nUNI sampler2D tex;\nUNI float amount;\n\nconst vec4 lumcoeff = vec4(0.299,0.587,0.114, 0.);\n\nvoid main()\n{\n vec4 col=vec4(1.0,0.0,0.0,1.0);\n col=texture(tex,texCoord);\n\n float luma = dot(col, lumcoeff);\n vec4 mask = (col - vec4(luma));\n mask = clamp(mask, 0.0, 1.0);\n float lumaMask = dot(lumcoeff, mask);\n lumaMask = 1.0 - lumaMask;\n vec4 vibrance = mix(vec4(luma), col, 1.0 + amount * lumaMask);\n outColor= vibrance;\n}",}; +const render = op.inTrigger("Render"); +const trigger = op.outTrigger("Trigger"); +const amount = op.inValue("amount", 2); + +const cgl = op.patch.cgl; +const shader = new CGL.Shader(cgl, op.name); + +shader.setSource(shader.getDefaultVertexShader(), attachments.vibrance_frag); +const textureUniform = new CGL.Uniform(shader, "t", "tex", 0); +const amountUniform = new CGL.Uniform(shader, "f", "amount", amount); + +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpInEffect(op)) return; + + cgl.pushShader(shader); + cgl.currentTextureEffect.bind(); + + cgl.setTexture(0, cgl.currentTextureEffect.getCurrentSourceTexture().tex); + + cgl.currentTextureEffect.finish(); + cgl.popShader(); + + trigger.trigger(); +}; + + +}; + +Ops.Gl.TextureEffects.Vibrance.prototype = new CABLES.Op(); +CABLES.OPS["9c71c980-e439-4397-9c2b-c2ae085eaed9"]={f:Ops.Gl.TextureEffects.Vibrance,objName:"Ops.Gl.TextureEffects.Vibrance"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.FullscreenRectangle +// +// ************************************************************** + +Ops.Gl.Meshes.FullscreenRectangle = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={"shader_frag":"UNI sampler2D tex;\nIN vec2 texCoord;\n\nvoid main()\n{\n outColor= texture(tex,texCoord);\n}\n\n","shader_vert":"{{MODULES_HEAD}}\n\nIN vec3 vPosition;\nUNI mat4 projMatrix;\nUNI mat4 mvMatrix;\n\nOUT vec2 texCoord;\nIN vec2 attrTexCoord;\n\nvoid main()\n{\n vec4 pos=vec4(vPosition, 1.0);\n\n texCoord=vec2(attrTexCoord.x,(1.0-attrTexCoord.y));\n\n gl_Position = projMatrix * mvMatrix * pos;\n}\n",}; +const + render = op.inTrigger("render"), + inScale = op.inSwitch("Scale", ["Stretch", "Fit"], "Fit"), + flipY = op.inValueBool("Flip Y"), + flipX = op.inValueBool("Flip X"), + inTexture = op.inTexture("Texture"), + trigger = op.outTrigger("trigger"); + +const cgl = op.patch.cgl; +let mesh = null; +let geom = new CGL.Geometry("fullscreen rectangle"); +let x = 0, y = 0, z = 0, w = 0, h = 0; + +flipX.onChange = rebuildFlip; +flipY.onChange = rebuildFlip; +render.onTriggered = doRender; +inTexture.onLinkChanged = updateUi; +op.toWorkPortsNeedToBeLinked(render); + +const shader = new CGL.Shader(cgl, "fullscreenrectangle"); +shader.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG"]); + +shader.setSource(attachments.shader_vert, attachments.shader_frag); +shader.fullscreenRectUniform = new CGL.Uniform(shader, "t", "tex", 0); +shader.aspectUni = new CGL.Uniform(shader, "f", "aspectTex", 0); + +let useShader = false; +let updateShaderLater = true; +let fitImageAspect = false; +let oldVp = []; + +updateUi(); + +inTexture.onChange = function () +{ + updateShaderLater = true; +}; + +function updateUi() +{ + if (!CABLES.UI) return; + flipY.setUiAttribs({ "greyout": !inTexture.isLinked() }); + flipX.setUiAttribs({ "greyout": !inTexture.isLinked() }); + inScale.setUiAttribs({ "greyout": !inTexture.isLinked() }); +} + +function updateShader() +{ + let tex = inTexture.get(); + if (tex) useShader = true; + else useShader = false; +} + +op.preRender = function () +{ + updateShader(); + shader.bind(); + if (mesh)mesh.render(shader); + doRender(); +}; + +inScale.onChange = () => +{ + fitImageAspect = inScale.get() == "Fit"; +}; + +function doRender() +{ + if (cgl.getViewPort()[2] != w || cgl.getViewPort()[3] != h || !mesh) rebuild(); + + if (updateShaderLater) updateShader(); + + cgl.pushPMatrix(); + mat4.identity(cgl.pMatrix); + mat4.ortho(cgl.pMatrix, 0, w, h, 0, -10.0, 1000); + + cgl.pushModelMatrix(); + mat4.identity(cgl.mMatrix); + + cgl.pushViewMatrix(); + mat4.identity(cgl.vMatrix); + + if (fitImageAspect && inTexture.get()) + { + const rat = inTexture.get().width / inTexture.get().height; + + let _h = h; + let _w = h * rat; + + if (_w > w) + { + _h = w * 1 / rat; + _w = w; + } + + oldVp[0] = cgl.getViewPort()[0]; + oldVp[1] = cgl.getViewPort()[1]; + oldVp[2] = cgl.getViewPort()[2]; + oldVp[3] = cgl.getViewPort()[3]; + + cgl.setViewPort((w - _w) / 2, (h - _h) / 2, _w, _h); + // cgl.gl.clear(cgl.gl.COLOR_BUFFER_BIT | cgl.gl.DEPTH_BUFFER_BIT); + } + + if (useShader) + { + if (inTexture.get()) + cgl.setTexture(0, inTexture.get().tex); + + mesh.render(shader); + } + else + { + mesh.render(cgl.getShader()); + } + + cgl.gl.clear(cgl.gl.DEPTH_BUFFER_BIT); + + cgl.popPMatrix(); + cgl.popModelMatrix(); + cgl.popViewMatrix(); + + if (fitImageAspect && inTexture.get()) + cgl.setViewPort(oldVp[0], oldVp[1], oldVp[2], oldVp[3]); + + trigger.trigger(); +} + +function rebuildFlip() +{ + mesh = null; +} + +function rebuild() +{ + const currentViewPort = cgl.getViewPort(); + + if (currentViewPort[2] == w && currentViewPort[3] == h && mesh) return; + + let xx = 0, xy = 0; + + w = currentViewPort[2]; + h = currentViewPort[3]; + + geom.vertices = new Float32Array([ + xx + w, xy + h, 0.0, + xx, xy + h, 0.0, + xx + w, xy, 0.0, + xx, xy, 0.0 + ]); + + let tc = null; + + if (flipY.get()) + tc = new Float32Array([ + 1.0, 0.0, + 0.0, 0.0, + 1.0, 1.0, + 0.0, 1.0 + ]); + else + tc = new Float32Array([ + 1.0, 1.0, + 0.0, 1.0, + 1.0, 0.0, + 0.0, 0.0 + ]); + + if (flipX.get()) + { + tc[0] = 0.0; + tc[2] = 1.0; + tc[4] = 0.0; + tc[6] = 1.0; + } + + geom.setTexCoords(tc); + + geom.verticesIndices = new Uint16Array([ + 2, 1, 0, + 3, 1, 2 + ]); + + geom.vertexNormals = new Float32Array([ + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + ]); + geom.tangents = new Float32Array([ + -1, 0, 0, + -1, 0, 0, + -1, 0, 0, + -1, 0, 0]); + geom.biTangents == new Float32Array([ + 0, -1, 0, + 0, -1, 0, + 0, -1, 0, + 0, -1, 0]); + + if (!mesh) mesh = new CGL.Mesh(cgl, geom); + else mesh.setGeom(geom); +} + + +}; + +Ops.Gl.Meshes.FullscreenRectangle.prototype = new CABLES.Op(); +CABLES.OPS["255bd15b-cc91-4a12-9b4e-53c710cbb282"]={f:Ops.Gl.Meshes.FullscreenRectangle,objName:"Ops.Gl.Meshes.FullscreenRectangle"}; + + + + +// ************************************************************** +// +// Ops.Gl.Matrix.TranslateView +// +// ************************************************************** + +Ops.Gl.Matrix.TranslateView = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render=op.inTrigger('render'), + x=op.inValueFloat("x"), + y=op.inValueFloat("y"), + z=op.inValueFloat("z"), + trigger=op.outTrigger('trigger'); + +const cgl=op.patch.cgl; +const vec=vec3.create(); + +render.onTriggered=function() +{ + vec3.set(vec, x.get(),y.get(),z.get()); + cgl.pushViewMatrix(); + mat4.translate(cgl.vMatrix,cgl.vMatrix, vec); + trigger.trigger(); + cgl.popViewMatrix(); +}; + + +}; + +Ops.Gl.Matrix.TranslateView.prototype = new CABLES.Op(); +CABLES.OPS["b15472e2-b895-4dde-95c3-239fa5e08afc"]={f:Ops.Gl.Matrix.TranslateView,objName:"Ops.Gl.Matrix.TranslateView"}; + + + + +// ************************************************************** +// +// Ops.Gl.Texture_v2 +// +// ************************************************************** + +Ops.Gl.Texture_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + filename = op.inUrl("File", [".jpg", ".png", ".webp", ".jpeg", ".avif"]), + tfilter = op.inSwitch("Filter", ["nearest", "linear", "mipmap"]), + wrap = op.inValueSelect("Wrap", ["repeat", "mirrored repeat", "clamp to edge"], "clamp to edge"), + aniso = op.inSwitch("Anisotropic", [0, 1, 2, 4, 8, 16], 0), + flip = op.inValueBool("Flip", false), + unpackAlpha = op.inValueBool("Pre Multiplied Alpha", false), + active = op.inValueBool("Active", true), + inFreeMemory = op.inBool("Save Memory", true), + textureOut = op.outTexture("Texture"), + width = op.outNumber("Width"), + height = op.outNumber("Height"), + ratio = op.outNumber("Aspect Ratio"), + loaded = op.outNumber("Loaded", false), + loading = op.outNumber("Loading", false); + +op.setPortGroup("Size", [width, height]); + +unpackAlpha.setUiAttribs({ "hidePort": true }); + +op.toWorkPortsNeedToBeLinked(textureOut); + +const cgl = op.patch.cgl; + +let loadedFilename = null; +let loadingId = null; +let tex = null; +let cgl_filter = CGL.Texture.FILTER_MIPMAP; +let cgl_wrap = CGL.Texture.WRAP_REPEAT; +let cgl_aniso = 0; +let timedLoader = 0; + +filename.onChange = flip.onChange = function () { reloadSoon(); }; +aniso.onChange = tfilter.onChange = onFilterChange; +wrap.onChange = onWrapChange; +unpackAlpha.onChange = function () { reloadSoon(); }; + +tfilter.set("mipmap"); +wrap.set("repeat"); + +textureOut.set(CGL.Texture.getEmptyTexture(cgl)); + +active.onChange = function () +{ + if (active.get()) + { + if (loadedFilename != filename.get() || !tex) reloadSoon(); + else textureOut.set(tex); + } + else + { + textureOut.set(CGL.Texture.getEmptyTexture(cgl)); + width.set(CGL.Texture.getEmptyTexture(cgl).width); + height.set(CGL.Texture.getEmptyTexture(cgl).height); + if (tex)tex.delete(); + tex = null; + } +}; + +const setTempTexture = function () +{ + const t = CGL.Texture.getTempTexture(cgl); + textureOut.set(t); +}; + +function reloadSoon(nocache) +{ + clearTimeout(timedLoader); + timedLoader = setTimeout(function () + { + realReload(nocache); + }, 30); +} + +function realReload(nocache) +{ + if (!active.get()) return; + // if (filename.get() === null) return; + if (!loadingId)loadingId = cgl.patch.loading.start("textureOp", filename.get()); + + let url = op.patch.getFilePath(String(filename.get())); + + if (nocache)url += "?rnd=" + CABLES.uuid(); + + if (String(filename.get()).indexOf("data:") == 0) url = filename.get(); + + let needsRefresh = false; + if (loadedFilename != filename.get()) needsRefresh = true; + loadedFilename = filename.get(); + + if ((filename.get() && filename.get().length > 1)) + { + loaded.set(false); + loading.set(true); + + const fileToLoad = filename.get(); + + op.setUiAttrib({ "extendTitle": CABLES.basename(url) }); + if (needsRefresh) op.refreshParams(); + + cgl.patch.loading.addAssetLoadingTask(() => + { + op.setUiError("urlerror", null); + + CGL.Texture.load(cgl, url, + function (err, newTex) + { + if (filename.get() != fileToLoad) + { + cgl.patch.loading.finished(loadingId); + loadingId = null; + return; + } + + if (err) + { + setTempTexture(); + op.setUiError("urlerror", "could not load texture: \"" + filename.get() + "\"", 2); + cgl.patch.loading.finished(loadingId); + return; + } + + textureOut.set(newTex); + + width.set(newTex.width); + height.set(newTex.height); + ratio.set(newTex.width / newTex.height); + + // if (!newTex.isPowerOfTwo()) op.setUiError("npot", "Texture dimensions not power of two! - Texture filtering will not work in WebGL 1.", 0); + // else op.setUiError("npot", null); + + if (tex)tex.delete(); + tex = newTex; + textureOut.set(null); + textureOut.set(tex); + + loading.set(false); + loaded.set(true); + + if (inFreeMemory.get()) tex.image = null; + + cgl.patch.loading.finished(loadingId); + }, { + "anisotropic": cgl_aniso, + "wrap": cgl_wrap, + "flip": flip.get(), + "unpackAlpha": unpackAlpha.get(), + "filter": cgl_filter + }); + + // textureOut.set(null); + // textureOut.set(tex); + }); + } + else + { + cgl.patch.loading.finished(loadingId); + setTempTexture(); + } +} + +function onFilterChange() +{ + if (tfilter.get() == "nearest") cgl_filter = CGL.Texture.FILTER_NEAREST; + else if (tfilter.get() == "linear") cgl_filter = CGL.Texture.FILTER_LINEAR; + else if (tfilter.get() == "mipmap") cgl_filter = CGL.Texture.FILTER_MIPMAP; + else if (tfilter.get() == "Anisotropic") cgl_filter = CGL.Texture.FILTER_ANISOTROPIC; + + cgl_aniso = parseFloat(aniso.get()); + + reloadSoon(); +} + +function onWrapChange() +{ + if (wrap.get() == "repeat") cgl_wrap = CGL.Texture.WRAP_REPEAT; + if (wrap.get() == "mirrored repeat") cgl_wrap = CGL.Texture.WRAP_MIRRORED_REPEAT; + if (wrap.get() == "clamp to edge") cgl_wrap = CGL.Texture.WRAP_CLAMP_TO_EDGE; + + reloadSoon(); +} + +op.onFileChanged = function (fn) +{ + if (filename.get() && filename.get().indexOf(fn) > -1) + { + textureOut.set(CGL.Texture.getEmptyTexture(op.patch.cgl)); + textureOut.set(CGL.Texture.getTempTexture(cgl)); + realReload(true); + } +}; + + +}; + +Ops.Gl.Texture_v2.prototype = new CABLES.Op(); +CABLES.OPS["790f3702-9833-464e-8e37-6f0f813f7e16"]={f:Ops.Gl.Texture_v2,objName:"Ops.Gl.Texture_v2"}; + + + + +// ************************************************************** +// +// Ops.Gl.Meshes.Rectangle_v2 +// +// ************************************************************** + +Ops.Gl.Meshes.Rectangle_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + render = op.inTrigger("render"), + trigger = op.outTrigger("trigger"), + width = op.inValue("width", 1), + height = op.inValue("height", 1), + pivotX = op.inSwitch("pivot x", ["left", "center", "right"]), + pivotY = op.inSwitch("pivot y", ["top", "center", "bottom"]), + nColumns = op.inValueInt("num columns", 1), + nRows = op.inValueInt("num rows", 1), + axis = op.inSwitch("axis", ["xy", "xz"], "xy"), + active = op.inValueBool("Active", true), + geomOut = op.outObject("geometry", null, "geometry"); + +geomOut.ignoreValueSerialize = true; + +const cgl = op.patch.cgl; +axis.set("xy"); +pivotX.set("center"); +pivotY.set("center"); + +op.setPortGroup("Pivot", [pivotX, pivotY]); +op.setPortGroup("Size", [width, height]); +op.setPortGroup("Structure", [nColumns, nRows]); +op.toWorkPortsNeedToBeLinked(render); + +const geom = new CGL.Geometry("rectangle"); +let mesh = null; +let needsRebuild = false; + +axis.onChange = + pivotX.onChange = + pivotY.onChange = + width.onChange = + height.onChange = + nRows.onChange = + nColumns.onChange = rebuildLater; +rebuild(); + +function rebuildLater() +{ + needsRebuild = true; +} + +op.preRender = +render.onTriggered = function () +{ + if (!CGL.TextureEffect.checkOpNotInTextureEffect(op)) return; + if (needsRebuild)rebuild(); + if (active.get() && mesh) mesh.render(cgl.getShader()); + trigger.trigger(); +}; + +function rebuild() +{ + let w = width.get(); + let h = parseFloat(height.get()); + let x = 0; + let y = 0; + + if (typeof w == "string")w = parseFloat(w); + if (typeof h == "string")h = parseFloat(h); + + if (pivotX.get() == "center") x = 0; + else if (pivotX.get() == "right") x = -w / 2; + else if (pivotX.get() == "left") x = +w / 2; + + if (pivotY.get() == "center") y = 0; + else if (pivotY.get() == "top") y = -h / 2; + else if (pivotY.get() == "bottom") y = +h / 2; + + const verts = []; + const tc = []; + const norms = []; + const tangents = []; + const biTangents = []; + const indices = []; + + const numRows = Math.round(nRows.get()); + const numColumns = Math.round(nColumns.get()); + + const stepColumn = w / numColumns; + const stepRow = h / numRows; + + let c, r, a; + a = axis.get(); + for (r = 0; r <= numRows; r++) + { + for (c = 0; c <= numColumns; c++) + { + verts.push(c * stepColumn - width.get() / 2 + x); + if (a == "xz") verts.push(0.0); + verts.push(r * stepRow - height.get() / 2 + y); + if (a == "xy") verts.push(0.0); + + tc.push(c / numColumns); + tc.push(1.0 - r / numRows); + + if (a == "xz") + { + norms.push(0, 1, 0); + tangents.push(1, 0, 0); + biTangents.push(0, 0, 1); + } + else if (a == "xy") + { + norms.push(0, 0, 1); + tangents.push(-1, 0, 0); + biTangents.push(0, -1, 0); + } + } + } + + for (c = 0; c < numColumns; c++) + { + for (r = 0; r < numRows; r++) + { + const ind = c + (numColumns + 1) * r; + const v1 = ind; + const v2 = ind + 1; + const v3 = ind + numColumns + 1; + const v4 = ind + 1 + numColumns + 1; + + indices.push(v1); + indices.push(v3); + indices.push(v2); + + indices.push(v2); + indices.push(v3); + indices.push(v4); + } + } + + geom.clear(); + geom.vertices = verts; + geom.texCoords = tc; + geom.verticesIndices = indices; + geom.vertexNormals = norms; + geom.tangents = tangents; + geom.biTangents = biTangents; + + if (numColumns * numRows > 64000)geom.unIndex(); + + if (!mesh) mesh = new CGL.Mesh(cgl, geom); + else mesh.setGeom(geom); + + geomOut.set(null); + geomOut.set(geom); + needsRebuild = false; +} + +op.onDelete = function () +{ + if (mesh)mesh.dispose(); +}; + + +}; + +Ops.Gl.Meshes.Rectangle_v2.prototype = new CABLES.Op(); +CABLES.OPS["fc5718d6-11a5-496e-8f16-1c78b1a2824c"]={f:Ops.Gl.Meshes.Rectangle_v2,objName:"Ops.Gl.Meshes.Rectangle_v2"}; + + + + +// ************************************************************** +// +// Ops.Anim.Timer_v2 +// +// ************************************************************** + +Ops.Anim.Timer_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + inSpeed = op.inValue("Speed", 1), + playPause = op.inValueBool("Play", true), + reset = op.inTriggerButton("Reset"), + inSyncTimeline = op.inValueBool("Sync to timeline", false), + outTime = op.outNumber("Time"); + +op.setPortGroup("Controls", [playPause, reset, inSpeed]); + +const timer = new CABLES.Timer(); +let lastTime = null; +let time = 0; +let syncTimeline = false; + +playPause.onChange = setState; +setState(); + +function setState() +{ + if (playPause.get()) + { + timer.play(); + op.patch.addOnAnimFrame(op); + } + else + { + timer.pause(); + op.patch.removeOnAnimFrame(op); + } +} + +reset.onTriggered = doReset; + +function doReset() +{ + time = 0; + lastTime = null; + timer.setTime(0); + outTime.set(0); +} + +inSyncTimeline.onChange = function () +{ + syncTimeline = inSyncTimeline.get(); + playPause.setUiAttribs({ "greyout": syncTimeline }); + reset.setUiAttribs({ "greyout": syncTimeline }); +}; + +op.onAnimFrame = function (tt) +{ + if (timer.isPlaying()) + { + if (CABLES.overwriteTime !== undefined) + { + outTime.set(CABLES.overwriteTime * inSpeed.get()); + } + else + + if (syncTimeline) + { + outTime.set(tt * inSpeed.get()); + } + else + { + timer.update(); + const timerVal = timer.get(); + + if (lastTime === null) + { + lastTime = timerVal; + return; + } + + const t = Math.abs(timerVal - lastTime); + lastTime = timerVal; + + time += t * inSpeed.get(); + if (time != time)time = 0; + outTime.set(time); + } + } +}; + + +}; + +Ops.Anim.Timer_v2.prototype = new CABLES.Op(); +CABLES.OPS["aac7f721-208f-411a-adb3-79adae2e471a"]={f:Ops.Anim.Timer_v2,objName:"Ops.Anim.Timer_v2"}; + + + + +// ************************************************************** +// +// Ops.Math.MapRange +// +// ************************************************************** + +Ops.Math.MapRange = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + v = op.inValueFloat("value", 0), + old_min = op.inValueFloat("old min", 0), + old_max = op.inValueFloat("old max", 1), + new_min = op.inValueFloat("new min", -1), + new_max = op.inValueFloat("new max", 1), + easing = op.inValueSelect("Easing", ["Linear", "Smoothstep", "Smootherstep"], "Linear"), + result = op.outNumber("result", 0); + +op.setPortGroup("Input Range", [old_min, old_max]); +op.setPortGroup("Output Range", [new_min, new_max]); + +let ease = 0; +let r = 0; + +v.onChange = + old_min.onChange = + old_max.onChange = + new_min.onChange = + new_max.onChange = exec; + +exec(); + +easing.onChange = function () +{ + if (easing.get() == "Smoothstep") ease = 1; + else if (easing.get() == "Smootherstep") ease = 2; + else ease = 0; +}; + +function exec() +{ + const nMin = new_min.get(); + const nMax = new_max.get(); + const oMin = old_min.get(); + const oMax = old_max.get(); + let x = v.get(); + + if (x >= Math.max(oMax, oMin)) + { + result.set(nMax); + return; + } + else + if (x <= Math.min(oMax, oMin)) + { + result.set(nMin); + return; + } + + let reverseInput = false; + const oldMin = Math.min(oMin, oMax); + const oldMax = Math.max(oMin, oMax); + if (oldMin != oMin) reverseInput = true; + + let reverseOutput = false; + const newMin = Math.min(nMin, nMax); + const newMax = Math.max(nMin, nMax); + if (newMin != nMin) reverseOutput = true; + + let portion = 0; + + if (reverseInput) portion = (oldMax - x) * (newMax - newMin) / (oldMax - oldMin); + else portion = (x - oldMin) * (newMax - newMin) / (oldMax - oldMin); + + if (reverseOutput) r = newMax - portion; + else r = portion + newMin; + + if (ease === 0) + { + result.set(r); + } + else + if (ease == 1) + { + x = Math.max(0, Math.min(1, (r - nMin) / (nMax - nMin))); + result.set(nMin + x * x * (3 - 2 * x) * (nMax - nMin)); // smoothstep + } + else + if (ease == 2) + { + x = Math.max(0, Math.min(1, (r - nMin) / (nMax - nMin))); + result.set(nMin + x * x * x * (x * (x * 6 - 15) + 10) * (nMax - nMin)); // smootherstep + } +} + + +}; + +Ops.Math.MapRange.prototype = new CABLES.Op(); +CABLES.OPS["2617b407-60a0-4ff6-b4a7-18136cfa7817"]={f:Ops.Math.MapRange,objName:"Ops.Math.MapRange"}; + + + + +// ************************************************************** +// +// Ops.Math.Compare.IfBetweenThen +// +// ************************************************************** + +Ops.Math.Compare.IfBetweenThen = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exe = op.inTrigger("exe"), + number = op.inValue("number", 0), + min = op.inValue("min", 0), + max = op.inValue("max", 1), + triggerThen = op.outTrigger("then"), + triggerElse = op.outTrigger("else"), + outBetween = op.outBoolNum("bs between"); + +exe.onTriggered = function () +{ + if (number.get() >= min.get() && number.get() < max.get()) + { + outBetween.set(true); + triggerThen.trigger(); + } + else + { + outBetween.set(false); + triggerElse.trigger(); + } +}; + + +}; + +Ops.Math.Compare.IfBetweenThen.prototype = new CABLES.Op(); +CABLES.OPS["c80437f0-f0e1-465c-9cea-8a044aa2feaa"]={f:Ops.Math.Compare.IfBetweenThen,objName:"Ops.Math.Compare.IfBetweenThen"}; + + + + +// ************************************************************** +// +// Ops.Gl.ViewPortSize +// +// ************************************************************** + +Ops.Gl.ViewPortSize = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + exec = op.inTrigger("Exec"), + next = op.outTrigger("Next"), + outX = op.outNumber("X"), + outY = op.outNumber("Y"), + outW = op.outNumber("Width"), + outH = op.outNumber("Height"); + +exec.onTriggered = function () +{ + const vp = op.patch.cgl.getViewPort(); + + outX.set(vp[0]); + outY.set(vp[1]); + outW.set(vp[2]); + outH.set(vp[3]); + + next.trigger(); +}; + + +}; + +Ops.Gl.ViewPortSize.prototype = new CABLES.Op(); +CABLES.OPS["7cb99d8f-d7ef-478e-902b-54e054e387a0"]={f:Ops.Gl.ViewPortSize,objName:"Ops.Gl.ViewPortSize"}; + + + + +// ************************************************************** +// +// Ops.Trigger.SetNumberOnTrigger +// +// ************************************************************** + +Ops.Trigger.SetNumberOnTrigger = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + setValuePort = op.inTriggerButton("Set"), + valuePort = op.inValueFloat("Number"), + outNext = op.outTrigger("Next"), + outValuePort = op.outNumber("Out Value"); + +outValuePort.changeAlways = true; + +setValuePort.onTriggered = function () +{ + outValuePort.set(valuePort.get()); + outNext.trigger(); +}; + + +}; + +Ops.Trigger.SetNumberOnTrigger.prototype = new CABLES.Op(); +CABLES.OPS["9989b1c0-1073-4d5f-bfa0-36dd98b66e27"]={f:Ops.Trigger.SetNumberOnTrigger,objName:"Ops.Trigger.SetNumberOnTrigger"}; + + + + +// ************************************************************** +// +// Ops.Color.HexToRGB_v2 +// +// ************************************************************** + +Ops.Color.HexToRGB_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + hex = op.inString("Hex", "#ff0000"), + asBytes = op.inValueBool("Bytes"), + outR = op.outNumber("R"), + outG = op.outNumber("G"), + outB = op.outNumber("B"); + +function hexToR(h) +{ + return parseInt((cutHex(h)).substring(0, 2), 16) || 0; +} +function hexToG(h) +{ + return parseInt((cutHex(h)).substring(2, 4), 16) || 0; +} +function hexToB(h) +{ + return parseInt((cutHex(h)).substring(4, 6), 16) || 0; +} +function cutHex(h) +{ + return (h.charAt(0) == "#") ? h.substring(1, 7) : h; +} + +hex.onChange = parse; +asBytes.onChange = parse; + +function parse() +{ + let str = hex.get() || ""; + let r = hexToR(str); + let g = hexToG(str); + let b = hexToB(str); + + if (!asBytes.get()) + { + r /= 255; + g /= 255; + b /= 255; + } + + outR.set(r); + outB.set(b); + outG.set(g); +} + + +}; + +Ops.Color.HexToRGB_v2.prototype = new CABLES.Op(); +CABLES.OPS["9877f198-8dac-48e5-9310-244ef1a8dec5"]={f:Ops.Color.HexToRGB_v2,objName:"Ops.Color.HexToRGB_v2"}; + + + + +// ************************************************************** +// +// Ops.String.String_v2 +// +// ************************************************************** + +Ops.String.String_v2 = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + v=op.inString("value",""), + result=op.outString("String"); + +v.onChange=function() +{ + result.set(v.get()); +}; + + + +}; + +Ops.String.String_v2.prototype = new CABLES.Op(); +CABLES.OPS["d697ff82-74fd-4f31-8f54-295bc64e713d"]={f:Ops.String.String_v2,objName:"Ops.String.String_v2"}; + + + + +// ************************************************************** +// +// Ops.Value.Number +// +// ************************************************************** + +Ops.Value.Number = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + v = op.inValueFloat("value"), + result = op.outNumber("result"); + +v.onChange = exec; + +function exec() +{ + result.set(Number(v.get())); +} + + +}; + +Ops.Value.Number.prototype = new CABLES.Op(); +CABLES.OPS["8fb2bb5d-665a-4d0a-8079-12710ae453be"]={f:Ops.Value.Number,objName:"Ops.Value.Number"}; + + + + +// ************************************************************** +// +// Ops.Ui.PatchInput +// +// ************************************************************** + +Ops.Ui.PatchInput = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const dyn = op.addOutPort(new CABLES.Port(op, "create port", CABLES.OP_PORT_TYPE_DYNAMIC)); + +function getPatchOp() +{ + for (let i in op.patch.ops) + { + if (op.patch.ops[i].patchId) + { + if (op.patch.ops[i].patchId.get() == op.uiAttribs.subPatch) + { + return op.patch.ops[i]; + } + } + } +} + +dyn.onLinkChanged = () => +{ + const mySubPatchOp = getPatchOp(); + + if (!dyn.links.length) return; + + const otherPort = dyn.links[0].getOtherPort(dyn); + dyn.removeLinks(); + + const newPortName = mySubPatchOp.addNewInPort(otherPort); + + const l = gui.scene().link( + otherPort.parent, + otherPort.getName(), + op, + newPortName); + + mySubPatchOp.saveData(); +}; + + +}; + +Ops.Ui.PatchInput.prototype = new CABLES.Op(); +CABLES.OPS["e3f68bc3-892a-4c78-9974-aca25c27025d"]={f:Ops.Ui.PatchInput,objName:"Ops.Ui.PatchInput"}; + + + + +// ************************************************************** +// +// Ops.Ui.PatchOutput +// +// ************************************************************** + +Ops.Ui.PatchOutput = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const dyn = op.addInPort(new CABLES.Port(op, "create port", CABLES.OP_PORT_TYPE_DYNAMIC)); + +function getPatchOp() +{ + for (let i in op.patch.ops) + { + if (op.patch.ops[i].patchId) + { + if (op.patch.ops[i].patchId.get() == op.uiAttribs.subPatch) + { + return op.patch.ops[i]; + } + } + } +} + +dyn.onLinkChanged = () => +{ + const mySubPatchOp = getPatchOp(); + + if (!dyn.links.length) return; + + const otherPort = dyn.links[0].getOtherPort(dyn); + dyn.removeLinks(); + + const newPortName = mySubPatchOp.addNewOutPort(otherPort); + + const l = gui.scene().link( + otherPort.parent, + otherPort.getName(), + op, + newPortName); + + mySubPatchOp.saveData(); +}; + + +}; + +Ops.Ui.PatchOutput.prototype = new CABLES.Op(); +CABLES.OPS["851b44cb-5667-4140-9800-5aeb7031f1d7"]={f:Ops.Ui.PatchOutput,objName:"Ops.Ui.PatchOutput"}; + + + + +// ************************************************************** +// +// Ops.Ui.SubPatch +// +// ************************************************************** + +Ops.Ui.SubPatch = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +op.dyn = op.addInPort(new CABLES.Port(op, "create port", CABLES.OP_PORT_TYPE_DYNAMIC)); +op.dynOut = op.addOutPort(new CABLES.Port(op, "create port out", CABLES.OP_PORT_TYPE_DYNAMIC)); + +const dataStr = op.addInPort(new CABLES.Port(op, "dataStr", CABLES.OP_PORT_TYPE_VALUE, { "display": "readonly" })); +op.patchId = op.addInPort(new CABLES.Port(op, "patchId", CABLES.OP_PORT_TYPE_VALUE, { "display": "readonly" })); + +if (CABLES.UI && CABLES.sandbox.isDevEnv()) +{ + const inMakeBp = op.inTriggerButton("Create Blueprint"); + inMakeBp.setUiAttribs({ "hidePort": true }); + + inMakeBp.onTriggered = makeBlueprint; +} + +dataStr.setUiAttribs({ "hideParam": true }); +op.patchId.setUiAttribs({ "hideParam": true }); + +let data = { "ports": [], "portsOut": [] }; +let oldPatchId = CABLES.generateUUID(); +op.patchId.set(oldPatchId); +getSubPatchInputOp(); +getSubPatchOutputOp(); + +let dataLoaded = false; + +op.saveData = saveData; + +op.patchId.onChange = function () +{ + const oldPatchOps = op.patch.getSubPatchOps(oldPatchId); + + if (oldPatchOps.length == 2) + { + for (let i = 0; i < oldPatchOps.length; i++) + { + op.patch.deleteOp(oldPatchOps[i].id); + } + } + else + { + } +}; + +op.onLoaded = function () +{ +}; + +op.onLoadedValueSet = function () +{ + data = JSON.parse(dataStr.get()); + if (!data) + { + data = { "ports": [], "portsOut": [] }; + } + setupPorts(); +}; + +function loadData() +{ +} + +dataStr.onChange = function () +{ + if (dataLoaded) return; + + if (!dataStr.get()) return; + try + { + loadData(); + } + catch (e) + { + op.logError("cannot load subpatch data..."); + op.logError(e); + } +}; + +function saveData() +{ + dataStr.set(JSON.stringify(data)); +} + +op.addPortListener = addPortListener; +function addPortListener(newPort, newPortInPatch) +{ + if (!newPort.hasSubpatchLstener) + { + newPort.hasSubpatchLstener = true; + newPort.addEventListener("onUiAttrChange", function (attribs) + { + if (attribs.title) + { + let i = 0; + for (i = 0; i < data.portsOut.length; i++) + if (data.portsOut[i].name == newPort.name) + data.portsOut[i].title = attribs.title; + + for (i = 0; i < data.ports.length; i++) + if (data.ports[i].name == newPort.name) + data.ports[i].title = attribs.title; + + saveData(); + } + }); + } + + if (newPort.direction == CABLES.PORT_DIR_IN) + { + if (newPort.type == CABLES.OP_PORT_TYPE_FUNCTION) + { + newPort.onTriggered = function () + { + if (newPortInPatch.isLinked()) + newPortInPatch.trigger(); + }; + } + else + { + newPort.onChange = function () + { + newPortInPatch.set(newPort.get()); + if (!newPort.isLinked()) + { + for (let i = 0; i < data.ports.length; i++) + { + if (data.ports[i].name === newPort.name) + { + data.ports[i].value = newPort.get(); + } + } + saveData(); + } + }; + } + } +} + +op.setupPorts = setupPorts; +function setupPorts() +{ + if (!op.patchId.get()) return; + const ports = data.ports || []; + const portsOut = data.portsOut || []; + let i = 0; + + for (i = 0; i < ports.length; i++) + { + if (!op.getPortByName(ports[i].name)) + { + const newPort = op.addInPort(new CABLES.Port(op, ports[i].name, ports[i].type)); + + const patchInputOp = getSubPatchInputOp(); + const newPortInPatch = patchInputOp.addOutPort(new CABLES.Port(patchInputOp, ports[i].name, ports[i].type)); + + newPort.ignoreValueSerialize = true; + newPort.setUiAttribs({ "editableTitle": true }); + if (ports[i].title) + { + newPort.setUiAttribs({ "title": ports[i].title }); + newPortInPatch.setUiAttribs({ "title": ports[i].title }); + } + if (ports[i].objType) + { + newPort.setUiAttribs({ "objType": ports[i].objType }); + newPortInPatch.setUiAttribs({ "objType": ports[i].objType }); + } + if (ports[i].value) + { + newPort.set(ports[i].value); + newPortInPatch.set(ports[i].value); + } + addPortListener(newPort, newPortInPatch); + } + } + + for (i = 0; i < portsOut.length; i++) + { + if (!op.getPortByName(portsOut[i].name)) + { + const newPortOut = op.addOutPort(new CABLES.Port(op, portsOut[i].name, portsOut[i].type)); + const patchOutputOp = getSubPatchOutputOp(); + const newPortOutPatch = patchOutputOp.addInPort(new CABLES.Port(patchOutputOp, portsOut[i].name, portsOut[i].type)); + + newPortOut.ignoreValueSerialize = true; + newPortOut.setUiAttribs({ "editableTitle": true }); + + if (portsOut[i].title) + { + newPortOut.setUiAttribs({ "title": portsOut[i].title }); + newPortOutPatch.setUiAttribs({ "title": portsOut[i].title }); + } + if (portsOut[i].objType) + { + newPortOut.setUiAttribs({ "objType": portsOut[i].objType }); + newPortOutPatch.setUiAttribs({ "objType": portsOut[i].objType }); + } + + // addPortListener(newPortOut,newPortOutPatch); + addPortListener(newPortOutPatch, newPortOut); + } + } + + dataLoaded = true; +} + +op.addNewInPort = function (otherPort, type, objType) +{ + const newName = "in" + data.ports.length + " " + otherPort.parent.name + " " + otherPort.name; + + const o = { "name": newName, "type": otherPort.type }; + if (otherPort.uiAttribs.objType)o.objType = otherPort.uiAttribs.objType; + + data.ports.push(o); + setupPorts(); + return newName; +}; + +op.dyn.onLinkChanged = function () +{ + if (op.dyn.isLinked()) + { + const otherPort = op.dyn.links[0].getOtherPort(op.dyn); + op.dyn.removeLinks(); + otherPort.removeLinkTo(op.dyn); + + op.log("dyn link changed!!!"); + + // const newName = "in" + data.ports.length + " " + otherPort.parent.name + " " + otherPort.name; + + // const o = { "name": newName, "type": otherPort.type }; + // if (otherPort.uiAttribs.objType)o.objType = otherPort.uiAttribs.objType; + // data.ports.push(o); + + // setupPorts(); + + const newName = op.addNewInPort(otherPort); + + const l = gui.scene().link( + otherPort.parent, + otherPort.getName(), + op, + newName + ); + + dataLoaded = true; + saveData(); + } + else + { + setTimeout(function () + { + op.dyn.removeLinks(); + }, 100); + } +}; + +op.addNewOutPort = function (otherPort, type, objType) +{ + const newName = "out" + data.portsOut.length + " " + otherPort.parent.name + " " + otherPort.name; + + const o = { "name": newName, "type": otherPort.type }; + if (otherPort.uiAttribs.objType)o.objType = otherPort.uiAttribs.objType; + + data.portsOut.push(o); + setupPorts(); + return newName; +}; + +op.dynOut.onLinkChanged = function () +{ + if (op.dynOut.isLinked()) + { + const otherPort = op.dynOut.links[0].getOtherPort(op.dynOut); + op.dynOut.removeLinks(); + otherPort.removeLinkTo(op.dynOut); + + const newName = op.addNewOutPort(otherPort); + + gui.scene().link( + otherPort.parent, + otherPort.getName(), + op, + newName + ); + + dataLoaded = true; + saveData(); + } + else + { + setTimeout(function () + { + op.dynOut.removeLinks(); + }, 100); + + op.log("dynOut unlinked..."); + } +}; + +function getSubPatchOutputOp() +{ + let patchOutputOP = op.patch.getSubPatchOp(op.patchId.get(), "Ops.Ui.PatchOutput"); + + if (!patchOutputOP) + { + op.patch.addOp("Ops.Ui.PatchOutput", { "subPatch": op.patchId.get(), "translate": { "x": 0, "y": 0 } }); + patchOutputOP = op.patch.getSubPatchOp(op.patchId.get(), "Ops.Ui.PatchOutput"); + if (!patchOutputOP) op.warn("no patchoutput!"); + } + return patchOutputOP; +} + +function getSubPatchInputOp() +{ + let patchInputOP = op.patch.getSubPatchOp(op.patchId.get(), "Ops.Ui.PatchInput"); + + if (!patchInputOP) + { + op.patch.addOp("Ops.Ui.PatchInput", { "subPatch": op.patchId.get(), "translate": { "x": 0, "y": 0 } }); + patchInputOP = op.patch.getSubPatchOp(op.patchId.get(), "Ops.Ui.PatchInput"); + if (!patchInputOP) op.warn("no patchinput2!"); + } + + return patchInputOP; +} + +op.addSubLink = function (p, p2) +{ + const num = data.ports.length; + const sublPortname = "in" + (num - 1) + " " + p2.parent.name + " " + p2.name; + + if (p.direction == CABLES.PORT_DIR_IN) + { + gui.scene().link( + p.parent, + p.getName(), + getSubPatchInputOp(), + sublPortname + ); + } + else + { + const numOut = data.portsOut.length; + gui.scene().link( + p.parent, + p.getName(), + getSubPatchOutputOp(), + "out" + (numOut - 1) + " " + p2.parent.name + " " + p2.name + ); + } + + const bounds = gui.patchView.getSubPatchBounds(op.patchId.get()); + + getSubPatchInputOp().uiAttr( + { + "translate": + { + "x": bounds.minx, + "y": bounds.miny - 100 + } + }); + + getSubPatchOutputOp().uiAttr( + { + "translate": + { + "x": bounds.minx, + "y": bounds.maxy + 100 + } + }); + saveData(); + return sublPortname; +}; + +op.onDelete = function () +{ + for (let i = op.patch.ops.length - 1; i >= 0; i--) + { + if (op.patch.ops[i] && op.patch.ops[i].uiAttribs && op.patch.ops[i].uiAttribs.subPatch == op.patchId.get()) + { + op.patch.deleteOp(op.patch.ops[i].id); + } + } +}; + +function makeBlueprint() +{ + const bpOp = op.patch.addOp(CABLES.UI.DEFAULTOPNAMES.blueprint); + + bpOp.getPortByName("externalPatchId").set(gui.patchId); + bpOp.getPortByName("subPatchId").set(op.patchId.get()); + bpOp.getPortByName("active").set(true); + + bpOp.uiAttr( + { + "translate": + { + "x": op.uiAttribs.translate.x - 150, + "y": op.uiAttribs.translate.y + } + }); +} + +op.rebuildListeners = () => +{ + op.log("rebuild listeners..."); + + const outop = getSubPatchOutputOp(); + for (let i = 0; i < outop.portsIn.length; i++) + { + if (outop.portsIn[i].isLinked()) + { + addPortListener(outop.portsIn[i], this.portsOut[i]); + } + } +}; + + +}; + +Ops.Ui.SubPatch.prototype = new CABLES.Op(); +CABLES.OPS["84d9a6f0-ed7a-466d-b386-225ed9e89c60"]={f:Ops.Ui.SubPatch,objName:"Ops.Ui.SubPatch"}; + + + + +// ************************************************************** +// +// Ops.Math.Sum +// +// ************************************************************** + +Ops.Math.Sum = function() +{ +CABLES.Op.apply(this,arguments); +const op=this; +const attachments={}; +const + number1 = op.inValueFloat("number1", 1), + number2 = op.inValueFloat("number2", 1), + result = op.outNumber("result"); + +op.setTitle("+"); + +number1.onChange = +number2.onChange = exec; +exec(); + +function exec() +{ + const v = number1.get() + number2.get(); + if (!isNaN(v)) + result.set(v); +} + + +}; + +Ops.Math.Sum.prototype = new CABLES.Op(); +CABLES.OPS["c8fb181e-0b03-4b41-9e55-06b6267bc634"]={f:Ops.Math.Sum,objName:"Ops.Math.Sum"}; + + diff --git a/survey_dashboard/hmc_layout/static/en_files/script.min.js b/survey_dashboard/hmc_layout/static/en_files/script.min.js new file mode 100644 index 0000000..4f7984f --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/script.min.js @@ -0,0 +1,3 @@ +function getHandleBarHtml(e,t){return cables.templates[e]?cables.templates[e](t):(console.log("template not found: "+e),"")}function uuid(){let e=(new Date).getTime();return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{const n=(e+16*Math.random())%16|0;return e=Math.floor(e/16),("x"===t?n:3&n|8).toString(16)})}function getQueryVariable(e){const t=window.location.search.substring(1).split("&");for(let n=0;n{if(e){const n=e.querySelector(".row.pagination");n&&n.remove(),e.innerHTML+=getHandleBarHtml("pagination",t)}});const i=e+" .pagination .tab-bar ";document.querySelectorAll(i+".prev").forEach(e=>{if(e){const t=()=>{const e=Math.max(0,o-n);s(n,e)};e.removeEventListener("pointerdown",t),e.addEventListener("pointerdown",t)}});document.querySelectorAll(i+".next").forEach(e=>{if(e){const i=()=>{const e=Math.min(t.count,o+n);s(n,e)};e.removeEventListener("pointerdown",i),e.addEventListener("pointerdown",i)}});document.querySelectorAll(i+".more").forEach(e=>{if(e){const t=()=>{s(0,0)};e.removeEventListener("pointerdown",t),e.addEventListener("pointerdown",t)}});document.querySelectorAll(i+"li.page").forEach((e,t)=>{e.addEventListener("pointerdown",o=>{let i=t;e.dataset.pageIndex&&(i=Number(e.dataset.pageIndex)-1);s(n,i*n)})})}(CABLES=CABLES||{}).EventTarget=function(){this._eventCallbacks={},this.addEventListener=function(e,t){this._eventCallbacks[e]?this._eventCallbacks[e].push(t):this._eventCallbacks[e]=[t]},this.hasEventListener=this.on=function(e,t){if(e&&t){if(this._eventCallbacks[e]){return-1!=this._eventCallbacks[e].indexOf(t)}}else console.log("hasListener: missing parameters")},this.removeEventListener=function(e,t){if(this._eventCallbacks[e]){const n=this._eventCallbacks[e].indexOf(t);-1==n?console.log("eventlistener "+e+" not found..."):this._eventCallbacks[e].splice(n)}},this.emitEvent=function(e,t,n,o,s,i,a){if(this._eventCallbacks[e])for(let r=0;r
    '+(e.title||"")+'
    '+t+"
    ",e.html&&(n+='
    ',n+='
    ',n+=e.html,n+="
    ",n+="
    ")}const o=ele.byId("results");return o&&(o.innerHTML+=n),t}function getDetailTitle(e){return"
    "+e+"

    "}function getDetail(e,t){return e+": "+t+"
    "}(CABLES=CABLES||{}).getGPU=function(e){const t={};let n=e;n=n.replace("Mesa DRI ",""),n=n.replace("Mesa ",""),n=n.replace("NVIDIA Corporation, ",""),n=n.replace("Intel Open Source Technology Center, ",""),n=n.replace("(R)",""),n=n.replace("(TM)",""),n=n.replace("Direct3D11 vs_5_0 ps_5_0)",""),n=n.replace("Direct3D11 vs_4_1 ps_4_1)",""),n=n.replace("OpenGL Engine",""),n=n.replace("/PCIe/SSE2",""),n=n.replace("X.Org, ",""),n=n.replace("ATI Radeon","Radeon"),n=n.replace("with Max-Q Design",""),n=n.replace("Series",""),n=n.replace(" "," ");let o=n.split(/[,(/)]/),s=null;for(let e=0;e-1&&(i="Nvidia"),e.toLowerCase().indexOf("geforce")>-1&&(i="Nvidia"),e.toLowerCase().indexOf("radeon")>-1&&(i="AMD"),e.toLowerCase().indexOf("amd ")>-1&&(i="AMD"),e.toLowerCase().indexOf("intel")>-1&&(i="Intel"),e.toLowerCase().indexOf("swiftshader")>-1&&(i="Google"),e.toLowerCase().indexOf("adreno")>-1&&(i="Qualcom"),e.toLowerCase().indexOf("mali-")>-1&&(i="ARM"),e.toLowerCase().indexOf("apple")>-1&&(i="Apple"),t.vendor=i,e.toLowerCase().indexOf("swiftshader")>-1&&(t.software=!0),t},CABLES.Browser={};const tests=[function(){logResult.browser=platform.name,logResult.browser_version=platform.version;showResult({hide:!0,title:"browser",info:platform.name+" "+platform.version,html:""})},function(){let e="";platform.os&&(platform.os.family&&(e+=platform.os.family+" ",logResult.os_family=platform.os.family),platform.os.version&&(e+=platform.os.version+" ",logResult.os_version=platform.os.version),platform.os.architecture&&(e+=platform.os.architecture+"bit ",logResult.os_architecture=platform.os.architecture),platform.product&&(e+="("+platform.product+")",logResult.product=platform.product)),logResult.language=navigator.language||navigator.userLanguage,showResult({hide:!0,title:"OS",info:e})},function(){let e,t,n;try{e=document.createElement("canvas");let o=0;if(t=e.getContext("webgl2",e),t?o=2:(t=e.getContext("webgl",e)||e.getContext("experimental-webgl",e),o=1),t){let s="";logResult.webgl_versionNum=o,n=t.getSupportedExtensions();const i=t.getParameter(t.VERSION);logResult.webgl_version=i;const a=t.getParameter(t.SHADING_LANGUAGE_VERSION);logResult.webgl_glsl_version=a;const r=t.getExtension("WEBGL_debug_renderer_info");if(r){const e=t.getParameter(r.UNMASKED_RENDERER_WEBGL);logResult.webgl_renderer=e,logResult.webgl_gpu_info=CABLES.getGPU(e),console.log(logResult.webgl_gpu_info);const n=t.getParameter(r.UNMASKED_VENDOR_WEBGL);logResult.webgl_vendor=n}e=document.createElement("canvas");const l=e.getContext("webgl",{failIfMajorPerformanceCaveat:!0})||e.getContext("experimental-webgl",{failIfMajorPerformanceCaveat:!0});logResult.webgl_majorPerformanceCaveat=!l,logResult.webgl_params={},void 0!==t.MAX_SAMPLES&&(logResult.webgl_params.MAX_SAMPLES=t.getParameter(t.MAX_SAMPLES)),logResult.webgl_params.MAX_FRAGMENT_UNIFORM_VECTORS=t.getParameter(t.MAX_FRAGMENT_UNIFORM_VECTORS),logResult.webgl_params.MAX_VERTEX_UNIFORM_VECTORS=t.getParameter(t.MAX_VERTEX_UNIFORM_VECTORS),logResult.webgl_params.MAX_TEXTURE_SIZE=t.getParameter(t.MAX_TEXTURE_SIZE),logResult.webgl_params.DEPTH_BITS=t.getParameter(t.DEPTH_BITS),logResult.webgl_params.MAX_VARYING_VECTORS=t.getParameter(t.MAX_VARYING_VECTORS),logResult.webgl_params.MAX_VERTEX_ATTRIBS=t.getParameter(t.MAX_VERTEX_ATTRIBS),logResult.webgl_params.MAX_COMBINED_TEXTURE_IMAGE_UNITS=t.getParameter(t.MAX_COMBINED_TEXTURE_IMAGE_UNITS),logResult.webgl_params.MAX_VERTEX_TEXTURE_IMAGE_UNITS=t.getParameter(t.MAX_VERTEX_TEXTURE_IMAGE_UNITS),logResult.webgl_params.MAX_RENDERBUFFER_SIZE=t.getParameter(t.MAX_RENDERBUFFER_SIZE);const c=t.getExtension("WEBGL_draw_buffers");if(c?logResult.webgl_params.MAX_DRAW_BUFFERS=t.getParameter(c.MAX_DRAW_BUFFERS_WEBGL):void 0!==t.MAX_DRAW_BUFFERS&&(logResult.webgl_params.MAX_DRAW_BUFFERS=t.getParameter(t.MAX_DRAW_BUFFERS)),n&&0!==n.length){logResult.webgl_extensions=n;for(let e=0;e"}else;showResult({success:!0,title:"WebGL",info:"WebGL "+o,html:s})}else logResult.webgl_versionNum=0,showResult({success:!1,title:"webgl"})}catch(e){return}e=void 0},async function(){let e=null!=navigator.gpu;if(e||showResult({title:"WebGPU",success:!1}),logResult.api_webGpu=e,navigator.gpu){let t=null;try{t=await navigator.gpu.requestAdapter()}catch(e){console.log("webgpu ex",e),t=null}e=!!t,showResult({title:"WebGPU",success:e}),logResult.api_webGpu=e}},function(){let e=null!=window.VideoEncoder;showResult({title:"WebGPU",success:e}),logResult.api_webCodecs=e},function(){logResult.display_pixel_ratio=window.devicePixelRatio,window.devicePixelRatio&&(logResult.display_pixel_ratio_float=window.devicePixelRatio.toPrecision(2)),logResult.window_size_width=window.innerWidth,logResult.window_size_height=window.innerHeight,logResult.window_size_pixel_width=window.innerWidth*window.devicePixelRatio,logResult.window_size_pixel_height=window.innerHeight*window.devicePixelRatio,logResult.screen_size_width=window.screen.availWidth,logResult.screen_size_height=window.screen.availHeight;let e="";e+=getDetail("Device Pixel Ratio",window.devicePixelRatio),e+=getDetail("Screen Size",window.screen.availWidth+" x "+window.screen.availHeight),e+=getDetail("Window Size",window.innerWidth+" x "+window.innerHeight),e+=getDetail("Window Size Pixels",window.innerWidth*window.devicePixelRatio+" x "+window.innerHeight*window.devicePixelRatio),showResult({title:"Screen",info:window.innerWidth+" x "+window.innerHeight,html:e})},function(){const e=!!navigator.getGamepads;logResult.api_gamepad=e,showResult({success:e,title:"Gamepad API"});const t=navigator.getGamepads?navigator.getGamepads():navigator.webkitGetGamepads?navigator.webkitGetGamepads:[];for(let e=0;e3)return"oops";o=o||"";for(const e in n)if("parent"!=e)if(n[e]&&"number"!=typeof n[e]&&"boolean"!=typeof n[e]&&"string"!=typeof n[e])if(Array.isArray(n[e])){let t="";try{t=JSON.stringify(n[e])}catch(n){}o+=""+e+""+t+""}else{if(!n[e].constructor)return;t="["+typeof n[e]+"] ";const s=n[e].constructor;s.name&&"Function"!=s.name&&(t+=s.name),o+=""+e+""+t+""}else o+=""+e+'',CABLES.lastBrowserEvent[n.type]&&CABLES.lastBrowserEvent[n.type][e]==n[e]||(o+=""),o+=n[e],CABLES.lastBrowserEvent[n.type]&&CABLES.lastBrowserEvent[n.type][e]==n[e]||(o+=""),o+="";return CABLES.lastBrowserEvent[n.type]=n,o}function logBrowserEvent(e){e.preventDefault();CABLES.browserEventHistory.unshift(e.type),CABLES.browserEventHistory.length>50&&(CABLES.browserEventHistory.length=50);let t="";for(let e=0;e";document.getElementById("history").innerHTML=t;let n="";return n+="

    "+e.type+"


    ",n+="",n+=logEventObject(e,e,"",0),n+="
    ",document.getElementById("output").innerHTML=n,!1}function initBrowserEvents(){document.getElementById("results").innerHTML="",window.addEventListener("load",logBrowserEvent),window.addEventListener("gamepadconnected",logBrowserEvent),window.addEventListener("DOMContentLoaded",logBrowserEvent),window.addEventListener("gamepadconnected",logBrowserEvent),window.addEventListener("gamepaddisconnected",logBrowserEvent),document.addEventListener("keydown",logBrowserEvent),document.addEventListener("keyup",logBrowserEvent),document.addEventListener("scroll",logBrowserEvent),document.getElementById("input").addEventListener("focus",logBrowserEvent),document.getElementById("input").addEventListener("blur",logBrowserEvent),document.getElementById("input").addEventListener("contextmenu",logBrowserEvent),document.getElementById("input").addEventListener("mouseenter",logBrowserEvent),document.getElementById("input").addEventListener("mouseleave",logBrowserEvent),document.getElementById("input").addEventListener("mousemove",logBrowserEvent),document.getElementById("input").addEventListener("pointerenter",logBrowserEvent),document.getElementById("input").addEventListener("pointerleave",logBrowserEvent),document.getElementById("input").addEventListener("pointermove",logBrowserEvent),document.getElementById("input").addEventListener("mousedown",logBrowserEvent),document.getElementById("input").addEventListener("mouseup",logBrowserEvent),document.getElementById("input").addEventListener("pointerdown",logBrowserEvent),document.getElementById("input").addEventListener("pointerup",logBrowserEvent),document.getElementById("input").addEventListener("click",logBrowserEvent),document.getElementById("input").addEventListener("dblclick",logBrowserEvent),document.getElementById("input").addEventListener("wheel",logBrowserEvent),document.getElementById("input").addEventListener("touchmove",logBrowserEvent),document.getElementById("input").addEventListener("touchstart",logBrowserEvent),document.getElementById("input").addEventListener("touchend",logBrowserEvent)}function saveDoc(e){CABLES.api.post("doc/ops/edit/"+e,{content:editor.getValue()},(function(e){console.log("res",e),e.success?document.getElementById("save_status").innerHTML="  saved...":document.getElementById("save_status").innerHTML="  not saved :/",setTimeout((function(){document.getElementById("save_status").innerHTML=""}),500)}),(function(e){console.log("err res",e)}))}CABLES.doBrowserTest=async function(e){for(const e in tests)await tests[e]();CABLES.CLIENT.COOKIES.createCookie("browserinfo",!0,100),CABLES.api.post("browser",{browser:logResult},t=>{console.log(t);const n=document.getElementById("resultIframe");n&&(n.src="/browser/r/"+t.id);const o=document.getElementsByTagName("head");if(o&&o.length>0){const e=document.createElement("base");e.setAttribute("target","_parent"),o[0].appendChild(e)}const s=document.getElementsByTagName("footer");s&&s.length>0&&s[0].remove(),e&&e(t)})},CABLES.doBrowserSpeedTest=function(e){function t(e){let t="abcdefghijklmnopqrstuvwxyz".split(""),n=t.length,o=[];for(;e--;)o.push(t[Math.random()*n|0]);return o.join("")}function n(e,t,n,o){const s=n.dir,i=document.getElementById("speedtestResult").querySelector(".results");if(n.result.clientDiff){i.querySelector("."+e+" .client .time").innerHTML=parseInt(n.result.clientDiff)+"ms";const o=i.querySelector("."+e+" .client .speed");o.innerHTML=parseInt(Number(n.result.clientDiff-n.result.diff))+"ms";const s=8*t/1024/1024/(n.result.clientDiff/1e3);o.innerHTML=s.toFixed(2)+" mbit/s"}if(n.result.hasOwnProperty("processingTime")){i.querySelector("."+e+" .servertime").innerHTML=parseInt(n.result.processingTime)+"ms"}if(s){if(o){const e=ele.byQuery("."+s+" .loading");e&&ele.hide(e)}ele.byQueryAll("."+s+" .result").forEach(e=>{ele.show(e)})}}function o(e){CABLES.stopSavingAnimButton();const t=document.getElementById("speedtestResult").querySelector(".error");if(t){t.classList.remove("hidden");const n=t.querySelector(".message");n&&(n.innerHTML="error during speedtest:"+e)}}CABLES.startSavingAnimButton(e);const s={};ele.byQueryAll(".results .result").forEach(e=>{ele.hide(e)});ele.byQueryAll(".results .loading").forEach(e=>{ele.show(e)});document.getElementById("speedtestResult").querySelector(".results").classList.remove("hidden");const i=performance.now(),a=Date.now();fetch("/test_files/onemb.txt?cb="+a).then(e=>e.text()).then(()=>{let e=performance.now(),r={};r.clientStart=i,r.clientEnd=e,r.clientDiff=e-i,s.fetchDirectSmall={dir:"downdirect",size:"small",result:r},n("downdirectsmall",1048576,s.fetchDirectSmall);const l=performance.now();CABLES.api.get("browser/download/small?cb="+a,e=>{const i=performance.now();r={},e.data&&(r=e.data),e.data.data&&delete e.data.data,r.clientStart=l,r.clientEnd=i,r.clientDiff=i-l,s.fetchSmall={dir:"down",size:"small",result:r},n("downsmall",1048576,s.fetchSmall);const c=performance.now();fetch("/test_files/tenmb.txt?cb="+a).then(e=>e.text()).then(()=>{const e=performance.now();r={},r.clientStart=c,r.clientEnd=e,r.clientDiff=e-c,s.fetchDirectBig={dir:"downdirect",size:"big",result:r},n("downdirectbig",10485760,s.fetchDirectBig,!0);const i=performance.now();CABLES.api.get("browser/download/big?cb="+a,e=>{const a=performance.now();r={},e.data&&(r=e.data),e.data.data&&delete e.data.data,r.clientStart=i,r.clientEnd=a,r.clientDiff=a-i,s.fetchBig={dir:"down",size:"big",result:r},n("downbig",10485760,s.fetchBig,!0);let l={data:t(1048576)};const c=performance.now();CABLES.api.post("browser/upload/small",l,e=>{const i=performance.now();r={},e.data&&(r=e.data),e.data.data&&delete e.data.data,r.clientStart=c,r.clientEnd=i,r.clientDiff=i-c,s.upSmall={dir:"up",size:"small",result:r},n("upsmall",1048576,s.upSmall),l={data:t(10485760)};const a=performance.now();CABLES.api.post("browser/upload/big",l,e=>{const t=performance.now();r={},e.data&&(r=e.data),e.data.data&&delete e.data.data,r.clientStart=a,r.clientEnd=t,r.clientDiff=t-a,s.upBig={dir:"up",size:"big",result:r},n("upbig",10485760,s.upBig,!0),CABLES.stopSavingAnimButton(),CABLES.api.post("browser/speedtest",s)},o)},o)},o)},o)},o)},o)},CABLES.Browser.browserCounter=0,(CABLES=CABLES||{}).lastBrowserEvent={},CABLES.browserEventHistory=[],(CABLES=CABLES||{}).startSavingAnimButton=e=>{if(!e.classList.contains("buttonSavingAnim")){CABLES.buttonSavingEle=e,CABLES.buttonSavingText=e.innerText,e.innerText="Working...";const t=document.createElement("span");t.classList.add("icon-loader"),t.classList.add("icon"),t.classList.add("icon-0_75x"),t.style["margin-left"]="10px",e.classList.add("buttonSavingAnim"),e.appendChild(t),CABLES.buttonSavingStart=performance.now()}},CABLES.stopSavingAnimButton=(e=!0)=>{if(performance.now()-CABLES.buttonSavingStart<200)return void setTimeout(()=>{CABLES.stopSavingAnimButton()},50);const t=document.querySelectorAll(".buttonSavingAnim .icon-loader"),n=document.querySelectorAll(".buttonSavingAnim");if(CABLES.buttonSavingEle&&(e&&(CABLES.buttonSavingEle.innerText="Done !"),setTimeout(()=>{CABLES.buttonSavingEle.innerText=CABLES.buttonSavingText},400)),n)for(let e=0;e":function(e,t){return e>t},"<=":function(e,t){return e<=t},">=":function(e,t){return e>=t},typeof:function(e,t){return typeof e==t}},!s[t])throw new Error("Handlerbars Helper 'compare' doesn't know the operator "+t);return i=s[t](e,n),!0===i?o.fn(this):o.inverse(this)})),Handlebars.registerHelper("paginationLoop",(function(e){let t=Number(this.currentPage)||0,n=t+19;n>this.pages&&(n=this.pages);let o=t-10;o<1&&(o=1);t+19>this.pages&&(o=this.pages-19),o<1&&(o=1);let s="",i=0;for(let t=o;t<=n&&!(i>19);t++){let a=t===n;19===i&&(a=!0),s+=e.fn({page:t,last:a,first:t==o}),i++}return s}))),(CABLES=CABLES||{}).CLIENT=CABLES.CLIENT||{},CABLES.CLIENT.COOKIES=CABLES.CLIENT.COOKIES||{},CABLES.CLIENT.COOKIES.KEYS=CABLES.CLIENT.COOKIES.KEYS={},CABLES.CLIENT.COOKIES.KEYS.ACCEPTED="accepted",CABLES.CLIENT.COOKIES.createCookie=function(e,t,n){let o="";if(n){const e=new Date;e.setTime(e.getTime()+24*n*60*60*1e3),o="; expires="+e.toUTCString()}document.cookie=e+"="+t+o+"; path=/; secure=true; SameSite=lax"},CABLES.CLIENT.COOKIES.readCookie=function(e){const t=e+"=",n=document.cookie.split(";");for(let e=0;e0?t[0]:null}byClassAll(e){e&&"."==e[0]&&console.warn("ele.byClassAll should not contain .");const t=document.getElementsByClassName(e);return t||[]}forEachClass(e,t){e&&"."==e[0]&&console.warn("ele.forEachClass should not contain .");const n=document.getElementsByClassName(e);for(let e=0;e';let o=e._id;e.shortId&&(o=e.shortId),ele.byId("open-project-button").setAttribute("href","/edit/"+o)}function getEmptyExample(){return{_id:null,name:"",tags:[],description:""}}function replaceDescription(e){e||(e=""),ele.byId("example-description").innerHTML=marked(e)}function replaceTags(e){const t=ele.byQuery(".tag-list-wrapper");if(t){if(t.innerHTML="",!e||0===e.length)return;e.forEach((function(e){const n=document.createElement("a");n.setAttribute("href","/tag/"+e),n.classList.add("tag"),n.innerHTML=e,t.appendChild(n)}))}}function updateState(e,t){if(e){if(window.hasOwnProperty("history")){const n={exampleName:e,exampleId:t},o="/examples/"+encodeURIComponent(e.trim());window.history.pushState(n,null,o),CABLES.EXAMPLES.state=n}}else console.error("no example name")}function handleExampleLinkClick(e){e.preventDefault(),e.stopPropagation();const t=e.target.dataset.id;return t!==CABLES.EXAMPLES.state.exampleId&&loadExampleAndShow(t,!0),!1}function loadExampleAndShow(e,t){e?CABLES.api.get("project/"+e,(function(e){showExample(e,t)})):showExample(getEmptyExample(),t)}function dataUriToFormData(e,t){let n;n=e.split(",")[0].indexOf("base64")>=0?atob(e.split(",")[1]):unescape(e.split(",")[1]);const o=e.split(",")[0].split(":")[1].split(";")[0],s=new Uint8Array(n.length);for(let e=0;e-1&&document.addEventListener("DOMContentLoaded",()=>{const e=ele.byId("example-page");CABLES.EXAMPLES.state={exampleName:e.dataset.exampleName,exampleId:e.dataset.exampleId},e.dataset.exampleName?CABLES.api.get("project/"+CABLES.EXAMPLES.state.exampleId,(function(e){showExample(e,!1)})):(CABLES.API.getExamples({selector:"#example-thumbs"}),window.history.pushState(CABLES.EXAMPLES.state,null,window.location.href),window.addEventListener("popstate",handlePopState)),ele.byQueryAll(".example-link").forEach(e=>{e.addEventListener("pointerdown",handleExampleLinkClick)}),ele.byQueryAll(".example-link-unsorted").forEach(e=>{e.addEventListener("pointerdown",handleExampleLinkClick)})}),CABLES.exportDialog=class{constructor(e){this._id=e,this._currentTab="",this.setTab("download")}setTab(e){this._currentTab&&(ele.hide(ele.byId("tab_"+this._currentTab)),ele.byId("tabitem_"+this._currentTab).classList.remove("active")),ele.show(ele.byId("tab_"+e)),ele.byId("tabitem_"+e).classList.add("active"),this._currentTab=e,window.location.hash="t="+e;let t="Export ZIP File";"netlify"===e&&(t="Deploy to Netlify"),"github"===e&&(t="Deploy to Github"),"exe"===e&&(t="Build Executable"),ele.byId("exportbutton").value=t,ele.byId("deploymentbutton").value="View Deployment",ele.byId("overviewbutton").innerHTML="Deployments overview","cmdline"===e||"iframe"===e?(ele.hide(ele.byId("exportoptions")),ele.hide(ele.byId("exportbutton"))):(ele.show(ele.byId("exportbutton")),ele.show(ele.byId("exportoptions"))),ele.byQueryAll(".exportOptionPanel").forEach(e=>{ele.hide(e)}),ele.show(ele.byId("export_options_"+this._currentTab))}_exportFinished(e,t){ele.hide(ele.byId("export_loading")),e&&(alert("export error"),console.log(e)),ele.byId("export_log").innerHTML=t.log||t.message,t.urls&&(t.urls.downloadUrl?(ele.show(ele.byId("downloadbutton")),ele.byId("downloadbutton").setAttribute("href",t.urls.downloadUrl)):ele.hide(ele.byId("downloadbutton")),t.urls.deploymentUrl?(ele.show(ele.byId("deploymentbutton")),ele.byId("deploymentbutton").setAttribute("href",t.urls.deploymentUrl)):ele.hide(ele.byId("deploymentbutton")),t.urls.overviewUrl?(ele.show(ele.byId("overviewbutton")),ele.byId("overviewbutton").setAttribute("href",t.urls.overviewUrl)):ele.hide(ele.byId("overviewbutton"))),ele.hide(ele.byId("export_dialog")),ele.show(ele.byId("export_result"))}export(){ele.hide(ele.byId("export_dialog")),ele.show(ele.byId("export_loading"));let e="project/"+this._id+"/export?a=1";e+="&type="+this._currentTab,e+="&assets="+ele.byId("export_settings_assets").value,"none"===ele.byId("export_settings_assets").value&&(e+="&ignoreAssets=true"),"single"===ele.byId("export_settings_combine").value&&(e+="&combineJS=true"),ele.byId("export_settings_skip_backups").checked&&(e+="&skipBackups=true"),ele.byId("export_settings_flat").checked&&(e+="&flat=true");document.querySelectorAll("#export_options_"+this._currentTab+" .exportOption").forEach(t=>{e+="&"+t.dataset.name+"="+encodeURIComponent(t.value)}),CABLES.api.get(e,e=>{this._exportFinished(null,e)},e=>{this._exportFinished(e,e)})}},CABLES.invitations=CABLES.invitations||{},CABLES.invitations.acceptPatchInvitation=function(e,t=null,n=!1){CABLES.api.post("patchinvite/"+e+"/accepted",{readOnly:n},(function(){t?window.location.href=t:window.location.reload()}),(function(){t?window.location.href=t:window.location.reload()}))},CABLES.invitations.declinePatchInvitation=function(e,t=null){CABLES.api.post("patchinvite/"+e+"/declined",{},(function(){t?window.location.href=t:window.location.reload()}),(function(){t?window.location.href=t:window.location.reload()}))},CABLES.invitations.leaveProject=function(e,t=null){confirm("really remove yourself as collaborator?")&&CABLES.api.patch("project/leave/"+e,{},(function(){t?window.location.href=t:window.location.reload()}),(function(e){alert("ERROR: "+e.msg)}))},CABLES.invitations.acceptTeamInvitation=function(e,t=null,n=!1){CABLES.api.post("teaminvites/"+e+"/accepted",{readOnly:n},(function(){t?window.location.href=t:window.location.reload()}),(function(){t?window.location.href=t:window.location.reload()}))},CABLES.invitations.declineTeamInvitation=function(e,t=null){CABLES.api.post("teaminvites/"+e+"/declined",{},(function(){t?window.location.href=t:window.location.reload()}),(function(){t?window.location.href=t:window.location.reload()}))},CABLES.API.requestPatchAccess=function(e){CABLES.api.post("patchinvite/request/"+e,{},e=>{ele.hide(ele.byId("request-access-button")),ele.show(ele.byId("request-pending-button"))})},CABLES.API.requestTeamAccess=function(e,t=!1){const n={};t&&(n.permission=t),CABLES.api.post("teaminvites/request/"+e,n,e=>{ele.hide(ele.byId("request-access-button")),ele.show(ele.byId("request-pending-button"))})},(CABLES=CABLES||{}).lazyLoad=function(){CABLES.revalidateLazyLoad(),setTimeout((function(){CABLES.revalidateLazyLoad()}),100),setTimeout((function(){CABLES.revalidateLazyLoad()}),500)},CABLES.revalidateLazyLoad=function(){CABLES.blazy.revalidate();document.querySelectorAll(".ribbon--example").forEach(e=>{e.dataset.hasOwnProperty("exampleFor")&&e.dataset.exampleFor&&e.addEventListener("click",()=>{window.location.href="/op/"+e.dataset.exampleFor})});document.querySelectorAll(".ribbon--featured").forEach(e=>{e.addEventListener("click",()=>{window.location.href="/patches?s=&w=featured"})})},CABLES.ajaxLogin=function(){const e={username:ele.byId("login_username").value,password:ele.byId("login_password").value};CABLES.api.post("loginajax",e,(function(e){if(e.success){const e=ele.byId("successRedir");e&&(e.value=document.location.pathname),ele.byId("loginform").submit()}else{let t="Login failed";e.error&&(t+=": "+e.error);const n=ele.byQuery(".errors_login");n.style.display="block",n.innerHTML="",n.innerHTML=t}}),(function(e){const t=ele.byQuery(".errors_login");t.style.display="block",t.innerHTML="",t.innerHTML="something went wrong... no success"}))},CABLES.signup=function(){const e={username:ele.byId("username").value,password:ele.byId("password").value,email:ele.byId("email").value,newsletter:document.getElementById("newslettercheckbox").checked},t=ele.byId("secret");if(t&&(e.secred=t.value),!document.getElementById("privacycheckbox").checked)return ele.byQuery(".errors_signup").style.display="block",void(ele.byQuery(".errors_signup").innerHTML="Please read and accept the privacy policy");ele.byQuery(".errors_signup").style.display="none",ele.byQuery(".errors_signup").innerHTML="",CABLES.api.post("user/signup",e,(function(e){"SUCCESS"==e.status&&e.goto?ele.byQuery(".tab_content_signup").innerHTML='
    Thank you for signing up!

    Please check your inbox to confirm your email.
    After that you can login
    ':(ele.byQuery(".errors_signup").style.display="block",ele.byQuery(".errors_signup").innerHTML="",ele.byQuery(".errors_signup").innerHTML="something went wrong... no success "+e.errors)}),(function(e){if(ele.byQuery(".errors_signup").style.display="block",ele.byQuery(".errors_signup").innerHTML="",e.errors&&e.errors.length>0){if(e.errors.includes("MAINTENANCE_MODE")||(ele.byQuery(".errors_signup").innerHTML="Please check your data:

    "),e.errors)for(const t in e.errors)"EMAIL_INVALID"===e.errors[t]?ele.byQuery(".errors_signup").innerHTML+="- This is not a valid email
    ":"PASSWORD_TOO_SHORT"===e.errors[t]?ele.byQuery(".errors_signup").innerHTML+="- Please use a longer password
    ":"USERNAME_TOO_SHORT"===e.errors[t]?ele.byQuery(".errors_signup").innerHTML+="- Please use a longer username
    ":"EMAIL_EXISTS"===e.errors[t]?ele.byQuery(".errors_signup").innerHTML+="- This email is already registered
    ":"USER_EXISTS"===e.errors[t]?ele.byQuery(".errors_signup").innerHTML+="- Username already exists
    ":"INVALID CHARACTERS"===e.errors[t]?ele.byQuery(".errors_signup").innerHTML+="- Please do not use any special characters or spaces in your username
    ":"ERROR_USERNAME_EQUALS_EMAIL"===e.errors[t]?ele.byQuery(".errors_signup").innerHTML+="- Your username cannot be your email-address
    ":"MAINTENANCE_MODE"===e.errors[t]?ele.byQuery(".errors_signup").innerHTML+="cables is currently in maintenance mode,
    please try again later":ele.byQuery(".errors_signup").innerHTML+="- "+e.errors[t]+"
    "}else ele.byQuery(".errors_signup").innerHTML="something went wrong..."}))},CABLES.signupNewsletter=function(){const e={username:ele.byId("username").value,password:ele.byId("password").value,email:ele.byId("email").value},t=ele.byId("secret");t&&(e.secred=t.value),CABLES.api.post("user/signupNewsletter",e,(function(e){"SUCCESS"==e.status&&e.goto?(ele.byQuery(".errors_signup").style.display="none",ele.byQuery(".tab_content_signup").innerHTML="Thank you for signing up! "):(ele.byQuery(".errors_signup").style.display="block",ele.byQuery(".errors_signup").innerHTML="",ele.byQuery(".errors_signup").innerHTML="something went wrong... no success")}),(function(e){if(ele.byQuery(".errors_signup").style.display="block",ele.byQuery(".errors_signup").innerHTML="",e.errors&&e.errors.length>0){ele.byQuery(".errors_signup").innerHTML="please check your data:

    ";for(const t in e.errors)ele.byQuery(".errors_signup").innerHTML+="- "+e.errors[t]+"
    "}else ele.byQuery(".errors_signup").innerHTML+="something went wrong..."}))},CABLES.setResetPassword=function(e,t){const n={password:ele.byId("password").value,hash:ele.byId("hash").value};CABLES.api.post("user/setResetPassword",n,(function(e){e.success?(ele.byQuery(".errors").style.display="block",ele.byQuery(".errors").innerHTML="",ele.byQuery(".tab_content_signup").innerHTML='new password set!

    login now'):(ele.byQuery(".errors").style.display="block",ele.byQuery(".errors").innerHTML="",ele.byQuery(".errors").innerHTML="something went wrong... no success")}),(function(e){if(ele.byQuery(".errors").style.display="block",ele.byQuery(".errors").innerHTML="",e.errors&&e.errors.length>0){e.errors.includes("USER_LOGGED_IN")||(ele.byQuery(".errors").innerHTML="please check your data:

    ");for(const t in e.errors)"USER_LOGGED_IN"===e.errors[t]?ele.byQuery(".errors").innerHTML+="you are currently logged in, log out to reset your password":ele.byQuery(".errors").innerHTML+="- "+e.errors[t]+"
    "}else ele.byQuery(".errors").innerHTML+="something went wrong..."}))},CABLES.resetPassword=function(){const e={email:ele.byId("email").value};CABLES.api.post("user/resetPassword",e,(function(e){e.success?(ele.byQuery(".errors").style.display="block",ele.byQuery(".errors").innerHTML="",ele.byQuery(".errors").innerHTML="password reset email sent!",ele.byId("resetpasswdbutton").style.display="none",ele.byId("email").style.display="block"):(ele.byQuery(".errors").style.display="block",ele.byQuery(".errors").innerHTML="",ele.byQuery(".errors").innerHTML="something went wrong... no success")}),(function(e){if(ele.byQuery(".errors").style.display="block",ele.byQuery(".errors").innerHTML="",e.errors&&e.errors.length>0){e.errors.includes("USER_LOGGED_IN")||(ele.byQuery(".errors").innerHTML="please check your data:

    ");for(const t in e.errors)"USER_LOGGED_IN"===e.errors[t]?ele.byQuery(".errors").innerHTML+="you are currently logged in, log out to reset your password":ele.byQuery(".errors").innerHTML+="- "+e.errors[t]+"
    "}else ele.byQuery(".errors").innerHTML+="something went wrong..."}))},CABLES.resendConfirmEmail=function(){const e={email:ele.byId("email").value};CABLES.api.post("send_confirm/",e,(function(e){e.success?(ele.byId("result").innerHTML="password reset email sent!",ele.byId("form").style.display="none"):(ele.byId("result").innerHTML="something went wrong... no success",ele.byId("form").style.display="none")}),(function(e){ele.byId("result").innerHTML="something went wrong... no success",ele.byId("form").style.display="none"}))},CABLES.showInfoBar=function(e,t){const n=document.getElementById("nav-infobar");n&&(n.innerHTML=e,n.classList.remove("warning"),n.classList.remove("info"),n.classList.remove("neutral"),n.classList.add(t),n.style.display="block")},CABLES.hideInfoBar=function(){const e=document.getElementById("nav-infobar");e&&(e.innerHTML="",e.classList.remove("warning"),e.classList.remove("info"),e.classList.remove("neutral"),e.style.display="none")},(CABLES=CABLES||{}).SandboxEditor=function(e){const t=document.getElementById("editorIframe");CABLES.talker=new CABLES.TalkerAPI(t.contentWindow),CABLES.patchId=e.config.patchId,CABLES.patchVersion=e.config.patchVersion,CABLES.talker.addEventListener("requestPatchData",(function(t,n){n&&n(e.config)})),CABLES.talker.addEventListener("sendBrowserInfo",(function(e,t){t&&t(platform)})),CABLES.talker.addEventListener("addMeUserlist",(function(t,n){console.log(e),CABLES.api.put("project/"+CABLES.patchId+"/user/"+e.config.user.id,(function(e){n(null,e)}),(function(e){n(e,e)}))})),CABLES.talker.addEventListener("checkProjectUpdated",(function(e,t){CABLES.api.get("project/"+e.projectId+"/updated",(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("patchCreateBackup",(function(e,t){CABLES.api.put("projectversion/createbackup/"+CABLES.patchId,{title:e.title},(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("reload",(function(e,t){document.location.reload()})),CABLES.talker.addEventListener("savePatch",(function(e,t){e.buildInfo&&(e.buildInfo.host=location.hostname);let n="project/"+e.id;e.fromBackup&&(n+="?fromBackup=true"),CABLES.api.put(n,{name:e.name,namespace:e.namespace,data:e.data,dataB64:e.dataB64,buildInfo:e.buildInfo},(function(e){t(null,e)}),(function(e){t(e,e)}))})),CABLES.talker.addEventListener("getPatch",(function(t,n){let o="project/"+CABLES.patchId;e.config.patchVersion&&(o+="/version/"+e.config.patchVersion),CABLES.api.get(o,(function(e){n(null,e)}),(function(e){n(e,e)}))})),CABLES.talker.addEventListener("gotoPatch",(function(e){document.location.href="/edit/"+e.id})),CABLES.talker.addEventListener("newPatch",(function(e,t){CABLES.api.post("project",{name:e.name},(function(e){t(null,e)}),(function(e){t(e,e)}))})),CABLES.talker.addEventListener("saveProjectAs",(function(e,t){CABLES.api.post("project/copy",{name:e.name,originalId:e.originalId,copyCollaborators:e.copyCollaborators},(function(e){t(null,e)}),(function(e){t(e,e)}))})),CABLES.talker.addEventListener("saveScreenshot",(function(e,t){CABLES.api.put("project/"+e.id+"/screenshot",{screenshot:e.screenshot},(function(e){t(null,e)}),(function(e){t(e,e)}))})),CABLES.talker.addEventListener("getBuildInfo",(e,t)=>{CABLES.api.get("buildinfo/?nc="+Date.now(),(function(e){t(null,e.data)}),(function(e){t(e,e)}))}),CABLES.talker.addEventListener("getFilelist",(e,t)=>{let n="library/";"patch"==e.source&&(n="project/"+CABLES.patchId+"/files/"),CABLES.api.get(n,(function(e){t(null,e)}),(function(e){t(e,e)}))}),CABLES.talker.addEventListener("fileConvert",(e,t)=>{CABLES.api.post("project/"+CABLES.patchId+"/file/convert/"+e.fileId+"/"+e.converterId,{options:e.options},(function(e){console.log(e),e&&e.filename&&CABLES.talker.send("fileUpdated",{filename:e.filename}),t(null,e)}),(function(e){t(e,e)}))}),CABLES.talker.addEventListener("updatePatchName",(e,t)=>{document.title=e.name}),CABLES.talker.addEventListener("getFileDetails",(e,t)=>{CABLES.api.get("project/"+CABLES.patchId+"/file/info/"+e.fileid,(function(e){t(null,e)}),(function(e){t(e,e)}))}),CABLES.talker.addEventListener("getLibraryFileInfo",(e,t)=>{CABLES.api.get("files/library/info/"+e.fileCategory+"/"+e.filename,e=>t(null,e),e=>t(e,e))}),CABLES.talker.addEventListener("deleteFile",(e,t)=>{CABLES.api.delete("project/"+CABLES.patchId+"/file/"+e.fileid,{},(function(e){t(null,e)}),(function(e){t(e,e)}))}),CABLES.talker.addEventListener("checkNumAssetPatches",(e,t)=>{const n=e.filenames||[];CABLES.api.post("assets/uses/count",{filenames:n},(function(e){t(null,e)}),(function(e){t(e,e)}))}),CABLES.talker.addEventListener("createFile",(e,t)=>{CABLES.api.put("project/"+CABLES.patchId+"/"+e.name,{content:"this is an empty file..."},(function(e){t(null,e)}),(function(e){t(e,e)}))}),CABLES.talker.addEventListener("fileUploadStr",(e,t)=>{const n=dataUriToFormData(e.fileStr,e.filename);CABLES.uploadFormadata(n,e.filename)}),CABLES.talker.addEventListener("getAllProjectOps",(function(e,t){CABLES.api.get("ops/project/"+e.projectId+"/?nc="+Date.now(),(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("getAllOps",(function(e,t){CABLES.api.get("ops/?nc="+Date.now(),(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("getOpDocsAll",(function(e,t){CABLES.api.get("doc/ops/all?nc="+String(Date.now()).substr(-6),(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("getOpDocs",(function(e,t){let n="doc/ops/"+e.name+"?nc="+String(Date.now()).substr(-6);e.id&&"undefined"!==e.id&&(n+="&id="+e.id),CABLES.api.get(n,(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("getExtensionOpDocs",(function(e,t){CABLES.api.get("doc/ops/extension/"+e.name+"?nc="+Date.now(),(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("getTeamNamespaceOpDocs",(function(e,t){CABLES.api.get("doc/ops/team/namespace/"+e.name+"?nc="+Date.now(),(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("opCreate",(function(e,t){CABLES.api.post("ops/create/"+e.opname,{},(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("saveOpCode",(function(e,t){CABLES.api.put("ops/"+e.opname,{code:e.code},(function(e){t(null,e)}),(function(e){t(e,e)}))})),CABLES.talker.addEventListener("getOpCode",(function(e,t){let n="ops/"+e.opname;e.projectId&&(n+="?projectId="+e.projectId),CABLES.api.get(n,(function(e){t(null,e)}),(function(e){t(e,e)}))})),CABLES.talker.addEventListener("getBlueprintOps",(function(e,t){CABLES.api.get("blueprints/"+e.blueprintId+"/"+e.patchId+"/"+e.subPatchId+"/"+e.opId+"/"+e.blueprintSubpatchId+"?nocache="+Date.now(),(function(e){t(null,e)}),(function(e){t(e,e)}))})),CABLES.talker.addEventListener("formatOpCode",(function(e,t){CABLES.api.post("ops/code/format",{code:e.code},(function(e){t(null,e)}),(function(e){t(e,e)}))})),CABLES.talker.addEventListener("opSaveLayout",(function(e,t){CABLES.api.post("op/layout/"+e.opname,{layout:e.layout},(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("opAddLib",(function(e,t){CABLES.api.put("op/"+e.opname+"/libs",{libName:e.name},(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("opRemoveLib",(function(e,t){CABLES.api.delete("op/"+e.opname+"/libs",{libName:e.name},(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("opAddCoreLib",(function(e,t){CABLES.api.put("op/"+e.opname+"/corelibs/"+e.name,{},(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("opRemoveCoreLib",(function(e,t){CABLES.api.delete("op/"+e.opname+"/corelibs/"+e.name,{},(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("opClone",(function(e,t){CABLES.api.get("ops/clone/"+e.opname+"/"+e.name,(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("opAttachmentAdd",(function(e,t){CABLES.api.post("op/"+e.opname+"/attachments/"+e.name,{},(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("opAttachmentGet",(function(e,t){CABLES.api.get("op/"+e.opname+"/attachment/"+e.name+"?nc="+(Date.now()+"").substr(-6),(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("opAttachmentDelete",(function(e,t){CABLES.api.delete("op/"+e.opname+"/attachments/"+e.name,{},(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("opAttachmentSave",(function(e,t){CABLES.api.post("op/"+e.opname+"/attachment/"+e.name,{content:e.content},(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("saveUserSettings",(function(e,t){CABLES.api.put("usersettings/",{settings:e.settings},(function(e){t(null,e)}),(function(e,n){t(e,n)}))})),CABLES.talker.addEventListener("toggleMultiplayerSession",(function(e,t){let n=window.location.href;const o=n.indexOf("mp=false")>-1;o?n=n.replaceAll("?mp=false","").replaceAll("&mp=false",""):n.indexOf("?")>-1?n+="&mp="+o:n+="?mp="+o,window.location.href=n}))},CABLES.uploadFormadata=function(e,t){const n="/api/project/"+CABLES.patchId+"/file";CABLES.talker.send("jobStart",{id:"upload"+t,title:"Uploading "+t});const o=new XMLHttpRequest;o.open("POST",n),o.upload.onprogress=function(e){if(e.lengthComputable){const n=e.loaded/e.total*100|0;CABLES.talker.send("jobProgress",{id:"upload"+t,progress:n}),100==n&&(CABLES.talker.send("notify",{msg:"File Uploaded"}),CABLES.talker.send("jobFinish",{id:"upload"+t}),setTimeout((function(){CABLES.talker.send("refreshFileManager"),CABLES.talker.send("fileUpdated",{filename:t})}),500))}},o.onload=function(e,t){let n="",s="";try{s=JSON.parse(e.target.response)}catch(e){console.log(e)}502!==o.status?(200===o.status?CABLES.talker.send("refreshFileManager"):(s.msg&&(n=s.msg),CABLES.talker.send("notifyError",{msg:"Upload error: "+(s.msg||"")}),CABLES.talker.send("refreshFileManager"),console.error("upload error",n)),s.hasOwnProperty("success")&&!s.success&&(CABLES.talker.send("notifyError",{msg:"Upload error: "+(s.msg||"")}),console.error("upload error",s.msg))):console.warn("ajax 502 error ! possibly upload ?")},o.send(e)},(CABLES=CABLES||{}).embedPatch=function(e,t=null){let n=e.sandboxUrl+"/sandboxviewer/"+e.projectId,o=e.secret;if(!o){const e=window.location.search.match(new RegExp("[?&]s=([^&]+)"));e&&e.length>0&&(o=o[1])}o?(n+="?s="+o,e.embedOverlay&&(n+="&embed=true")):e.embedOverlay&&(n+="?embed=true"),e.locationHash&&(n+=e.locationHash),document.getElementById(e.elementId).innerHTML='';const s=document.getElementById("canvasiframe"),i=new CABLES.TalkerAPI(s.contentWindow);i.addEventListener("sendPatch",(n,s)=>{let a="project/"+e.projectId+"?nocache="+Date.now();if(e.secret||o){a+="&s="+(e.secret||o)}CABLES.api.get(a,e=>{i.send("patch",{patch:e})},n=>{console.warn("api error on url:","project/"+e.projectId+"?nocache="+Date.now()),console.log(n),"function"==typeof t&&t(n)})}),i.addEventListener("sendBlueprint",(n,s)=>{let a="blueprints"+n.url+"?nocache="+Date.now();if(e.secret||o){const t=e.secret||o;a+="&s="+t}CABLES.api.get(a,(function(e){i.send("blueprint",{blueprint:e})}),(function(e){console.warn("api error on url:",a),console.log(e),"function"==typeof t&&t(e)}))})},CABLES.CLIENT=CABLES.CLIENT||{},CABLES.CLIENT.userInfos={},CABLES.CLIENT.loadFavsAndUpdateDom=e=>{CABLES.api.get("favs/"+e,(function(e){const t={};if(t.likes=e,t.likeColumns=Math.max(Math.ceil(e.length/10),1),e){if(e.length>0){const e=getHandleBarHtml("likelist",t);ele.byQueryAll(".fav-hover-view").forEach(t=>{t.innerHTML=e})}ele.byQueryAll(".num-favs").forEach(t=>{t.innerText=e.length})}}))},CABLES.CLIENT.disableIframeScrolling=function(){let e={insideIframe:!1};document.getElementById("canvasiframe").addEventListener("mouseenter",(function(){e.insideIframe=!0,e.scrollX=window.scrollX,e.scrollY=window.scrollY})),document.getElementById("canvasiframe").addEventListener("mouseleave",(function(){e.insideIframe=!1})),document.addEventListener("wheel",(function(t){if(e.insideIframe)return t.preventDefault(),!1}),!1),document.addEventListener("scroll",(function(t){if(e.insideIframe)return t.preventDefault(),window.scrollTo(0,0),!1}))},CABLES.API=CABLES.API||{},CABLES.API.saveProjectDescription=function(e){CABLES.api.post("project/"+e+"/save_description",{content:editor.getValue()},(function(e){e.success?ele.byId("save_status").innerHTML="  saved...":ele.byId("save_status").innerHTML="  not saved :/",setTimeout((function(){ele.byId("save_status").innerHTML=""}),500)}),(function(e){console.log("err res",e)}))},CABLES.API.updateFav=function(e,t){e?ele.byQueryAll(".fav-icon").forEach(e=>{e.classList.remove("icon-heart"),e.classList.add("icon-heart-fill")}):ele.byQueryAll(".fav-icon").forEach(e=>{e.classList.add("icon-heart"),e.classList.remove("icon-heart-fill")}),CABLES.CLIENT.loadFavsAndUpdateDom(t)},CABLES.API.follow=function(e){CABLES.api.post("follow/"+e,(function(e){}),(function(e){e.followstate?ele.byId("follow-button").innerHTML="Following":ele.byId("follow-button").innerHTML="Follow"}))},CABLES.API.toggleFav=function(e){CABLES.api.post("fav/toggle/"+e,(function(e){}),(function(t){CABLES.API.updateFav(t.favstate,e)}))},CABLES.API.getUserLikes=function(e,t,n=0){t=Number(t),n=Number(n);let o="user/favs/"+e;(t||0===t)&&(o+="?l="+t),n&&(o+="&o="+n),CABLES.api.get(o,(function(e){let o="";for(const t in e.projects)o+=getHandleBarHtml("project",e.projects[t]);ele.byId("projects").innerHTML=o,e.pagination&&initPagination("#projects",e.pagination,t,n,(e,t)=>{let n="";(e||0===e)&&(n+="?l="+e),t&&(n+="&o="+t),window.location=location.origin+location.pathname+n})}))},CABLES.API.getUserFeatured=function(e,t,n=0){t=Number(t),n=Number(n);let o="user/featured/"+e;(t||0===t)&&(o+="?l="+t),n&&(o+="&o="+n),CABLES.api.get(o,(function(e){let o="";for(const t in e.projects)o+=getHandleBarHtml("project",e.projects[t]);ele.byId("projects").innerHTML=o,e.pagination&&initPagination("#results_container",e.pagination,t,n,(e,t)=>{let n="";(e||0===e)&&(n+="?l="+e),t&&(n+="&o="+t),window.location=location.origin+location.pathname+n})}))},CABLES.API.getUserProjects=function(e,t,n,o=0){let s="user/"+e+"/projects";t&&(s="admin/user/"+e+"/projects"),n=Number(n),o=Number(o),(n||0===n)&&(s+="?l="+n),o&&(s+="&o="+o),CABLES.api.get(s,(function(e){let t="";for(const n in e.projects){const o=e.projects[n];o.publishedReadable=o.updatedReadable,t+=getHandleBarHtml("project",e.projects[n])}document.getElementById("projects").innerHTML=t,e.pagination&&initPagination("#results_container",e.pagination,n,o,(e,t)=>{let n="";(e||0===e)&&(n+="?l="+e),t&&(n+="&o="+t),window.location=location.origin+location.pathname+n})}))},CABLES.API.getTeamProjects=function(e,t){let n="teams/"+e+"/projects";CABLES.api.get(n,(function(n){let o="",s=!0;for(const t in n.data){s=!1;const i=n.data[t];i.teamId=e,o+=getHandleBarHtml("myproject",i)}s&&(o='

    This team has no patches yet


    Go to the collaboration-settings of any patch and assign this team to it.
    '),document.getElementById(t).innerHTML=o}))},CABLES.API.getTeamNamespaceOps=function(e,t){if(!e)return;let n="teams/namespace/Ops.Team."+e+"/ops",o=!0,s="";CABLES.api.get(n,e=>{for(const t in e.data.ops)o=!1,e.data.ops[t]&&(s+=getHandleBarHtml("projectOp",e.data.ops[t]));s+="
    ",o&&(s='

    This namespace has no ops yet


    Move a userop to the namespace to share them with the team.
    '),ele.byQuery(t).innerHTML=s},e=>{s='

    Failed to load ops for namespace


    '+e.msg+"
    ",ele.byQuery(t).innerHTML=s})},CABLES.API.getTeamExtensionOps=function(e,t){if(!e)return;let n="extension/Ops.Extension."+e+"/ops",o=!0,s="";CABLES.api.get(n,e=>{for(const t in e.data.ops)o=!1,e.data.ops[t]&&(s+=getHandleBarHtml("projectOp",e.data.ops[t]));s+="
    ",o&&(s='

    This namespace has no ops yet


    Move a userop/teamop to the namespace to share them with the community.
    '),ele.byQuery(t).innerHTML=s},e=>{s='

    Failed to load ops for namespace


    '+e.msg+"
    ",ele.byQuery(t).innerHTML=s})},CABLES.API.addTeamAsCollaborators=function(e,t,n){let o="teams/"+t+"/collaborators/add/"+e;CABLES.api.post(o,e=>{console.error("error",e)},e=>{if("function"==typeof n){const t=[];e.data.forEach(e=>{t.push(e.username)}),n(t)}})},CABLES.API.getTags=function(){CABLES.api.get("projects/tags",(function(e){let t="",n=0,o=0;for(o in e)n=Math.max(n,e[o]);for(o in e)t+=getHandleBarHtml("tag",{name:o,size:12+e[o]/n*8});ele.byId("tags").innerHTML=t}))},CABLES.API.getFeaturedProjectsList=function(e){e&&e.selector&&CABLES.api.get("projects/featured",(function(t){let n=getHandleBarHtml("project_list_headline",{title:"Featured Patches"});n+='
    ';for(const e in t)n+=getHandleBarHtml("project",t[e]);n+="
    \x3c!-- end row --\x3e",ele.byQuery(e.selector).innerHTML=n}))},CABLES.API.getExamples=function(e){e&&e.selector&&CABLES.api.get("examples",(function(t){let n="";for(const e in t)n+=getHandleBarHtml("example",t[e]);ele.byQuery(e.selector).innerHTML=n}))},CABLES.API.getMyFavs=function(e){CABLES.api.get("myfavs",(function(e){let t="";for(const n in e)t+=getHandleBarHtml("project",e[n]);ele.byId("myfavs").innerHTML=t}))},CABLES.API.getMyPatches=function(e,t,n=0,o=0){ele.byQueryAll(".tab-bar li").forEach(e=>{e.classList.remove("active")}),ele.byQueryAll(".tab-bar li[data-tab-name='tab_"+e+"']").forEach(e=>{e.classList.add("active")});const s=ele.byId("namespaces"),i=s.value;CABLES.API.MYPATCHES.lastFilter=e,CABLES.API.MYPATCHES.lastOrder=t,ele.byId("my-projects").innerHTML='


    ';let a="mypatches?filter="+e+"&ns="+i+"&sort="+t;n=Number(n),o=Number(o),(n||0===n)&&(a+="&l="+n),o&&(a+="&o="+o),CABLES.api.get(a,(function(a){const r=CABLES.getTagsFromProjects(a),l=ele.byId("tags");l&&(l.innerHTML=getHandleBarHtml("tags",{tags:r})),s.length=0;let c=document.createElement("option");c.value="all",c.innerText="all namespaces","all"===i&&c.setAttribute("selected","selected"),s.appendChild(c),a.namespaces.forEach(e=>{c=document.createElement("option"),c.value=e,c.innerText=e,i===e&&c.setAttribute("selected","selected"),s.appendChild(c)});let d="";d+='
    ';for(const e in a.patches){const n=a.patches[e];"created"===t&&(n.publishedReadable=n.createdReadable),d+=getHandleBarHtml("myproject",a.patches[e])}d+="
    \x3c!-- end row --\x3e",ele.byId("my-projects").innerHTML=d,a.pagination&&initPagination("#my-projects",a.pagination,n,o,(n,o)=>{CABLES.API.MYPATCHES.setUrl(e,t,n,o)})}))},CABLES.lastPatchTemplates=0,CABLES.API.getTemplateListNav=function(){0===CABLES.lastPatchTemplates&&(CABLES.lastPatchTemplates=Date.now(),CABLES.api.get("templates",(function(e){let t='

    Empty Project

    ';for(const n in e)e[n].linkedId=e[n].shortId?e[n].shortId:e[n]._id,t+=getHandleBarHtml("templates_nav",e[n]);ele.byId("template-list-dropdown").innerHTML=t})))},CABLES.lastRecentProjects="recentpatches",CABLES.API.getMyProjectListNav=function(e){if("recentpatches"===e&&CABLES.lastRecentProjects===e)return void(document.location.href="/mypatches");if("recentinvitedpatches"===e&&CABLES.lastRecentProjects===e)return void(document.location.href="/mypatches?w=sharedme");if("teams"===e&&CABLES.lastRecentProjects===e)return void(document.location.href="/teams");const t=document.getElementById("my-recent-projects-dropdown");if(!t)return;t.innerHTML='
    ',document.getElementById("mypatches_"+CABLES.lastRecentProjects).classList.remove("myPatchesFilterActive"),document.getElementById("mypatches_"+CABLES.lastRecentProjects).classList.add("myPatchesFilterInActive"),e=e||"recentpatches",document.getElementById("mypatches_"+e).classList.add("myPatchesFilterActive"),document.getElementById("mypatches_"+e).classList.remove("myPatchesFilterInActive"),CABLES.lastRecentProjects=e;let n=e;"teams"===e&&(n="teams/mine"),CABLES.api.get(n,(function(n){let o="";if("teams"===e){0===n.data.length&&(o+="
    No teams yet!

    "),n.data.length>4&&(n.data.length=4);for(const e in n.data)o+=getHandleBarHtml("team_thumb",n.data[e]);o+='
    Manage your teams
    '}else{n.msg&&(n=n.msg),0===n.length&&(o="None"),n.length>4&&(n.length=4);for(const e in n)o+=getHandleBarHtml("myproject_nav",n[e]);o+="recentinvitedpatches"===e?'
    See all invites
    ':'
    All my patches
    '}t.innerHTML=o}))},CABLES.API.getMyLatestProjectList=function(){CABLES.api.get("recentpatches",(function(e){let t="";e.length=4;for(const n in e)t+=getHandleBarHtml("project",e[n]);ele.byId("mylatestprojects").innerHTML=t}))},CABLES.API.getProjectList=function(){CABLES.api.get("projects",(function(e){let t="";for(const n in e)t+=getHandleBarHtml("project",e[n]);ele.byId("projectlist").innerHTML=t}))},CABLES.API.comment=function(e){if(""===ele.byQuery(".comment_content textarea").value)return CABLES.stopSavingAnimButton(this);CABLES.api.post("comment/"+e,{content:ele.byQuery(".comment_content textarea").value},(function(t){CABLES.API.getProjectComments(e,!0)}))},CABLES.API.getProjectComments=function(e,t){CABLES.api.get("comments/"+e,(function(n){let o="";n.reverse();for(const e in n)o+=getHandleBarHtml("comment",n[e]);t&&(o+=getHandleBarHtml("comments_head",{numComments:n.length,projectId:e})),ele.byId("project_comments").innerHTML=o,CABLES.stopSavingAnimButton(this)}))},CABLES.getTagsFromProjects=function(e){const t={},n=[];for(const n in e)if(e[n].tags)for(let o=0;oe.num-t.num),n},CABLES.API.getTagProjects=function(e){CABLES.api.get("tag/"+e+"/projects",(function(e){let t="";for(const n in e.projects)t+=getHandleBarHtml("project",e.projects[n]);const n=CABLES.getTagsFromProjects(e.projects);ele.byId("tags").innerHTML=getHandleBarHtml("tags",{tags:n}),ele.byId("tag_projects").innerHTML=t,e.projects&&0!==e.projects.length||(ele.byId("tag_projects").innerHTML="No Projects found.")}))},CABLES.API.getOpPatches=function(e,t,n,o,s=0,i=0){const a=document.querySelector("#loading");a&&a.classList.remove("hide");let r="op/"+e+"/patches";s=Number(s),i=Number(i),(s||0===s)&&(r+="?l="+s),i&&(r+="&o="+i),CABLES.api.get(r,(function(e){projectPagePatchList(e.projects,t,o,e.pagination),e.pagination&&initPagination("#"+n,e.pagination,s,i,(e,t)=>{CABLES.API.OPPATCHES.setUrl("public",e,t)}),a&&a.classList.add("hide")}))};const projectPagePatchList=(e,t,n,o={})=>{let s="";for(const t in e)s+=getHandleBarHtml("project",e[t]);const i=document.getElementById(t);i&&(i.innerHTML=s,e&&0!==e.length||(i.innerHTML='
    '+n+"
    "))};CABLES.API.getOpMyPatches=function(e,t,n,o,s=0,i=0){const a=document.querySelector("#loading");a&&a.classList.remove("hide");let r="op/"+e+"/mypatches";s=Number(s),i=Number(i),(s||0===s)&&(r+="?l="+s),i&&(r+="&o="+i),CABLES.api.get(r,(function(e){projectPagePatchList(e.projects,t,o,e.pagination),e.pagination&&initPagination("#"+n,e.pagination,s,i,(e,t)=>{CABLES.API.OPPATCHES.setUrl("mine",e,t)}),a&&a.classList.add("hide")}))},CABLES.API.getOpPrivatePatches=function(e,t,n,o,s=0,i=0){const a=document.querySelector("#loading");a&&a.classList.remove("hide");let r="op/"+e+"/privatepatches";s=Number(s),i=Number(i),(s||0===s)&&(r+="?l="+s),i&&(r+="&o="+i),CABLES.api.get(r,e=>{if(projectPagePatchList(e.projects,t,o,e.pagination),e.pagination){const t=document.getElementById("num_private");t&&(t.innerHTML="("+e.pagination.count+")"),initPagination("#"+n,e.pagination,s,i,(e,t)=>{CABLES.API.OPPATCHES.setUrl("private",e,t)})}a&&a.classList.add("hide")})},CABLES.API.getCountOpPatches=function(e,t="(",n=")"){CABLES.api.get("op/"+e+"/count",e=>{if(e&&e.data)for(let o in e.data){const s=document.getElementById("num_"+o);s&&(s.innerHTML=t+e.data[o]+n)}})},CABLES.API.getOpExamples=function(e,t,n,o,s=0,i=0){const a=document.querySelector("#loading");a&&a.classList.remove("hide");let r="op/"+e+"/examples";s=Number(s),i=Number(i),(s||0===s)&&(r+="?l="+s),i&&(r+="&o="+i),CABLES.api.get(r,(function(e){projectPagePatchList(e.projects,t,o,e.pagination),e.pagination&&initPagination("#"+n,e.pagination,s,i,(e,t)=>{CABLES.API.OPPATCHES.setUrl("examples",e,t)}),a&&a.classList.add("hide")}))},CABLES.API.getRandomOps=function(){CABLES.api.get("doc/ops/random",(function(e){let t=getHandleBarHtml("project_list_headline",{link:"/ops",title:"Random Ops"});t+='
    ';for(const n in e.ops)e.ops[n]&&(t+=getHandleBarHtml("projectOp",e.ops[n]));t+="
    ",document.getElementById("random-ops").innerHTML=t}))},CABLES.API.landingPatchteaser=function(){CABLES.api.get("fav/top",(function(e){let t=0,n=getHandleBarHtml("project_list_headline",{link:"/ops",title:""});for(t in n+='
    ',e.topFavs.length>4&&(e.topFavs.length=4),e.topFavs)n+=getHandleBarHtml("project",e.topFavs[t].proj);n+="
    ",document.getElementById("landingteaser").innerHTML=n;let o=getHandleBarHtml("project_list_headline",{link:"/ops",title:""});for(t in o+='
    ',e.allTimeTop.length>4&&(e.allTimeTop.length=4),e.allTimeTop)o+=getHandleBarHtml("project",e.allTimeTop[t].proj);o+="
    ",document.getElementById("landingteaser2").innerHTML=o}))},CABLES.API.getTopProjectList=function(){CABLES.api.get("fav/top",(function(e){let t=0,n=getHandleBarHtml("project_list_headline",{link:"/patches?w=topMonth",title:"Top Of The Month"});for(t in n+='
    ',e.topFavs.length>8&&(e.topFavs.length=8),e.topFavs.length<4&&(e.topFavs.length=Math.min(4,e.topFavs.length)),e.topFavs)n+=getHandleBarHtml("project",e.topFavs[t].proj);n+="
    ",document.getElementById("top-of-the-month").innerHTML=n;let o=getHandleBarHtml("project_list_headline",{link:"/patches?w=ppub&or=favs",title:"Top Patches (Six Months)"});for(t in o+='
    ',e.allTimeTop)o+=getHandleBarHtml("project",e.allTimeTop[t].proj);o+="
    ",document.getElementById("alltimetop").innerHTML=o;const s=document.getElementById("featured");s&&(s.innerHTML=getHandleBarHtml("featured_project",e.featured))}))},CABLES.API.getLatestProjectList=function(){CABLES.api.get("latestProjects",(function(e){let t=getHandleBarHtml("project_list_headline",{link:"/projects",title:"Latest Patches"});t+='
    ',e.length=12;for(const n in e)t+=getHandleBarHtml("project",e[n]);t+="
    ",ele.byId("latest-projects").innerHTML=t}))},CABLES.API.newProject=function(){CABLES.api.post("project/",null,(function(e){const t=e.shortId||e._id;document.location.href="/edit/"+t}))},CABLES.API.checkInvites=()=>{CABLES.api.get("invites/count",(function(e){const t=e.data.count,n=document.getElementById("mypatches_patchinvitesnew"),o=document.getElementById("myPatchesBubble"),s=document.getElementById("myInvites");t>0?(o&&(o.innerHTML=t),o&&o.classList.remove("hide"),s&&(s.innerHTML=t),n&&n.classList.remove("hide"),n&&n.classList.add("block")):(o&&o.classList.add("hide"),n&&n.classList.add("hide"),n&&n.classList.remove("block"))})),CABLES.api.get("teams/mine",(function(e){if(e.data.length>0){const e=document.getElementById("mypatches_teams");e&&(e.classList.remove("hide"),e.classList.add("block"))}}))},(CABLES=CABLES||{}).SEARCH=CABLES.SEARCH||{};const numResults=32;let lastOptions=[],lastTerm="";var CABLES;window.ele&&document.addEventListener("DOMContentLoaded",()=>{const e=ele.byId("headsearch");e&&e.addEventListener("keydown",t=>{13===t.keyCode&&(document.location.href="/search?s="+e.value)});const t=ele.byId("search");t&&t.addEventListener("keydown",t=>{13===t.keyCode&&(document.location.href="/search?s="+e.value)})}),CABLES.SEARCH.setOrder=function(e){lastOptions.order=e,CABLES.SEARCH.setWhat(lastOptions.what,e,lastOptions.limit,lastOptions.offset)},CABLES.SEARCH.didCount=!1,CABLES.SEARCH.getCount=function(){if(CABLES.SEARCH.didCount)return;CABLES.SEARCH.didCount=!0;const e=lastOptions,t=JSON.parse(JSON.stringify(lastOptions));t.count=!0,t.what="ppriv",CABLES.SEARCH.search(lastTerm,t,(function(e,t){ele.byId("num_ppriv").innerHTML=" ("+t.numResults+")"}),48),t.what="ppub",CABLES.SEARCH.search(lastTerm,t,(function(e,t){ele.byId("num_ppub").innerHTML=" ("+t.numResults+")"}),48),t.what="pshared",CABLES.SEARCH.search(lastTerm,t,(function(e,t){ele.byId("num_pshared").innerHTML=" ("+t.numResults+")"}),48),t.what="featured",CABLES.SEARCH.search(lastTerm,t,(function(e,t){ele.byId("num_featured").innerHTML=" ("+t.numResults+")"}),48),t.what="example",CABLES.SEARCH.search(lastTerm,t,(function(e,t){ele.byId("num_example").innerHTML=" ("+t.numResults+")"}),48),t.what="ops",CABLES.SEARCH.search(lastTerm,t,(function(e,t){ele.byId("num_ops").innerHTML=" ("+t.numResults+")"}),48),t.what="u",CABLES.SEARCH.search(lastTerm,t,(function(e,t){ele.byId("num_user").innerHTML=" ("+t.numResults+")"}),48),t.what="topMonth",CABLES.SEARCH.search(lastTerm,t,(function(e,t){ele.byId("num_topMonth").innerHTML=" ("+t.numResults+")"}),48),lastOptions=e},CABLES.SEARCH.setWhat=function(e,t,n,o){n=Number(n),o=Number(o);let s="?s="+lastTerm+"&w="+e;t&&(s+="&or="+t),(n||0===n)&&(s+="&l="+n),o&&(s+="&o="+o),window.location.search=s},CABLES.SEARCH.showResults=function(e,t){ele.byId("results").innerHTML="";let n="",o=0;if(t.tags&&t.tags.length>0){for(n+='
    Related tags: ',o=0;o'+t.tags[o].tag+" ");n+="

    "}if(t.projects)for(o in t.projects)n+=getHandleBarHtml("project",t.projects[o]);if(t.users)for(o in t.users)n+=getHandleBarHtml("user",t.users[o]);if(t.items)for(o in t.items)n+=getHandleBarHtml("op",t.items[o]);0===n.length&&(n='

    No Results

    '),ele.byId("results").innerHTML=n,CABLES.SEARCH.getCount(),ele.hide(ele.byId("loading")),ele.show(ele.byId("results"))},CABLES.SEARCH.search=function(e,t,n,o=0,s=0){(t=t||{}).count||(ele.hide(ele.byId("results")),ele.show(ele.byId("loading")));let i="s="+e;if(lastOptions=t,lastOptions.limit=o,lastOptions.offset=s,lastTerm=e,t.order){i+="&or="+t.order;const e=document.getElementById("order");e&&(e.value=t.order)}t.what&&(i+="&w="+t.what),t.count?i+="&count="+!0:(o=Number(o),s=Number(s),(o||0===o)&&(i+="&l="+o),s&&(i+="&o="+s));let a="search?"+i;CABLES.api.get(a,(function(e){n||(n=CABLES.SEARCH.showResults),n(null,e),e.pagination&&initPagination("#results_container",e.pagination,o,s,(e,n)=>{lastOptions.limit=e,lastOptions.offset=n,CABLES.SEARCH.setWhat(t.what,t.order,e,n)})}),(function(e){console.log(e)}))},CABLES.API=CABLES.API||{},CABLES.API.SETTINGS=CABLES.API.SETTINGS||{},CABLES.API.SETTINGS.sendConfirmationEMail=function(){document.getElementById("settings_emailconfirm").innerHTML='',CABLES.api.get("settings/sendConfirmation",(function(e){let t="an error occured, try again later.";e.success&&(t="confirmation email sent. check your inbox"),document.getElementById("settings_emailconfirm").innerHTML=t}))},CABLES.importProject=function(){const e=document.getElementById("hiddenfileElem");e&&e.click()},CABLES.importProjectFile=function(e){const t=new FormData;for(let n in e){const o=e[n];t.append(n,o)}const n=new XMLHttpRequest;n.open("POST","/api/project/import"),n.onload=function(e,t){console.log("ONLOAD..."),console.log(e.target.response);const n=JSON.parse(e.target.response);n.projectId?document.getElementById("importjson").innerHTML='open patch':document.getElementById("importjson").innerHTML="something went wrong..."},n.send(t)},CABLES.ignoreAutoSuggestRequest=!1,CABLES.initializeAutosuggestsFromApi=(e=[],t={})=>{const n=e=>{if(CABLES.ignoreAutoSuggestRequest)return;const n=e.target,o=n.value;t.minLength&&o.length{const t={title:e[n.dataset.autosuggestTitlefield],value:e[n.dataset.autosuggestValuefield]};e.image&&(t.image=e.image),o.push(t)}),CABLES.ignoreAutoSuggestRequest||CABLES.showInputSuggestions(n,o,t)}))};e.forEach(e=>{e.addEventListener("focus",(function(e){CABLES.ignoreAutoSuggestRequest=!1,n(e)})),e.addEventListener("input",n)})},CABLES.showInputSuggestions=(e,t,n={})=>{e.onkeydown=null,document.querySelectorAll(".inputSuggestionList").forEach(e=>e.remove());const o=document.createElement("div");o.classList.add("inputSuggestionList");let s="";for(let e=0;e',t[e].image&&(s+=''),s+=t[e].title,s+="";o.innerHTML=s;const i=e.getBoundingClientRect();o.style.top=i.top+i.height+window.scrollY+"px",o.style.left=i.left+"px",o.style.width=i.width+"px";const a=getComputedStyle(e);o.style.background=a.background,o.style["background-color"]=a["background-color"],o.dataset.selected=0;const r=s=>{const i=s.key;if("ArrowDown"===i)o.dataset.selected++,o.dataset.selected>t.length&&(o.dataset.selected=t.length),o.childNodes.forEach((e,t)=>{const n=t+1;o.dataset.selected==n?(e.classList.add("selected"),o.scrollTop=e.offsetTop):e.classList.remove("selected")});else if("ArrowUp"===i)o.dataset.selected--,o.dataset.selected<1&&(o.dataset.selected=1),o.childNodes.forEach((e,t)=>{const n=t+1;o.dataset.selected==n?(e.classList.add("selected"),o.scrollTop=e.offsetTop):e.classList.remove("selected")});else if("Enter"===i&&o.dataset.selected&&o.dataset.selected>0&&o.dataset.selected<=t.length){let s=t[o.dataset.selected-1].title,i=t[o.dataset.selected-1].title,a=t[o.dataset.selected-1].value;if(n.append){const r=n.seperator||",";s=e.value+=r+t[o.dataset.selected-1].title,i=e.dataset.autosuggestTitle+r+t[o.dataset.selected-1].title,a=e.dataset.autosuggestValue+r+t[o.dataset.selected-1].value,s=s.replace(r+r,r),i=i.replace(r+r,r),a=a.replace(r+r,r)}e.value=s,e.dataset.autosuggestTitle=i,e.dataset.autosuggestValue=a,e.removeEventListener("keydown",r),o.remove()}};e.onkeydown=r,e.addEventListener("blur",()=>{CABLES.ignoreAutoSuggestRequest=!0,setTimeout(()=>{e.onkeydown=null,o.remove()},100)}),o.addEventListener("pointerdown",t=>{n.append?e.value=e.value+","+t.target.dataset.title:e.value=t.target.dataset.title,e.dataset.autosuggestTitle=t.target.dataset.title,e.dataset.autosuggestValue=t.target.dataset.value,e.onkeydown=null,o.remove()}),document.body.appendChild(o)},(CABLES=CABLES||{}).PAGE=CABLES.PAGE||{},CABLES.PAGE.SETTINGS=CABLES.PAGE.SETTINGS||{},CABLES.PAGE.SETTINGS.saveAccount=function(){const e=ele.byId("accountsavebutton");e.innerHTML="Working....",CABLES.api.put("user/account/",{account_email:ele.byId("account_email").value,account_newsletter:document.getElementById("account_newsletter").checked},(function(t){t.success?setTimeout((function(){e.innerHTML="Account updated!"}),500):console.log("fail ",t),console.log("res",t)}),(function(t){e.innerHTML="Something went wrong: "+t.msg,console.log("err res",t)}))},CABLES.PAGE.SETTINGS.deleteAccount=function(e,t){const n=prompt("please enter your username:","");n&&n===t?CABLES.api.delete("user/"+e+"?userName="+t,{},(function(e){window.location="/logout"}),(function(e){document.getElementById("errors_delete").innerHTML="this did not work as expected..."})):document.getElementById("errors_delete").innerHTML="usernames do not match..."},CABLES.PAGE.SETTINGS.saveProfile=function(){const e=ele.byId("profilesavebutton");e.innerHTML="working....";let t=ele.byId("profile-website").value;if(t.length>0){let e=!1;if(-1===t.indexOf("https://")&&-1===t.indexOf("http://")&&(e=!0),-1===t.indexOf(".")&&(e=!0),e)return void(ele.byId("errors_links").innerHTML="Website invalid url");ele.byId("errors_links").innerHTML=""}CABLES.api.put("user/profile/",{profile_bio:ele.byId("profile-bio").value,profile_website:t,profile_twitter:ele.byId("profile-twitter").value,profile_facebook:ele.byId("profile-facebook").value,profile_instagram:ele.byId("profile-instagram").value,profile_mastodon:ele.byId("profile-mastodon").value,profile_country:ele.byId("profile-country").value,profile_city:ele.byId("profile-city").value},(function(t){t.success?setTimeout((function(){e.innerHTML="profile saved!",setTimeout((function(){e.innerHTML="save again"}),3e3)}),500):console.log("fail ",t),console.log("res",t)}),(function(t){e.innerHTML="something went wrong",console.log("err res",t)}))},CABLES.PAGE.SETTINGS.savePassword=function(){const e=ele.byId("passwordSavebutton");e.innerHTML="working....",CABLES.api.put("user/password/",{password1:ele.byId("password1").value,password2:ele.byId("password2").value},(function(t){t.success?setTimeout((function(){e.innerHTML="password changed!",setTimeout((function(){e.innerHTML="set password"}),3e3)}),500):console.log("fail ",t),console.log("res",t)}),(function(t){t.msg?e.innerHTML=t.msg:e.innerHTML="something went wrong",console.log("err res",t),setTimeout((function(){e.innerHTML="set password"}),3e3)}))},CABLES.PAGE.SETTINGS.init=function(){const e=ele.byQueryAll(".tab-bar li");e.forEach(t=>{t.addEventListener("pointerdown",()=>{e.forEach(e=>{e.classList.remove("active")}),t.classList.add("active");const n=t.dataset.tabName;ele.byQueryAll(".tab-bar-content").forEach(e=>{e.classList.add("hidden")}),ele.byQuery(".tab-bar-content[data-tab-name='"+n+"']").classList.remove("hidden")})})},(CABLES=CABLES||{}).TalkerAPI=function(e){CABLES.EventTarget.apply(this),this._talker=new Talker(e,"*"),this._callbackCounter=0,this._callbacks={},this._talker.onMessage=function(e){"callback"==e.data.cmd?this._callbacks[e.data.cb]&&this._callbacks[e.data.cb](e.data.error,e.data.response):this.emitEvent(e.data.cmd,e.data.data,function(t,n){this._talker.send("cables",{cmd:"callback",cb:e.data.cb,response:n,error:t})}.bind(this))}.bind(this)},CABLES.TalkerAPI.prototype.send=function(e,t,n){const o={cmd:e,data:t};n&&(this._callbackCounter++,this._callbacks[this._callbackCounter]=n,o.cb=this._callbackCounter),this._talker.send("cables",o)},CABLES.TEST={},CABLES.overwriteTime=1e-5,CABLES.TEST.Tests=class{constructor(e,t){CABLES.EventTarget.apply(this),this.tests=[],this.testResults=[],this.testsToRun=[],this.selectedTags=new Set,this.runId=uuid(),this.browserTestId=null,this.currentScene=null,this.currentIndex=null,this.testIsRunning=!1,this._codeHost=e,this._sandboxHost=t,this._storageKey="cables_tests_environment",this._currentProjectId=null,this.envConfig=this._buildEnvironmentConfig(),this.allDoneCb=null,"hidden"in document?document.addEventListener("visibilitychange",this.cancelTests):"mozHidden"in document?document.addEventListener("mozvisibilitychange",this.cancelTests):"webkitHidden"in document?document.addEventListener("webkitvisibilitychange",this.cancelTests):"msHidden"in document?document.addEventListener("msvisibilitychange",this.cancelTests):"onfocusin"in document?document.onfocusin=document.onfocusout=this.cancelTests:window.onpageshow=window.onpagehide=window.onfocus=window.onblur=this.cancelTests,this.loadTestLibs(()=>{this.emitEvent("ready")},e=>{this.emitEvent("error")})}getEnvironmentConfig(){return this.envConfig}setEnvironmentConfig(e,t){this.envConfig={codeHost:e,sandboxHost:t},window.localStorage&&window.localStorage.setItem(this._storageKey,JSON.stringify(this.envConfig))}cancelTests(){this.testIsRunning&&(this.testIsRunning=!1,ele.byId("resultall").innerHTML="Testing canceled... do not switch focus to another tab while runnign tests...",ele.byId("resultall").classList.add("warning"))}logTest(e,t){console.log(e,t)}loadTestLibs(e,t){const n="cables.gl"===this.envConfig.codeHost?"cables.min.js":"cables.max.js",o=document.createElement("script");o.type="text/javascript",o.src="//"+this.envConfig.sandboxHost+"/ui/js/"+n+"?nc="+Date.now(),o.onload=()=>{const n="cables.gl"===this.envConfig.codeHost?"libs.core.min.js":"libs.core.js",o=document.createElement("script");o.type="text/javascript",o.src="//"+this.envConfig.sandboxHost+"/ui/js/"+n+"?nc="+Date.now(),o.onload=()=>{const n=document.createElement("script");n.type="text/javascript",n.src="//"+this.envConfig.codeHost+"/api/ops/code?nc="+Date.now(),n.onload=()=>{e&&e()},n.onerror=()=>{t("failed to load "+n.src)},(ele.byQuery("head")||ele.byQuery("body")).appendChild(n)},o.onerror=()=>{t("failed to load "+o.src)},(ele.byQuery("head")||ele.byQuery("body")).appendChild(o)},o.onerror=()=>{t("failed to load "+o.src)},(ele.byQuery("head")||ele.byQuery("body")).appendChild(o)}showResults(e){ele.byId("testresult").innerHTML="";ele.byId("testresult").innerHTML=getHandleBarHtml("test",this.testsToRun[e]);const t=new Image;t.src=this.testsToRun[e].resultData.getImageDataUrl();ele.byId("container_comparison").appendChild(t);const n=this.testsToRun[e].correctImg;ele.byId("container_specification").appendChild(n);ele.byId("container_resultimage").appendChild(this.testsToRun[e].testImg)}runTestId(e,t){CABLES.doBrowserTest(n=>{n&&n.id&&(this.browserTestId=n.id),CABLES.api.get("tests/"+e,e=>{this.runId=uuid(),this.testsToRun=[e],this.testResults=[],this.runTest(0,t)})})}runAllTests(e){CABLES.doBrowserTest(t=>{if(t&&t.id&&(this.browserTestId=t.id),ele.byQueryAll(".testcontainer").forEach(()=>{ele.byQueryAll(".test_failed").forEach(e=>{e.remove()}),ele.byQueryAll(".test_passed").forEach(e=>{e.remove()})}),this.testsToRun=[],0===this.selectedTags.size)this.testsToRun=this.tests;else{const e=".testcontainer:not(.hidden)";ele.byQueryAll(e).forEach(e=>{const t=e.dataset.testIndex;this.testsToRun.push(this.tests[t])})}this.testResults=[],this.runId=uuid(),this.runTest(0,e)})}allTestsFinished(e){const t=ele.byId("testcontrols");t&&t.classList.remove("hidden");const n=ele.byId("viewrun");n&&(n.href="/tests/run/"+this.runId,n.classList.remove("hidden"),n.dataset.runId=this.runId),e&&e(this.testResults||[])}saveResult(e){ele.byId("saveimage-button").innerHTML="saving...",this.logTest("save result... "+e),CABLES.api.put("test/save_result/"+e,{screenshot:ele.byId("glcanvas_"+this.currentIndex).toDataURL()},e=>{ele.byId("saveimage-button").innerHTML="IMAGE SAVED!",this.logTest(e)})}runTest(e,t){if(this.allDoneCb=t,this.testIsRunning)return void this.logTest("test still running...");const n=ele.byId("viewrun");n&&n.classList.add("hidden"),this.testIsRunning=!0,ele.byId("testresult").innerHTML='
    running test...
    ',this.currentScene&&(this.currentScene.dispose(),ele.byId("glcanvas_"+this.currentIndex).remove(),this.currentScene=null,this.logTest("patch disposed...")),this.logTest("***************************************************"),this.logTest("run test ",e+": "+this.testsToRun[e].name),this.currentIndex=e;const o=ele.byId("glContainer"),s=document.createElement("canvas");s.setAttribute("id","glcanvas_"+this.currentIndex),s.setAttribute("width","640"),s.setAttribute("height","360"),s.style.width="640px",s.style.height="360px",o.appendChild(s),this.currentFinished=-1,CABLES.internalNow=function(){return 1e3*CABLES.overwriteTime},CABLES.Timer.prototype.get=function(){return CABLES.overwriteTime},this._resetTimers(1e-5);let i=new CABLES.Patch({glCanvasId:"glcanvas_"+e,prefixAssetPath:"",onFinishedLoading:()=>{this._finishedLoading(i)},canvas:{antialias:!1,preserveDrawingBuffer:!0,alpha:!0},onError(e){console.error("test on error",e)}});CABLES.api.get("project/"+this.testsToRun[e]._id,t=>{const n=document.createElement("script");n.type="text/javascript",n.async=!0,n.src="//"+this.envConfig.codeHost+"/api/project/"+this.testsToRun[e]._id+"/libs.js?nc=tests",n.onload=()=>{const n=document.createElement("script");n.type="text/javascript",n.src="//"+this.envConfig.codeHost+"/api/project/"+this.testsToRun[e]._id+"/projectops.js?nc="+Date.now(),n.onload=()=>{this.testResults[e]={},i.deSerialize(t),this.currentScene=i},(ele.byQuery("head")||ele.byQuery("body")).appendChild(n)},(ele.byQuery("head")||ele.byQuery("body")).appendChild(n)})}showAll(e){const t=new Set,n=getQueryVariable("op");let o="tests";n&&(o+="?op="+n),CABLES.api.get(o,n=>{const o=ele.byId("tests");this.tests=n;let s="",i="";const a={};for(const e in n){const o=n[e];o.testIndex=e;const r=[];o.tags&&Array.isArray(o.tags)&&o.tags.forEach(e=>{if(a.hasOwnProperty(e)||(a[e]=0),a[e]++,a[e]>1){const n=this._sanitizeTagName(e);r.push(n),t.add(e)}}),i+=getHandleBarHtml("test_row",{test:o,tagClasses:r.join(" ")}),s+=getHandleBarHtml("project_test",{project:o,tagClasses:r.join(" "),cb:Date.now()})}this._initTagContainer(t),o.innerHTML=i,ele.byId("thumbnails").innerHTML=s,e&&e()})}runBrowserstack(e,t,n,o){CABLES.startSavingAnimButton(e);const s=ele.byId("browserstack-progress");s&&ele.show(s),CABLES.api.post("tests/browserstack",{device:t,os:n,browser:o},e=>{const t=ele.byId("testprogressinner");t&&t.classList.remove("failed");const n=ele.byId("resultall");n&&(n.innerHTML="
     ");const o=ele.byId("resultcontainer");if(ele.show(o),e.data.runId){const t=e.data.runId,n=ele.byId("viewrun");n&&(n.href="/tests/run/"+t,n.classList.remove("hidden"),n.dataset.runId=t)}CABLES.stopSavingAnimButton()},e=>{const t=ele.byId("resultcontainer");ele.show(t);const n=ele.byId("resultall");n&&(n.innerHTML="
    ERROR: "+e.msg.error);const o=ele.byId("testprogressinner");o&&o.classList.add("failed"),CABLES.stopSavingAnimButton()})}filterByTag(e){this.removeAllTagFilters(),this.selectedTags.add(e),this._updateTagSelection()}filterByTags(e){this.selectedTags=new Set(e),this._updateTagSelection()}removeAllTagFilters(){this.selectedTags.clear();ele.byQueryAll(".testcontainer, #thumbnails .project").forEach(e=>{e.classList.remove("hidden"),e.classList.remove("filtered")});ele.byQueryAll("#tagcontainer .tag").forEach(e=>{e.classList.remove("active")}),ele.byId("runalltests").innerHTML="Run all tests",history.replaceState(null,null," "),window.localStorage&&window.localStorage.removeItem("cables_tests_tags")}initCategories(e,t,n=null){e.innerHTML=getHandleBarHtml("test_categories",{categories:t}),this._currentProjectId=n;const o=ele.byQueryAll("#categories li"),s=o[0];o.forEach(e=>{e.addEventListener("pointerdown",()=>{this._setCategoryTab(e,10,0)})});let i=new URL(window.location.href),a=i.searchParams.get("l")||10,r=i.searchParams.get("o")||0;s&&this._setCategoryTab(s,a,r)}_setCategoryTab(e,t,n){const o=ele.byId("loading"),s=ele.byId("testresults");s.innerHTML="",o&&ele.show(o);let i=e.dataset.category;ele.byQueryAll("#categories li").forEach(e=>e.classList.remove("active")),e.classList.add("active"),CABLES.api.post("test/category/results?l="+t+"&o="+n,{projectId:this._currentProjectId,category:i},i=>{if(o&&ele.hide(o),i.data&&Array.isArray(i.data)){let e="";i.data.forEach(t=>{e+=getHandleBarHtml("test_resultrow",t)}),s.innerHTML=e+"
    "}i.pagination&&initPagination("#pagination",i.pagination,t,n,(t,n)=>{this._setCategoryTab(e,t,n)})})}initEnvironments(e,t){e.innerHTML=getHandleBarHtml("test_environments",{environments:t});const n=this.getEnvironmentConfig(),o=ele.byId("codeHost");o&&(o.value=n.codeHost);const s=ele.byId("sandboxHost");s&&(s.value=n.sandboxHost);const i=ele.byId("addTestEnv");i&&i.addEventListener("pointerdown",()=>{this.setEnvironmentConfig(o.value,s.value),window.location.reload()});const a=ele.byQueryAll("#environments li");let r=!1;if(a.forEach(e=>{e.dataset.codeHost===n.codeHost&&(r=!0),e.addEventListener("pointerdown",()=>{a.forEach(e=>e.classList.remove("active")),e.classList.add("active"),this.setEnvironmentConfig(e.dataset.codeHost,e.dataset.sandboxHost),window.location.reload()})}),!r){const e=ele.byId("environments"),t=document.createElement("li");t.dataset.codeHost=n.codeHost,t.dataset.sandboxHost=n.sandboxHost,t.innerText=n.codeHost,e.appendChild(t)}const l=ele.byQuery('#environments li[data-code-host="'+n.codeHost+'"]');l&&l.classList.add("active");const c=ele.byId("add_test_env");c&&c.addEventListener("pointerdown",()=>{const e=ele.byId("add_env"),t=e.classList.contains("hidden");e.classList.toggle("hidden"),t?(c.classList.remove("icon-plus"),c.classList.add("icon-minus")):(c.classList.add("icon-plus"),c.classList.remove("icon-minus"))})}_updateTagSelection(){ele.byQueryAll(".testcontainer, #thumbnails .project").forEach(e=>{this.selectedTags.forEach(t=>{if(e.classList.contains(String(t))&&!e.classList.contains("filtered"))e.classList.remove("hidden");else{const n=".tag[data-tag='"+t+"']";ele.byQueryAll(n).forEach(e=>{e.classList.add("active")}),e.classList.add("hidden"),e.classList.add("filtered")}})}),ele.byId("runalltests").innerHTML="run tests",window.location.hash=Array.from(this.selectedTags).join(",")}_getTestRow(e,t){const n=document.createElement("div");try{const o=document.createElement("a");o.href="/tests/"+t._id,o.appendChild(document.createTextNode(t.name+" ")),n.appendChild(o),n.classList.add("testcontainer"),n.setAttribute("id","test_"+e),n.dataset.testIndex=e}catch(e){this.logTest(t.name,"exception ",e)}return n}_initTagContainer(e){const t=ele.byId("tagcontainer");t&&e.forEach(e=>{const n=this._sanitizeTagName(e),o=document.createElement("a");o.innerText=e,o.classList.add("tag"),o.dataset.tag=n,o.onclick=()=>{o.classList.contains("active")?(o.classList.remove("active"),this.removeAllTagFilters()):(o.classList.add("active"),this.filterByTag(n))},t.appendChild(o)})}_sanitizeTagName(e){let t=e||"";return t=t.toLowerCase(),t=t.split(" ").join("_"),t=t.replace(/\./g,"_"),t.match(/^\d/)&&(t="u_"+t),t}_updateProgress(){let e=0,t="";for(let t=0;tfailed: "+e+"/"+this.testsToRun.length;const n=ele.byId("testprogressinner");n&&(e>0?n.classList.add("failed"):n.classList.remove("failed"),ele.byId("testprogressinner").style.width=Math.round(this.currentIndex/(this.testsToRun.length-1)*100)+"%");const o=ele.byId("resultall");o&&(o.innerHTML=t);const s=ele.byId("testcontrols");s&&s.classList.add("hidden");const i=ele.byId("resultcontainer");i&&i.classList.remove("hidden")}_saveResultToServer(e,t,n,o,s,i){let a="failed";o&&(a="passed");let r=null;const l=document.getElementById("resultimage_"+i);l&&(r=l.src);const c=s.resultData.getImageDataUrl(),d={run:e,status:a,browserInfo:t,resultThreshold:s.resultData?s.resultData.rawMisMatchPercentage:null,platform:platform||{},resultData:s.resultData,comparisonImage:c,renderImage:r,codeHost:this.envConfig.codeHost,sandboxHost:this.envConfig.sandboxHost};CABLES.api.put("test/save/"+n,d,e=>{const t=ele.byId("testresulturl");t&&t.setAttribute("href",e.data.resultUrl)},()=>{this.logTest("ERROR SAVING TO SERVER")})}_rendered(e){e.pause(),this.logTest("rendered...",e.getFrameNum());const t=new Image,n=new Image;n.setAttribute("id","resultimage_"+this.currentIndex),n.src=ele.byId("glcanvas_"+this.currentIndex).toDataURL(),t.onabort=t.onerror=()=>{ele.byId("testresult").innerHTML="",this.testIsRunning=!1;const e=ele.byId("testresult"),t=document.createElement("div");t.appendChild(document.createTextNode("could not load correct image to compare...")),this.logTest("could not load correct image to compare...",this.testsToRun[this.currentIndex].name),t.classList.add("failed"),this.testResults[this.currentIndex].passed=!1,e.appendChild(t);const n=ele.byId("test_"+this.currentIndex);n.classList.add("testcontainer"),n.classList.add("failed"),this.logTest("not complete.... ignore..."),this._updateProgress(),this.testsToRun[this.currentIndex+1]?this.runTest(this.currentIndex+1):this.allTestsFinished(this.allDoneCb)},t.onload=()=>{this.testsToRun[this.currentIndex].correctImg=t,this.testsToRun[this.currentIndex].testImg=n,resemble(n.src).compareTo(t.src).onComplete(e=>{this._onResembleComplete(e,this.testsToRun[this.currentIndex],this.allDoneCb)})},t.src="/api/test/result/"+this.testsToRun[this.currentIndex]._id+"?nc="+Date.now()}_resetTimers(e){CABLES.overwriteTime=e}_finishedLoading(e){e.onFinishedLoading=null,this.logTest("finishedloading...",e.getFrameNum()),this.currentFinished!==e.config.glCanvasId&&(this.currentFinished=e.config.glCanvasId,e.pause(),this._resetTimers(.01),e.renderOneFrame(),e.renderOneFrame(),this._resetTimers(.3),e.renderOneFrame(),e.onOneFrameRendered=()=>{this._rendered(e)},e.renderOneFrame(),e.pause(),this._resetTimers(1e-5))}_onResembleComplete(e,t,n){if(!this.testResults[this.currentIndex])return;if(this.testResults[this.currentIndex]&&this.testResults[this.currentIndex].hasOwnProperty("passed"))return;const o=ele.byId("test_"+t.testIndex);let s="passed";this.logTest("currentIndex",this.currentIndex,this.testResults[this.currentIndex]),this.testResults[this.currentIndex].passed=!0,this.testResults[this.currentIndex].name=this.testsToRun[this.currentIndex].name,this.testResults[this.currentIndex].projectId=this.testsToRun[this.currentIndex]._id,e.misMatchPercentage>2&&(s="failed",this.testResults[this.currentIndex].passed=!1),this.logTest("result ",this.testsToRun[this.currentIndex].name,this.testResults[this.currentIndex].passed);const i=ele.byId("testthumb_"+this.testsToRun[this.currentIndex]._id);if(i)if("passed"===s)i.style.border="3px solid green";else{i.style.border="3px solid red";const t=e.getImageDataUrl();i.setAttribute("src",t)}if(o){const e=document.createElement("span");e.classList.add("test_"+s),e.innerText=s,o.appendChild(e)}this.testsToRun[this.currentIndex].resultClass=s,this.testsToRun[this.currentIndex].resultData=e,this.showResults(this.currentIndex),this.testIsRunning=!1,this.logTest("complete...."),this._saveResultToServer(this.runId,this.browserTestId,this.testsToRun[this.currentIndex]._id,this.testResults[this.currentIndex].passed,this.testsToRun[this.currentIndex],this.currentIndex),this._updateProgress(),this.testsToRun[this.currentIndex+1]?this.runTest(this.currentIndex+1):this.allTestsFinished(n)}_buildEnvironmentConfig(){let e={codeHost:this._codeHost,sandboxHost:this._sandboxHost};if(window.localStorage&&window.localStorage.getItem(this._storageKey))try{const t=JSON.parse(window.localStorage.getItem(this._storageKey));t.codeHost&&(e.codeHost=t.codeHost),t.sandboxHost&&(e.sandboxHost=t.sandboxHost)}catch(t){this.logTest("could not parse stored testenvironment, using",e.codeHost,e.sandboxHost,"error: ",t)}return e}}; +//# sourceMappingURL=script.min.js.map +CABLES.API.build = {"timestamp":1671443420321,"created":"2022-12-19T09:50:20.321Z","git":{"branch":"master","commit":"739587e6bcac1872e707cf575961a89230dc30d1","date":"2022-12-19T09:48:19.000Z","message":"changelogitem headline"}}; \ No newline at end of file diff --git a/survey_dashboard/hmc_layout/static/en_files/surveyBG.png b/survey_dashboard/hmc_layout/static/en_files/surveyBG.png new file mode 100644 index 0000000..d40c44d Binary files /dev/null and b/survey_dashboard/hmc_layout/static/en_files/surveyBG.png differ diff --git a/survey_dashboard/hmc_layout/static/en_files/talkerapi.js b/survey_dashboard/hmc_layout/static/en_files/talkerapi.js new file mode 100644 index 0000000..2714894 --- /dev/null +++ b/survey_dashboard/hmc_layout/static/en_files/talkerapi.js @@ -0,0 +1,2 @@ +var CABLES=CABLES||{};CABLES.EventTarget=function(){this._eventCallbacks={},this._logName="",this._doLog=!1,this._listeners={},this.addEventListener=this.on=function(e,t,s){const n={id:(s||"")+CABLES.uuid(),name:e,cb:t};return this._eventCallbacks[e]?this._eventCallbacks[e].push(n):this._eventCallbacks[e]=[n],this._listeners[n.id]=n,n.id},this.hasEventListener=function(e,t){if(e&&!t)return!!this._listeners[e];if(console.warn("old eventtarget function haseventlistener!"),e&&t&&this._eventCallbacks[e]){return-1!=this._eventCallbacks[e].indexOf(t)}},this.removeEventListener=this.off=function(e,t){if(null==e)return;if(!t){const t=this._listeners[e];if(!t)return;let s=!0;for(;s;){s=!1;let n=-1;for(let a=0;ae;e++)o[e]()}))),i};return h.then=function(h,l){var c=a(),u=function(){try{var s=i?h:l;e(s)?function s(a){var i,r=0;try{if(a&&(t(a)||e(a))&&e(i=a.then)){if(a===c)throw new TypeError;i.call(a,(function(){r++||s.apply(n,arguments)}),(function(e){r++||c(!1,[e])}))}else c(!0,arguments)}catch(e){r++||c(!1,[e])}}(s.apply(n,r||[])):c(i,r)}catch(e){c(!1,[e])}};return null!=i?s(u):o.push(u),c},h}}(),objectCreate=function(e){function t(){}return t.prototype=e,new t},Talker=function(e,t){this.remoteWindow=e,this.remoteOrigin=t,this.timeout=3e3,this.handshaken=!1,this.handshake=pinkySwearPromise(),this._id=0,this._queue=[],this._sent={};var s=this;return window.addEventListener("message",(function(e){s._receiveMessage(e)}),!1),this._sendHandshake(),this};Talker.prototype.send=function(e,t,s){var n=new Talker.OutgoingMessage(this,e,t,s),a=pinkySwearPromise();return this._sent[n.id]=a,this._queue.push(n),this._flushQueue(),setTimeout((function(){a(!1,[new Error(TALKER_ERR_TIMEOUT)])}),this.timeout),a},Talker.prototype._receiveMessage=function(e){var t;try{t=JSON.parse(e.data)}catch(e){t={}}return!!this._isSafeMessage(e.source,e.origin,t.type)&&(t.handshake||t.handshakeConfirmation?this._handleHandshake(t):this._handleMessage(t))},Talker.prototype._isSafeMessage=function(e,t,s){var n,a;return n=e===this.remoteWindow,a="*"===this.remoteOrigin||t===this.remoteOrigin,n&&a&&s===TALKER_TYPE},Talker.prototype._handleHandshake=function(e){e.handshake&&this._sendHandshake(this.handshaken),this.handshaken=!0,this.handshake(!0,[this.handshaken]),this._flushQueue()},Talker.prototype._handleMessage=function(e){var t=new Talker.IncomingMessage(this,e.namespace,e.data,e.id),s=e.responseToId;return s?this._respondToMessage(s,t):this._broadcastMessage(t)},Talker.prototype._respondToMessage=function(e,t){this._sent[e]&&(this._sent[e](!0,[t]),delete this._sent[e])},Talker.prototype._broadcastMessage=function(e){this.onMessage&&this.onMessage.call(this,e)},Talker.prototype._sendHandshake=function(e){var t={type:TALKER_TYPE};t[e?"handshakeConfirmation":"handshake"]=!0,this._postMessage(t)},Talker.prototype._nextId=function(){return this._id+=1},Talker.prototype._postMessage=function(e){this.remoteWindow&&this.remoteOrigin&&this.remoteWindow.postMessage(JSON.stringify(e),this.remoteOrigin)},Talker.prototype._flushQueue=function(){if(this.handshaken){var e=this._queue.shift();if(!e)return this._queue;if(this._postMessage(e),this._queue.length>0)return this._flushQueue()}return this._queue},Talker.Message=function(e,t,s){return this.talker=e,this.namespace=t,this.data=s,this.type=TALKER_TYPE,this},Talker.OutgoingMessage=function(e,t,s,n){Talker.Message.call(this,e,t,s),this.responseToId=n||null,this.id=this.talker._nextId()},Talker.OutgoingMessage.prototype=objectCreate(Talker.Message.prototype),Talker.OutgoingMessage.prototype.constructor=Talker.Message,Talker.OutgoingMessage.prototype.toJSON=function(){return{id:this.id,responseToId:this.responseToId,namespace:this.namespace,data:this.data,type:this.type}},Talker.IncomingMessage=function(e,t,s,n){Talker.Message.call(this,e,t,s),this.id=n},Talker.IncomingMessage.prototype=objectCreate(Talker.Message.prototype),Talker.IncomingMessage.prototype.constructor=Talker.Message,Talker.IncomingMessage.prototype.respond=function(e){return this.talker.send(null,e,this.id)},window.Talker=Talker;var CABLESUILOADER=CABLESUILOADER||{};CABLESUILOADER.TalkerAPI=function(e){CABLES.EventTarget.apply(this),this._talker=new Talker(e,"*"),this._callbackCounter=0,this._callbacks={},this._talker.onMessage=function(e){"callback"==e.data.cmd?this._callbacks[e.data.cb]&&this._callbacks[e.data.cb](e.data.error,e.data.response):this.emitEvent(e.data.cmd,e.data.data,function(t,s){this._talker.send("cables",{cmd:"callback",cb:e.data.cb,response:s,error:t})}.bind(this))}.bind(this)},CABLESUILOADER.TalkerAPI.prototype.send=function(e,t,s){let n={cmd:e,data:t};s&&(this._callbackCounter++,this._callbacks[this._callbackCounter]=s,n.cb=this._callbackCounter),this._talker.send("cables",n)}; +//# originalSourceMappingURL=talkerapi.js.map diff --git a/survey_dashboard/data/download_data.py b/survey_dashboard/i18n/__init__.py similarity index 56% rename from survey_dashboard/data/download_data.py rename to survey_dashboard/i18n/__init__.py index e75297d..14c0585 100644 --- a/survey_dashboard/data/download_data.py +++ b/survey_dashboard/i18n/__init__.py @@ -8,19 +8,8 @@ # https://github.com/Materials-Data-Science-and-Informatics/survey_dashboard # # For further information on the license, see the LICENSE file # ############################################################################### -import requests -# HMC survey data: -#doi = 'https://doi.org/10.7802/2433' -#https://search.gesis.org/research_data/SDN-10.7802-2433?doi=10.7802/2433 -#url="https://access.gesis.org/sharing/2433/3778" - -def download_data(url="https://access.gesis.org/sharing/2433/3778", - destination="survey_dashboard/data/hmc_survey_2021_data_cleaned.csv"): - """ - This function downloads the dataset for a given DOI - """ - # For now go to the website of the DOI and download by hand - - with open(destination, "wb") as fileo: - fileo.write(requests.get(url).content) +""" +Internationalization module for the survey dashboard. +This module contains all translatable text content for the dashboard. +""" \ No newline at end of file diff --git a/survey_dashboard/text_display.py b/survey_dashboard/i18n/text_display.py similarity index 75% rename from survey_dashboard/text_display.py rename to survey_dashboard/i18n/text_display.py index 753ac88..aa77f42 100644 --- a/survey_dashboard/text_display.py +++ b/survey_dashboard/i18n/text_display.py @@ -12,10 +12,13 @@ This is the central place for all text from the dashboard which needs to be translated """ +md_text_title = {'EN': 'Survey Data Explorer: ', 'DE': 'HMC Survey Data Explorer'} + +md_dashboard_title = {'EN': 'HMC Community Survey 2021', 'DE': 'HMC Community Survey 2021'} # Description md_text_description = {'EN': ("Explorer interactively the HMC 2021 Survey results. " - "The overview sections displays some main results, while you can apply some global filters to these. " + "The overview sections displays some main results, while you can apply some global filters to these. " "Find out what methods, tools, software and standards are applied by others in your research area. " "The question explorer allows for in detail analysis of a specific question and simple correlations of two questions. " "Interact with the visualizations and widgets on the left to explorer the data.\n" @@ -31,8 +34,14 @@ 'DE':('Exploriere interakiv die Resultate der HMC 2021 Umfrage.')} +md_text_descriptions_icons = { + 'people': {'EN': ("**631** Researchers took part in the survey"), 'DE':("**631** Forschende nahmen an der Umfrage teil")}, + 'institution': {'EN': ("**18** Helmholtz research centers and institutes"), 'DE':("**18** Helmholtz-Zentren und Institute")}, + 'questions': {'EN': ("**49** Survey questions"), 'DE':("**49** Fragen gestellt")}, +} + -## Global data filters\n +## Global data filters\n md_text_global_filter = {'EN': ("Apply filters to displayed data according to research areas and data generation method"), 'DE': ("Wende Filter auf die Resultate an um nur Daten bestimmter " "Forschungsfelder und Erzeugungsmethode dazustellen.")} @@ -40,13 +49,17 @@ md_text_global_filters_widgets = [{'EN': "Research area", 'DE': "Forschungsfeld"}, {'EN': "Data generation method", 'DE': "Datenerzeugungs Methode"}] # Overview\n + md_text_overview = {'EN': "Birds eye view of survey results related to research data management.", 'DE': "Übersicht mit hervorgehobene Fragen zum Forschungsdatenmanagement"} +# Tools and Methods\n +md_text_tools_tabs = {'methods': {'EN': 'Data generation methods', 'DE': 'Datengenerierungsmethoden'}, + 'software': {'EN': 'Main software in use', 'DE': 'Haupt Software in Benutzung'}, + 'repositories': {'EN': 'Repositories data published in', 'DE': 'Repositorien mit Datenpublikationen'}} -# Tools and Methods\n md_text_tools_used = {'EN': ("Discover the scientific methods, used software and repositories of our communities."), 'DE': ("Entdecke die wissenschaftliche Methoden, Werkzeuge, Software und Repositorien welche in unseren Forschungsgemeinschaft " "genutzt werden.")} @@ -64,6 +77,6 @@ md_text_button = {'EN': ("# Further charts\n")} accordion_titles = { - 'EN': ['Global Data Filters', 'Overview', 'Methods, Tools and Software', 'Survey Data Explorer'], - 'DE': ['Globale Datenfilter', 'Überblick', 'Methoden, Werkzeuge und Software', 'Umfrage-explorer'] -} \ No newline at end of file + 'EN': ['Global Data Filters', 'Community Profiles', 'Methods, Tools and Software', 'Survey Data Explorer'], + 'DE': ['Globale Datenfilter', 'Communityprofile', 'Methoden, Werkzeuge und Software', 'Survey Data Explorer'] +} diff --git a/survey_dashboard/main.py b/survey_dashboard/main.py deleted file mode 100644 index e1bf886..0000000 --- a/survey_dashboard/main.py +++ /dev/null @@ -1,774 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################### -# Copyright (c), Forschungszentrum Jülich GmbH, IAS-9, Germany. # -# All rights reserved. # -# This file is part of the survey_dashboard package. # -# # -# The code is hosted on GitHub at # -# https://github.com/Materials-Data-Science-and-Informatics/survey_dashboard # -# For further information on the license, see the LICENSE file # -############################################################################### -""" -This file contains the main code for the dashboard and its layout. -""" -import os -from os.path import dirname, join -import pandas as pd -import panel as pn -from bokeh.palettes import Category20 -from bokeh.models import ColumnDataSource, Div -from .plots import bokeh_barchart, bokeh_piechart, add_legend_at, bokeh_corr_plot -from .plots import create_legend_corr, generate_wordcloud, interactive_wordcloud -from .plots import DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_HEIGHT -from .analysis import calculate_crosstab, prepare_data_research_field, filter_dataframe -from .analysis import percentage_to_area, get_all_values -from .data.display_specifications.hcs_clean_dictionaries import HCSquestions, HCS_orderedCats, HCS_MCsubquestions -from .data.display_specifications.hcs_clean_dictionaries import HCS_colnamesDict, abbrevCenterAffilDict, HCS_MCList -from .data.display_specifications.hcs_clean_dictionaries import HCS_dtypesWOmc, HCS_MCList, HCS_MCsubquestions -from .text_display import * -from .data.display_specifications.hcs_clean_dictionaries import FILTER_OPTIONS, BARCHART_ALLOWED -from .data.display_specifications.hmc_custom_layout import hmc_custom_css_accordion - - -# GLOBAL -LANGUAGE = os.environ.get('LANGUAGE_DASHBOARD', 'EN') #'DE' -ACCORDION_WIDTH = int(DEFAULT_FIGURE_WIDTH*2) # maybe this can be made dynamic. -# This is the only width parameter to which everything streches to - -pn.config.loading_spinner = 'dots' -pn.config.loading_color = '#005AA0' -pn.config.raw_css = [hmc_custom_css_accordion] - -# Specific data configuration for the HMC survey data -HCS_COLNAMES_REVERT_DICT = {val:key for key, val in HCS_colnamesDict.items()} -HCSquestions_revert = {} -HCSquestions_revert[LANGUAGE] = {val:key for key, val in HCSquestions[LANGUAGE].items()} -HCS_MCsubquestions_flattened = {} -for key, val in HCS_MCsubquestions.items(): - for ke, va in val.items(): - HCS_MCsubquestions_flattened[ke] = va - -# if LANGUAGE = 'DE', we translate the data entries because these will often be used as tick labels - - -# Small Helpers functions - -def map_qkey_to_question(key: str, lang:str =LANGUAGE)-> str: - """ - Given a key return the full question to be displayed associated with the key for a given language - """ - mc_key = key - - if key in HCS_MCList: - # Multiple choice, all have the same question for now - mc_key = list(HCS_MCsubquestions[key].keys())[0] - #print(mc_key) - index = HCS_COLNAMES_REVERT_DICT[mc_key].split('/')[0] - #print(index) - else: - index = HCS_COLNAMES_REVERT_DICT[mc_key] - - return HCSquestions[lang][index] - -def map_question_to_qkey(question: str, lang:str =LANGUAGE) -> list: - """ - Map a given question String to the corresponding columns keys in the dataframe - - usually this is one column, but for multiple choice this can be several columns. - """ - column_keys = [] - key = HCSquestions_revert[lang][question] - if key in HCS_MCList: - print(f'Multiple Choice,{key}') - #for multiple choice this is a list of subquestions - key_s = key + '/' - for key in HCS_colnamesDict.keys(): - if key_s in key: - if not 'other' in key: # for now, needs to be included in HCS_MCsubquestions and others is strange - column_keys.append(HCS_colnamesDict[key]) - column_keys.sort() # Wrong sort... _1 _10 _2 ... - else: - column_keys.append(HCS_colnamesDict[key]) - return column_keys - -# create tabs -def construct_tabs(tab_list): - return pn.Tabs(*tab_list)#, dynamic=True) - -pwd = os.getcwd() # TODO better use the absolute location of the main.py file... -datafilepath= join(pwd, 'survey_dashboard/data/hmc_survey_2021_data_cleaned.csv') -if not os.path.exists(datafilepath): - from .data.download_data import download_data - print('Downloading Data') - download_data() - -# For the dashboard presentation, we load some metadata to certain stuff out of the HMC graph. -# However this gets prepared in before in as a new dataframe - -desc = Div(text=open(join(dirname(__file__), "description.html")).read(), sizing_mode="stretch_width") -pwd = os.getcwd() -questions_keys = BARCHART_ALLOWED -questions = [map_qkey_to_question(key) for key in questions_keys] - -# Data displayed on startup: - -# Overview -# TODO combine plots to something nice, high information density -START_DATA_OV1 = map_qkey_to_question("fairFamiliarity") #and ocid and docStructured -START_DATA_OV2 = map_qkey_to_question("yearsInResearch") -START_DATA_OV3 = map_qkey_to_question("researchArea") -START_DATA_OV4 = map_qkey_to_question("pubAmount") - -# Methods: -# Software tools, wordclouds, data generation methods - -# Questions explorer -START_DATA_BAR = map_qkey_to_question("careerLevel") -START_DATA_BAR2 = map_qkey_to_question("docStructured") -START_DATA_CORR_1 = map_qkey_to_question("careerLevel") -START_DATA_CORR_2 = map_qkey_to_question("docStructured") - -FILTER_BY = "researchArea" -FILTER_BY_2 = "dataGenMethod_" - -TOOLTIPS=[ - ("Title", "@title"), - ("Answer", "@x"), - ("Number of Answers", "@y") -] - - -# colors of research areas -#ra_colors = {'All': "#75968f", 'Chemistry': "#a5bab7", 'Earth Science':"#c9d9d3", -#Engineering Science': "#e2e2e2", 'Life Science': "#dfccce", 'Mathematics': "#ddb7b1", -#'Other': "#cc7878", 'Physics': "#933b41", 'Psychology': "#550b1d"} -re_fields = ['All', 'Cum. Sum', 'Chemistry', 'Earth Science', 'Engineering Science', 'Life Science', - 'Mathematics', 'Other', 'Physics', 'Psychology', 'Other'] -re_c = Category20[len(re_fields)] -ra_colors = {field: re_c[i] for i, field in enumerate(re_fields)} - - -# Read data -survey_data = pd.read_csv(datafilepath) - -# Rename columns to something more human Readable: #TODO stay with orginal -survey_data.rename(columns=HCS_colnamesDict, inplace=True) - -# Different sources, because there wil be different filters applied to these. -source = ColumnDataSource(survey_data) -source_corr = ColumnDataSource(survey_data) - - -def select_data(question, data_filters, data_filters_method, filter_by=FILTER_BY): - """Select the data to display""" - print(question) - q_index = map_question_to_qkey(question) - print(q_index) - q_index_0 = q_index[0] - question_full = question - to_exclude = [] - - # due to data cleaning some columns are removed... - # we ignore them if they are not in the index.... to avoid KeyErrors - q_index_clean = [] - keys = list(survey_data.keys()) - for key in q_index: - if key in keys: - q_index_clean.append(key) - - exclude_nan = True - if len(q_index) >1: - exclude_nan = False - - method_include = [] - method_exclude = [] - methods_dict = HCS_MCsubquestions[FILTER_BY_2] - for method in data_filters_method: - for key, val in methods_dict.items(): - if val == method: - method_include.append(key) - # Cut out the rows out the ones who provided False - method_exclude.append((key, [False])) - #print(list(set([FILTER_BY]+ q_index_clean + method_include))) - #print(method_exclude) - - - include_clean = list(set([FILTER_BY]+ q_index_clean + method_include)) - # for now this is greedy, if too slow think of another way - # we want to display anything in terms of researchArea, todo better was to filter, generalize this - df = filter_dataframe(survey_data, include=include_clean, exclude=method_exclude, exclude_nan=exclude_nan)# [(q_index, to_exclude)]+ - data_all = get_all_values(df, q_index_clean, display_dict=HCS_MCsubquestions_flattened) - - exclude = [] - for field in re_fields: - if field not in data_filters: - exclude.append(field) - for filter_key in exclude: - df = df[df[filter_by] != filter_key] - data, y_keys = prepare_data_research_field(df, q_index) # this add also Cum. Sum. - if 'All' in data_filters: - data['All'] = data_all['All'] - #print(data) - # We create two ColumnDataSources, because they have to be n*n and - # it is therefore not posible to put all specifics into one - ydata_spec = {} - colors = [] - for key in data_filters: - colors.append(ra_colors[key]) - - # Enforced order of x and y axis - xtype = None - if q_index_0 in HCS_dtypesWOmc.keys(): - xtype = HCS_dtypesWOmc[q_index_0] - - if len(q_index) >1: # multiple choice case - x_range = data['x_value'] - width = 0.1 - elif xtype == 'category': - x_range = HCS_orderedCats[q_index_0] - width = 0.1 - else: - x_range = None - width = 0.6 - y_range = None - - - ydata_spec['y_keys'] = data_filters - ydata_spec['colors'] = colors - ydata_spec['legend_labels'] = data_filters - selected = ColumnDataSource(data=data) - ydata_spec = ColumnDataSource(data=ydata_spec) - - display_options = {'x_range' : x_range, 'y_range': y_range, - 'title': f'{question_full}', 'width': width} - #print(display_options) - return selected, ydata_spec, display_options - - - -def select_data_corr(question, question2, data_filters, data_filters_method): - """Select the data to display in the correlation vis""" - - q1_key = map_question_to_qkey(question) - q2_key = map_question_to_qkey(question2) - q1_index_0 = q1_key[0] - q2_index_0 = q2_key[0] - # Enforced order of x and y axis - # If something is not a category, use default instead - xtype = None - if q1_index_0 in HCS_dtypesWOmc.keys(): - xtype = HCS_dtypesWOmc[q1_index_0] - - if xtype == 'category': - x_range = HCS_orderedCats[q1_index_0] - else: - x_range = None - - ytype = None - if q2_index_0 in HCS_dtypesWOmc.keys(): - ytype = HCS_dtypesWOmc[q2_index_0] - if ytype == 'category': - y_range = HCS_orderedCats[q2_index_0] - else: - y_range = None - - q1_key_clean = [] - keys = list(survey_data.keys()) - for key in q1_key: - if key in keys: - q1_key_clean.append(key) - - q2_key_clean = [] - for key in q2_key: - if key in keys: - q2_key_clean.append(key) - - exclude_nan = True - if len(q1_key) >1: - exclude_nan = False - - - method_include = [] - method_exclude = [] - methods_dict = HCS_MCsubquestions[FILTER_BY_2] - for method in data_filters_method: - for key, val in methods_dict.items(): - if val == method: - method_include.append(key) - # Filter out the one who provided False - method_exclude.append((key, [False])) - - exclude_area = [] - for field in re_fields: - if field not in data_filters: - pass - #exclude_area.append(("researchArea", [field])) - #exclude_areas = ["researchArea", exclude_area] - - include_clean = list(set([FILTER_BY]+ q2_key_clean + q1_key_clean + method_include)) - - # If this is slow to calculate each time, it might make sense to calculate all of these - # at start up. i.e n^2 tables, with arbitray filters not possible - df = filter_dataframe(survey_data, include=include_clean, exclude=method_exclude, exclude_nan=exclude_nan) - - # if list, merge somehow..., multi column crosstab - - - cross_tab = calculate_crosstab(df, q1_index_0, q2_index_0) - # marker size is radius, we want the Area to be proportional to the value - # we also scale the markers with the max values are to small, or depending how many Cat, or - # figure width... - marker_scale = 20.0 - cross_tab['markersize'] = percentage_to_area(cross_tab['percentage'], scale_m=marker_scale) - cross_tab['x_values'] = cross_tab[q1_index_0] - cross_tab['y_values'] = cross_tab[q2_index_0] - cross_tab['color'] = ['#A0235A' for i in cross_tab[q2_index_0]] - - # for hover tool - tooltips = [(f"{q1_key[0]}", "@x_values"), - (f"{q2_key[0]}", "@y_values"), - ("total", "@total"), - ("percentage", "@percentage")] - - title = f''#{q1_key[0]} in dependence to {q2_key[0]}' - xlabel = f'{question}' - ylabel = f'{question2}' - - # Bokeh plots need a ColumnDataSource, but this can be initialized from a pandas - selected = ColumnDataSource(cross_tab) - - display_options = {'x_range' : x_range, 'y_range' : y_range, 'xlabel': xlabel, 'ylabel': ylabel, - 'title': title, 'tooltips' : tooltips} - - return selected, display_options, marker_scale - -def select_data_wordcloud(data_filters, data_filters_method, content=['dataGenMetdataGenMethodSpec_hodSpec_']): - """ - Filter data for wordcloud from data filters - """ - word_list = [] - - method_include = [] - method_exclude = [] - methods_dict = HCS_MCsubquestions[FILTER_BY_2] - method_keys = list(methods_dict.keys()) - for method in data_filters_method: - for key in method_keys: - if methods_dict[key] == method: - method_include.append(key) - # Filter out the one who provided False - method_exclude.append((key, [False])) - - if len(data_filters_method) == 0: - method_include = method_keys - method_exclude = [] - - - data_include = [] - if 'dataGenMethodSpec_' in content: - for i, method in enumerate(method_include): - id_meth = method[-1] - if id_meth == 'r': # From other - id_meth = i+1 - data_include.append('dataGenMethodSpec_{}_1'.format(id_meth)) - data_include.append('dataGenMethodSpec_{}_2'.format(id_meth)) - data_include.append('dataGenMethodSpec_{}_3'.format(id_meth)) - else: - data_include = content - df = filter_dataframe(survey_data, include=[FILTER_BY]+method_include+data_include, exclude=method_exclude, as_type ='str') - exclude = [] - for field in re_fields: - if field not in data_filters: - exclude.append(field) - if 'All' in data_filters: - exclude = [] - for area in exclude: - df = df[df[FILTER_BY] != area] - #print(list(df.keys())) - #print(data_include) - # prepare word list - word_list = [] - for method in data_include: - #print(df[method]) - w_list = [word for word in df[method] if str(word)!='nan'] - word_list = word_list + w_list #ent.replace(' ', '-') # Add '-' - - - return word_list - - -##### Widgets - - -#### Control widgets - -# global filters -# section probably better than tabs.. -#tab1 = ("Filter research area", fig) -#tab2 = ("Filter HFG field", fig2) -#filter_tabs = pn.Tabs(*[tab1, tab2]) - -multi_choice = pn.widgets.MultiChoice(name=md_text_global_filters_widgets[0][LANGUAGE], value=["All"], options=FILTER_OPTIONS['researchArea']) -multi_choice_method = pn.widgets.MultiChoice(name=md_text_global_filters_widgets[1][LANGUAGE], value=[], options=FILTER_OPTIONS['method']) -#multi_choice_hgf_field = pn.widgets.MultiChoice(name="Filter by HGF research field (Each selected will be shown)", value=["All"], options=FILTER_OPTIONS['HGFresearchfield']) -# for careerlevel there can be only one, so we use a Multiselect instead -#select_careerlevel = pn.widgets.Select(name="Filter by career level.", value=[], options=FILTER_OPTIONS['careerLevel']) -#multi_choice_facility = pn.widgets.MultiChoice(name="Filter by career level.", value=[], options=FILTER_OPTIONS['LargeScaleFacility']) - -# Bar chart -# D: question select could also be a slider? -# TODO: get filter options for question -question_select = pn.widgets.Select(name=md_text_select_widgets[0][LANGUAGE], value=START_DATA_BAR, - options=questions)#, description="Select the survey question, which results should be displayed.") - -multi_filter = pn.widgets.MultiChoice(name="Filter by data by question specific filter", value=[], - options=FILTER_OPTIONS['method'], visible=False) - -question_select2 = pn.widgets.Select(name=md_text_select_widgets[1][LANGUAGE], value=START_DATA_BAR2, - options=questions)#, description="Select the survey question, which results should be displayed.") - -multi_filter2 = pn.widgets.MultiChoice(name="Filter by data by question specific filter", value=[], - options=FILTER_OPTIONS['method'], visible=False) - - - -# D: better than a Select would be to use the HMC template for this... -# D: Maybe have two dashboards running a German and a English one and link build in the link in the template... -#lang_select = Select(title="Language", value="en", -# options=['en', 'de'], description="Change the language of the Dashboard.") - -chart_select1 = pn.widgets.Select(title="Visualization type", value="Vertical Bar chart", - options=['Vertical Bar chart', 'Horizontal Bar chart', 'Pie chart']) -chart_select2 = pn.widgets.Select(title="Visualization type", value="Vertical Bar chart", - options=['Vertical Bar chart', 'Horizontal Bar chart', 'Pie chart']) - -# Correlation plot -# Not every question can be correlated with every question? -#question_select_corr2 = pn.widgets.Select(name="Question X-Axis", value=START_DATA_CORR_1, -# options=questions)#, description="Select the survey question which results should be displayed on the X-Axis.") -#question_select_corr3 = pn.widgets.Select(name="Question Y-Axis", value=START_DATA_CORR_2, -# options=questions)#, description="Select the survey question which results should be displayed on the Y-Axis.") - - -# Others -plot_aspect_ratio_select = pn.widgets.Select(name="Filter data", value="Cum. Sum", - options=FILTER_OPTIONS) -menu = ['Barchart', 'Correlation Plot']#('Barchart', 'bar_chart'), ('Correlation Plot', '(corr_plot')] -button_bar = pn.widgets.Select(name="Add a chart", options=menu) - - -def generate_global_filters(): - g_filters = [multi_choice, multi_choice_method] - return g_filters - - -def generate_bar_controls(): - controls_bar = [question_select, multi_filter, chart_select1] - return controls_bar - -#def generate_corr_controls(): -# controls_corr = [question_select_corr2, question_select_corr3] -# return controls_corr - -#################################### -# Generate Start figures and panes # -#################################### -# TODO, just trigger updates... -data_filters = multi_choice.value -data_filters_method = multi_choice_method.value -print('creating starting figures') - -start_display_data, ydata_spec, display_options= select_data(question_select.value, data_filters, data_filters_method) -y_keys = ydata_spec.data['y_keys'] -fill_colors = ydata_spec.data['colors'] - - -#fig = pn.pane.Bokeh(bokeh_barchart(start_display_data, y=y_keys, factors=y_keys, legend_labels=y_keys, -# fill_color=fill_colors, orientation='vertical', **display_options)) - -fig_exp1 = pn.pane.Bokeh(bokeh_barchart(start_display_data, y=y_keys, factors=y_keys, legend_labels=y_keys, - fill_color=fill_colors, orientation='vertical', **display_options)) - -start_display_data, ydata_spec, display_options= select_data(question_select2.value, data_filters, data_filters_method) -y_keys = ydata_spec.data['y_keys'] -fill_colors = ydata_spec.data['colors'] -fig_exp2 = pn.pane.Bokeh(bokeh_barchart(start_display_data, y=y_keys, factors=y_keys, legend_labels=y_keys, - fill_color=fill_colors, orientation='vertical', **display_options)) - -start_corr_data, display_options_corr, marker_scale = select_data_corr(question_select.value, - question_select2.value, data_filters, data_filters_method) -fig_corr_1 = bokeh_corr_plot(start_corr_data, **display_options_corr) -fig_corr = pn.pane.Bokeh(fig_corr_1) -leg_corr = pn.pane.Bokeh(create_legend_corr(fig_corr_1, colors=start_corr_data.data['color'], scale_m=marker_scale)) - -# Overview: - -#fig_ov1, fig_ov2, fig_ov3, fig_ov4 = generate_overview() -# for now place holders... -start_display_data, ydata_spec, display_options= select_data(START_DATA_OV1, data_filters, data_filters_method) -y_keys = ydata_spec.data['y_keys'] -fig_ov1 = pn.pane.Bokeh(bokeh_barchart(start_display_data, y=y_keys, factors=y_keys, legend_labels=y_keys, - fill_color=ydata_spec.data['colors'], orientation='vertical', **display_options)) - -start_display_data, ydata_spec, display_options= select_data(START_DATA_OV2, data_filters, data_filters_method) -y_keys = ydata_spec.data['y_keys'] -fig_ov2 = pn.pane.Bokeh(bokeh_barchart(start_display_data, y=y_keys, factors=y_keys, legend_labels=y_keys, - fill_color=ydata_spec.data['colors'], orientation='vertical', **display_options)) - -start_display_data, ydata_spec, display_options= select_data(START_DATA_OV3, data_filters, data_filters_method) -y_keys = ydata_spec.data['y_keys'] -fig_ov3 = pn.pane.Bokeh(bokeh_barchart(start_display_data, y=y_keys, factors=y_keys, legend_labels=y_keys, - fill_color=ydata_spec.data['colors'], orientation='vertical', **display_options)) - -start_display_data, ydata_spec, display_options= select_data(START_DATA_OV4, data_filters, data_filters_method) -y_keys = ydata_spec.data['y_keys'] -fig_ov4 = pn.pane.Bokeh(bokeh_barchart(start_display_data, y=y_keys, factors=y_keys, legend_labels=y_keys, - fill_color=ydata_spec.data['colors'], orientation='vertical', **display_options)) - - -# Methods, Software and repos - -half_width = int(ACCORDION_WIDTH/2) -# Wordcloud of methods #RSDP2b -text_list = select_data_wordcloud(data_filters, data_filters_method, content=["dataGenMethodSpec_"]) -wordcloud = generate_wordcloud(text_list, height=DEFAULT_FIGURE_HEIGHT, width=half_width) -svg_pane = pn.pane.Bokeh(interactive_wordcloud(wordcloud), width=wordcloud.width, height=wordcloud.height) -#pn.pane.SVG(wordcloud.to_svg(), width=wordcloud.width, height=wordcloud.height) - -# Wordcloud of software #RDMPR10 -text_list = select_data_wordcloud(data_filters, data_filters_method, content=["software_1", "software_2", "software_3"]) -wordcloud_soft = generate_wordcloud(text_list, height=DEFAULT_FIGURE_HEIGHT, width=half_width) -svg_pane_software = pn.pane.Bokeh(interactive_wordcloud(wordcloud_soft), width=wordcloud.width, height=wordcloud.height) -#pn.pane.SVG(wordcloud_soft.to_svg(), width=wordcloud_soft.width, height=wordcloud_soft.height) - -# Wordcloud of repos #DTPUB5 -text_list = select_data_wordcloud(data_filters, data_filters_method, content=["pubRepo_1", "pubRepo_2", "pubRepo_3", "pubRepo_4", "pubRepo_5"]) -wordcloud_repo = generate_wordcloud(text_list, height=DEFAULT_FIGURE_HEIGHT, width=half_width) -svg_pane_repo = pn.pane.Bokeh(interactive_wordcloud(wordcloud_repo), width=wordcloud.width, height=wordcloud.height) -#pn.pane.SVG(wordcloud_repo.to_svg(), width=wordcloud_repo.width, height=wordcloud_repo.height) - - -# - - -def update(target, event, question_sel, f_choice, m_choice, q_filter, charttype): - """Update the charts - - The target will be replaced, the event contains what interaction was trickered. - Here we assume value change, because no others where allowed. - """ - print(event) - question = question_sel#.value - data_filters = f_choice.value - data_filters_method = m_choice.value - charttype = charttype#.value - - df, ydata_spec, display_options = select_data(question, data_filters, data_filters_method) - source = df - - y_keys = ydata_spec.data['y_keys'] - fill_colors = ydata_spec.data['colors'] - if charttype == 'Vertical Bar chart': - fig = bokeh_barchart(source, y=y_keys, factors=y_keys, legend_labels=y_keys, fill_color=fill_colors, orientation='vertical', **display_options)#df.data['factors'], legend_labels='legend_labels')#, figure=figure) - elif charttype == 'Horizontal Bar chart': - y_range = display_options['y_range'] - display_options['y_range'] = display_options['x_range'] - display_options['x_range'] = y_range - # TODO change tooltips... - fig = bokeh_barchart(source, y=y_keys, factors=y_keys, legend_labels=y_keys, - fill_color=fill_colors, orientation='horizontal', xlabel='Number of Answers', ylabel='', **display_options)#'horizontal')#df.data['factors'], legend_labels='legend_labels')#, figure=figure) - elif charttype == "Pie chart": - display_options.pop('x_range') - display_options.pop('y_range') - display_options.pop('width') - fig = bokeh_piechart(source, y=y_keys, legend_labels=y_keys, - fill_color=fill_colors, **display_options) - #else: - # fig = None - # print(f'This chart type does not exists: {charttype}') - target.object = fig - - -def update_corr(target, event, question_sel, question_sel2, f_choice, m_choice): - """Update the correlation plot""" - - print(event) - print('correlation_plot') - question = question_sel.value - question2 = question_sel2.value - data_filters = f_choice.value - data_filters_method = m_choice.value - df, display_options, marker_scale = select_data_corr(question, question2, data_filters, data_filters_method) - print(df.data) - print(display_options) - fig_corr = bokeh_corr_plot(df, **display_options) - leg_corr = create_legend_corr(fig_corr, colors=df.data['color'], scale_m=marker_scale) - - target.object = fig_corr - - -def update_wordcloud(target, event, f_choice, m_choice, content): - """Update the correlation plot""" - - print(event) - data_filters = f_choice.value - data_filters_method = m_choice.value - - text_list = select_data_wordcloud(data_filters, data_filters_method, content=content) - wordcloud = generate_wordcloud(text_list, height=DEFAULT_FIGURE_HEIGHT, width=DEFAULT_FIGURE_WIDTH) - target.object = interactive_wordcloud(wordcloud)#wordcloud.to_svg() - - -# TODO It would be better performance wise to filter one time and update all plots -# But I did not figure out how to update a full bunch of things and not only the give instance -# So the update function has to be splitted to archive/cache the filtered data somehow... - -def gen_update_overview1(target, event): - f_choice, m_choice = multi_choice, multi_choice_method - question_sel = START_DATA_OV1 - update(target, event, question_sel, f_choice, m_choice, q_filter=None, - charttype='Vertical Bar chart') - -def gen_update_overview2(target, event): - f_choice, m_choice = multi_choice, multi_choice_method - question_sel = START_DATA_OV2 - update(target, event, question_sel, f_choice, m_choice, q_filter=None, - charttype='Vertical Bar chart') - -def gen_update_overview3(target, event): - f_choice, m_choice = multi_choice, multi_choice_method - question_sel = START_DATA_OV3 - update(target, event, question_sel, f_choice, m_choice, q_filter=None, - charttype='Vertical Bar chart') - -def gen_update_overview4(target, event): - f_choice, m_choice = multi_choice, multi_choice_method - question_sel = START_DATA_OV4 - update(target, event, question_sel, f_choice, m_choice, q_filter=None, charttype='Vertical Bar chart') - -def gen_update_exp1(target, event): - f_choice, m_choice, = multi_choice, multi_choice_method - question_sel, q_filter, charttype = question_select.value, multi_filter, chart_select1.value - update(target, event, question_sel, f_choice, m_choice, q_filter, charttype) - -def gen_update_exp2(target, event): - f_choice, m_choice, = multi_choice, multi_choice_method - question_sel, q_filter, charttype = question_select2.value, multi_filter2, chart_select2.value - update(target, event, question_sel, f_choice, m_choice, q_filter, charttype) - -def gen_update_corr(target, event): - f_choice, m_choice = multi_choice, multi_choice_method - question_sel = question_select - question_sel2 = question_select2 - update_corr(target, event, question_sel, question_sel2, f_choice, m_choice) - -def gen_update_wc_methods(target, event): - f_choice, m_choice = multi_choice, multi_choice_method - content = ["dataGenMethodSpec_"] - update_wordcloud(target, event, f_choice, m_choice, content) - -def gen_update_wc_software(target, event): - f_choice, m_choice = multi_choice, multi_choice_method - content = ["software_1", "software_2", "software_3"] - update_wordcloud(target, event, f_choice, m_choice, content) - -def gen_update_wc_repo(target, event): - f_choice, m_choice = multi_choice, multi_choice_method - content = ["pubRepo_1", "pubRepo_2", "pubRepo_3", "pubRepo_4", "pubRepo_5"] - update_wordcloud(target, event, f_choice, m_choice, content) - -# Register Links between widgets and plots and their respective callbacks - -g_filters = generate_global_filters() -for control in g_filters: - control.link(fig_exp1, callbacks={'value': gen_update_exp1}) - control.link(fig_exp2, callbacks={'value': gen_update_exp2}) - control.link(svg_pane, callbacks={'value': gen_update_wc_methods}) - control.link(svg_pane_software, callbacks={'value': gen_update_wc_software}) - control.link(svg_pane_repo, callbacks={'value': gen_update_wc_repo}) - control.link(fig_corr, callbacks={'value': gen_update_corr}) - control.link(fig_ov1, callbacks={'value': gen_update_overview1}) - control.link(fig_ov2, callbacks={'value': gen_update_overview2}) - control.link(fig_ov3, callbacks={'value': gen_update_overview3}) - control.link(fig_ov4, callbacks={'value': gen_update_overview4}) - -controls_bar = generate_bar_controls() -for control in controls_bar: - control.link(fig_exp1, callbacks={'value': gen_update_exp1}) - control.link(fig_corr, callbacks={'value': gen_update_corr}) - -controls_bar2 = [question_select2, multi_filter2, chart_select2] -for control in controls_bar2: - control.link(fig_exp2, callbacks={'value': gen_update_exp2}) - control.link(fig_corr, callbacks={'value': gen_update_corr}) - -#controls_corr = generate_corr_controls() -#for control in controls_corr: -# control.link(fig_corr, callbacks={'value': gen_update_corr}) - -#################### -# Dashboard layout # -#################### -print('Creating layout') -# Layout with Panel -# We provide the layout in this explicit way and not all in one list because first -# we addressed the objects over the rows name, now this may be obsolete - - - -# Global data filters - -row1 = pn.Column(md_text_global_filter[LANGUAGE], g_filters[0], g_filters[1], sizing_mode="scale_width") - -global_filters_sec = row1 - -# Overview part -overview_sec = pn.Column(md_text_overview[LANGUAGE], pn.Row(fig_ov3, fig_ov2), pn.Row(fig_ov1, fig_ov4)) - - -# Tools -row4 = pn.Column(md_text_tools_used[LANGUAGE], "## Research and Data Generation Methods :\n", svg_pane, "## Main Software in use:\n", svg_pane_software,"## Repositories Data published in:\n", svg_pane_repo) -methods_tools_sec = row4 - - -# Question Explorer -# Merge Question explorer and Correlation explorer, allow two questions side by side? - - -# section probably better than tabs.. -#tab1 = ("Vertical Bar chart", fig) -#tab2 = ("Horizontal Bar chart", fig2) -#tab3 = ("Pie chart", fig3) -#tabs = construct_tabs([tab1, tab2, tab3]) - -inputs = pn.Column(*controls_bar, width=half_width) -inputs2 = pn.Column(*controls_bar2, width=half_width) -row2 = pn.Column(pn.Row(inputs, inputs2), pn.Row(fig_exp1, fig_exp2)) -# Correlation -#inputs_corr = pn.Column(*controls_corr, width=800) -row3 = pn.Column(md_text_corrchart[LANGUAGE], pn.Row(fig_corr, leg_corr)) -coree_ex_sec = row3 -question_ex_sec = pn.Column(md_text_barchart[LANGUAGE], row2, row3) - - -#row5 = pn.Row(button_bar) -#layout = pn.Column(row1, md_text_barchart, row2, md_text_corrchart, row3, row4, -# sizing_mode="scale_both", title='HMC Survey Dashboard') -#md_text_button, row4, sizing_mode="scale_both", title='HMC Survey Dashboard') - - -# Depending on the layout these could also be in tabs, but then they cannot be viewed together... -overall_accordion = pn.Accordion((accordion_titles[LANGUAGE][0], global_filters_sec), - (accordion_titles[LANGUAGE][1], overview_sec), - (accordion_titles[LANGUAGE][2], methods_tools_sec), - (accordion_titles[LANGUAGE][3], question_ex_sec), sizing_mode="scale_both")#, css_classes=['accordion', 'accordion-header'])#, - #('Correlation explorer', coree_ex_sec)) -overall_accordion.active = [0,3]#[0,1] -overall_accordion.scroll = True -overall_accordion.margin = 0 -overall_accordion.width = ACCORDION_WIDTH -overall_accordion.min_width = ACCORDION_WIDTH - -layout = pn.Column(desc, md_text_description[LANGUAGE], overall_accordion) -layout.servable(title='HMC Survey Data Explorer') -print('All done') \ No newline at end of file diff --git a/survey_dashboard/plots.py b/survey_dashboard/plots.py index 80771af..9fe6cde 100644 --- a/survey_dashboard/plots.py +++ b/survey_dashboard/plots.py @@ -15,6 +15,12 @@ from functools import wraps from collections import Counter from bokeh.models import ColumnDataSource + +from bokeh.models import HelpTool +from bokeh.models import HoverTool +from bokeh.models import Range1d +from bokeh.transform import dodge + from bokeh.plotting import figure as bokeh_figure from bokeh.palettes import Category20c #from bokeh.transform import factor_cmap @@ -102,6 +108,47 @@ def add_legend_at(fig, position='right'): "width": int(DEFAULT_FIGURE_WIDTH*1.5), "height": int(DEFAULT_FIGURE_HEIGHT*1.5)} } +pie_theme = { + "figure_kwargs" : { + "background_fill_color" : '#00000000', #transparent + "border_fill_color" : '#00000000', + # Note: No x_range.range_padding for pie charts as they use numeric ranges + "xgrid.grid_line_color": None, + "xaxis.major_label_orientation": 1, + "title.text_font_size": '18px', + "yaxis.axis_label_text_font_size": '18px', + "xaxis.axis_label_text_font_size": '18px', + "xaxis.major_label_text_font_size": '16px', + "yaxis.major_label_text_font_size": '16px', + "toolbar.logo": None, + "toolbar_location": "right", + "legend.location": "top_right", + "legend.orientation": "vertical", + "legend.click_policy": "hide", + "width": DEFAULT_FIGURE_WIDTH, + "height": DEFAULT_FIGURE_HEIGHT} +} + +horizontal_theme = { + "figure_kwargs" : { + "background_fill_color" : '#00000000', #transparent + "border_fill_color" : '#00000000', + # Note: No x_range.range_padding for horizontal bars as x_range is numeric + "xgrid.grid_line_color": None, + "xaxis.major_label_orientation": 1, + "title.text_font_size": '18px', + "yaxis.axis_label_text_font_size": '18px', + "xaxis.axis_label_text_font_size": '18px', + "xaxis.major_label_text_font_size": '16px', + "yaxis.major_label_text_font_size": '16px', + "toolbar.logo": None, + "toolbar_location": "right", + "legend.location": "top_right", + "legend.orientation": "vertical", + "legend.click_policy": "hide", + "width": DEFAULT_FIGURE_WIDTH, + "height": DEFAULT_FIGURE_HEIGHT} +} @@ -137,7 +184,7 @@ def rek_set_attr(obj: object, key: str, val:object) -> None: """ Recursively assigns to a given object and a key in dot notation a given value of any form - Example: + Example: 1. rek_set_attr(figure, title, 'my-title') figure.title= 'my-title' @@ -145,6 +192,10 @@ def rek_set_attr(obj: object, key: str, val:object) -> None: rek_set_attr(figure, axis.xaxis.label.size, 10) figure.axis.xaxis.label.size = 10 """ + # Skip legend properties if the plot has no legend + if key.startswith('legend.') and hasattr(obj, 'legend') and not obj.legend: + return + if not '.' in key: return setattr(obj, key, val) else: @@ -153,112 +204,152 @@ def rek_set_attr(obj: object, key: str, val:object) -> None: key_new = ".".join(ke for ke in keys[1:]) return rek_set_attr(obj2, key_new, val) +# DONE: Refactored this function heavily to get the plots to work +def bokeh_barchart(df, x='x_value', y=['y_value'], factors=None, figure=None, data_visible=[True], title='', + width=0.1, xlabel='', ylabel='Number of answers', palette=Category20c, + fill_color=None, legend_labels=None, description='For more information about the HMC survey click here.', + redirect='https://helmholtz-metadaten.de/en/', orientation='vertical', x_range=None, y_range=None,**kwargs): + """Create an interactive bar chart with bokeh""" + + # Choose theme based on orientation + if orientation == 'horizontal': + return _bokeh_barchart_horizontal(df, x, y, factors, figure, data_visible, title, + width, xlabel, ylabel, palette, fill_color, legend_labels, + description, redirect, orientation, x_range, y_range, **kwargs) + else: + return _bokeh_barchart_vertical(df, x, y, factors, figure, data_visible, title, + width, xlabel, ylabel, palette, fill_color, legend_labels, + description, redirect, orientation, x_range, y_range, **kwargs) +@apply_theme(theme=horizontal_theme) +def _bokeh_barchart_horizontal(df, x='x_value', y=['y_value'], factors=None, figure=None, data_visible=[True], title='', + width=0.1, xlabel='', ylabel='Number of answers', palette=Category20c, + fill_color=None, legend_labels=None, description='For more information about the HMC survey click here.', + redirect='https://helmholtz-metadaten.de/en/', orientation='vertical', x_range=None, y_range=None,**kwargs): + """Internal function for horizontal bar charts with horizontal theme""" + return _bokeh_barchart_impl(df, x, y, factors, figure, data_visible, title, + width, xlabel, ylabel, palette, fill_color, legend_labels, + description, redirect, orientation, x_range, y_range, **kwargs) +@apply_theme(theme=default_theme) +def _bokeh_barchart_vertical(df, x='x_value', y=['y_value'], factors=None, figure=None, data_visible=[True], title='', + width=0.1, xlabel='', ylabel='Number of answers', palette=Category20c, + fill_color=None, legend_labels=None, description='For more information about the HMC survey click here.', + redirect='https://helmholtz-metadaten.de/en/', orientation='vertical', x_range=None, y_range=None,**kwargs): + """Internal function for vertical bar charts with default theme""" + return _bokeh_barchart_impl(df, x, y, factors, figure, data_visible, title, + width, xlabel, ylabel, palette, fill_color, legend_labels, + description, redirect, orientation, x_range, y_range, **kwargs) -@apply_theme() -def bokeh_barchart(df, x='x_value', y=['y_value'], factors=None, figure=None, data_visible=[True], title='', +def _bokeh_barchart_impl(df, x='x_value', y=['y_value'], factors=None, figure=None, data_visible=[True], title='', width=0.1, xlabel='', ylabel='Number of answers', palette=Category20c, fill_color=None, legend_labels=None, description='For more information about the HMC survey click here.', redirect='https://helmholtz-metadaten.de/en/', orientation='vertical', x_range=None, y_range=None,**kwargs): - """Create an interactive bar chart with bokeh - - :param df: [description] - :type df: bokeh.models.ColumnDataSource - :param x: [description], defaults to 'x_value' - :type x: str, optional - :param y: [description], defaults to ['y_value'] - :type y: list, optional - :param factors: [description], defaults to None - :type factors: [type], optional - :param figure: [description], defaults to None - :type figure: [type], optional - :param data_visible: [description], defaults to [True] - :type data_visible: list, optional - :param title: [description], defaults to '' - :type title: str, optional - :param width: [description], defaults to 0.1 - :type width: float, optional - :param xlabel: [description], defaults to '' - :type xlabel: str, optional - :param ylabel: [description], defaults to 'Number of answers' - :type ylabel: str, optional - :param palette: [description], defaults to Category20c - :type palette: [type], optional - :param fill_color: [description], defaults to None - :type fill_color: [type], optional - :param legend_labels: [description], defaults to None - :type legend_labels: [type], optional - :param description: [description], defaults to 'For more information about the HMC survey click here.' - :type description: str, optional - :param redirect: [description], defaults to 'https://helmholtz-metadaten.de/en/pages/structure-governance' - :type redirect: str, optional - :return: [description] - :rtype: [type] - """ + """Internal implementation of bar chart creation""" + y_keys = y source = df - #print(y, x) - #print(df.column_names) help_t = HelpTool(description=description, redirect=redirect) tools = 'wheel_zoom,box_zoom,undo,reset,save' - #if x_range is None: - # x_range = source.data[x] - fig = bokeh_figure(x_range=x_range, y_range=y_range, title=title, #y_range=(0, 280), - height=DEFAULT_FIGURE_HEIGHT, width=DEFAULT_FIGURE_WIDTH, toolbar_location='above', tools=tools) + + # Use the provided ranges or calculate defaults + if x_range is None: + if x in source.data: + x_range = source.data[x] + else: + x_range = ['Category 1', 'Category 2', 'Category 3'] + + # Convert numerical lists to strings for categorical data + if isinstance(x_range, list) and len(x_range) > 0 and isinstance(x_range[0], (int, float)): + x_range = [str(val) for val in x_range] + + #if y_range is None: + # Calculate numerical range from actual data values + max_values = [] + for y_key in y_keys: + if y_key in source.data: + max_values.extend(source.data[y_key]) + + if max_values: + numerical_max = max(max_values) + numerical_range = (0, numerical_max * 1.1) + else: + numerical_range = (0, 10) # Fallback default range + + # Set up ranges based on orientation + if orientation == 'vertical': + # Vertical: categorical on x-axis, numerical on y-axis + fig_x_range = x_range + fig_y_range = numerical_range + fig_xlabel = xlabel + fig_ylabel = ylabel + else: + # Horizontal: categorical on y-axis, numerical on x-axis + fig_x_range = numerical_range + fig_y_range = x_range + fig_xlabel = ylabel + fig_ylabel = xlabel + + # Create figure + fig = bokeh_figure(x_range=fig_x_range, y_range=fig_y_range, title=title, + height=DEFAULT_FIGURE_HEIGHT, width=DEFAULT_FIGURE_WIDTH, + toolbar_location='above', tools=tools) + fig.add_tools(help_t) + # Calculate bar positions for multiple series nvisible = len(y_keys) step = width + 0.05 - if nvisible%2 == 0: - start = -step*nvisible/2 + step/2.0 - elif nvisible==1: + if nvisible % 2 == 0: + start = -step * nvisible / 2 + step / 2.0 + elif nvisible == 1: start = 0.0 else: - start = nvisible//2 * -step + start = nvisible // 2 * -step - position = [start + i*step for i in range(len(y))] - tooltips=[(f'{x}', f'@{x}')] + position = [start + i * step for i in range(len(y_keys))] + tooltips = [(f'{x}', f'@{x}')] bars = [] - - #for i, y in enumerate(y_keys): - # bar = fig.vbar(x=dodge(x, position[i], range=fig.x_range), top=y, source=source, - # width=width, color=fill_color[i], legend_label=y, **kwargs) - for i, y in enumerate(y_keys): - if orientation=='vertical': - bar = fig.vbar(x=dodge(x, position[i], range=fig.x_range), top=y, source=source, - width=width, color=fill_color[i], legend_label=y, selection_fill_color='black', - selection_fill_alpha=0.8, - nonselection_fill_alpha=0.2, - nonselection_fill_color="blue", - selection_line_color="black", fill_alpha=0.8, - nonselection_line_alpha=0.5, hover_fill_alpha=1.0, - hover_line_color="black", hover_line_width=5.0, **kwargs) - fig.y_range.start = 0 - else: # orientation=='horizontal': - bar = fig.hbar(y=dodge(x, position[i], range=fig.y_range), right=y, source=source, - height=width, color=fill_color[i], legend_label=y, selection_fill_color='black', selection_fill_alpha=0.8, - nonselection_fill_alpha=0.2, - nonselection_fill_color="blue", - selection_line_color="black", fill_alpha=0.8, - nonselection_line_alpha=0.5, hover_fill_alpha=1.0, - hover_line_color="black", hover_line_width=5.0, **kwargs) - fig.x_range.start = 0 - - tooltips.append((f'{y}', '@{' + str(y) + '}')) + + # Create bars based on orientation + for i, y_key in enumerate(y_keys): + if orientation == 'vertical': + # Vertical bars: dodge along x-axis (categorical) + bar = fig.vbar(x=dodge(x, position[i], range=fig.x_range), + top=y_key, source=source, + width=width, color=fill_color[i], legend_label=y_key, + selection_fill_color='black', selection_fill_alpha=0.8, + nonselection_fill_alpha=0.2, nonselection_fill_color="blue", + selection_line_color="black", fill_alpha=0.8, + nonselection_line_alpha=0.5, hover_fill_alpha=1.0, + hover_line_color="black", hover_line_width=5.0, **kwargs) + else: + # Horizontal bars: dodge along y-axis (categorical) + bar = fig.hbar(y=dodge(x, position[i], range=fig.y_range), + right=y_key, source=source, + height=width, color=fill_color[i], legend_label=y_key, + selection_fill_color='black', selection_fill_alpha=0.8, + nonselection_fill_alpha=0.2, nonselection_fill_color="blue", + selection_line_color="black", fill_alpha=0.8, + nonselection_line_alpha=0.5, hover_fill_alpha=1.0, + hover_line_color="black", hover_line_width=5.0, **kwargs) + + tooltips.append((f'{y_key}', f'@{y_key}')) bars.append(bar) - - # How the data was given, there is not a way for the hover tool to display a single value - hover = HoverTool(tooltips=tooltips,renderers=bars) + + # Add hover tool + hover = HoverTool(tooltips=tooltips, renderers=bars) fig.add_tools(hover) - fig.yaxis.axis_label = ylabel - fig.xaxis.axis_label = xlabel + + # Set axis labels + fig.yaxis.axis_label = fig_ylabel + fig.xaxis.axis_label = fig_xlabel return fig # bokeh piechart -@apply_theme() +@apply_theme(theme=pie_theme) def bokeh_piechart(df, x='x_value', y=['counts'], figure=None, outer_radius=0.7, inner_radius=0.4, title='', fill_color=None, legend_labels=None, line_color='black', **kwargs): """Draw an interactive piechart with bokeh @@ -354,13 +445,17 @@ def bokeh_piechart(df, x='x_value', y=['counts'], figure=None, outer_radius=0.7, tools = 'hover,wheel_zoom,box_zoom,undo,reset,save' if figure is None: + x_range = (-1.2, 1.2) # Give some padding around the pie chart + y_range = (0.2, 1.8) # Give some padding around the pie chart fig = bokeh_figure(height=DEFAULT_FIGURE_HEIGHT, width=DEFAULT_FIGURE_WIDTH, title=title, toolbar_location='above', tools=tools, tooltips=[('Data', f'@{x}'), ('Percentage', '@percent{0.00%}'), - ('Count', f'@count')]) + ('Count', f'@count')], + x_range=x_range, + y_range=y_range) else: fig = figure @@ -601,7 +696,7 @@ def bokeh_corr_plot(df, x='x_values', y='y_values', figure=None, title='', mark alpha = 1.0 colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"] mapper = LinearColorMapper(palette=colors, low=df.data[y].min(), high=df.data[y].max()) - fig.circle(source=df, x=x, y=y, radius = 0.9, **kwargs)#size=markersize, fill_color={'field': 'region', 'transform': color_mapper}, fill_alpha=alpha) + fig.scatter(source=df, x=x, y=y, size=0.9, **kwargs)#size=markersize, fill_color={'field': 'region', 'transform': color_mapper}, fill_alpha=alpha) #line_color='#7c7e71', #line_width=0.5, #line_alpha=0.5, @@ -648,7 +743,7 @@ def bokeh_corr_plot(source, x='x_values', y='y_values', figure=None, title='', tools='hover,wheel_zoom,box_zoom,undo,reset,save', y_range=y_range, x_range=x_range, tooltips=tooltips) - circle = fig.circle(source=source, x=x, y=y, size=markersize, alpha=alpha, hover_alpha=1.0, + circle = fig.scatter(source=source, x=x, y=y, size=markersize, alpha=alpha, hover_alpha=1.0, hover_line_color='black', hover_line_width=5, fill_color='color', line_color='color', **kwargs) #radius=0.1, fig.xaxis.major_label_orientation = 1 @@ -693,7 +788,7 @@ def create_legend_items(number, size_min, color, fig): size = size_min alpha_min = 0.2 for i in range(number): - circ = fig.circle(radius=size, x=0.0, y=0.0, muted=True, visible=False, fill_color=color[i], name='foo') + circ = fig.scatter(size=size, x=0.0, y=0.0, muted=True, visible=False, fill_color=color[i], name='foo') leg_items.append((f'{size}', [circ])) size = size + step @@ -724,7 +819,7 @@ def create_legend_items(number, size_min, color, fig, steps=None, data=None, sca sizes = percentage_to_area(steps, scale_m=scale_m) for i in range(number): size = sizes[i] - circ = fig.circle(size=size, x=3.0, y=y, fill_color=color[i], name='foo', alpha=alpha) + circ = fig.scatter(size=size, x=3.0, y=y, fill_color=color[i], name='foo', alpha=alpha) txt = fig.text(text=[f'{steps[i]}'], x=3.0+x_offset, y=y, text_font_size="18px", text_align="left", text_baseline="middle") y = y - y_step diff --git a/survey_dashboard/scripts.py b/survey_dashboard/scripts.py new file mode 100644 index 0000000..5ac5d72 --- /dev/null +++ b/survey_dashboard/scripts.py @@ -0,0 +1,102 @@ + +# -*- coding: utf-8 -*- +############################################################################### +# Copyright (c), Forschungszentrum Jülich GmbH, IAS-9, Germany. # +# All rights reserved. # +# This file is part of the survey_dashboard package. # +# # +# The code is hosted on GitHub at # +# https://github.com/Materials-Data-Science-and-Informatics/survey_dashboard # +# For further information on the license, see the LICENSE file # +############################################################################### +""" +Command line scripts for the survey dashboard. +""" + +import argparse +import os +import subprocess +import sys +from pathlib import Path + + +def run_app(): + """Run the survey dashboard application using Panel serve. + + Supports both development and production modes via command-line arguments. + """ + # Parse command-line arguments + parser = argparse.ArgumentParser(description="Run the HMC Survey Dashboard") + parser.add_argument( + "--production", + action="store_true", + help="Run in production mode (for Docker/server deployments)" + ) + parser.add_argument( + "--host", + default="localhost", + help="Host to bind to (default: localhost, use 0.0.0.0 for production)" + ) + parser.add_argument( + "--port", + default="5006", + help="Port to run the server on (default: 5006)" + ) + args = parser.parse_args() + + # Read URL prefix from environment (set by Docker Compose VIRTUAL_PATH) + # This is needed when the dashboard is served from a subpath (e.g., /2021community) + virtual_path = os.environ.get("VIRTUAL_PATH", "").strip() + + # Get the directory containing app.py (same directory as scripts.py) + script_dir = Path(__file__).parent + app_path = script_dir / "app.py" + + # Static files directory for assets + static_dir = script_dir / "hmc_layout" / "static" / "en_files" + + # Build the panel serve command + cmd = [ + sys.executable, "-m", "panel", "serve", + str(app_path), + "--port", args.port, + "--address", args.host if args.production else "localhost", + "--static-dirs", f"en_files={static_dir}", + "--index", "app", # Serve app.py at the root of prefix instead of /app + ] + + # Production-specific settings + if args.production: + cmd.extend([ + "--allow-websocket-origin", "*", # Allow external connections + ]) + print("Starting HMC Survey Dashboard in PRODUCTION mode...") + print(f"Server will be accessible at http://{args.host}:{args.port}") + else: + # Development mode - open browser automatically + cmd.append("--show") + print("Starting HMC Survey Dashboard in DEVELOPMENT mode...") + + # Add URL prefix if VIRTUAL_PATH is set (for serving from subpath) + # This tells Panel to prepend the path to all generated URLs (static files, WebSockets, etc.) + # With --index flag, the app is served at the root of the prefix (not /app) + if virtual_path: + cmd.extend(["--prefix", virtual_path]) + print(f"Using URL prefix: {virtual_path}") + if args.production: + print(f"Dashboard will be accessible at: http://{args.host}:{args.port}{virtual_path}/") + + print(f"Running: {' '.join(cmd)}") + + try: + subprocess.run(cmd, check=True) + except subprocess.CalledProcessError as e: + print(f"Error running dashboard: {e}") + sys.exit(1) + except KeyboardInterrupt: + print("\nDashboard stopped.") + sys.exit(0) + + +if __name__ == "__main__": + run_app() \ No newline at end of file diff --git a/survey_dashboard/ui/__init__.py b/survey_dashboard/ui/__init__.py new file mode 100644 index 0000000..297168c --- /dev/null +++ b/survey_dashboard/ui/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +""" +User interface components for the survey dashboard. +""" \ No newline at end of file diff --git a/survey_dashboard/ui/callbacks.py b/survey_dashboard/ui/callbacks.py new file mode 100644 index 0000000..9e804ed --- /dev/null +++ b/survey_dashboard/ui/callbacks.py @@ -0,0 +1,211 @@ +# -*- coding: utf-8 -*- +############################################################################### +# Copyright (c), Forschungszentrum Jülich GmbH, IAS-9, Germany. # +# All rights reserved. # +# This file is part of the survey_dashboard package. # +# # +# The code is hosted on GitHub at # +# https://github.com/Materials-Data-Science-and-Informatics/survey_dashboard # +# For further information on the license, see the LICENSE file # +############################################################################### +""" +Callbacks module for the survey dashboard. +Handles all interactive update callbacks for charts and visualizations. +""" + +from survey_dashboard.core.config import DEFAULT_QUESTIONS, WORDCLOUD_CONTENT +from survey_dashboard.core.charts import ChartManager + + +class CallbackManager: + """Manages all callback functions for interactive updates.""" + + def __init__(self, data_processor, chart_manager, widget_factory): + """ + Initialize callback manager with data processor, chart manager, and widget factory. + + Args: + data_processor: DataProcessor instance for data operations + chart_manager: ChartManager instance for chart creation + widget_factory: WidgetFactory instance for question key lookups (required for validation) + """ + self.data_processor = data_processor + self.chart_manager = chart_manager + self.widget_factory = widget_factory + self.correlation_row = None # Will be set via set_correlation_row() + + def set_correlation_row(self, correlation_row): + """ + Store reference to correlation row for visibility toggling. + + Args: + correlation_row: Panel Column containing the correlation section + """ + self.correlation_row = correlation_row + + def _check_both_questions_compatible(self, question1_text, question2_text): + """ + Check if both questions are correlation-compatible. + + Args: + question1_text: Display text from question selector 1 (may have ★) + question2_text: Display text from question selector 2 (may have ★) + + Returns: + bool: True if both questions can be used in correlation plot + + Raises: + RuntimeError: If widget_factory was not provided during initialization + """ + from survey_dashboard.data.hcs_clean_dictionaries import corr_chart_allowed + + # Fail fast if widget_factory wasn't provided (programming error) + if not self.widget_factory: + raise RuntimeError( + "CallbackManager requires widget_factory for question validation. " + "Pass widget_factory to CallbackManager.__init__()" + ) + + try: + # Get internal keys for both questions using the source of truth + key1 = self.widget_factory.get_question_key(question1_text) + key2 = self.widget_factory.get_question_key(question2_text) + + # Check if both are in the allowed list + both_compatible = (key1 in corr_chart_allowed and key2 in corr_chart_allowed) + return both_compatible + + except Exception as e: + # If we can't determine, hide correlation (safe default) + return False + + def update_chart(self, target, event, question_sel, f_choice, m_choice, q_filter, charttype): + """Update charts based on user selections.""" + question = question_sel + data_filters = f_choice.value + data_filters_method = m_choice.value + charttype = charttype + + fig = self.chart_manager.create_chart(question, data_filters, data_filters_method, charttype) + target.object = fig + + def update_correlation_chart(self, target, event, question_sel, question_sel2, f_choice, m_choice): + """Update the correlation plot and toggle visibility based on question compatibility.""" + question = question_sel.value + question2 = question_sel2.value + + # Check if both questions are correlation-compatible + both_compatible = self._check_both_questions_compatible(question, question2) + + # Toggle visibility of correlation section + if self.correlation_row is not None: + self.correlation_row.visible = both_compatible + + # Only update the plot if both questions are compatible (performance optimization) + if both_compatible: + data_filters = f_choice.value + data_filters_method = m_choice.value + + fig_corr = self.chart_manager.create_correlation_plot( + question, question2, data_filters, data_filters_method + ) + target.object = fig_corr + + def update_wordcloud(self, target, event, f_choice, m_choice, content): + """Update word cloud visualizations.""" + data_filters = f_choice.value + data_filters_method = m_choice.value + + wordcloud = self.chart_manager.create_wordcloud(data_filters, data_filters_method, content) + target.object = wordcloud + + def create_update_callbacks(self, widgets): + """Create all update callback functions.""" + # Extract widgets for easier access + multi_choice = widgets["global_filters"]["research_area"] + multi_choice_method = widgets["global_filters"]["method"] + question_select = widgets["exploration"]["question1"] + question_select2 = widgets["exploration"]["question2"] + chart_select1 = widgets["exploration"]["chart_type1"] + chart_select2 = widgets["exploration"]["chart_type2"] + multi_filter = widgets["exploration"]["filter1"] + multi_filter2 = widgets["exploration"]["filter2"] + + # Create callback functions + def gen_update_overview1(target, event): + f_choice, m_choice = multi_choice, multi_choice_method + question_sel = self.data_processor.map_qkey_to_question(DEFAULT_QUESTIONS["overview"]["ov1"]) + self.update_chart( + target, event, question_sel, f_choice, m_choice, + q_filter=None, charttype="Vertical Bar chart" + ) + + def gen_update_overview2(target, event): + f_choice, m_choice = multi_choice, multi_choice_method + question_sel = self.data_processor.map_qkey_to_question(DEFAULT_QUESTIONS["overview"]["ov2"]) + self.update_chart( + target, event, question_sel, f_choice, m_choice, + q_filter=None, charttype="Vertical Bar chart" + ) + + def gen_update_overview3(target, event): + f_choice, m_choice = multi_choice, multi_choice_method + question_sel = self.data_processor.map_qkey_to_question(DEFAULT_QUESTIONS["overview"]["ov3"]) + self.update_chart( + target, event, question_sel, f_choice, m_choice, + q_filter=None, charttype="Vertical Bar chart" + ) + + def gen_update_overview4(target, event): + f_choice, m_choice = multi_choice, multi_choice_method + question_sel = self.data_processor.map_qkey_to_question(DEFAULT_QUESTIONS["overview"]["ov4"]) + self.update_chart( + target, event, question_sel, f_choice, m_choice, + q_filter=None, charttype="Vertical Bar chart" + ) + + def gen_update_exp1(target, event): + f_choice, m_choice = multi_choice, multi_choice_method + question_sel, q_filter, charttype = ( + question_select.value, + multi_filter, + chart_select1.value, + ) + self.update_chart(target, event, question_sel, f_choice, m_choice, q_filter, charttype) + + def gen_update_exp2(target, event): + f_choice, m_choice = multi_choice, multi_choice_method + question_sel, q_filter, charttype = ( + question_select2.value, + multi_filter2, + chart_select2.value, + ) + self.update_chart(target, event, question_sel, f_choice, m_choice, q_filter, charttype) + + def gen_update_corr(target, event): + f_choice, m_choice = multi_choice, multi_choice_method + question_sel = question_select + question_sel2 = question_select2 + self.update_correlation_chart(target, event, question_sel, question_sel2, f_choice, m_choice) + + def gen_update_wc_methods(target, event): + f_choice, m_choice = multi_choice, multi_choice_method + content = WORDCLOUD_CONTENT["methods"] + self.update_wordcloud(target, event, f_choice, m_choice, content) + + def gen_update_wc_software(target, event): + f_choice, m_choice = multi_choice, multi_choice_method + content = WORDCLOUD_CONTENT["software"] + self.update_wordcloud(target, event, f_choice, m_choice, content) + + def gen_update_wc_repo(target, event): + f_choice, m_choice = multi_choice, multi_choice_method + content = WORDCLOUD_CONTENT["repositories"] + self.update_wordcloud(target, event, f_choice, m_choice, content) + + return { + "overview": [gen_update_overview1, gen_update_overview2, gen_update_overview3, gen_update_overview4], + "exploration": [gen_update_exp1, gen_update_exp2], + "correlation": gen_update_corr, + "wordclouds": [gen_update_wc_methods, gen_update_wc_software, gen_update_wc_repo] + } \ No newline at end of file diff --git a/survey_dashboard/ui/layout.py b/survey_dashboard/ui/layout.py new file mode 100644 index 0000000..449e3d0 --- /dev/null +++ b/survey_dashboard/ui/layout.py @@ -0,0 +1,226 @@ +# -*- coding: utf-8 -*- +############################################################################### +# Copyright (c), Forschungszentrum Jülich GmbH, IAS-9, Germany. # +# All rights reserved. # +# This file is part of the survey_dashboard package. # +# # +# The code is hosted on GitHub at # +# https://github.com/Materials-Data-Science-and-Informatics/survey_dashboard # +# For further information on the license, see the LICENSE file # +############################################################################### +""" +Layout manager module for the survey dashboard. +Handles the creation and organization of the dashboard layout and template integration. +""" + +import panel as pn +from jinja2 import Environment, FileSystemLoader + +from survey_dashboard.core.config import ( + LANGUAGE, + PANEL_CONFIG, + DEFAULT_QUESTIONS, + get_template_path, + get_assets_path +) +from survey_dashboard.i18n.text_display import ( + md_text_global_filter, + md_text_overview, + md_text_barchart, + md_text_corrchart, + md_text_title, + md_dashboard_title, + accordion_titles, + md_text_descriptions_icons +) +from survey_dashboard.hmc_layout.hmc_custom_layout import ( + hmc_custom_css_accordion, +) +from survey_dashboard.data.hcs_clean_dictionaries import ( + corr_chart_allowed +) + + +class LayoutManager: + """Manages the dashboard layout and template integration.""" + + def __init__(self): + """Initialize layout manager and configure Panel.""" + self.correlation_row = None # Will be set during layout creation + self.setup_panel_config() + self.setup_template() + self.setup_overview_icons() + + def setup_panel_config(self): + """Configure Panel global settings.""" + pn.config.loading_spinner = PANEL_CONFIG["loading_spinner"] + pn.config.loading_color = PANEL_CONFIG["loading_color"] + pn.config.raw_css = [hmc_custom_css_accordion] + + def setup_template(self): + """Setup Jinja2 template for the dashboard.""" + template_path = get_template_path() + # Set the loader to look in the directory containing the template + env = Environment(loader=FileSystemLoader(template_path.parent)) + jinja_template = env.get_template(template_path.name) + self.template = pn.Template(jinja_template) + + def setup_overview_icons(self): + """Create overview icons with SVG images.""" + assets_path = get_assets_path() + + people_ic = pn.Row( + pn.pane.SVG(assets_path / "people.svg"), + md_text_descriptions_icons["people"][LANGUAGE], + ) + inst_ic = pn.Row( + pn.pane.SVG(assets_path / "institute.svg"), + md_text_descriptions_icons["institution"][LANGUAGE], + ) + questions_ic = pn.Row( + pn.pane.SVG(assets_path / "quiz_black_48dp.svg"), + md_text_descriptions_icons["questions"][LANGUAGE], + ) + + self.overview_icons = pn.Row(people_ic, inst_ic, questions_ic) + + def create_global_filters_section(self, control_groups): + """Create the global filters section.""" + global_filters_sec = pn.Column( + md_text_global_filter[LANGUAGE], + control_groups["global_filters"][0], + control_groups["global_filters"][1], + sizing_mode="stretch_width" + ) + return global_filters_sec + + def create_overview_section(self, overview_charts): + """Create the overview section with charts.""" + overview_sec = pn.Column( + md_text_overview[LANGUAGE], + pn.Row(overview_charts['ov3'], overview_charts['ov2'], sizing_mode="stretch_width"), + pn.Row(overview_charts['ov1'], overview_charts['ov4'], sizing_mode="stretch_width"), + sizing_mode="stretch_width", + ) + return overview_sec + + def create_question_explorer_section(self, control_groups, exploration_charts, correlation_chart): + """Create the question explorer section with exploration and correlation charts.""" + half_width = 400 # Approximate half width for controls + + # Control inputs + inputs = pn.Column(*control_groups["controls_bar1"], width=half_width) + inputs2 = pn.Column(*control_groups["controls_bar2"], width=half_width) + + # Charts row with controls and visualizations + charts_row = pn.Column( + pn.Row(inputs, inputs2, sizing_mode="stretch_width"), + pn.Row(exploration_charts[0], exploration_charts[1], sizing_mode="stretch_width"), + sizing_mode="stretch_width" + ) + + # Determine initial visibility of correlation section + # Check if both default questions are correlation-compatible + default_q1 = DEFAULT_QUESTIONS["exploration"]["bar1"] + default_q2 = DEFAULT_QUESTIONS["exploration"]["bar2"] + + try: + initial_visible = (default_q1 in corr_chart_allowed and + default_q2 in corr_chart_allowed) + except: + # If we can't determine compatibility, hide by default + initial_visible = False + + # Correlation section (conditionally visible) + fig_corr, leg_corr = correlation_chart + correlation_row = pn.Column( + md_text_corrchart[LANGUAGE], + pn.Row( + pn.layout.VSpacer(), + fig_corr, + leg_corr, + pn.layout.VSpacer(), + sizing_mode="stretch_width" + ), + sizing_mode="stretch_width", + visible=initial_visible # Set initial visibility based on default questions + ) + + # Combined question explorer section + question_ex_sec = pn.Column( + md_text_barchart[LANGUAGE], + charts_row, + correlation_row, + sizing_mode="stretch_width" + ) + + return question_ex_sec, correlation_row # Return both section and correlation reference + + def create_accordion_layout(self, sections): + """Create the main accordion layout.""" + overall_accordion = pn.Accordion( + (accordion_titles[LANGUAGE][0], sections["global_filters"]), + (accordion_titles[LANGUAGE][1], sections["overview"]), + (accordion_titles[LANGUAGE][2], sections["methods_tools"]), + (accordion_titles[LANGUAGE][3], sections["question_explorer"]), + sizing_mode="stretch_both", + ) + + # Configure accordion settings + overall_accordion.active = [0, 3] # Open global filters and question explorer by default + overall_accordion.scroll = True + overall_accordion.margin = (20, 20, 20, 20) # Add consistent margin on all sides + overall_accordion.width = None # Remove fixed width constraint + overall_accordion.min_width = None # Remove min-width constraint + + return overall_accordion + + def create_complete_layout(self, control_groups, overview_charts, exploration_charts, + correlation_chart, methods_tools_tabs): + """Create the complete dashboard layout.""" + # Create question explorer section and capture correlation_row reference + question_explorer_section, correlation_row = self.create_question_explorer_section( + control_groups, exploration_charts, correlation_chart + ) + + # Store correlation_row for later access by callbacks + self.correlation_row = correlation_row + + # Create all sections + sections = { + "global_filters": self.create_global_filters_section(control_groups), + "overview": self.create_overview_section(overview_charts), + "methods_tools": methods_tools_tabs, + "question_explorer": question_explorer_section + } + + # Create accordion + accordion = self.create_accordion_layout(sections) + + # Main layout container + layout = pn.Column(accordion, sizing_mode="stretch_both") + + return layout # Return only layout - no breaking change to app.py + + def get_correlation_row(self): + """ + Get reference to the correlation row for callback binding. + + Returns: + Panel Column containing the correlation plot section, or None if not yet created. + """ + return self.correlation_row + + def setup_template_variables(self, layout): + """Setup template with layout and variables.""" + self.template.add_panel("App", layout) + self.template.add_variable("app_title", md_text_title[LANGUAGE]) + self.template.add_variable("dashboard_title", md_dashboard_title[LANGUAGE]) + self.template.add_variable("image_url", "./en_files/Banner.png") + + return self.template + + def make_servable(self): + """Make the template servable.""" + self.template.servable(title=md_text_title[LANGUAGE]) + return self.template diff --git a/survey_dashboard/ui/widgets.py b/survey_dashboard/ui/widgets.py new file mode 100644 index 0000000..7df1d29 --- /dev/null +++ b/survey_dashboard/ui/widgets.py @@ -0,0 +1,232 @@ +# -*- coding: utf-8 -*- +############################################################################### +# Copyright (c), Forschungszentrum Jülich GmbH, IAS-9, Germany. # +# All rights reserved. # +# This file is part of the survey_dashboard package. # +# # +# The code is hosted on GitHub at # +# https://github.com/Materials-Data-Science-and-Informatics/survey_dashboard # +# For further information on the license, see the LICENSE file # +############################################################################### +""" +Widget factory module for the survey dashboard. +Creates and manages all interactive widgets used in the dashboard. +""" + +import panel as pn + +from survey_dashboard.core.config import ( + LANGUAGE, + CHART_TYPES, + DEFAULT_QUESTIONS, +) +from survey_dashboard.i18n.text_display import ( + md_text_global_filters_widgets, + md_text_select_widgets +) +from survey_dashboard.data.hcs_clean_dictionaries import ( + FILTER_OPTIONS, + BARCHART_ALLOWED, + corr_chart_allowed +) + + +class WidgetFactory: + """Factory class for creating dashboard widgets.""" + + def __init__(self, data_processor): + """Initialize widget factory with data processor for question mapping.""" + self.data_processor = data_processor + + # Create question list with visual indicators for correlation-compatible questions + # Also maintain a mapping from display text to internal key + self.questions = [] + self.question_to_key = {} # Maps display text (with ★) -> internal key + + for key in BARCHART_ALLOWED: + question_text = self.data_processor.map_qkey_to_question(key) + + # Add ★ indicator for correlation-compatible questions + if key in corr_chart_allowed: + display_text = f"★ {question_text}" + else: + display_text = question_text + + self.questions.append(display_text) + self.question_to_key[display_text] = key + + def _get_display_text_for_key(self, key): + """ + Get the display text (with ★ if applicable) for a given question key. + + Args: + key: Internal question key (e.g., 'careerLevel') + + Returns: + Display text with ★ prefix if correlation-compatible + """ + question_text = self.data_processor.map_qkey_to_question(key) + if key in corr_chart_allowed: + return f"★ {question_text}" + return question_text + + def get_question_key(self, display_text): + """ + Get the internal key for a question from its display text. + Handles both decorated (★) and plain text. + + Args: + display_text: Question text as shown in dropdown (may have ★) + + Returns: + Internal question key (e.g., 'careerLevel') + """ + return self.question_to_key.get(display_text) + + def is_correlation_compatible(self, display_text): + """ + Check if a question is correlation-compatible. + + Args: + display_text: Question text as shown in dropdown (may have ★) + + Returns: + True if the question can be used in correlation plots + """ + key = self.get_question_key(display_text) + return key in corr_chart_allowed if key else False + + def create_global_filters(self): + """Create global filter widgets.""" + multi_choice = pn.widgets.MultiChoice( + name=md_text_global_filters_widgets[0][LANGUAGE], + value=["All"], + options=FILTER_OPTIONS["researchArea"], + ) + + multi_choice_method = pn.widgets.MultiChoice( + name=md_text_global_filters_widgets[1][LANGUAGE], + value=[], + options=FILTER_OPTIONS["method"], + ) + + return [multi_choice, multi_choice_method] + + def create_question_selectors(self): + """Create question selector widgets for exploration charts.""" + # Get default question keys + default_key1 = DEFAULT_QUESTIONS["exploration"]["bar1"] + default_key2 = DEFAULT_QUESTIONS["exploration"]["bar2"] + + # Find the display text (with ★ if applicable) that matches the default key + default_value1 = self._get_display_text_for_key(default_key1) + default_value2 = self._get_display_text_for_key(default_key2) + + question_select = pn.widgets.Select( + name=md_text_select_widgets[0][LANGUAGE], + value=default_value1, + options=self.questions + ) + + question_select2 = pn.widgets.Select( + name=md_text_select_widgets[1][LANGUAGE], + value=default_value2, + options=self.questions + ) + + return question_select, question_select2 + + def create_chart_type_selectors(self): + """Create chart type selector widgets.""" + chart_select1 = pn.widgets.Select( + name="Visualization type", + value="Vertical Bar chart", + options=CHART_TYPES + ) + + chart_select2 = pn.widgets.Select( + name="Visualization type", + value="Vertical Bar chart", + options=CHART_TYPES + ) + + return chart_select1, chart_select2 + + def create_hidden_filters(self): + """Create hidden filter widgets (currently not used but kept for compatibility).""" + multi_filter = pn.widgets.MultiChoice( + name="Filter by data by question specific filter", + value=[], + options=FILTER_OPTIONS["method"], + visible=False, + ) + + multi_filter2 = pn.widgets.MultiChoice( + name="Filter by data by question specific filter", + value=[], + options=FILTER_OPTIONS["method"], + visible=False, + ) + + return multi_filter, multi_filter2 + + def create_all_widgets(self): + """Create all widgets and return them organized by type.""" + # Global filters + global_filters = self.create_global_filters() + multi_choice, multi_choice_method = global_filters + + # Question selectors + question_select, question_select2 = self.create_question_selectors() + + # Chart type selectors + chart_select1, chart_select2 = self.create_chart_type_selectors() + + # Hidden filters + multi_filter, multi_filter2 = self.create_hidden_filters() + + # Organize widgets + widgets = { + "global_filters": { + "research_area": multi_choice, + "method": multi_choice_method + }, + "exploration": { + "question1": question_select, + "question2": question_select2, + "chart_type1": chart_select1, + "chart_type2": chart_select2, + "filter1": multi_filter, # hidden + "filter2": multi_filter2 # hidden + } + } + + return widgets + + def get_control_groups(self, widgets): + """Get organized control groups for layout.""" + # Global filters group + global_filters = [ + widgets["global_filters"]["research_area"], + widgets["global_filters"]["method"] + ] + + # Bar chart controls for chart 1 + controls_bar1 = [ + widgets["exploration"]["question1"], + widgets["exploration"]["filter1"], + widgets["exploration"]["chart_type1"] + ] + + # Bar chart controls for chart 2 + controls_bar2 = [ + widgets["exploration"]["question2"], + widgets["exploration"]["filter2"], + widgets["exploration"]["chart_type2"] + ] + + return { + "global_filters": global_filters, + "controls_bar1": controls_bar1, + "controls_bar2": controls_bar2 + }