diff --git a/.github/workflows/dev-desktop-builds.yml b/.github/workflows/dev-desktop-builds.yml index 2391c0c534..dcd2ba47d9 100644 --- a/.github/workflows/dev-desktop-builds.yml +++ b/.github/workflows/dev-desktop-builds.yml @@ -1,279 +1,285 @@ -name: "Build Material Maker" +# name: "Build Material Maker" -on: - push: - branches: [master] - pull_request: - branches: [master] - workflow_dispatch: - inputs: - artifacts: - description: "Generate artifacts" - type: boolean - required: true - default: "false" - sign_macos: - description: "Sign macOS version" - type: boolean - required: true - default: "false" - gen_doc: - description: "Generate documentation" - type: boolean - required: true - default: "true" - steam: - description: "Generate Steam version" - type: boolean - required: true - default: "false" - steam_deploy: - description: "Upload Steam version" - type: boolean - required: true - default: "false" +# on: +# push: +# branches: [master] +# pull_request: +# branches: [master] +# workflow_dispatch: +# inputs: +# artifacts: +# description: "Generate artifacts" +# type: boolean +# required: true +# default: false +# sign_macos: +# description: "Sign macOS version" +# type: boolean +# required: true +# default: false +# android_release: +# description: "Generate Android release" +# type: boolean +# required: true +# default: false +# gen_doc: +# description: "Generate documentation" +# type: boolean +# required: true +# default: true +# steam: +# description: "Generate Steam version" +# type: boolean +# required: true +# default: false +# steam_deploy: +# description: "Upload Steam version" +# type: boolean +# required: true +# default: false -env: - GODOT_VERSION: 4.7.2 - GODOT_SUB: stable - GODOT_DOWNLOAD_DIR: https://github.com/godotengine/godot-builds/releases/download/4.7.2-stable - EXPORT_NAME: material_maker - MM_RELEASE: 1_8 - EXPORT_TARGET_SUFFIX: "${{ github.event.inputs.steam == 'true' && ' Steam' || '' }}" - PACKAGE_SUFFIX: "${{ github.event.inputs.steam == 'true' && '_steam' || '' }}" +# env: +# GODOT_VERSION: 4.8 +# GODOT_SUB: beta1 +# GODOT_DOWNLOAD_DIR: https://github.com/godotengine/godot-builds/releases/download/4.8-beta1 +# EXPORT_NAME: material_maker +# MM_RELEASE: 1_7 +# EXPORT_TARGET_SUFFIX: "${{ github.event.inputs.steam == 'true' && ' Steam' || '' }}" +# PACKAGE_SUFFIX: "${{ github.event.inputs.steam == 'true' && '_steam' || '' }}" -jobs: - export_windows_linux: - name: Export Windows and Linux 🗔 - runs-on: ubuntu-latest - steps: - - name: Checkout 🛎️ - uses: actions/checkout@v1 - with: - submodules: true - - name: Setup 💻 - run: | - cp -f material_maker/theme/default_theme_icons.svg material_maker/theme/default_theme_icons_export.svg - wget -q ${GODOT_DOWNLOAD_DIR}/Godot_v${GODOT_VERSION}-${GODOT_SUB}_linux.x86_64.zip - unzip Godot_v${GODOT_VERSION}-${GODOT_SUB}_linux.x86_64.zip - wget -q ${GODOT_DOWNLOAD_DIR}/Godot_v${GODOT_VERSION}-${GODOT_SUB}_export_templates.tpz - unzip -a Godot_v${GODOT_VERSION}-${GODOT_SUB}_export_templates.tpz - mkdir -v -p ~/.local/share/godot/export_templates/${GODOT_VERSION}.${GODOT_SUB} - mv ./templates/* ~/.local/share/godot/export_templates/${GODOT_VERSION}.${GODOT_SUB} - mkdir -v -p build/${EXPORT_NAME}_${MM_RELEASE}_windows build/${EXPORT_NAME}_${MM_RELEASE}_linux - - name: Generate Documentation - if: ${{ github.event.inputs.gen_doc == 'true' }} - uses: ammaraskar/sphinx-action@master - with: - docs-folder: "material_maker/doc" - - name: Windows Build 🗔 - run: | - ./Godot_v${GODOT_VERSION}-${GODOT_SUB}_linux.x86_64 --headless -v --export-release "Windows${EXPORT_TARGET_SUFFIX}" ./build/${EXPORT_NAME}_${MM_RELEASE}_windows/$EXPORT_NAME.exe - - name: Linux Build 🐧 - run: | - ./Godot_v${GODOT_VERSION}-${GODOT_SUB}_linux.x86_64 --headless -v --export-release "Linux/X11${EXPORT_TARGET_SUFFIX}" ./build/${EXPORT_NAME}_${MM_RELEASE}_linux/$EXPORT_NAME.x86_64 - - name: Copy Material Maker data 📁 - run: | - cp -R ./addons/material_maker/nodes ./build/${EXPORT_NAME}_${MM_RELEASE}_windows - cp -R ./material_maker/environments ./build/${EXPORT_NAME}_${MM_RELEASE}_windows - cp -R ./material_maker/examples ./build/${EXPORT_NAME}_${MM_RELEASE}_windows - cp -R ./material_maker/library ./build/${EXPORT_NAME}_${MM_RELEASE}_windows - cp -R ./material_maker/meshes ./build/${EXPORT_NAME}_${MM_RELEASE}_windows - cp -R ./material_maker/misc/export ./build/${EXPORT_NAME}_${MM_RELEASE}_windows - cp -R ./material_maker/doc/_build/html ./build/${EXPORT_NAME}_${MM_RELEASE}_windows/doc || : - cp -R ./addons/material_maker/nodes ./build/${EXPORT_NAME}_${MM_RELEASE}_linux - cp -R ./material_maker/environments ./build/${EXPORT_NAME}_${MM_RELEASE}_linux - cp -R ./material_maker/examples ./build/${EXPORT_NAME}_${MM_RELEASE}_linux - cp -R ./material_maker/library ./build/${EXPORT_NAME}_${MM_RELEASE}_linux - cp -R ./material_maker/meshes ./build/${EXPORT_NAME}_${MM_RELEASE}_linux - cp -R ./material_maker/misc/export ./build/${EXPORT_NAME}_${MM_RELEASE}_linux - cp -R ./material_maker/doc/_build/html ./build/${EXPORT_NAME}_${MM_RELEASE}_linux/doc || : - - name: Create archives 📁 - run: | - cd build - zip -r ${EXPORT_NAME}_${MM_RELEASE}_windows${PACKAGE_SUFFIX}.zip ${EXPORT_NAME}_${MM_RELEASE}_windows - tar zcvf ${EXPORT_NAME}_${MM_RELEASE}_linux${PACKAGE_SUFFIX}.tar.gz ${EXPORT_NAME}_${MM_RELEASE}_linux - - name: Upload Documentation 🚀 - if: ${{ github.event.inputs.gen_doc == 'true' && github.event.inputs.artifacts == 'true' }} - uses: actions/upload-artifact@v6 - with: - name: documentation - path: ./material_maker/doc/_build/html - - name: Upload Windows Artifact 🚀 - if: ${{ github.event.inputs.steam == 'false' && github.event.inputs.artifacts == 'true' }} - uses: actions/upload-artifact@v6 - with: - name: windows_snapshot - path: build/${{ env.EXPORT_NAME }}_${{ env.MM_RELEASE }}_windows${{ env.PACKAGE_SUFFIX }}.zip - - name: Upload Windows Artifact (Steam) 🚀 - if: ${{ github.event.inputs.steam == 'true' }} - uses: actions/upload-artifact@v6 - with: - name: windows_snapshot - path: build/${{ env.EXPORT_NAME }}_${{ env.MM_RELEASE }}_windows - - name: Upload Linux Artifact 🚀 - if: ${{ github.event.inputs.steam == 'false' && github.event.inputs.artifacts == 'true' }} - uses: actions/upload-artifact@v6 - with: - name: linux_snapshot - path: build/${{ env.EXPORT_NAME }}_${{ env.MM_RELEASE }}_linux${{ env.PACKAGE_SUFFIX }}.tar.gz - - name: Upload Linux Artifact (Steam) 🚀 - if: ${{ github.event.inputs.steam == 'true' }} - uses: actions/upload-artifact@v6 - with: - name: linux_snapshot - path: build/${{ env.EXPORT_NAME }}_${{ env.MM_RELEASE }}_linux - export_macos: - name: Mac Export 🍎 - needs: export_windows_linux - runs-on: macos-26 - steps: - - name: Checkout 🛎️ - uses: actions/checkout@v1 - with: - submodules: true - - name: Setup environment 🔧 - run: | - cp -f material_maker/theme/default_theme_icons.svg material_maker/theme/default_theme_icons_export.svg - export GODOT_VERSION=${GODOT_VERSION} - export EXPORT_NAME=material_maker - - name: Install the Apple certificate and provisioning profile - if: ${{ github.event.inputs.sign_macos == 'true' }} - env: - BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} - P12_PASSWORD: ${{ secrets.P12_PASSWORD }} - BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }} - KEYCHAIN_PASSWORD: "${{ secrets.KEYCHAIN_PASSWORD }}" - run: | - # create variables - CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 - PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision - KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db +# jobs: +# export_windows_linux: +# name: Export Windows and Linux 🗔 +# runs-on: ubuntu-latest +# steps: +# - name: Checkout 🛎️ +# uses: actions/checkout@v1 +# with: +# submodules: true +# - name: Setup 💻 +# run: | +# cp -f material_maker/theme/default_theme_icons.svg material_maker/theme/default_theme_icons_export.svg +# wget -q ${GODOT_DOWNLOAD_DIR}/Godot_v${GODOT_VERSION}-${GODOT_SUB}_linux.x86_64.zip +# unzip Godot_v${GODOT_VERSION}-${GODOT_SUB}_linux.x86_64.zip +# wget -q ${GODOT_DOWNLOAD_DIR}/Godot_v${GODOT_VERSION}-${GODOT_SUB}_export_templates.tpz +# unzip -a Godot_v${GODOT_VERSION}-${GODOT_SUB}_export_templates.tpz +# mkdir -v -p ~/.local/share/godot/export_templates/${GODOT_VERSION}.${GODOT_SUB} +# mv ./templates/* ~/.local/share/godot/export_templates/${GODOT_VERSION}.${GODOT_SUB} +# mkdir -v -p build/${EXPORT_NAME}_${MM_RELEASE}_windows build/${EXPORT_NAME}_${MM_RELEASE}_linux +# - name: Generate Documentation +# if: ${{ github.event.inputs.gen_doc == 'true' }} +# uses: ammaraskar/sphinx-action@master +# with: +# docs-folder: "material_maker/doc" +# - name: Windows Build 🗔 +# run: | +# ./Godot_v${GODOT_VERSION}-${GODOT_SUB}_linux.x86_64 --headless -v --export-release "Windows${EXPORT_TARGET_SUFFIX}" ./build/${EXPORT_NAME}_${MM_RELEASE}_windows/$EXPORT_NAME.exe +# - name: Linux Build 🐧 +# run: | +# ./Godot_v${GODOT_VERSION}-${GODOT_SUB}_linux.x86_64 --headless -v --export-release "Linux/X11${EXPORT_TARGET_SUFFIX}" ./build/${EXPORT_NAME}_${MM_RELEASE}_linux/$EXPORT_NAME.x86_64 +# - name: Copy Material Maker data 📁 +# run: | +# cp -R ./addons/material_maker/nodes ./build/${EXPORT_NAME}_${MM_RELEASE}_windows +# cp -R ./material_maker/environments ./build/${EXPORT_NAME}_${MM_RELEASE}_windows +# cp -R ./material_maker/examples ./build/${EXPORT_NAME}_${MM_RELEASE}_windows +# cp -R ./material_maker/library ./build/${EXPORT_NAME}_${MM_RELEASE}_windows +# cp -R ./material_maker/meshes ./build/${EXPORT_NAME}_${MM_RELEASE}_windows +# cp -R ./material_maker/misc/export ./build/${EXPORT_NAME}_${MM_RELEASE}_windows +# cp -R ./material_maker/doc/_build/html ./build/${EXPORT_NAME}_${MM_RELEASE}_windows/doc || : +# cp -R ./addons/material_maker/nodes ./build/${EXPORT_NAME}_${MM_RELEASE}_linux +# cp -R ./material_maker/environments ./build/${EXPORT_NAME}_${MM_RELEASE}_linux +# cp -R ./material_maker/examples ./build/${EXPORT_NAME}_${MM_RELEASE}_linux +# cp -R ./material_maker/library ./build/${EXPORT_NAME}_${MM_RELEASE}_linux +# cp -R ./material_maker/meshes ./build/${EXPORT_NAME}_${MM_RELEASE}_linux +# cp -R ./material_maker/misc/export ./build/${EXPORT_NAME}_${MM_RELEASE}_linux +# cp -R ./material_maker/doc/_build/html ./build/${EXPORT_NAME}_${MM_RELEASE}_linux/doc || : +# - name: Create archives 📁 +# run: | +# cd build +# zip -r ${EXPORT_NAME}_${MM_RELEASE}_windows${PACKAGE_SUFFIX}.zip ${EXPORT_NAME}_${MM_RELEASE}_windows +# tar zcvf ${EXPORT_NAME}_${MM_RELEASE}_linux${PACKAGE_SUFFIX}.tar.gz ${EXPORT_NAME}_${MM_RELEASE}_linux +# - name: Upload Documentation 🚀 +# if: ${{ github.event.inputs.gen_doc == 'true' && github.event.inputs.artifacts == 'true' }} +# uses: actions/upload-artifact@v6 +# with: +# name: documentation +# path: ./material_maker/doc/_build/html +# - name: Upload Windows Artifact 🚀 +# if: ${{ github.event.inputs.steam == 'false' && github.event.inputs.artifacts == 'true' }} +# uses: actions/upload-artifact@v6 +# with: +# name: windows_snapshot +# path: build/${{ env.EXPORT_NAME }}_${{ env.MM_RELEASE }}_windows${{ env.PACKAGE_SUFFIX }}.zip +# - name: Upload Windows Artifact (Steam) 🚀 +# if: ${{ github.event.inputs.steam == 'true' }} +# uses: actions/upload-artifact@v6 +# with: +# name: windows_snapshot +# path: build/${{ env.EXPORT_NAME }}_${{ env.MM_RELEASE }}_windows +# - name: Upload Linux Artifact 🚀 +# if: ${{ github.event.inputs.steam == 'false' && github.event.inputs.artifacts == 'true' }} +# uses: actions/upload-artifact@v6 +# with: +# name: linux_snapshot +# path: build/${{ env.EXPORT_NAME }}_${{ env.MM_RELEASE }}_linux${{ env.PACKAGE_SUFFIX }}.tar.gz +# - name: Upload Linux Artifact (Steam) 🚀 +# if: ${{ github.event.inputs.steam == 'true' }} +# uses: actions/upload-artifact@v6 +# with: +# name: linux_snapshot +# path: build/${{ env.EXPORT_NAME }}_${{ env.MM_RELEASE }}_linux +# export_macos: +# name: Mac Export 🍎 +# needs: export_windows_linux +# runs-on: macos-26 +# steps: +# - name: Checkout 🛎️ +# uses: actions/checkout@v1 +# with: +# submodules: true +# - name: Setup environment 🔧 +# run: | +# cp -f material_maker/theme/default_theme_icons.svg material_maker/theme/default_theme_icons_export.svg +# export GODOT_VERSION=${GODOT_VERSION} +# export EXPORT_NAME=material_maker +# - name: Install the Apple certificate and provisioning profile +# if: ${{ github.event.inputs.sign_macos == 'true' }} +# env: +# BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} +# P12_PASSWORD: ${{ secrets.P12_PASSWORD }} +# BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }} +# KEYCHAIN_PASSWORD: "${{ secrets.KEYCHAIN_PASSWORD }}" +# run: | +# # create variables +# CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 +# PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision +# KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db - # import certificate and provisioning profile from secrets - echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode --output $CERTIFICATE_PATH - echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode --output $PP_PATH +# # import certificate and provisioning profile from secrets +# echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode --output $CERTIFICATE_PATH +# echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode --output $PP_PATH - # create temporary keychain - security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH - security set-keychain-settings -lut 21600 $KEYCHAIN_PATH - security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH +# # create temporary keychain +# security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH +# security set-keychain-settings -lut 21600 $KEYCHAIN_PATH +# security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH - # import certificate to keychain - security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH - security list-keychain -d user -s $KEYCHAIN_PATH +# # import certificate to keychain +# security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH +# security list-keychain -d user -s $KEYCHAIN_PATH - # apply provisioning profile - mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles - cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles - - name: Download and extract Godot and export templates 💾 - run: | - wget ${GODOT_DOWNLOAD_DIR}/Godot_v${GODOT_VERSION}-${GODOT_SUB}_macos.universal.zip - unzip -a Godot_v${GODOT_VERSION}-${GODOT_SUB}_macos.universal.zip - wget ${GODOT_DOWNLOAD_DIR}/Godot_v${GODOT_VERSION}-${GODOT_SUB}_export_templates.tpz - unzip -a Godot_v${GODOT_VERSION}-${GODOT_SUB}_export_templates.tpz - mkdir -v -p "/Users/runner/Library/Application Support/Godot/export_templates/${GODOT_VERSION}.${GODOT_SUB}" - mv ./templates/* "/Users/runner/Library/Application Support/Godot/export_templates/${GODOT_VERSION}.${GODOT_SUB}" - - name: Mac Build 🔧 - run: | - chown runner Godot.app/Contents/MacOS/Godot - chmod +x Godot.app/Contents/MacOS/Godot - mkdir -v -p ./build/mac - Godot.app/Contents/MacOS/Godot --headless -v --export-release "Mac OSX${EXPORT_TARGET_SUFFIX}" ./build/mac/material_maker.zip - - name: Make application executable 🔧 - run: | - unzip -a ./build/mac/material_maker.zip -d ./build/mac - chmod +x "./build/mac/Material Maker.app/Contents/MacOS/Material Maker" - rm ./build/mac/material_maker.zip - - name: Get documentation 🚀 - if: ${{ github.event.inputs.gen_doc == 'true' && github.event.inputs.artifacts == 'true' }} - uses: actions/download-artifact@v8 - with: - name: documentation - path: doc - - name: Copy data folder 📁 - run: | - cp -R ./addons/material_maker/nodes "./build/mac/Material Maker.app/Contents/MacOS" - cp -R ./material_maker/environments "./build/mac/Material Maker.app/Contents/MacOS" - cp -R ./material_maker/examples "./build/mac/Material Maker.app/Contents/MacOS" - cp -R ./material_maker/library "./build/mac/Material Maker.app/Contents/MacOS" - cp -R ./material_maker/meshes "./build/mac/Material Maker.app/Contents/MacOS" - cp -R ./material_maker/misc/export "./build/mac/Material Maker.app/Contents/MacOS" - cp -R ./doc "./build/mac/Material Maker.app/Contents/MacOS/doc" || : - - name: Ad-hoc signing ✍️ - if: ${{ github.event.inputs.sign_macos != 'true' }} - run: | - codesign -s - --force --deep "./build/mac/Material Maker.app" - - name: Signing ✍️ - if: ${{ github.event.inputs.sign_macos == 'true' }} - run: | - codesign -s "Rodolphe Suescun" --force --timestamp --options runtime --deep "./build/mac/Material Maker.app" - - name: Create DMG archive 🔧 - if: ${{ github.event.inputs.steam == 'false' }} - run: | - brew untap aws/tap || true - brew install imagemagick - cp ./.github/workflows/create-dmg-bg.sh . - chmod +x create-dmg-bg.sh - ./create-dmg-bg.sh ./splash_screen/backgrounds/pavel_oliva_vintage_luggage.png ./bg.png - #hdiutil create -srcfolder ./build/mac -fs HFS+ -volname material_maker material_maker_${MM_RELEASE}${PACKAGE_SUFFIX}.dmg - wget https://github.com/create-dmg/create-dmg/archive/refs/tags/v1.2.2.zip - unzip v1.2.2.zip - create-dmg-1.2.2/create-dmg --volname "Material Maker" --icon-size 128 --background ./bg.png --window-size 540 330 --icon "Material Maker.app" 158 125 --app-drop-link 384 125 --hide-extension "Material Maker.app" ./build/mac/material_maker_${MM_RELEASE}${PACKAGE_SUFFIX}.dmg ./build/mac - ls - - name: Notarizing ✍️ - if: ${{ github.event.inputs.steam == 'false' && github.event.inputs.sign_macos == 'true' }} - env: - APPLE_ID: ${{ secrets.APPLE_ID }} - NOTARYTOOL_APP_PASSWORD: ${{ secrets.NOTARYTOOL_APP_PASSWORD }} - APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - run: | - xcrun notarytool submit ./build/mac/material_maker_${MM_RELEASE}${PACKAGE_SUFFIX}.dmg --apple-id $APPLE_ID --password $NOTARYTOOL_APP_PASSWORD --team-id $APPLE_TEAM_ID --wait - xcrun stapler staple -v ./build/mac/material_maker_${MM_RELEASE}${PACKAGE_SUFFIX}.dmg - - name: Upload Mac OSX Artifact 🚀 - if: ${{ github.event.inputs.steam == 'false' && github.event.inputs.artifacts == 'true' }} - uses: actions/upload-artifact@v6 - with: - name: macos_snapshot - path: ./build/mac/material_maker_${{ env.MM_RELEASE }}${{ env.PACKAGE_SUFFIX }}.dmg - - name: Upload Mac OSX Artifact (Steam) 🚀 - if: ${{ github.event.inputs.steam == 'true' }} - uses: actions/upload-artifact@v6 - with: - name: macos_snapshot - path: ./build/mac - deploy_to_steam: - name: Steam deploy 🎮 - runs-on: ubuntu-latest - needs: export_macos - if: ${{ github.event.inputs.steam_deploy == 'true' }} - steps: - - name: Get Windows build 🚀 - uses: actions/download-artifact@v8 - with: - name: windows_snapshot - path: build/windows - - name: Get Linux build 🚀 - uses: actions/download-artifact@v8 - with: - name: linux_snapshot - path: build/linux - - name: Get Macos build 🚀 - uses: actions/download-artifact@v8 - with: - name: macos_snapshot - path: build/macos - - name: Prepare packages 🔧 - run: | - find . - - uses: game-ci/steam-deploy@v3 - with: - username: ${{ secrets.STEAM_USERNAME }} - configVdf: ${{ secrets.STEAM_CONFIG_VDF}} - appId: 4110830 - buildDescription: v${{ env.MM_RELEASE }}_${{ github.sha }} - rootPath: build - depot1Path: windows - depot2Path: macos - depot3Path: linux - releaseBranch: prerelease +# # apply provisioning profile +# mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles +# cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles +# - name: Download and extract Godot and export templates 💾 +# run: | +# wget ${GODOT_DOWNLOAD_DIR}/Godot_v${GODOT_VERSION}-${GODOT_SUB}_macos.arm64.zip +# unzip -a Godot_v${GODOT_VERSION}-${GODOT_SUB}_macos.arm64.zip +# wget ${GODOT_DOWNLOAD_DIR}/Godot_v${GODOT_VERSION}-${GODOT_SUB}_export_templates.tpz +# unzip -a Godot_v${GODOT_VERSION}-${GODOT_SUB}_export_templates.tpz +# mkdir -v -p "/Users/runner/Library/Application Support/Godot/export_templates/${GODOT_VERSION}.${GODOT_SUB}" +# mv ./templates/* "/Users/runner/Library/Application Support/Godot/export_templates/${GODOT_VERSION}.${GODOT_SUB}" +# - name: Mac Build 🔧 +# run: | +# chown runner Godot.app/Contents/MacOS/Godot +# chmod +x Godot.app/Contents/MacOS/Godot +# mkdir -v -p ./build/mac +# Godot.app/Contents/MacOS/Godot --headless -v --export-release "Mac OSX${EXPORT_TARGET_SUFFIX}" ./build/mac/material_maker.zip +# - name: Make application executable 🔧 +# run: | +# unzip -a ./build/mac/material_maker.zip -d ./build/mac +# chmod +x "./build/mac/Material Maker.app/Contents/MacOS/Material Maker" +# rm ./build/mac/material_maker.zip +# - name: Get documentation 🚀 +# if: ${{ github.event.inputs.gen_doc == 'true' && github.event.inputs.artifacts == 'true' }} +# uses: actions/download-artifact@v8 +# with: +# name: documentation +# path: doc +# - name: Copy data folder 📁 +# run: | +# cp -R ./addons/material_maker/nodes "./build/mac/Material Maker.app/Contents/MacOS" +# cp -R ./material_maker/environments "./build/mac/Material Maker.app/Contents/MacOS" +# cp -R ./material_maker/examples "./build/mac/Material Maker.app/Contents/MacOS" +# cp -R ./material_maker/library "./build/mac/Material Maker.app/Contents/MacOS" +# cp -R ./material_maker/meshes "./build/mac/Material Maker.app/Contents/MacOS" +# cp -R ./material_maker/misc/export "./build/mac/Material Maker.app/Contents/MacOS" +# cp -R ./doc "./build/mac/Material Maker.app/Contents/MacOS/doc" || : +# - name: Ad-hoc signing ✍️ +# if: ${{ github.event.inputs.sign_macos != 'true' }} +# run: | +# codesign -s - --force --deep "./build/mac/Material Maker.app" +# - name: Signing ✍️ +# if: ${{ github.event.inputs.sign_macos == 'true' }} +# run: | +# codesign -s "Rodolphe Suescun" --force --timestamp --options runtime --deep "./build/mac/Material Maker.app" +# - name: Create DMG archive 🔧 +# if: ${{ github.event.inputs.steam == 'false' }} +# run: | +# brew untap aws/tap || true +# brew install imagemagick +# cp ./.github/workflows/create-dmg-bg.sh . +# chmod +x create-dmg-bg.sh +# ./create-dmg-bg.sh ./splash_screen/backgrounds/pavel_oliva_vintage_luggage.png ./bg.png +# #hdiutil create -srcfolder ./build/mac -fs HFS+ -volname material_maker material_maker_${MM_RELEASE}${PACKAGE_SUFFIX}.dmg +# wget https://github.com/create-dmg/create-dmg/archive/refs/tags/v1.2.2.zip +# unzip v1.2.2.zip +# create-dmg-1.2.2/create-dmg --volname "Material Maker" --icon-size 128 --background ./bg.png --window-size 540 330 --icon "Material Maker.app" 158 125 --app-drop-link 384 125 --hide-extension "Material Maker.app" ./build/mac/material_maker_${MM_RELEASE}${PACKAGE_SUFFIX}.dmg ./build/mac +# ls +# - name: Notarizing ✍️ +# if: ${{ github.event.inputs.steam == 'false' && github.event.inputs.sign_macos == 'true' }} +# env: +# APPLE_ID: ${{ secrets.APPLE_ID }} +# NOTARYTOOL_APP_PASSWORD: ${{ secrets.NOTARYTOOL_APP_PASSWORD }} +# APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} +# run: | +# xcrun notarytool submit ./build/mac/material_maker_${MM_RELEASE}${PACKAGE_SUFFIX}.dmg --apple-id $APPLE_ID --password $NOTARYTOOL_APP_PASSWORD --team-id $APPLE_TEAM_ID --wait +# xcrun stapler staple -v ./build/mac/material_maker_${MM_RELEASE}${PACKAGE_SUFFIX}.dmg +# - name: Upload Mac OSX Artifact 🚀 +# if: ${{ github.event.inputs.steam == 'false' && github.event.inputs.artifacts == 'true' }} +# uses: actions/upload-artifact@v6 +# with: +# name: macos_snapshot +# path: ./build/mac/material_maker_${{ env.MM_RELEASE }}${{ env.PACKAGE_SUFFIX }}.dmg +# - name: Upload Mac OSX Artifact (Steam) 🚀 +# if: ${{ github.event.inputs.steam == 'true' }} +# uses: actions/upload-artifact@v6 +# with: +# name: macos_snapshot +# path: ./build/mac + +# deploy_to_steam: +# name: Steam deploy 🎮 +# runs-on: ubuntu-latest +# needs: export_macos +# if: ${{ github.event.inputs.steam_deploy == 'true' }} +# steps: +# - name: Get Windows build 🚀 +# uses: actions/download-artifact@v8 +# with: +# name: windows_snapshot +# path: build/windows +# - name: Get Linux build 🚀 +# uses: actions/download-artifact@v8 +# with: +# name: linux_snapshot +# path: build/linux +# - name: Get Macos build 🚀 +# uses: actions/download-artifact@v8 +# with: +# name: macos_snapshot +# path: build/macos +# - name: Prepare packages 🔧 +# run: | +# find . +# - uses: game-ci/steam-deploy@v3 +# with: +# username: ${{ secrets.STEAM_USERNAME }} +# configVdf: ${{ secrets.STEAM_CONFIG_VDF}} +# appId: 4110830 +# buildDescription: v1.7 +# rootPath: build +# depot1Path: windows +# depot2Path: macos +# depot3Path: linux +# releaseBranch: prerelease diff --git a/addons/flexible_layout/flexible_dragger.gd b/addons/flexible_layout/flexible_dragger.gd index 1c53f2ba2a..314fed500a 100644 --- a/addons/flexible_layout/flexible_dragger.gd +++ b/addons/flexible_layout/flexible_dragger.gd @@ -5,12 +5,24 @@ var dragging : bool = false var flex_split : WeakRef var dragger_index : int var vertical : bool +var half_grip_size : int + +var touch_dragger : TouchDragger func _init(): set_meta("flexlayout", true) +func _ready() -> void: + if mm_globals.get_config("touch_optimization"): + touch_dragger = TouchDragger.new() + touch_dragger.name = "TouchDragger" + add_child(touch_dragger) + mouse_entered.disconnect($TextureRect.show) + mouse_exited.disconnect($TextureRect.hide) + func set_split(s, i : int, v : bool): flex_split = weakref(s) + half_grip_size = flex_split.get_ref().grip_size * 0.5 dragger_index = i vertical = v if vertical: @@ -20,10 +32,14 @@ func set_split(s, i : int, v : bool): mouse_default_cursor_shape = Control.CURSOR_HSPLIT $TextureRect.texture = get_theme_icon("grabber", "HSplitContainer") + if mm_globals.get_config("touch_optimization"): + touch_dragger.setup() + mouse_filter = Control.MOUSE_FILTER_IGNORE + var drag_limits : Vector2i var drag_position : int -func _on_gui_input(event): +func _on_gui_input(event : InputEvent, is_touch_dragger_input : bool = false): if event is InputEventMouseButton: if event.button_index == MOUSE_BUTTON_LEFT: dragging = event.pressed @@ -34,15 +50,30 @@ func _on_gui_input(event): drag_limits = flex_split.get_ref().start_flexlayout_drag(dragger_index, drag_position) elif event is InputEventMouseMotion: if dragging: + accept_event() if vertical: - drag_position = position.y+event.position.y-5 + drag_position = position.y+event.position.y - half_grip_size + + if is_touch_dragger_input: + drag_position -= touch_dragger.get_drag_offset() + var new_position_y = clampi(drag_position, drag_limits.x, drag_limits.y) if position.y != new_position_y: position.y = new_position_y flex_split.get_ref().drag(dragger_index, position.y) + + if is_touch_dragger_input: + touch_dragger.update_position(new_position_y) else: - drag_position = position.x+event.position.x-5 + drag_position = position.x+event.position.x - half_grip_size + + if is_touch_dragger_input: + drag_position -= touch_dragger.get_drag_offset() + var new_position_x = clampi(drag_position, drag_limits.x, drag_limits.y) if position.x != new_position_x: position.x = new_position_x flex_split.get_ref().drag(dragger_index, position.x) + + if is_touch_dragger_input: + touch_dragger.update_position(new_position_x) diff --git a/addons/flexible_layout/flexible_dragger.tscn b/addons/flexible_layout/flexible_dragger.tscn index deef46f076..e2016a3abf 100644 --- a/addons/flexible_layout/flexible_dragger.tscn +++ b/addons/flexible_layout/flexible_dragger.tscn @@ -1,18 +1,16 @@ -[gd_scene load_steps=2 format=3 uid="uid://cucx3oayvvxhu"] +[gd_scene format=3 uid="uid://cucx3oayvvxhu"] -[ext_resource type="Script" path="res://addons/flexible_layout/flexible_dragger.gd" id="1_3i5mx"] +[ext_resource type="Script" uid="uid://dgwcni3ebvc8s" path="res://addons/flexible_layout/flexible_dragger.gd" id="1_3i5mx"] -[node name="Dragger" type="HBoxContainer"] -anchors_preset = 8 +[node name="Dragger" type="HBoxContainer" unique_id=1107978390] +anchors_preset = -1 anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 anchor_bottom = 0.5 -grow_horizontal = 2 -grow_vertical = 2 script = ExtResource("1_3i5mx") -[node name="TextureRect" type="TextureRect" parent="."] +[node name="TextureRect" type="TextureRect" parent="." unique_id=1116440276] visible = false layout_mode = 2 size_flags_horizontal = 6 diff --git a/addons/flexible_layout/flexible_dragger_touch.gd b/addons/flexible_layout/flexible_dragger_touch.gd new file mode 100644 index 0000000000..c2f63226f8 --- /dev/null +++ b/addons/flexible_layout/flexible_dragger_touch.gd @@ -0,0 +1,94 @@ +class_name TouchDragger +extends Control + +var is_pressed : bool = false + +static var sb_normal : StyleBoxFlat +static var sb_pressed : StyleBoxFlat + +func _ready() -> void: + set_notify_transform(true) + gui_input.connect(get_parent()._on_gui_input.bind(true)) + + mouse_filter = Control.MOUSE_FILTER_STOP + size_flags_horizontal = Control.SIZE_SHRINK_CENTER + size_flags_vertical = Control.SIZE_SHRINK_CENTER + top_level = true + + init_styleboxes() + +func _draw() -> void: + if sb_pressed and sb_normal: + draw_style_box(sb_pressed if is_pressed else sb_normal, Rect2(Vector2.ZERO, size)) + +func _gui_input(event : InputEvent) -> void: + if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT: + is_pressed = event.pressed + queue_redraw() + +func _notification(what : int) -> void: + match what: + NOTIFICATION_THEME_CHANGED: + update_theme_colors() + NOTIFICATION_TRANSFORM_CHANGED: + update_dragger_global_pos() + +func update_stylebox_colors(base_color : Color, border : Color, + normal_opacity : float, pressed_opacity : float) -> void: + sb_normal.bg_color = base_color + sb_normal.bg_color.a = normal_opacity + sb_normal.border_color = border + + sb_pressed.bg_color = base_color + sb_pressed.bg_color.a = pressed_opacity + sb_pressed.border_color = border + +func init_styleboxes() -> void: + if not sb_normal: + sb_normal = StyleBoxFlat.new() + sb_normal.set_border_width_all(2) + sb_normal.set_corner_radius_all(5) + sb_normal.border_blend = true + sb_normal.corner_detail = 4 + + if not sb_pressed: + sb_pressed = sb_normal.duplicate(true) + +func setup() -> void: + show() + if get_parent().vertical: + mouse_default_cursor_shape = Control.CURSOR_VSPLIT + custom_minimum_size = Vector2(52, 16) + else: + mouse_default_cursor_shape = Control.CURSOR_HSPLIT + custom_minimum_size = Vector2(16, 52) + update_theme_colors() + update_dragger_global_pos.call_deferred() + +func update_dragger_global_pos() -> void: + global_position = get_parent().global_position + (get_parent().size - size) * 0.5 + +func update_position(v : float) -> void: + if get_parent().vertical: + position.y = v + else: + position.x = v + queue_redraw() + +func get_drag_offset() -> int: + return mini(custom_minimum_size.x, custom_minimum_size.y) / 2 + +func update_theme_colors() -> void: + if not sb_normal or not sb_pressed: + init_styleboxes() + match ThemeUtils.current_theme: + ThemeUtils.CUSTOM_THEME: + update_stylebox_colors(ThemeUtils.base_color.lightened(0.3), + ThemeUtils.base_color.darkened(0.2), 0.25, 0.8) + ThemeUtils.DARK_THEME: + update_stylebox_colors(Color.WHITE, Color.BLACK, 0.25, 0.8) + ThemeUtils.LIGHT_THEME: + update_stylebox_colors(Color.BLACK, Color.WHITE, 0.6, 0.25) + ThemeUtils.CLASSIC_THEME: + update_stylebox_colors(Color("506396ff"), Color("768ac2ff"), .25, .8) + queue_redraw() diff --git a/addons/flexible_layout/flexible_dragger_touch.gd.uid b/addons/flexible_layout/flexible_dragger_touch.gd.uid new file mode 100644 index 0000000000..65e38f5042 --- /dev/null +++ b/addons/flexible_layout/flexible_dragger_touch.gd.uid @@ -0,0 +1 @@ +uid://dgeyah0cwww2p diff --git a/addons/flexible_layout/flexible_layout.gd b/addons/flexible_layout/flexible_layout.gd index 1b6a85e2bc..7ce37adc88 100644 --- a/addons/flexible_layout/flexible_layout.gd +++ b/addons/flexible_layout/flexible_layout.gd @@ -109,7 +109,8 @@ class FlexSplit: var draggers : Array[Control] = [] const DRAGGER_SCENE = preload("res://addons/flexible_layout/flexible_dragger.tscn") - + var grip_size : int = 4 if mm_globals.get_config("touch_optimization") else 10 + func _init(p : FlexNode, fl : FlexLayout): super._init(p, fl, "FlexSplit") @@ -122,13 +123,13 @@ class FlexSplit: func get_minimum_size() -> Vector2i: var s : Vector2i if vertical: - s = Vector2i(0, (10*children.size()-1)) + s = Vector2i(0, (grip_size*children.size()-1)) for c in children: var ms : Vector2i = c.get_minimum_size() s.x = max(s.x, ms.x) s.y += ms.y else: - s = Vector2i(10*(children.size()-1), 0) + s = Vector2i(grip_size*(children.size()-1), 0) for c in children: var ms : Vector2i = c.get_minimum_size() s.x += ms.x @@ -185,7 +186,6 @@ class FlexSplit: func layout(r : Rect2): #print("Layout FlexSplit (%d children) - %s" % [ children.size(), str(r) ]) - var grip_size : int = 10 rect = r var children_count : int = children.size() var draggers_count : int = draggers.size() @@ -240,19 +240,19 @@ class FlexSplit: var min_c1_size : Vector2i = c1.get_minimum_size() var min_c2_size : Vector2i = c2.get_minimum_size() if vertical: - return Vector2i(c1.rect.position.y+min_c1_size.y, c2.rect.position.y+c2.rect.size.y-min_c2_size.y-10) + return Vector2i(c1.rect.position.y+min_c1_size.y, c2.rect.position.y+c2.rect.size.y-min_c2_size.y-grip_size) else: - return Vector2i(c1.rect.position.x+min_c1_size.x, c2.rect.position.x+c2.rect.size.x-min_c2_size.x-10) + return Vector2i(c1.rect.position.x+min_c1_size.x, c2.rect.position.x+c2.rect.size.x-min_c2_size.x-grip_size) func drag(dragger_index : int, p : int): var c1 = children[dragger_index] var c2 = children[dragger_index+1] if vertical: c1.layout(Rect2(c1.rect.position, Vector2(c1.rect.size.x, p-c1.rect.position.y))) - c2.layout(Rect2(c2.rect.position.x, p+10, c1.rect.size.x, c2.rect.position.y+c2.rect.size.y-(p+10))) + c2.layout(Rect2(c2.rect.position.x, p+grip_size, c1.rect.size.x, c2.rect.position.y+c2.rect.size.y-(p+grip_size))) else: c1.layout(Rect2(c1.rect.position, Vector2(p-c1.rect.position.x, c1.rect.size.y))) - c2.layout(Rect2(p+10, c2.rect.position.y, c2.rect.position.x+c2.rect.size.x-(p+10), c1.rect.size.y)) + c2.layout(Rect2(p+grip_size, c2.rect.position.y, c2.rect.position.x+c2.rect.size.x-(p+grip_size), c1.rect.size.y)) class FlexTab: diff --git a/addons/flexible_layout/flexible_tab.gd b/addons/flexible_layout/flexible_tab.gd index ff7390b371..c69e155848 100644 --- a/addons/flexible_layout/flexible_tab.gd +++ b/addons/flexible_layout/flexible_tab.gd @@ -24,13 +24,17 @@ func get_flex_layout(): func update(): %Close.texture_normal = get_theme_icon("close", "MM_FlexibleTab") %Close.modulate = get_theme_color("font_selected_color", "MM_FlexibleTab") - %Undock.texture_normal = get_theme_icon("undock", "MM_FlexibleTab") - %Undock.modulate = get_theme_color("font_selected_color", "MM_FlexibleTab") + + if not OS.get_name() == "Android": + %Undock.texture_normal = get_theme_icon("undock", "MM_FlexibleTab") + %Undock.modulate = get_theme_color("font_selected_color", "MM_FlexibleTab") + if not updating: updating = true var is_current: bool = (get_index() == get_parent().get_parent().current) add_theme_stylebox_override("panel", get_theme_stylebox("tab_selected" if is_current else "tab_unselected", "MM_FlexibleTab")) - %Undock.visible = is_current and get_flex_layout().main_control.allow_undock + if not OS.get_name() == "Android": + %Undock.visible = is_current and get_flex_layout().main_control.allow_undock %Close.visible = is_current %Label.add_theme_color_override("font_color", get_theme_color("font_selected_color" if is_current else "font_unselected_color", "MM_FlexibleTab") ) updating = false diff --git a/addons/godotsteam/godotsteam.gdextension b/addons/godotsteam/godotsteam.gdextension index ee29ceb7ac..c649b9996b 100644 --- a/addons/godotsteam/godotsteam.gdextension +++ b/addons/godotsteam/godotsteam.gdextension @@ -14,9 +14,14 @@ linux.debug.x86_32 = "res://addons/godotsteam/linux32/libgodotsteam.linux.templa linux.release.x86_64 = "res://addons/godotsteam/linux64/libgodotsteam.linux.template_release.x86_64.so" linux.release.x86_32 = "res://addons/godotsteam/linux32/libgodotsteam.linux.template_release.x86_32.so" +ios.debug.arm64 = { } +ios.release.arm64 = { } + [dependencies] macos.universal = { "res://addons/godotsteam/osx/libsteam_api.dylib": "" } windows.x86_64 = { "res://addons/godotsteam/win64/steam_api64.dll": "" } windows.x86_32 = { "res://addons/godotsteam/win32/steam_api.dll": "" } linux.x86_64 = { "res://addons/godotsteam/linux64/libsteam_api.so": "" } linux.x86_32 = { "res://addons/godotsteam/linux32/libsteam_api.so": "" } + +ios.arm64 = { } diff --git a/addons/material_maker/engine/nodes/gen_sdf.gd b/addons/material_maker/engine/nodes/gen_sdf.gd index b9e25eb7f6..c8521462c1 100644 --- a/addons/material_maker/engine/nodes/gen_sdf.gd +++ b/addons/material_maker/engine/nodes/gen_sdf.gd @@ -188,8 +188,8 @@ func _deserialize(data : Dictionary) -> void: func edit(node, tab : String = "") -> void: if scene != null: - var edit_window = load("res://material_maker/windows/sdf_builder/sdf_builder.tscn").instantiate() - node.get_parent().add_child(edit_window) + var edit_window : Window = load("res://material_maker/windows/sdf_builder/sdf_builder.tscn").instantiate() + mm_globals.main_window.add_dialog(edit_window) edit_window.set_node_parameter_defs(node_parameters) edit_window.set_sdf_scene(scene) edit_window.connect("node_changed", Callable(node, "update_sdf_generator")) diff --git a/addons/material_maker/engine/nodes/gen_shader.gd b/addons/material_maker/engine/nodes/gen_shader.gd index 7363eda319..ecd9152605 100644 --- a/addons/material_maker/engine/nodes/gen_shader.gd +++ b/addons/material_maker/engine/nodes/gen_shader.gd @@ -822,8 +822,13 @@ func do_edit(node, edit_window_scene : PackedScene, tab : String = "") -> void: edit_window.title = "%s - %s" % [material, edit_window.title] edit_window.get_window().content_scale_factor = mm_globals.ui_scale_factor() edit_window.get_window().min_size = Vector2(950, 450) * edit_window.get_window().content_scale_factor - edit_window.hide() - edit_window.popup_centered() + + if OS.get_name() == "Android": + mm_touch.make_dialog_fullscreen.call_deferred(edit_window, true) + else: + edit_window.hide() + edit_window.popup_centered() + if tab != "": edit_window.show_tab(tab) diff --git a/addons/material_maker/engine/paths.gd b/addons/material_maker/engine/paths.gd index 855334c391..b3be1473d5 100644 --- a/addons/material_maker/engine/paths.gd +++ b/addons/material_maker/engine/paths.gd @@ -6,9 +6,13 @@ const WEBSITE_ADDRESS : String = "https://www.materialmaker.org" const STD_GENDEF_PATH = "res://addons/material_maker/nodes" +const DOC_ADDRESS : String = "https://rodzill4.github.io/material-maker/doc" + static func get_resource_dir() -> String: if Engine.is_editor_hint(): return ProjectSettings.globalize_path("res://material_maker") + if OS.get_name() == "Android": + return "user:/" return OS.get_executable_path().get_base_dir() static func get_nodes_paths() -> Array: diff --git a/export_presets.cfg b/export_presets.cfg index 686352a3a5..d7769ebc85 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -1,14 +1,21 @@ +[runnable_presets] + +"Windows Desktop"="Windows" +Linux="Linux/X11" +macOS="Mac OSX" +Android="Android" +Web="Web" + [preset.0] name="Windows" platform="Windows Desktop" -runnable=true dedicated_server=false custom_features="" export_filter="exclude" export_files=PackedStringArray("res://addons/godotsteam/godotsteam.gdextension", "res://addons/gut/cli/change_project_warnings.gd", "res://addons/gut/cli/gut_cli.gd", "res://addons/gut/cli/optparse.gd", "res://addons/gut/fonts/AnonymousPro-Bold.ttf", "res://addons/gut/fonts/AnonymousPro-BoldItalic.ttf", "res://addons/gut/fonts/AnonymousPro-Italic.ttf", "res://addons/gut/fonts/AnonymousPro-Regular.ttf", "res://addons/gut/fonts/CourierPrime-Bold.ttf", "res://addons/gut/fonts/CourierPrime-BoldItalic.ttf", "res://addons/gut/fonts/CourierPrime-Italic.ttf", "res://addons/gut/fonts/CourierPrime-Regular.ttf", "res://addons/gut/fonts/LobsterTwo-Bold.ttf", "res://addons/gut/fonts/LobsterTwo-BoldItalic.ttf", "res://addons/gut/fonts/LobsterTwo-Italic.ttf", "res://addons/gut/fonts/LobsterTwo-Regular.ttf", "res://addons/gut/gui/about.gd", "res://addons/gut/gui/about.tscn", "res://addons/gut/gui/arrow.png", "res://addons/gut/gui/EditorRadioButton.tres", "res://addons/gut/gui/editor_globals.gd", "res://addons/gut/gui/GutBottomPanel.gd", "res://addons/gut/gui/GutBottomPanel.tscn", "res://addons/gut/gui/GutControl.gd", "res://addons/gut/gui/GutControl.tscn", "res://addons/gut/gui/GutEditorWindow.gd", "res://addons/gut/gui/GutEditorWindow.tscn", "res://addons/gut/gui/GutLogo.tscn", "res://addons/gut/gui/GutRunner.gd", "res://addons/gut/gui/GutRunner.tscn", "res://addons/gut/gui/GutSceneTheme.tres", "res://addons/gut/gui/gut_config_gui.gd", "res://addons/gut/gui/gut_gui.gd", "res://addons/gut/gui/gut_logo.gd", "res://addons/gut/gui/gut_user_preferences.gd", "res://addons/gut/gui/MinGui.tscn", "res://addons/gut/gui/NormalGui.tscn", "res://addons/gut/gui/option_maker.gd", "res://addons/gut/gui/OutputText.gd", "res://addons/gut/gui/OutputText.tscn", "res://addons/gut/gui/panel_controls.gd", "res://addons/gut/gui/play.png", "res://addons/gut/gui/ResizeHandle.gd", "res://addons/gut/gui/ResizeHandle.tscn", "res://addons/gut/gui/ResultsTree.gd", "res://addons/gut/gui/ResultsTree.tscn", "res://addons/gut/gui/RunAtCursor.gd", "res://addons/gut/gui/RunAtCursor.tscn", "res://addons/gut/gui/RunExternally.gd", "res://addons/gut/gui/RunExternally.tscn", "res://addons/gut/gui/RunResults.gd", "res://addons/gut/gui/RunResults.tscn", "res://addons/gut/gui/run_from_editor.gd", "res://addons/gut/gui/run_from_editor.tscn", "res://addons/gut/gui/Settings.tscn", "res://addons/gut/gui/ShellOutOptions.gd", "res://addons/gut/gui/ShellOutOptions.tscn", "res://addons/gut/gui/ShortcutButton.gd", "res://addons/gut/gui/ShortcutButton.tscn", "res://addons/gut/gui/ShortcutDialog.gd", "res://addons/gut/gui/ShortcutDialog.tscn", "res://addons/gut/images/eyey.png", "res://addons/gut/images/Folder.svg", "res://addons/gut/images/green.png", "res://addons/gut/images/GutIconV2_base.png", "res://addons/gut/images/GutIconV2_no_shine.png", "res://addons/gut/images/HSplitContainer.svg", "res://addons/gut/images/red.png", "res://addons/gut/images/Script.svg", "res://addons/gut/images/VSplitContainer.svg", "res://addons/gut/images/yellow.png", "res://addons/gut/autofree.gd", "res://addons/gut/awaiter.gd", "res://addons/gut/collected_script.gd", "res://addons/gut/collected_test.gd", "res://addons/gut/comparator.gd", "res://addons/gut/compare_result.gd", "res://addons/gut/diff_formatter.gd", "res://addons/gut/diff_tool.gd", "res://addons/gut/doubler.gd", "res://addons/gut/double_tools.gd", "res://addons/gut/dynamic_gdscript.gd", "res://addons/gut/editor_caret_context_notifier.gd", "res://addons/gut/error_tracker.gd", "res://addons/gut/get_editor_interface.gd", "res://addons/gut/gut.gd", "res://addons/gut/GutScene.gd", "res://addons/gut/GutScene.tscn", "res://addons/gut/gut_cmdln.gd", "res://addons/gut/gut_config.gd", "res://addons/gut/gut_fonts.gd", "res://addons/gut/gut_loader.gd", "res://addons/gut/gut_loader_the_scene.tscn", "res://addons/gut/gut_menu.gd", "res://addons/gut/gut_plugin.gd", "res://addons/gut/gut_to_move.gd", "res://addons/gut/gut_tracked_error.gd", "res://addons/gut/gut_vscode_debugger.gd", "res://addons/gut/hook_script.gd", "res://addons/gut/icon.png", "res://addons/gut/inner_class_registry.gd", "res://addons/gut/input_factory.gd", "res://addons/gut/input_sender.gd", "res://addons/gut/junit_xml_export.gd", "res://addons/gut/lazy_loader.gd", "res://addons/gut/logger.gd", "res://addons/gut/method_maker.gd", "res://addons/gut/one_to_many.gd", "res://addons/gut/orphan_counter.gd", "res://addons/gut/parameter_factory.gd", "res://addons/gut/parameter_handler.gd", "res://addons/gut/printers.gd", "res://addons/gut/result_exporter.gd", "res://addons/gut/script_parser.gd", "res://addons/gut/signal_watcher.gd", "res://addons/gut/source_code_pro.fnt", "res://addons/gut/spy.gd", "res://addons/gut/strutils.gd", "res://addons/gut/stubber.gd", "res://addons/gut/stub_params.gd", "res://addons/gut/summary.gd", "res://addons/gut/test.gd", "res://addons/gut/test_collector.gd", "res://addons/gut/thing_counter.gd", "res://addons/gut/UserFileViewer.gd", "res://addons/gut/UserFileViewer.tscn", "res://addons/gut/utils.gd", "res://addons/gut/version_conversion.gd", "res://addons/gut/version_numbers.gd", "res://addons/gut/warnings_manager.gd", "res://demo/demo.tscn", "res://demo/object.tscn") include_filter="*.tmpl" -exclude_filter="*.ptex,*.mmn,*.mmg" +exclude_filter="*.ptex,*.mmn,*.mmg, no_export/*" export_path="../../rodz_labs/releases/mm_1_5/material_maker_1_5_windows/material_maker.exe" patches=PackedStringArray() patch_delta_encoding=false @@ -79,13 +86,12 @@ texture_format/etc2=true name="Linux/X11" platform="Linux" -runnable=true dedicated_server=false custom_features="" export_filter="exclude" export_files=PackedStringArray("res://addons/godotsteam/godotsteam.gdextension", "res://addons/gut/cli/change_project_warnings.gd", "res://addons/gut/cli/gut_cli.gd", "res://addons/gut/cli/optparse.gd", "res://addons/gut/fonts/AnonymousPro-Bold.ttf", "res://addons/gut/fonts/AnonymousPro-BoldItalic.ttf", "res://addons/gut/fonts/AnonymousPro-Italic.ttf", "res://addons/gut/fonts/AnonymousPro-Regular.ttf", "res://addons/gut/fonts/CourierPrime-Bold.ttf", "res://addons/gut/fonts/CourierPrime-BoldItalic.ttf", "res://addons/gut/fonts/CourierPrime-Italic.ttf", "res://addons/gut/fonts/CourierPrime-Regular.ttf", "res://addons/gut/fonts/LobsterTwo-Bold.ttf", "res://addons/gut/fonts/LobsterTwo-BoldItalic.ttf", "res://addons/gut/fonts/LobsterTwo-Italic.ttf", "res://addons/gut/fonts/LobsterTwo-Regular.ttf", "res://addons/gut/gui/about.gd", "res://addons/gut/gui/about.tscn", "res://addons/gut/gui/arrow.png", "res://addons/gut/gui/EditorRadioButton.tres", "res://addons/gut/gui/editor_globals.gd", "res://addons/gut/gui/GutBottomPanel.gd", "res://addons/gut/gui/GutBottomPanel.tscn", "res://addons/gut/gui/GutControl.gd", "res://addons/gut/gui/GutControl.tscn", "res://addons/gut/gui/GutEditorWindow.gd", "res://addons/gut/gui/GutEditorWindow.tscn", "res://addons/gut/gui/GutLogo.tscn", "res://addons/gut/gui/GutRunner.gd", "res://addons/gut/gui/GutRunner.tscn", "res://addons/gut/gui/GutSceneTheme.tres", "res://addons/gut/gui/gut_config_gui.gd", "res://addons/gut/gui/gut_gui.gd", "res://addons/gut/gui/gut_logo.gd", "res://addons/gut/gui/gut_user_preferences.gd", "res://addons/gut/gui/MinGui.tscn", "res://addons/gut/gui/NormalGui.tscn", "res://addons/gut/gui/option_maker.gd", "res://addons/gut/gui/OutputText.gd", "res://addons/gut/gui/OutputText.tscn", "res://addons/gut/gui/panel_controls.gd", "res://addons/gut/gui/play.png", "res://addons/gut/gui/ResizeHandle.gd", "res://addons/gut/gui/ResizeHandle.tscn", "res://addons/gut/gui/ResultsTree.gd", "res://addons/gut/gui/ResultsTree.tscn", "res://addons/gut/gui/RunAtCursor.gd", "res://addons/gut/gui/RunAtCursor.tscn", "res://addons/gut/gui/RunExternally.gd", "res://addons/gut/gui/RunExternally.tscn", "res://addons/gut/gui/RunResults.gd", "res://addons/gut/gui/RunResults.tscn", "res://addons/gut/gui/run_from_editor.gd", "res://addons/gut/gui/run_from_editor.tscn", "res://addons/gut/gui/Settings.tscn", "res://addons/gut/gui/ShellOutOptions.gd", "res://addons/gut/gui/ShellOutOptions.tscn", "res://addons/gut/gui/ShortcutButton.gd", "res://addons/gut/gui/ShortcutButton.tscn", "res://addons/gut/gui/ShortcutDialog.gd", "res://addons/gut/gui/ShortcutDialog.tscn", "res://addons/gut/images/eyey.png", "res://addons/gut/images/Folder.svg", "res://addons/gut/images/green.png", "res://addons/gut/images/GutIconV2_base.png", "res://addons/gut/images/GutIconV2_no_shine.png", "res://addons/gut/images/HSplitContainer.svg", "res://addons/gut/images/red.png", "res://addons/gut/images/Script.svg", "res://addons/gut/images/VSplitContainer.svg", "res://addons/gut/images/yellow.png", "res://addons/gut/autofree.gd", "res://addons/gut/awaiter.gd", "res://addons/gut/collected_script.gd", "res://addons/gut/collected_test.gd", "res://addons/gut/comparator.gd", "res://addons/gut/compare_result.gd", "res://addons/gut/diff_formatter.gd", "res://addons/gut/diff_tool.gd", "res://addons/gut/doubler.gd", "res://addons/gut/double_tools.gd", "res://addons/gut/dynamic_gdscript.gd", "res://addons/gut/editor_caret_context_notifier.gd", "res://addons/gut/error_tracker.gd", "res://addons/gut/get_editor_interface.gd", "res://addons/gut/gut.gd", "res://addons/gut/GutScene.gd", "res://addons/gut/GutScene.tscn", "res://addons/gut/gut_cmdln.gd", "res://addons/gut/gut_config.gd", "res://addons/gut/gut_fonts.gd", "res://addons/gut/gut_loader.gd", "res://addons/gut/gut_loader_the_scene.tscn", "res://addons/gut/gut_menu.gd", "res://addons/gut/gut_plugin.gd", "res://addons/gut/gut_to_move.gd", "res://addons/gut/gut_tracked_error.gd", "res://addons/gut/gut_vscode_debugger.gd", "res://addons/gut/hook_script.gd", "res://addons/gut/icon.png", "res://addons/gut/inner_class_registry.gd", "res://addons/gut/input_factory.gd", "res://addons/gut/input_sender.gd", "res://addons/gut/junit_xml_export.gd", "res://addons/gut/lazy_loader.gd", "res://addons/gut/logger.gd", "res://addons/gut/method_maker.gd", "res://addons/gut/one_to_many.gd", "res://addons/gut/orphan_counter.gd", "res://addons/gut/parameter_factory.gd", "res://addons/gut/parameter_handler.gd", "res://addons/gut/printers.gd", "res://addons/gut/result_exporter.gd", "res://addons/gut/script_parser.gd", "res://addons/gut/signal_watcher.gd", "res://addons/gut/source_code_pro.fnt", "res://addons/gut/spy.gd", "res://addons/gut/strutils.gd", "res://addons/gut/stubber.gd", "res://addons/gut/stub_params.gd", "res://addons/gut/summary.gd", "res://addons/gut/test.gd", "res://addons/gut/test_collector.gd", "res://addons/gut/thing_counter.gd", "res://addons/gut/UserFileViewer.gd", "res://addons/gut/UserFileViewer.tscn", "res://addons/gut/utils.gd", "res://addons/gut/version_conversion.gd", "res://addons/gut/version_numbers.gd", "res://addons/gut/warnings_manager.gd", "res://demo/demo.tscn", "res://demo/object.tscn") include_filter="*.tmpl" -exclude_filter="*.ptex,*.mmn,*.mmg" +exclude_filter="*.ptex,*.mmn,*.mmg, no_export/*" export_path="../material_maker.x86_64" patches=PackedStringArray() patch_delta_encoding=false @@ -131,13 +137,12 @@ texture_format/etc2=false name="Mac OSX" platform="macOS" -runnable=true dedicated_server=false custom_features="" export_filter="exclude" export_files=PackedStringArray("res://addons/godotsteam/godotsteam.gdextension", "res://addons/gut/cli/change_project_warnings.gd", "res://addons/gut/cli/gut_cli.gd", "res://addons/gut/cli/optparse.gd", "res://addons/gut/fonts/AnonymousPro-Bold.ttf", "res://addons/gut/fonts/AnonymousPro-BoldItalic.ttf", "res://addons/gut/fonts/AnonymousPro-Italic.ttf", "res://addons/gut/fonts/AnonymousPro-Regular.ttf", "res://addons/gut/fonts/CourierPrime-Bold.ttf", "res://addons/gut/fonts/CourierPrime-BoldItalic.ttf", "res://addons/gut/fonts/CourierPrime-Italic.ttf", "res://addons/gut/fonts/CourierPrime-Regular.ttf", "res://addons/gut/fonts/LobsterTwo-Bold.ttf", "res://addons/gut/fonts/LobsterTwo-BoldItalic.ttf", "res://addons/gut/fonts/LobsterTwo-Italic.ttf", "res://addons/gut/fonts/LobsterTwo-Regular.ttf", "res://addons/gut/gui/about.gd", "res://addons/gut/gui/about.tscn", "res://addons/gut/gui/arrow.png", "res://addons/gut/gui/EditorRadioButton.tres", "res://addons/gut/gui/editor_globals.gd", "res://addons/gut/gui/GutBottomPanel.gd", "res://addons/gut/gui/GutBottomPanel.tscn", "res://addons/gut/gui/GutControl.gd", "res://addons/gut/gui/GutControl.tscn", "res://addons/gut/gui/GutEditorWindow.gd", "res://addons/gut/gui/GutEditorWindow.tscn", "res://addons/gut/gui/GutLogo.tscn", "res://addons/gut/gui/GutRunner.gd", "res://addons/gut/gui/GutRunner.tscn", "res://addons/gut/gui/GutSceneTheme.tres", "res://addons/gut/gui/gut_config_gui.gd", "res://addons/gut/gui/gut_gui.gd", "res://addons/gut/gui/gut_logo.gd", "res://addons/gut/gui/gut_user_preferences.gd", "res://addons/gut/gui/MinGui.tscn", "res://addons/gut/gui/NormalGui.tscn", "res://addons/gut/gui/option_maker.gd", "res://addons/gut/gui/OutputText.gd", "res://addons/gut/gui/OutputText.tscn", "res://addons/gut/gui/panel_controls.gd", "res://addons/gut/gui/play.png", "res://addons/gut/gui/ResizeHandle.gd", "res://addons/gut/gui/ResizeHandle.tscn", "res://addons/gut/gui/ResultsTree.gd", "res://addons/gut/gui/ResultsTree.tscn", "res://addons/gut/gui/RunAtCursor.gd", "res://addons/gut/gui/RunAtCursor.tscn", "res://addons/gut/gui/RunExternally.gd", "res://addons/gut/gui/RunExternally.tscn", "res://addons/gut/gui/RunResults.gd", "res://addons/gut/gui/RunResults.tscn", "res://addons/gut/gui/run_from_editor.gd", "res://addons/gut/gui/run_from_editor.tscn", "res://addons/gut/gui/Settings.tscn", "res://addons/gut/gui/ShellOutOptions.gd", "res://addons/gut/gui/ShellOutOptions.tscn", "res://addons/gut/gui/ShortcutButton.gd", "res://addons/gut/gui/ShortcutButton.tscn", "res://addons/gut/gui/ShortcutDialog.gd", "res://addons/gut/gui/ShortcutDialog.tscn", "res://addons/gut/images/eyey.png", "res://addons/gut/images/Folder.svg", "res://addons/gut/images/green.png", "res://addons/gut/images/GutIconV2_base.png", "res://addons/gut/images/GutIconV2_no_shine.png", "res://addons/gut/images/HSplitContainer.svg", "res://addons/gut/images/red.png", "res://addons/gut/images/Script.svg", "res://addons/gut/images/VSplitContainer.svg", "res://addons/gut/images/yellow.png", "res://addons/gut/autofree.gd", "res://addons/gut/awaiter.gd", "res://addons/gut/collected_script.gd", "res://addons/gut/collected_test.gd", "res://addons/gut/comparator.gd", "res://addons/gut/compare_result.gd", "res://addons/gut/diff_formatter.gd", "res://addons/gut/diff_tool.gd", "res://addons/gut/doubler.gd", "res://addons/gut/double_tools.gd", "res://addons/gut/dynamic_gdscript.gd", "res://addons/gut/editor_caret_context_notifier.gd", "res://addons/gut/error_tracker.gd", "res://addons/gut/get_editor_interface.gd", "res://addons/gut/gut.gd", "res://addons/gut/GutScene.gd", "res://addons/gut/GutScene.tscn", "res://addons/gut/gut_cmdln.gd", "res://addons/gut/gut_config.gd", "res://addons/gut/gut_fonts.gd", "res://addons/gut/gut_loader.gd", "res://addons/gut/gut_loader_the_scene.tscn", "res://addons/gut/gut_menu.gd", "res://addons/gut/gut_plugin.gd", "res://addons/gut/gut_to_move.gd", "res://addons/gut/gut_tracked_error.gd", "res://addons/gut/gut_vscode_debugger.gd", "res://addons/gut/hook_script.gd", "res://addons/gut/icon.png", "res://addons/gut/inner_class_registry.gd", "res://addons/gut/input_factory.gd", "res://addons/gut/input_sender.gd", "res://addons/gut/junit_xml_export.gd", "res://addons/gut/lazy_loader.gd", "res://addons/gut/logger.gd", "res://addons/gut/method_maker.gd", "res://addons/gut/one_to_many.gd", "res://addons/gut/orphan_counter.gd", "res://addons/gut/parameter_factory.gd", "res://addons/gut/parameter_handler.gd", "res://addons/gut/printers.gd", "res://addons/gut/result_exporter.gd", "res://addons/gut/script_parser.gd", "res://addons/gut/signal_watcher.gd", "res://addons/gut/source_code_pro.fnt", "res://addons/gut/spy.gd", "res://addons/gut/strutils.gd", "res://addons/gut/stubber.gd", "res://addons/gut/stub_params.gd", "res://addons/gut/summary.gd", "res://addons/gut/test.gd", "res://addons/gut/test_collector.gd", "res://addons/gut/thing_counter.gd", "res://addons/gut/UserFileViewer.gd", "res://addons/gut/UserFileViewer.tscn", "res://addons/gut/utils.gd", "res://addons/gut/version_conversion.gd", "res://addons/gut/version_numbers.gd", "res://addons/gut/warnings_manager.gd", "res://demo/demo.tscn", "res://demo/object.tscn") include_filter="*.tmpl" -exclude_filter="*.ptex,*.mmn,*.mmg" +exclude_filter="*.ptex,*.mmn,*.mmg, no_export/*" export_path="../material_maker_macosx.dmg.zip" patches=PackedStringArray() patch_delta_encoding=false @@ -397,7 +402,6 @@ application/min_macos_version="10.12" name="Windows Steam" platform="Windows Desktop" -runnable=false dedicated_server=false custom_features="" export_filter="exclude" @@ -474,13 +478,12 @@ texture_format/etc2=true name="Linux/X11 Steam" platform="Linux" -runnable=false dedicated_server=false custom_features="" export_filter="exclude" export_files=PackedStringArray("res://addons/gut/cli/change_project_warnings.gd", "res://addons/gut/cli/gut_cli.gd", "res://addons/gut/cli/optparse.gd", "res://addons/gut/fonts/AnonymousPro-Bold.ttf", "res://addons/gut/fonts/AnonymousPro-BoldItalic.ttf", "res://addons/gut/fonts/AnonymousPro-Italic.ttf", "res://addons/gut/fonts/AnonymousPro-Regular.ttf", "res://addons/gut/fonts/CourierPrime-Bold.ttf", "res://addons/gut/fonts/CourierPrime-BoldItalic.ttf", "res://addons/gut/fonts/CourierPrime-Italic.ttf", "res://addons/gut/fonts/CourierPrime-Regular.ttf", "res://addons/gut/fonts/LobsterTwo-Bold.ttf", "res://addons/gut/fonts/LobsterTwo-BoldItalic.ttf", "res://addons/gut/fonts/LobsterTwo-Italic.ttf", "res://addons/gut/fonts/LobsterTwo-Regular.ttf", "res://addons/gut/gui/about.gd", "res://addons/gut/gui/about.tscn", "res://addons/gut/gui/arrow.png", "res://addons/gut/gui/EditorRadioButton.tres", "res://addons/gut/gui/editor_globals.gd", "res://addons/gut/gui/GutBottomPanel.gd", "res://addons/gut/gui/GutBottomPanel.tscn", "res://addons/gut/gui/GutControl.gd", "res://addons/gut/gui/GutControl.tscn", "res://addons/gut/gui/GutEditorWindow.gd", "res://addons/gut/gui/GutEditorWindow.tscn", "res://addons/gut/gui/GutLogo.tscn", "res://addons/gut/gui/GutRunner.gd", "res://addons/gut/gui/GutRunner.tscn", "res://addons/gut/gui/GutSceneTheme.tres", "res://addons/gut/gui/gut_config_gui.gd", "res://addons/gut/gui/gut_gui.gd", "res://addons/gut/gui/gut_logo.gd", "res://addons/gut/gui/gut_user_preferences.gd", "res://addons/gut/gui/MinGui.tscn", "res://addons/gut/gui/NormalGui.tscn", "res://addons/gut/gui/option_maker.gd", "res://addons/gut/gui/OutputText.gd", "res://addons/gut/gui/OutputText.tscn", "res://addons/gut/gui/panel_controls.gd", "res://addons/gut/gui/play.png", "res://addons/gut/gui/ResizeHandle.gd", "res://addons/gut/gui/ResizeHandle.tscn", "res://addons/gut/gui/ResultsTree.gd", "res://addons/gut/gui/ResultsTree.tscn", "res://addons/gut/gui/RunAtCursor.gd", "res://addons/gut/gui/RunAtCursor.tscn", "res://addons/gut/gui/RunExternally.gd", "res://addons/gut/gui/RunExternally.tscn", "res://addons/gut/gui/RunResults.gd", "res://addons/gut/gui/RunResults.tscn", "res://addons/gut/gui/run_from_editor.gd", "res://addons/gut/gui/run_from_editor.tscn", "res://addons/gut/gui/Settings.tscn", "res://addons/gut/gui/ShellOutOptions.gd", "res://addons/gut/gui/ShellOutOptions.tscn", "res://addons/gut/gui/ShortcutButton.gd", "res://addons/gut/gui/ShortcutButton.tscn", "res://addons/gut/gui/ShortcutDialog.gd", "res://addons/gut/gui/ShortcutDialog.tscn", "res://addons/gut/images/eyey.png", "res://addons/gut/images/Folder.svg", "res://addons/gut/images/green.png", "res://addons/gut/images/GutIconV2_base.png", "res://addons/gut/images/GutIconV2_no_shine.png", "res://addons/gut/images/HSplitContainer.svg", "res://addons/gut/images/red.png", "res://addons/gut/images/Script.svg", "res://addons/gut/images/VSplitContainer.svg", "res://addons/gut/images/yellow.png", "res://addons/gut/autofree.gd", "res://addons/gut/awaiter.gd", "res://addons/gut/collected_script.gd", "res://addons/gut/collected_test.gd", "res://addons/gut/comparator.gd", "res://addons/gut/compare_result.gd", "res://addons/gut/diff_formatter.gd", "res://addons/gut/diff_tool.gd", "res://addons/gut/doubler.gd", "res://addons/gut/double_tools.gd", "res://addons/gut/dynamic_gdscript.gd", "res://addons/gut/editor_caret_context_notifier.gd", "res://addons/gut/error_tracker.gd", "res://addons/gut/get_editor_interface.gd", "res://addons/gut/gut.gd", "res://addons/gut/GutScene.gd", "res://addons/gut/GutScene.tscn", "res://addons/gut/gut_cmdln.gd", "res://addons/gut/gut_config.gd", "res://addons/gut/gut_fonts.gd", "res://addons/gut/gut_loader.gd", "res://addons/gut/gut_loader_the_scene.tscn", "res://addons/gut/gut_menu.gd", "res://addons/gut/gut_plugin.gd", "res://addons/gut/gut_to_move.gd", "res://addons/gut/gut_tracked_error.gd", "res://addons/gut/gut_vscode_debugger.gd", "res://addons/gut/hook_script.gd", "res://addons/gut/icon.png", "res://addons/gut/inner_class_registry.gd", "res://addons/gut/input_factory.gd", "res://addons/gut/input_sender.gd", "res://addons/gut/junit_xml_export.gd", "res://addons/gut/lazy_loader.gd", "res://addons/gut/logger.gd", "res://addons/gut/method_maker.gd", "res://addons/gut/one_to_many.gd", "res://addons/gut/orphan_counter.gd", "res://addons/gut/parameter_factory.gd", "res://addons/gut/parameter_handler.gd", "res://addons/gut/printers.gd", "res://addons/gut/result_exporter.gd", "res://addons/gut/script_parser.gd", "res://addons/gut/signal_watcher.gd", "res://addons/gut/source_code_pro.fnt", "res://addons/gut/spy.gd", "res://addons/gut/strutils.gd", "res://addons/gut/stubber.gd", "res://addons/gut/stub_params.gd", "res://addons/gut/summary.gd", "res://addons/gut/test.gd", "res://addons/gut/test_collector.gd", "res://addons/gut/thing_counter.gd", "res://addons/gut/UserFileViewer.gd", "res://addons/gut/UserFileViewer.tscn", "res://addons/gut/utils.gd", "res://addons/gut/version_conversion.gd", "res://addons/gut/version_numbers.gd", "res://addons/gut/warnings_manager.gd", "res://demo/demo.tscn", "res://demo/object.tscn") include_filter="*.tmpl" -exclude_filter="*.ptex,*.mmn,*.mmg" +exclude_filter="*.ptex,*.mmn,*.mmg, no_export/*" export_path="" patches=PackedStringArray() patch_delta_encoding=false @@ -526,7 +529,6 @@ texture_format/etc2=false name="Mac OSX Steam" platform="macOS" -runnable=false dedicated_server=false custom_features="" export_filter="exclude" @@ -792,7 +794,6 @@ application/min_macos_version="10.12" name="Windows Demo" platform="Windows Desktop" -runnable=false dedicated_server=false custom_features="" export_filter="resources" @@ -869,13 +870,13 @@ texture_format/etc2=true name="Android" platform="Android" -runnable=true dedicated_server=false custom_features="" -export_filter="all_resources" -include_filter="*.json,*.mmg,*.mmt,addons/material_maker/nodes/*,material_maker/library/*.json" -exclude_filter="" -export_path="./material_maker.apk" +export_filter="exclude" +export_files=PackedStringArray("res://addons/godotsteam/godotsteam.gdextension", "res://addons/gut/cli/change_project_warnings.gd", "res://addons/gut/cli/gut_cli.gd", "res://addons/gut/cli/optparse.gd", "res://addons/gut/fonts/AnonymousPro-Bold.ttf", "res://addons/gut/fonts/AnonymousPro-BoldItalic.ttf", "res://addons/gut/fonts/AnonymousPro-Italic.ttf", "res://addons/gut/fonts/AnonymousPro-Regular.ttf", "res://addons/gut/fonts/CourierPrime-Bold.ttf", "res://addons/gut/fonts/CourierPrime-BoldItalic.ttf", "res://addons/gut/fonts/CourierPrime-Italic.ttf", "res://addons/gut/fonts/CourierPrime-Regular.ttf", "res://addons/gut/fonts/LobsterTwo-Bold.ttf", "res://addons/gut/fonts/LobsterTwo-BoldItalic.ttf", "res://addons/gut/fonts/LobsterTwo-Italic.ttf", "res://addons/gut/fonts/LobsterTwo-Regular.ttf", "res://addons/gut/gui/about.gd", "res://addons/gut/gui/about.tscn", "res://addons/gut/gui/arrow.png", "res://addons/gut/gui/EditorRadioButton.tres", "res://addons/gut/gui/editor_globals.gd", "res://addons/gut/gui/GutBottomPanel.gd", "res://addons/gut/gui/GutBottomPanel.tscn", "res://addons/gut/gui/GutControl.gd", "res://addons/gut/gui/GutControl.tscn", "res://addons/gut/gui/GutEditorWindow.gd", "res://addons/gut/gui/GutEditorWindow.tscn", "res://demo/object.tscn", "res://addons/gut/gui/GutRunner.gd", "res://addons/gut/gui/GutRunner.tscn", "res://addons/gut/gui/GutSceneTheme.tres", "res://addons/gut/gui/gut_config_gui.gd", "res://addons/gut/gui/gut_gui.gd", "res://addons/gut/gui/gut_logo.gd", "res://addons/gut/gui/gut_user_preferences.gd", "res://addons/gut/gui/MinGui.tscn", "res://addons/gut/gui/NormalGui.tscn", "res://addons/gut/gui/option_maker.gd", "res://addons/gut/gui/OutputText.gd", "res://addons/gut/gui/OutputText.tscn", "res://addons/gut/gui/panel_controls.gd", "res://addons/gut/gui/play.png", "res://addons/gut/gui/ResizeHandle.gd", "res://addons/gut/gui/ResizeHandle.tscn", "res://addons/gut/gui/ResultsTree.gd", "res://addons/gut/gui/ResultsTree.tscn", "res://addons/gut/gui/RunAtCursor.gd", "res://addons/gut/gui/RunAtCursor.tscn", "res://addons/gut/gui/RunExternally.gd", "res://addons/gut/gui/RunExternally.tscn", "res://addons/gut/gui/RunResults.gd", "res://addons/gut/gui/RunResults.tscn", "res://addons/gut/gui/run_from_editor.gd", "res://addons/gut/gui/run_from_editor.tscn", "res://addons/gut/gui/Settings.tscn", "res://addons/gut/gui/ShellOutOptions.gd", "res://addons/gut/gui/ShellOutOptions.tscn", "res://addons/gut/gui/ShortcutButton.gd", "res://addons/gut/gui/ShortcutButton.tscn", "res://addons/gut/gui/ShortcutDialog.gd", "res://addons/gut/gui/ShortcutDialog.tscn", "res://addons/gut/images/eyey.png", "res://addons/gut/images/Folder.svg", "res://addons/gut/images/green.png", "res://addons/gut/images/GutIconV2_base.png", "res://addons/gut/images/GutIconV2_no_shine.png", "res://addons/gut/images/HSplitContainer.svg", "res://addons/gut/images/red.png", "res://addons/gut/images/Script.svg", "res://addons/gut/images/VSplitContainer.svg", "res://addons/gut/images/yellow.png", "res://addons/gut/autofree.gd", "res://addons/gut/awaiter.gd", "res://addons/gut/collected_script.gd", "res://addons/gut/collected_test.gd", "res://addons/gut/comparator.gd", "res://addons/gut/compare_result.gd", "res://addons/gut/diff_formatter.gd", "res://addons/gut/diff_tool.gd", "res://addons/gut/doubler.gd", "res://addons/gut/double_tools.gd", "res://addons/gut/dynamic_gdscript.gd", "res://addons/gut/editor_caret_context_notifier.gd", "res://addons/gut/error_tracker.gd", "res://addons/gut/get_editor_interface.gd", "res://addons/gut/gut.gd", "res://addons/gut/GutScene.gd", "res://addons/gut/GutScene.tscn", "res://addons/gut/gut_cmdln.gd", "res://addons/gut/gut_config.gd", "res://addons/gut/gut_fonts.gd", "res://addons/gut/gut_loader.gd", "res://addons/gut/gut_loader_the_scene.tscn", "res://addons/gut/gut_menu.gd", "res://addons/gut/gut_plugin.gd", "res://addons/gut/gut_to_move.gd", "res://addons/gut/gut_tracked_error.gd", "res://addons/gut/gut_vscode_debugger.gd", "res://addons/gut/hook_script.gd", "res://addons/gut/icon.png", "res://addons/gut/inner_class_registry.gd", "res://addons/gut/input_factory.gd", "res://addons/gut/input_sender.gd", "res://addons/gut/junit_xml_export.gd", "res://addons/gut/lazy_loader.gd", "res://addons/gut/logger.gd", "res://addons/gut/method_maker.gd", "res://addons/gut/one_to_many.gd", "res://addons/gut/orphan_counter.gd", "res://addons/gut/parameter_factory.gd", "res://addons/gut/parameter_handler.gd", "res://addons/gut/printers.gd", "res://addons/gut/result_exporter.gd", "res://addons/gut/script_parser.gd", "res://addons/gut/signal_watcher.gd", "res://addons/gut/source_code_pro.fnt", "res://addons/gut/spy.gd", "res://addons/gut/strutils.gd", "res://addons/gut/stubber.gd", "res://addons/gut/stub_params.gd", "res://addons/gut/summary.gd", "res://addons/gut/test.gd", "res://addons/gut/test_collector.gd", "res://addons/gut/thing_counter.gd", "res://addons/gut/UserFileViewer.gd", "res://addons/gut/UserFileViewer.tscn", "res://addons/gut/utils.gd", "res://addons/gut/version_conversion.gd", "res://addons/gut/version_numbers.gd", "res://addons/gut/warnings_manager.gd", "res://demo/demo.tscn", "res://test/test_doc_completion.gd", "res://addons/gut/gui/GutLogo.tscn", "res://material_maker/theme/test_graphedit.tscn", "res://material_maker/locale/generate_po_template.gd", "res://material_maker/panels/preview_3d/meshes/bricks.tres", "res://material_maker/panels/preview_3d/meshes/bricks_albedo.png", "res://material_maker/panels/preview_3d/meshes/bricks_normal.png", "res://material_maker/panels/preview_3d/meshes/bricks_orm.png", "res://material_maker/panels/preview_3d/meshes/bricks_heightmap.png", "res://scripts/fixup.gd", "res://addons/flexible_layout/test.tscn", "res://addons/flexible_layout/test.gd", "res://addons/material_maker/map_generator/test.gd", "res://addons/material_maker/map_generator/test.tscn", "res://start.gd", "res://start.tscn", "res://addons/material_maker/import_plugin/ptex_import.gd", "res://addons/material_maker/import_plugin/ptex_spatial_material.gd", "res://addons/material_maker/import_plugin/tesselated.gdshader", "res://material_maker/theme/optimize_theme.gd") +include_filter="*.json,*.mmg,*.mmt,addons/material_maker/nodes/*,material_maker/library/*.json,material_maker/examples/*.ptex" +exclude_filter="no_export/*" +export_path="../../../../../Downloads/material-maker.apk" patches=PackedStringArray() patch_delta_encoding=false patch_delta_compression_level_zstd=19 @@ -901,25 +902,25 @@ gradle_build/export_format=0 gradle_build/min_sdk="" gradle_build/target_sdk="" gradle_build/custom_theme_attributes={} -architectures/armeabi-v7a=true +architectures/armeabi-v7a=false architectures/arm64-v8a=true architectures/x86=false -architectures/x86_64=false -version/code=2 -version/name="1.5" +architectures/x86_64=true +version/code=1 +version/name="1.7" package/unique_name="org.rodzlabs.materialmaker" -package/name="" +package/name="Material Maker" package/signed=true -package/app_category=2 +package/app_category=3 package/retain_data_on_uninstall=false package/exclude_from_recents=false package/show_in_android_tv=false package/show_in_app_library=true package/show_as_launcher_app=false -launcher_icons/main_192x192="" -launcher_icons/adaptive_foreground_432x432="" -launcher_icons/adaptive_background_432x432="" -launcher_icons/adaptive_monochrome_432x432="" +launcher_icons/main_192x192="res://no_export/android/android_legacy_icon.webp" +launcher_icons/adaptive_foreground_432x432="res://no_export/android/adaptive_foreground.svg" +launcher_icons/adaptive_background_432x432="res://no_export/android/adaptive_background.svg" +launcher_icons/adaptive_monochrome_432x432="res://no_export/android/adaptive_monochrome.svg" graphics/opengl_debug=false shader_baker/enabled=false xr_features/xr_mode=0 @@ -931,11 +932,12 @@ screen/support_normal=true screen/support_large=true screen/support_xlarge=true screen/background_color=Color(0, 0, 0, 1) +splash_screen/disable_godot_boot_splash=true +splash_screen/icon="" +splash_screen/branding_image="" +splash_screen/background_color=Color(0, 0, 0, 1) user_data_backup/allow=false command_line/extra_args="" -apk_expansion/enable=false -apk_expansion/SALT="" -apk_expansion/public_key="" permissions/custom_permissions=PackedStringArray() permissions/access_checkin_properties=false permissions/access_coarse_location=false @@ -1010,7 +1012,7 @@ permissions/location_hardware=false permissions/manage_accounts=false permissions/manage_app_tokens=false permissions/manage_documents=false -permissions/manage_external_storage=false +permissions/manage_external_storage=true permissions/manage_media=false permissions/master_clear=false permissions/media_content_control=false @@ -1025,7 +1027,7 @@ permissions/process_outgoing_calls=false permissions/read_calendar=false permissions/read_call_log=false permissions/read_contacts=false -permissions/read_external_storage=true +permissions/read_external_storage=false permissions/read_frame_buffer=false permissions/read_history_bookmarks=false permissions/read_input_state=false @@ -1080,7 +1082,7 @@ permissions/write_apn_settings=false permissions/write_calendar=false permissions/write_call_log=false permissions/write_contacts=false -permissions/write_external_storage=true +permissions/write_external_storage=false permissions/write_gservices=false permissions/write_history_bookmarks=false permissions/write_profile=false @@ -1090,15 +1092,244 @@ permissions/write_sms=false permissions/write_social_stream=false permissions/write_sync_settings=false permissions/write_user_dictionary=false +apk_expansion/enable=false +apk_expansion/SALT="" +apk_expansion/public_key="" xr_features/hand_tracking=0 xr_features/hand_tracking_frequency=0 xr_features/passthrough=0 [preset.8] +name="Android AAB" +platform="Android" +dedicated_server=false +custom_features="" +export_filter="exclude" +export_files=PackedStringArray("res://addons/godotsteam/godotsteam.gdextension", "res://addons/gut/cli/change_project_warnings.gd", "res://addons/gut/cli/gut_cli.gd", "res://addons/gut/cli/optparse.gd", "res://addons/gut/fonts/AnonymousPro-Bold.ttf", "res://addons/gut/fonts/AnonymousPro-BoldItalic.ttf", "res://addons/gut/fonts/AnonymousPro-Italic.ttf", "res://addons/gut/fonts/AnonymousPro-Regular.ttf", "res://addons/gut/fonts/CourierPrime-Bold.ttf", "res://addons/gut/fonts/CourierPrime-BoldItalic.ttf", "res://addons/gut/fonts/CourierPrime-Italic.ttf", "res://addons/gut/fonts/CourierPrime-Regular.ttf", "res://addons/gut/fonts/LobsterTwo-Bold.ttf", "res://addons/gut/fonts/LobsterTwo-BoldItalic.ttf", "res://addons/gut/fonts/LobsterTwo-Italic.ttf", "res://addons/gut/fonts/LobsterTwo-Regular.ttf", "res://addons/gut/gui/about.gd", "res://addons/gut/gui/about.tscn", "res://addons/gut/gui/arrow.png", "res://addons/gut/gui/EditorRadioButton.tres", "res://addons/gut/gui/editor_globals.gd", "res://addons/gut/gui/GutBottomPanel.gd", "res://addons/gut/gui/GutBottomPanel.tscn", "res://addons/gut/gui/GutControl.gd", "res://addons/gut/gui/GutControl.tscn", "res://addons/gut/gui/GutEditorWindow.gd", "res://addons/gut/gui/GutEditorWindow.tscn", "res://demo/object.tscn", "res://addons/gut/gui/GutRunner.gd", "res://addons/gut/gui/GutRunner.tscn", "res://addons/gut/gui/GutSceneTheme.tres", "res://addons/gut/gui/gut_config_gui.gd", "res://addons/gut/gui/gut_gui.gd", "res://addons/gut/gui/gut_logo.gd", "res://addons/gut/gui/gut_user_preferences.gd", "res://addons/gut/gui/MinGui.tscn", "res://addons/gut/gui/NormalGui.tscn", "res://addons/gut/gui/option_maker.gd", "res://addons/gut/gui/OutputText.gd", "res://addons/gut/gui/OutputText.tscn", "res://addons/gut/gui/panel_controls.gd", "res://addons/gut/gui/play.png", "res://addons/gut/gui/ResizeHandle.gd", "res://addons/gut/gui/ResizeHandle.tscn", "res://addons/gut/gui/ResultsTree.gd", "res://addons/gut/gui/ResultsTree.tscn", "res://addons/gut/gui/RunAtCursor.gd", "res://addons/gut/gui/RunAtCursor.tscn", "res://addons/gut/gui/RunExternally.gd", "res://addons/gut/gui/RunExternally.tscn", "res://addons/gut/gui/RunResults.gd", "res://addons/gut/gui/RunResults.tscn", "res://addons/gut/gui/run_from_editor.gd", "res://addons/gut/gui/run_from_editor.tscn", "res://addons/gut/gui/Settings.tscn", "res://addons/gut/gui/ShellOutOptions.gd", "res://addons/gut/gui/ShellOutOptions.tscn", "res://addons/gut/gui/ShortcutButton.gd", "res://addons/gut/gui/ShortcutButton.tscn", "res://addons/gut/gui/ShortcutDialog.gd", "res://addons/gut/gui/ShortcutDialog.tscn", "res://addons/gut/images/eyey.png", "res://addons/gut/images/Folder.svg", "res://addons/gut/images/green.png", "res://addons/gut/images/GutIconV2_base.png", "res://addons/gut/images/GutIconV2_no_shine.png", "res://addons/gut/images/HSplitContainer.svg", "res://addons/gut/images/red.png", "res://addons/gut/images/Script.svg", "res://addons/gut/images/VSplitContainer.svg", "res://addons/gut/images/yellow.png", "res://addons/gut/autofree.gd", "res://addons/gut/awaiter.gd", "res://addons/gut/collected_script.gd", "res://addons/gut/collected_test.gd", "res://addons/gut/comparator.gd", "res://addons/gut/compare_result.gd", "res://addons/gut/diff_formatter.gd", "res://addons/gut/diff_tool.gd", "res://addons/gut/doubler.gd", "res://addons/gut/double_tools.gd", "res://addons/gut/dynamic_gdscript.gd", "res://addons/gut/editor_caret_context_notifier.gd", "res://addons/gut/error_tracker.gd", "res://addons/gut/get_editor_interface.gd", "res://addons/gut/gut.gd", "res://addons/gut/GutScene.gd", "res://addons/gut/GutScene.tscn", "res://addons/gut/gut_cmdln.gd", "res://addons/gut/gut_config.gd", "res://addons/gut/gut_fonts.gd", "res://addons/gut/gut_loader.gd", "res://addons/gut/gut_loader_the_scene.tscn", "res://addons/gut/gut_menu.gd", "res://addons/gut/gut_plugin.gd", "res://addons/gut/gut_to_move.gd", "res://addons/gut/gut_tracked_error.gd", "res://addons/gut/gut_vscode_debugger.gd", "res://addons/gut/hook_script.gd", "res://addons/gut/icon.png", "res://addons/gut/inner_class_registry.gd", "res://addons/gut/input_factory.gd", "res://addons/gut/input_sender.gd", "res://addons/gut/junit_xml_export.gd", "res://addons/gut/lazy_loader.gd", "res://addons/gut/logger.gd", "res://addons/gut/method_maker.gd", "res://addons/gut/one_to_many.gd", "res://addons/gut/orphan_counter.gd", "res://addons/gut/parameter_factory.gd", "res://addons/gut/parameter_handler.gd", "res://addons/gut/printers.gd", "res://addons/gut/result_exporter.gd", "res://addons/gut/script_parser.gd", "res://addons/gut/signal_watcher.gd", "res://addons/gut/source_code_pro.fnt", "res://addons/gut/spy.gd", "res://addons/gut/strutils.gd", "res://addons/gut/stubber.gd", "res://addons/gut/stub_params.gd", "res://addons/gut/summary.gd", "res://addons/gut/test.gd", "res://addons/gut/test_collector.gd", "res://addons/gut/thing_counter.gd", "res://addons/gut/UserFileViewer.gd", "res://addons/gut/UserFileViewer.tscn", "res://addons/gut/utils.gd", "res://addons/gut/version_conversion.gd", "res://addons/gut/version_numbers.gd", "res://addons/gut/warnings_manager.gd", "res://demo/demo.tscn", "res://test/test_doc_completion.gd", "res://addons/gut/gui/GutLogo.tscn", "res://material_maker/theme/test_graphedit.tscn", "res://material_maker/locale/generate_po_template.gd", "res://material_maker/panels/preview_3d/meshes/bricks.tres", "res://material_maker/panels/preview_3d/meshes/bricks_albedo.png", "res://material_maker/panels/preview_3d/meshes/bricks_normal.png", "res://material_maker/panels/preview_3d/meshes/bricks_orm.png", "res://material_maker/panels/preview_3d/meshes/bricks_heightmap.png", "res://scripts/fixup.gd", "res://addons/flexible_layout/test.tscn", "res://addons/flexible_layout/test.gd", "res://addons/material_maker/map_generator/test.gd", "res://addons/material_maker/map_generator/test.tscn", "res://start.gd", "res://start.tscn", "res://addons/material_maker/import_plugin/ptex_import.gd", "res://addons/material_maker/import_plugin/ptex_spatial_material.gd", "res://addons/material_maker/import_plugin/tesselated.gdshader", "res://material_maker/theme/optimize_theme.gd") +include_filter="*.json,*.mmg,*.mmt,addons/material_maker/nodes/*,material_maker/library/*.json,material_maker/examples/*.ptex" +exclude_filter="no_export/*" +export_path="./material-maker.aab" +patches=PackedStringArray() +patch_delta_encoding=false +patch_delta_compression_level_zstd=19 +patch_delta_min_reduction=0.1 +patch_delta_include_filters="*" +patch_delta_exclude_filters="" +encryption_include_filters="" +encryption_exclude_filters="" +seed=0 +encrypt_pck=false +encrypt_directory=false +script_export_mode=2 + +[preset.8.options] + +custom_template/debug="" +custom_template/release="" +gradle_build/use_gradle_build=true +gradle_build/gradle_build_directory="" +gradle_build/android_source_template="" +gradle_build/compress_native_libraries=false +gradle_build/export_format=1 +gradle_build/min_sdk="" +gradle_build/target_sdk="" +gradle_build/custom_theme_attributes={} +architectures/armeabi-v7a=false +architectures/arm64-v8a=true +architectures/x86=false +architectures/x86_64=true +version/code=1 +version/name="1.7" +package/unique_name="org.rodzlabs.materialmaker" +package/name="Material Maker" +package/signed=true +package/app_category=3 +package/retain_data_on_uninstall=false +package/exclude_from_recents=false +package/show_in_android_tv=false +package/show_in_app_library=true +package/show_as_launcher_app=false +launcher_icons/main_192x192="res://no_export/android/android_legacy_icon.webp" +launcher_icons/adaptive_foreground_432x432="res://no_export/android/adaptive_foreground.svg" +launcher_icons/adaptive_background_432x432="res://no_export/android/adaptive_background.svg" +launcher_icons/adaptive_monochrome_432x432="res://no_export/android/adaptive_monochrome.svg" +graphics/opengl_debug=false +shader_baker/enabled=false +xr_features/xr_mode=0 +gesture/swipe_to_dismiss=false +screen/immersive_mode=true +screen/edge_to_edge=false +screen/support_small=true +screen/support_normal=true +screen/support_large=true +screen/support_xlarge=true +screen/background_color=Color(0, 0, 0, 1) +splash_screen/disable_godot_boot_splash=true +splash_screen/icon="" +splash_screen/branding_image="" +splash_screen/background_color=Color(0, 0, 0, 1) +user_data_backup/allow=false +command_line/extra_args="" +permissions/custom_permissions=PackedStringArray() +permissions/access_checkin_properties=false +permissions/access_coarse_location=false +permissions/access_fine_location=false +permissions/access_location_extra_commands=false +permissions/access_media_location=false +permissions/access_mock_location=false +permissions/access_network_state=false +permissions/access_surface_flinger=false +permissions/access_wifi_state=false +permissions/account_manager=false +permissions/add_voicemail=false +permissions/authenticate_accounts=false +permissions/battery_stats=false +permissions/bind_accessibility_service=false +permissions/bind_appwidget=false +permissions/bind_device_admin=false +permissions/bind_input_method=false +permissions/bind_nfc_service=false +permissions/bind_notification_listener_service=false +permissions/bind_print_service=false +permissions/bind_remoteviews=false +permissions/bind_text_service=false +permissions/bind_vpn_service=false +permissions/bind_wallpaper=false +permissions/bluetooth=false +permissions/bluetooth_admin=false +permissions/bluetooth_privileged=false +permissions/brick=false +permissions/broadcast_package_removed=false +permissions/broadcast_sms=false +permissions/broadcast_sticky=false +permissions/broadcast_wap_push=false +permissions/call_phone=false +permissions/call_privileged=false +permissions/camera=false +permissions/capture_audio_output=false +permissions/capture_secure_video_output=false +permissions/capture_video_output=false +permissions/change_component_enabled_state=false +permissions/change_configuration=false +permissions/change_network_state=false +permissions/change_wifi_multicast_state=false +permissions/change_wifi_state=false +permissions/clear_app_cache=false +permissions/clear_app_user_data=false +permissions/control_location_updates=false +permissions/delete_cache_files=false +permissions/delete_packages=false +permissions/device_power=false +permissions/diagnostic=false +permissions/disable_keyguard=false +permissions/dump=false +permissions/expand_status_bar=false +permissions/factory_test=false +permissions/flashlight=false +permissions/force_back=false +permissions/get_accounts=false +permissions/get_package_size=false +permissions/get_tasks=false +permissions/get_top_activity_info=false +permissions/global_search=false +permissions/hardware_test=false +permissions/inject_events=false +permissions/install_location_provider=false +permissions/install_packages=false +permissions/install_shortcut=false +permissions/internal_system_window=false +permissions/internet=true +permissions/kill_background_processes=false +permissions/location_hardware=false +permissions/manage_accounts=false +permissions/manage_app_tokens=false +permissions/manage_documents=false +permissions/manage_external_storage=true +permissions/manage_media=false +permissions/master_clear=false +permissions/media_content_control=false +permissions/modify_audio_settings=false +permissions/modify_phone_state=false +permissions/mount_format_filesystems=false +permissions/mount_unmount_filesystems=false +permissions/nfc=false +permissions/persistent_activity=false +permissions/post_notifications=false +permissions/process_outgoing_calls=false +permissions/read_calendar=false +permissions/read_call_log=false +permissions/read_contacts=false +permissions/read_external_storage=false +permissions/read_frame_buffer=false +permissions/read_history_bookmarks=false +permissions/read_input_state=false +permissions/read_logs=false +permissions/read_media_audio=false +permissions/read_media_images=false +permissions/read_media_video=false +permissions/read_media_visual_user_selected=false +permissions/read_phone_state=false +permissions/read_profile=false +permissions/read_sms=false +permissions/read_social_stream=false +permissions/read_sync_settings=false +permissions/read_sync_stats=false +permissions/read_user_dictionary=false +permissions/reboot=false +permissions/receive_boot_completed=false +permissions/receive_mms=false +permissions/receive_sms=false +permissions/receive_wap_push=false +permissions/record_audio=false +permissions/reorder_tasks=false +permissions/restart_packages=false +permissions/send_respond_via_message=false +permissions/send_sms=false +permissions/set_activity_watcher=false +permissions/set_alarm=false +permissions/set_always_finish=false +permissions/set_animation_scale=false +permissions/set_debug_app=false +permissions/set_orientation=false +permissions/set_pointer_speed=false +permissions/set_preferred_applications=false +permissions/set_process_limit=false +permissions/set_time=false +permissions/set_time_zone=false +permissions/set_wallpaper=false +permissions/set_wallpaper_hints=false +permissions/signal_persistent_processes=false +permissions/status_bar=false +permissions/subscribed_feeds_read=false +permissions/subscribed_feeds_write=false +permissions/system_alert_window=false +permissions/transmit_ir=false +permissions/uninstall_shortcut=false +permissions/update_device_stats=false +permissions/use_credentials=false +permissions/use_sip=false +permissions/vibrate=false +permissions/wake_lock=false +permissions/write_apn_settings=false +permissions/write_calendar=false +permissions/write_call_log=false +permissions/write_contacts=false +permissions/write_external_storage=false +permissions/write_gservices=false +permissions/write_history_bookmarks=false +permissions/write_profile=false +permissions/write_secure_settings=false +permissions/write_settings=false +permissions/write_sms=false +permissions/write_social_stream=false +permissions/write_sync_settings=false +permissions/write_user_dictionary=false + +[preset.9] + name="Web" platform="Web" -runnable=true dedicated_server=false custom_features="" export_filter="all_resources" @@ -1118,7 +1349,7 @@ encrypt_pck=false encrypt_directory=false script_export_mode=2 -[preset.8.options] +[preset.9.options] custom_template/debug="" custom_template/release="" @@ -1143,3 +1374,271 @@ progressive_web_app/icon_512x512="" progressive_web_app/background_color=Color(0, 0, 0, 1) threads/emscripten_pool_size=8 threads/godot_pool_size=4 + +[preset.9] + +name="iOS" +platform="iOS" +dedicated_server=false +custom_features="" +export_filter="exclude" +export_files=PackedStringArray("res://addons/gut/cli/change_project_warnings.gd", "res://addons/gut/cli/gut_cli.gd", "res://addons/gut/cli/optparse.gd", "res://addons/gut/fonts/AnonymousPro-Bold.ttf", "res://addons/gut/fonts/AnonymousPro-BoldItalic.ttf", "res://addons/gut/fonts/AnonymousPro-Italic.ttf", "res://addons/gut/fonts/AnonymousPro-Regular.ttf", "res://addons/gut/fonts/CourierPrime-Bold.ttf", "res://addons/gut/fonts/CourierPrime-BoldItalic.ttf", "res://addons/gut/fonts/CourierPrime-Italic.ttf", "res://addons/gut/fonts/CourierPrime-Regular.ttf", "res://addons/gut/fonts/LobsterTwo-Bold.ttf", "res://addons/gut/fonts/LobsterTwo-BoldItalic.ttf", "res://addons/gut/fonts/LobsterTwo-Italic.ttf", "res://addons/gut/fonts/LobsterTwo-Regular.ttf", "res://addons/gut/gui/about.gd", "res://addons/gut/gui/about.tscn", "res://addons/gut/gui/arrow.png", "res://addons/gut/gui/EditorRadioButton.tres", "res://addons/gut/gui/editor_globals.gd", "res://addons/gut/gui/GutBottomPanel.gd", "res://addons/gut/gui/GutBottomPanel.tscn", "res://addons/gut/gui/GutControl.gd", "res://addons/gut/gui/GutControl.tscn", "res://addons/gut/gui/GutEditorWindow.gd", "res://addons/gut/gui/GutEditorWindow.tscn", "res://addons/gut/gui/GutLogo.tscn", "res://addons/gut/gui/GutRunner.gd", "res://addons/gut/gui/GutRunner.tscn", "res://addons/gut/gui/GutSceneTheme.tres", "res://addons/gut/gui/gut_config_gui.gd", "res://addons/gut/gui/gut_gui.gd", "res://addons/gut/gui/gut_logo.gd", "res://addons/gut/gui/gut_user_preferences.gd", "res://addons/gut/gui/MinGui.tscn", "res://addons/gut/gui/NormalGui.tscn", "res://addons/gut/gui/option_maker.gd", "res://addons/gut/gui/OutputText.gd", "res://addons/gut/gui/OutputText.tscn", "res://addons/gut/gui/panel_controls.gd", "res://addons/gut/gui/play.png", "res://addons/gut/gui/ResizeHandle.gd", "res://addons/gut/gui/ResizeHandle.tscn", "res://addons/gut/gui/ResultsTree.gd", "res://addons/gut/gui/ResultsTree.tscn", "res://addons/gut/gui/RunAtCursor.gd", "res://addons/gut/gui/RunAtCursor.tscn", "res://addons/gut/gui/RunExternally.gd", "res://addons/gut/gui/RunExternally.tscn", "res://addons/gut/gui/RunResults.gd", "res://addons/gut/gui/RunResults.tscn", "res://addons/gut/gui/run_from_editor.gd", "res://addons/gut/gui/run_from_editor.tscn", "res://addons/gut/gui/Settings.tscn", "res://addons/gut/gui/ShellOutOptions.gd", "res://addons/gut/gui/ShellOutOptions.tscn", "res://addons/gut/gui/ShortcutButton.gd", "res://addons/gut/gui/ShortcutButton.tscn", "res://addons/gut/gui/ShortcutDialog.gd", "res://addons/gut/gui/ShortcutDialog.tscn", "res://addons/gut/images/eyey.png", "res://addons/gut/images/Folder.svg", "res://addons/gut/images/green.png", "res://addons/gut/images/GutIconV2_base.png", "res://addons/gut/images/GutIconV2_no_shine.png", "res://addons/gut/images/HSplitContainer.svg", "res://addons/gut/images/red.png", "res://addons/gut/images/Script.svg", "res://addons/gut/images/VSplitContainer.svg", "res://addons/gut/images/yellow.png", "res://addons/gut/autofree.gd", "res://addons/gut/awaiter.gd", "res://addons/gut/collected_script.gd", "res://addons/gut/collected_test.gd", "res://addons/gut/comparator.gd", "res://addons/gut/compare_result.gd", "res://addons/gut/diff_formatter.gd", "res://addons/gut/diff_tool.gd", "res://addons/gut/doubler.gd", "res://addons/gut/double_tools.gd", "res://addons/gut/dynamic_gdscript.gd", "res://addons/gut/editor_caret_context_notifier.gd", "res://addons/gut/error_tracker.gd", "res://addons/gut/get_editor_interface.gd", "res://addons/gut/gut.gd", "res://addons/gut/GutScene.gd", "res://addons/gut/GutScene.tscn", "res://addons/gut/gut_cmdln.gd", "res://addons/gut/gut_config.gd", "res://addons/gut/gut_fonts.gd", "res://addons/gut/gut_loader.gd", "res://addons/gut/gut_loader_the_scene.tscn", "res://addons/gut/gut_menu.gd", "res://addons/gut/gut_plugin.gd", "res://addons/gut/gut_to_move.gd", "res://addons/gut/gut_tracked_error.gd", "res://addons/gut/gut_vscode_debugger.gd", "res://addons/gut/hook_script.gd", "res://addons/gut/icon.png", "res://addons/gut/inner_class_registry.gd", "res://addons/gut/input_factory.gd", "res://addons/gut/input_sender.gd", "res://addons/gut/junit_xml_export.gd", "res://addons/gut/lazy_loader.gd", "res://addons/gut/logger.gd", "res://addons/gut/method_maker.gd", "res://addons/gut/one_to_many.gd", "res://addons/gut/orphan_counter.gd", "res://addons/gut/parameter_factory.gd", "res://addons/gut/parameter_handler.gd", "res://addons/gut/printers.gd", "res://addons/gut/result_exporter.gd", "res://addons/gut/script_parser.gd", "res://addons/gut/signal_watcher.gd", "res://addons/gut/source_code_pro.fnt", "res://addons/gut/spy.gd", "res://addons/gut/strutils.gd", "res://addons/gut/stubber.gd", "res://addons/gut/stub_params.gd", "res://addons/gut/summary.gd", "res://addons/gut/test.gd", "res://addons/gut/test_collector.gd", "res://addons/gut/thing_counter.gd", "res://addons/gut/UserFileViewer.gd", "res://addons/gut/UserFileViewer.tscn", "res://addons/gut/utils.gd", "res://addons/gut/version_conversion.gd", "res://addons/gut/version_numbers.gd", "res://addons/gut/warnings_manager.gd", "res://demo/demo.tscn", "res://demo/object.tscn") +include_filter="*.tmpl" +exclude_filter="*.ptex,*.mmn,*.mmg" +export_path="" +patches=PackedStringArray() +patch_delta_encoding=false +patch_delta_compression_level_zstd=19 +patch_delta_min_reduction=0.1 +patch_delta_include_filters="*" +patch_delta_exclude_filters="" +encryption_include_filters="" +encryption_exclude_filters="" +seed=0 +encrypt_pck=false +encrypt_directory=false +script_export_mode=2 + +[preset.9.options] + +custom_template/debug="" +custom_template/release="" +architectures/arm64=true +application/app_store_team_id="" +application/export_method_debug=1 +application/code_sign_identity_debug="" +application/code_sign_identity_release="" +application/provisioning_profile_specifier_debug="" +application/provisioning_profile_specifier_release="" +application/export_method_release=0 +application/bundle_identifier="com.rodzill4.materialmaker" +application/signature="" +application/short_version="" +application/version="" +application/additional_plist_content="" +application/icon_interpolation=4 +application/export_project_only=false +application/delete_old_export_files_unconditionally=false +modules/camera=false +entitlements/increased_memory_limit=false +entitlements/game_center=false +entitlements/push_notifications="Disabled" +entitlements/additional="" +capabilities/access_wifi=true +capabilities/performance_gaming_tier=false +capabilities/performance_a12=false +capabilities/additional=PackedStringArray() +shader_baker/enabled=false +user_data/accessible_from_files_app=true +user_data/accessible_from_itunes_sharing=true +privacy/camera_usage_description="" +privacy/camera_usage_description_localized={} +privacy/microphone_usage_description="" +privacy/microphone_usage_description_localized={} +privacy/photolibrary_usage_description="" +privacy/photolibrary_usage_description_localized={} +privacy/file_timestamp_access_reasons=3 +privacy/system_boot_time_access_reasons=1 +privacy/disk_space_access_reasons=3 +privacy/active_keyboard_access_reasons=0 +privacy/user_defaults_access_reasons=0 +privacy/tracking_enabled=false +privacy/tracking_domains=PackedStringArray() +privacy/collected_data/name/collected=false +privacy/collected_data/name/linked_to_user=false +privacy/collected_data/name/used_for_tracking=false +privacy/collected_data/name/collection_purposes=0 +privacy/collected_data/email_address/collected=false +privacy/collected_data/email_address/linked_to_user=false +privacy/collected_data/email_address/used_for_tracking=false +privacy/collected_data/email_address/collection_purposes=0 +privacy/collected_data/phone_number/collected=false +privacy/collected_data/phone_number/linked_to_user=false +privacy/collected_data/phone_number/used_for_tracking=false +privacy/collected_data/phone_number/collection_purposes=0 +privacy/collected_data/physical_address/collected=false +privacy/collected_data/physical_address/linked_to_user=false +privacy/collected_data/physical_address/used_for_tracking=false +privacy/collected_data/physical_address/collection_purposes=0 +privacy/collected_data/other_contact_info/collected=false +privacy/collected_data/other_contact_info/linked_to_user=false +privacy/collected_data/other_contact_info/used_for_tracking=false +privacy/collected_data/other_contact_info/collection_purposes=0 +privacy/collected_data/health/collected=false +privacy/collected_data/health/linked_to_user=false +privacy/collected_data/health/used_for_tracking=false +privacy/collected_data/health/collection_purposes=0 +privacy/collected_data/fitness/collected=false +privacy/collected_data/fitness/linked_to_user=false +privacy/collected_data/fitness/used_for_tracking=false +privacy/collected_data/fitness/collection_purposes=0 +privacy/collected_data/payment_info/collected=false +privacy/collected_data/payment_info/linked_to_user=false +privacy/collected_data/payment_info/used_for_tracking=false +privacy/collected_data/payment_info/collection_purposes=0 +privacy/collected_data/credit_info/collected=false +privacy/collected_data/credit_info/linked_to_user=false +privacy/collected_data/credit_info/used_for_tracking=false +privacy/collected_data/credit_info/collection_purposes=0 +privacy/collected_data/other_financial_info/collected=false +privacy/collected_data/other_financial_info/linked_to_user=false +privacy/collected_data/other_financial_info/used_for_tracking=false +privacy/collected_data/other_financial_info/collection_purposes=0 +privacy/collected_data/precise_location/collected=false +privacy/collected_data/precise_location/linked_to_user=false +privacy/collected_data/precise_location/used_for_tracking=false +privacy/collected_data/precise_location/collection_purposes=0 +privacy/collected_data/coarse_location/collected=false +privacy/collected_data/coarse_location/linked_to_user=false +privacy/collected_data/coarse_location/used_for_tracking=false +privacy/collected_data/coarse_location/collection_purposes=0 +privacy/collected_data/sensitive_info/collected=false +privacy/collected_data/sensitive_info/linked_to_user=false +privacy/collected_data/sensitive_info/used_for_tracking=false +privacy/collected_data/sensitive_info/collection_purposes=0 +privacy/collected_data/contacts/collected=false +privacy/collected_data/contacts/linked_to_user=false +privacy/collected_data/contacts/used_for_tracking=false +privacy/collected_data/contacts/collection_purposes=0 +privacy/collected_data/emails_or_text_messages/collected=false +privacy/collected_data/emails_or_text_messages/linked_to_user=false +privacy/collected_data/emails_or_text_messages/used_for_tracking=false +privacy/collected_data/emails_or_text_messages/collection_purposes=0 +privacy/collected_data/photos_or_videos/collected=false +privacy/collected_data/photos_or_videos/linked_to_user=false +privacy/collected_data/photos_or_videos/used_for_tracking=false +privacy/collected_data/photos_or_videos/collection_purposes=0 +privacy/collected_data/audio_data/collected=false +privacy/collected_data/audio_data/linked_to_user=false +privacy/collected_data/audio_data/used_for_tracking=false +privacy/collected_data/audio_data/collection_purposes=0 +privacy/collected_data/gameplay_content/collected=false +privacy/collected_data/gameplay_content/linked_to_user=false +privacy/collected_data/gameplay_content/used_for_tracking=false +privacy/collected_data/gameplay_content/collection_purposes=0 +privacy/collected_data/customer_support/collected=false +privacy/collected_data/customer_support/linked_to_user=false +privacy/collected_data/customer_support/used_for_tracking=false +privacy/collected_data/customer_support/collection_purposes=0 +privacy/collected_data/other_user_content/collected=false +privacy/collected_data/other_user_content/linked_to_user=false +privacy/collected_data/other_user_content/used_for_tracking=false +privacy/collected_data/other_user_content/collection_purposes=0 +privacy/collected_data/browsing_history/collected=false +privacy/collected_data/browsing_history/linked_to_user=false +privacy/collected_data/browsing_history/used_for_tracking=false +privacy/collected_data/browsing_history/collection_purposes=0 +privacy/collected_data/search_history/collected=false +privacy/collected_data/search_history/linked_to_user=false +privacy/collected_data/search_history/used_for_tracking=false +privacy/collected_data/search_history/collection_purposes=0 +privacy/collected_data/user_id/collected=false +privacy/collected_data/user_id/linked_to_user=false +privacy/collected_data/user_id/used_for_tracking=false +privacy/collected_data/user_id/collection_purposes=0 +privacy/collected_data/device_id/collected=false +privacy/collected_data/device_id/linked_to_user=false +privacy/collected_data/device_id/used_for_tracking=false +privacy/collected_data/device_id/collection_purposes=0 +privacy/collected_data/purchase_history/collected=false +privacy/collected_data/purchase_history/linked_to_user=false +privacy/collected_data/purchase_history/used_for_tracking=false +privacy/collected_data/purchase_history/collection_purposes=0 +privacy/collected_data/product_interaction/collected=false +privacy/collected_data/product_interaction/linked_to_user=false +privacy/collected_data/product_interaction/used_for_tracking=false +privacy/collected_data/product_interaction/collection_purposes=0 +privacy/collected_data/advertising_data/collected=false +privacy/collected_data/advertising_data/linked_to_user=false +privacy/collected_data/advertising_data/used_for_tracking=false +privacy/collected_data/advertising_data/collection_purposes=0 +privacy/collected_data/other_usage_data/collected=false +privacy/collected_data/other_usage_data/linked_to_user=false +privacy/collected_data/other_usage_data/used_for_tracking=false +privacy/collected_data/other_usage_data/collection_purposes=0 +privacy/collected_data/crash_data/collected=false +privacy/collected_data/crash_data/linked_to_user=false +privacy/collected_data/crash_data/used_for_tracking=false +privacy/collected_data/crash_data/collection_purposes=0 +privacy/collected_data/performance_data/collected=false +privacy/collected_data/performance_data/linked_to_user=false +privacy/collected_data/performance_data/used_for_tracking=false +privacy/collected_data/performance_data/collection_purposes=0 +privacy/collected_data/other_diagnostic_data/collected=false +privacy/collected_data/other_diagnostic_data/linked_to_user=false +privacy/collected_data/other_diagnostic_data/used_for_tracking=false +privacy/collected_data/other_diagnostic_data/collection_purposes=0 +privacy/collected_data/environment_scanning/collected=false +privacy/collected_data/environment_scanning/linked_to_user=false +privacy/collected_data/environment_scanning/used_for_tracking=false +privacy/collected_data/environment_scanning/collection_purposes=0 +privacy/collected_data/hands/collected=false +privacy/collected_data/hands/linked_to_user=false +privacy/collected_data/hands/used_for_tracking=false +privacy/collected_data/hands/collection_purposes=0 +privacy/collected_data/head/collected=false +privacy/collected_data/head/linked_to_user=false +privacy/collected_data/head/used_for_tracking=false +privacy/collected_data/head/collection_purposes=0 +privacy/collected_data/other_data_types/collected=false +privacy/collected_data/other_data_types/linked_to_user=false +privacy/collected_data/other_data_types/used_for_tracking=false +privacy/collected_data/other_data_types/collection_purposes=0 +icons/icon_1024x1024="" +icons/icon_1024x1024_dark="" +icons/icon_1024x1024_tinted="" +icons/settings_58x58="" +icons/settings_58x58_dark="" +icons/settings_58x58_tinted="" +icons/settings_87x87="" +icons/settings_87x87_dark="" +icons/settings_87x87_tinted="" +icons/notification_40x40="" +icons/notification_40x40_dark="" +icons/notification_40x40_tinted="" +icons/notification_60x60="" +icons/notification_60x60_dark="" +icons/notification_60x60_tinted="" +icons/notification_76x76="" +icons/notification_76x76_dark="" +icons/notification_76x76_tinted="" +icons/notification_114x114="" +icons/notification_114x114_dark="" +icons/notification_114x114_tinted="" +icons/spotlight_80x80="" +icons/spotlight_80x80_dark="" +icons/spotlight_80x80_tinted="" +icons/spotlight_120x120="" +icons/spotlight_120x120_dark="" +icons/spotlight_120x120_tinted="" +icons/iphone_120x120="" +icons/iphone_120x120_dark="" +icons/iphone_120x120_tinted="" +icons/iphone_180x180="" +icons/iphone_180x180_dark="" +icons/iphone_180x180_tinted="" +icons/ipad_167x167="" +icons/ipad_167x167_dark="" +icons/ipad_167x167_tinted="" +icons/ipad_152x152="" +icons/ipad_152x152_dark="" +icons/ipad_152x152_tinted="" +icons/ios_128x128="" +icons/ios_128x128_dark="" +icons/ios_128x128_tinted="" +icons/ios_192x192="" +icons/ios_192x192_dark="" +icons/ios_192x192_tinted="" +icons/ios_136x136="" +icons/ios_136x136_dark="" +icons/ios_136x136_tinted="" +icons/app_store_1024x1024="" +icons/app_store_1024x1024_dark="" +icons/app_store_1024x1024_tinted="" +application/targeted_device_family=1 +application/min_ios_version="14.0" +storyboard/image_scale_mode=0 +storyboard/custom_image@2x="" +storyboard/custom_image@3x="" +storyboard/use_custom_bg_color=false +storyboard/custom_bg_color=Color(0, 0, 0, 1) diff --git a/material_maker/darken.gd.uid b/material_maker/darken.gd.uid index deb559d6f0..30e8d28d6b 100644 --- a/material_maker/darken.gd.uid +++ b/material_maker/darken.gd.uid @@ -1 +1 @@ -uid://du7vv67kc65qb +uid://dydhg5xaf7bjm diff --git a/material_maker/darken.tscn b/material_maker/darken.tscn deleted file mode 100644 index 3e59f8ab13..0000000000 --- a/material_maker/darken.tscn +++ /dev/null @@ -1,10 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://cmeh4ewlvp7vx"] - -[ext_resource type="Script" path="res://material_maker/darken.gd" id="1"] - -[node name="Darken" type="ColorRect"] -anchor_right = 1.0 -anchor_bottom = 1.0 -script = ExtResource("1") - -[connection signal="resized" from="." to="." method="_on_resized"] diff --git a/material_maker/doc/user_interface.rst b/material_maker/doc/user_interface.rst index 38f1217381..002024ed54 100644 --- a/material_maker/doc/user_interface.rst +++ b/material_maker/doc/user_interface.rst @@ -6,6 +6,7 @@ User interface user_interface_overview user_interface_shortcuts + user_interface_gestures user_interface_first_steps user_interface_main_menu user_interface_panels diff --git a/material_maker/doc/user_interface_gestures.rst b/material_maker/doc/user_interface_gestures.rst new file mode 100644 index 0000000000..4030a1c322 --- /dev/null +++ b/material_maker/doc/user_interface_gestures.rst @@ -0,0 +1,81 @@ +Touch Gestures +~~~~~~~~~~~~~~ + +While not an exhuaustive list, this shows the most +common touch gestures available in Material Maker for Android. + +In general, most desktop inputs can be mapped to +touch inputs in the following manner: + +**Tap**: Left Click, **Double-Tap**: Left Double Click, **Long-Press**: Right Click + +Add Node Popup +++++++++++++++ ++-------------------------------------------------------+----------------------------------------------------+ +| One-Finger Drag | Scroll | ++-------------------------------------------------------+----------------------------------------------------+ +| One-Finger Drag | Drag item from list (at icon) | ++-------------------------------------------------------+----------------------------------------------------+ + + +Graph Editor +++++++++++++ ++-------------------------------------------------------+----------------------------------------------------+ +| Two-Finger drag | Pan | ++-------------------------------------------------------+----------------------------------------------------+ +| Two-Finger Pinch | Double-Tap + Drag | Zoom in/out | ++-------------------------------------------------------+----------------------------------------------------+ +| Long Tap | Add node menu | ++-------------------------------------------------------+----------------------------------------------------+ +| One-Finger Drag | Box selection | ++-------------------------------------------------------+----------------------------------------------------+ +| Double Tap | Enters subgraph/nodegroup, or exit/go up a level | +| | in subgraph hierarchy when double-tapping in an | +| | empty area. | ++-------------------------------------------------------+----------------------------------------------------+ +| Two-Finger Tap | Undo | ++-------------------------------------------------------+----------------------------------------------------+ +| Three-Finger Tap | Redo | ++-------------------------------------------------------+----------------------------------------------------+ + +Nodes ++++++ ++-------------------------------------------------------+----------------------------------------------------+ +| Long Tap | Open expression editor (float parameter) | ++-------------------------------------------------------+----------------------------------------------------+ + +Reference ++++++++++ ++-------------------------------------------------------+----------------------------------------------------+ +| Two-Finger drag | Pan | ++-------------------------------------------------------+----------------------------------------------------+ +| Two-Finger Pinch | Double-Tap + Drag | Zoom in/out | ++-------------------------------------------------------+----------------------------------------------------+ + +Preview 2D +++++++++++ ++-------------------------------------------------------+----------------------------------------------------+ +| One-Finger Drag | Pan | ++-------------------------------------------------------+----------------------------------------------------+ +| Two-Finger Pinch | Double-Tap + Drag | Zoom in/out | ++-------------------------------------------------------+----------------------------------------------------+ +| Two-Finger Tap | Reset view | ++-------------------------------------------------------+----------------------------------------------------+ + +Preview 3D +++++++++++ ++-------------------------------------------------------+----------------------------------------------------+ +| One-Finger Drag | Orbit | ++-------------------------------------------------------+----------------------------------------------------+ +| Two-Finger Pinch | Double-Tap + Drag | Zoom in/out | ++-------------------------------------------------------+----------------------------------------------------+ + +Library ++++++++ ++-------------------------------------------------------+----------------------------------------------------+ +| One-Finger Drag | Two-Finger Drag | Scroll / Fast Scroll | ++-------------------------------------------------------+----------------------------------------------------+ +| One-Finger Drag | Drag item from libary panel (at icon) | ++-------------------------------------------------------+----------------------------------------------------+ +| Two-Finger Pinch | Double-Tap + Drag | Zoom in/out | ++-------------------------------------------------------+----------------------------------------------------+ diff --git a/material_maker/environments/environments.json b/material_maker/environments/environments.json index 26750029d0..ba422d7250 100644 --- a/material_maker/environments/environments.json +++ b/material_maker/environments/environments.json @@ -1 +1 @@ -[{"name":"Epping Forest","hdri_url":"https://hdrihaven.com/files/hdris/epping_forest_01_1k.hdr","show_color":false,"color":{"type":"Color","r":0,"g":0,"b":0,"a":1},"sky_energy":1,"ambient_light_color":{"type":"Color","r":1,"g":1,"b":1,"a":1},"ambient_light_energy":0.5,"ambient_light_sky_contribution":0.7,"sun_color":{"type":"Color","r":1,"g":1,"b":1,"a":1},"sun_energy":0,"sun_direction":0,"sun_angle":7.9,"thumbnail":"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"},{"name":"Moonless Golf","hdri_url":"https://hdrihaven.com/files/hdris/moonless_golf_1k.hdr","show_color":false,"color":{"type":"Color","r":0,"g":0,"b":0,"a":1},"sky_energy":1,"ambient_light_color":{"type":"Color","r":0,"g":0,"b":0,"a":1},"ambient_light_energy":1,"ambient_light_sky_contribution":1,"sun_color":{"type":"Color","r":1,"g":0.984375,"b":0,"a":1},"sun_energy":0.5,"sun_direction":130,"sun_angle":10,"thumbnail":"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"},{"name":"Studio","hdri_url":"https://hdrihaven.com/files/hdris/photo_studio_01_1k.hdr","show_color":true,"color":{"type":"Color","r":0.671875,"g":0.671875,"b":0.671875,"a":1},"sky_energy":1,"ambient_light_color":{"type":"Color","r":1,"g":1,"b":1,"a":1},"ambient_light_energy":0.2,"ambient_light_sky_contribution":0.2,"sun_color":{"type":"Color","r":1,"g":1,"b":1,"a":1},"sun_energy":1,"sun_direction":0,"sun_angle":90,"thumbnail":"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"}] +[{"name":"Epping Forest","hdri_url":"https://hdrihaven.com/files/hdris/epping_forest_01_1k.exr","show_color":false,"color":{"type":"Color","r":0,"g":0,"b":0,"a":1},"sky_energy":1,"ambient_light_color":{"type":"Color","r":1,"g":1,"b":1,"a":1},"ambient_light_energy":0.5,"ambient_light_sky_contribution":0.7,"sun_color":{"type":"Color","r":1,"g":1,"b":1,"a":1},"sun_energy":0,"sun_direction":0,"sun_angle":7.9,"thumbnail":"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"},{"name":"Moonless Golf","hdri_url":"https://hdrihaven.com/files/hdris/moonless_golf_1k.exr","show_color":false,"color":{"type":"Color","r":0,"g":0,"b":0,"a":1},"sky_energy":1,"ambient_light_color":{"type":"Color","r":0,"g":0,"b":0,"a":1},"ambient_light_energy":1,"ambient_light_sky_contribution":1,"sun_color":{"type":"Color","r":1,"g":0.984375,"b":0,"a":1},"sun_energy":0.5,"sun_direction":130,"sun_angle":10,"thumbnail":"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"},{"name":"Studio","hdri_url":"https://hdrihaven.com/files/hdris/photo_studio_01_1k.exr","show_color":true,"color":{"type":"Color","r":0.671875,"g":0.671875,"b":0.671875,"a":1},"sky_energy":1,"ambient_light_color":{"type":"Color","r":1,"g":1,"b":1,"a":1},"ambient_light_energy":0.2,"ambient_light_sky_contribution":0.2,"sun_color":{"type":"Color","r":1,"g":1,"b":1,"a":1},"sun_energy":1,"sun_direction":0,"sun_angle":90,"thumbnail":"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"}] diff --git a/material_maker/environments/hdris/epping_forest_01_1k.exr b/material_maker/environments/hdris/epping_forest_01_1k.exr new file mode 100644 index 0000000000..5a25b66a6e Binary files /dev/null and b/material_maker/environments/hdris/epping_forest_01_1k.exr differ diff --git a/material_maker/environments/hdris/epping_forest_01_1k.hdr.import b/material_maker/environments/hdris/epping_forest_01_1k.exr.import similarity index 58% rename from material_maker/environments/hdris/epping_forest_01_1k.hdr.import rename to material_maker/environments/hdris/epping_forest_01_1k.exr.import index b9c8621ebc..17165dad6c 100644 --- a/material_maker/environments/hdris/epping_forest_01_1k.hdr.import +++ b/material_maker/environments/hdris/epping_forest_01_1k.exr.import @@ -3,19 +3,21 @@ importer="texture" type="CompressedTexture2D" uid="uid://by6042vpo6i1o" -path="res://.godot/imported/epping_forest_01_1k.hdr-deb5d85b1c0b655387fa44d4d061848a.ctex" +path.bptc="res://.godot/imported/epping_forest_01_1k.exr-dd265e3a1064f51c25b4469230bf58cd.bptc.ctex" +path.astc="res://.godot/imported/epping_forest_01_1k.exr-dd265e3a1064f51c25b4469230bf58cd.astc.ctex" metadata={ -"vram_texture": false +"imported_formats": ["s3tc_bptc", "etc2_astc"], +"vram_texture": true } [deps] -source_file="res://material_maker/environments/hdris/epping_forest_01_1k.hdr" -dest_files=["res://.godot/imported/epping_forest_01_1k.hdr-deb5d85b1c0b655387fa44d4d061848a.ctex"] +source_file="res://material_maker/environments/hdris/epping_forest_01_1k.exr" +dest_files=["res://.godot/imported/epping_forest_01_1k.exr-dd265e3a1064f51c25b4469230bf58cd.bptc.ctex", "res://.godot/imported/epping_forest_01_1k.exr-dd265e3a1064f51c25b4469230bf58cd.astc.ctex"] [params] -compress/mode=0 +compress/mode=2 compress/high_quality=false compress/lossy_quality=0.7 compress/uastc_level=0 @@ -23,7 +25,7 @@ compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 -mipmaps/generate=false +mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" diff --git a/material_maker/environments/hdris/epping_forest_01_1k.hdr b/material_maker/environments/hdris/epping_forest_01_1k.hdr deleted file mode 100644 index 0307bffbb6..0000000000 Binary files a/material_maker/environments/hdris/epping_forest_01_1k.hdr and /dev/null differ diff --git a/material_maker/environments/hdris/moonless_golf_1k.exr b/material_maker/environments/hdris/moonless_golf_1k.exr new file mode 100644 index 0000000000..f9733fe607 Binary files /dev/null and b/material_maker/environments/hdris/moonless_golf_1k.exr differ diff --git a/material_maker/environments/hdris/moonless_golf_1k.hdr.import b/material_maker/environments/hdris/moonless_golf_1k.exr.import similarity index 67% rename from material_maker/environments/hdris/moonless_golf_1k.hdr.import rename to material_maker/environments/hdris/moonless_golf_1k.exr.import index ec7781b3a9..db085950f2 100644 --- a/material_maker/environments/hdris/moonless_golf_1k.hdr.import +++ b/material_maker/environments/hdris/moonless_golf_1k.exr.import @@ -3,8 +3,8 @@ importer="texture" type="CompressedTexture2D" uid="uid://bqre7xkdgb655" -path.bptc="res://.godot/imported/moonless_golf_1k.hdr-9cc5420e458979fa0268bbd265e3a765.bptc.ctex" -path.astc="res://.godot/imported/moonless_golf_1k.hdr-9cc5420e458979fa0268bbd265e3a765.astc.ctex" +path.bptc="res://.godot/imported/moonless_golf_1k.exr-dc79b74455e0bb044175d039bc8ecb2e.bptc.ctex" +path.astc="res://.godot/imported/moonless_golf_1k.exr-dc79b74455e0bb044175d039bc8ecb2e.astc.ctex" metadata={ "imported_formats": ["s3tc_bptc", "etc2_astc"], "vram_texture": true @@ -12,8 +12,8 @@ metadata={ [deps] -source_file="res://material_maker/environments/hdris/moonless_golf_1k.hdr" -dest_files=["res://.godot/imported/moonless_golf_1k.hdr-9cc5420e458979fa0268bbd265e3a765.bptc.ctex", "res://.godot/imported/moonless_golf_1k.hdr-9cc5420e458979fa0268bbd265e3a765.astc.ctex"] +source_file="res://material_maker/environments/hdris/moonless_golf_1k.exr" +dest_files=["res://.godot/imported/moonless_golf_1k.exr-dc79b74455e0bb044175d039bc8ecb2e.bptc.ctex", "res://.godot/imported/moonless_golf_1k.exr-dc79b74455e0bb044175d039bc8ecb2e.astc.ctex"] [params] diff --git a/material_maker/environments/hdris/moonless_golf_1k.hdr b/material_maker/environments/hdris/moonless_golf_1k.hdr deleted file mode 100644 index cc60dc8624..0000000000 Binary files a/material_maker/environments/hdris/moonless_golf_1k.hdr and /dev/null differ diff --git a/material_maker/environments/hdris/photo_studio_01_1k.exr b/material_maker/environments/hdris/photo_studio_01_1k.exr new file mode 100644 index 0000000000..5fdde59957 Binary files /dev/null and b/material_maker/environments/hdris/photo_studio_01_1k.exr differ diff --git a/material_maker/environments/hdris/photo_studio_01_1k.hdr.import b/material_maker/environments/hdris/photo_studio_01_1k.exr.import similarity index 60% rename from material_maker/environments/hdris/photo_studio_01_1k.hdr.import rename to material_maker/environments/hdris/photo_studio_01_1k.exr.import index 315f5fd614..bd5e8af18d 100644 --- a/material_maker/environments/hdris/photo_studio_01_1k.hdr.import +++ b/material_maker/environments/hdris/photo_studio_01_1k.exr.import @@ -3,19 +3,21 @@ importer="texture" type="CompressedTexture2D" uid="uid://ceqyb6morrwwp" -path="res://.godot/imported/photo_studio_01_1k.hdr-67066106c81aadd61efb3176d5af71b1.ctex" +path.bptc="res://.godot/imported/photo_studio_01_1k.exr-8c8b30710711710f3cfa9bec036e54ec.bptc.ctex" +path.astc="res://.godot/imported/photo_studio_01_1k.exr-8c8b30710711710f3cfa9bec036e54ec.astc.ctex" metadata={ -"vram_texture": false +"imported_formats": ["s3tc_bptc", "etc2_astc"], +"vram_texture": true } [deps] -source_file="res://material_maker/environments/hdris/photo_studio_01_1k.hdr" -dest_files=["res://.godot/imported/photo_studio_01_1k.hdr-67066106c81aadd61efb3176d5af71b1.ctex"] +source_file="res://material_maker/environments/hdris/photo_studio_01_1k.exr" +dest_files=["res://.godot/imported/photo_studio_01_1k.exr-8c8b30710711710f3cfa9bec036e54ec.bptc.ctex", "res://.godot/imported/photo_studio_01_1k.exr-8c8b30710711710f3cfa9bec036e54ec.astc.ctex"] [params] -compress/mode=0 +compress/mode=2 compress/high_quality=false compress/lossy_quality=0.7 compress/uastc_level=0 diff --git a/material_maker/environments/hdris/photo_studio_01_1k.hdr b/material_maker/environments/hdris/photo_studio_01_1k.hdr deleted file mode 100644 index 043cc54f95..0000000000 Binary files a/material_maker/environments/hdris/photo_studio_01_1k.hdr and /dev/null differ diff --git a/material_maker/examples/.gdignore b/material_maker/examples/.gdignore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/material_maker/examples/mm_icon.png.import b/material_maker/examples/mm_icon.png.import new file mode 100644 index 0000000000..8dd0c09d14 --- /dev/null +++ b/material_maker/examples/mm_icon.png.import @@ -0,0 +1,3 @@ +[remap] + +importer="keep" diff --git a/material_maker/globals.gd b/material_maker/globals.gd index be003b1229..ba2444b805 100644 --- a/material_maker/globals.gd +++ b/material_maker/globals.gd @@ -3,7 +3,15 @@ extends Node @onready var menu_manager = $MenuManager -var main_window +var main_window : MainWindow + +@warning_ignore("unused_signal") +signal preferences_updated + + +const DEFAULT_DARK : int = 0 +const DEFAULT_LIGHT : int = 1 +const CLASSIC : int = 2 var config : ConfigFile = ConfigFile.new() const DEFAULT_CONFIG : Dictionary = { @@ -70,17 +78,33 @@ const DEFAULT_CONFIG : Dictionary = { custom_theme_contrast = 0.8, ui_3d_preview_generated_mesh = true, nearest_filter_reference = false, + keep_screen_on = true, + touch_node_actions = false, + touch_optimization = false, + touch_full_screen = false, sub_node_items = [], } +const ANDROID_CONFIG : Dictionary[String, Variant] = { + node_minimize_button = false, + node_close_button = false, + touch_node_actions = true, + touch_optimization = true, + touch_full_screen = true, + ui_3d_preview_generated_mesh = false, +} -func _enter_tree(): +func _enter_tree() -> void: config.load("user://mm_config.ini") for k : String in DEFAULT_CONFIG.keys(): - if ! config.has_section_key("config", k): + if not config.has_section_key("config", k): config.set_value("config", k, DEFAULT_CONFIG[k]) -func _exit_tree(): + # android-specific defaults + if OS.get_name() == "Android" and k in ANDROID_CONFIG: + config.set_value("config", k, ANDROID_CONFIG[k]) + +func _exit_tree() -> void: config.save("user://mm_config.ini") # Config @@ -194,7 +218,7 @@ func popup_menu(menu : PopupMenu, parent : Control): var content_scale_factor : float = mm_globals.ui_scale_factor() menu.popup(Rect2(parent.get_local_mouse_position()*content_scale_factor*zoom_fac + parent.get_screen_position(), Vector2(0, 0))) -func set_tip_text(tip : String, timeout : float = 0.0, priority: int = 0): +func set_tip_text(tip : String, timeout : float = 0.0, priority: int = 0) -> void: if main_window: main_window.set_tip_text(TranslationServer.translate(tip), timeout, priority) else: @@ -226,7 +250,13 @@ func propagate_shortcuts(control : Control, event : InputEvent): do_propagate_shortcuts(control, event) func get_home_directory() -> String: - return OS.get_environment("USERPROFILE" if OS.has_feature("windows") else "HOME") + match OS.get_name(): + "Windows": + return OS.get_environment("USERPROFILE") + "Android": + return "/storage/emulated/%s" % [ mm_globals.android_get_user_uid() ] + _: + return OS.get_environment("HOME") func get_node_title_from_gen(generator : MMGenBase) -> String: # Get GraphNode title from generator (in current graph) @@ -246,3 +276,68 @@ func ui_scale_factor() -> float: func is_custom_theme() -> bool: return config.get_value("window", "theme") == "custom" + +func get_ui_scale() -> float: + var ui_scale = mm_globals.get_config("ui_scale") + if ui_scale <= 0: + # If scale is set to 0 (auto), scale everything if the display requires it (crude hiDPI support). + # This prevents UI elements from being too small on hiDPI displays. + return 2 if DisplayServer.screen_get_dpi() >= 192 and DisplayServer.screen_get_size().x >= 2048 else 1 + return ui_scale + +## Returns current theme based on Main Window's theme resource path. +func current_theme() -> int: + var t : String = main_window.theme.resource_path.get_file() + match t.trim_suffix(".tres").to_lower(): + "default dark": + return DEFAULT_DARK + "default light": + return DEFAULT_LIGHT + "classic": + return CLASSIC + _: + return DEFAULT_DARK + +#region android utilties + +## Creates a toast message. +## [param duration] set to 0 displays the message for a short period of time. +func android_make_toast(message : String, duration : int = 1) -> void: + if mm_touch.android_runtime: + var activity : JavaObject = mm_touch.android_runtime.getActivity() + var toastCallable = func() -> void: + var ToastClass : JavaClass = JavaClassWrapper.wrap("android.widget.Toast") + ToastClass.makeText(activity, message, duration).show() + + activity.runOnUiThread(mm_touch.android_runtime.createRunnableFromGodotCallable(toastCallable)) + else: + printerr("Unable to access android runtime") + +## Returns the current user's uid (i.e. the '0' in /storage/emulated/0). +func android_get_user_uid() -> int: + if mm_touch.android_runtime: + var processClass : JavaClass = JavaClassWrapper.wrap("android.os.Process") + var userHandle : JavaClass = JavaClassWrapper.wrap("android.os.UserHandle") + return userHandle.getUserId(processClass.myUid()) + else: + printerr("Unable to access android runtime") + return -1 + +func android_move_task_to_back() -> void: + if mm_touch.android_runtime: + mm_touch.android_runtime.getActivity().moveTaskToBack(true) + +func android_open_url(url : String) -> void: + # can't open url directly via shell_open + var b : Button = Button.new() + add_child(b) + b.pressed.connect(OS.shell_open.call_deferred.bind(url)) + b.pressed.connect(b.queue_free) + b.modulate.a = 0 + b.pressed.emit() + +func should_dim_fullscreen(window : Window) -> bool: + const dim : String = "android_fullscreen_dim" + return OS.get_name() == "Android" and window.has_meta(dim) and window.get_meta(dim) + +#endregion diff --git a/material_maker/globals_menu_manager.gd b/material_maker/globals_menu_manager.gd index af5f2f335b..5dd8bbc460 100644 --- a/material_maker/globals_menu_manager.gd +++ b/material_maker/globals_menu_manager.gd @@ -253,7 +253,10 @@ func create_menu(menu_def : Array, object : Object, menu_name : String, menu : M if s == "Alt": shortcut |= KEY_MASK_ALT elif s == "Control": - shortcut |= KEY_MASK_CTRL + if OS.get_name() == "iOS": + shortcut |= KEY_MASK_META + else: + shortcut |= KEY_MASK_CTRL elif s == "Shift": shortcut |= KEY_MASK_SHIFT else: diff --git a/material_maker/main_window.gd b/material_maker/main_window.gd index 406d12a4f3..5e6c0b6952 100644 --- a/material_maker/main_window.gd +++ b/material_maker/main_window.gd @@ -1,4 +1,4 @@ - +class_name MainWindow extends Control var quitting : bool = false @@ -24,10 +24,11 @@ var preview_tesselation_detail : int = 256 @onready var node_library_manager = $NodeLibraryManager @onready var brush_library_manager = $BrushLibraryManager +@onready var tip_label : RichTextLabel = %Tip -@onready var projects_panel = $VBoxContainer/Layout/FlexibleLayout/Main +@onready var projects_panel = %Main -@onready var layout = $VBoxContainer/Layout +@onready var layout = %Layout var library var preview_2d : Array var histogram @@ -67,7 +68,7 @@ const MENU : Array[Dictionary] = [ { menu="File/Export material", submenu="export_material", not_in_ports=["HTML5"] }, { menu="File/-" }, { menu="File/Close", command="close_project", shortcut="Control+Shift+Q" }, - { menu="File/Quit", command="quit", shortcut="Control+Q", not_in_ports=["HTML5"] }, + { menu="File/Quit", command="quit", shortcut="Control+Q", not_in_ports=["HTML5", "iOS"] }, { menu="Edit/Undo", command="edit_undo", shortcut="Control+Z" }, { menu="Edit/Redo", command="edit_redo", shortcut="Control+Shift+Z" }, @@ -131,8 +132,17 @@ enum WinTabletDriver { WININK, WINTAB, DISABLED } func _enter_tree() -> void: mm_globals.main_window = self + if OS.get_name() == "Android": + ready.connect(android_setup_margins) + mm_globals.preferences_updated.connect(android_setup_margins) + + if mm_globals.get_config("touch_optimization"): + android_setup_status_bar() func _ready() -> void: + if OS.get_name() == "iOS": + DirAccess.make_dir_absolute("user://Documents") + get_window().borderless = false get_window().transparent = false get_window().grab_focus() @@ -144,26 +154,28 @@ func _ready() -> void: if mm_globals.get_config("locale") == "": mm_globals.set_config("locale", TranslationServer.get_locale()) + mm_globals.preferences_updated.connect(on_config_changed) on_config_changed() - # Set a minimum window size to prevent UI elements from collapsing on each other. - get_window().min_size = Vector2(1024, 600) + if OS.get_name() != "Android": + # Set a minimum window size to prevent UI elements from collapsing on each other. + get_window().min_size = Vector2(1024, 600) - # Restore the window position/size if values are present in the configuration cache - if mm_globals.config.has_section_key("window", "screen"): - get_window().current_screen = mm_globals.config.get_value("window", "screen") + # Restore the window position/size if values are present in the configuration cache + if mm_globals.config.has_section_key("window", "screen"): + get_window().current_screen = mm_globals.config.get_value("window", "screen") - if mm_globals.config.has_section_key("window", "maximized"): - get_window().mode = Window.MODE_MAXIMIZED if (mm_globals.config.get_value("window", "maximized")) else Window.MODE_WINDOWED + if mm_globals.config.has_section_key("window", "maximized"): + get_window().mode = Window.MODE_MAXIMIZED if (mm_globals.config.get_value("window", "maximized")) else Window.MODE_WINDOWED - if get_window().mode != Window.MODE_MAXIMIZED: - if mm_globals.config.has_section_key("window", "position"): - get_window().position = mm_globals.config.get_value("window", "position") - else: - get_window().min_size *= get_window().content_scale_factor - get_window().move_to_center() - if mm_globals.config.has_section_key("window", "size"): - get_window().size = mm_globals.config.get_value("window", "size") + if get_window().mode != Window.MODE_MAXIMIZED: + if mm_globals.config.has_section_key("window", "position"): + get_window().position = mm_globals.config.get_value("window", "position") + else: + get_window().min_size *= get_window().content_scale_factor + get_window().move_to_center() + if mm_globals.config.has_section_key("window", "size"): + get_window().size = mm_globals.config.get_value("window", "size") # Restore the theme var theme_name: String = "default dark" @@ -245,7 +257,6 @@ func _ready() -> void: DirAccess.remove_absolute(f) if get_current_graph_edit() == null: - await get_tree().process_frame new_material() size = get_window().size @@ -258,6 +269,10 @@ func _ready() -> void: size = get_viewport().size/get_viewport().content_scale_factor position = Vector2i(0, 0) + if OS.get_name() == "Android": + # copy image node's default mm_icon.png + android_copy_examples("png") + tip_label.hide() var menu_update_requested : bool = false @@ -273,7 +288,7 @@ func do_update_menus() -> void: menu_bar_class = mm_globals.menu_manager.MenuBarDisplayServer else: menu_bar_class = mm_globals.menu_manager.MenuBarGodot - var menu_bar = menu_bar_class.new($VBoxContainer/TopBar/Menu) + var menu_bar = menu_bar_class.new($MainContainer/VBoxContainer/TopBar/Menu) mm_globals.menu_manager.create_menus(MENU, self, menu_bar) menu_update_requested = false @@ -294,6 +309,7 @@ func _input(event: InputEvent) -> void: get_window().mode = Window.MODE_MAXIMIZED func on_config_changed() -> void: + DisplayServer.screen_set_keep_on(mm_globals.get_config("keep_screen_on")) DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_ENABLED if (mm_globals.get_config("vsync")) else DisplayServer.VSYNC_DISABLED) # Convert FPS to microseconds per frame. # Clamp the FPS to reasonable values to avoid locking up the UI. @@ -307,12 +323,7 @@ func on_config_changed() -> void: if OS.get_name() == "macOS": mm_globals.main_window.update_menus() - var ui_scale = mm_globals.get_config("ui_scale") - if ui_scale <= 0: - # If scale is set to 0 (auto), scale everything if the display requires it (crude hiDPI support). - # This prevents UI elements from being too small on hiDPI displays. - ui_scale = 2 if DisplayServer.screen_get_dpi() >= 192 and DisplayServer.screen_get_size().x >= 2048 else 1 - get_viewport().content_scale_factor = ui_scale + get_viewport().content_scale_factor = mm_globals.get_ui_scale() size = get_viewport().size/get_viewport().content_scale_factor position = Vector2i(0, 0) #ProjectSettings.set_setting("display/window/stretch/scale", scale) @@ -348,6 +359,7 @@ func on_config_changed() -> void: if mm_globals.config.get_value("window", "theme") == "custom": change_theme("custom") + func get_panel(panel_name : String) -> Control: return layout.get_panel(panel_name) @@ -659,6 +671,10 @@ func change_theme(theme_name : String) -> void: _theme.update() theme = _theme + + if mm_globals.get_config("touch_optimization"): + mobile_set_theme_overrides(theme) + ThemeUtils.setup_clear_color() $NodeFactory.on_theme_changed() @@ -722,15 +738,15 @@ func _on_PanelsPreset_id_pressed(id : int) -> void: var replace_status : String = await accept_dialog( "Preset \"%s\" already exists. Do you want to replace it?" % [preset_name], true) if replace_status == "ok": - existing_preset.preset = $VBoxContainer/Layout/FlexibleLayout.serialize() + existing_preset.preset = $MainContainer/VBoxContainer/Layout/FlexibleLayout.serialize() else: var new_preset : Dictionary = { "name": preset_name, - "preset": $VBoxContainer/Layout/FlexibleLayout.serialize() + "preset": $MainContainer/VBoxContainer/Layout/FlexibleLayout.serialize() } layout.presets.push_back(new_preset) _: - $VBoxContainer/Layout/FlexibleLayout.init(layout.presets[id].preset) + $MainContainer/VBoxContainer/Layout/FlexibleLayout.init(layout.presets[id].preset) update_menus() func create_menu_create(menu : MMMenuManager.MenuBase) -> void: @@ -916,11 +932,13 @@ func quit() -> void: quitting = false return if mm_globals.get_config("confirm_close_project"): - var result = await $VBoxContainer/Layout/FlexibleLayout/Main/Projects.check_save_tabs() + var result = await $MainContainer/VBoxContainer/Layout/FlexibleLayout/Main/Projects.check_save_tabs() if !result: quitting = false return await mm_renderer.stop_rendering_thread() + if OS.get_name() == "Android": + mm_globals.android_move_task_to_back() dim_window() get_tree().quit() quitting = false @@ -1112,10 +1130,10 @@ func view_reset_zoom() -> void: graph_edit.zoom = 1 func view_reset_panels() -> void: - $VBoxContainer/Layout.reset_panels() + $MainContainer/VBoxContainer/Layout.reset_panels() func toggle_side_panels() -> void: - $VBoxContainer/Layout.toggle_side_panels() + $MainContainer/VBoxContainer/Layout.toggle_side_panels() func get_selected_nodes() -> Array: var graph_edit : MMGraphEdit = get_current_graph_edit() @@ -1231,7 +1249,7 @@ func _on_PaintEnvironment_id_pressed(id) -> void: func environment_editor() -> Node: var env_editor : Node = load("res://material_maker/windows/environment_editor/environment_editor.tscn").instantiate() - add_child(env_editor) + add_dialog(env_editor) return env_editor # ----------------------------------------------------------------------- @@ -1239,6 +1257,9 @@ func environment_editor() -> Node: # ----------------------------------------------------------------------- func get_doc_dir() -> String: + if OS.get_name() == "Android": + return MMPaths.DOC_ADDRESS + var base_dir = MMPaths.get_resource_dir().replace("\\", "/") # In release builds, documentation is expected to be located in # a subdirectory of the program directory @@ -1252,6 +1273,9 @@ func get_doc_dir() -> String: return "" func show_doc() -> void: + if OS.get_name() == "Android": + mm_globals.android_open_url(MMPaths.DOC_ADDRESS) + return var doc_dir = get_doc_dir() if doc_dir != "": OS.shell_open(doc_dir+"/index.html") @@ -1259,39 +1283,54 @@ func show_doc() -> void: func show_doc_is_disabled() -> bool: + if OS.get_name() == "Android": + return false return get_doc_dir() == "" func show_library_item_doc() -> void: var doc_dir : String = get_doc_dir() if doc_dir != "": var doc_name = library.get_selected_item_doc_name() + var doc_path : String = doc_dir+"/node_"+doc_name+".html" + + if OS.get_name() == "Android": + if library.get_selected_item_name() == "" or not library.is_inside_tree(): + mm_globals.android_make_toast("Please select an item in the libary panel.") + else: + var path : String = android_process_doc_path(doc_dir, doc_name) + mm_globals.android_open_url(path) + return + while doc_name != "": - var doc_path : String = doc_dir+"/node_"+doc_name+".html" if FileAccess.file_exists(doc_path): OS.shell_open(doc_path) break doc_name = doc_name.left(doc_name.rfind("_")) func show_library_item_doc_is_disabled() -> bool: + if OS.get_name() == "Android": + return false return get_doc_dir() == "" or !library.is_inside_tree() or library.get_selected_item_doc_name() == "" func bug_report() -> void: OS.shell_open("https://github.com/RodZill4/godot-procedural-textures/issues") func about() -> void: - var about_box = preload("res://material_maker/windows/about/about.tscn").instantiate() - add_child(about_box) - about_box.hide() - about_box.popup_centered() + var about_box : Window = preload("res://material_maker/windows/about/about.tscn").instantiate() + add_dialog(about_box) func show_example_projects() -> void: - var base_dir : String = MMPaths.get_resource_dir().replace("\\", "/") - var release_examples_path : String = base_dir.path_join("examples") - var devel_examples_path : String = ProjectSettings.globalize_path("res://material_maker/examples") - for p in [ release_examples_path, devel_examples_path ]: - if DirAccess.dir_exists_absolute(p): - OS.shell_open(p) - return + if OS.get_name() == "Android": + android_copy_examples() + android_load_example_project() + else: + var base_dir : String = MMPaths.get_resource_dir().replace("\\", "/") + var release_examples_path : String = base_dir.path_join("examples") + var devel_examples_path : String = ProjectSettings.globalize_path("res://material_maker/examples") + for p in [ release_examples_path, devel_examples_path ]: + if DirAccess.dir_exists_absolute(p): + OS.shell_open(p) + return # Preview @@ -1518,8 +1557,8 @@ func set_tip_text(tip : String, timeout : float = 0.0, priority: int = 0): tip = tip.replace("#RIGHT", "[img]res://material_maker/icons/right_arrow.tres[/img]") if priority >= tip_priority: tip_priority = priority - $VBoxContainer/StatusBar/HBox/Tip.text = tip - var tip_timer : Timer = $VBoxContainer/StatusBar/HBox/Tip/Timer + tip_label.text = tip + var tip_timer : Timer = tip_label.get_node("Timer") tip_timer.stop() if timeout > 0.0: tip_timer.one_shot = true @@ -1528,15 +1567,20 @@ func set_tip_text(tip : String, timeout : float = 0.0, priority: int = 0): func _on_Tip_Timer_timeout(): tip_priority = 0 - $VBoxContainer/StatusBar/HBox/Tip.text = "" + tip_label.text = "" # Add dialog -func add_dialog(dialog : Window): - if mm_globals.get_config("dialog_dim_background"): - var background : ColorRect = load("res://material_maker/darken.tscn").instantiate() - add_child(background) - dialog.tree_exited.connect(background.queue_free) +func add_dialog(dialog : Window) -> void: + var opaque_dim : bool = mm_globals.should_dim_fullscreen(dialog) + if opaque_dim or mm_globals.get_config("dialog_dim_background"): + var bg : ColorRect = ColorRect.new() + bg.set_anchors_and_offsets_preset(PRESET_FULL_RECT) + bg.color = theme.get_stylebox("panel", "Panel").bg_color + bg.color.a = 1.0 if opaque_dim else 0.8 + + get_tree().root.add_child(bg) + dialog.tree_exited.connect(bg.queue_free) add_child(dialog) # Accept dialog @@ -1575,3 +1619,136 @@ func draw_children(p, x): func _draw_debug(): draw_children(self, get_global_mouse_position()) + +#region mobile-specific setups + +func android_setup_margins() -> void: + # offset by MM_MainBackground stylebox content margins + if not mm_globals.get_config("touch_full_screen"): + $MainContainer.add_theme_constant_override("margin_left", + maxi(mm_touch.cutout_margins(SIDE_LEFT) - 10, 0)) + $MainContainer.add_theme_constant_override("margin_right", + maxi(mm_touch.cutout_margins(SIDE_RIGHT) - 10, 0)) + else: + $MainContainer.remove_theme_constant_override("margin_right") + $MainContainer.remove_theme_constant_override("margin_left") + +func android_setup_status_bar() -> void: + # move status bar items to menu bar + var status_bar_hbox : HBoxContainer = $MainContainer/VBoxContainer/StatusBar/HBox + var menu_bar_hbox : HBoxContainer = $MainContainer/VBoxContainer/TopBar/Menu + + status_bar_hbox.owner = null + status_bar_hbox.reparent(menu_bar_hbox.get_parent()) + status_bar_hbox.owner = self + + var status_spacer : Control = Control.new() + status_spacer.name = "StatusBarSpacer" + status_bar_hbox.add_child(status_spacer) + + var menu_spacer : Control = Control.new() + menu_spacer.name = "MenuBarSpacer" + menu_bar_hbox.add_child(menu_spacer) + menu_bar_hbox.move_child(menu_spacer, 0) + + android_update_spacers(menu_spacer, status_spacer) + mm_globals.preferences_updated.connect( + android_update_spacers.bind(menu_spacer, status_spacer)) + + await status_bar_hbox.ready + status_bar_hbox.get_node("Tip").hide() + $MainContainer/VBoxContainer/StatusBar.hide() + +func android_update_spacers(menu : Control, status : Control) -> void: + android_update_spacer_margins(status, SIDE_RIGHT, CORNER_BOTTOM_RIGHT) + android_update_spacer_margins(menu, SIDE_LEFT, CORNER_TOP_RIGHT) + +func android_update_spacer_margins(spacer : Control, + side : Side, corner : Corner) -> void: + var corner_reach : float = 0.0 + + # avoid screen corners + var r : float = mm_touch.corner_radius(corner) + if r > 0.0: + var h : float = 36.0 # window title_height theme constant + corner_reach = sqrt(maxf((r) ** 2.0 - (r-h) ** 2.0, 0.0)) + corner_reach /= mm_globals.get_ui_scale() + + if mm_globals.get_config("touch_full_screen"): + DisplayServer.get_display_cutouts() + spacer.custom_minimum_size.x = corner_reach + else: + # account for main container's already-applied margins + spacer.custom_minimum_size.x = maxf(corner_reach - mm_touch.cutout_margins(side), 0.0) + +func mobile_set_theme_overrides(t : Theme) -> void: + const vh_scroll_width : int = 10 + var sv : StyleBoxFlat = t.get_stylebox("scroll", "VScrollBar") + sv.set_border_width(SIDE_LEFT, vh_scroll_width) + sv.set_border_width(SIDE_RIGHT, vh_scroll_width) + + var sh : StyleBoxFlat = t.get_stylebox("scroll", "HScrollBar") + sh.set_border_width(SIDE_TOP, vh_scroll_width) + sh.set_border_width(SIDE_BOTTOM, vh_scroll_width) + + t.set_constant("v_separation", "PopupMenu", 16) + t.set_constant("v_separation", "ItemList", 16) + t.set_constant("resize_margin", "Window", 32) + + t.set_stylebox("pressed", "Button", t.get_stylebox("hover_pressed", "Button")) + t.set_stylebox("hover", "Button", t.get_stylebox("normal", "Button")) + +func android_copy_examples(ext : String = "ptex") -> void: + # copy example projects from exported examples + var base : String = "res://material_maker/examples/" + var examples : String = "user://examples/" + DirAccess.make_dir_absolute("user://examples/") + var dir : DirAccess = DirAccess.open(base) + dir.list_dir_begin() + var arr : PackedStringArray + while true: + var f : String = dir.get_next() + arr.push_back(f) + if f.is_empty(): + break + if f.get_extension() == ext and not FileAccess.file_exists(examples.path_join(f)): + dir.copy(base.path_join(f), examples.path_join(f)) + dir.list_dir_end() + +func android_load_example_project() -> void: + const fd : String = "res://material_maker/windows/file_dialog/file_dialog.tscn" + var dialog : FileDialog = preload(fd).instantiate() + dialog.access = FileDialog.ACCESS_USERDATA + dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILES + dialog.current_dir = "examples" + dialog.add_filter("*.ptex;Procedural Textures File") + var files = await dialog.select_files() + if files.size() > 0: + do_load_project(files[0]) + +func android_process_doc_path(doc_dir : String, doc_name : String) -> String: + const maps : Dictionary[String, String] = { + "miscellaneous_reroute": "reroute_nodes", + "miscellaneous": "miscellaneous_nodes", + "workflow": "nodes_workflow", + "transform": "nodes_transform", + "filter": "nodes_filter", + "noise": "nodes_noise", + "pattern": "nodes_pattern", + "3d": "nodes_3d", + "simple": "nodes_simple", + } + + const prefix : Dictionary[String, String] = { + "miscellaneous_aperture": "aperture_nodes" + } + + for p in prefix.keys(): + if doc_name.begins_with(p): + return doc_dir.path_join(prefix[p]+".html") + + if maps.has(doc_name): + return doc_dir.path_join(maps[doc_name]+".html") + return doc_dir+"/node_"+doc_name+".html" + +#endregion diff --git a/material_maker/main_window.tscn b/material_maker/main_window.tscn index ebdc776254..b5ce0c2dac 100644 --- a/material_maker/main_window.tscn +++ b/material_maker/main_window.tscn @@ -102,10 +102,10 @@ filter_clip = true anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -offset_left = -160.0 -offset_top = -21.0 -offset_right = 430.0 -offset_bottom = 311.0 +offset_left = -54.99 +offset_top = 18.19 +offset_right = 535.01 +offset_bottom = 350.19 grow_horizontal = 2 grow_vertical = 2 size_flags_horizontal = 3 @@ -139,29 +139,35 @@ config_section = "brush_lib" [node name="EnvironmentManager" parent="." unique_id=2064810205 instance=ExtResource("13")] -[node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=257055939] +[node name="MainContainer" type="MarginContainer" parent="." unique_id=1229937872] +layout_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="MainContainer" unique_id=257055939] +unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 -[node name="TopBar" type="HBoxContainer" parent="VBoxContainer" unique_id=1671198557] +[node name="TopBar" type="HBoxContainer" parent="MainContainer/VBoxContainer" unique_id=1671198557] layout_mode = 2 -[node name="Menu" type="HBoxContainer" parent="VBoxContainer/TopBar" unique_id=1359206080] +[node name="Menu" type="HBoxContainer" parent="MainContainer/VBoxContainer/TopBar" unique_id=1359206080] layout_mode = 2 size_flags_horizontal = 3 -[node name="Layout" type="HBoxContainer" parent="VBoxContainer" unique_id=1034731775] +[node name="Layout" type="HBoxContainer" parent="MainContainer/VBoxContainer" unique_id=1034731775] +unique_name_in_owner = true layout_mode = 2 size_flags_vertical = 3 script = ExtResource("2") -[node name="FlexibleLayout" parent="VBoxContainer/Layout" unique_id=2116126116 instance=ExtResource("6_ygla4")] +[node name="FlexibleLayout" parent="MainContainer/VBoxContainer/Layout" unique_id=2116126116 instance=ExtResource("6_ygla4")] layout_mode = 2 size_flags_horizontal = 3 allow_undock = true -[node name="Main" parent="VBoxContainer/Layout/FlexibleLayout" unique_id=1335562493 instance=ExtResource("7_ih0ps")] +[node name="Main" parent="MainContainer/VBoxContainer/Layout/FlexibleLayout" unique_id=1335562493 instance=ExtResource("7_ih0ps")] +unique_name_in_owner = true layout_mode = 0 anchors_preset = 0 anchor_right = 0.0 @@ -173,13 +179,13 @@ offset_bottom = 32.0 grow_horizontal = 1 grow_vertical = 1 -[node name="ConsoleResizer" type="Control" parent="VBoxContainer" unique_id=2025564150] +[node name="ConsoleResizer" type="Control" parent="MainContainer/VBoxContainer" unique_id=2025564150] unique_name_in_owner = true custom_minimum_size = Vector2(0, 10) layout_mode = 2 mouse_default_cursor_shape = 9 -[node name="ResizerBar" type="PanelContainer" parent="VBoxContainer/ConsoleResizer" unique_id=606354979] +[node name="ResizerBar" type="PanelContainer" parent="MainContainer/VBoxContainer/ConsoleResizer" unique_id=606354979] custom_minimum_size = Vector2(0, 4) layout_mode = 1 anchors_preset = 14 @@ -192,28 +198,29 @@ size_flags_horizontal = 4 mouse_filter = 2 theme_override_styles/panel = SubResource("StyleBoxFlat_2cpsi") -[node name="Console" type="HBoxContainer" parent="VBoxContainer" unique_id=9505509] +[node name="Console" type="HBoxContainer" parent="MainContainer/VBoxContainer" unique_id=9505509] unique_name_in_owner = true visible = false custom_minimum_size = Vector2(0, 100) layout_mode = 2 script = ExtResource("8_1tb00") -[node name="RichTextLabel" type="RichTextLabel" parent="VBoxContainer/Console" unique_id=223286998] +[node name="RichTextLabel" type="RichTextLabel" parent="MainContainer/VBoxContainer/Console" unique_id=223286998] custom_minimum_size = Vector2(0, 100) layout_mode = 2 size_flags_horizontal = 3 bbcode_enabled = true scroll_following = true -[node name="StatusBar" type="PanelContainer" parent="VBoxContainer" unique_id=1997079745] +[node name="StatusBar" type="PanelContainer" parent="MainContainer/VBoxContainer" unique_id=1997079745] layout_mode = 2 theme_type_variation = &"MM_StatusBarBackground" -[node name="HBox" type="HBoxContainer" parent="VBoxContainer/StatusBar" unique_id=860693887] +[node name="HBox" type="HBoxContainer" parent="MainContainer/VBoxContainer/StatusBar" unique_id=860693887] layout_mode = 2 -[node name="Tip" type="RichTextLabel" parent="VBoxContainer/StatusBar/HBox" unique_id=2056192730] +[node name="Tip" type="RichTextLabel" parent="MainContainer/VBoxContainer/StatusBar/HBox" unique_id=2056192730] +unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 4 @@ -221,9 +228,9 @@ bbcode_enabled = true fit_content = true scroll_active = false -[node name="Timer" type="Timer" parent="VBoxContainer/StatusBar/HBox/Tip" unique_id=654728135] +[node name="Timer" type="Timer" parent="MainContainer/VBoxContainer/StatusBar/HBox/Tip" unique_id=654728135] -[node name="UndoRedoLabel" type="Label" parent="VBoxContainer/StatusBar/HBox" unique_id=984075942] +[node name="UndoRedoLabel" type="Label" parent="MainContainer/VBoxContainer/StatusBar/HBox" unique_id=984075942] unique_name_in_owner = true visible = false layout_mode = 2 @@ -231,14 +238,14 @@ size_flags_horizontal = 4 text = "Undo/Redo action added" script = SubResource("6") -[node name="AnimationPlayer" type="AnimationPlayer" parent="VBoxContainer/StatusBar/HBox/UndoRedoLabel" unique_id=955898904] +[node name="AnimationPlayer" type="AnimationPlayer" parent="MainContainer/VBoxContainer/StatusBar/HBox/UndoRedoLabel" unique_id=955898904] libraries/ = SubResource("AnimationLibrary_kxf7t") -[node name="ConsoleControls" type="HBoxContainer" parent="VBoxContainer/StatusBar/HBox" unique_id=365066398] +[node name="ConsoleControls" type="HBoxContainer" parent="MainContainer/VBoxContainer/StatusBar/HBox" unique_id=365066398] layout_mode = 2 alignment = 2 -[node name="ClearConsoleButton" type="TextureButton" parent="VBoxContainer/StatusBar/HBox/ConsoleControls" unique_id=416342385] +[node name="ClearConsoleButton" type="TextureButton" parent="MainContainer/VBoxContainer/StatusBar/HBox/ConsoleControls" unique_id=416342385] unique_name_in_owner = true modulate = Color(1, 1, 1, 0.49803922) custom_minimum_size = Vector2(20, 20) @@ -248,7 +255,7 @@ size_flags_vertical = 4 tooltip_text = "Clear console" stretch_mode = 0 -[node name="ConsoleButton" type="TextureButton" parent="VBoxContainer/StatusBar/HBox/ConsoleControls" unique_id=1288312618] +[node name="ConsoleButton" type="TextureButton" parent="MainContainer/VBoxContainer/StatusBar/HBox/ConsoleControls" unique_id=1288312618] unique_name_in_owner = true modulate = Color(1, 1, 1, 0.49803922) custom_minimum_size = Vector2(20, 20) @@ -259,41 +266,41 @@ size_flags_vertical = 4 tooltip_text = "Show console" stretch_mode = 0 -[node name="VSeparator1" type="VSeparator" parent="VBoxContainer/StatusBar/HBox" unique_id=398470012] +[node name="VSeparator1" type="VSeparator" parent="MainContainer/VBoxContainer/StatusBar/HBox" unique_id=398470012] layout_mode = 2 -[node name="Share" parent="VBoxContainer/StatusBar/HBox" unique_id=798130657 instance=ExtResource("12")] +[node name="Share" parent="MainContainer/VBoxContainer/StatusBar/HBox" unique_id=798130657 instance=ExtResource("12")] unique_name_in_owner = true layout_mode = 2 -[node name="VSeparator2" type="VSeparator" parent="VBoxContainer/StatusBar/HBox" unique_id=46983986] +[node name="VSeparator2" type="VSeparator" parent="MainContainer/VBoxContainer/StatusBar/HBox" unique_id=46983986] layout_mode = 2 -[node name="ClipBoardAnalyzer" type="HBoxContainer" parent="VBoxContainer/StatusBar/HBox" unique_id=500957646] +[node name="ClipBoardAnalyzer" type="HBoxContainer" parent="MainContainer/VBoxContainer/StatusBar/HBox" unique_id=500957646] layout_mode = 2 script = SubResource("9") -[node name="Clipboard" type="TextureRect" parent="VBoxContainer/StatusBar/HBox/ClipBoardAnalyzer" unique_id=1605541228] +[node name="Clipboard" type="TextureRect" parent="MainContainer/VBoxContainer/StatusBar/HBox/ClipBoardAnalyzer" unique_id=1605541228] visible = false layout_mode = 2 size_flags_vertical = 4 mouse_filter = 2 texture = SubResource("8") -[node name="Contents" type="TextureRect" parent="VBoxContainer/StatusBar/HBox/ClipBoardAnalyzer" unique_id=795860269] +[node name="Contents" type="TextureRect" parent="MainContainer/VBoxContainer/StatusBar/HBox/ClipBoardAnalyzer" unique_id=795860269] layout_mode = 2 size_flags_vertical = 4 mouse_filter = 2 texture = ExtResource("15") -[node name="Timer" type="Timer" parent="VBoxContainer/StatusBar/HBox/ClipBoardAnalyzer" unique_id=358487496] +[node name="Timer" type="Timer" parent="MainContainer/VBoxContainer/StatusBar/HBox/ClipBoardAnalyzer" unique_id=358487496] wait_time = 0.5 autostart = true -[node name="VSeparator3" type="VSeparator" parent="VBoxContainer/StatusBar/HBox" unique_id=1220214490] +[node name="VSeparator3" type="VSeparator" parent="MainContainer/VBoxContainer/StatusBar/HBox" unique_id=1220214490] layout_mode = 2 -[node name="RenderCounter" parent="VBoxContainer/StatusBar/HBox" unique_id=57795798 instance=ExtResource("11")] +[node name="RenderCounter" parent="MainContainer/VBoxContainer/StatusBar/HBox" unique_id=57795798 instance=ExtResource("11")] layout_mode = 2 [node name="NodeFactory" type="Node" parent="." unique_id=738541505] @@ -302,13 +309,13 @@ script = ExtResource("9") [node name="AddNodePopup" parent="." unique_id=142473620 instance=ExtResource("7")] visible = false -[connection signal="layout_changed" from="VBoxContainer/Layout/FlexibleLayout" to="." method="update_menus"] -[connection signal="gui_input" from="VBoxContainer/ConsoleResizer" to="VBoxContainer/Console" method="_on_console_resizer_gui_input"] -[connection signal="gui_input" from="VBoxContainer/ConsoleResizer/ResizerBar" to="VBoxContainer/Console" method="_on_console_resizer_gui_input"] -[connection signal="meta_clicked" from="VBoxContainer/Console/RichTextLabel" to="VBoxContainer/Console" method="_on_rich_text_label_meta_clicked"] -[connection signal="meta_hover_ended" from="VBoxContainer/Console/RichTextLabel" to="VBoxContainer/Console" method="_on_rich_text_label_meta_hover_ended"] -[connection signal="meta_hover_started" from="VBoxContainer/Console/RichTextLabel" to="VBoxContainer/Console" method="_on_rich_text_label_meta_hover_started"] -[connection signal="timeout" from="VBoxContainer/StatusBar/HBox/Tip/Timer" to="." method="_on_Tip_Timer_timeout"] -[connection signal="pressed" from="VBoxContainer/StatusBar/HBox/ConsoleControls/ClearConsoleButton" to="VBoxContainer/Console" method="clear"] -[connection signal="pressed" from="VBoxContainer/StatusBar/HBox/ConsoleControls/ConsoleButton" to="VBoxContainer/Console" method="toggle"] -[connection signal="timeout" from="VBoxContainer/StatusBar/HBox/ClipBoardAnalyzer/Timer" to="VBoxContainer/StatusBar/HBox/ClipBoardAnalyzer" method="_on_Timer_timeout"] +[connection signal="layout_changed" from="MainContainer/VBoxContainer/Layout/FlexibleLayout" to="." method="update_menus"] +[connection signal="gui_input" from="MainContainer/VBoxContainer/ConsoleResizer" to="MainContainer/VBoxContainer/Console" method="_on_console_resizer_gui_input"] +[connection signal="gui_input" from="MainContainer/VBoxContainer/ConsoleResizer/ResizerBar" to="MainContainer/VBoxContainer/Console" method="_on_console_resizer_gui_input"] +[connection signal="meta_clicked" from="MainContainer/VBoxContainer/Console/RichTextLabel" to="MainContainer/VBoxContainer/Console" method="_on_rich_text_label_meta_clicked"] +[connection signal="meta_hover_ended" from="MainContainer/VBoxContainer/Console/RichTextLabel" to="MainContainer/VBoxContainer/Console" method="_on_rich_text_label_meta_hover_ended"] +[connection signal="meta_hover_started" from="MainContainer/VBoxContainer/Console/RichTextLabel" to="MainContainer/VBoxContainer/Console" method="_on_rich_text_label_meta_hover_started"] +[connection signal="timeout" from="MainContainer/VBoxContainer/StatusBar/HBox/Tip/Timer" to="." method="_on_Tip_Timer_timeout"] +[connection signal="pressed" from="MainContainer/VBoxContainer/StatusBar/HBox/ConsoleControls/ClearConsoleButton" to="MainContainer/VBoxContainer/Console" method="clear"] +[connection signal="pressed" from="MainContainer/VBoxContainer/StatusBar/HBox/ConsoleControls/ConsoleButton" to="MainContainer/VBoxContainer/Console" method="toggle"] +[connection signal="timeout" from="MainContainer/VBoxContainer/StatusBar/HBox/ClipBoardAnalyzer/Timer" to="MainContainer/VBoxContainer/StatusBar/HBox/ClipBoardAnalyzer" method="_on_Timer_timeout"] diff --git a/material_maker/nodes/base.gd b/material_maker/nodes/base.gd index ec8a871170..8ce5a90eb8 100644 --- a/material_maker/nodes/base.gd +++ b/material_maker/nodes/base.gd @@ -331,15 +331,7 @@ func _on_gui_input(event) -> void: doubleclicked = true if event.button_index == MOUSE_BUTTON_RIGHT: accept_event() - var menu : PopupMenu = create_context_menu() - if menu != null: - if menu.get_item_count() != 0: - add_child(menu) - menu.popup_hide.connect(menu.queue_free) - menu.id_pressed.connect(self._on_menu_id_pressed) - mm_globals.popup_menu(menu, self) - else: - menu.free() + show_context_menu() elif doubleclicked: doubleclicked = false if generator is MMGenGraph: @@ -421,6 +413,17 @@ func create_context_menu() -> PopupMenu: menu.add_item(tr("Propagate changes"), MENU_PROPAGATE_CHANGES) return menu +func show_context_menu() -> void: + var menu : PopupMenu = create_context_menu() + if menu != null: + if menu.get_item_count() != 0: + add_child(menu) + menu.popup_hide.connect(menu.queue_free) + menu.id_pressed.connect(self._on_menu_id_pressed) + mm_globals.popup_menu(menu, self) + else: + menu.free() + func _on_menu_id_pressed(id : int) -> void: match id: MENU_PROPAGATE_CHANGES: diff --git a/material_maker/nodes/debug/debug.gd b/material_maker/nodes/debug/debug.gd index a5fd1d00e1..0aa56645eb 100644 --- a/material_maker/nodes/debug/debug.gd +++ b/material_maker/nodes/debug/debug.gd @@ -1,3 +1,4 @@ +class_name MMGraphDebug extends MMGraphNodeBase func _ready(): diff --git a/material_maker/nodes/generic/generic.tscn b/material_maker/nodes/generic/generic.tscn index b6e7ae52bd..d93efbbef4 100644 --- a/material_maker/nodes/generic/generic.tscn +++ b/material_maker/nodes/generic/generic.tscn @@ -5,7 +5,6 @@ [node name="Generic" type="GraphNode" unique_id=1189007728] offset_right = 95.0 offset_bottom = 29.0 -scaling_menus = true title = "Generic" script = ExtResource("1") diff --git a/material_maker/nodes/minimal.gd b/material_maker/nodes/minimal.gd index d26a2eca0a..3b858d9ed6 100644 --- a/material_maker/nodes/minimal.gd +++ b/material_maker/nodes/minimal.gd @@ -13,7 +13,7 @@ const CLOSE_ICON : Texture2D = preload("res://material_maker/icons/close.tres") func _ready() -> void: - scaling_menus = true + scaling_menus = false position_offset_changed.connect(self._on_offset_changed) if buttons == null: buttons = HBoxContainer.new() diff --git a/material_maker/nodes/portal/portal.gd b/material_maker/nodes/portal/portal.gd index 59ba9e23b6..1c3e682b7b 100644 --- a/material_maker/nodes/portal/portal.gd +++ b/material_maker/nodes/portal/portal.gd @@ -10,7 +10,7 @@ var is_editing : bool = false var syncing_io : bool = false var is_navigating_source : bool = false -const label_y_offset : float = 35.0 +const LABEL_Y_OFFSET : float = 35.0 func _ready() -> void: super._ready() @@ -41,7 +41,7 @@ func _draw() -> void: if generator.horizontal_label: label_draw_pos += Vector2(31.0 if is_portal_in() else (-label_size.x - 31.0), 5.0) else: - label_draw_pos -= Vector2(label_size.x * 0.5, label_y_offset) + label_draw_pos -= Vector2(label_size.x * 0.5, LABEL_Y_OFFSET) draw_string_outline(LABEL_FONT, label_draw_pos, get_link(), HORIZONTAL_ALIGNMENT_CENTER, -1, label_font_size, 5, Color.BLACK) draw_string(LABEL_FONT, label_draw_pos, get_link(), HORIZONTAL_ALIGNMENT_CENTER, -1, label_font_size, label_color) @@ -299,6 +299,19 @@ func set_color(c : Color) -> void: queue_redraw() get_parent().send_changed_signal() +func get_rect_with_link() -> Rect2: + var label_size : Vector2 = LABEL_FONT.get_string_size( + get_link(), HORIZONTAL_ALIGNMENT_CENTER) + var label_width_half = label_size.x * 0.5 + var r : Rect2 = Rect2(Vector2.ZERO, size) + if generator.horizontal_label: + r = r.grow_side(SIDE_RIGHT if is_portal_in() else SIDE_LEFT, label_size.x + 31.0) + else: + r = r.grow_side(SIDE_LEFT, label_width_half) + r = r.grow_side(SIDE_RIGHT, label_width_half) + r = r.grow_side(SIDE_TOP, LABEL_Y_OFFSET) + return r + #region portal link edit ## Replaces all links from [param from_link] to [param new_link]. @@ -317,7 +330,7 @@ func replace_links(new_link : String, from_link : String) -> void: p.on_parameter_changed("link", new_link) func edit_box_set_position(edit : LineEdit) -> void: - var y_offset : float = label_y_offset + 21.0 + var y_offset : float = LABEL_Y_OFFSET + 21.0 var g : MMGraphEdit = get_parent() if g == null: edit.queue_free() diff --git a/material_maker/nodes/reroute/reroute.gd b/material_maker/nodes/reroute/reroute.gd index 4c752c7ea0..e13173b6c0 100644 --- a/material_maker/nodes/reroute/reroute.gd +++ b/material_maker/nodes/reroute/reroute.gd @@ -1,3 +1,4 @@ +class_name MMGraphReroute extends MMGraphNodeMinimal diff --git a/material_maker/nodes/switch/switch.gd b/material_maker/nodes/switch/switch.gd index 8aacfaf32d..aeaae37542 100644 --- a/material_maker/nodes/switch/switch.gd +++ b/material_maker/nodes/switch/switch.gd @@ -1,3 +1,4 @@ +class_name MMGraphSwitch extends MMGraphNodeGeneric var fixed_lines : int = 0 diff --git a/material_maker/panels/graph_edit/graph_actions_menu.gd b/material_maker/panels/graph_edit/graph_actions_menu.gd new file mode 100644 index 0000000000..cc28b82f9e --- /dev/null +++ b/material_maker/panels/graph_edit/graph_actions_menu.gd @@ -0,0 +1,41 @@ +extends PanelContainer + +var graph : MMGraphEdit + +func _ready() -> void: + if OS.get_name() != "Android": + hide() + +func _on_knife_tool_toggled(toggled_on : bool) -> void: + if not graph: + graph = mm_globals.main_window.get_current_graph_edit() + if toggled_on: + if not graph.cut_drag_finished.is_connected(reset_knife_action_button): + graph.cut_drag_finished.connect(reset_knife_action_button) + should_hide_selection_rect(true) + should_disable_graph_elements(true) + graph.drag_cut_line.clear() + else: + reset_knife_action_button() + graph.valid_drag_cut_entry = toggled_on + +func reset_knife_action_button() -> void: + $HBox/KnifeTool.hide() + $HBox/KnifeTool.show.call_deferred() + $HBox/KnifeTool.set_pressed_no_signal(false) + should_disable_graph_elements(false) + should_hide_selection_rect(false) + +func should_hide_selection_rect(is_hide : bool) -> void: + if is_hide: + graph.add_theme_color_override("selection_fill", Color.TRANSPARENT) + graph.add_theme_color_override("selection_stroke", Color.TRANSPARENT) + else: + graph.remove_theme_color_override("selection_fill") + graph.remove_theme_color_override("selection_stroke") + +func should_disable_graph_elements(disable : bool) -> void: + for x in graph.get_children(): + if x is GraphElement: + x.modulate.a = 0.5 if disable else 1.0 + x.selectable = not disable diff --git a/material_maker/panels/graph_edit/graph_actions_menu.gd.uid b/material_maker/panels/graph_edit/graph_actions_menu.gd.uid new file mode 100644 index 0000000000..ec6fe17ee0 --- /dev/null +++ b/material_maker/panels/graph_edit/graph_actions_menu.gd.uid @@ -0,0 +1 @@ +uid://c7hvi7bvtgwbd diff --git a/material_maker/panels/graph_edit/graph_edit.gd b/material_maker/panels/graph_edit/graph_edit.gd index f47e33fa8c..bee953a6d8 100644 --- a/material_maker/panels/graph_edit/graph_edit.gd +++ b/material_maker/panels/graph_edit/graph_edit.gd @@ -16,7 +16,7 @@ class Preview: var node_factory = null -var save_path := "": set = set_save_path +var save_path : String = "": set = set_save_path var need_save : bool = false var save_crash_recovery_path = "" var need_save_crash_recovery : bool = false @@ -68,11 +68,17 @@ var is_dragging_connection : bool = false: is_dragging_connection = v set_process_if_necessary() +var has_double_tap : bool = false + +var node_actions_panel : NodeActionsPanel + signal save_path_changed signal graph_changed signal view_updated signal preview_changed +## Emitted when connections are cut using the knife tool. +signal cut_drag_finished func _ready() -> void: OS.low_processor_usage_mode = true @@ -82,6 +88,13 @@ func _ready() -> void: add_valid_connection_type(42, t) node_popup.about_to_popup.connect(func(): valid_drag_cut_entry = false) + if mm_globals.get_config("touch_node_actions"): + node_actions_panel = NodeActionsPanel.new(self) + + if mm_globals.get_config("touch_optimization"): + $GraphUI/ButtonReroll.hide() + $GraphUI/ButtonShowTree.hide() + func _exit_tree(): remove_crash_recovery_file() @@ -130,8 +143,24 @@ func process_port_click(pressed : bool): port_click_port_index = -1 return - func _input(event : InputEvent) -> void: + if DisplayServer.is_touchscreen_available(): + if event.get("position") and get_rect().has_point( + make_input_local(event).position): + if OS.get_name() == "Android": + if event is InputEventPanGesture: + scroll_offset += event.delta + if is_dragging_connection: + force_connection_drag_end() + accept_event() + elif OS.get_name() == "iOS": + if event is InputEventScreenDrag and event.index == 1: + scroll_offset -= event.relative + force_selection_end() + if is_dragging_connection: + force_connection_drag_end() + accept_event() + # Handle node grab if has_grab: var selected_nodes := get_selected_nodes() @@ -175,7 +204,7 @@ func _input(event : InputEvent) -> void: if event.unicode >= KEY_0 and event.unicode <= KEY_9 and event.pressed: grab_focus() -func _gui_input(event) -> void: +func _gui_input(event : InputEvent) -> void: if ( event.is_action_pressed("ui_library_popup") and not Input.is_key_pressed(KEY_CTRL) @@ -187,21 +216,7 @@ func _gui_input(event) -> void: node_popup.position = Vector2i(get_screen_transform()*get_local_mouse_position()) node_popup.show_popup() elif event.is_action_released("ui_cut_drag"): - var conns : Array[Dictionary] - for p in len(drag_cut_line) - 1: - var rect : Rect2 - rect.position = drag_cut_line[p] - rect.end = drag_cut_line[p + 1] - conns = get_connections_intersecting_with_rect(rect.abs()) - if conns.size(): - connections_to_cut.append_array(conns) - if connections_to_cut.size(): - on_cut_connections(connections_to_cut) - connections_to_cut.clear() - Input.set_custom_mouse_cursor(null) - drag_cut_line.clear() - conns.clear() - queue_redraw() + do_cut_drag() elif event.is_action_released("ui_lasso_select", true): for node in get_children(): if node is GraphElement: @@ -378,7 +393,29 @@ func _gui_input(event) -> void: Input.set_custom_mouse_cursor(null) lasso_points.clear() queue_redraw() - + elif event is InputEventScreenTouch: + if not event.pressed: + if mm_touch.last_touch_duration_msec < 150: + cut_drag_finished.emit() + valid_drag_cut_entry = false + if mm_touch.last_touch_duration_msec < 80: + if event.index == 1: + mm_globals.main_window.edit_undo() + elif event.index == 2: + mm_globals.main_window.edit_redo() + elif valid_drag_cut_entry and event.index == 0: + do_cut_drag() + valid_drag_cut_entry = false + elif event is InputEventScreenDrag and event.index == 0 and valid_drag_cut_entry: + # actions menu knife gesture + if is_dragging_connection: + force_connection_drag_end() + drag_cut_line.append(get_local_mouse_position()) + queue_redraw() + else: + if not valid_drag_cut_entry: + drag_cut_line.clear() + queue_redraw() func get_padded_node_rect(graph_node:GraphNode) -> Rect2: var rect : Rect2 = graph_node.get_global_rect() @@ -591,7 +628,7 @@ func set_need_save(ns = true) -> void: update_tab_title() need_save_crash_recovery = true -func set_save_path(path: String) -> void: +func set_save_path(path : String) -> void: if path != save_path: remove_crash_recovery_file() need_save_crash_recovery = false @@ -703,7 +740,7 @@ func new_material(init_nodes = {nodes=[{name="Material", type="material",paramet add_child(top_generator) move_child(top_generator, 0) update_view(top_generator) - center_view() + center_view.call_deferred() set_save_path("") set_need_save(false) @@ -1643,7 +1680,6 @@ func add_reroute_under_mouse() -> void: var next : Dictionary = generator.serialize() undoredo_create_step("Reroute on connection", generator.get_hier_name(), prev, next) - func add_reroute_to_input(node : MMGraphNodeMinimal, port_index : int) -> void: var prev = generator.serialize() var new_connections = [] @@ -2039,6 +2075,34 @@ func _on_button_reroll_pressed() -> void: func _on_button_reroll_mouse_entered() -> void: mm_globals.set_tip_text("#LMB: Reroll all nodes, Shift+#LMB: Reroll selected nodes") +func do_cut_drag() -> void: + var conns : Array[Dictionary] + for p in len(drag_cut_line) - 1: + var rect : Rect2 + rect.position = drag_cut_line[p] + rect.end = drag_cut_line[p + 1] + conns = get_connections_intersecting_with_rect(rect.abs()) + if conns.size(): + connections_to_cut.append_array(conns) + if connections_to_cut.size(): + on_cut_connections(connections_to_cut) + connections_to_cut.clear() + Input.set_custom_mouse_cursor(null) + drag_cut_line.clear() + conns.clear() + queue_redraw() + cut_drag_finished.emit() + +#region mobile-specific + +func force_selection_end() -> void: + var e : InputEventMouseButton = InputEventMouseButton.new() + e.pressed = false + e.button_index = MOUSE_BUTTON_LEFT + e.position = get_local_mouse_position() + Input.parse_input_event(e) + +#endregion func align_start() -> void: var nodes : Array = get_selected_nodes() var min_offset : float = INF diff --git a/material_maker/panels/graph_edit/graph_edit.tscn b/material_maker/panels/graph_edit/graph_edit.tscn index 59333b1487..489e982315 100644 --- a/material_maker/panels/graph_edit/graph_edit.tscn +++ b/material_maker/panels/graph_edit/graph_edit.tscn @@ -23,14 +23,12 @@ atlas = ExtResource("2") region = Rect2(0, 48, 16, 16) [node name="GraphEdit" type="GraphEdit" unique_id=909518343 groups=["mm_graphedit"]] -anchors_preset = 15 +anchors_preset = -1 anchor_right = 1.0 anchor_bottom = 1.0 offset_top = -1.0 offset_right = 1529.0 offset_bottom = 1193.0 -grow_horizontal = 2 -grow_vertical = 2 grid_pattern = 1 snapping_distance = 24 right_disconnects = true diff --git a/material_maker/panels/graph_edit/node_actions_panel.gd b/material_maker/panels/graph_edit/node_actions_panel.gd new file mode 100644 index 0000000000..f79257bd3d --- /dev/null +++ b/material_maker/panels/graph_edit/node_actions_panel.gd @@ -0,0 +1,360 @@ +class_name NodeActionsPanel +extends PanelContainer + +## floating panel for node titlebar actions, mainly for touch. + +static var sb_selection : StyleBoxFlat + +const BUTTON_SIZE : Vector2 = Vector2(16, 16) +const H_PAD : int = 16 +const AREA_PAD : int = 24 +const PADDING : Vector2 = Vector2(AREA_PAD + H_PAD, -AREA_PAD) +const AVOID_PAD : int = 12 + +var parent : MMGraphEdit +var selection_area : Rect2 + +var is_updating : bool = false +var is_theme_updating : bool = false + +var selected_nodes : Array + +var container : VBoxContainer +var buttons : Dictionary[String, ActionButton] + +func _init(graph : MMGraphEdit) -> void: + name = "NodeActionsPanel" + parent = graph + parent.add_child(self) + scale = Vector2(2.5, 2.5) + top_level = true + +func _ready() -> void: + hide() + init_stylebox() + setup_signals() + + container = VBoxContainer.new() + add_child(container) + create_buttons() + + theme_type_variation = "MM_PanelMenuSubPanel" + +func _notification(what : int) -> void: + if what == NOTIFICATION_THEME_CHANGED: + if not is_node_ready(): + await ready + update_button_icons() + update_stylebox() + +func _input(event : InputEvent) -> void: + if is_visible_in_tree() and event is InputEventPanGesture and event.delta.length(): + hide_panel() + +func viewport_focus_changed(c : Control) -> void: + if visible and c.owner and c.owner.get_script() in [GradientPopup, GradientEdit]: + hide_panel() + +func setup_signals() -> void: + get_viewport().gui_focus_changed.connect(viewport_focus_changed) + parent.node_selected.connect(should_panel_update.unbind(1)) + parent.scroll_offset_changed.connect(should_panel_update.unbind(1)) + parent.node_deselected.connect(hide_panel.unbind(1)) + parent.begin_node_move.connect(hide_panel) + parent.connection_drag_started.connect(hide_panel.unbind(3)) + parent.draw.connect(draw_selection_area) + +class ActionButton extends Button: + ## Emitted when button is right clicked (long pressed for touch) + signal on_show_popup + + func _gui_input(event : InputEvent) -> void: + if event is InputEventMouseButton and event.pressed: + if event.button_index == MOUSE_BUTTON_RIGHT: + on_show_popup.emit() + + func disconnect_actions() -> void: + for s in [ pressed, on_show_popup ]: + for connection in s.get_connections(): + if s.is_connected(connection.callable): + s.disconnect(connection.callable) + + func connect_actions(pressed_callback : Callable = Callable(), + popup_callback : Callable = Callable()) -> void: + disconnect_actions() + if visible: + if pressed_callback != Callable() and not pressed.is_connected(pressed_callback): + pressed.connect(pressed_callback) + if popup_callback != Callable() and not on_show_popup.is_connected(popup_callback): + on_show_popup.connect(popup_callback) + +#region panel creation/update + +func input_released() -> void: + while Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): + if visible and Input.is_key_pressed(KEY_SHIFT): + hide() + await get_tree().process_frame + await get_tree().process_frame + +func create_panel() -> void: + if not is_node_ready(): + return + await input_released() + + selected_nodes = parent.get_selected_nodes() + if selected_nodes.is_empty(): + return hide_panel() + + for button : ActionButton in container.get_children(): + button.show() + + var nodes_rect : Rect2 = Rect2(0, 0, -1, -1) + for n in selected_nodes: + if nodes_rect.size == Vector2(-1, -1): + nodes_rect = calc_node_rect(n) + else: + nodes_rect = nodes_rect.merge(calc_node_rect(n)) + + if not n.tree_exiting.is_connected(should_panel_update): + n.tree_exiting.connect(should_panel_update) + + global_position = nodes_rect.get_support(Vector2(1, -1)) + parent.global_position + + if selected_nodes.size() == 1: + selection_area = Rect2() + global_position.x += AREA_PAD + + var node : GraphElement = selected_nodes[0] + var gen : MMGenBase = node.generator + + if is_node_simple(node): + buttons.minimize.hide() + buttons.randomize.hide() + buttons.generic.hide() + buttons.custom.hide() + + if node is MMGraphSwitch: + buttons.custom.show() + buttons.custom.connect_actions(node_switch_edit.bind(node)) + + if should_node_panel_center(node): + var local_p : Vector2 = node.position + local_p.x += node.size.x * 0.5 * parent.zoom - size.x - 6.0 + local_p.y += (node.size.y + H_PAD) * parent.zoom + global_position = parent.global_position + local_p + else: + buttons.close.visible = should_close_visible(gen) + buttons.randomize.visible = should_random_visible(gen) + buttons.generic.visible = should_generic_visible(gen) + buttons.custom.visible = should_custom_visible(gen) + + buttons.randomize.connect_actions(node.on_randomness_pressed, node.randomness_button_create_popup) + buttons.generic.connect_actions(node.on_generic_pressed, node.generic_button_create_popup) + buttons.custom.connect_actions(node.edit_generator, node.custom_button_create_popup) + + elif selected_nodes.size() > 1: + selection_area = nodes_rect + global_position += PADDING + + buttons.close.visible = node_selection_can_be_deleted() + buttons.randomize.visible = node_selection_has_randomness() + buttons.generic.visible = false + buttons.custom.visible = false + + buttons.randomize.connect_actions(randomize_selected_nodes) + + size = get_combined_minimum_size() + + avoid_intersecting_popups() + set_top_level() + show_panel() + +func is_node_simple(node : GraphElement) -> bool: + return node.get_script() in [ MMGraphPortal, MMGraphReroute, + MMGraphCommentLine, MMGraphSwitch, MMGraphComment, + MMGraphDebug, MMGraphNodeRemote ] + +func should_node_panel_center(node : GraphElement) -> bool: + return node.get_script() in [ MMGraphPortal, MMGraphReroute, + MMGraphCommentLine ] + +func set_top_level() -> void: + # have panel visible only within graph bounds + var prev : Vector2 = global_position + var graph_rect : Rect2 = parent.get_global_rect() + var panel_rect : Rect2 = get_global_rect() + + # account for graph scrollbars width/height + var wh : int = -get_theme_stylebox("scroll").border_width_left * 2.0 - 6.0 + graph_rect = graph_rect.grow_individual(0.0, 0.0, wh, wh) + + # avoid covering subgraph menu and graph menubar + var graph_menu : ScrollContainer = mm_globals.main_window.projects_panel.get_node("MenuBar") + var intersect_subgraph_ui : bool = parent.subgraph_ui.get_global_rect().intersects(panel_rect) + var intersect_graph_menu : bool = graph_menu.get_global_rect().intersects(panel_rect) + + top_level = graph_rect.encloses(panel_rect) and not (intersect_subgraph_ui or intersect_graph_menu) + global_position = prev + +var _gradient_edits : Array[Node] + +func avoid_intersecting_popups() -> void: + # avoid intersecting with GradientEdit's popup + if selected_nodes.size() != 1 or not selected_nodes[0]: + return + var node : GraphElement = selected_nodes[0] + var popup : GradientPopup + + var edits : Array[Node] = node.find_children("*", "GradientEdit", true, false) + if edits.hash() != _gradient_edits.hash(): + _gradient_edits = edits + + for edit in _gradient_edits: + if edit and is_instance_valid(edit.popup): + popup = edit.popup + break + + if not popup: + return + var panel_r : Rect2 = get_global_rect() + var popup_r : Rect2 = popup.get_global_rect() + if panel_r.intersects(popup_r): + global_position.y = popup_r.position.y - panel_r.size.y - AVOID_PAD + +func should_panel_update() -> void: + if is_updating: + return + is_updating = true + create_panel.call_deferred() + +func show_panel() -> void: + show() + move_to_front() + parent.queue_redraw() + is_updating = false + +func hide_panel() -> void: + hide() + selection_area = Rect2() + parent.queue_redraw() + is_updating = false + +func calc_node_rect(n : GraphElement) -> Rect2: + if n is MMGraphPortal: + var r : Rect2 = n.get_rect_with_link() + return Rect2(r.position * parent.zoom + n.position, + r.size * parent.zoom) + return Rect2(n.position, n.size * parent.zoom) + +#endregion + +#region generator conditionals/functions + +func node_switch_edit(node : MMGraphSwitch) -> void: + node.generator.toggle_editable() + node.update_node() + +func node_selection_has_generic() -> bool: + for node in selected_nodes: + if should_generic_visible(node.generator): + return true + return false + +func node_selection_has_randomness() -> bool: + for node in selected_nodes: + if should_random_visible(node.generator): + return true + return false + +func node_selection_can_be_deleted() -> bool: + for node in selected_nodes: + if should_close_visible(node.generator): + return true + return false + +func randomize_selected_nodes() -> void: + parent.undoredo.start_group() + for node in selected_nodes: + if should_random_visible(node.generator): + node.on_randomness_pressed() + parent.undoredo.end_group() + +func should_close_visible(g : MMGenBase) -> bool: + return g and g.can_be_deleted() + +func should_random_visible(g : MMGenBase) -> bool: + return g and g.has_randomness() + +func should_generic_visible(g : MMGenBase) -> bool: + return g and g.has_method("is_generic") and g.is_generic() + +func should_custom_visible(g : MMGenBase) -> bool: + return g and g.model == null and (g is MMGenShader or g is MMGenGraph) + +#endregion + +#region area stylebox draw/update + +func init_stylebox() -> void: + if not sb_selection: + sb_selection = StyleBoxFlat.new() + sb_selection.set_border_width_all(2) + sb_selection.set_corner_radius_all(4) + sb_selection.corner_detail = 4 + +func update_stylebox() -> void: + if not sb_selection: + init_stylebox() + + match ThemeUtils.current_theme: + ThemeUtils.CUSTOM_THEME: + sb_selection.bg_color = ThemeUtils.base_color.darkened(0.5) + sb_selection.border_color = ThemeUtils.base_color.lightened(0.2) + ThemeUtils.CLASSIC_THEME: + sb_selection.bg_color = Color(0.22, 0.255, 0.36, 1.0) + sb_selection.border_color = Color(0.377, 0.482, 0.65, 1.0) + ThemeUtils.DARK_THEME: + sb_selection.bg_color = Color(0.14, 0.14, 0.14, 1.0) + sb_selection.border_color = Color(0.355, 0.355, 0.355, 1.0) + ThemeUtils.LIGHT_THEME: + sb_selection.bg_color = Color(0.62, 0.62, 0.62, 1.0) + sb_selection.border_color = Color(0.33, 0.33, 0.33, 1.0) + +func draw_selection_area() -> void: + if selection_area.size != Vector2.ZERO and sb_selection and visible: + var ci : RID = parent.get_canvas_item() + sb_selection.draw(ci, selection_area.grow(AREA_PAD)) + +#endregion + +#region button init/setup + +func create_buttons() -> void: + buttons.close = create_button(parent.remove_selection) + buttons.minimize = create_button(parent.minimize_selection) + buttons.randomize = create_button() + buttons.generic = create_button() + buttons.custom = create_button() + +func update_button_icons() -> void: + buttons.close.icon = get_theme_icon("delete_2x", "MM_Icons") + buttons.minimize.icon = get_theme_icon("minimize", "MM_Icons") + buttons.randomize.icon = get_theme_icon("randomize", "MM_Icons") + buttons.generic.icon = get_theme_icon("generic_size", "MM_Icons") + buttons.custom.icon = get_theme_icon("draw_2x", "MM_Icons") + + buttons.randomize.add_theme_color_override("icon_normal_color", Color.WHITE) + +func create_button(pressed_callback : Callable = Callable()) -> ActionButton: + var button : ActionButton = ActionButton.new() + button.custom_minimum_size = BUTTON_SIZE + button.flat = true + button.expand_icon = true + button.add_theme_color_override("icon_hover_color", Color.WHITE) + if pressed_callback != Callable(): + button.pressed.connect(pressed_callback) + container.add_child(button) + return button + +#endregion diff --git a/material_maker/panels/graph_edit/node_actions_panel.gd.uid b/material_maker/panels/graph_edit/node_actions_panel.gd.uid new file mode 100644 index 0000000000..405c05dc74 --- /dev/null +++ b/material_maker/panels/graph_edit/node_actions_panel.gd.uid @@ -0,0 +1 @@ +uid://dcre4rccoc1fw diff --git a/material_maker/panels/library/library.gd b/material_maker/panels/library/library.gd index 3ecf3f1efa..3f5b89fa51 100644 --- a/material_maker/panels/library/library.gd +++ b/material_maker/panels/library/library.gd @@ -49,6 +49,15 @@ func _ready() -> void: init_expanded_items() update_tree() update_theme() + + if mm_globals.get_config("touch_optimization"): + var web_btn : Button = Button.new() + web_btn.name = "GetFromWebsite" + web_btn.pressed.connect(_on_GetFromWebsite_pressed) + $Library/Filter.add_child(web_btn) + $Library/Filter.move_child(web_btn, 1) + $Library/GetFromWebsite.hide() + func _notification(what: int) -> void: if what == NOTIFICATION_THEME_CHANGED: @@ -59,6 +68,8 @@ func _notification(what: int) -> void: button.icon = get_theme_icon("section_" + s.to_lower(), "MM_Icons") update_category_button_styleboxes(button, s) update_theme() + if mm_globals.get_config("touch_optimization"): + $Library/Filter.get_node("GetFromWebsite").icon = get_theme_icon("download", "MM_Icons") func update_theme() -> void: libraries_button.icon = get_theme_icon("settings", "MM_Icons") diff --git a/material_maker/panels/library/library.tscn b/material_maker/panels/library/library.tscn index 3b9143afcc..8bfece0610 100644 --- a/material_maker/panels/library/library.tscn +++ b/material_maker/panels/library/library.tscn @@ -90,8 +90,10 @@ item_5/id = 5 [connection signal="text_changed" from="Library/Filter/Filter" to="." method="_on_Filter_text_changed"] [connection signal="about_to_popup" from="Library/Filter/Libraries" to="." method="_on_Libraries_about_to_show"] +[connection signal="gui_input" from="Library/Tree" to="Library/Tree" method="_on_gui_input"] [connection signal="item_collapsed" from="Library/Tree" to="." method="_on_Tree_item_collapsed"] [connection signal="item_mouse_selected" from="Library/Tree" to="." method="_on_tree_item_mouse_selected"] +[connection signal="ready" from="Library/Tree" to="Library/Tree" method="_on_ready"] [connection signal="pressed" from="Library/GetFromWebsite" to="." method="_on_GetFromWebsite_pressed"] [connection signal="about_to_popup" from="ItemMenu" to="Library" method="_on_PopupMenu_about_to_show"] [connection signal="index_pressed" from="ItemMenu" to="." method="_on_PopupMenu_index_pressed"] diff --git a/material_maker/panels/library/library_tree.gd b/material_maker/panels/library/library_tree.gd index 6cc8e56139..df7457ffa5 100644 --- a/material_maker/panels/library/library_tree.gd +++ b/material_maker/panels/library/library_tree.gd @@ -2,7 +2,16 @@ extends Tree @export var supports_drag : bool = true -var scroll_position = 0.0 +var force_drag_started : bool + +var tree_scrollbar : VScrollBar + +func _on_ready() -> void: + for node in get_children(true): + if node is VScrollBar: + tree_scrollbar = node + if mm_globals.get_config("touch_optimization"): + %Tree.add_theme_constant_override("v_separation", 4) func get_last_item(parent : TreeItem): while true: @@ -13,7 +22,7 @@ func get_last_item(parent : TreeItem): return parent parent = items.back() -func _draw(): +func _draw() -> void: if get_root() == null: return var last_tree_item = get_last_item(get_root()) @@ -33,14 +42,37 @@ func _draw(): draw_rect(Rect2(1, rect.position.y, 4, last_rect.position.y-rect.position.y+last_rect.size.y), color) item = item.get_next() -func _get_drag_data(_position): - if !supports_drag: +func _get_drag_data(_position) -> Variant: + var _data_preview : Dictionary = _get_data_preview() + if _data_preview.is_empty(): return null + else: + set_drag_preview(_data_preview.preview) + return _data_preview.data + +func _on_gui_input(event : InputEvent) -> void: + if not force_drag_started: + if event is InputEventScreenDrag and event.index == 0: + var icon_rect : Rect2 = get_item_area_rect(get_selected(), 1) + icon_rect = icon_rect.grow_individual(6, 0, 6, 0) + if icon_rect.has_point(get_local_mouse_position()): + ## 1-finger item drag from library + _force_drag() + accept_event() + elif event is InputEventScreenTouch and event.index == 0: + if not event.pressed and mm_touch.last_touch_duration_msec > 120: + deselect_all() + + if OS.get_name() == "Android" and event is InputEventPanGesture: + tree_scrollbar.value += event.delta.y * 2.0 + accept_event() + +func _get_data_preview() -> Dictionary: var selected_item = get_selected() if selected_item != null: var data = selected_item.get_metadata(0) if data == null: - return null + return {} var preview : Control var preview_texture = selected_item.get_icon(1) if preview_texture != null: @@ -55,6 +87,22 @@ func _get_drag_data(_position): else: preview = Label.new() preview.text = data.tree_item - set_drag_preview(preview) - return data - return null + + if mm_globals.get_config("touch_optimization"): + var offset : Vector2 = Vector2.ZERO + preview.scale = Vector2(1.5, 1.5) + offset = preview_texture.get_size() if preview_texture else preview.size + preview.offset_transform_enabled = true + preview.offset_transform_position = -offset * 0.5 + + return { "preview": preview, "data": data } + return {} + +func _force_drag() -> void: + if force_drag_started: + return + force_drag_started = true + var drag_data = _get_data_preview() + if not drag_data.is_empty(): + force_drag(drag_data.data, drag_data.preview) + force_drag_started = false diff --git a/material_maker/panels/preview_2d/control_point.gd b/material_maker/panels/preview_2d/control_point.gd index 701dd7a0c7..8f76c07a94 100644 --- a/material_maker/panels/preview_2d/control_point.gd +++ b/material_maker/panels/preview_2d/control_point.gd @@ -19,6 +19,8 @@ var parent_control_node = null var children_control_nodes = [] func _ready() -> void: + if mm_globals.get_config("touch_optimization"): + custom_minimum_size = size * 1.5 if parent_control != "": parent_control_node = get_parent().get_node(parent_control) if parent_control_node != null: diff --git a/material_maker/panels/preview_2d/control_point.tscn b/material_maker/panels/preview_2d/control_point.tscn index 0084844371..1fe7fbaaea 100644 --- a/material_maker/panels/preview_2d/control_point.tscn +++ b/material_maker/panels/preview_2d/control_point.tscn @@ -5,6 +5,7 @@ [node name="Point" type="TextureRect"] mouse_filter = 0 mouse_default_cursor_shape = 13 +stretch_mode = 3 script = ExtResource("1") [connection signal="gui_input" from="." to="." method="_on_Point_gui_input"] diff --git a/material_maker/panels/preview_2d/export_menu.gd b/material_maker/panels/preview_2d/export_menu.gd index 5d4efb1f6d..52c41694ae 100644 --- a/material_maker/panels/preview_2d/export_menu.gd +++ b/material_maker/panels/preview_2d/export_menu.gd @@ -113,7 +113,7 @@ func get_export_resolution() -> Vector2i: func _on_image_pressed() -> void: - var path: String = %ExportFolder.text + var path : String = %ExportFolder.text var file_name: String = %ExportFile.text if file_name: diff --git a/material_maker/panels/preview_2d/preview_2d_panel.gd b/material_maker/panels/preview_2d/preview_2d_panel.gd index b533ba1640..2f2a8478dd 100644 --- a/material_maker/panels/preview_2d/preview_2d_panel.gd +++ b/material_maker/panels/preview_2d/preview_2d_panel.gd @@ -57,6 +57,9 @@ var checker_brightness: int = 1: material.set_shader_parameter("background_color_2", color_b) mm_globals.set_config("preview"+config_var_suffix+"_checker_brightness", checker_brightness) +const MIN_ZOOM : float = 0.005 +const MAX_ZOOM : float = 5.0 + const POSTPROCESS_OPTIONS : Array = [ { name="None", function="preview_2d(uv)" }, { name="Lowres 32x32", function="preview_2d((floor(uv*32.0)+vec2(0.5))/32.0)" }, @@ -259,6 +262,7 @@ func on_resized() -> void: var dragging : bool = false var zooming : bool = false +var magnifying : bool = false func _input(event): if event.is_pressed(): @@ -275,9 +279,9 @@ func _on_gui_input(event): if event.pressed: match event.button_index: MOUSE_BUTTON_WHEEL_DOWN: - new_scale = min(new_scale*1.05, 5.0) + new_scale = min(new_scale*1.05, MAX_ZOOM) MOUSE_BUTTON_WHEEL_UP: - new_scale = max(new_scale*0.95, 0.005) + new_scale = max(new_scale*0.95, MIN_ZOOM) MOUSE_BUTTON_MIDDLE: dragging = true MOUSE_BUTTON_LEFT: @@ -292,13 +296,21 @@ func _on_gui_input(event): if dragging: new_center = center-event.relative*view_scale/multiplier elif zooming: - new_scale = clamp(new_scale*(1.0+0.01*event.relative.y), 0.005, 5.0) - elif event is InputEventPanGesture: - new_center = center-event.delta*10.0*view_scale/multiplier + new_scale = clamp(new_scale*(1.0+0.01*event.relative.y), MIN_ZOOM, MAX_ZOOM) elif event is InputEventMagnifyGesture: - new_scale = clamp(new_scale/event.factor, 0.005, 5.0) + magnifying = true + new_scale = clampf(new_scale / event.factor, MIN_ZOOM, MAX_ZOOM) + elif event is InputEventScreenTouch and event.index == 1: + # two-finger tap: center view + if not event.pressed and mm_touch.last_touch_duration_msec < 80: + reset_view.call_deferred() + elif event is InputEventScreenDrag and event.index == 0: + new_center = center-event.relative * view_scale/multiplier + else: + magnifying = false if new_scale != view_scale: - new_center = center+offset_from_center*(view_scale-new_scale)/multiplier + if not magnifying: + new_center = center+offset_from_center*(view_scale-new_scale)/multiplier view_scale = new_scale need_update = true if new_center != center: diff --git a/material_maker/panels/preview_2d/preview_2d_panel.tscn b/material_maker/panels/preview_2d/preview_2d_panel.tscn index 08467621f2..28f86f2c6b 100644 --- a/material_maker/panels/preview_2d/preview_2d_panel.tscn +++ b/material_maker/panels/preview_2d/preview_2d_panel.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=30 format=3 uid="uid://b7x7yqgsurxhv"] +[gd_scene format=3 uid="uid://b7x7yqgsurxhv"] [ext_resource type="Texture2D" uid="uid://c0j4px4n72di5" path="res://material_maker/icons/icons.tres" id="1"] [ext_resource type="PackedScene" uid="uid://est6pi7xbptp" path="res://material_maker/panels/preview_2d/control_point.tscn" id="2"] @@ -19,7 +19,7 @@ [ext_resource type="Script" uid="uid://pielyrq85378" path="res://material_maker/panels/preview_2d/two_icon_toggle_button.gd" id="17_07kc5"] [ext_resource type="FontFile" uid="uid://lro0qdrhfytt" path="res://material_maker/theme/font_rubik/Rubik-Light.ttf" id="18_kn37y"] -[sub_resource type="Shader" id="Shader_0mwcg"] +[sub_resource type="Shader" id="Shader_r76ng"] resource_local_to_scene = true code = "shader_type canvas_item; @@ -47,9 +47,9 @@ void fragment() { } " -[sub_resource type="ShaderMaterial" id="2"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_63a3x"] resource_local_to_scene = true -shader = SubResource("Shader_0mwcg") +shader = SubResource("Shader_r76ng") shader_parameter/preview_2d_size = Vector2(100, 100) shader_parameter/preview_2d_scale = 1.655 shader_parameter/preview_2d_center = Vector2(0.46, 0.56) @@ -95,15 +95,14 @@ keycode = 69 [sub_resource type="Shortcut" id="Shortcut_llf02"] events = [SubResource("InputEventKey_rhw4u")] -[node name="Preview2D" node_paths=PackedStringArray("shortcut_context") instance=ExtResource("3")] -material = SubResource("2") +[node name="Preview2D" unique_id=415203794 node_paths=PackedStringArray("shortcut_context") instance=ExtResource("3")] +material = SubResource("ShaderMaterial_63a3x") custom_minimum_size = Vector2(100, 100) +anchors_preset = -1 offset_left = 8.0 offset_top = -5.0 offset_right = 481.0 offset_bottom = 414.0 -grow_horizontal = 2 -grow_vertical = 2 shortcut_context = NodePath(".") color = Color(1, 1, 1, 0) script = ExtResource("4") @@ -165,21 +164,21 @@ void fragment() { } " -[node name="Guides" type="Control" parent="." index="0"] +[node name="Guides" type="Control" parent="." index="0" unique_id=1437580332] anchors_preset = 0 anchor_right = 1.0 anchor_bottom = 1.0 mouse_filter = 2 script = ExtResource("5") -[node name="Axes" type="Control" parent="." index="1"] +[node name="Axes" type="Control" parent="." index="1" unique_id=1769337482] visible = false anchors_preset = 0 offset_right = 40.0 offset_bottom = 40.0 script = ExtResource("3_r76ng") -[node name="PolygonEditor" parent="." index="2" instance=ExtResource("4_gd40d")] +[node name="PolygonEditor" parent="." index="2" unique_id=1840385301 instance=ExtResource("4_gd40d")] visible = false layout_mode = 1 offset_right = 0.0 @@ -187,25 +186,25 @@ offset_bottom = 0.0 draw_area = false auto_rescale = false -[node name="SplinesEditor" parent="." index="3" instance=ExtResource("5_5hlfo")] +[node name="SplinesEditor" parent="." index="3" unique_id=1375481755 instance=ExtResource("5_5hlfo")] visible = false layout_mode = 1 draw_area = false draw_control_lines = true -[node name="PixelsEditor" parent="." index="4" instance=ExtResource("6_m4663")] +[node name="PixelsEditor" parent="." index="4" unique_id=362722278 instance=ExtResource("6_m4663")] visible = false layout_mode = 1 draw_area = false alpha = 0.5 -[node name="LatticeEditor" parent="." index="5" instance=ExtResource("7_u2w4r")] +[node name="LatticeEditor" parent="." index="5" unique_id=1404568824 instance=ExtResource("7_u2w4r")] visible = false layout_mode = 1 offset_right = 0.0 offset_bottom = 0.0 -[node name="P1" parent="." index="6" instance=ExtResource("2")] +[node name="P1" parent="." index="6" unique_id=1765205436 instance=ExtResource("2")] visible = false self_modulate = Color(1, 0.466667, 0, 1) layout_mode = 0 @@ -215,7 +214,7 @@ offset_right = 37.0 offset_bottom = 61.0 texture = SubResource("3") -[node name="P2" parent="." index="7" instance=ExtResource("2")] +[node name="P2" parent="." index="7" unique_id=1580629670 instance=ExtResource("2")] visible = false self_modulate = Color(0, 0.505882, 1, 1) layout_mode = 0 @@ -225,7 +224,7 @@ offset_right = 37.0 offset_bottom = 61.0 texture = SubResource("3") -[node name="P11" parent="." index="8" instance=ExtResource("2")] +[node name="P11" parent="." index="8" unique_id=1205963807 instance=ExtResource("2")] visible = false self_modulate = Color(0, 0.505882, 1, 1) layout_mode = 0 @@ -237,7 +236,7 @@ texture = SubResource("3") parent_control = "P1" apply_local_transform = true -[node name="RadiusP11" parent="." index="9" instance=ExtResource("2")] +[node name="RadiusP11" parent="." index="9" unique_id=1589820436 instance=ExtResource("2")] visible = false self_modulate = Color(1, 0.631373, 0, 1) layout_mode = 0 @@ -250,7 +249,7 @@ texture = SubResource("4") parent_control = "P11" control_type = 2 -[node name="P12" parent="." index="10" instance=ExtResource("2")] +[node name="P12" parent="." index="10" unique_id=249875203 instance=ExtResource("2")] visible = false self_modulate = Color(0, 0.505882, 1, 1) layout_mode = 0 @@ -262,7 +261,7 @@ texture = SubResource("3") parent_control = "P1" apply_local_transform = true -[node name="P3" parent="." index="11" instance=ExtResource("2")] +[node name="P3" parent="." index="11" unique_id=1688060177 instance=ExtResource("2")] visible = false self_modulate = Color(0, 1, 0.380392, 1) layout_mode = 0 @@ -272,7 +271,7 @@ offset_right = 21.0 offset_bottom = 45.0 texture = SubResource("4") -[node name="Rect1" parent="." index="12" instance=ExtResource("2")] +[node name="Rect1" parent="." index="12" unique_id=844748247 instance=ExtResource("2")] visible = false self_modulate = Color(1, 0.631373, 0, 1) layout_mode = 0 @@ -285,7 +284,7 @@ parent_control = "P1" control_type = 1 apply_local_transform = true -[node name="Radius1" parent="." index="13" instance=ExtResource("2")] +[node name="Radius1" parent="." index="13" unique_id=1399381492 instance=ExtResource("2")] visible = false self_modulate = Color(1, 0.631373, 0, 1) layout_mode = 0 @@ -298,7 +297,7 @@ texture = SubResource("4") parent_control = "P1" control_type = 2 -[node name="Radius2" parent="." index="14" instance=ExtResource("2")] +[node name="Radius2" parent="." index="14" unique_id=1594322313 instance=ExtResource("2")] visible = false self_modulate = Color(0, 0.505882, 1, 1) layout_mode = 0 @@ -311,7 +310,7 @@ texture = SubResource("4") parent_control = "P2" control_type = 2 -[node name="Radius11" parent="." index="15" instance=ExtResource("2")] +[node name="Radius11" parent="." index="15" unique_id=1948264432 instance=ExtResource("2")] visible = false self_modulate = Color(1, 0.631373, 0, 1) layout_mode = 0 @@ -324,7 +323,7 @@ texture = SubResource("4") parent_control = "Radius1" control_type = 2 -[node name="Scale1" parent="." index="16" instance=ExtResource("2")] +[node name="Scale1" parent="." index="16" unique_id=1543136436 instance=ExtResource("2")] visible = false self_modulate = Color(1, 0.631373, 0, 1) layout_mode = 0 @@ -337,7 +336,7 @@ texture = SubResource("4") parent_control = "P1" control_type = 3 -[node name="RotateScale1" parent="." index="17" instance=ExtResource("2")] +[node name="RotateScale1" parent="." index="17" unique_id=1073873848 instance=ExtResource("2")] visible = false self_modulate = Color(1, 0.631373, 0, 1) layout_mode = 0 @@ -350,7 +349,7 @@ texture = SubResource("4") parent_control = "P1" control_type = 4 -[node name="Angle1" parent="." index="18" instance=ExtResource("2")] +[node name="Angle1" parent="." index="18" unique_id=56837712 instance=ExtResource("2")] visible = false self_modulate = Color(1, 0.631373, 0, 1) layout_mode = 0 @@ -363,7 +362,7 @@ texture = SubResource("4") parent_control = "P1" control_type = 2 -[node name="Angle2" parent="." index="19" instance=ExtResource("2")] +[node name="Angle2" parent="." index="19" unique_id=1272609448 instance=ExtResource("2")] visible = false self_modulate = Color(1, 0.631373, 0, 1) layout_mode = 0 @@ -376,7 +375,7 @@ texture = SubResource("4") parent_control = "P1" control_type = 2 -[node name="Accumulate" type="SubViewport" parent="." index="20"] +[node name="Accumulate" type="SubViewport" parent="." index="20" unique_id=68447703] disable_3d = true handle_input_locally = false gui_snap_controls_to_pixels = false @@ -384,12 +383,12 @@ size = Vector2i(2, 2) render_target_clear_mode = 1 render_target_update_mode = 1 -[node name="Iteration" type="ColorRect" parent="Accumulate" index="0"] +[node name="Iteration" type="ColorRect" parent="Accumulate" index="0" unique_id=824547017] material = SubResource("6") offset_right = 40.0 offset_bottom = 40.0 -[node name="MenuBar" type="ScrollContainer" parent="." index="21"] +[node name="MenuBar" type="ScrollContainer" parent="." index="21" unique_id=1082056955] unique_name_in_owner = true clip_contents = false layout_mode = 1 @@ -402,21 +401,21 @@ theme_type_variation = &"MM_PanelMenuBackground" horizontal_scroll_mode = 3 vertical_scroll_mode = 0 -[node name="HBox" type="HFlowContainer" parent="MenuBar" index="0"] +[node name="HBox" type="HFlowContainer" parent="MenuBar" index="0" unique_id=182327461] layout_mode = 2 size_flags_horizontal = 3 mouse_filter = 2 -[node name="MainMenu" type="PanelContainer" parent="MenuBar/HBox" index="0"] +[node name="MainMenu" type="PanelContainer" parent="MenuBar/HBox" index="0" unique_id=398954274] layout_mode = 2 size_flags_vertical = 0 theme_type_variation = &"MM_PanelMenuBar" -[node name="HBox" type="HBoxContainer" parent="MenuBar/HBox/MainMenu" index="0"] +[node name="HBox" type="HBoxContainer" parent="MenuBar/HBox/MainMenu" index="0" unique_id=2074778138] layout_mode = 2 theme_type_variation = &"MM_PanelMenuBar" -[node name="ResetViewButton" type="Button" parent="MenuBar/HBox/MainMenu/HBox" index="0"] +[node name="ResetViewButton" type="Button" parent="MenuBar/HBox/MainMenu/HBox" index="0" unique_id=798283184] unique_name_in_owner = true custom_minimum_size = Vector2(25, 25) layout_mode = 2 @@ -428,7 +427,7 @@ icon_alignment = 1 script = ExtResource("10_83edi") icon_name = "reset_view" -[node name="ViewMenu" type="Button" parent="MenuBar/HBox/MainMenu/HBox" index="1" node_paths=PackedStringArray("shortcut_context")] +[node name="ViewMenu" type="Button" parent="MenuBar/HBox/MainMenu/HBox" index="1" unique_id=1038944622 node_paths=PackedStringArray("shortcut_context")] custom_minimum_size = Vector2(40, 25) layout_mode = 2 tooltip_text = "View" @@ -439,7 +438,7 @@ button_mask = 3 script = ExtResource("12_nrhap") icon_name = "view" -[node name="ViewMenuPanel" type="PanelContainer" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu" index="0"] +[node name="ViewMenuPanel" type="PanelContainer" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu" index="0" unique_id=1472687647] top_level = true layout_mode = 0 offset_left = 493.0 @@ -449,20 +448,20 @@ offset_bottom = 145.0 theme_type_variation = &"MM_PanelMenuSubPanel" script = ExtResource("13_5w2hy") -[node name="VBox" type="GridContainer" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel" index="0"] +[node name="VBox" type="GridContainer" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel" index="0" unique_id=1223609843] layout_mode = 2 columns = 2 -[node name="Control" type="Control" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="0"] +[node name="Control" type="Control" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="0" unique_id=92161024] visible = false layout_mode = 2 -[node name="ViewModeLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="1"] +[node name="ViewModeLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="1" unique_id=663479758] layout_mode = 2 theme_type_variation = &"MM_PanelMenuSubPanelLabel" text = "View" -[node name="ViewMode" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="2" instance=ExtResource("12_4017l")] +[node name="ViewMode" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="2" unique_id=1232097209 instance=ExtResource("12_4017l")] unique_name_in_owner = true layout_mode = 2 selected = 0 @@ -474,12 +473,12 @@ popup/item_1/id = 1 popup/item_2/text = "Clamp" popup/item_2/id = 2 -[node name="PostProcessingLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="3"] +[node name="PostProcessingLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="3" unique_id=1208707070] layout_mode = 2 theme_type_variation = &"MM_PanelMenuSubPanelLabel" text = "Filter" -[node name="PostProcessing" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="4" instance=ExtResource("12_4017l")] +[node name="PostProcessing" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="4" unique_id=1278149163 instance=ExtResource("12_4017l")] unique_name_in_owner = true layout_mode = 2 selected = 0 @@ -497,15 +496,15 @@ popup/item_4/id = 4 popup/item_5/text = "Lowres 512x512" popup/item_5/id = 5 -[node name="GuidesLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="5"] +[node name="GuidesLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="5" unique_id=2077812196] layout_mode = 2 theme_type_variation = &"MM_PanelMenuSubPanelLabel" text = "Guides" -[node name="BoxContainer" type="BoxContainer" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="6"] +[node name="BoxContainer" type="BoxContainer" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="6" unique_id=1545146403] layout_mode = 2 -[node name="Guides" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox/BoxContainer" index="0" instance=ExtResource("12_4017l")] +[node name="Guides" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox/BoxContainer" index="0" unique_id=481345934 instance=ExtResource("12_4017l")] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -520,7 +519,7 @@ popup/item_2/id = 2 popup/item_3/text = "Grid" popup/item_3/id = 3 -[node name="CustomGridSize" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox/BoxContainer" index="1" instance=ExtResource("14_qr76f")] +[node name="CustomGridSize" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox/BoxContainer" index="1" unique_id=49865437 instance=ExtResource("14_qr76f")] unique_name_in_owner = true layout_mode = 2 value = 10.0 @@ -529,20 +528,20 @@ max_value = 32.0 step = 1.0 float_only = true -[node name="GuidesColor" type="ColorPickerButton" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox/BoxContainer" index="2"] +[node name="GuidesColor" type="ColorPickerButton" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox/BoxContainer" index="2" unique_id=119437571] unique_name_in_owner = true custom_minimum_size = Vector2(32, 0) layout_mode = 2 -[node name="AlphaLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="7"] +[node name="AlphaLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="7" unique_id=1462781046] layout_mode = 2 theme_type_variation = &"MM_PanelMenuSubPanelLabel" text = "Alpha" -[node name="BoxContainer2" type="BoxContainer" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="8"] +[node name="BoxContainer2" type="BoxContainer" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox" index="8" unique_id=513106806] layout_mode = 2 -[node name="CheckerBrightness" type="OptionButton" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox/BoxContainer2" index="0"] +[node name="CheckerBrightness" type="OptionButton" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox/BoxContainer2" index="0" unique_id=830063006] unique_name_in_owner = true layout_mode = 2 tooltip_text = "Transparency checkers brightness" @@ -555,7 +554,7 @@ popup/item_1/id = 1 popup/item_2/text = "Dark" popup/item_2/id = 2 -[node name="CheckerSize" type="OptionButton" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox/BoxContainer2" index="1"] +[node name="CheckerSize" type="OptionButton" parent="MenuBar/HBox/MainMenu/HBox/ViewMenu/ViewMenuPanel/VBox/BoxContainer2" index="1" unique_id=1281944466] unique_name_in_owner = true layout_mode = 2 tooltip_text = "Transparency checkers size" @@ -568,7 +567,7 @@ popup/item_1/id = 1 popup/item_2/text = "Large" popup/item_2/id = 2 -[node name="ExportMenu" type="Button" parent="MenuBar/HBox/MainMenu/HBox" index="2" node_paths=PackedStringArray("shortcut_context")] +[node name="ExportMenu" type="Button" parent="MenuBar/HBox/MainMenu/HBox" index="2" unique_id=372091705 node_paths=PackedStringArray("shortcut_context")] unique_name_in_owner = true custom_minimum_size = Vector2(40, 25) layout_mode = 2 @@ -580,7 +579,7 @@ button_mask = 3 script = ExtResource("12_nrhap") icon_name = "export" -[node name="ExportMenuPanel" type="PanelContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu" index="0"] +[node name="ExportMenuPanel" type="PanelContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu" index="0" unique_id=1894299873] top_level = true custom_minimum_size = Vector2(320, 0) layout_mode = 0 @@ -591,50 +590,50 @@ offset_bottom = 380.0 theme_type_variation = &"MM_PanelMenuSubPanel" script = ExtResource("16_0fl4g") -[node name="VBox" type="BoxContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel" index="0"] +[node name="VBox" type="BoxContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel" index="0" unique_id=56797128] layout_mode = 2 vertical = true -[node name="Grid" type="GridContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox" index="0"] +[node name="Grid" type="GridContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox" index="0" unique_id=951766683] layout_mode = 2 columns = 2 -[node name="ExportFolderLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid" index="0"] +[node name="ExportFolderLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid" index="0" unique_id=222750042] layout_mode = 2 theme_type_variation = &"MM_PanelMenuSubPanelLabel" text = "Folder" -[node name="ExportFolder" type="BoxContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid" index="1"] +[node name="ExportFolder" type="BoxContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid" index="1" unique_id=445756125] layout_mode = 2 theme_override_constants/separation = 2 -[node name="ExportFolder" type="LineEdit" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ExportFolder" index="0"] +[node name="ExportFolder" type="LineEdit" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ExportFolder" index="0" unique_id=1924452745] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 theme_override_font_sizes/font_size = 15 -[node name="ExportFolderButton" type="Button" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ExportFolder" index="1"] +[node name="ExportFolderButton" type="Button" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ExportFolder" index="1" unique_id=1318426978] unique_name_in_owner = true custom_minimum_size = Vector2(25, 25) layout_mode = 2 icon_alignment = 1 -[node name="ExportFileLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid" index="2"] +[node name="ExportFileLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid" index="2" unique_id=1748884565] layout_mode = 2 size_flags_vertical = 0 theme_type_variation = &"MM_PanelMenuSubPanelLabel" text = "File Name" -[node name="ExportFile" type="BoxContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid" index="3"] +[node name="ExportFile" type="BoxContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid" index="3" unique_id=2132902207] layout_mode = 2 theme_override_constants/separation = 2 vertical = true -[node name="BoxContainer" type="BoxContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ExportFile" index="0"] +[node name="BoxContainer" type="BoxContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ExportFile" index="0" unique_id=183570309] layout_mode = 2 -[node name="ExportFile" type="LineEdit" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ExportFile/BoxContainer" index="0"] +[node name="ExportFile" type="LineEdit" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ExportFile/BoxContainer" index="0" unique_id=1326714374] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -644,7 +643,7 @@ You can use $project, $node, $idx and $resolution to make the file-name auto-adj theme_override_font_sizes/font_size = 15 text = "$project_$node" -[node name="FileType" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ExportFile/BoxContainer" index="1" instance=ExtResource("12_4017l")] +[node name="FileType" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ExportFile/BoxContainer" index="1" unique_id=854524278 instance=ExtResource("12_4017l")] unique_name_in_owner = true layout_mode = 2 selected = 0 @@ -654,22 +653,22 @@ popup/item_0/id = 0 popup/item_1/text = ".exr" popup/item_1/id = 1 -[node name="ExportFileResultLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ExportFile" index="1"] +[node name="ExportFileResultLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ExportFile" index="1" unique_id=1095061228] unique_name_in_owner = true layout_mode = 2 theme_type_variation = &"MM_PanelMenuSubPanelLabel" theme_override_fonts/font = SubResource("FontVariation_wkuuo") -[node name="ResolutionLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid" index="4"] +[node name="ResolutionLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid" index="4" unique_id=888000205] layout_mode = 2 theme_type_variation = &"MM_PanelMenuSubPanelLabel" text = "Resolution" -[node name="ResolutionSection" type="BoxContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid" index="5"] +[node name="ResolutionSection" type="BoxContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid" index="5" unique_id=1471406219] unique_name_in_owner = true layout_mode = 2 -[node name="Resolution" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ResolutionSection" index="0" instance=ExtResource("12_4017l")] +[node name="Resolution" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ResolutionSection" index="0" unique_id=98709583 instance=ExtResource("12_4017l")] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -694,12 +693,12 @@ popup/item_7/id = 7 popup/item_8/text = "Custom" popup/item_8/id = 8 -[node name="CustomResolutionSection" type="BoxContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ResolutionSection" index="1"] +[node name="CustomResolutionSection" type="BoxContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ResolutionSection" index="1" unique_id=143731711] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 -[node name="CustomResolutionX" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ResolutionSection/CustomResolutionSection" index="0" instance=ExtResource("14_qr76f")] +[node name="CustomResolutionX" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ResolutionSection/CustomResolutionSection" index="0" unique_id=1990106158 instance=ExtResource("14_qr76f")] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -710,11 +709,11 @@ max_value = 2048.0 step = 1.0 float_only = true -[node name="x" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ResolutionSection/CustomResolutionSection" index="1"] +[node name="x" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ResolutionSection/CustomResolutionSection" index="1" unique_id=1904246614] layout_mode = 2 text = "x" -[node name="CustomResolutionY" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ResolutionSection/CustomResolutionSection" index="2" instance=ExtResource("14_qr76f")] +[node name="CustomResolutionY" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/ResolutionSection/CustomResolutionSection" index="2" unique_id=120110795 instance=ExtResource("14_qr76f")] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -725,42 +724,42 @@ max_value = 2048.0 step = 1.0 float_only = true -[node name="ExportLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid" index="6"] +[node name="ExportLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid" index="6" unique_id=300852845] layout_mode = 2 theme_type_variation = &"MM_PanelMenuSubPanelLabel" text = "Export" -[node name="BoxContainer" type="GridContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid" index="7"] +[node name="BoxContainer" type="GridContainer" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid" index="7" unique_id=827077119] layout_mode = 2 size_flags_horizontal = 3 columns = 2 -[node name="Image" type="Button" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/BoxContainer" index="0"] +[node name="Image" type="Button" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/BoxContainer" index="0" unique_id=1455711006] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 shortcut = SubResource("Shortcut_llf02") text = "Image" -[node name="Reference" type="Button" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/BoxContainer" index="1"] +[node name="Reference" type="Button" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/BoxContainer" index="1" unique_id=432697365] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 text = "To Reference" -[node name="Animation" type="Button" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/BoxContainer" index="2"] +[node name="Animation" type="Button" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/BoxContainer" index="2" unique_id=115406925] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 text = "Animation" -[node name="TAA_Render" type="Button" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/BoxContainer" index="3"] +[node name="TAA_Render" type="Button" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox/Grid/BoxContainer" index="3" unique_id=816810603] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 text = "TAA Render" -[node name="ExportNotificationLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox" index="1"] +[node name="ExportNotificationLabel" type="Label" parent="MenuBar/HBox/MainMenu/HBox/ExportMenu/ExportMenuPanel/VBox" index="1" unique_id=1573873066] unique_name_in_owner = true visible = false layout_mode = 2 @@ -769,7 +768,7 @@ theme_override_colors/font_color = Color(0.52, 0.52, 0.52, 1) theme_override_fonts/font = SubResource("FontVariation_wkuuo") autowrap_mode = 1 -[node name="PreviewLocked" type="Button" parent="MenuBar/HBox/MainMenu/HBox" index="3"] +[node name="PreviewLocked" type="Button" parent="MenuBar/HBox/MainMenu/HBox" index="3" unique_id=1901034297] unique_name_in_owner = true custom_minimum_size = Vector2(25, 25) layout_mode = 2 @@ -780,7 +779,7 @@ script = ExtResource("17_07kc5") icon_normal_name = "lock_unlocked" icon_pressed_name = "lock_locked" -[node name="ComplexParameters" type="OptionButton" parent="MenuBar/HBox/MainMenu/HBox" index="4"] +[node name="ComplexParameters" type="OptionButton" parent="MenuBar/HBox/MainMenu/HBox" index="4" unique_id=1709215385] unique_name_in_owner = true visible = false layout_mode = 2 @@ -788,7 +787,9 @@ layout_mode = 2 [connection signal="gui_input" from="." to="." method="_on_gui_input"] [connection signal="mouse_entered" from="." to="." method="_on_Preview2D_mouse_entered"] [connection signal="unhandled_event" from="PolygonEditor" to="." method="_on_gui_input"] -[connection signal="gui_input" from="PolygonEditor/@Control@42512" to="PolygonEditor/@Control@42512" method="_on_ControlPoint_gui_input"] +[connection signal="gui_input" from="PolygonEditor/ControlPoint" to="PolygonEditor/ControlPoint" method="_on_ControlPoint_gui_input"] +[connection signal="mouse_entered" from="PolygonEditor/ControlPoint" to="PolygonEditor/ControlPoint" method="_on_mouse_entered"] +[connection signal="mouse_exited" from="PolygonEditor/ControlPoint" to="PolygonEditor/ControlPoint" method="_on_mouse_exited"] [connection signal="unhandled_event" from="SplinesEditor" to="." method="_on_gui_input"] [connection signal="unhandled_event" from="PixelsEditor" to="." method="_on_gui_input"] [connection signal="unhandled_event" from="LatticeEditor" to="." method="_on_gui_input"] diff --git a/material_maker/panels/preview_3d/preview_3d_panel.tscn b/material_maker/panels/preview_3d/preview_3d_panel.tscn index 2aa9757625..d94fa08832 100644 --- a/material_maker/panels/preview_3d/preview_3d_panel.tscn +++ b/material_maker/panels/preview_3d/preview_3d_panel.tscn @@ -45,16 +45,15 @@ reflected_light_source = 2 environment = SubResource("Environment_qxxdb") camera_attributes = SubResource("CameraAttributesPractical_g4ldw") -[sub_resource type="ButtonGroup" id="ButtonGroup_j6uuq"] +[sub_resource type="ButtonGroup" id="ButtonGroup_jy7sc"] [node name="Preview3D" unique_id=308580129 instance=ExtResource("1")] custom_minimum_size = Vector2(250, 200) +anchors_preset = -1 offset_left = -1.0 offset_top = -2.0 offset_right = 248.0 offset_bottom = 253.0 -grow_horizontal = 2 -grow_vertical = 2 script = ExtResource("3") click_material = SubResource("2") @@ -97,16 +96,16 @@ layout_mode = 2 size_flags_horizontal = 3 [node name="Speed_Pause" parent="MainMenu/HBox/ModelMenu/ModelMenuPanel/VBoxContainer/Model/RotationSpeeds" parent_id_path=PackedInt32Array(530040303) index="0" unique_id=1158744206] -button_group = SubResource("ButtonGroup_j6uuq") +button_group = SubResource("ButtonGroup_jy7sc") [node name="Speed_Slow" parent="MainMenu/HBox/ModelMenu/ModelMenuPanel/VBoxContainer/Model/RotationSpeeds" parent_id_path=PackedInt32Array(530040303) index="1" unique_id=1454681268] -button_group = SubResource("ButtonGroup_j6uuq") +button_group = SubResource("ButtonGroup_jy7sc") [node name="Speed_Medium" parent="MainMenu/HBox/ModelMenu/ModelMenuPanel/VBoxContainer/Model/RotationSpeeds" parent_id_path=PackedInt32Array(530040303) index="2" unique_id=1024390903] -button_group = SubResource("ButtonGroup_j6uuq") +button_group = SubResource("ButtonGroup_jy7sc") [node name="Speed_Fast" parent="MainMenu/HBox/ModelMenu/ModelMenuPanel/VBoxContainer/Model/RotationSpeeds" parent_id_path=PackedInt32Array(530040303) index="3" unique_id=1976754458] -button_group = SubResource("ButtonGroup_j6uuq") +button_group = SubResource("ButtonGroup_jy7sc") [connection signal="mouse_entered" from="." to="." method="_on_Preview3D_mouse_entered"] [connection signal="resized" from="." to="." method="_on_resized"] diff --git a/material_maker/panels/preview_3d/preview_3d_scene.tscn b/material_maker/panels/preview_3d/preview_3d_scene.tscn index c845553aa7..56cb0805da 100644 --- a/material_maker/panels/preview_3d/preview_3d_scene.tscn +++ b/material_maker/panels/preview_3d/preview_3d_scene.tscn @@ -1,8 +1,7 @@ -[gd_scene load_steps=10 format=3 uid="uid://dpulty2lkvcht"] +[gd_scene format=3 uid="uid://dpulty2lkvcht"] [ext_resource type="PackedScene" uid="uid://cxcw0mi4sfl2x" path="res://material_maker/panels/preview_3d/preview_objects.tscn" id="2"] [ext_resource type="PackedScene" uid="uid://dw4wghi1pn4qr" path="res://material_maker/windows/environment_editor/camera_controller.tscn" id="2_g4ldw"] -[ext_resource type="Texture2D" uid="uid://bqre7xkdgb655" path="res://material_maker/environments/hdris/moonless_golf_1k.hdr" id="2_ks6fo"] [sub_resource type="Animation" id="3"] loop_mode = 1 @@ -24,8 +23,11 @@ _data = { &"rotate": SubResource("3") } +[sub_resource type="CompressedTexture2D" id="CompressedTexture2D_w6dyo"] +load_path = "res://.godot/imported/moonless_golf_1k.hdr-9cc5420e458979fa0268bbd265e3a765.bptc.ctex" + [sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_40ogr"] -panorama = ExtResource("2_ks6fo") +panorama = SubResource("CompressedTexture2D_w6dyo") [sub_resource type="Sky" id="Sky_wye7d"] sky_material = SubResource("PanoramaSkyMaterial_40ogr") @@ -39,31 +41,29 @@ reflected_light_source = 2 [sub_resource type="CameraAttributesPractical" id="CameraAttributesPractical_g4ldw"] -[node name="Preview3dScene" type="Node3D"] +[node name="Preview3dScene" type="Node3D" unique_id=368054269] -[node name="ObjectsPivot" type="Node3D" parent="."] +[node name="ObjectsPivot" type="Node3D" parent="." unique_id=900793287] -[node name="Objects" parent="ObjectsPivot" instance=ExtResource("2")] +[node name="Objects" parent="ObjectsPivot" unique_id=1124287291 instance=ExtResource("2")] -[node name="CameraController" parent="." instance=ExtResource("2_g4ldw")] +[node name="CameraController" parent="." unique_id=610403260 instance=ExtResource("2_g4ldw")] camera_path = NodePath("../Camera3D") -[node name="Camera3D" type="Camera3D" parent="."] +[node name="Camera3D" type="Camera3D" parent="." unique_id=1210778811] transform = Transform3D(1, 0, 0, 0, 0.766044, 0.642788, 0, -0.642788, 0.766044, 0, 2.57115, 3.06418) current = true fov = 50.0 -[node name="ObjectRotate" type="AnimationPlayer" parent="."] -libraries = { -&"": SubResource("AnimationLibrary_sxr5g") -} +[node name="ObjectRotate" type="AnimationPlayer" parent="." unique_id=2024899918] +libraries/ = SubResource("AnimationLibrary_sxr5g") -[node name="Sun" type="DirectionalLight3D" parent="."] +[node name="Sun" type="DirectionalLight3D" parent="." unique_id=1498759412] shadow_enabled = true shadow_bias = 0.03 directional_shadow_mode = 0 directional_shadow_max_distance = 5.0 -[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=502695456] environment = SubResource("Environment_qxxdb") camera_attributes = SubResource("CameraAttributesPractical_g4ldw") diff --git a/material_maker/panels/reference/reference_panel.gd b/material_maker/panels/reference/reference_panel.gd index eade101bbe..5ff2576b4b 100644 --- a/material_maker/panels/reference/reference_panel.gd +++ b/material_maker/panels/reference/reference_panel.gd @@ -43,6 +43,12 @@ func _ready(): %GradientSlot.toggled.connect(_on_slot_toggled.bind(%GradientSlot)) + if DisplayServer.is_touchscreen_available(): + %PasteImageButton.hide() + %CheckClipboardImage.stop() + %CheckClipboardImage.queue_free() + $Empty/Label.text = "Add reference image to get started" + ## This is magically called by the main window :) func on_drop_image_file(file_name: String) -> void: @@ -167,7 +173,7 @@ func _on_image_resized() -> void: %Image.material.set_shader_parameter("canvas_size", %Image.get_size()) -func _on_image_gui_input(event: InputEvent) -> void: +func _on_image_gui_input(event : InputEvent) -> void: if opened_images.is_empty(): return @@ -177,8 +183,8 @@ func _on_image_gui_input(event: InputEvent) -> void: handle_movement(event) -func handle_movement(event: InputEvent) -> void: - var m: ShaderMaterial = %Image.material +func handle_movement(event : InputEvent) -> void: + var m : ShaderMaterial = %Image.material var canvas_size : Vector2 = %Image.get_size() var image_size : Vector2 = m.get_shader_parameter("image_size") @@ -212,9 +218,12 @@ func handle_movement(event: InputEvent) -> void: elif event is InputEventMouseMotion: if is_dragging: new_center = m.get_shader_parameter("center")-event.relative*image_scale/multiplier - elif is_zooming: new_scale = clamp(new_scale*(1.0+0.01*event.relative.y), 0.005, 3) + elif event is InputEventMagnifyGesture: + new_scale = clamp(new_scale / event.factor, 0.005, 3) + elif event is InputEventScreenDrag and event.index == 0: + new_center = m.get_shader_parameter("center")-event.relative*image_scale/multiplier if new_scale != image_scale: m.set_shader_parameter("scale", new_scale) diff --git a/material_maker/panels/reference/reference_panel.tscn b/material_maker/panels/reference/reference_panel.tscn index 4877a5f569..5c992f6fce 100644 --- a/material_maker/panels/reference/reference_panel.tscn +++ b/material_maker/panels/reference/reference_panel.tscn @@ -40,13 +40,11 @@ allow_unpress = true [node name="ReferencePanel" type="Panel" unique_id=329764457] clip_children = 2 -anchors_preset = 15 +anchors_preset = -1 anchor_right = 1.0 anchor_bottom = 1.0 offset_right = 171.0 offset_bottom = 237.0 -grow_horizontal = 2 -grow_vertical = 2 theme_type_variation = &"MM_PanelBackground" script = ExtResource("1") @@ -126,6 +124,7 @@ tooltip_text = "Remove Image" icon_alignment = 1 [node name="CheckClipboardImage" type="Timer" parent="MenuBar/HBox/MainMenu/HBox" unique_id=2067403748] +unique_name_in_owner = true autostart = true [node name="ViewMenu" type="PanelContainer" parent="MenuBar/HBox" unique_id=2108939916] diff --git a/material_maker/projects_panel.tscn b/material_maker/projects_panel.tscn index 84beac16a5..57b07afa01 100644 --- a/material_maker/projects_panel.tscn +++ b/material_maker/projects_panel.tscn @@ -11,14 +11,15 @@ [ext_resource type="Script" uid="uid://bxwor0k6svci8" path="res://material_maker/panels/graph_edit/graph_view_menu.gd" id="8_nl2qi"] [ext_resource type="Script" uid="uid://pqxjwlcff5ko" path="res://material_maker/panels/graph_edit/graph_align_menu.gd" id="8_r5hxx"] [ext_resource type="ButtonGroup" uid="uid://biv6we3po8wbb" path="res://material_maker/line_style_btn_group.tres" id="10_lbgjg"] +[ext_resource type="Script" uid="uid://c7hvi7bvtgwbd" path="res://material_maker/panels/graph_edit/graph_actions_menu.gd" id="12_qnupl"] -[sub_resource type="Shader" id="Shader_r5hxx"] +[sub_resource type="Shader" id="Shader_qnupl"] resource_local_to_scene = true code = "shader_type canvas_item;" -[sub_resource type="ShaderMaterial" id="ShaderMaterial_qnupl"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_uk6aw"] resource_local_to_scene = true -shader = SubResource("Shader_r5hxx") +shader = SubResource("Shader_qnupl") [sub_resource type="InputEventKey" id="InputEventKey_r5hxx"] device = -1 @@ -75,7 +76,7 @@ theme_type_variation = &"MM_ProjectsBackground" [node name="Preview2D" parent="BackgroundPreviews" unique_id=650291010 instance=ExtResource("2_oiaqi")] visible = false -material = SubResource("ShaderMaterial_qnupl") +material = SubResource("ShaderMaterial_uk6aw") layout_mode = 1 offset_right = 64.0 offset_bottom = 64.0 @@ -419,7 +420,27 @@ icon_alignment = 1 script = ExtResource("7_qnupl") icon_name = "arrange_nodes" -[node name="AlignMenu" type="PanelContainer" parent="MenuBar/HBox" unique_id=254250138] +[node name="ActionsMenu" type="PanelContainer" parent="MenuBar/HBox" unique_id=1156734553] +layout_mode = 2 +size_flags_vertical = 0 +theme_type_variation = &"MM_PanelMenuBar" +script = ExtResource("12_qnupl") + +[node name="HBox" type="HBoxContainer" parent="MenuBar/HBox/ActionsMenu" unique_id=1846468046] +layout_mode = 2 +theme_type_variation = &"MM_PanelMenuBar" + +[node name="KnifeTool" type="Button" parent="MenuBar/HBox/ActionsMenu/HBox" unique_id=409994758] +custom_minimum_size = Vector2(25, 25) +layout_mode = 2 +tooltip_text = "Knife tool" +toggle_mode = true +shortcut_in_tooltip = false +icon_alignment = 1 +script = ExtResource("7_qnupl") +icon_name = "knife" + +[node name="AlignMenu" type="PanelContainer" parent="MenuBar/HBox" unique_id=243111021] layout_mode = 2 size_flags_vertical = 0 theme_type_variation = &"MM_PanelMenuBar" @@ -531,6 +552,7 @@ Scroll to zoom the 3D Preview." [connection signal="value_changed" from="MenuBar/HBox/MainGraphMenuBar/HBox/ViewMenu/ViewMenuPanel/VBoxContainer/VBoxContainer2/Thickness/LineThickness" to="MenuBar/HBox/MainGraphMenuBar/HBox/ViewMenu/ViewMenuPanel" method="_on_line_thickness_value_changed"] [connection signal="value_changed" from="MenuBar/HBox/MainGraphMenuBar/HBox/ViewMenu/ViewMenuPanel/VBoxContainer/VBoxContainer2/Curvature/LineCurvature" to="MenuBar/HBox/MainGraphMenuBar/HBox/ViewMenu" method="_on_line_curvature_value_changed"] [connection signal="value_changed" from="MenuBar/HBox/MainGraphMenuBar/HBox/ViewMenu/ViewMenuPanel/VBoxContainer/VBoxContainer2/Curvature/LineCurvature" to="MenuBar/HBox/MainGraphMenuBar/HBox/ViewMenu/ViewMenuPanel" method="_on_line_curvature_value_changed"] +[connection signal="toggled" from="MenuBar/HBox/ActionsMenu/HBox/KnifeTool" to="MenuBar/HBox/ActionsMenu" method="_on_knife_tool_toggled"] [connection signal="pressed" from="MenuBar/HBox/AlignMenu/HBox/AlignStart" to="MenuBar/HBox/AlignMenu" method="_on_align_start_pressed"] [connection signal="pressed" from="MenuBar/HBox/AlignMenu/HBox/AlignTop" to="MenuBar/HBox/AlignMenu" method="_on_align_top_pressed"] [connection signal="pressed" from="MenuBar/HBox/AlignMenu/HBox/AlignEnd" to="MenuBar/HBox/AlignMenu" method="_on_align_end_pressed"] diff --git a/material_maker/theme/classic_base.tres b/material_maker/theme/classic_base.tres index edbf134c3b..ee2f470bd1 100644 --- a/material_maker/theme/classic_base.tres +++ b/material_maker/theme/classic_base.tres @@ -441,7 +441,7 @@ atlas = ExtResource("1_fw8f4") region = Rect2(112, 224, 16, 16) metadata/scale = 2.0 -[sub_resource type="AtlasTexture" id="AtlasTexture_rgi6n"] +[sub_resource type="AtlasTexture" id="AtlasTexture_0v3cv"] atlas = ExtResource("1_fw8f4") region = Rect2(32, 240, 16, 16) filter_clip = true @@ -452,7 +452,7 @@ metadata/recolor = true atlas = ExtResource("1_fw8f4") region = Rect2(64, 160, 16, 16) -[sub_resource type="AtlasTexture" id="AtlasTexture_0v3cv"] +[sub_resource type="AtlasTexture" id="AtlasTexture_l3428"] atlas = ExtResource("1_fw8f4") region = Rect2(112, 48, 16, 16) filter_clip = true @@ -463,10 +463,28 @@ metadata/recolor = true atlas = ExtResource("1_fw8f4") region = Rect2(32, 16, 16, 16) +[sub_resource type="AtlasTexture" id="AtlasTexture_rgi6n"] +atlas = ExtResource("1_fw8f4") +region = Rect2(32, 16, 16, 16) +metadata/scale = 2.0 + +[sub_resource type="AtlasTexture" id="AtlasTexture_jtuhu"] +atlas = ExtResource("1_fw8f4") +region = Rect2(0, 64, 16, 16) + +[sub_resource type="AtlasTexture" id="AtlasTexture_l22ac"] +atlas = ExtResource("1_fw8f4") +region = Rect2(96, 240, 16, 16) + [sub_resource type="AtlasTexture" id="AtlasTexture_oy0ko"] atlas = ExtResource("1_fw8f4") region = Rect2(64, 0, 16, 16) +[sub_resource type="AtlasTexture" id="AtlasTexture_omlq7"] +atlas = ExtResource("1_fw8f4") +region = Rect2(63, 0, 16, 16) +metadata/scale = 2.0 + [sub_resource type="AtlasTexture" id="AtlasTexture_2gawd"] atlas = ExtResource("1_fw8f4") region = Rect2(112, 16, 16, 16) @@ -497,11 +515,24 @@ metadata/scale = 2.0 atlas = ExtResource("1_fw8f4") region = Rect2(112, 128, 16, 16) +[sub_resource type="AtlasTexture" id="AtlasTexture_n4y2n"] +atlas = ExtResource("1_fw8f4") +region = Rect2(32, 80, 16, 16) +margin = Rect2(-2, -2, -4, -4) +metadata/scale = 2.0 + [sub_resource type="AtlasTexture" id="AtlasTexture_pbgus"] atlas = ExtResource("1_fw8f4") region = Rect2(16, 240, 16, 16) metadata/scale = 3.0 +[sub_resource type="AtlasTexture" id="AtlasTexture_7b7js"] +atlas = ExtResource("1_fw8f4") +region = Rect2(48, 240, 16, 16) +filter_clip = true +metadata/scale = 2.0 +metadata/recolor = true + [sub_resource type="AtlasTexture" id="AtlasTexture_c7xvc"] atlas = ExtResource("1_fw8f4") region = Rect2(80, 32, 16, 16) @@ -520,6 +551,11 @@ region = Rect2(0, 240, 16, 16) filter_clip = true metadata/scale = 3.0 +[sub_resource type="AtlasTexture" id="AtlasTexture_fh3ks"] +atlas = ExtResource("1_fw8f4") +region = Rect2(80, 240, 16, 16) +metadata/scale = 2.0 + [sub_resource type="AtlasTexture" id="AtlasTexture_dsr33"] atlas = ExtResource("1_fw8f4") region = Rect2(64, 64, 16, 16) @@ -536,6 +572,12 @@ region = Rect2(64, 80, 16, 16) atlas = ExtResource("1_fw8f4") region = Rect2(48, 80, 16, 16) +[sub_resource type="AtlasTexture" id="AtlasTexture_l6nwy"] +atlas = ExtResource("1_fw8f4") +region = Rect2(96, 64, 16, 16) +metadata/recolor = true +metadata/scale = 2.0 + [sub_resource type="AtlasTexture" id="AtlasTexture_lsxnf"] atlas = ExtResource("1_fw8f4") region = Rect2(96, 128, 16, 16) @@ -1215,11 +1257,15 @@ MM_Icons/icons/arrow_right = SubResource("AtlasTexture_r3xak") MM_Icons/icons/arrow_updown = SubResource("AtlasTexture_dnklm") MM_Icons/icons/category_ascending = SubResource("AtlasTexture_50kh2") MM_Icons/icons/category_descending = SubResource("AtlasTexture_ivx1c") -MM_Icons/icons/clean = SubResource("AtlasTexture_rgi6n") +MM_Icons/icons/clean = SubResource("AtlasTexture_0v3cv") MM_Icons/icons/color_picker = SubResource("AtlasTexture_7ns35") -MM_Icons/icons/console = SubResource("AtlasTexture_0v3cv") +MM_Icons/icons/console = SubResource("AtlasTexture_l3428") MM_Icons/icons/delete = SubResource("AtlasTexture_agwde") +MM_Icons/icons/delete_2x = SubResource("AtlasTexture_rgi6n") +MM_Icons/icons/download = SubResource("AtlasTexture_jtuhu") +MM_Icons/icons/drag_hint = SubResource("AtlasTexture_l22ac") MM_Icons/icons/draw = SubResource("AtlasTexture_oy0ko") +MM_Icons/icons/draw_2x = SubResource("AtlasTexture_omlq7") MM_Icons/icons/dropdown = SubResource("AtlasTexture_2gawd") MM_Icons/icons/environment = SubResource("AtlasTexture_x8swe") MM_Icons/icons/export = SubResource("AtlasTexture_5e0gw") @@ -1227,15 +1273,19 @@ MM_Icons/icons/folder = SubResource("AtlasTexture_rqlqa") MM_Icons/icons/frequency_ascending = SubResource("AtlasTexture_6kl5u") MM_Icons/icons/frequency_descending = SubResource("AtlasTexture_ya45l") MM_Icons/icons/function = SubResource("AtlasTexture_jxpkm") +MM_Icons/icons/generic_size = SubResource("AtlasTexture_n4y2n") MM_Icons/icons/internet = SubResource("AtlasTexture_pbgus") +MM_Icons/icons/knife = SubResource("AtlasTexture_7b7js") MM_Icons/icons/link = SubResource("AtlasTexture_c7xvc") MM_Icons/icons/lock_locked = SubResource("AtlasTexture_m27ao") MM_Icons/icons/lock_unlocked = SubResource("AtlasTexture_asgc8") MM_Icons/icons/logo = SubResource("AtlasTexture_mnfe7") +MM_Icons/icons/minimize = SubResource("AtlasTexture_fh3ks") MM_Icons/icons/model = SubResource("AtlasTexture_dsr33") MM_Icons/icons/paste_image = SubResource("AtlasTexture_64fc4") MM_Icons/icons/pin_pinned = SubResource("AtlasTexture_du4od") MM_Icons/icons/pin_unpinned = SubResource("AtlasTexture_nkmvd") +MM_Icons/icons/randomize = SubResource("AtlasTexture_l6nwy") MM_Icons/icons/reset_view = SubResource("AtlasTexture_lsxnf") MM_Icons/icons/section_3d = SubResource("AtlasTexture_vbdqj") MM_Icons/icons/section_filter = SubResource("AtlasTexture_h5b0q") diff --git a/material_maker/theme/default.tres b/material_maker/theme/default.tres index 67966383ed..fb0ae8add3 100644 --- a/material_maker/theme/default.tres +++ b/material_maker/theme/default.tres @@ -497,6 +497,11 @@ filter_clip = true metadata/scale = 2.0 metadata/recolor = true +[sub_resource type="AtlasTexture" id="AtlasTexture_qnupl"] +atlas = ExtResource("1_s43fy") +region = Rect2(48, 0, 16, 16) +metadata/scale = 2.0 + [sub_resource type="AtlasTexture" id="AtlasTexture_j13i3"] atlas = ExtResource("1_s43fy") region = Rect2(64, 160, 16, 16) @@ -521,7 +526,7 @@ region = Rect2(32, 192, 16, 16) atlas = ExtResource("1_s43fy") region = Rect2(64, 192, 16, 16) -[sub_resource type="AtlasTexture" id="AtlasTexture_npn74"] +[sub_resource type="AtlasTexture" id="AtlasTexture_ov3t0"] atlas = ExtResource("1_s43fy") region = Rect2(112, 48, 16, 16) filter_clip = true @@ -532,10 +537,24 @@ metadata/recolor = true atlas = ExtResource("1_s43fy") region = Rect2(32, 16, 16, 16) +[sub_resource type="AtlasTexture" id="AtlasTexture_u5byk"] +atlas = ExtResource("1_s43fy") +region = Rect2(32, 16, 16, 16) +metadata/scale = 2.0 + +[sub_resource type="AtlasTexture" id="AtlasTexture_w255t"] +atlas = ExtResource("1_s43fy") +region = Rect2(96, 240, 16, 16) + [sub_resource type="AtlasTexture" id="AtlasTexture_oy0ko"] atlas = ExtResource("1_s43fy") region = Rect2(64, 0, 16, 16) +[sub_resource type="AtlasTexture" id="AtlasTexture_omlq7"] +atlas = ExtResource("1_s43fy") +region = Rect2(63, 0, 16, 16) +metadata/scale = 2.0 + [sub_resource type="AtlasTexture" id="AtlasTexture_2gawd"] atlas = ExtResource("1_s43fy") region = Rect2(112, 16, 16, 16) @@ -544,6 +563,11 @@ region = Rect2(112, 16, 16, 16) atlas = ExtResource("1_s43fy") region = Rect2(80, 64, 16, 16) +[sub_resource type="AtlasTexture" id="AtlasTexture_6yetl"] +atlas = ExtResource("1_s43fy") +region = Rect2(48, 240, 16, 16) +metadata/scale = 1.0 + [sub_resource type="AtlasTexture" id="AtlasTexture_bn15y"] atlas = ExtResource("1_s43fy") region = Rect2(16, 0, 16, 16) @@ -552,7 +576,7 @@ region = Rect2(16, 0, 16, 16) atlas = ExtResource("1_s43fy") region = Rect2(0, 32, 16, 16) -[sub_resource type="AtlasTexture" id="AtlasTexture_xdmf6"] +[sub_resource type="AtlasTexture" id="AtlasTexture_ooua1"] atlas = ExtResource("1_s43fy") region = Rect2(64, 224, 16, 16) metadata/scale = 2.0 @@ -566,6 +590,12 @@ metadata/scale = 2.0 atlas = ExtResource("1_s43fy") region = Rect2(112, 128, 16, 16) +[sub_resource type="AtlasTexture" id="AtlasTexture_8an74"] +atlas = ExtResource("1_s43fy") +region = Rect2(32, 80, 16, 16) +margin = Rect2(-2, -2, -4, -4) +metadata/scale = 2.0 + [sub_resource type="AtlasTexture" id="AtlasTexture_pkv4t"] atlas = ExtResource("1_s43fy") region = Rect2(0, 128, 16, 16) @@ -575,6 +605,13 @@ atlas = ExtResource("1_s43fy") region = Rect2(16, 240, 16, 16) metadata/scale = 3.0 +[sub_resource type="AtlasTexture" id="AtlasTexture_npn74"] +atlas = ExtResource("1_s43fy") +region = Rect2(64, 240, 16, 16) +filter_clip = true +metadata/scale = 2.0 +metadata/recolor = true + [sub_resource type="AtlasTexture" id="AtlasTexture_8uenv"] atlas = ExtResource("1_s43fy") region = Rect2(80, 32, 16, 16) @@ -596,6 +633,11 @@ metadata/scale = 3.0 atlas = ExtResource("1_s43fy") region = Rect2(16, 128, 16, 16) +[sub_resource type="AtlasTexture" id="AtlasTexture_xdmf6"] +atlas = ExtResource("1_s43fy") +region = Rect2(80, 240, 16, 16) +metadata/scale = 2.0 + [sub_resource type="AtlasTexture" id="AtlasTexture_dsr33"] atlas = ExtResource("1_s43fy") region = Rect2(64, 64, 16, 16) @@ -612,6 +654,12 @@ region = Rect2(64, 80, 16, 16) atlas = ExtResource("1_s43fy") region = Rect2(48, 80, 16, 16) +[sub_resource type="AtlasTexture" id="AtlasTexture_l6nwy"] +atlas = ExtResource("1_s43fy") +region = Rect2(96, 64, 16, 16) +metadata/recolor = true +metadata/scale = 2.0 + [sub_resource type="AtlasTexture" id="AtlasTexture_c58nb"] atlas = ExtResource("1_s43fy") region = Rect2(96, 192, 16, 16) @@ -688,15 +736,6 @@ region = Rect2(96, 16, 16, 16) atlas = ExtResource("1_s43fy") region = Rect2(48, 16, 16, 16) -[sub_resource type="AtlasTexture" id="AtlasTexture_6yetl"] -atlas = ExtResource("1_s43fy") -region = Rect2(48, 240, 16, 16) -metadata/scale = 1.0 - -[sub_resource type="AtlasTexture" id="AtlasTexture_l6nwy"] -atlas = ExtResource("1_s43fy") -region = Rect2(64, 240, 16, 16) - [sub_resource type="AtlasTexture" id="AtlasTexture_en6gw"] atlas = ExtResource("1_s43fy") region = Rect2(0, 0, 16, 16) @@ -1462,33 +1501,43 @@ MM_Icons/icons/camera = SubResource("AtlasTexture_cscp3") MM_Icons/icons/category_ascending = SubResource("AtlasTexture_ha0qk") MM_Icons/icons/category_descending = SubResource("AtlasTexture_4tel2") MM_Icons/icons/clean = SubResource("AtlasTexture_888jp") +MM_Icons/icons/close = SubResource("AtlasTexture_qnupl") MM_Icons/icons/color_picker = SubResource("AtlasTexture_j13i3") MM_Icons/icons/connection_bezier = SubResource("AtlasTexture_rqjp3") MM_Icons/icons/connection_diagonal = SubResource("AtlasTexture_8tn7x") MM_Icons/icons/connection_direct = SubResource("AtlasTexture_pfiqs") MM_Icons/icons/connection_manhattan = SubResource("AtlasTexture_pfsii") MM_Icons/icons/connection_rounded = SubResource("AtlasTexture_1lfk8") -MM_Icons/icons/console = SubResource("AtlasTexture_npn74") +MM_Icons/icons/console = SubResource("AtlasTexture_ov3t0") MM_Icons/icons/delete = SubResource("AtlasTexture_agwde") +MM_Icons/icons/delete_2x = SubResource("AtlasTexture_u5byk") +MM_Icons/icons/download = SubResource("AtlasTexture_n4y2n") +MM_Icons/icons/drag_hint = SubResource("AtlasTexture_w255t") MM_Icons/icons/draw = SubResource("AtlasTexture_oy0ko") +MM_Icons/icons/draw_2x = SubResource("AtlasTexture_omlq7") MM_Icons/icons/dropdown = SubResource("AtlasTexture_2gawd") MM_Icons/icons/environment = SubResource("AtlasTexture_x8swe") +MM_Icons/icons/expand = SubResource("AtlasTexture_6yetl") MM_Icons/icons/export = SubResource("AtlasTexture_bn15y") MM_Icons/icons/folder = SubResource("AtlasTexture_rqlqa") -MM_Icons/icons/frequency_ascending = SubResource("AtlasTexture_xdmf6") +MM_Icons/icons/frequency_ascending = SubResource("AtlasTexture_ooua1") MM_Icons/icons/frequency_descending = SubResource("AtlasTexture_5jxva") MM_Icons/icons/function = SubResource("AtlasTexture_0jwmb") +MM_Icons/icons/generic_size = SubResource("AtlasTexture_8an74") MM_Icons/icons/grid = SubResource("AtlasTexture_pkv4t") MM_Icons/icons/internet = SubResource("AtlasTexture_bp85t") +MM_Icons/icons/knife = SubResource("AtlasTexture_npn74") MM_Icons/icons/link = SubResource("AtlasTexture_8uenv") MM_Icons/icons/lock_locked = SubResource("AtlasTexture_m27ao") MM_Icons/icons/lock_unlocked = SubResource("AtlasTexture_asgc8") MM_Icons/icons/logo = SubResource("AtlasTexture_5e0gw") MM_Icons/icons/minimap = SubResource("AtlasTexture_ld0tj") +MM_Icons/icons/minimize = SubResource("AtlasTexture_xdmf6") MM_Icons/icons/model = SubResource("AtlasTexture_dsr33") MM_Icons/icons/paste_image = SubResource("AtlasTexture_dqlpm") MM_Icons/icons/pin_pinned = SubResource("AtlasTexture_du4od") MM_Icons/icons/pin_unpinned = SubResource("AtlasTexture_nkmvd") +MM_Icons/icons/randomize = SubResource("AtlasTexture_l6nwy") MM_Icons/icons/reset = SubResource("AtlasTexture_c58nb") MM_Icons/icons/reset_view = SubResource("AtlasTexture_w0re2") MM_Icons/icons/section_3d = SubResource("AtlasTexture_to270") diff --git a/material_maker/theme/default_theme_icons.svg b/material_maker/theme/default_theme_icons.svg index d7ec1d960a..eb673403ca 100644 --- a/material_maker/theme/default_theme_icons.svg +++ b/material_maker/theme/default_theme_icons.svg @@ -8,7 +8,7 @@ version="1.1" id="svg1" inkscape:version="1.4.4 (dcaf3e7, 2026-05-05)" - sodipodi:docname="default_theme_icons.svg" + sodipodi:docname="master.svg" inkscape:export-filename="new_theme_icons.png" inkscape:export-xdpi="96" inkscape:export-ydpi="96" @@ -28,15 +28,15 @@ inkscape:deskcolor="#d1d1d1" inkscape:document-units="mm" showgrid="true" - inkscape:zoom="8" - inkscape:cx="41.125" - inkscape:cy="210.5625" + inkscape:zoom="5.6568543" + inkscape:cx="45.608387" + inkscape:cy="221.58959" inkscape:window-width="1152" inkscape:window-height="981" inkscape:window-x="0" inkscape:window-y="38" inkscape:window-maximized="0" - inkscape:current-layer="g44" + inkscape:current-layer="g234" showguides="true"> bool: while progress_window != null: await get_tree().process_frame environment_textures[index].erase("hdri") + if OS.get_name() == "Android" and android_set_hdr(index, url): + return true if set_hdr(index, base_dir+"/environments/hdris/"+url.get_file()): return true if set_hdr(index, "res://material_maker/environments/hdris/"+url.get_file()): @@ -202,7 +204,7 @@ func read_hdr(index : int, url : String) -> bool: func _physics_process(_delta) -> void: progress_window.set_progress(float($HTTPRequest.get_downloaded_bytes())/float($HTTPRequest.get_body_size())) -func set_hdr(index, hdr_path) -> bool: +func set_hdr(index : int, hdr_path : String) -> bool: if not FileAccess.file_exists(hdr_path): return false print("Setting hdr "+hdr_path) @@ -262,3 +264,13 @@ func do_update_thumbnail() -> void: emit_signal("thumbnail_updated", index, t) thumbnail_update_list = [] rendering = false + +func android_set_hdr(index : int, hdr_path : String) -> bool: + var res : String = "res://material_maker/environments/hdris" + for f in DirAccess.get_files_at(res): + var file_name : String = f.trim_suffix(".import") + if file_name == hdr_path.get_file(): + print("Setting hdr "+ res.path_join(file_name)) + environment_textures[index].hdri = load(res.path_join(file_name)) + return true + return false diff --git a/material_maker/tools/share/share_button.gd b/material_maker/tools/share/share_button.gd index d95ca44de9..35be912138 100644 --- a/material_maker/tools/share/share_button.gd +++ b/material_maker/tools/share/share_button.gd @@ -195,8 +195,8 @@ func _notification(what : int) -> void: setup_icons() func setup_icons() -> void: - $SendButton.texture_normal = owner.get_theme_icon("internet", "MM_Icons") - $ConnectButton.texture_normal = owner.get_theme_icon("logo", "MM_Icons") + $SendButton.texture_normal = mm_globals.main_window.get_theme_icon("internet", "MM_Icons") + $ConnectButton.texture_normal = mm_globals.main_window.get_theme_icon("logo", "MM_Icons") $SendButton.texture_disabled = $SendButton.texture_normal $ConnectButton.texture_disabled = $ConnectButton.texture_normal diff --git a/material_maker/touch.gd b/material_maker/touch.gd new file mode 100644 index 0000000000..768bc1ecb9 --- /dev/null +++ b/material_maker/touch.gd @@ -0,0 +1,219 @@ +class_name MMTouch +extends Node + +## basic touch handling and android utilities + +var _display_corner_radii : PackedInt32Array = PackedInt32Array([0, 0, 0, 0]) +var _dispalay_cutout_margins : PackedInt32Array = PackedInt32Array([0, 0, 0, 0]) + +var android_runtime : JNISingleton + +var long_press_timer : Timer + +# workaround for godot issue #123454 for Android 16 +var last_go_back_request : int = 0 + +func _ready() -> void: + if OS.get_name() not in ["iOS", "Android"]: + set_process_input(false) + else: + if OS.get_name() == "Android": + android_runtime = Engine.get_singleton("AndroidRuntime") + _display_corner_radii = _get_corner_radius() + _dispalay_cutout_margins = _get_cutout_margins() + elif OS.get_name() == "iOS": + long_press_timer = Timer.new() + long_press_timer.wait_time = 0.45 + long_press_timer.autostart = false + long_press_timer.timeout.connect(_emulate_right_click) + add_child(long_press_timer) + +var _touch_start : int = -1 + +## Duration between touch down/up events in milliseconds. +var last_touch_duration_msec : int = -1 + +## Time since last touch down event in milliseconds. +var time_since_touch_down : int = -1: + get: return Time.get_ticks_msec() - _touch_start + +var last_touch_position : Vector2 + +func _input(event : InputEvent) -> void: + if event is InputEventScreenTouch: + if event.pressed: + _touch_start = Time.get_ticks_msec() + long_press_timer.start() + last_touch_position = event.position + elif not event.pressed: + last_touch_duration_msec = Time.get_ticks_msec() - _touch_start + long_press_timer.stop() + else: + long_press_timer.stop() + +func _emulate_right_click() -> void: + var rmb : InputEventMouseButton = InputEventMouseButton.new() + rmb.pressed = true + rmb.position = last_touch_position * mm_globals.get_ui_scale() + rmb.global_position = last_touch_position * mm_globals.get_ui_scale() + rmb.button_index = MOUSE_BUTTON_RIGHT + rmb.button_mask = MOUSE_BUTTON_MASK_RIGHT + get_viewport().push_input(rmb, true) + await get_tree().process_frame + rmb.pressed = false + get_viewport().push_input(rmb, true) + +func _notification(what : int) -> void: + match what: + NOTIFICATION_APPLICATION_PAUSED: + mm_globals.config.save("user://mm_config.ini") + NOTIFICATION_WM_GO_BACK_REQUEST: + if _get_android_version() >= 36: + if Time.get_ticks_msec() - last_go_back_request < 125: + return + last_go_back_request = Time.get_ticks_msec() + + var main_window : MainWindow = mm_globals.main_window + var exclude : PackedStringArray = PackedStringArray(["AddNodePopup"]) + var windows : Array[Window] + + if main_window: + windows.append(_first_window_child(main_window, exclude)) + windows.append(_first_window_child(main_window.get_current_graph_edit(), exclude)) + + # ask window to quit + for window in windows: + if window: + window.close_requested.emit() + return + + # exit app when no other dialogs are shown + main_window.quit() + +## Get display corner radius per corner. +func corner_radius(corner : Corner, scale : float = mm_globals.get_ui_scale()) -> int: + return ceili(_display_corner_radii[corner] / scale) + +## Get cutout margins per side. +func cutout_margins(side : Side, scale : float = mm_globals.get_ui_scale()) -> int: + return ceili(_dispalay_cutout_margins[side] / scale) + +func make_dialog_fullscreen(window : Window, show : bool = false) -> void: + window.borderless = true + window.size = mm_globals.main_window.size + window.min_size = Vector2.ZERO + window.position = Vector2.ZERO + # offset by MM_MainBackground stylebox content margins + window.position.x += maxi(0, calc_margins(Side.SIDE_LEFT) - 10) + window.size.x -= (window.position.x + calc_margins(Side.SIDE_RIGHT)) + if show: + window.show() + +## Get display safe margins accounting for cutouts and corner radii. +## [param side] can be either Side.SIDE_LEFT or Side.SIDE_RIGHT +func calc_margins(side : Side, scale : float = mm_globals.get_ui_scale()) -> int: + var top : int = cutout_margins(SIDE_TOP, scale) + var bottom : int = cutout_margins(SIDE_BOTTOM, scale) + match side: + Side.SIDE_LEFT: + var top_left : int = _inset(corner_radius(CORNER_TOP_LEFT, scale), top) + var bottom_left : int = _inset(corner_radius(CORNER_BOTTOM_LEFT, scale), bottom) + return maxi(maxi(top_left, bottom_left), cutout_margins(SIDE_LEFT, scale)) + Side.SIDE_RIGHT: + var top_right : int = _inset(corner_radius(CORNER_TOP_RIGHT, scale), top) + var bottom_right : int = _inset(corner_radius(CORNER_BOTTOM_RIGHT, scale), bottom) + return maxi(maxi(top_right, bottom_right), cutout_margins(SIDE_RIGHT, scale)) + return 0 + +func setup_margins(container : MarginContainer, margin_offset_left : int, + margin_ofset_right : int = margin_offset_left) -> void: + container.add_theme_constant_override("margin_left", + maxi(0, calc_margins(Side.SIDE_LEFT) + margin_offset_left)) + container.add_theme_constant_override("margin_right", + maxi(0, calc_margins(Side.SIDE_RIGHT) + margin_ofset_right)) + +## Allows a control to show its tooltip when tapped. +func handle_tap_show_tooltip(c : Control) -> void: + if not c.gui_input.is_connected(_control_tap_show_tooltip.bind(c)): + c.gui_input.connect(_control_tap_show_tooltip.bind(c)) + +func _first_window_child(node : Node, exclude_list : PackedStringArray) -> Window: + if node != null: + for w in node.get_children(): + if w is Window and w.name not in exclude_list: + return w + return null + +func _inset(radius : int, y : int) -> int: + return ceili(radius - sqrt(radius ** 2 - (y - radius) ** 2)) if y < radius else 0 + +func _get_corner_radius() -> PackedInt32Array: + # github.com/godotengine/godot-proposals/issues/14056#issuecomment-3816832522 + var result : PackedInt32Array = PackedInt32Array([0, 0, 0, 0]) + if not android_runtime: + return result + var version : JavaClass = JavaClassWrapper.wrap("android.os.Build$VERSION") + + # Available only on Android 12 and later + if version.SDK_INT < 31: + return result + + var insets : JavaObject = android_runtime.getActivity().getWindow().getDecorView().getRootWindowInsets() + var RoundedCorner : JavaClass = JavaClassWrapper.wrap("android.view.RoundedCorner") + + var topLeft : JavaObject = insets.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT) + var topRight : JavaObject = insets.getRoundedCorner(RoundedCorner.POSITION_TOP_RIGHT) + var bottomRight : JavaObject = insets.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT) + var bottomLeft : JavaObject = insets.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT) + + if is_instance_valid(topLeft): + result[Corner.CORNER_TOP_LEFT] = topLeft.getRadius() + if is_instance_valid(topRight): + result[Corner.CORNER_TOP_RIGHT] = topRight.getRadius() + if is_instance_valid(bottomRight): + result[Corner.CORNER_BOTTOM_RIGHT] = bottomRight.getRadius() + if is_instance_valid(bottomLeft): + result[Corner.CORNER_BOTTOM_LEFT] = bottomLeft.getRadius() + return result + +func _get_cutout_margins() -> PackedInt32Array: + var result : PackedInt32Array = PackedInt32Array([0, 0, 0, 0]) + var safe_area : Rect2i = DisplayServer.get_display_safe_area() + var screen_size : Vector2i = DisplayServer.screen_get_size() + result[SIDE_LEFT] = safe_area.position.x + result[SIDE_TOP] = safe_area.position.y + result[SIDE_RIGHT] = screen_size.x - safe_area.end.x + result[SIDE_BOTTOM] = screen_size.y - safe_area.end.y + return result + +func _get_android_version() -> int: + if not android_runtime: + return -1 + return JavaClassWrapper.wrap("android.os.Build$VERSION").SDK_INT + +func _control_tap_show_tooltip(e : InputEvent, c : Control) -> void: + if e is InputEventScreenTouch and e.pressed and e.index == 0: + _show_tooltip(c.get_global_mouse_position(), c.tooltip_text) + +func _show_tooltip(at : Vector2, text : String) -> void: + if get_tree().root.has_node("TouchTooltipPanel"): + get_tree().root.get_node("TouchTooltipPanel").queue_free() + const margin : Vector2i = Vector2i(24, 24) + var main_window : MainWindow = get_node("/root/MainWindow") + + var tool_tip_panel : PopupPanel = PopupPanel.new() + tool_tip_panel.name = "TouchTooltipPanel" + tool_tip_panel.theme = main_window.theme + tool_tip_panel.theme_type_variation = "TooltipPanel" + + var label : Label = Label.new() + label.text = text + + tool_tip_panel.add_child(label) + tool_tip_panel.size = Vector2.ZERO + get_tree().root.add_child(tool_tip_panel) + var tsize : Vector2i = tool_tip_panel.get_contents_minimum_size() + var vsize : Vector2i = get_viewport().get_visible_rect().size + tool_tip_panel.position = at.clamp(margin, vsize - tsize - margin) + tool_tip_panel.popup() + tool_tip_panel.popup_hide.connect(tool_tip_panel.queue_free) diff --git a/material_maker/touch.gd.uid b/material_maker/touch.gd.uid new file mode 100644 index 0000000000..74b55faf0e --- /dev/null +++ b/material_maker/touch.gd.uid @@ -0,0 +1 @@ +uid://uyvqjubc7arn diff --git a/material_maker/widgets/curve_edit/control_point.gd b/material_maker/widgets/curve_edit/control_point.gd index 58b17c8037..ce3f7407a9 100644 --- a/material_maker/widgets/curve_edit/control_point.gd +++ b/material_maker/widgets/curve_edit/control_point.gd @@ -15,10 +15,13 @@ signal moved(index) signal removed(index) signal selected(index) -func _ready(): - pass # Replace with function body. +func _ready() -> void: + if mm_globals.get_config("touch_optimization"): + offset_transform_scale = Vector2(2.5, 2.5) + offset_transform_visual_only = false + offset_transform_enabled = true -func _draw(): +func _draw() -> void: var current_theme : Theme = mm_globals.main_window.theme var color : Color = current_theme.get_color("font_color", "Label") var selected_color : Color = current_theme.get_color("icon_pressed_color", "Button") @@ -29,8 +32,7 @@ func _draw(): draw_rect(Rect2(Vector2.ZERO, custom_minimum_size), color.inverted(), false) if hovering or moving: draw_rect(Rect2(-custom_minimum_size * 0.5, custom_minimum_size * 2.0), color, false, 1.0) - draw_rect(Rect2(-custom_minimum_size*0.5-Vector2(1.0,1.0), - custom_minimum_size*2.0+Vector2(2.0,2.0)), color.inverted(), false, 1.0) + draw_rect(Rect2(-custom_minimum_size * 0.5, custom_minimum_size * 2.0).grow(1.0), color.inverted(), false, 1.0) func initialize(p : MMCurve.Point) -> void: position = get_parent().transform_point(p.p)-OFFSET @@ -61,7 +63,7 @@ func _on_ControlPoint_gui_input(event): elif event.button_index == MOUSE_BUTTON_RIGHT and event.pressed: emit_signal("removed", get_index()) elif moving and event is InputEventMouseMotion: - var new_pos : Vector2 = position + event.relative + var new_pos : Vector2 = position + event.relative * offset_transform_scale if event.is_command_or_control_pressed(): if get_parent().axes_density > 1.0: var snap : float = 1.0 / (get_parent().axes_density - 1.0) diff --git a/material_maker/widgets/curve_edit/slope_point.gd b/material_maker/widgets/curve_edit/slope_point.gd index 54061ebcca..a9400c7397 100644 --- a/material_maker/widgets/curve_edit/slope_point.gd +++ b/material_maker/widgets/curve_edit/slope_point.gd @@ -8,16 +8,20 @@ var is_selected : bool = false const OFFSET = -Vector2(0, 0) -func _ready(): - pass # Replace with function body. +func _ready() -> void: + if OS.get_name() == "Android": + offset_transform_scale = Vector2(2.5, 2.5) + offset_transform_visual_only = false + offset_transform_enabled = true -func _draw(): +func _draw() -> void: var current_theme : Theme = mm_globals.main_window.theme var color : Color = current_theme.get_color("font_color", "Label") var selected_color : Color = current_theme.get_color("icon_pressed_color", "Button") - draw_circle(custom_minimum_size*0.5, 3.0, selected_color if is_selected else color) + var adjusted_scale : float = offset_transform_scale.x + draw_circle(custom_minimum_size*0.5, 3.0 / adjusted_scale, selected_color if is_selected else color) if hovering or is_selected: - draw_circle(custom_minimum_size*0.5, 6.0, color, false, 0.5, true) + draw_circle(custom_minimum_size*0.5, 6.0 / adjusted_scale, color, false, 0.5 / adjusted_scale, true) func _on_ControlPoint_gui_input(event : InputEvent): if event is InputEventMouseButton: diff --git a/material_maker/widgets/file_picker_button/file_picker_button.gd b/material_maker/widgets/file_picker_button/file_picker_button.gd index 8194903d73..c67bd192af 100644 --- a/material_maker/widgets/file_picker_button/file_picker_button.gd +++ b/material_maker/widgets/file_picker_button/file_picker_button.gd @@ -23,11 +23,13 @@ func add_filter(f : String) -> void: filters.append(f) func _on_Control_pressed() -> void: - var dialog = preload("res://material_maker/windows/file_dialog/file_dialog.tscn").instantiate() - dialog.min_size = Vector2i(500, 500) - dialog.access = FileDialog.ACCESS_FILESYSTEM - dialog.file_mode = mode - dialog.current_dir = path.get_base_dir() + var dialog : FileDialog = preload("res://material_maker/windows/file_dialog/file_dialog.tscn").instantiate() + if not OS.get_name() == "Android": + dialog.min_size = Vector2i(500, 500) + dialog.access = FileDialog.ACCESS_FILESYSTEM + dialog.file_mode = mode + if path: + dialog.current_dir = path.get_base_dir() for f in filters: dialog.add_filter(f) var files = await dialog.select_files() diff --git a/material_maker/widgets/float_edit/float_edit.gd b/material_maker/widgets/float_edit/float_edit.gd index 649faf89bd..239372f0b2 100644 --- a/material_maker/widgets/float_edit/float_edit.gd +++ b/material_maker/widgets/float_edit/float_edit.gd @@ -362,6 +362,8 @@ func _exit_tree() -> void: mm_globals.set_config("ui_field_sensitivity", sensitivity) func _handle_sensitivity_adjustment(event : InputEvent) -> void: + if OS.get_name() == "Android": + return if mode == Modes.SLIDING: adjust_increment = 0.05 if event.alt_pressed else 0.1 if event is InputEventMouseButton: diff --git a/material_maker/widgets/gradient_editor/gradient_edit.gd b/material_maker/widgets/gradient_editor/gradient_edit.gd index 5aecc63b1f..3f345da059 100644 --- a/material_maker/widgets/gradient_editor/gradient_edit.gd +++ b/material_maker/widgets/gradient_editor/gradient_edit.gd @@ -127,12 +127,13 @@ func select_color(cursor : GradientEditCursor) -> void: if mm_globals.has_config("color_picker_shape"): color_picker.picker_shape = mm_globals.get_config("color_picker_shape") - # find and focus/highlight hex code - for node in color_picker.get_child(0,true).get_child(0,true).get_children(true): - for hex in node.get_children(true): - if hex is LineEdit: - hex.grab_focus() - hex.select_all() + if OS.get_name() != "Android": + # find and focus/highlight hex code + for node in color_picker.get_child(0,true).get_child(0,true).get_children(true): + for hex in node.get_children(true): + if hex is LineEdit: + hex.grab_focus() + hex.select_all() var content_scale_factor : float = mm_globals.ui_scale_factor() color_picker_popup.content_scale_factor = content_scale_factor @@ -279,7 +280,6 @@ func _on_popup_button_toggled(toggled_on: bool) -> void: update_popup_position() set_notify_transform(true) - else: if is_instance_valid(popup): popup.close() diff --git a/material_maker/widgets/gradient_editor/gradient_popup.gd b/material_maker/widgets/gradient_editor/gradient_popup.gd index de6ec7edc0..2d3b02493d 100644 --- a/material_maker/widgets/gradient_editor/gradient_popup.gd +++ b/material_maker/widgets/gradient_editor/gradient_popup.gd @@ -1,3 +1,4 @@ +class_name GradientPopup extends Control signal updated(value, merge_undos) diff --git a/material_maker/widgets/image_picker_button/image_picker_button.gd b/material_maker/widgets/image_picker_button/image_picker_button.gd index 6e3940334c..8abddd87b6 100644 --- a/material_maker/widgets/image_picker_button/image_picker_button.gd +++ b/material_maker/widgets/image_picker_button/image_picker_button.gd @@ -52,7 +52,7 @@ func get_filetime(file_path : String) -> int: return 0 func open_image_dialog() -> void: - var dialog = preload("res://material_maker/windows/file_dialog/file_dialog.tscn").instantiate() + var dialog = load("res://material_maker/windows/file_dialog/file_dialog.tscn").instantiate() if image_path: dialog.current_dir = image_path.get_base_dir() if FileAccess.file_exists(image_path): diff --git a/material_maker/widgets/pixels_edit/pixels_editor.gd b/material_maker/widgets/pixels_edit/pixels_editor.gd index f9e9869a7e..74301ac8b2 100644 --- a/material_maker/widgets/pixels_edit/pixels_editor.gd +++ b/material_maker/widgets/pixels_edit/pixels_editor.gd @@ -33,6 +33,7 @@ func _ready() -> void: if get_parent().has_method("add_menu_bar"): menu_bar.get_parent().remove_child(menu_bar) get_parent().add_menu_bar(menu_bar, self) + func is_mouse_in_canvas() -> bool: return Rect2(draw_offset, draw_size).has_point(get_local_mouse_position()) @@ -61,6 +62,10 @@ func set_pixels(p : MMPixels) -> void: queue_redraw() update_color_buttons() +func color_button_gui_input(event : InputEvent, button : ColorPickerButton) -> void: + if event is InputEventScreenTouch: + button.accept_event() + func update_color_buttons() -> void: if not is_visible_in_tree(): return @@ -85,6 +90,9 @@ func update_color_buttons() -> void: color_button.toggle_mode = true color_button.button_mask = MOUSE_BUTTON_MASK_RIGHT colors.add_child(color_button) + if OS.get_name() == "Android": + color_button.custom_minimum_size = Vector2i(32, 32) + color_button.gui_input.connect(color_button_gui_input.bind(color_button)) color_button.focus_entered.connect(self.set_current_color.bind(button_count)) color_button.color_changed.connect(self.set_palette_color.bind(button_count)) button_count += 1 diff --git a/material_maker/widgets/polygon_edit/control_point.gd b/material_maker/widgets/polygon_edit/control_point.gd index 72bc5da513..bc73e82e34 100644 --- a/material_maker/widgets/polygon_edit/control_point.gd +++ b/material_maker/widgets/polygon_edit/control_point.gd @@ -14,7 +14,13 @@ signal moved(index) signal selected(index, control_pressed, shift_pressed) signal removed(index) -func _draw(): +func _ready() -> void: + if mm_globals.get_config("touch_optimization"): + offset_transform_enabled = true + offset_transform_visual_only = false + offset_transform_scale = Vector2(2.5, 2.5) + +func _draw() -> void: var current_theme : Theme = mm_globals.main_window.theme var moving_color : Color = current_theme.get_color("icon_pressed_color", "Button") var color : Color = Color(1.0, 0.0, 0.0) if is_selected else current_theme.get_color("font_color", "Label") @@ -26,8 +32,8 @@ func _draw(): draw_rect(Rect2(Vector2(0, 0), custom_minimum_size), color.inverted(), false) if is_moving or hovered: draw_rect(Rect2(-custom_minimum_size*0.5, custom_minimum_size*2.0), current_theme.get_color("font_color", "Label"), false, 1.0) - draw_rect(Rect2(-custom_minimum_size*0.5-Vector2(1.0,1.0), - custom_minimum_size*2.0+Vector2(2.0,2.0)), current_theme.get_color("font_color", "Label").inverted(), false, 1.0) + draw_rect(Rect2(-custom_minimum_size*0.5, custom_minimum_size*2.0).grow(1.0), + current_theme.get_color("font_color", "Label").inverted(), false, 1.0) func initialize(p : Vector2, e : Control = null) -> void: editor = e if e != null else get_parent() @@ -62,7 +68,7 @@ func _on_ControlPoint_gui_input(event): elif event.button_index == MOUSE_BUTTON_RIGHT and event.pressed: removed.emit(get_index()) elif is_moving and event is InputEventMouseMotion: - var new_pos : Vector2 = position + event.relative + var new_pos : Vector2 = position + event.relative * offset_transform_scale.x if event.is_command_or_control_pressed(): var value : Vector2 var parent = get_parent().owner diff --git a/material_maker/widgets/render_counter/render_counter.gd b/material_maker/widgets/render_counter/render_counter.gd index ec0b853748..a481629d12 100644 --- a/material_maker/widgets/render_counter/render_counter.gd +++ b/material_maker/widgets/render_counter/render_counter.gd @@ -53,6 +53,9 @@ func _ready() -> void: # GPU RAM tooltip $GpuRam.tooltip_text = "Adapter: %s\nVendor: %s" % [ RenderingServer.get_video_adapter_name(), RenderingServer.get_video_adapter_vendor() ] + if OS.get_name() == "Android": + mm_touch.handle_tap_show_tooltip($GpuRam) + func on_counter_change(count : int, pending : int) -> void: if pending == 0: $ProgressBar.max_value = 1 diff --git a/material_maker/widgets/tabs/tabs.gd b/material_maker/widgets/tabs/tabs.gd index 2bf69f0646..4259e170ad 100644 --- a/material_maker/widgets/tabs/tabs.gd +++ b/material_maker/widgets/tabs/tabs.gd @@ -123,11 +123,6 @@ func _on_Tabs_tab_changed(tab) -> void: current_tab = tab func _on_Projects_resized() -> void: - $TabBar.anchor_left = 0 - $TabBar.anchor_right = 0 - $TabBar.anchor_top = 0 - $TabBar.anchor_bottom = 0 - $TabBar.size.x = size.x if current_tab >= 0: var node = get_child(current_tab) node.position = Vector2(0, $TabBar.size.y) diff --git a/material_maker/windows/about/about.gd b/material_maker/windows/about/about.gd index ce871db70c..ad3100c17c 100644 --- a/material_maker/windows/about/about.gd +++ b/material_maker/windows/about/about.gd @@ -154,6 +154,12 @@ func _ready() -> void: continue patrons_list.add_item(p) + if OS.get_name() == "Android": + mm_touch.make_dialog_fullscreen(self, true) + else: + hide() + popup_centered() + func _name_control_gui_input(event : InputEvent, url : String) -> void: if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: open_url(url) diff --git a/material_maker/windows/about/about.tscn b/material_maker/windows/about/about.tscn index 9008425d1c..9efb30af73 100644 --- a/material_maker/windows/about/about.tscn +++ b/material_maker/windows/about/about.tscn @@ -52,6 +52,7 @@ title = "About Material Maker" position = Vector2i(0, 36) size = Vector2i(600, 500) script = ExtResource("1") +metadata/android_fullscreen_dim = true [node name="BG" type="ColorRect" parent="."] anchors_preset = 15 diff --git a/material_maker/windows/add_node_popup/add_node_popup.gd b/material_maker/windows/add_node_popup/add_node_popup.gd index e989868ea0..9317af1bda 100644 --- a/material_maker/windows/add_node_popup/add_node_popup.gd +++ b/material_maker/windows/add_node_popup/add_node_popup.gd @@ -13,12 +13,24 @@ var qc_slot : int var qc_slot_type : int var qc_is_output : bool +## Whether a drag has initiated from item's icon. +var dragging_from_icon : bool = false +const ICON_DRAG_MARGIN : int = 12 + @onready var library_manager = get_node("/root/MainWindow/NodeLibraryManager") func get_current_graph(): return get_parent().get_current_graph_edit() func _ready() -> void: + if mm_globals.get_config("touch_optimization"): + %List.add_theme_constant_override("v_separation", 4) + $PanelContainer.custom_minimum_size.y = 325 + size.y = 325 + %List.icon_scale = 1.5 + for i in $PanelContainer/VBoxContainer/Buttons.get_children(): + i.custom_minimum_size *= 1.25 + filter.connect("text_changed", Callable(self, "update_list")) filter.connect("text_submitted", Callable(self, "filter_entered")) %List.set_drag_forwarding(get_list_drag_data, Callable(), Callable()) @@ -162,6 +174,10 @@ func check_quick_connect(obj : Dictionary) -> bool: return true func update_list(filter_text : String = "") -> void: + var isize : Vector2i = %List.fixed_icon_size + var empty : Image = Image.create_empty(isize.x, isize.y, false, Image.FORMAT_RGBA8) + var placeholder_icon = ImageTexture.create_from_image(empty) + filter_text = filter_text.to_lower() %List.clear() var idx : int = 0 @@ -184,7 +200,8 @@ func update_list(filter_text : String = "") -> void: var _name : String = obj.display_name _name = obj.tree_item# + "("+str(i.quality)+")" + " ("+str(i.idx)+")" - %List.add_item(_name, i.icon) + var icon : ImageTexture = i.icon if i.icon else placeholder_icon + %List.add_item(_name, icon) %List.set_item_custom_fg_color(idx, color) %List.set_item_metadata(idx, i) %List.set_item_tooltip_enabled(idx, false) @@ -206,26 +223,69 @@ func _on_filter_gui_input(event: InputEvent) -> void: %List.grab_focus() %List.select(1) +var click_start : int -func _on_list_gui_input(event: InputEvent) -> void: +func _on_list_gui_input(event : InputEvent) -> void: if event.is_action("ui_up"): if not %List.item_count or %List.is_selected(0): %Filter.grab_focus() - if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and not event.pressed: - var idx: int = %List.get_item_at_position(%List.get_local_mouse_position(), true) - if idx != -1: - _on_list_item_activated(idx) - - -func get_list_drag_data(m_position : Vector2): + if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT: + if event.pressed: + click_start = Time.get_ticks_msec() + else: + # releasing a pan gesture also triggers a left click release + # use click down/up duration to tell them part + if Time.get_ticks_msec() - click_start > 150 and\ + event.device == InputEvent.DEVICE_ID_EMULATION: + return + activate_item_at_current_position() + elif event is InputEventScreenTouch and event.index == 0: + var icon_width : float = get_icon_size().x + ICON_DRAG_MARGIN + dragging_from_icon = event.pressed and event.position.x < icon_width + if event.pressed: + %Filter.mouse_filter = Control.MOUSE_FILTER_IGNORE + else: + %Filter.mouse_filter = Control.MOUSE_FILTER_STOP + elif event is InputEventScreenDrag and event.index == 0: + # allow drag to only occur on text + if event.position.x > get_icon_size().x + ICON_DRAG_MARGIN and not dragging_from_icon: + %List.get_v_scroll_bar().value -= event.relative.y + %List.accept_event() + +func activate_item_at_current_position() -> void: + var idx: int = %List.get_item_at_position(%List.get_local_mouse_position(), true) + if idx != -1: + _on_list_item_activated(idx) + +func get_list_drag_data(m_position : Vector2) -> Variant: var idx : int = %List.get_item_at_position(m_position) - var data = %List.get_item_metadata(idx) + if OS.get_name() == "Android": + if m_position.x > get_icon_size().x + ICON_DRAG_MARGIN: + return "" + + var preview : Control + var data : Dictionary = %List.get_item_metadata(idx) sub_node_disable_item_drag(data, idx) - var texture_rect : TextureRect = TextureRect.new() - texture_rect.texture = data.icon - texture_rect.scale = Vector2(0.35, 0.35) - %List.set_drag_preview(texture_rect) + + if data.icon: + preview = TextureRect.new() + preview.texture = data.icon + preview.scale = Vector2(0.35, 0.35) + else: + preview = Label.new() + preview.text = %List.get_item_text(idx) + + if mm_globals.get_config("touch_optimization"): + var offset : Vector2 + preview.scale = Vector2.ONE * (1.5 if preview is Label else 0.8) + if preview is TextureRect: + offset = preview.texture.get_size() if data.icon else preview.size + preview.offset_transform_enabled = true + preview.offset_transform_visual_only = false + preview.offset_transform_position = -offset * 0.5 + + %List.set_drag_preview(preview) return data.item.tree_item @@ -249,6 +309,8 @@ func _on_sort_menu_pressed() -> void: else: panel.popup(Rect2(panel.get_mouse_position() * content_scale_factor, panel.size)) +func get_icon_size() -> Vector2: + return %List.fixed_icon_size * %List.icon_scale #region sub-node items diff --git a/material_maker/windows/add_node_popup/quick_button.gd b/material_maker/windows/add_node_popup/quick_button.gd index b7ede170a4..b1a6df6f93 100644 --- a/material_maker/windows/add_node_popup/quick_button.gd +++ b/material_maker/windows/add_node_popup/quick_button.gd @@ -20,6 +20,8 @@ func _ready(): func _can_drop_data(_position, _data): + if OS.get_name() == "Android": + return _data != "" return true @@ -41,10 +43,12 @@ func _drop_data(_position, data): func _on_gui_input(event): if !disabled and event is InputEventMouseButton: - if event.pressed and event.button_index == MOUSE_BUTTON_LEFT: + if event.button_index == MOUSE_BUTTON_LEFT and not (event.pressed or event.canceled): emit_signal("object_selected", library_item.item) - if event.pressed and event.button_index == MOUSE_BUTTON_RIGHT: + elif event.button_index == MOUSE_BUTTON_RIGHT and event.pressed: set_library_item("") + if OS.get_name() == "Android": + mm_globals.android_make_toast("Item cleared.") disable() func enable() -> void: diff --git a/material_maker/windows/environment_editor/camera_controller.gd b/material_maker/windows/environment_editor/camera_controller.gd index ae12ea641b..25b963f01b 100644 --- a/material_maker/windows/environment_editor/camera_controller.gd +++ b/material_maker/windows/environment_editor/camera_controller.gd @@ -15,9 +15,21 @@ extends Node3D var mouse_start_position : Vector2 +var world_env : WorldEnvironment +var parent_vp : SubViewport + func _ready(): camera_path = camera_path + if has_node("../WorldEnvironment"): + world_env = get_node("../WorldEnvironment") + + await get_tree().process_frame + for node in [get_parent(), get_parent().get_parent()]: + if node is SubViewport: + parent_vp = node + break + func process_event(event : InputEvent, viewport : Viewport = null) -> bool: if event is InputEventMouseMotion: if (event.button_mask & MOUSE_BUTTON_MASK_MIDDLE != 0 @@ -32,9 +44,13 @@ func process_event(event : InputEvent, viewport : Viewport = null) -> bool: return true elif event.button_mask & MOUSE_BUTTON_MASK_RIGHT != 0: if event.shift_pressed: - var world_env : WorldEnvironment = get_node("../WorldEnvironment") world_env.environment.sky_rotation.y += event.relative.x * 0.001 return false + elif event.button_mask & MOUSE_BUTTON_MASK_LEFT != 0: + if event.device == InputEvent.DEVICE_ID_EMULATION: + camera_rotation2.rotate_x(-0.0125 * event.relative.y) + camera_rotation1.rotate_y(-0.0125 * event.relative.x) + return true elif event is InputEventMouseButton: if not event.is_command_or_control_pressed(): var zoom = 0.0 @@ -60,11 +76,16 @@ func process_event(event : InputEvent, viewport : Viewport = null) -> bool: var factor : float = 0.01 * camera_position.position.z camera_target_position.translate(-factor*event.delta.x*camera_position.global_transform.basis.x) camera_target_position.translate(factor*event.delta.y*camera_position.global_transform.basis.y) - else: + elif OS.get_name() != "Android": camera_rotation2.rotate_x(-0.05*event.delta.y) camera_rotation1.rotate_y(-0.05*event.delta.x) return true elif event is InputEventMagnifyGesture: camera_position.position.z /= event.factor return true + elif event is InputEventScreenDrag: + if event.index == 0: + camera_rotation2.rotate_x(-4.0 * event.relative.y / parent_vp.size.x ) + camera_rotation1.rotate_y(-4.0 * event.relative.x / parent_vp.size.y ) + return true return false diff --git a/material_maker/windows/environment_editor/camera_controller.tscn b/material_maker/windows/environment_editor/camera_controller.tscn index 9a82e13ae3..d602922785 100644 --- a/material_maker/windows/environment_editor/camera_controller.tscn +++ b/material_maker/windows/environment_editor/camera_controller.tscn @@ -1,14 +1,14 @@ -[gd_scene load_steps=2 format=3 uid="uid://dw4wghi1pn4qr"] +[gd_scene format=3 uid="uid://dw4wghi1pn4qr"] [ext_resource type="Script" uid="uid://yamgbb24fo4g" path="res://material_maker/windows/environment_editor/camera_controller.gd" id="1_i358n"] -[node name="CameraController" type="Node3D"] +[node name="CameraController" type="Node3D" unique_id=1858284500] script = ExtResource("1_i358n") -[node name="CameraRotation1" type="Node3D" parent="."] +[node name="CameraRotation1" type="Node3D" parent="." unique_id=1698689953] -[node name="CameraRotation2" type="Node3D" parent="CameraRotation1"] +[node name="CameraRotation2" type="Node3D" parent="CameraRotation1" unique_id=1440601724] transform = Transform3D(1, 0, 0, 0, 0.707107, 0.707107, 0, -0.707107, 0.707107, 0, 0, 0) -[node name="Camera3D" type="RemoteTransform3D" parent="CameraRotation1/CameraRotation2"] +[node name="Camera3D" type="RemoteTransform3D" parent="CameraRotation1/CameraRotation2" unique_id=929968289] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 4) diff --git a/material_maker/windows/environment_editor/environment_editor.gd b/material_maker/windows/environment_editor/environment_editor.gd index 89b81d3e8c..4ddf8346ff 100644 --- a/material_maker/windows/environment_editor/environment_editor.gd +++ b/material_maker/windows/environment_editor/environment_editor.gd @@ -32,8 +32,14 @@ func _ready(): v.add_theme_stylebox_override("scroll", grabber_sb) v.add_theme_constant_override("padding_left", 8) - hide() - popup_centered() + if OS.get_name() == "Android": + min_size = Vector2.ZERO + $Main.custom_minimum_size = Vector2.ZERO + mm_touch.make_dialog_fullscreen(self, true) + else: + hide() + popup_centered() + connect_controls() environment_manager.environment_updated.connect(self.on_environment_updated) environment_manager.name_updated.connect(self.on_name_updated) diff --git a/material_maker/windows/environment_editor/environment_editor.tscn b/material_maker/windows/environment_editor/environment_editor.tscn index f70cd34574..8725d53299 100644 --- a/material_maker/windows/environment_editor/environment_editor.tscn +++ b/material_maker/windows/environment_editor/environment_editor.tscn @@ -9,6 +9,7 @@ oversampling_override = 1.0 position = Vector2i(0, 36) exclusive = true script = ExtResource("2") +metadata/android_fullscreen_dim = true [node name="Main" type="VBoxContainer" parent="."] custom_minimum_size = Vector2(800, 500) diff --git a/material_maker/windows/environment_editor/environment_editor_viewport.tscn b/material_maker/windows/environment_editor/environment_editor_viewport.tscn index 8606d265e1..f4051935a4 100644 --- a/material_maker/windows/environment_editor/environment_editor_viewport.tscn +++ b/material_maker/windows/environment_editor/environment_editor_viewport.tscn @@ -1,7 +1,7 @@ -[gd_scene load_steps=10 format=3 uid="uid://bb76ty33yvxj2"] +[gd_scene format=3 uid="uid://bb76ty33yvxj2"] [ext_resource type="PackedScene" uid="uid://cdkj3jrppq51u" path="res://material_maker/windows/environment_editor/environment_editor_scene.tscn" id="1"] -[ext_resource type="Texture2D" uid="uid://by6042vpo6i1o" path="res://material_maker/environments/hdris/epping_forest_01_1k.hdr" id="1_r627v"] +[ext_resource type="Texture2D" uid="uid://by6042vpo6i1o" path="res://material_maker/environments/hdris/epping_forest_01_1k.exr" id="1_r627v"] [ext_resource type="PackedScene" uid="uid://dw4wghi1pn4qr" path="res://material_maker/windows/environment_editor/camera_controller.tscn" id="3_iommd"] [sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_f7v0t"] diff --git a/material_maker/windows/file_dialog/file_dialog.gd b/material_maker/windows/file_dialog/file_dialog.gd index ba0fe7d075..2ec7698e66 100644 --- a/material_maker/windows/file_dialog/file_dialog.gd +++ b/material_maker/windows/file_dialog/file_dialog.gd @@ -24,6 +24,10 @@ func _fix_context_menu() -> void: break func _ready() -> void: + if OS.get_name() == "Android": + OS.request_permissions() + mm_touch.make_dialog_fullscreen(self) + _fix_context_menu() load_fav_recents() if file_mode == FileMode.FILE_MODE_SAVE_FILE: @@ -34,7 +38,7 @@ func _ready() -> void: setup_thumbnail_callbacks() - use_native_dialog = mm_globals.get_config("ui_use_native_file_dialogs") + use_native_dialog = mm_globals.get_config("ui_use_native_file_dialogs") and not OS.get_name() == "Android" content_scale_factor = mm_globals.ui_scale_factor() min_size = get_contents_minimum_size().max(Vector2i(750, 500)) * content_scale_factor @@ -45,8 +49,8 @@ func _ready() -> void: left_panel = n.get_child(1).get_children()[0] favorites_list = left_panel.get_child(0).get_child(1) recents_list = left_panel.get_child(1).get_child(1) - favorites_list.gui_input.connect(_on_favorites_list_gui_input) - recents_list.gui_input.connect(_on_recents_list_gui_input) + favorites_list.gui_input.connect(_on_recent_faves_list_gui_input.bind(favorites_list)) + recents_list.gui_input.connect(_on_recent_faves_list_gui_input.bind(recents_list)) # setup display list/thumbnail buttons signals var thumb_list_btns : HBoxContainer = n.get_child(1).get_child(1).get_child(0).get_child(3) @@ -55,23 +59,23 @@ func _ready() -> void: thumbnail_button.pressed.connect(set_thumbnail_mode_callback) list_button.pressed.connect(set_list_mode_callback) -func _on_favorites_list_gui_input(event : InputEvent) -> void: - if event is InputEventKey and event.pressed and event.keycode == KEY_DELETE: - if not favorites_list.get_selected_items().is_empty(): - var fav = get_favorite_list() - fav.remove_at(favorites_list.get_selected_items()[0]) - favorites_list.remove_item(favorites_list.get_selected_items()[0]) - set_favorite_list(fav) - left_panel.accept_event() - -func _on_recents_list_gui_input(event : InputEvent) -> void: +func _on_recent_faves_list_gui_input(event : InputEvent, list : ItemList) -> void: + if _should_delete_recents_faves(event) and not list.get_selected_items().is_empty(): + var list_data = get_recent_list() if list == recents_list else get_favorite_list() + list_data.remove_at(list.get_selected_items()[0]) + list.remove_item(list.get_selected_items()[0]) + if list == recents_list: + set_recent_list(list_data) + else: + set_favorite_list(list_data) + left_panel.accept_event() + +func _should_delete_recents_faves(event : InputEvent) -> bool: if event is InputEventKey and event.pressed and event.keycode == KEY_DELETE: - if not recents_list.get_selected_items().is_empty(): - var recents = get_recent_list() - recents.remove_at(recents_list.get_selected_items()[0]) - recents_list.remove_item(recents_list.get_selected_items()[0]) - set_recent_list(recents) - left_panel.accept_event() + return true + elif event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_RIGHT: + return OS.get_name() == "Android" + return false func _on_FileDialog_file_selected(path) -> void: emit_signal("return_paths", [ path ]) diff --git a/material_maker/windows/file_dialog/file_dialog.tscn b/material_maker/windows/file_dialog/file_dialog.tscn index fb97d662d6..22cff28dcc 100644 --- a/material_maker/windows/file_dialog/file_dialog.tscn +++ b/material_maker/windows/file_dialog/file_dialog.tscn @@ -10,6 +10,7 @@ ok_button_text = "Open" file_mode = 0 access = 2 script = ExtResource("1") +metadata/android_fullscreen_dim = true [connection signal="canceled" from="." to="." method="_on_FileDialog_popup_hide"] [connection signal="child_entered_tree" from="." to="." method="_on_child_entered_tree"] diff --git a/material_maker/windows/material_editor/export_editor.tscn b/material_maker/windows/material_editor/export_editor.tscn index 5bd2df39a4..feb1fae7de 100644 --- a/material_maker/windows/material_editor/export_editor.tscn +++ b/material_maker/windows/material_editor/export_editor.tscn @@ -37,6 +37,7 @@ oversampling_override = 1.0 title = "Material Export Editor" position = Vector2i(0, 36) script = ExtResource("2") +metadata/android_fullscreen_dim = true [node name="BG" type="ColorRect" parent="."] anchors_preset = 15 diff --git a/material_maker/windows/node_editor/node_editor.gd b/material_maker/windows/node_editor/node_editor.gd index f950428e1b..17c696449f 100644 --- a/material_maker/windows/node_editor/node_editor.gd +++ b/material_maker/windows/node_editor/node_editor.gd @@ -143,7 +143,8 @@ func _on_Functions_text_changed(): error_label.text = "Syntax error line "+str(globals_error_line+1)+": "+result.msg func _on_Sizer_minimum_size_changed(): - size = $Sizer.get_combined_minimum_size() + Vector2(4, 4) + if OS.get_name() != "Android": + size = $Sizer.get_combined_minimum_size() + Vector2(4, 4) # OK/Apply/Cancel buttons diff --git a/material_maker/windows/preferences/preference_touch_hint.gd b/material_maker/windows/preferences/preference_touch_hint.gd new file mode 100644 index 0000000000..607f988890 --- /dev/null +++ b/material_maker/windows/preferences/preference_touch_hint.gd @@ -0,0 +1,62 @@ +extends Control + +var highlight : StyleBoxFlat + +var t : Tween + +func _ready() -> void: + if not OS.get_name() == "Android": + queue_free() + return + show() + + var panel_sb : StyleBoxFlat = get_theme_stylebox("panel") + panel_sb.set_corner_radius_all(3) + panel_sb.corner_detail = 3 + add_theme_stylebox_override("panel", panel_sb) + + highlight = StyleBoxFlat.new() + highlight.set_corner_radius_all(4) + highlight.corner_detail = 3 + highlight.bg_color = Color.WEB_GRAY + highlight.bg_color.a = 0.1 + highlight.set_expand_margin_all(4.0) + + var prefs : TabContainer = get_node("../TabContainer") + for tab in prefs.get_children(): + for container in tab.get_child(0).get_children(): + if container is not Container: + continue + for control : Control in container.get_children(): + if control.get_script() in [BoolOption, EnumOption, FloatOption]: + control.mouse_entered.connect(_item_mouse_entered.bind(container, control.tooltip_text)) + control.mouse_exited.connect(_item_mouse_exited.bind(container)) + container.mouse_entered.connect(_item_mouse_entered.bind(container, control.tooltip_text)) + container.mouse_exited.connect(_item_mouse_exited.bind(container)) + break + +func setup_tween() -> void: + var vs : VScrollBar = $MarginContainer/ScrollContainer.get_v_scroll_bar() + if t: + t.kill() + + # do not animate scroll if the text still fits + if abs(vs.max_value - $MarginContainer/ScrollContainer.size.y) > 5.0: + t = create_tween().set_loops() + t.tween_interval(1.5) + t.tween_property(vs, "ratio", 1.0, 1.5) + t.tween_interval(1.5) + t.tween_property(vs, "ratio", 0.0, 1.5) + +func _item_mouse_entered(c : Container, hint : String) -> void: + var hint_lb : Label = $MarginContainer/ScrollContainer/TouchHintLabel + highlight.draw.call_deferred(c.get_parent().get_canvas_item(), c.get_rect()) + hint_lb.text = hint.replacen("\n", " ") + setup_tween.call_deferred() + +func _item_mouse_exited(c : Container) -> void: + c.get_parent().queue_redraw() + var hint_lb : Label = $MarginContainer/ScrollContainer/TouchHintLabel + hint_lb.text = "" + if t: + t.kill.call_deferred() diff --git a/material_maker/windows/preferences/preference_touch_hint.gd.uid b/material_maker/windows/preferences/preference_touch_hint.gd.uid new file mode 100644 index 0000000000..c36e0989d9 --- /dev/null +++ b/material_maker/windows/preferences/preference_touch_hint.gd.uid @@ -0,0 +1 @@ +uid://c8mnypok072xm diff --git a/material_maker/windows/preferences/preferences.gd b/material_maker/windows/preferences/preferences.gd index 5c0e5a9900..642a8bf9e6 100644 --- a/material_maker/windows/preferences/preferences.gd +++ b/material_maker/windows/preferences/preferences.gd @@ -12,12 +12,16 @@ func edit_preferences(c : ConfigFile) -> void: config = c var main_window = mm_globals.main_window main_window.add_dialog(self) - config_changed.connect(main_window.on_config_changed) + config_changed.connect(mm_globals.preferences_updated.emit) content_scale_factor = mm_globals.ui_scale_factor() update_controls(self) - size *= content_scale_factor - hide() - popup_centered(size) + + if OS.get_name() == "Android": + mm_touch.make_dialog_fullscreen(self, true) + else: + size *= content_scale_factor + hide() + popup_centered(size) func update_controls(p : Node) -> void: for c in p.get_children(): @@ -72,3 +76,12 @@ func _on_DownloadLanguage_closed(): func _on_ready() -> void: %WinTabletDriver.visible = OS.get_name() == "Windows" %WinTabletDriverSpacer.visible = OS.get_name() == "Windows" + + %GuiSingleWindowMode.visible = OS.get_name() != "Android" + %GuiUseNativeFileDialogs.visible = OS.get_name() != "Android" + %IdleFPSLimit.visible = OS.get_name() != "Android" + %TouchFullScreen.visible = OS.get_name() == "Android" + + if OS.get_name() == "Android": + config_changed.connect(mm_touch.make_dialog_fullscreen.bind(self), + ConnectFlags.CONNECT_DEFERRED) diff --git a/material_maker/windows/preferences/preferences.tscn b/material_maker/windows/preferences/preferences.tscn index 7c381d3cc9..678467b67d 100644 --- a/material_maker/windows/preferences/preferences.tscn +++ b/material_maker/windows/preferences/preferences.tscn @@ -17,6 +17,7 @@ position = Vector2i(0, 36) size = Vector2i(700, 450) exclusive = true script = ExtResource("2") +metadata/android_fullscreen_dim = true [node name="HSplitContainer" type="HSplitContainer" parent="." unique_id=1807450959] anchors_preset = 15 @@ -161,6 +162,7 @@ step = 0.01 float_only = true [node name="GuiUseNativeFileDialogs" type="HBoxContainer" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer" unique_id=912910531] +unique_name_in_owner = true layout_mode = 2 [node name="Label" type="Label" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer/GuiUseNativeFileDialogs" unique_id=1637894285] @@ -195,6 +197,7 @@ flat = false config_variable = "dialog_dim_background" [node name="GuiSingleWindowMode" type="HBoxContainer" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer" unique_id=2099467585] +unique_name_in_owner = true layout_mode = 2 [node name="Label" type="Label" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer/GuiSingleWindowMode" unique_id=721519803] @@ -202,7 +205,7 @@ layout_mode = 2 mouse_filter = 1 text = "Single window mode (requires restart)" -[node name="GuiSingleWindowMode" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer/GuiSingleWindowMode" unique_id=1386250423 instance=ExtResource("1")] +[node name="SingleWindowMode" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer/GuiSingleWindowMode" unique_id=1386250423 instance=ExtResource("1")] custom_minimum_size = Vector2(200, 0) layout_mode = 2 size_flags_horizontal = 10 @@ -211,10 +214,6 @@ text = "On" flat = false config_variable = "ui_single_window_mode" -[node name="Spacer6" type="Control" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer" unique_id=2007307925] -custom_minimum_size = Vector2(0, 10) -layout_mode = 2 - [node name="GuiCustomThemeBase" type="HBoxContainer" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer" unique_id=2087466635] layout_mode = 2 @@ -357,6 +356,7 @@ unique_name_in_owner = true layout_mode = 2 [node name="Label" type="Label" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer/WinTabletDriver" unique_id=724900106] +visible = false layout_mode = 2 text = "Tablet Driver" @@ -420,6 +420,7 @@ step = 1.0 float_only = true [node name="IdleFPSLimit" type="HBoxContainer" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer" unique_id=918523289] +unique_name_in_owner = true layout_mode = 2 [node name="Label" type="Label" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer/IdleFPSLimit" unique_id=34014532] @@ -443,6 +444,24 @@ max_value = 20.0 step = 1.0 float_only = true +[node name="KeepScreenOn" type="HBoxContainer" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer" unique_id=1389077131] +layout_mode = 2 + +[node name="Label" type="Label" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer/KeepScreenOn" unique_id=1745336321] +layout_mode = 2 +size_flags_horizontal = 0 +mouse_filter = 1 +text = "Keep Screen On" + +[node name="KeepScreenOn" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer/KeepScreenOn" unique_id=760988835 instance=ExtResource("1")] +custom_minimum_size = Vector2(200, 0) +layout_mode = 2 +size_flags_horizontal = 10 +tooltip_text = "Whether screen should stay on after a period of inactivity (based on OS settings)" +text = "On" +flat = false +config_variable = "keep_screen_on" + [node name="Spacer4" type="Control" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer" unique_id=1280062657] custom_minimum_size = Vector2(0, 10) layout_mode = 2 @@ -690,6 +709,94 @@ text = "On" flat = false config_variable = "remember_anim_export" +[node name="Touch" type="ScrollContainer" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer" unique_id=881994305] +visible = false +layout_mode = 2 +theme_type_variation = &"MM_PreferenceTab" +metadata/_tab_index = 4 + +[node name="VBoxContainer" type="VBoxContainer" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/Touch" unique_id=276816290] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="TouchNodeActions" type="HBoxContainer" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/Touch/VBoxContainer" unique_id=1309858269] +layout_mode = 2 + +[node name="Label" type="Label" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/Touch/VBoxContainer/TouchNodeActions" unique_id=895456211] +layout_mode = 2 +text = "Enable node actions panel (requires restart)" + +[node name="NodeActions" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/Touch/VBoxContainer/TouchNodeActions" unique_id=307131792 instance=ExtResource("1")] +custom_minimum_size = Vector2(200, 0) +layout_mode = 2 +size_flags_horizontal = 10 +tooltip_text = "A touch-friendly panel that provides access to common actions +(such as delete, minimize, randomize etc.) for selected node(s) in graph panel. + +This is enabled by default on Android." +text = "On" +flat = false +config_variable = "touch_node_actions" + +[node name="TouchOptimizations" type="HBoxContainer" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/Touch/VBoxContainer" unique_id=315705879] +layout_mode = 2 + +[node name="Label" type="Label" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/Touch/VBoxContainer/TouchOptimizations" unique_id=1640622729] +layout_mode = 2 +text = "Enable touch optimizations (requires restart)" + +[node name="TouchOptimize" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/Touch/VBoxContainer/TouchOptimizations" unique_id=1259798418 instance=ExtResource("1")] +custom_minimum_size = Vector2(200, 0) +layout_mode = 2 +size_flags_horizontal = 10 +tooltip_text = "When enabled, this increases the touch area of scrollbars, makes vertical seperation between popup menu items +larger, enables a touch dragger for panel splits etc. to increase usability on smaller screens. + +This is enabled by default on Android." +text = "On" +flat = false +config_variable = "touch_optimization" + +[node name="TouchFullScreen" type="HBoxContainer" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/Touch/VBoxContainer" unique_id=860528142] +unique_name_in_owner = true +layout_mode = 2 + +[node name="Label" type="Label" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/Touch/VBoxContainer/TouchFullScreen" unique_id=93076913] +layout_mode = 2 +text = "Enable full screen" + +[node name="FullScreen" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/Touch/VBoxContainer/TouchFullScreen" unique_id=1590147791 instance=ExtResource("1")] +custom_minimum_size = Vector2(200, 0) +layout_mode = 2 +size_flags_horizontal = 10 +tooltip_text = "When enabled, this extends the window towards screen edges." +text = "On" +flat = false +config_variable = "touch_full_screen" + +[node name="PreferenceTouchHint" type="PanelContainer" parent="HSplitContainer/PreferencesPanel/VBoxContainer" unique_id=328849096] +visible = false +layout_mode = 2 +theme_type_variation = &"MM_PanelBackground" + +[node name="MarginContainer" type="MarginContainer" parent="HSplitContainer/PreferencesPanel/VBoxContainer/PreferenceTouchHint" unique_id=508458780] +layout_mode = 2 +theme_override_constants/margin_left = 6 +theme_override_constants/margin_top = 6 +theme_override_constants/margin_right = 6 +theme_override_constants/margin_bottom = 6 + +[node name="ScrollContainer" type="ScrollContainer" parent="HSplitContainer/PreferencesPanel/VBoxContainer/PreferenceTouchHint/MarginContainer" unique_id=1664878493] +custom_minimum_size = Vector2(0, 60) +custom_maximum_size = Vector2(-1, 60) +layout_mode = 2 + +[node name="TouchHintLabel" type="Label" parent="HSplitContainer/PreferencesPanel/VBoxContainer/PreferenceTouchHint/MarginContainer/ScrollContainer" unique_id=1926624238] +custom_minimum_size = Vector2(1, 0) +layout_mode = 2 +size_flags_horizontal = 3 +autowrap_mode = 3 + [node name="MarginContainer" type="MarginContainer" parent="HSplitContainer/PreferencesPanel/VBoxContainer" unique_id=245791047] layout_mode = 2 theme_override_constants/margin_top = 4 diff --git a/material_maker/windows/sdf_builder/preview_3d.gd b/material_maker/windows/sdf_builder/preview_3d.gd index a760959466..210487a99d 100644 --- a/material_maker/windows/sdf_builder/preview_3d.gd +++ b/material_maker/windows/sdf_builder/preview_3d.gd @@ -121,7 +121,7 @@ func _on_Preview3D_resized(): viewport.size = size update_viewport() -func navigation_input(ev) -> bool: +func navigation_input(ev : InputEvent) -> bool: if ! get_global_rect().has_point(get_global_mouse_position()): return false if ev is InputEventMouseMotion: @@ -152,8 +152,27 @@ func navigation_input(ev) -> bool: if zoom != 0.0: camera.translate(Vector3(0.0, 0.0, zoom*(1.0 if ev.shift_pressed else 0.1))) return true + elif ev is InputEventScreenDrag and ev.index == 0: + # one-finger drag: orbit + camera_rotation2.rotate_x(-0.01*ev.relative.y) + camera_rotation1.rotate_y(-0.01*ev.relative.x) + return true + elif ev is InputEventMagnifyGesture: + # two-finger pinch: zoom + camera.position.z /= ev.factor + return true + elif ev is InputEventPanGesture: + # two-finger pan: offset + var factor = camera.position.z + camera_position.translate(-factor/size.x*-4.0*ev.delta.x*camera.global_transform.basis.x) + camera_position.translate(factor/size.y*-4.0*ev.delta.y*camera.global_transform.basis.y) + return true return false +func _gui_input(event : InputEvent) -> void: + if event is InputEventMagnifyGesture or event is InputEventPanGesture: + _on_Background_input_event(null, event, null, null, null) + func _on_Background_input_event(_camera, event, _position, _normal, _shape_idx): if navigation_input(event): accept_event() diff --git a/material_maker/windows/sdf_builder/sdf_builder.gd b/material_maker/windows/sdf_builder/sdf_builder.gd index e618bacfb9..1729cf20b2 100644 --- a/material_maker/windows/sdf_builder/sdf_builder.gd +++ b/material_maker/windows/sdf_builder/sdf_builder.gd @@ -31,7 +31,7 @@ signal editor_window_closed const BUTTON_SHOWN = preload("res://material_maker/icons/eye_open.tres") const BUTTON_HIDDEN = preload("res://material_maker/icons/eye_closed.tres") - +var button_drag_hint : Texture2D func _ready(): tree.set_hide_root(true) @@ -45,9 +45,23 @@ func _ready(): await get_tree().process_frame content_scale_factor = mm_globals.ui_scale_factor() - min_size = Vector2(800, 400) * content_scale_factor - size = min_size - move_to_center() + + if OS.get_name() == "Android": + mm_touch.make_dialog_fullscreen(self, true) + var top_spacer : Control = Control.new() + top_spacer.custom_minimum_size.y = 24 + $TopContainer.add_child(top_spacer) + $TopContainer.move_child(top_spacer, 0) + $TopContainer/Main/Tree/AddMenuHint.text = "Tap and hold to add shapes" + else: + min_size = Vector2(800, 400) * content_scale_factor + size = min_size + move_to_center() + _update_tree_menu_hint_visibility() + +func _notification(what : int) -> void: + if what == NOTIFICATION_THEME_CHANGED: + button_drag_hint = get_theme_icon("drag_hint", "MM_Icons") func get_next_index() -> int: next_index += 1 @@ -154,9 +168,9 @@ func update_node_parameters_grid(): if button != null: button.disabled = true -func node_parameter_exists_already(name : String, param_index : int) -> bool: +func node_parameter_exists_already(_name : String, param_index : int) -> bool: for pi in range($GenSDF.node_parameters.size()): - if pi != param_index and $GenSDF.node_parameters[pi].name == name: + if pi != param_index and $GenSDF.node_parameters[pi].name == _name: return true return false @@ -253,9 +267,13 @@ func add_sdf_item(i : Dictionary, parent_item : TreeItem) -> TreeItem: var item_type = mm_sdf_builder.item_types[mm_sdf_builder.item_ids[i.type]] var item_icon = item_type.get("icon") if item_icon != null: - item.set_icon(0, item_icon) + var icon : Texture2D = item_icon + if mm_globals.get_config("touch_optimization"): + icon = resize_icon(item_icon, 24) + item.set_icon(0, icon) i.index = get_next_index() item.add_button(2, BUTTON_HIDDEN if i.has("hidden") and i.hidden else BUTTON_SHOWN, 0) + add_mobile_drag_hint_button(item, 1) item.set_meta("scene", i) set_sdf_scene(i.children, item) if i.has("collapsed") and i.collapsed: @@ -266,6 +284,7 @@ func rebuild_scene(item : TreeItem = tree.get_root()) -> Dictionary: var scene_list : Array = [] for child in item.get_children(): scene_list.push_back(rebuild_scene(child)) + _update_tree_menu_hint_visibility() if item == tree.get_root(): scene = scene_list return {} @@ -349,6 +368,11 @@ func _on_menu(id : int, current_item : TreeItem): MENU_DUMP: print(current_item.get_meta("scene")) +func resize_icon(icon : Texture2D, width : int, height = width) -> ImageTexture: + var img : Image = icon.get_image() + img.resize(width, height) + return ImageTexture.create_from_image(img) + func _on_menu_add_shape(id : int, current_item : TreeItem): var shape = mm_sdf_builder.item_types[id] var shape_name = shape.item_type @@ -369,24 +393,31 @@ func _on_menu_add_shape(id : int, current_item : TreeItem): current_item.get_meta("scene").children.push_back(data) var item_icon = shape.get("icon") if item_icon != null: - item.set_icon(0, item_icon) + var icon : Texture2D = item_icon + if mm_globals.get_config("touch_optimization"): + icon = resize_icon(item_icon, 24) + item.set_icon(0, icon) data.index = get_next_index() item.set_text(0, shape_name) item.set_meta("scene", data) item.add_button(2, BUTTON_SHOWN, 0) + add_mobile_drag_hint_button(item, 1) set_preview(scene) item.select(0) + _update_tree_menu_hint_visibility() func _on_Tree_item_edited(): var item : TreeItem = tree.get_selected() + if not item: + return item.set_editable(0, false) var item_scene : Dictionary = item.get_meta("scene") - var name : String = item.get_text(0) - if name == "" or name == item_scene.type: + var _name : String = item.get_text(0) + if _name == "" or _name == item_scene.type: item_scene.erase("name") item.set_text(0, item_scene.type) else: - item_scene.name = name + item_scene.name = _name func _on_Tree_item_collapsed(item): var item_scene : Dictionary = item.get_meta("scene") @@ -623,16 +654,18 @@ func _on_Tree_item_selected(): preview_3d.setup_controls("n%d" % index) $GenSDF.set_parameter("index", float(index)) -func _on_tree_button_clicked(item, _column, _id, mouse_button_index): +func _on_tree_button_clicked(item : Variant, _column : Variant, + id : int, mouse_button_index : Variant): if mouse_button_index != MOUSE_BUTTON_LEFT: return var item_scene : Dictionary = item.get_meta("scene") - if item_scene.has("hidden") and item_scene.hidden: - item_scene.erase("hidden") - item.set_button(2, 0, BUTTON_SHOWN) - else: - item_scene.hidden = true - item.set_button(2, 0, BUTTON_HIDDEN) + if id == 0: + if item_scene.has("hidden") and item_scene.hidden: + item_scene.erase("hidden") + item.set_button(2, 0, BUTTON_SHOWN) + else: + item_scene.hidden = true + item.set_button(2, 0, BUTTON_HIDDEN) set_preview(scene) _on_Tree_item_selected() @@ -658,16 +691,17 @@ func duplicate_item(item : TreeItem, parent : TreeItem, index : int = -1): new_item.set_text(0, item.get_text(0)) new_item.set_icon(0, item.get_icon(0)) new_item.add_button(2, item.get_button(2, 0), 0) + add_mobile_drag_hint_button(new_item, 1) new_item.set_meta("scene", item.get_meta("scene")) for c in item.get_children(): duplicate_item(c, new_item) return new_item -func move_item(item, dest, position): +func move_item(item, dest, target_position): var source_transform : Transform3D = get_item_transform_3d(item) var dest_transform : Transform3D = get_item_transform_3d(dest) var new_transform : Transform3D = dest_transform.affine_inverse()*source_transform - var new_item : TreeItem = duplicate_item(item, dest, position) + var new_item : TreeItem = duplicate_item(item, dest, target_position) item.get_parent().remove_child(item) # update copy's transform parameters rebuild_scene() @@ -686,8 +720,8 @@ func move_item(item, dest, position): parameters["n%d_position_z" % index] = new_transform.origin.z set_node_parameters($GenSDF, parameters) -func _on_Tree_drop_item(item, dest, position): - move_item(item, dest, position) +func _on_Tree_drop_item(item, dest, target_position): + move_item(item, dest, target_position) # OK/Apply/Cancel buttons @@ -744,3 +778,16 @@ func _input(event): func _on_VBoxContainer_minimum_size_changed(): min_size = $TopContainer.get_combined_minimum_size()+Vector2(4, 4) + +func _update_tree_menu_hint_visibility() -> void: + var should_show : bool = tree.get_root().get_child_count() == 0 + $TopContainer/Main/Tree/AddMenuHint.visible = should_show + +#region android specific + +func add_mobile_drag_hint_button(item : TreeItem, id : int = -1) -> void: + if OS.get_name() == "Android": + item.add_button(3, button_drag_hint, id) + item.set_icon_modulate(3, Color.RED) + +#endregion diff --git a/material_maker/windows/sdf_builder/sdf_builder.tscn b/material_maker/windows/sdf_builder/sdf_builder.tscn index c790d96f68..606ef1bb61 100644 --- a/material_maker/windows/sdf_builder/sdf_builder.tscn +++ b/material_maker/windows/sdf_builder/sdf_builder.tscn @@ -30,6 +30,7 @@ title = "Easy SDF" position = Vector2i(0, 36) exclusive = true script = ExtResource("3") +metadata/android_fullscreen_dim = true [node name="TopContainer" type="VBoxContainer" parent="."] custom_minimum_size = Vector2(800, 400) @@ -53,10 +54,27 @@ custom_minimum_size = Vector2(200, 200) layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 -columns = 3 +columns = 4 select_mode = 1 +auto_tooltip = false script = ExtResource("4") +[node name="AddMenuHint" type="Label" parent="TopContainer/Main/Tree" unique_id=909843201] +modulate = Color(1, 1, 1, 0.5176471) +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -20.0 +offset_top = -11.5 +offset_right = 20.0 +offset_bottom = 11.5 +grow_horizontal = 2 +grow_vertical = 2 +text = "Right click to add shapes" + [node name="Preview2D" parent="TopContainer/Main" instance=ExtResource("2")] unique_name_in_owner = true material = SubResource("ShaderMaterial_pgcwv") diff --git a/material_maker/windows/sdf_builder/sdf_builder_tree.gd b/material_maker/windows/sdf_builder/sdf_builder_tree.gd index 5ec2a8d188..45eea0d62e 100644 --- a/material_maker/windows/sdf_builder/sdf_builder_tree.gd +++ b/material_maker/windows/sdf_builder/sdf_builder_tree.gd @@ -1,5 +1,6 @@ extends Tree +var tree_scrollbar : VScrollBar signal drop_item(item, dest, position) @@ -9,6 +10,47 @@ func _ready(): set_column_custom_minimum_width(1, 28) set_column_expand(2, false) set_column_custom_minimum_width(2, 28) + set_column_expand(3, false) + set_column_custom_minimum_width(3, 32) + + if mm_globals.get_config("touch_optimization"): + add_theme_constant_override("v_separation", 12) + + for node in get_children(true): + if node is VScrollBar: + tree_scrollbar = node + +func get_drag_handle_pos(item : TreeItem) -> float: + if not item: + return 0.0 + var scroll_w : float = 0.0 + if tree_scrollbar.visible: + scroll_w = tree_scrollbar.size.x + var item_w : float = get_item_area_rect(item).size.x + return maxf(item_w - scroll_w - 72.0, 0.0) + +var dragged_from_handle : bool = false + +func _gui_input(event : InputEvent) -> void: + if event is InputEventMouseButton: + if event.device == InputEvent.DEVICE_ID_EMULATION: + accept_event() + elif event is InputEventScreenDrag and event.index == 0: + var item : TreeItem = get_item_at_position(event.position) + if not dragged_from_handle and item and event.position.x < get_drag_handle_pos(item): + tree_scrollbar.value -= event.relative.y + accept_event() + elif event is InputEventScreenTouch and event.index == 0: + if event.pressed: + var item : TreeItem = get_item_at_position(event.position) + if item: + item.select(0, false) + if event.position.x > get_drag_handle_pos(item): + dragged_from_handle = true + else: + deselect_all() + else: + dragged_from_handle = false func get_sdf_item_type(item : TreeItem) -> Object: if item == null or not item.has_meta("scene"): @@ -29,11 +71,13 @@ func get_nearest_parent(item : TreeItem, type : String) -> TreeItem: item = item.get_parent() return item -func _get_drag_data(position): - var item : TreeItem = get_item_at_position(position) +func _get_drag_data(at_position : Vector2): + var item : TreeItem = get_item_at_position(at_position) if item == null: return null else: + if at_position.x < get_drag_handle_pos(item): + return null var label = Label.new() label.text = item.get_text(0) set_drag_preview(label) @@ -62,10 +106,10 @@ func get_valid_children_types(parent : TreeItem): valid_children_types.push_back(parent_type.item_category) return valid_children_types -func _can_drop_data(position, data): +func _can_drop_data(at_position : Vector2, data : Variant): if data is Dictionary and data.has("item") and data.item is TreeItem: - var destination : TreeItem = get_item_at_position(position) - if destination != null and get_drop_section_at_position(position) != 0: + var destination : TreeItem = get_item_at_position(at_position) + if destination != null and get_drop_section_at_position(at_position) != 0: destination = destination.get_parent() if not mm_sdf_builder.scene_get_type(data.item.get_meta("scene")).item_category in get_valid_children_types(destination): return false @@ -82,10 +126,10 @@ func get_item_index(item : TreeItem) -> int: index += 1 return -1 -func _drop_data(position, data): +func _drop_data(at_position : Vector2, data : Variant): if data is Dictionary and data.has("item") and data.item is TreeItem: - var item = get_item_at_position(position) - match get_drop_section_at_position(position): + var item = get_item_at_position(at_position) + match get_drop_section_at_position(at_position): 0: emit_signal("drop_item", data.item, item, -1) -1: diff --git a/no_export/android/adaptive_background.svg b/no_export/android/adaptive_background.svg new file mode 100644 index 0000000000..0dfac893f5 --- /dev/null +++ b/no_export/android/adaptive_background.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/no_export/android/adaptive_background.svg.import b/no_export/android/adaptive_background.svg.import new file mode 100644 index 0000000000..4812a947d7 --- /dev/null +++ b/no_export/android/adaptive_background.svg.import @@ -0,0 +1,3 @@ +[remap] + +importer="skip" diff --git a/no_export/android/adaptive_foreground.svg b/no_export/android/adaptive_foreground.svg new file mode 100644 index 0000000000..11adbb3d5d --- /dev/null +++ b/no_export/android/adaptive_foreground.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/no_export/android/adaptive_foreground.svg.import b/no_export/android/adaptive_foreground.svg.import new file mode 100644 index 0000000000..4812a947d7 --- /dev/null +++ b/no_export/android/adaptive_foreground.svg.import @@ -0,0 +1,3 @@ +[remap] + +importer="skip" diff --git a/no_export/android/adaptive_monochrome.svg b/no_export/android/adaptive_monochrome.svg new file mode 100644 index 0000000000..456ae0dbf4 --- /dev/null +++ b/no_export/android/adaptive_monochrome.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/no_export/android/adaptive_monochrome.svg.import b/no_export/android/adaptive_monochrome.svg.import new file mode 100644 index 0000000000..4812a947d7 --- /dev/null +++ b/no_export/android/adaptive_monochrome.svg.import @@ -0,0 +1,3 @@ +[remap] + +importer="skip" diff --git a/no_export/android/android_legacy_icon.webp b/no_export/android/android_legacy_icon.webp new file mode 100644 index 0000000000..993b80cafd Binary files /dev/null and b/no_export/android/android_legacy_icon.webp differ diff --git a/no_export/android/android_legacy_icon.webp.import b/no_export/android/android_legacy_icon.webp.import new file mode 100644 index 0000000000..4812a947d7 --- /dev/null +++ b/no_export/android/android_legacy_icon.webp.import @@ -0,0 +1,3 @@ +[remap] + +importer="skip" diff --git a/project.godot b/project.godot index 9b602ebfd4..5eb03560ae 100644 --- a/project.godot +++ b/project.godot @@ -20,7 +20,8 @@ config/tags=PackedStringArray("material_maker") run/main_scene="res://parse_args.tscn" config/use_custom_user_dir=true config/custom_user_dir_name="material_maker_2" -config/features=PackedStringArray("4.7") +config/quit_on_go_back=false +config/features=PackedStringArray("4.8") boot_splash/bg_color=Color(0, 0, 0, 1) boot_splash/show_image=false boot_splash/use_filter=false @@ -35,6 +36,7 @@ driver/driver="Dummy" [autoload] +mm_touch="*res://material_maker/touch.gd" mm_logger="*res://addons/material_maker/engine/logger.gd" mm_steam="*res://material_maker/steam.gd" mm_globals="*res://material_maker/globals.tscn" @@ -60,9 +62,9 @@ window/size/borderless=true window/size/transparent=true window/size/window_width_override=1 window/size/window_height_override=1 -window/per_pixel_transparency/allowed=true window/subwindows/embed_subwindows=false -window/handheld/orientation.Android="sensor_landscape" +window/per_pixel_transparency/allowed=true +window/per_pixel_transparency/allowed.android=false [editor] @@ -82,57 +84,257 @@ timers/tooltip_delay_sec=0.1 toggle_fullscreen={ "deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777254,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777221,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) -] +"events": [Object(InputEventKey, +"resource_local_to_scene": false, +"resource_name": "", +"device": 0, +"window_id": 0, +"alt_pressed": false, +"shift_pressed": false, +"ctrl_pressed": false, +"meta_pressed": false, +"pressed": false, +"keycode": 16777254, +"physical_keycode": 0, +"key_label": 0, +"unicode": 0, +"location": 0, +"echo": false, +"script": null +), Object(InputEventKey, +"resource_local_to_scene": false, +"resource_name": "", +"device": 0, +"window_id": 0, +"alt_pressed": true, +"shift_pressed": false, +"ctrl_pressed": false, +"meta_pressed": false, +"pressed": false, +"keycode": 16777221, +"physical_keycode": 0, +"key_label": 0, +"unicode": 0, +"location": 0, +"echo": false, +"script": null +)] } ui_library_popup={ "deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) -] +"events": [Object(InputEventKey, +"resource_local_to_scene": false, +"resource_name": "", +"device": 0, +"window_id": 0, +"alt_pressed": false, +"shift_pressed": false, +"ctrl_pressed": false, +"meta_pressed": false, +"pressed": false, +"keycode": 32, +"physical_keycode": 0, +"key_label": 0, +"unicode": 0, +"location": 0, +"echo": false, +"script": null +)] } ui_hierarchy_up={ "deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777220,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777218,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) -] +"events": [Object(InputEventKey, +"resource_local_to_scene": false, +"resource_name": "", +"device": 0, +"window_id": 0, +"alt_pressed": false, +"shift_pressed": false, +"ctrl_pressed": false, +"meta_pressed": false, +"pressed": false, +"keycode": 16777220, +"physical_keycode": 0, +"key_label": 0, +"unicode": 0, +"location": 0, +"echo": false, +"script": null +), Object(InputEventKey, +"resource_local_to_scene": false, +"resource_name": "", +"device": 0, +"window_id": 0, +"alt_pressed": false, +"shift_pressed": true, +"ctrl_pressed": false, +"meta_pressed": false, +"pressed": false, +"keycode": 16777218, +"physical_keycode": 0, +"key_label": 0, +"unicode": 0, +"location": 0, +"echo": false, +"script": null +)] } ui_hierarchy_down={ "deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777218,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) -] +"events": [Object(InputEventKey, +"resource_local_to_scene": false, +"resource_name": "", +"device": 0, +"window_id": 0, +"alt_pressed": false, +"shift_pressed": false, +"ctrl_pressed": false, +"meta_pressed": false, +"pressed": false, +"keycode": 16777218, +"physical_keycode": 0, +"key_label": 0, +"unicode": 0, +"location": 0, +"echo": false, +"script": null +)] } ui_toggle_docks={ "deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":true,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) -] +"events": [Object(InputEventKey, +"resource_local_to_scene": false, +"resource_name": "", +"device": 0, +"window_id": 0, +"alt_pressed": false, +"shift_pressed": false, +"ctrl_pressed": true, +"meta_pressed": true, +"pressed": false, +"keycode": 32, +"physical_keycode": 0, +"key_label": 0, +"unicode": 0, +"location": 0, +"echo": false, +"script": null +)] } ui_previous_tab={ "deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":true,"meta_pressed":true,"pressed":false,"keycode":16777218,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) -] +"events": [Object(InputEventKey, +"resource_local_to_scene": false, +"resource_name": "", +"device": 0, +"window_id": 0, +"alt_pressed": false, +"shift_pressed": true, +"ctrl_pressed": true, +"meta_pressed": true, +"pressed": false, +"keycode": 16777218, +"physical_keycode": 0, +"key_label": 0, +"unicode": 0, +"location": 0, +"echo": false, +"script": null +)] } ui_next_tab={ "deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":true,"pressed":false,"keycode":16777218,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) -] +"events": [Object(InputEventKey, +"resource_local_to_scene": false, +"resource_name": "", +"device": 0, +"window_id": 0, +"alt_pressed": false, +"shift_pressed": false, +"ctrl_pressed": true, +"meta_pressed": true, +"pressed": false, +"keycode": 16777218, +"physical_keycode": 0, +"key_label": 0, +"unicode": 0, +"location": 0, +"echo": false, +"script": null +)] } ui_cut_drag={ "deadzone": 0.5, -"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":false,"button_mask":2,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":2,"canceled":false,"pressed":true,"double_click":false,"script":null) -] +"events": [Object(InputEventMouseButton, +"resource_local_to_scene": false, +"resource_name": "", +"device": 0, +"window_id": 0, +"alt_pressed": false, +"shift_pressed": false, +"ctrl_pressed": true, +"meta_pressed": false, +"button_mask": 2, +"position": Vector2(0, 0), +"global_position": Vector2(0, 0), +"factor": 1.0, +"button_index": 2, +"canceled": false, +"pressed": true, +"double_click": false, +"script": null +)] } ui_lasso_select={ "deadzone": 0.5, -"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(391, 10),"global_position":Vector2(407, 91),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null) -] +"events": [Object(InputEventMouseButton, +"resource_local_to_scene": false, +"resource_name": "", +"device": -1, +"window_id": 0, +"alt_pressed": true, +"shift_pressed": false, +"ctrl_pressed": false, +"meta_pressed": false, +"button_mask": 1, +"position": Vector2(391, 10), +"global_position": Vector2(407, 91), +"factor": 1.0, +"button_index": 1, +"canceled": false, +"pressed": true, +"double_click": false, +"script": null +)] } left_click={ "deadzone": 0.2, -"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(80, 13),"global_position":Vector2(89, 61),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null) -] +"events": [Object(InputEventMouseButton, +"resource_local_to_scene": false, +"resource_name": "", +"device": -1, +"window_id": 0, +"alt_pressed": false, +"shift_pressed": false, +"ctrl_pressed": false, +"meta_pressed": false, +"button_mask": 1, +"position": Vector2(80, 13), +"global_position": Vector2(89, 61), +"factor": 1.0, +"button_index": 1, +"canceled": false, +"pressed": true, +"double_click": false, +"script": null +)] } +[input_devices] + +pointing/android/enable_long_press_as_right_click=true +pointing/android/enable_pan_and_scale_gestures=true + [internationalization] rendering/root_node_layout_direction=1 @@ -155,6 +357,7 @@ limits/debugger/max_chars_per_second=204800000 [rendering] +rendering_device/driver.ios="vulkan" rendering_device/driver.macos="vulkan" textures/vram_compression/import_etc2_astc=true shading/overrides/force_lambert_over_burley.mobile=false diff --git a/splash_screen/splash_screen.gd b/splash_screen/splash_screen.gd index d721c8da01..25b24c8191 100644 --- a/splash_screen/splash_screen.gd +++ b/splash_screen/splash_screen.gd @@ -12,7 +12,7 @@ var mm_scene : PackedScene = null const BACKGROUNDS_DIR : String = "res://splash_screen/backgrounds/" -const BACKGROUNDS : Array[Dictionary] = [ +var splash_backgrounds : Array[Dictionary] = [ { author="Angel", entries=[ { title="Beanbag Chair", file="angel_beanbag_chair.png" }, { title="Soft Nurball", file="angel_soft_nurball.png" }, @@ -101,6 +101,8 @@ const ACTIVITY_MESSAGES : Array[String] = [ ] func _enter_tree(): + if OS.get_name() == "Android": + android_filter_splash_screens() var date : Dictionary = Time.get_date_dict_from_system() var date_int : int = date.month*33+date.day var screen : int = 0 @@ -108,32 +110,42 @@ func _enter_tree(): _: randomize() var sum : float = 0.0 - for i in BACKGROUNDS.size(): - if BACKGROUNDS[i].has("odds"): - sum += BACKGROUNDS[i].odds + for i in splash_backgrounds.size(): + if splash_backgrounds[i].has("odds"): + sum += splash_backgrounds[i].odds else: sum += 1 var value : float = randf_range(0, sum) sum = 0.0 - for i in BACKGROUNDS.size(): - if BACKGROUNDS[i].has("odds"): - sum += BACKGROUNDS[i].odds + for i in splash_backgrounds.size(): + if splash_backgrounds[i].has("odds"): + sum += splash_backgrounds[i].odds else: sum += 1 if sum >= value: screen = i break set_screen(screen) + var window : Window = get_window() - var current_screen_index = window.current_screen - var ui_scale : int = 2 if DisplayServer.screen_get_dpi() >= 192 and DisplayServer.screen_get_size().x >= 2048 else 1 - window.position = (DisplayServer.screen_get_size(current_screen_index)-Vector2i(ui_scale*size))/2 + DisplayServer.screen_get_position(current_screen_index) - window.size = ui_scale*size + var ui_scale : int = _ui_scale() window.content_scale_factor = ui_scale + if OS.get_name() == "Android": + android_setup_margins() + android_setup_artwork_details_size() + $SplashScreen.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_COVERED + else: + var current_screen_index = window.current_screen + @warning_ignore("integer_division") + window.position = (DisplayServer.screen_get_size(current_screen_index)-Vector2i(ui_scale*size))/2 + DisplayServer.screen_get_position(current_screen_index) + window.size = ui_scale*size + +func _ui_scale() -> int: + return 2 if DisplayServer.screen_get_dpi() >= 192 and DisplayServer.screen_get_size().x >= 2048 else 1 func set_screen(bi : int, sub_index = -1) -> void: background_index = bi - var background : Dictionary = BACKGROUNDS[background_index] + var background : Dictionary = splash_backgrounds[background_index] var author : String = background.author if background.has("author") else "" var file : String = background.file if background.has("file") else "" var title : String = background.title if background.has("title") else "" @@ -173,6 +185,9 @@ func set_screen(bi : int, sub_index = -1) -> void: %Title.gui_input.disconnect(c.callable) func _ready(): + if OS.get_name() == "Android": + android_splash_fade_in() + await get_tree().create_timer(0.7).timeout set_process(false) resource_path = "res://material_maker/main_window.tscn" @@ -260,16 +275,16 @@ func _on_secret_button_gui_input(event): mm_steam.unlock_achievement("ACH_EAGLE_EYE") func _on_previous_pressed(): - if BACKGROUNDS[background_index].has("entries") and background_subindex > 0: + if splash_backgrounds[background_index].has("entries") and background_subindex > 0: set_screen(background_index, background_subindex-1) else: - set_screen(background_index-1 if background_index > 0 else BACKGROUNDS.size()-1, 1000) + set_screen(background_index-1 if background_index > 0 else splash_backgrounds.size()-1, 1000) func _on_next_pressed(): - if BACKGROUNDS[background_index].has("entries") and background_subindex < BACKGROUNDS[background_index].entries.size()-1: + if splash_backgrounds[background_index].has("entries") and background_subindex < splash_backgrounds[background_index].entries.size()-1: set_screen(background_index, background_subindex+1) else: - set_screen(background_index+1 if background_index < BACKGROUNDS.size()-1 else 0, 0) + set_screen(background_index+1 if background_index < splash_backgrounds.size()-1 else 0, 0) func _on_title_gui_input(event, url : String): if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: @@ -279,3 +294,61 @@ func _on_title_gui_input(event, url : String): func _on_url_gui_input(event): if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: OS.shell_open("https://www.materialmaker.org") + +#region android-specific + +func android_setup_artwork_details_size() -> void: + %URL.add_theme_font_size_override("font_size", 14) + %Title.add_theme_font_size_override("font_size", 22) + %Author.add_theme_font_size_override("font_size", 22) + +func android_setup_margins() -> void: + await get_tree().process_frame + var scale_fac : float = get_window().content_scale_factor + + custom_minimum_size = Vector2.ZERO + $SplashScreen.custom_minimum_size = Vector2.ZERO + var nine_patch : NinePatchRect = $SplashScreen/TextureRect/LogoExtend + var logo : TextureRect = $SplashScreen/TextureRect + set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + + var safe_margin_left : int = mm_touch.calc_margins(SIDE_LEFT, scale_fac) + var safe_margin_right : int = mm_touch.calc_margins(SIDE_RIGHT, scale_fac) + + # url / artwork details margins + $MarginContainer.add_theme_constant_override("margin_left", safe_margin_left) + $MarginContainer.add_theme_constant_override("margin_right", safe_margin_right) + $MarginContainer.add_theme_constant_override("margin_bottom", 12) + + # keep logo/progress bar within safe area + logo.position.x += safe_margin_left + nine_patch.position.x -= safe_margin_left + nine_patch.patch_margin_left = safe_margin_left + 4 + progress_bar.position.x -= safe_margin_left + progress_bar.size.x += safe_margin_left + +func android_filter_splash_screens() -> void: + # filter animated shaders + var filtered_backgrounds : Array[Dictionary] + for group in splash_backgrounds: + var entries : Array[Dictionary] = [] + if group.has("entries"): + for e in group.entries: + if e.file.get_extension() == "png": + entries.append(e) + if entries.is_empty(): + continue + group.entries = entries + filtered_backgrounds.append(group) + splash_backgrounds = filtered_backgrounds + +func android_splash_fade_in() -> void: + var darken : ColorRect = ColorRect.new() + darken.color = Color.BLACK + tree_exiting.connect(darken.queue_free) + add_child(darken) + var t : Tween = get_tree().create_tween() + t.set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT) + t.tween_property(darken, "color:a", 0.0, 0.6).set_delay(0.5) + +#endregion diff --git a/splash_screen/splash_screen.tscn b/splash_screen/splash_screen.tscn index cfad1586ef..93e3ac444e 100644 --- a/splash_screen/splash_screen.tscn +++ b/splash_screen/splash_screen.tscn @@ -44,8 +44,8 @@ offset_bottom = 40.0 script = ExtResource("1_q7nii") [node name="SplashScreen" type="TextureRect" parent="." unique_id=1261927513] -clip_contents = true custom_minimum_size = Vector2(760, 430) +clip_contents = true layout_mode = 2 texture = SubResource("PlaceholderTexture2D_jeaul") expand_mode = 1 @@ -53,9 +53,17 @@ expand_mode = 1 [node name="TextureRect" type="TextureRect" parent="SplashScreen" unique_id=547599219] layout_mode = 0 offset_top = 34.0 -offset_right = 500.0 -offset_bottom = 177.0 +offset_right = 503.00006 +offset_bottom = 178.0 +texture = ExtResource("2_uba88") + +[node name="LogoExtend" type="NinePatchRect" parent="SplashScreen/TextureRect" unique_id=512569899] +layout_mode = 1 +anchors_preset = 9 +anchor_bottom = 1.0 +grow_vertical = 2 texture = ExtResource("2_uba88") +region_rect = Rect2(0, 0, 25, 144) [node name="MM" type="Label" parent="SplashScreen/TextureRect" unique_id=1234938026] layout_mode = 0 @@ -139,18 +147,6 @@ anchor_bottom = 1.0 offset_top = 331.0 offset_bottom = 1.0 -[node name="URL" type="Label" parent="SplashScreen" unique_id=710870014] -unique_name_in_owner = true -layout_mode = 0 -offset_left = 4.0 -offset_top = 414.0 -offset_right = 134.0 -offset_bottom = 433.0 -mouse_filter = 0 -mouse_default_cursor_shape = 2 -theme_override_font_sizes/font_size = 11 -text = "materialmaker.org" - [node name="MarginContainer" type="MarginContainer" parent="." unique_id=986076381] layout_mode = 2 mouse_filter = 2 @@ -160,10 +156,24 @@ theme_override_constants/margin_bottom = 3 [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer" unique_id=383891881] layout_mode = 2 -size_flags_horizontal = 8 size_flags_vertical = 8 alignment = 2 +[node name="URLSpacer" type="Control" parent="MarginContainer/HBoxContainer" unique_id=1549656315] +custom_minimum_size = Vector2(2, 0) +layout_mode = 2 + +[node name="URL" type="Label" parent="MarginContainer/HBoxContainer" unique_id=710870014] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 2 +size_flags_vertical = 8 +mouse_filter = 0 +mouse_default_cursor_shape = 2 +theme_override_font_sizes/font_size = 11 +text = "materialmaker.org" +vertical_alignment = 2 + [node name="Title" type="Label" parent="MarginContainer/HBoxContainer" unique_id=736839233] unique_name_in_owner = true layout_mode = 2 @@ -251,6 +261,6 @@ mouse_filter = 2 texture = SubResource("AtlasTexture_587d8") [connection signal="gui_input" from="SplashScreen/TextureRect/SecretButton" to="." method="_on_secret_button_gui_input"] -[connection signal="gui_input" from="SplashScreen/URL" to="." method="_on_url_gui_input"] +[connection signal="gui_input" from="MarginContainer/HBoxContainer/URL" to="." method="_on_url_gui_input"] [connection signal="pressed" from="BackgroundSelect/Previous" to="." method="_on_previous_pressed"] [connection signal="pressed" from="BackgroundSelect/Next" to="." method="_on_next_pressed"]