├── .clang-format
├── .clang-tidy
├── .codespellrc
├── .gdlintrc
├── .gitattributes
├── .github
└── workflows
│ └── master.yml
├── .gitignore
├── .gitmodules
├── .markdownlint.yaml
├── LICENSE.md
├── README.md
├── SConstruct
├── demo
├── addons
│ └── native_dialogs
│ │ ├── icons
│ │ ├── native_accept_dialog.svg
│ │ ├── native_accept_dialog.svg.import
│ │ ├── native_confirmation_dialog.svg
│ │ ├── native_confirmation_dialog.svg.import
│ │ ├── native_file_dialog.svg
│ │ ├── native_file_dialog.svg.import
│ │ ├── native_notification.svg
│ │ └── native_notification.svg.import
│ │ ├── native_dialogs.gdextension
│ │ ├── plugin.cfg
│ │ └── plugin.gd
├── icon.png
├── icon.png.import
├── icons
│ ├── checked.png
│ ├── checked.png.import
│ ├── unchecked.png
│ └── unchecked.png.import
├── main.tscn
├── main_theme.tres
├── project.godot
└── scenes
│ ├── native_accept_dialog.gd
│ ├── native_accept_dialog.tscn
│ ├── native_confirmation_dialog.gd
│ ├── native_confirmation_dialog.tscn
│ ├── native_file_dialog.gd
│ ├── native_file_dialog.tscn
│ ├── native_notification.gd
│ └── native_notification.tscn
├── doc
├── images
│ ├── code_usage.png
│ ├── editor_usage.png
│ ├── native_accept_dialog.png
│ ├── native_confirmation_dialog.png
│ ├── native_dialogs_banner.png
│ ├── native_dialogs_icon.png
│ ├── native_file_dialog.png
│ ├── native_notification.png
│ └── windows_example.png
├── native_accept_dialog.md
├── native_confirmation_dialog.md
├── native_file_dialog.md
└── native_notification.md
└── src
├── native_accept_dialog.cpp
├── native_accept_dialog.h
├── native_confirmation_dialog.cpp
├── native_confirmation_dialog.h
├── native_file_dialog.cpp
├── native_file_dialog.h
├── native_notification.cpp
├── native_notification.h
├── register_types.cpp
└── register_types.h
/.clang-format:
--------------------------------------------------------------------------------
1 | # From Godot Engine's repository
2 | # Commented out parameters are those with the same value as base LLVM style.
3 | # We can uncomment them if we want to change their value, or enforce the
4 | # chosen value in case the base style changes (last sync: Clang 14.0).
5 | ---
6 | ### General config, applies to all languages ###
7 | BasedOnStyle: LLVM
8 | AccessModifierOffset: -4
9 | AlignAfterOpenBracket: DontAlign
10 | # AlignArrayOfStructures: None
11 | # AlignConsecutiveMacros: None
12 | # AlignConsecutiveAssignments: None
13 | # AlignConsecutiveBitFields: None
14 | # AlignConsecutiveDeclarations: None
15 | # AlignEscapedNewlines: Right
16 | AlignOperands: DontAlign
17 | AlignTrailingComments: false
18 | # AllowAllArgumentsOnNextLine: true
19 | AllowAllParametersOfDeclarationOnNextLine: false
20 | # AllowShortEnumsOnASingleLine: true
21 | # AllowShortBlocksOnASingleLine: Never
22 | # AllowShortCaseLabelsOnASingleLine: false
23 | # AllowShortFunctionsOnASingleLine: All
24 | # AllowShortLambdasOnASingleLine: All
25 | # AllowShortIfStatementsOnASingleLine: Never
26 | # AllowShortLoopsOnASingleLine: false
27 | # AlwaysBreakAfterDefinitionReturnType: None
28 | # AlwaysBreakAfterReturnType: None
29 | # AlwaysBreakBeforeMultilineStrings: false
30 | # AlwaysBreakTemplateDeclarations: MultiLine
31 | # AttributeMacros:
32 | # - __capability
33 | # BinPackArguments: true
34 | # BinPackParameters: true
35 | # BraceWrapping:
36 | # AfterCaseLabel: false
37 | # AfterClass: false
38 | # AfterControlStatement: Never
39 | # AfterEnum: false
40 | # AfterFunction: false
41 | # AfterNamespace: false
42 | # AfterObjCDeclaration: false
43 | # AfterStruct: false
44 | # AfterUnion: false
45 | # AfterExternBlock: false
46 | # BeforeCatch: false
47 | # BeforeElse: false
48 | # BeforeLambdaBody: false
49 | # BeforeWhile: false
50 | # IndentBraces: false
51 | # SplitEmptyFunction: true
52 | # SplitEmptyRecord: true
53 | # SplitEmptyNamespace: true
54 | # BreakBeforeBinaryOperators: None
55 | # BreakBeforeConceptDeclarations: true
56 | # BreakBeforeBraces: Attach
57 | # BreakBeforeInheritanceComma: false
58 | # BreakInheritanceList: BeforeColon
59 | # BreakBeforeTernaryOperators: true
60 | # BreakConstructorInitializersBeforeComma: false
61 | BreakConstructorInitializers: AfterColon
62 | # BreakStringLiterals: true
63 | ColumnLimit: 0
64 | # CommentPragmas: '^ IWYU pragma:'
65 | # QualifierAlignment: Leave
66 | # CompactNamespaces: false
67 | ConstructorInitializerIndentWidth: 8
68 | ContinuationIndentWidth: 8
69 | Cpp11BracedListStyle: false
70 | # DeriveLineEnding: true
71 | # DerivePointerAlignment: false
72 | # DisableFormat: false
73 | # EmptyLineAfterAccessModifier: Never
74 | # EmptyLineBeforeAccessModifier: LogicalBlock
75 | # ExperimentalAutoDetectBinPacking: false
76 | # PackConstructorInitializers: BinPack
77 | ConstructorInitializerAllOnOneLineOrOnePerLine: true
78 | # AllowAllConstructorInitializersOnNextLine: true
79 | # FixNamespaceComments: true
80 | # ForEachMacros:
81 | # - foreach
82 | # - Q_FOREACH
83 | # - BOOST_FOREACH
84 | # IfMacros:
85 | # - KJ_IF_MAYBE
86 | # IncludeBlocks: Preserve
87 | IncludeCategories:
88 | - Regex: '".*"'
89 | Priority: 1
90 | - Regex: '^<.*\.h>'
91 | Priority: 2
92 | - Regex: '^<.*'
93 | Priority: 3
94 | # IncludeIsMainRegex: '(Test)?$'
95 | # IncludeIsMainSourceRegex: ''
96 | # IndentAccessModifiers: false
97 | IndentCaseLabels: true
98 | # IndentCaseBlocks: false
99 | # IndentGotoLabels: true
100 | # IndentPPDirectives: None
101 | # IndentExternBlock: AfterExternBlock
102 | # IndentRequires: false
103 | IndentWidth: 4
104 | # IndentWrappedFunctionNames: false
105 | # InsertTrailingCommas: None
106 | # JavaScriptQuotes: Leave
107 | # JavaScriptWrapImports: true
108 | KeepEmptyLinesAtTheStartOfBlocks: false
109 | # LambdaBodyIndentation: Signature
110 | # MacroBlockBegin: ''
111 | # MacroBlockEnd: ''
112 | # MaxEmptyLinesToKeep: 1
113 | # NamespaceIndentation: None
114 | # PenaltyBreakAssignment: 2
115 | # PenaltyBreakBeforeFirstCallParameter: 19
116 | # PenaltyBreakComment: 300
117 | # PenaltyBreakFirstLessLess: 120
118 | # PenaltyBreakOpenParenthesis: 0
119 | # PenaltyBreakString: 1000
120 | # PenaltyBreakTemplateDeclaration: 10
121 | # PenaltyExcessCharacter: 1000000
122 | # PenaltyReturnTypeOnItsOwnLine: 60
123 | # PenaltyIndentedWhitespace: 0
124 | # PointerAlignment: Right
125 | # PPIndentWidth: -1
126 | # ReferenceAlignment: Pointer
127 | # ReflowComments: true
128 | # RemoveBracesLLVM: false
129 | # SeparateDefinitionBlocks: Leave
130 | # ShortNamespaceLines: 1
131 | # SortIncludes: CaseSensitive
132 | # SortJavaStaticImport: Before
133 | # SortUsingDeclarations: true
134 | # SpaceAfterCStyleCast: false
135 | # SpaceAfterLogicalNot: false
136 | # SpaceAfterTemplateKeyword: true
137 | # SpaceBeforeAssignmentOperators: true
138 | # SpaceBeforeCaseColon: false
139 | # SpaceBeforeCpp11BracedList: false
140 | # SpaceBeforeCtorInitializerColon: true
141 | # SpaceBeforeInheritanceColon: true
142 | # SpaceBeforeParens: ControlStatements
143 | # SpaceBeforeParensOptions:
144 | # AfterControlStatements: true
145 | # AfterForeachMacros: true
146 | # AfterFunctionDefinitionName: false
147 | # AfterFunctionDeclarationName: false
148 | # AfterIfMacros: true
149 | # AfterOverloadedOperator: false
150 | # BeforeNonEmptyParentheses: false
151 | # SpaceAroundPointerQualifiers: Default
152 | # SpaceBeforeRangeBasedForLoopColon: true
153 | # SpaceInEmptyBlock: false
154 | # SpaceInEmptyParentheses: false
155 | # SpacesBeforeTrailingComments: 1
156 | # SpacesInAngles: Never
157 | # SpacesInConditionalStatement: false
158 | # SpacesInContainerLiterals: true
159 | # SpacesInCStyleCastParentheses: false
160 | ## Godot TODO: We'll want to use a min of 1, but we need to see how to fix
161 | ## our comment capitalization at the same time.
162 | SpacesInLineCommentPrefix:
163 | Minimum: 0
164 | Maximum: -1
165 | # SpacesInParentheses: false
166 | # SpacesInSquareBrackets: false
167 | # SpaceBeforeSquareBrackets: false
168 | # BitFieldColonSpacing: Both
169 | # StatementAttributeLikeMacros:
170 | # - Q_EMIT
171 | # StatementMacros:
172 | # - Q_UNUSED
173 | # - QT_REQUIRE_VERSION
174 | TabWidth: 4
175 | # UseCRLF: false
176 | UseTab: Always
177 | # WhitespaceSensitiveMacros:
178 | # - STRINGIZE
179 | # - PP_STRINGIZE
180 | # - BOOST_PP_STRINGIZE
181 | # - NS_SWIFT_NAME
182 | # - CF_SWIFT_NAME
183 | ---
184 | ### C++ specific config ###
185 | Language: Cpp
186 | Standard: c++17
187 | ---
188 | ### ObjC specific config ###
189 | Language: ObjC
190 | # ObjCBinPackProtocolList: Auto
191 | ObjCBlockIndentWidth: 4
192 | # ObjCBreakBeforeNestedBlockParam: true
193 | # ObjCSpaceAfterProperty: false
194 | # ObjCSpaceBeforeProtocolList: true
195 | ---
196 | ### Java specific config ###
197 | Language: Java
198 | # BreakAfterJavaFieldAnnotations: false
199 | JavaImportGroups: ['org.godotengine', 'android', 'androidx', 'com.android', 'com.google', 'java', 'javax']
200 | ...
201 |
--------------------------------------------------------------------------------
/.clang-tidy:
--------------------------------------------------------------------------------
1 | # From Godot Engine's repository
2 | ---
3 | Checks: 'clang-diagnostic-*,clang-analyzer-*,-*,cppcoreguidelines-pro-type-member-init,modernize-redundant-void-arg,modernize-use-bool-literals,modernize-use-default-member-init,modernize-use-nullptr,readability-braces-around-statements,readability-redundant-member-init'
4 | WarningsAsErrors: ''
5 | HeaderFilterRegex: ''
6 | AnalyzeTemporaryDtors: false
7 | FormatStyle: none
8 | CheckOptions:
9 | - key: cert-dcl16-c.NewSuffixes
10 | value: 'L;LL;LU;LLU'
11 | - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
12 | value: '0'
13 | - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors
14 | value: '1'
15 | - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
16 | value: '1'
17 | - key: cppcoreguidelines-pro-type-member-init.IgnoreArrays
18 | value: '1'
19 | - key: cppcoreguidelines-pro-type-member-init.UseAssignment
20 | value: '1'
21 | - key: google-readability-function-size.StatementThreshold
22 | value: '800'
23 | - key: google-readability-namespace-comments.ShortNamespaceLines
24 | value: '10'
25 | - key: google-readability-namespace-comments.SpacesBeforeComments
26 | value: '2'
27 | - key: modernize-loop-convert.MaxCopySize
28 | value: '16'
29 | - key: modernize-loop-convert.MinConfidence
30 | value: reasonable
31 | - key: modernize-loop-convert.NamingStyle
32 | value: CamelCase
33 | - key: modernize-pass-by-value.IncludeStyle
34 | value: llvm
35 | - key: modernize-replace-auto-ptr.IncludeStyle
36 | value: llvm
37 | - key: modernize-use-bool-literals.IgnoreMacros
38 | value: '0'
39 | - key: modernize-use-default-member-init.IgnoreMacros
40 | value: '0'
41 | - key: modernize-use-default-member-init.UseAssignment
42 | value: '1'
43 | - key: modernize-use-nullptr.NullMacros
44 | value: 'NULL'
45 | - key: readability-braces-around-statements.ShortStatementLines
46 | value: '0'
47 | ...
--------------------------------------------------------------------------------
/.codespellrc:
--------------------------------------------------------------------------------
1 | [codespell]
2 | skip = godot-cpp,portable-file-dialogs
3 | builtin = en-GB_to_en-US
4 |
--------------------------------------------------------------------------------
/.gdlintrc:
--------------------------------------------------------------------------------
1 | class-definitions-order:
2 | - tools
3 | - classnames
4 | - extends
5 | - signals
6 | - enums
7 | - consts
8 | - exports
9 | - pubvars
10 | - prvvars
11 | - onreadypubvars
12 | - onreadyprvvars
13 | - others
14 | class-load-variable-name: (([A-Z][a-z0-9]*)+|_?[a-z][a-z0-9]*(_[a-z0-9]+)*)
15 | class-name: ([A-Z][a-z0-9]*)+
16 | class-variable-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)*
17 | comparison-with-itself: null
18 | constant-name: '[A-Z][A-Z0-9]*(_[A-Z0-9]+)*'
19 | disable: []
20 | duplicated-load: null
21 | enum-element-name: '[A-Z][A-Z0-9]*(_[A-Z0-9]+)*'
22 | enum-name: ([A-Z][a-z0-9]*)+
23 | excluded_directories: !!set
24 | .git: null
25 | expression-not-assigned: null
26 | function-argument-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)*
27 | function-arguments-number: 10
28 | function-name: (_on_([A-Z][a-z0-9]*)+(_[a-z0-9]+)*|_?[a-z][a-z0-9]*(_[a-z0-9]+)*)
29 | function-preload-variable-name: ([A-Z][a-z0-9]*)+
30 | function-variable-name: '[a-z][a-z0-9]*(_[a-z0-9]+)*'
31 | load-constant-name: (([A-Z][a-z0-9]*)+|[A-Z][A-Z0-9]*(_[A-Z0-9]+)*)
32 | loop-variable-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)*
33 | max-file-lines: 1000
34 | max-line-length: 100
35 | max-public-methods: 20
36 | max-returns: 6
37 | mixed-tabs-and-spaces: null
38 | no-elif-return: null
39 | no-else-return: null
40 | private-method-call: null
41 | signal-name: '[a-z][a-z0-9]*(_[a-z0-9]+)*'
42 | sub-class-name: _?([A-Z][a-z0-9]*)+
43 | tab-characters: 1
44 | trailing-whitespace: null
45 | unnecessary-pass: null
46 | unused-argument: null
47 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.c eol=lf
2 | *.cpp eol=lf
3 | *.gd eol=lf
4 | *.tscn eol=lf
5 | *.cfg eol=lf
6 | *.godot eol=lf
7 | *.tres eol=lf
8 | *.gdnlib eol=lf
9 | *.gdns eol=lf
10 |
--------------------------------------------------------------------------------
/.github/workflows/master.yml:
--------------------------------------------------------------------------------
1 | name: 🌟 Master
2 |
3 | on:
4 | pull_request:
5 | branches: [master]
6 |
7 | concurrency:
8 | group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-macos
9 | cancel-in-progress: true
10 |
11 | jobs:
12 | gdscript:
13 | name: 💅 Linting / 🤖 GDScript
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v3
17 | - run: pip3 install "gdtoolkit==4.*"
18 | - run: bash -c 'for f in ./demo/**/*.gd; do gdlint "$f"; done'
19 |
20 | cplusplus:
21 | name: 💅 Linting / ➕ C++
22 | runs-on: ubuntu-latest
23 | steps:
24 | - uses: actions/checkout@v3
25 | - uses: jidicula/clang-format-action@v4.9.0
26 | with:
27 | check-path: src
28 |
29 | markdown:
30 | name: 💅 Linting / 📝 Markdown
31 | runs-on: ubuntu-latest
32 | steps:
33 | - uses: actions/checkout@v3
34 | - uses: DavidAnson/markdownlint-cli2-action@v9
35 | with:
36 | globs: |
37 | README.md
38 | doc/**/*.md
39 |
40 | spelling:
41 | name: 💅 Linting / 👓 Spelling
42 | runs-on: ubuntu-latest
43 | steps:
44 | - uses: actions/checkout@v3
45 | - uses: codespell-project/actions-codespell@v1
46 |
47 | build:
48 | strategy:
49 | fail-fast: false
50 | matrix:
51 | include:
52 | - identifier: windows-debug
53 | os: windows-latest
54 | name: 🏗 Builds / 🪟 Windows Debug
55 | target: template_debug
56 | platform: windows
57 | arch: x86_64
58 |
59 | - identifier: windows-release
60 | os: windows-latest
61 | name: 🏗 Builds / 🪟 Windows Release
62 | target: template_release
63 | platform: windows
64 | arch: x86_64
65 |
66 | - identifier: macos-debug
67 | os: macos-latest
68 | name: 🏗 Builds / 🍎 macOS (universal) Debug
69 | target: template_debug
70 | platform: macos
71 | arch: universal
72 |
73 | - identifier: macos-release
74 | os: macos-latest
75 | name: 🏗 Builds / 🍎 macOS (universal) Release
76 | target: template_release
77 | platform: macos
78 | arch: universal
79 |
80 | - identifier: linux-debug
81 | os: ubuntu-latest
82 | name: 🏗 Builds / 🐧 Linux Debug
83 | runner: ubuntu-20.04
84 | target: template_debug
85 | platform: linux
86 | arch: x86_64
87 |
88 | - identifier: linux-release
89 | os: ubuntu-latest
90 | name: 🏗 Builds / 🐧 Linux Release
91 | runner: ubuntu-20.04
92 | target: template_release
93 | platform: linux
94 | arch: x86_64
95 |
96 | runs-on: ${{matrix.os}}
97 | name: ${{matrix.name}}
98 | steps:
99 | - name: Checkout project
100 | uses: actions/checkout@v3
101 | with:
102 | submodules: recursive
103 |
104 | - name: Set up Python
105 | uses: actions/setup-python@v4
106 | with:
107 | python-version: "3.x"
108 |
109 | - name: Set up SCons
110 | shell: bash
111 | run: |
112 | python -c "import sys; print(sys.version)"
113 | python -m pip install scons
114 | scons --version
115 |
116 | - name: Compile godot-cpp
117 | shell: sh
118 | run: |
119 | scons target='${{ matrix.target }}' platform='${{ matrix.platform }}' arch='${{ matrix.arch }}'
120 | working-directory: godot-cpp
121 |
122 | - name: Compile Extension
123 | shell: sh
124 | run: |
125 | scons target='${{ matrix.target }}' platform='${{ matrix.platform }}' arch='${{ matrix.arch }}'
126 |
127 | - name: Delete compilation files
128 | if: ${{ matrix.platform == 'windows' }}
129 | run: |
130 | Remove-Item demo/addons/native_dialogs/bin/* -Include *.exp,*.lib,*.pdb -Force
131 |
132 | - name: Upload binaries
133 | uses: actions/upload-artifact@v3
134 | with:
135 | name: binaries
136 | path: demo/addons/native_dialogs/bin/*
137 |
138 | package:
139 | name: 📦 Package
140 | needs: build
141 | runs-on: ubuntu-latest
142 | steps:
143 | - uses: actions/checkout@v3
144 |
145 | - name: Create addon
146 | run: |
147 | mkdir addons
148 | cp -R demo/addons/native_dialogs addons
149 | cp LICENSE.md addons/native_dialogs
150 | mkdir addons/native_dialogs/bin
151 |
152 | - name: Download binaries
153 | uses: actions/download-artifact@v3
154 | with:
155 | name: binaries
156 | path: addons/native_dialogs/bin
157 |
158 | - name: Create package
159 | run: |
160 | zip -r native_dialogs.zip addons
161 |
162 | - name: Upload addon
163 | uses: actions/upload-artifact@v3
164 | with:
165 | name: native_dialogs
166 | path: native_dialogs.zip
167 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 | zconf.h
3 | zconf.h.included
4 | *.o
5 | *.os
6 | .import/
7 | *.dblite
8 | *.exp
9 | *.lib
10 | *.obj
11 | *.TMP
12 | logs
13 | Thumbs.db
14 | **/bin/
15 | export_presets.cfg
16 | .vscode
17 | .godot
18 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "godot-cpp"]
2 | path = godot-cpp
3 | url = https://github.com/godotengine/godot-cpp
4 | [submodule "portable-file-dialogs"]
5 | path = portable-file-dialogs
6 | url = https://github.com/samhocevar/portable-file-dialogs
7 |
--------------------------------------------------------------------------------
/.markdownlint.yaml:
--------------------------------------------------------------------------------
1 | MD013: false
2 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Tomás Espejo Gómez
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Native Dialogs
2 |
3 | 
4 |
5 | > **Warning**
6 | > The main branch of this repository now supports Godot 4.x. If you are looking for the Godot 3.x version, please check [this branch](https://github.com/98teg/NativeDialogs/tree/godot-3.x).
7 |
8 | ## Introduction
9 |
10 | Native Dialogs is a plugin for Godot that allows you to interact with OS-specific dialogs, such as notifications, messages and file dialogs. It adds four new nodes that wrap the functionality of the C++ Library [portable-file-dialogs](https://github.com/samhocevar/portable-file-dialogs).
11 |
12 | [`NativeAcceptDialog`](./doc/native_accept_dialog.md) is useful for small notifications to the user about an event. [`NativeConfirmationDialog`](./doc/native_confirmation_dialog.md) allows you to prompt the user about confirmation of actions. [`NativeNotification`](./doc/native_notification.md) would show the user a brief message and then fade away. And [`NativeFileDialog`](./doc/native_file_dialog.md) is used to choose files and directories in the filesystem.
13 |
14 | It supports the following operating systems:
15 |
16 | * Windows
17 | * MacOS
18 | * Linux
19 |
20 | Please note that this plugin follows [Godot's file paths format](https://docs.godotengine.org/en/stable/tutorials/io/data_paths.html), and it uses [`ProjectSettings`' `globalize_path` method](https://docs.godotengine.org/en/stable/classes/class_projectsettings.html?highlight=ProjectSettings#class-projectsettings-method-globalize-path) to resolve `user://`, and `res://`, so consult the documentation if you have any doubt.
21 |
22 | ## How to use it
23 |
24 | As previously said, this plugin adds four new nodes. To use any of these nodes' functionality, you first need to add them to the scene. Then, update any of their properties if necessary. You also need to connect their signals to any method if you want to process the user's input. Finally, call the node's function that shows the native dialog to the user.
25 |
26 | ### Using the editor
27 |
28 | Probably the more intuitive way of using this plugin:
29 |
30 | 1. Instantiate a Native Dialog's node in your scene.
31 | 2. Change any of its properties, if needed.
32 | 3. Connect its signal if you want to process the user's input.
33 | 4. Make sure to call the `show` or `send` method of the Native Dialog's node. For example, via a button's signal.
34 |
35 | 
36 |
37 | ### Using code
38 |
39 | If you want to instantiate nodes using GDScript, you may follow this example:
40 |
41 | 1. Instantiate the desired node.
42 | 2. Change any of its attributes.
43 | 3. Connect its corresponding signals to the methods that would process the user's input.
44 | 4. Add it to the scene.
45 | 5. Call the `show` or `send` method when you need to show the native dialog.
46 |
47 | 
48 |
49 | ## How to build it
50 |
51 | Here is an overview on how to compile the plugin from source:
52 |
53 | 1. Check the [official Godot documentation](https://docs.godotengine.org/es/stable/development/compiling/index.html) on how to compile the engine. You won't need to compile it, but it would help you install the necessary dependencies on your target platform.
54 | 2. Clone this repository recursively:
55 |
56 | ```bash
57 | git clone --recursive https://github.com/98teg/NativeDialogs
58 | cd NativeDialogs
59 | ```
60 |
61 | 3. Build the C++ bindings:
62 |
63 | ```bash
64 | cd godot-cpp
65 | scons
66 | cd ..
67 | ```
68 |
69 | 4. Compile the plugin:
70 |
71 | ```bash
72 | scons
73 | ```
74 |
75 | 5. If you have encountered any problems, check the [official Godot documentation](https://docs.godotengine.org/en/stable/tutorials/scripting/gdextension/gdextension_cpp_example.html) on how to build a GDExtension plugin.
76 |
77 | ## Classes documentation
78 |
79 | For more information about this plugin's classes, check the following documentation:
80 |
81 | * [`NativeAcceptDialog`](./doc/native_accept_dialog.md)
82 | * [`NativeConfirmationDialog`](./doc/native_confirmation_dialog.md)
83 | * [`NativeFileDialog`](./doc/native_file_dialog.md)
84 | * [`NativeNotification`](./doc/native_notification.md)
85 |
--------------------------------------------------------------------------------
/SConstruct:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | env = SConscript("godot-cpp/SConstruct")
6 |
7 | # For the reference:
8 | # - CCFLAGS are compilation flags shared between C and C++
9 | # - CFLAGS are for C-specific compilation flags
10 | # - CXXFLAGS are for C++-specific compilation flags
11 | # - CPPFLAGS are for pre-processor flags
12 | # - CPPDEFINES are for pre-processor defines
13 | # - LINKFLAGS are for linking flags
14 |
15 | # portable-file-dialogs
16 | env.Append(CPPPATH=["portable-file-dialogs"])
17 |
18 | # tweak this if you want to use different folders, or more folders, to store your source code in.
19 | env.Append(CPPPATH=["src/"])
20 |
21 | # windows' libs
22 | if env["platform"] == "windows":
23 | env.Append(LIBS=["User32", "Shell32"])
24 |
25 | sources = Glob("src/*.cpp")
26 |
27 | if env["platform"] == "macos":
28 | library = env.SharedLibrary(
29 | "demo/addons/native_dialogs/bin/libnativedialogs.{}.{}.framework/libnativedialogs.{}.{}".format(
30 | env["platform"], env["target"], env["platform"], env["target"]
31 | ),
32 | source=sources,
33 | )
34 | else:
35 | library = env.SharedLibrary(
36 | "demo/addons/native_dialogs/bin/libnativedialogs{}{}".format(env["suffix"], env["SHLIBSUFFIX"]),
37 | source=sources,
38 | )
39 |
40 | Default(library)
41 |
--------------------------------------------------------------------------------
/demo/addons/native_dialogs/icons/native_accept_dialog.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/demo/addons/native_dialogs/icons/native_accept_dialog.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://byxb1khbmskho"
6 | path="res://.godot/imported/native_accept_dialog.svg-29bc0991aa5bf1244bb9d9d5fee5b403.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/native_dialogs/icons/native_accept_dialog.svg"
14 | dest_files=["res://.godot/imported/native_accept_dialog.svg-29bc0991aa5bf1244bb9d9d5fee5b403.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/demo/addons/native_dialogs/icons/native_confirmation_dialog.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/demo/addons/native_dialogs/icons/native_confirmation_dialog.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bqc06qvvvhcrs"
6 | path="res://.godot/imported/native_confirmation_dialog.svg-dc5b681628a3393fd579446b7fc6e9c2.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/native_dialogs/icons/native_confirmation_dialog.svg"
14 | dest_files=["res://.godot/imported/native_confirmation_dialog.svg-dc5b681628a3393fd579446b7fc6e9c2.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/demo/addons/native_dialogs/icons/native_file_dialog.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/demo/addons/native_dialogs/icons/native_file_dialog.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cw1rhuvsspl32"
6 | path="res://.godot/imported/native_file_dialog.svg-3682a30350fe181d2f98696f239d4dc8.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/native_dialogs/icons/native_file_dialog.svg"
14 | dest_files=["res://.godot/imported/native_file_dialog.svg-3682a30350fe181d2f98696f239d4dc8.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/demo/addons/native_dialogs/icons/native_notification.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/demo/addons/native_dialogs/icons/native_notification.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bfiq688swf5bg"
6 | path="res://.godot/imported/native_notification.svg-aeed5747dd1cc9332f06d2a8339dd62a.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/native_dialogs/icons/native_notification.svg"
14 | dest_files=["res://.godot/imported/native_notification.svg-aeed5747dd1cc9332f06d2a8339dd62a.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 | svg/scale=1.0
36 | editor/scale_with_editor_scale=false
37 | editor/convert_colors_with_editor_theme=false
38 |
--------------------------------------------------------------------------------
/demo/addons/native_dialogs/native_dialogs.gdextension:
--------------------------------------------------------------------------------
1 | [configuration]
2 |
3 | entry_symbol = "native_dialogs_init"
4 | compatibility_minimum = 4.1
5 |
6 | [icons]
7 |
8 | NativeAcceptDialog = "res://addons/native_dialogs/icons/native_accept_dialog.svg"
9 | NativeConfirmationDialog = "res://addons/native_dialogs/icons/native_confirmation_dialog.svg"
10 | NativeFileDialog = "res://addons/native_dialogs/icons/native_file_dialog.svg"
11 | NativeNotification = "res://addons/native_dialogs/icons/native_notification.svg"
12 |
13 | [libraries]
14 |
15 | macos.debug = "bin/libnativedialogs.macos.template_debug.framework"
16 | macos.release = "bin/libnativedialogs.macos.template_release.framework"
17 | windows.debug.x86_64 = "bin/libnativedialogs.windows.template_debug.x86_64.dll"
18 | windows.release.x86_64 = "bin/libnativedialogs.windows.template_release.x86_64.dll"
19 | linux.debug.x86_64 = "bin/libnativedialogs.linux.template_debug.x86_64.so"
20 | linux.release.x86_64 = "bin/libnativedialogs.linux.template_release.x86_64.so"
21 |
--------------------------------------------------------------------------------
/demo/addons/native_dialogs/plugin.cfg:
--------------------------------------------------------------------------------
1 | [plugin]
2 |
3 | name="Native Dialogs"
4 | description="Native Dialogs is a plugin for Godot that allows you to interact with OS-specific dialogs, such as notifications, messages and file dialogs. "
5 | author="Teggy"
6 | version="2.2.1"
7 | script="plugin.gd"
8 |
--------------------------------------------------------------------------------
/demo/addons/native_dialogs/plugin.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | extends EditorPlugin
3 |
4 | func _enter_tree():
5 | pass
6 |
7 | func _exit_tree():
8 | pass
9 |
--------------------------------------------------------------------------------
/demo/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/98teg/NativeDialogs/e829043a4d13214ec83b7b9912b4c62a3c0e21b6/demo/icon.png
--------------------------------------------------------------------------------
/demo/icon.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://drmcwcrrum2ru"
6 | path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://icon.png"
14 | dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 |
--------------------------------------------------------------------------------
/demo/icons/checked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/98teg/NativeDialogs/e829043a4d13214ec83b7b9912b4c62a3c0e21b6/demo/icons/checked.png
--------------------------------------------------------------------------------
/demo/icons/checked.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dgyx2waty8f13"
6 | path="res://.godot/imported/checked.png-a23913dbb696ec9fd4de8dd7991ed9f0.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://icons/checked.png"
14 | dest_files=["res://.godot/imported/checked.png-a23913dbb696ec9fd4de8dd7991ed9f0.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 |
--------------------------------------------------------------------------------
/demo/icons/unchecked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/98teg/NativeDialogs/e829043a4d13214ec83b7b9912b4c62a3c0e21b6/demo/icons/unchecked.png
--------------------------------------------------------------------------------
/demo/icons/unchecked.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cx3dk4v48aupp"
6 | path="res://.godot/imported/unchecked.png-e61615c556436a910b4fbed448ab715b.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://icons/unchecked.png"
14 | dest_files=["res://.godot/imported/unchecked.png-e61615c556436a910b4fbed448ab715b.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/lossy_quality=0.7
20 | compress/hdr_compression=1
21 | compress/bptc_ldr=0
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 |
--------------------------------------------------------------------------------
/demo/main.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=8 format=3 uid="uid://dsceba4s677re"]
2 |
3 | [ext_resource type="PackedScene" uid="uid://cyowfuspidj6l" path="res://scenes/native_accept_dialog.tscn" id="1_r21be"]
4 | [ext_resource type="Theme" uid="uid://dghnjlpplxvrd" path="res://main_theme.tres" id="1_xfap8"]
5 | [ext_resource type="PackedScene" uid="uid://bahfxvu3r7io" path="res://scenes/native_confirmation_dialog.tscn" id="2_35kej"]
6 | [ext_resource type="PackedScene" uid="uid://b3lywl2to6wuh" path="res://scenes/native_notification.tscn" id="3_hnvye"]
7 | [ext_resource type="PackedScene" uid="uid://bfhf2x2p1f5fv" path="res://scenes/native_file_dialog.tscn" id="3_mcjmb"]
8 |
9 | [sub_resource type="Gradient" id="Gradient_su64u"]
10 | colors = PackedColorArray(0.376471, 0.631373, 0.882353, 1, 0.67451, 0.980392, 0.988235, 1)
11 |
12 | [sub_resource type="GradientTexture2D" id="GradientTexture2D_7jcan"]
13 | gradient = SubResource("Gradient_su64u")
14 | fill_to = Vector2(0, 1)
15 |
16 | [node name="Main" type="TextureRect"]
17 | anchors_preset = 15
18 | anchor_right = 1.0
19 | anchor_bottom = 1.0
20 | grow_horizontal = 2
21 | grow_vertical = 2
22 | texture = SubResource("GradientTexture2D_7jcan")
23 |
24 | [node name="MarginContainer" type="MarginContainer" parent="."]
25 | layout_mode = 0
26 | anchor_right = 1.0
27 | anchor_bottom = 1.0
28 | grow_horizontal = 2
29 | grow_vertical = 2
30 | theme = ExtResource("1_xfap8")
31 | theme_override_constants/margin_top = 15
32 | theme_override_constants/margin_right = 15
33 | theme_override_constants/margin_bottom = 15
34 |
35 | [node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer"]
36 | layout_mode = 2
37 | size_flags_horizontal = 3
38 | size_flags_vertical = 3
39 | horizontal_scroll_mode = 0
40 |
41 | [node name="MarginContainer" type="MarginContainer" parent="MarginContainer/ScrollContainer"]
42 | layout_mode = 2
43 | size_flags_horizontal = 3
44 | theme_override_constants/margin_left = 60
45 | theme_override_constants/margin_top = 15
46 | theme_override_constants/margin_right = 45
47 | theme_override_constants/margin_bottom = 15
48 |
49 | [node name="HFlowContainer" type="HFlowContainer" parent="MarginContainer/ScrollContainer/MarginContainer"]
50 | layout_mode = 2
51 | theme_override_constants/h_separation = 45
52 | theme_override_constants/v_separation = 30
53 | alignment = 1
54 |
55 | [node name="NativeAcceptDialog" parent="MarginContainer/ScrollContainer/MarginContainer/HFlowContainer" instance=ExtResource("1_r21be")]
56 | custom_minimum_size = Vector2(720, 0)
57 | layout_mode = 2
58 |
59 | [node name="NativeConfirmationDialog" parent="MarginContainer/ScrollContainer/MarginContainer/HFlowContainer" instance=ExtResource("2_35kej")]
60 | custom_minimum_size = Vector2(720, 0)
61 | layout_mode = 2
62 |
63 | [node name="NativeFileDialog" parent="MarginContainer/ScrollContainer/MarginContainer/HFlowContainer" instance=ExtResource("3_mcjmb")]
64 | custom_minimum_size = Vector2(720, 0)
65 | layout_mode = 2
66 |
67 | [node name="NativeNotification" parent="MarginContainer/ScrollContainer/MarginContainer/HFlowContainer" instance=ExtResource("3_hnvye")]
68 | custom_minimum_size = Vector2(720, 0)
69 | layout_mode = 2
70 |
--------------------------------------------------------------------------------
/demo/project.godot:
--------------------------------------------------------------------------------
1 | ; Engine configuration file.
2 | ; It's best edited using the editor UI and not directly,
3 | ; since the parameters that go here are not all obvious.
4 | ;
5 | ; Format:
6 | ; [section] ; section goes between []
7 | ; param=value ; assign values to parameters
8 |
9 | config_version=5
10 |
11 | [application]
12 |
13 | config/name="Native Dialogs"
14 | run/main_scene="res://main.tscn"
15 | config/features=PackedStringArray("4.1")
16 | config/icon="res://icon.png"
17 |
18 | [debug]
19 |
20 | gdscript/warnings/shadowed_variable=0
21 |
22 | [editor_plugins]
23 |
24 | enabled=PackedStringArray("res://addons/native_dialogs/plugin.cfg")
25 |
26 | [rendering]
27 |
28 | environment/defaults/default_clear_color=Color(0.85098, 0.85098, 0.85098, 1)
29 | environment/default_environment="res://default_env.tres"
30 |
--------------------------------------------------------------------------------
/demo/scenes/native_accept_dialog.gd:
--------------------------------------------------------------------------------
1 | extends PanelContainer
2 |
3 |
4 | @onready var native_accept_dialog: NativeAcceptDialog = %_NativeAcceptDialog
5 | @onready var text: TextEdit = %_Text
6 | @onready var result: LineEdit = %_Result
7 |
8 |
9 | func text_changed():
10 | native_accept_dialog.set_text(text.text)
11 |
12 |
13 | func set_confirmed():
14 | result.text = "Confirmed"
15 |
16 |
17 | func set_canceled():
18 | result.text = "Canceled"
19 |
--------------------------------------------------------------------------------
/demo/scenes/native_accept_dialog.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://cyowfuspidj6l"]
2 |
3 | [ext_resource type="Theme" uid="uid://dghnjlpplxvrd" path="res://main_theme.tres" id="1_1bdvd"]
4 | [ext_resource type="Script" path="res://scenes/native_accept_dialog.gd" id="1_wtpim"]
5 |
6 | [node name="NativeAcceptDialog" type="PanelContainer"]
7 | anchors_preset = 15
8 | anchor_right = 1.0
9 | anchor_bottom = 1.0
10 | grow_horizontal = 2
11 | grow_vertical = 2
12 | size_flags_vertical = 3
13 | theme = ExtResource("1_1bdvd")
14 | script = ExtResource("1_wtpim")
15 |
16 | [node name="_NativeAcceptDialog" type="NativeAcceptDialog" parent="."]
17 | unique_name_in_owner = true
18 |
19 | [node name="MarginContainer" type="MarginContainer" parent="."]
20 | layout_mode = 2
21 | theme_override_constants/margin_left = 90
22 | theme_override_constants/margin_top = 60
23 | theme_override_constants/margin_right = 90
24 | theme_override_constants/margin_bottom = 60
25 |
26 | [node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
27 | layout_mode = 2
28 | size_flags_horizontal = 3
29 |
30 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer"]
31 | layout_mode = 2
32 | theme_type_variation = &"HeaderSmall"
33 | text = "NativeAcceptDialog"
34 |
35 | [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
36 | layout_mode = 2
37 |
38 | [node name="VBoxContainer1" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer"]
39 | custom_minimum_size = Vector2(150, 0)
40 | layout_mode = 2
41 | size_flags_horizontal = 3
42 | theme_override_constants/separation = 0
43 |
44 | [node name="Lable" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer1"]
45 | layout_mode = 2
46 | text = "Title"
47 |
48 | [node name="LineEdit" type="LineEdit" parent="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer1"]
49 | layout_mode = 2
50 | size_flags_horizontal = 3
51 | text = "Alert!"
52 | caret_blink = true
53 | caret_blink_interval = 0.5
54 |
55 | [node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer"]
56 | custom_minimum_size = Vector2(150, 0)
57 | layout_mode = 2
58 | theme_override_constants/separation = 0
59 |
60 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2"]
61 | layout_mode = 2
62 | text = "Icon"
63 |
64 | [node name="OptionButton" type="OptionButton" parent="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2"]
65 | layout_mode = 2
66 | item_count = 4
67 | selected = 1
68 | popup/item_0/text = "Info"
69 | popup/item_0/id = 0
70 | popup/item_1/text = "Warning"
71 | popup/item_1/id = 1
72 | popup/item_2/text = "Error"
73 | popup/item_2/id = 2
74 | popup/item_3/text = "Question"
75 | popup/item_3/id = 3
76 |
77 | [node name="VBoxContainer1" type="VBoxContainer" parent="MarginContainer/VBoxContainer"]
78 | layout_mode = 2
79 | theme_override_constants/separation = 0
80 |
81 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/VBoxContainer1"]
82 | layout_mode = 2
83 | text = "Text"
84 |
85 | [node name="_Text" type="TextEdit" parent="MarginContainer/VBoxContainer/VBoxContainer1"]
86 | unique_name_in_owner = true
87 | custom_minimum_size = Vector2(0, 90)
88 | layout_mode = 2
89 |
90 | [node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer/VBoxContainer"]
91 | layout_mode = 2
92 | theme_override_constants/separation = 0
93 |
94 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/VBoxContainer2"]
95 | layout_mode = 2
96 | text = "Result"
97 |
98 | [node name="_Result" type="LineEdit" parent="MarginContainer/VBoxContainer/VBoxContainer2"]
99 | unique_name_in_owner = true
100 | layout_mode = 2
101 | size_flags_horizontal = 3
102 | editable = false
103 |
104 | [node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer"]
105 | layout_mode = 2
106 | theme_override_constants/margin_top = 15
107 |
108 | [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/MarginContainer"]
109 | layout_mode = 2
110 | theme_override_constants/separation = 15
111 | alignment = 2
112 |
113 | [node name="Button1" type="Button" parent="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer"]
114 | layout_mode = 2
115 | size_flags_vertical = 4
116 | theme_type_variation = &"GhostButton"
117 | text = "Hide"
118 |
119 | [node name="Button2" type="Button" parent="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer"]
120 | layout_mode = 2
121 | size_flags_vertical = 4
122 | text = "Show"
123 |
124 | [connection signal="canceled" from="_NativeAcceptDialog" to="." method="set_canceled"]
125 | [connection signal="confirmed" from="_NativeAcceptDialog" to="." method="set_confirmed"]
126 | [connection signal="text_changed" from="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer1/LineEdit" to="_NativeAcceptDialog" method="set_title"]
127 | [connection signal="item_selected" from="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2/OptionButton" to="_NativeAcceptDialog" method="set_icon"]
128 | [connection signal="text_changed" from="MarginContainer/VBoxContainer/VBoxContainer1/_Text" to="." method="text_changed"]
129 | [connection signal="pressed" from="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer/Button1" to="_NativeAcceptDialog" method="hide"]
130 | [connection signal="pressed" from="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer/Button2" to="_NativeAcceptDialog" method="show"]
131 |
--------------------------------------------------------------------------------
/demo/scenes/native_confirmation_dialog.gd:
--------------------------------------------------------------------------------
1 | extends PanelContainer
2 |
3 |
4 | @onready var native_confirmation_dialog: NativeConfirmationDialog = %_NativeConfirmationDialog
5 | @onready var text: TextEdit = %_Text
6 | @onready var result: LineEdit = %_Result
7 |
8 |
9 | func text_changed():
10 | native_confirmation_dialog.set_text(text.text)
11 |
12 |
13 | func set_confirmed():
14 | result.text = "Confirmed"
15 |
16 |
17 | func set_canceled():
18 | result.text = "Canceled"
19 |
--------------------------------------------------------------------------------
/demo/scenes/native_confirmation_dialog.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://bahfxvu3r7io"]
2 |
3 | [ext_resource type="Script" path="res://scenes/native_confirmation_dialog.gd" id="1_1ix4v"]
4 | [ext_resource type="Theme" uid="uid://dghnjlpplxvrd" path="res://main_theme.tres" id="1_skr1f"]
5 |
6 | [node name="NativeConfirmationDialog" type="PanelContainer"]
7 | anchors_preset = 15
8 | anchor_right = 1.0
9 | anchor_bottom = 1.0
10 | grow_horizontal = 2
11 | grow_vertical = 2
12 | size_flags_vertical = 3
13 | theme = ExtResource("1_skr1f")
14 | script = ExtResource("1_1ix4v")
15 |
16 | [node name="_NativeConfirmationDialog" type="NativeConfirmationDialog" parent="."]
17 | unique_name_in_owner = true
18 |
19 | [node name="MarginContainer" type="MarginContainer" parent="."]
20 | offset_right = 1152.0
21 | offset_bottom = 648.0
22 | theme_override_constants/margin_left = 90
23 | theme_override_constants/margin_top = 60
24 | theme_override_constants/margin_right = 90
25 | theme_override_constants/margin_bottom = 60
26 |
27 | [node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
28 | offset_left = 90.0
29 | offset_top = 60.0
30 | offset_right = 1062.0
31 | offset_bottom = 588.0
32 | size_flags_horizontal = 3
33 |
34 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer"]
35 | offset_right = 972.0
36 | offset_bottom = 31.0
37 | theme_type_variation = &"HeaderSmall"
38 | text = "NativeConfirmationDialog"
39 |
40 | [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
41 | offset_top = 46.0
42 | offset_right = 972.0
43 | offset_bottom = 104.0
44 |
45 | [node name="VBoxContainer1" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer"]
46 | custom_minimum_size = Vector2(150, 0)
47 | offset_right = 612.0
48 | offset_bottom = 58.0
49 | size_flags_horizontal = 3
50 | theme_override_constants/separation = 0
51 |
52 | [node name="Lable" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer1"]
53 | offset_right = 612.0
54 | offset_bottom = 26.0
55 | text = "Title"
56 |
57 | [node name="LineEdit" type="LineEdit" parent="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer1"]
58 | offset_top = 26.0
59 | offset_right = 612.0
60 | offset_bottom = 58.0
61 | size_flags_horizontal = 3
62 | text = "Please Confirm..."
63 | caret_blink = true
64 | caret_blink_interval = 0.5
65 |
66 | [node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer"]
67 | custom_minimum_size = Vector2(150, 0)
68 | offset_left = 642.0
69 | offset_right = 792.0
70 | offset_bottom = 58.0
71 | theme_override_constants/separation = 0
72 |
73 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2"]
74 | offset_right = 150.0
75 | offset_bottom = 26.0
76 | text = "Icon"
77 |
78 | [node name="OptionButton" type="OptionButton" parent="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2"]
79 | offset_top = 26.0
80 | offset_right = 150.0
81 | offset_bottom = 58.0
82 | item_count = 4
83 | selected = 3
84 | popup/item_0/text = "Info"
85 | popup/item_0/id = 0
86 | popup/item_1/text = "Warning"
87 | popup/item_1/id = 1
88 | popup/item_2/text = "Error"
89 | popup/item_2/id = 2
90 | popup/item_3/text = "Question"
91 | popup/item_3/id = 3
92 |
93 | [node name="VBoxContainer3" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer"]
94 | custom_minimum_size = Vector2(150, 0)
95 | offset_left = 822.0
96 | offset_right = 972.0
97 | offset_bottom = 58.0
98 | theme_override_constants/separation = 0
99 |
100 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer3"]
101 | offset_right = 150.0
102 | offset_bottom = 26.0
103 | text = "Buttons Texts"
104 |
105 | [node name="OptionButton" type="OptionButton" parent="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer3"]
106 | offset_top = 26.0
107 | offset_right = 150.0
108 | offset_bottom = 58.0
109 | item_count = 2
110 | selected = 0
111 | popup/item_0/text = "OK Cancel"
112 | popup/item_0/id = 0
113 | popup/item_1/text = "Yes No"
114 | popup/item_1/id = 1
115 |
116 | [node name="VBoxContainer1" type="VBoxContainer" parent="MarginContainer/VBoxContainer"]
117 | offset_top = 119.0
118 | offset_right = 972.0
119 | offset_bottom = 235.0
120 | theme_override_constants/separation = 0
121 |
122 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/VBoxContainer1"]
123 | offset_right = 972.0
124 | offset_bottom = 26.0
125 | text = "Text"
126 |
127 | [node name="_Text" type="TextEdit" parent="MarginContainer/VBoxContainer/VBoxContainer1"]
128 | unique_name_in_owner = true
129 | custom_minimum_size = Vector2(0, 90)
130 | offset_top = 26.0
131 | offset_right = 972.0
132 | offset_bottom = 116.0
133 |
134 | [node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer/VBoxContainer"]
135 | offset_top = 250.0
136 | offset_right = 972.0
137 | offset_bottom = 308.0
138 | theme_override_constants/separation = 0
139 |
140 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/VBoxContainer2"]
141 | offset_right = 972.0
142 | offset_bottom = 26.0
143 | text = "Result"
144 |
145 | [node name="_Result" type="LineEdit" parent="MarginContainer/VBoxContainer/VBoxContainer2"]
146 | unique_name_in_owner = true
147 | offset_top = 26.0
148 | offset_right = 972.0
149 | offset_bottom = 58.0
150 | size_flags_horizontal = 3
151 | editable = false
152 |
153 | [node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer"]
154 | offset_top = 323.0
155 | offset_right = 972.0
156 | offset_bottom = 376.0
157 | theme_override_constants/margin_top = 15
158 |
159 | [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/MarginContainer"]
160 | offset_top = 15.0
161 | offset_right = 972.0
162 | offset_bottom = 53.0
163 | grow_horizontal = 2
164 | grow_vertical = 2
165 | theme_override_constants/separation = 15
166 | alignment = 2
167 |
168 | [node name="Button1" type="Button" parent="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer"]
169 | offset_left = 779.0
170 | offset_right = 864.0
171 | offset_bottom = 38.0
172 | size_flags_vertical = 4
173 | theme_type_variation = &"GhostButton"
174 | text = "Hide"
175 |
176 | [node name="Button2" type="Button" parent="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer"]
177 | offset_left = 879.0
178 | offset_right = 972.0
179 | offset_bottom = 38.0
180 | size_flags_vertical = 4
181 | text = "Show"
182 |
183 | [connection signal="canceled" from="_NativeConfirmationDialog" to="." method="set_canceled"]
184 | [connection signal="confirmed" from="_NativeConfirmationDialog" to="." method="set_confirmed"]
185 | [connection signal="text_changed" from="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer1/LineEdit" to="_NativeConfirmationDialog" method="set_title"]
186 | [connection signal="item_selected" from="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2/OptionButton" to="_NativeConfirmationDialog" method="set_icon"]
187 | [connection signal="item_selected" from="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer3/OptionButton" to="_NativeConfirmationDialog" method="set_buttons_texts"]
188 | [connection signal="text_changed" from="MarginContainer/VBoxContainer/VBoxContainer1/_Text" to="." method="text_changed"]
189 | [connection signal="pressed" from="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer/Button1" to="_NativeConfirmationDialog" method="hide"]
190 | [connection signal="pressed" from="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer/Button2" to="_NativeConfirmationDialog" method="show"]
191 |
--------------------------------------------------------------------------------
/demo/scenes/native_file_dialog.gd:
--------------------------------------------------------------------------------
1 | extends PanelContainer
2 |
3 |
4 | @onready var native_file_dialog: NativeFileDialog = %_NativeFileDialog
5 | @onready var title: LineEdit = %_Title
6 | @onready var overrides: CheckButton = %_Overrides
7 | @onready var filter: LineEdit = %_Filter
8 | @onready var description: LineEdit = %_Description
9 | @onready var filters: VBoxContainer = %_Filters
10 | @onready var result: LineEdit = %_Result
11 |
12 |
13 | func select_file_mode(file_mode):
14 | native_file_dialog.file_mode = file_mode
15 |
16 | override_title()
17 |
18 |
19 | func override_title():
20 | native_file_dialog.mode_overrides_title = overrides.button_pressed
21 |
22 | if native_file_dialog.mode_overrides_title:
23 | title.editable = false
24 | title.text = native_file_dialog.title
25 | else:
26 | title.editable = true
27 |
28 |
29 | func add_filter():
30 | native_file_dialog.add_filter(filter.text, description.text)
31 |
32 | filter.text = ""
33 | description.text = ""
34 |
35 | update_filters()
36 |
37 |
38 | func clear_filters():
39 | native_file_dialog.clear_filters()
40 |
41 | update_filters()
42 |
43 |
44 | func update_filters():
45 | for child in filters.get_children():
46 | child.queue_free()
47 |
48 | for filter in native_file_dialog.filters:
49 | var label = Label.new()
50 | label.text = filter
51 |
52 | filters.add_child(label)
53 |
54 |
55 | func file_selected(paths: String):
56 | files_selected([paths])
57 |
58 |
59 | func files_selected(paths: Array[String]):
60 | result.text = paths.reduce(
61 | func(paths, path): return path if paths == "" else paths + ", " + path, ""
62 | )
63 |
64 |
65 | func dialog_closed():
66 | result.text = ""
67 |
--------------------------------------------------------------------------------
/demo/scenes/native_file_dialog.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=5 format=3 uid="uid://bfhf2x2p1f5fv"]
2 |
3 | [ext_resource type="Script" path="res://scenes/native_file_dialog.gd" id="1_4eq6a"]
4 | [ext_resource type="Theme" uid="uid://dghnjlpplxvrd" path="res://main_theme.tres" id="1_kvkvm"]
5 |
6 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_h5ge7"]
7 | content_margin_left = 10.0
8 | content_margin_right = 10.0
9 | content_margin_bottom = 6.0
10 | bg_color = Color(1, 1, 1, 1)
11 | border_width_left = 3
12 | border_width_top = 3
13 | border_width_right = 3
14 | border_width_bottom = 3
15 | border_color = Color(0.909804, 0.909804, 0.909804, 1)
16 | border_blend = true
17 | corner_radius_top_left = 5
18 | corner_radius_top_right = 5
19 | corner_radius_bottom_right = 5
20 | corner_radius_bottom_left = 5
21 |
22 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_cvo7c"]
23 | content_margin_left = 10.0
24 | content_margin_right = 10.0
25 | content_margin_bottom = 6.0
26 | bg_color = Color(1, 1, 1, 1)
27 | border_width_left = 3
28 | border_width_top = 3
29 | border_width_right = 3
30 | border_width_bottom = 3
31 | border_color = Color(0.909804, 0.909804, 0.909804, 1)
32 | border_blend = true
33 | corner_radius_top_left = 5
34 | corner_radius_top_right = 5
35 | corner_radius_bottom_right = 5
36 | corner_radius_bottom_left = 5
37 |
38 | [node name="NativeFileDialog" type="PanelContainer"]
39 | anchors_preset = 15
40 | anchor_right = 1.0
41 | anchor_bottom = 1.0
42 | grow_horizontal = 2
43 | grow_vertical = 2
44 | size_flags_vertical = 3
45 | theme = ExtResource("1_kvkvm")
46 | script = ExtResource("1_4eq6a")
47 |
48 | [node name="_NativeFileDialog" type="NativeFileDialog" parent="."]
49 | unique_name_in_owner = true
50 |
51 | [node name="MarginContainer" type="MarginContainer" parent="."]
52 | layout_mode = 2
53 | theme_override_constants/margin_left = 90
54 | theme_override_constants/margin_top = 60
55 | theme_override_constants/margin_right = 90
56 | theme_override_constants/margin_bottom = 60
57 |
58 | [node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
59 | layout_mode = 2
60 | size_flags_horizontal = 3
61 |
62 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer"]
63 | layout_mode = 2
64 | theme_type_variation = &"HeaderSmall"
65 | text = "NativeFileDialog"
66 |
67 | [node name="HBoxContainer1" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
68 | layout_mode = 2
69 |
70 | [node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer1"]
71 | layout_mode = 2
72 | size_flags_horizontal = 3
73 | theme_override_constants/separation = 0
74 |
75 | [node name="Lable" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer1/VBoxContainer"]
76 | layout_mode = 2
77 | text = "Title"
78 |
79 | [node name="_Title" type="LineEdit" parent="MarginContainer/VBoxContainer/HBoxContainer1/VBoxContainer"]
80 | unique_name_in_owner = true
81 | layout_mode = 2
82 | size_flags_horizontal = 3
83 | text = "Save a File"
84 | editable = false
85 | caret_blink = true
86 | caret_blink_interval = 0.5
87 |
88 | [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer1"]
89 | layout_mode = 2
90 | size_flags_vertical = 4
91 | theme_override_constants/separation = 0
92 |
93 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer1/HBoxContainer"]
94 | layout_mode = 2
95 | text = "Mode Overrides Title"
96 |
97 | [node name="_Overrides" type="CheckButton" parent="MarginContainer/VBoxContainer/HBoxContainer1/HBoxContainer"]
98 | unique_name_in_owner = true
99 | layout_mode = 2
100 | button_pressed = true
101 |
102 | [node name="HBoxContainer2" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
103 | layout_mode = 2
104 |
105 | [node name="VBoxContainer1" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer2"]
106 | layout_mode = 2
107 | theme_override_constants/separation = 0
108 |
109 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer2/VBoxContainer1"]
110 | layout_mode = 2
111 | text = "File Mode"
112 |
113 | [node name="OptionButton" type="OptionButton" parent="MarginContainer/VBoxContainer/HBoxContainer2/VBoxContainer1"]
114 | layout_mode = 2
115 | item_count = 4
116 | selected = 3
117 | popup/item_0/text = "Open File"
118 | popup/item_0/id = 0
119 | popup/item_1/text = "Open Files"
120 | popup/item_1/id = 1
121 | popup/item_2/text = "Open Folder"
122 | popup/item_2/id = 2
123 | popup/item_3/text = "Save"
124 | popup/item_3/id = 3
125 |
126 | [node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer2"]
127 | layout_mode = 2
128 | theme_override_constants/separation = 0
129 |
130 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer2/VBoxContainer2"]
131 | layout_mode = 2
132 | text = "Access"
133 |
134 | [node name="OptionButton" type="OptionButton" parent="MarginContainer/VBoxContainer/HBoxContainer2/VBoxContainer2"]
135 | layout_mode = 2
136 | item_count = 3
137 | selected = 0
138 | popup/item_0/text = "Resources"
139 | popup/item_0/id = 0
140 | popup/item_1/text = "User Data"
141 | popup/item_1/id = 1
142 | popup/item_2/text = "File System"
143 | popup/item_2/id = 2
144 |
145 | [node name="VBoxContainer3" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer2"]
146 | layout_mode = 2
147 | size_flags_horizontal = 3
148 | theme_override_constants/separation = 0
149 |
150 | [node name="Lable" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer2/VBoxContainer3"]
151 | layout_mode = 2
152 | text = "Root Subfolder"
153 |
154 | [node name="LineEdit" type="LineEdit" parent="MarginContainer/VBoxContainer/HBoxContainer2/VBoxContainer3"]
155 | layout_mode = 2
156 | size_flags_horizontal = 3
157 | caret_blink = true
158 | caret_blink_interval = 0.5
159 |
160 | [node name="VBoxContainer1" type="VBoxContainer" parent="MarginContainer/VBoxContainer"]
161 | layout_mode = 2
162 | theme_override_constants/separation = 0
163 |
164 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/VBoxContainer1"]
165 | layout_mode = 2
166 | text = "Filters"
167 |
168 | [node name="PanelContainer" type="PanelContainer" parent="MarginContainer/VBoxContainer/VBoxContainer1"]
169 | layout_mode = 2
170 | theme_override_styles/panel = SubResource("StyleBoxFlat_h5ge7")
171 |
172 | [node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer"]
173 | layout_mode = 2
174 | theme_override_constants/margin_left = 15
175 | theme_override_constants/margin_top = 15
176 | theme_override_constants/margin_right = 15
177 | theme_override_constants/margin_bottom = 15
178 |
179 | [node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer/MarginContainer"]
180 | layout_mode = 2
181 |
182 | [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer/MarginContainer/VBoxContainer"]
183 | layout_mode = 2
184 |
185 | [node name="VBoxContainer1" type="VBoxContainer" parent="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"]
186 | layout_mode = 2
187 | size_flags_horizontal = 3
188 | theme_override_constants/separation = 0
189 |
190 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer1"]
191 | layout_mode = 2
192 | text = "Filter"
193 |
194 | [node name="_Filter" type="LineEdit" parent="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer1"]
195 | unique_name_in_owner = true
196 | layout_mode = 2
197 | size_flags_horizontal = 3
198 |
199 | [node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"]
200 | layout_mode = 2
201 | size_flags_horizontal = 3
202 | theme_override_constants/separation = 0
203 |
204 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2"]
205 | layout_mode = 2
206 | text = "Description"
207 |
208 | [node name="_Description" type="LineEdit" parent="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2"]
209 | unique_name_in_owner = true
210 | layout_mode = 2
211 | size_flags_horizontal = 3
212 |
213 | [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"]
214 | layout_mode = 2
215 | theme_override_constants/separation = 15
216 | alignment = 2
217 |
218 | [node name="Button1" type="Button" parent="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/HBoxContainer"]
219 | layout_mode = 2
220 | size_flags_vertical = 4
221 | text = "Add"
222 |
223 | [node name="Button2" type="Button" parent="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/HBoxContainer"]
224 | layout_mode = 2
225 | size_flags_vertical = 4
226 | theme_type_variation = &"GhostButton"
227 | text = "Clear"
228 |
229 | [node name="PanelContainer" type="PanelContainer" parent="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer/MarginContainer/VBoxContainer"]
230 | layout_mode = 2
231 | size_flags_horizontal = 3
232 | size_flags_vertical = 3
233 | theme_override_styles/panel = SubResource("StyleBoxFlat_cvo7c")
234 |
235 | [node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer/MarginContainer/VBoxContainer/PanelContainer"]
236 | custom_minimum_size = Vector2(0, 90)
237 | layout_mode = 2
238 | horizontal_scroll_mode = 0
239 |
240 | [node name="_Filters" type="VBoxContainer" parent="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer/MarginContainer/VBoxContainer/PanelContainer/ScrollContainer"]
241 | unique_name_in_owner = true
242 | layout_mode = 2
243 | theme_override_constants/separation = 0
244 |
245 | [node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer/VBoxContainer"]
246 | layout_mode = 2
247 | theme_override_constants/separation = 0
248 |
249 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/VBoxContainer2"]
250 | layout_mode = 2
251 | text = "Result"
252 |
253 | [node name="_Result" type="LineEdit" parent="MarginContainer/VBoxContainer/VBoxContainer2"]
254 | unique_name_in_owner = true
255 | layout_mode = 2
256 | size_flags_horizontal = 3
257 | editable = false
258 |
259 | [node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer"]
260 | layout_mode = 2
261 | theme_override_constants/margin_top = 15
262 |
263 | [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/MarginContainer"]
264 | layout_mode = 2
265 | theme_override_constants/separation = 15
266 | alignment = 2
267 |
268 | [node name="Button1" type="Button" parent="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer"]
269 | layout_mode = 2
270 | size_flags_vertical = 4
271 | theme_type_variation = &"GhostButton"
272 | text = "Hide"
273 |
274 | [node name="Button2" type="Button" parent="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer"]
275 | layout_mode = 2
276 | size_flags_vertical = 4
277 | text = "Show"
278 |
279 | [connection signal="canceled" from="_NativeFileDialog" to="." method="dialog_closed"]
280 | [connection signal="dir_selected" from="_NativeFileDialog" to="." method="file_selected"]
281 | [connection signal="file_selected" from="_NativeFileDialog" to="." method="file_selected"]
282 | [connection signal="files_selected" from="_NativeFileDialog" to="." method="files_selected"]
283 | [connection signal="text_changed" from="MarginContainer/VBoxContainer/HBoxContainer1/VBoxContainer/_Title" to="_NativeFileDialog" method="set_title"]
284 | [connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer1/HBoxContainer/_Overrides" to="." method="override_title"]
285 | [connection signal="item_selected" from="MarginContainer/VBoxContainer/HBoxContainer2/VBoxContainer1/OptionButton" to="." method="select_file_mode"]
286 | [connection signal="item_selected" from="MarginContainer/VBoxContainer/HBoxContainer2/VBoxContainer2/OptionButton" to="_NativeFileDialog" method="set_access"]
287 | [connection signal="text_changed" from="MarginContainer/VBoxContainer/HBoxContainer2/VBoxContainer3/LineEdit" to="_NativeFileDialog" method="set_root_subfolder"]
288 | [connection signal="pressed" from="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/HBoxContainer/Button1" to="." method="add_filter"]
289 | [connection signal="pressed" from="MarginContainer/VBoxContainer/VBoxContainer1/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/HBoxContainer/Button2" to="." method="clear_filters"]
290 | [connection signal="pressed" from="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer/Button1" to="_NativeFileDialog" method="hide"]
291 | [connection signal="pressed" from="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer/Button2" to="_NativeFileDialog" method="show"]
292 |
--------------------------------------------------------------------------------
/demo/scenes/native_notification.gd:
--------------------------------------------------------------------------------
1 | extends PanelContainer
2 |
3 |
4 | @onready var native_notification: NativeNotification = %_NativeNotification
5 | @onready var text: TextEdit = %_Text
6 |
7 |
8 | func text_changed():
9 | native_notification.set_text(text.text)
10 |
--------------------------------------------------------------------------------
/demo/scenes/native_notification.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=3 uid="uid://b3lywl2to6wuh"]
2 |
3 | [ext_resource type="Script" path="res://scenes/native_notification.gd" id="1_dl8uo"]
4 | [ext_resource type="Theme" uid="uid://dghnjlpplxvrd" path="res://main_theme.tres" id="1_kx2dd"]
5 |
6 | [node name="NativeNotification" type="PanelContainer"]
7 | anchors_preset = 15
8 | anchor_right = 1.0
9 | anchor_bottom = 1.0
10 | grow_horizontal = 2
11 | grow_vertical = 2
12 | size_flags_vertical = 3
13 | theme = ExtResource("1_kx2dd")
14 | script = ExtResource("1_dl8uo")
15 |
16 | [node name="_NativeNotification" type="NativeNotification" parent="."]
17 | unique_name_in_owner = true
18 |
19 | [node name="MarginContainer" type="MarginContainer" parent="."]
20 | layout_mode = 2
21 | theme_override_constants/margin_left = 90
22 | theme_override_constants/margin_top = 60
23 | theme_override_constants/margin_right = 90
24 | theme_override_constants/margin_bottom = 60
25 |
26 | [node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
27 | layout_mode = 2
28 |
29 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer"]
30 | layout_mode = 2
31 | theme_type_variation = &"HeaderSmall"
32 | text = "NativeNotification"
33 |
34 | [node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer"]
35 | layout_mode = 2
36 | size_flags_horizontal = 3
37 | alignment = 1
38 |
39 | [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/VBoxContainer"]
40 | layout_mode = 2
41 |
42 | [node name="VBoxContainer1" type="VBoxContainer" parent="MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer"]
43 | layout_mode = 2
44 | size_flags_horizontal = 3
45 | size_flags_stretch_ratio = 3.0
46 | theme_override_constants/separation = 0
47 |
48 | [node name="Lable" type="Label" parent="MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer/VBoxContainer1"]
49 | layout_mode = 2
50 | text = "Title"
51 |
52 | [node name="LineEdit" type="LineEdit" parent="MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer/VBoxContainer1"]
53 | layout_mode = 2
54 | size_flags_horizontal = 3
55 | text = "Alert!"
56 | caret_blink = true
57 | caret_blink_interval = 0.5
58 |
59 | [node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer"]
60 | layout_mode = 2
61 | size_flags_horizontal = 3
62 | theme_override_constants/separation = 0
63 |
64 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer/VBoxContainer2"]
65 | layout_mode = 2
66 | text = "Icon"
67 |
68 | [node name="OptionButton" type="OptionButton" parent="MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer/VBoxContainer2"]
69 | layout_mode = 2
70 | item_count = 3
71 | selected = 1
72 | popup/item_0/text = "Info"
73 | popup/item_0/id = 0
74 | popup/item_1/text = "Warning"
75 | popup/item_1/id = 1
76 | popup/item_2/text = "Error"
77 | popup/item_2/id = 2
78 |
79 | [node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/VBoxContainer"]
80 | layout_mode = 2
81 | theme_override_constants/separation = 0
82 |
83 | [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/VBoxContainer/VBoxContainer"]
84 | layout_mode = 2
85 | text = "Text"
86 |
87 | [node name="_Text" type="TextEdit" parent="MarginContainer/VBoxContainer/VBoxContainer/VBoxContainer"]
88 | unique_name_in_owner = true
89 | custom_minimum_size = Vector2(0, 90)
90 | layout_mode = 2
91 |
92 | [node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer"]
93 | layout_mode = 2
94 | theme_override_constants/margin_top = 15
95 |
96 | [node name="Button" type="Button" parent="MarginContainer/VBoxContainer/MarginContainer"]
97 | layout_mode = 2
98 | size_flags_horizontal = 8
99 | size_flags_vertical = 4
100 | text = "Send"
101 |
102 | [connection signal="text_changed" from="MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer/VBoxContainer1/LineEdit" to="_NativeNotification" method="set_title"]
103 | [connection signal="item_selected" from="MarginContainer/VBoxContainer/VBoxContainer/HBoxContainer/VBoxContainer2/OptionButton" to="_NativeNotification" method="set_icon"]
104 | [connection signal="text_changed" from="MarginContainer/VBoxContainer/VBoxContainer/VBoxContainer/_Text" to="." method="text_changed"]
105 | [connection signal="pressed" from="MarginContainer/VBoxContainer/MarginContainer/Button" to="_NativeNotification" method="send"]
106 |
--------------------------------------------------------------------------------
/doc/images/code_usage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/98teg/NativeDialogs/e829043a4d13214ec83b7b9912b4c62a3c0e21b6/doc/images/code_usage.png
--------------------------------------------------------------------------------
/doc/images/editor_usage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/98teg/NativeDialogs/e829043a4d13214ec83b7b9912b4c62a3c0e21b6/doc/images/editor_usage.png
--------------------------------------------------------------------------------
/doc/images/native_accept_dialog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/98teg/NativeDialogs/e829043a4d13214ec83b7b9912b4c62a3c0e21b6/doc/images/native_accept_dialog.png
--------------------------------------------------------------------------------
/doc/images/native_confirmation_dialog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/98teg/NativeDialogs/e829043a4d13214ec83b7b9912b4c62a3c0e21b6/doc/images/native_confirmation_dialog.png
--------------------------------------------------------------------------------
/doc/images/native_dialogs_banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/98teg/NativeDialogs/e829043a4d13214ec83b7b9912b4c62a3c0e21b6/doc/images/native_dialogs_banner.png
--------------------------------------------------------------------------------
/doc/images/native_dialogs_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/98teg/NativeDialogs/e829043a4d13214ec83b7b9912b4c62a3c0e21b6/doc/images/native_dialogs_icon.png
--------------------------------------------------------------------------------
/doc/images/native_file_dialog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/98teg/NativeDialogs/e829043a4d13214ec83b7b9912b4c62a3c0e21b6/doc/images/native_file_dialog.png
--------------------------------------------------------------------------------
/doc/images/native_notification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/98teg/NativeDialogs/e829043a4d13214ec83b7b9912b4c62a3c0e21b6/doc/images/native_notification.png
--------------------------------------------------------------------------------
/doc/images/windows_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/98teg/NativeDialogs/e829043a4d13214ec83b7b9912b4c62a3c0e21b6/doc/images/windows_example.png
--------------------------------------------------------------------------------
/doc/native_accept_dialog.md:
--------------------------------------------------------------------------------
1 | # `NativeAcceptDialog`
2 |
3 | ## Description
4 |
5 | This dialog is useful for small notifications to the user about an event. It can only be accepted or closed. The functionality of this node is already implemented in Godot via the `OS.alert()` method, althought it doesn't let you customize the icon.
6 |
7 | 
8 |
9 | ## Properties
10 |
11 | |Type|Name|Default value|
12 | |-|-|-|
13 | |[`Icon`](#enum-icon)|[`dialog_icon`](#icon-dialog_icon--1)|`1`|
14 | |`String`|[`dialog_text`](#string-dialog_text--)|`""`|
15 | |`String`|[`title`](#string-title--alert)|`"Alert!"`|
16 |
17 | ## Methods
18 |
19 | |Returned type|Declaration|
20 | |-|-|
21 | |`void`|[`hide()`](#void-hide)|
22 | |`void`|[`show()`](#void-show)|
23 |
24 | ## Signals
25 |
26 | ### `canceled()`
27 |
28 | Emitted when the dialog is closed.
29 |
30 | ### `confirmed()`
31 |
32 | Emitted when the dialog is accepted, i.e. the OK button is pressed.
33 |
34 | ## Enumerations
35 |
36 | ### `enum Icon`
37 |
38 | ```gdscript
39 | Icon ICON_INFO = 0
40 | ```
41 |
42 | Usually an icon with the letter i in a blue circle*.
43 |
44 | ```gdscript
45 | Icon ICON_WARNING = 1
46 | ```
47 |
48 | Usually an icon with an exclamation mark in a yellow triangle*.
49 |
50 | ```gdscript
51 | Icon ICON_ERROR = 2
52 | ```
53 |
54 | Usually an icon with a cross in a red circle*.
55 |
56 | ```gdscript
57 | Icon ICON_QUESTION = 3
58 | ```
59 |
60 | Usually an icon with a question mark*.
61 |
62 | **(*)** Depends on your OS theme.
63 |
64 | ## Property Descriptions
65 |
66 | ### `Icon dialog_icon = 1`
67 |
68 | The icon displayed by the dialog.
69 |
70 | ```gdscript
71 | void set_icon(Icon value)
72 |
73 | Icon get_icon()
74 | ```
75 |
76 | ### `String dialog_text = ""`
77 |
78 | The text displayed by the dialog.
79 |
80 | ```gdscript
81 | void set_text(String value)
82 |
83 | String get_text()
84 | ```
85 |
86 | ### `String title = "Alert!"`
87 |
88 | The dialog's title.
89 |
90 | ```gdscript
91 | void set_title(String value)
92 |
93 | String get_title()
94 | ```
95 |
96 | ## Method Descriptions
97 |
98 | ### `void hide()`
99 |
100 | Hides the dialog.
101 |
102 | ### `void show()`
103 |
104 | Makes the dialog appear. If this dialog is already visible, it would call [`hide`](#void-hide) first.
105 |
--------------------------------------------------------------------------------
/doc/native_confirmation_dialog.md:
--------------------------------------------------------------------------------
1 | # `NativeConfirmationDialog`
2 |
3 | ## Description
4 |
5 | Dialog for confirmation of actions. This dialog inherits from [`NativeAcceptDialog`](./native_accept_dialog.md),
6 |
7 | 
8 |
9 | ## Properties
10 |
11 | |Type|Name|Default value|
12 | |-|-|-|
13 | |[`ButtonsTexts`](#enum-buttonstexts)|[`buttons_texts`](#buttonstexts-buttons_texts--0)|`0`|
14 | |[`Icon`](./native_accept_dialog.md#enum-icon)|[`dialog_icon`](./native_accept_dialog.md#icon-dialog_icon--1)|`3` (overrides [`NativeAcceptDialog`](./native_accept_dialog.md))|
15 | |`String`|[`title`](./native_accept_dialog.md#string-title--alert)|`"Please Confirm..."` (overrides [`NativeAcceptDialog`](./native_accept_dialog.md))|
16 |
17 | ## Enumerations
18 |
19 | ### `enum ButtonsTexts`
20 |
21 | ```gdscript
22 | ButtonsTexts BUTTONS_TEXTS_OK_CANCEL = 0
23 | ```
24 |
25 | Pressing `OK` would emit the [`confirmed`](./native_accept_dialog.md#confirmed) signal and pressing `Cancel` would emit the [`canceled`](./native_accept_dialog.md#canceled) signal.
26 |
27 | ```gdscript
28 | Icon BUTTONS_TEXTS_YES_NO = 1
29 | ```
30 |
31 | Pressing `Yes` would emit the [`confirmed`](./native_accept_dialog.md#confirmed) signal and pressing `No` would emit the [`canceled`](./native_accept_dialog.md#canceled) signal.
32 |
33 | ## Property Descriptions
34 |
35 | ### `ButtonsTexts buttons_texts = 0`
36 |
37 | The text that would be displayed inside the dialog's buttons.
38 |
39 | ```gdscript
40 | void set_buttons_texts(ButtonsTexts value)
41 |
42 | ButtonsTexts get_buttons_texts()
43 | ```
44 |
--------------------------------------------------------------------------------
/doc/native_file_dialog.md:
--------------------------------------------------------------------------------
1 | # `NativeFileDialog`
2 |
3 | ## Description
4 |
5 | NativeFileDialog is a dialog used to choose files and directories in the filesystem. It supports filter masks. The NativeFileDialog automatically sets its window title according to the `mode`. If you want to use a custom title, disable this by setting `mode_overrides_title` to `false`.
6 |
7 | 
8 |
9 | ## Properties
10 |
11 | |Type|Name|Default value|
12 | |-|-|-|
13 | |[`Access`](#enum-access)|[`access`](#access-access--0)|`0`|
14 | |[`FileMode`](#enum-filemode)|[`file_mode`](#filemode-file_mode--3)|`3`|
15 | |`PoolStringArray`|[`filters`](#packedstringarray-filters--packedstringarray)|`PoolStringArray()`|
16 | |`bool`|[`mode_overrides_title`](#bool-mode_overrides_title--true)|`true`|
17 | |`String`|[`root_subfolder`](#string-root_subfolder--)|`""`|
18 | |`String`|[`title`](#string-title--save-a-file)|`"Save a File"`|
19 |
20 | ## Methods
21 |
22 | |Returned type|Declaration|
23 | |-|-|
24 | |`void`|[`add_filter(String filter, String description="")`](#void-add_filterstring-filter-string-description)|
25 | |`void`|[`clear_filters()`](#void-clear_filters)|
26 | |`void`|[`hide()`](#void-hide)|
27 | |`void`|[`show()`](#void-show)|
28 |
29 | ## Signals
30 |
31 | ### `dir_selected(String dir)`
32 |
33 | Emitted when the user selects a directory.
34 |
35 | ### `file_selected(String path)`
36 |
37 | Emitted when the user selects a file by double-clicking it or pressing the **OK** button.
38 |
39 | ### `files_selected(PoolStringArray paths)`
40 |
41 | Emitted when the user selects multiple files.
42 |
43 | ### `canceled()`
44 |
45 | Emitted when the dialog is closed.
46 |
47 | ## Enumerations
48 |
49 | ### `enum FileMode`
50 |
51 | ```gdscript
52 | FileMode MODE_OPEN_FILE = 0
53 | ```
54 |
55 | The dialog allows selecting one, and only one file.
56 |
57 | ```gdscript
58 | FileMode MODE_OPEN_FILES = 1
59 | ```
60 |
61 | The dialog allows selecting multiple files.
62 |
63 | ```gdscript
64 | FileMode MODE_OPEN_DIR = 2
65 | ```
66 |
67 | The dialog only allows selecting a directory, disallowing the selection of any file.
68 |
69 | ```gdscript
70 | FileMode MODE_SAVE_FILE = 3
71 | ```
72 |
73 | The dialog will warn when a file exists.
74 |
75 | ### `enum Access`
76 |
77 | ```gdscript
78 | Access ACCESS_RESOURCES = 0
79 | ```
80 |
81 | The dialog is initiated under the Resource path (`res://`).
82 |
83 | ```gdscript
84 | Access ACCESS_USERDATA = 1
85 | ```
86 |
87 | The dialog is initiated under the user data path (`user://`).
88 |
89 | ```gdscript
90 | Access ACCESS_FILESYSTEM = 2
91 | ```
92 |
93 | The dialog allows accessing files on the whole file system.
94 |
95 | ## Property Descriptions
96 |
97 | ### `Access access = 0`
98 |
99 | The file system access scope. See enum `Access` constants. Changing this value would reset `root_subfolder`. So when using code, you need to set `access` before `root_subfolder`.
100 |
101 | ```gdscript
102 | void set_access(Access value)
103 |
104 | Access get_access()
105 | ```
106 |
107 | ### `FileMode file_mode = 3`
108 |
109 | The dialog's open or save mode, which affects the selection behavior. See `FileMode`.
110 |
111 | ```gdscript
112 | void set_file_mode(FileMode value)
113 |
114 | FileMode get_file_mode()
115 | ```
116 |
117 | ### `PackedStringArray filters = PackedStringArray()`
118 |
119 | The available file type filters. For example, this shows only `.png` and `.gd` files: `set_filters(PackedStringArray(["*.png ; PNG Images","*.gd ; GDScript Files"]))`. Multiple file types can also be specified in a single filter. `"*.png, *.jpg, *.jpeg ; Supported Images"` will show both PNG and JPEG files when selected.
120 |
121 | ```gdscript
122 | void set_filters(PackedStringArray value)
123 |
124 | PackedStringArray get_filters()
125 | ```
126 |
127 | ### `bool mode_overrides_title = true`
128 |
129 | If `true`, changing the `Mode` property will set the window title accordingly (e.g. setting mode to `FILE_MODE_OPEN_FILE` will change the window title to "Open a File").
130 |
131 | ```gdscript
132 | void set_mode_overrides_title(bool value)
133 |
134 | bool is_mode_overriding_title()
135 | ```
136 |
137 | ### `String root_subfolder = ""`
138 |
139 | The subfolder where the native dialog would start.
140 |
141 | ```gdscript
142 | void set_root_subfolder(String value)
143 |
144 | String get_root_subfolder()
145 | ```
146 |
147 | ### `String title = "Save a File"`
148 |
149 | The dialog's title.
150 |
151 | ```gdscript
152 | void set_title(String value)
153 |
154 | String get_title()
155 | ```
156 |
157 | ## Method Descriptions
158 |
159 | ### `void add_filter(String filter, String description="")`
160 |
161 | Adds a comma-delimited file name `filter` option to the **FileDialog** with an optional `description`, which restricts what files can be picked.
162 |
163 | A `filter` should be of the form `"filename.extension"`, where filename and extension can be * to match any string. Filters starting with `.` (i.e. empty filenames) are not allowed.
164 |
165 | For example, a `filter` of `"*.png, *.jpg"` and a description of `"Images"` results in filter text `"Images (*.png, *.jpg)"`.
166 |
167 | ### `void clear_filters()`
168 |
169 | Clear all the added filters in the dialog.
170 |
171 | ### `void hide()`
172 |
173 | Hides the dialog.
174 |
175 | ### `void show()`
176 |
177 | Makes the dialog appear. If this dialog is already visible, it would call [`hide`](#void-hide) first.
178 |
--------------------------------------------------------------------------------
/doc/native_notification.md:
--------------------------------------------------------------------------------
1 | # `NativeNotification`
2 |
3 | ## Description
4 |
5 | This node would show the user a brief message and then fade away.
6 |
7 | 
8 |
9 | ## Properties
10 |
11 | |Type|Name|Default value|
12 | |-|-|-|
13 | |[`Icon`](#enum-icon)|[`notification_icon`](#icon-notification_icon--1)|`1`|
14 | |`String`|[`notification_text`](#string-notification_text--)|`""`|
15 | |`String`|[`title`](#string-title--alert)|`"Alert!"`|
16 |
17 | ## Methods
18 |
19 | |Returned type|Declaration|
20 | |-|-|
21 | |`void`|[`send()`](#void-send)|
22 |
23 | ## Enumerations
24 |
25 | ### `enum Icon`
26 |
27 | ```gdscript
28 | Icon ICON_INFO = 0
29 | ```
30 |
31 | Usually an icon with the letter i in a blue circle*.
32 |
33 | ```gdscript
34 | Icon ICON_WARNING = 1
35 | ```
36 |
37 | Usually an icon with an exclamation mark in a yellow triangle*.
38 |
39 | ```gdscript
40 | Icon ICON_ERROR = 2
41 | ```
42 |
43 | Usually an icon with a cross in a red circle*.
44 |
45 | **(*)** Depends on your OS theme.
46 |
47 | ## Property Descriptions
48 |
49 | ### `Icon notification_icon = 1`
50 |
51 | The icon displayed by the notification.
52 |
53 | ```gdscript
54 | void set_icon(Icon value)
55 |
56 | Icon get_icon()
57 | ```
58 |
59 | ### `String notification_text = ""`
60 |
61 | The text displayed by the notification.
62 |
63 | ```gdscript
64 | void set_text(String value)
65 |
66 | String get_text()
67 | ```
68 |
69 | ### `String title = "Alert!"`
70 |
71 | The notification's title.
72 |
73 | ```gdscript
74 | void set_title(String value)
75 |
76 | String get_title()
77 | ```
78 |
79 | ## Method Descriptions
80 |
81 | ### `void send()`
82 |
83 | Sends the notification to appear to the user and then fade away.
84 |
--------------------------------------------------------------------------------
/src/native_accept_dialog.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "native_accept_dialog.h"
4 |
5 | using namespace godot;
6 |
7 | void NativeAcceptDialog::_bind_methods() {
8 | ClassDB::bind_method(D_METHOD("set_title", "title"), &NativeAcceptDialog::set_title);
9 | ClassDB::bind_method(D_METHOD("get_title"), &NativeAcceptDialog::get_title);
10 | ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
11 |
12 | ADD_GROUP("Dialog", "dialog");
13 | ClassDB::bind_method(D_METHOD("set_text", "text"), &NativeAcceptDialog::set_text);
14 | ClassDB::bind_method(D_METHOD("get_text"), &NativeAcceptDialog::get_text);
15 | ADD_PROPERTY(PropertyInfo(Variant::STRING, "dialog_text", PROPERTY_HINT_MULTILINE_TEXT, ""), "set_text", "get_text");
16 |
17 | ClassDB::bind_method(D_METHOD("set_icon", "icon"), &NativeAcceptDialog::set_icon);
18 | ClassDB::bind_method(D_METHOD("get_icon"), &NativeAcceptDialog::get_icon);
19 | ADD_PROPERTY(PropertyInfo(Variant::INT, "dialog_icon", PROPERTY_HINT_ENUM, "Info,Warning,Error,Question"), "set_icon", "get_icon");
20 |
21 | ClassDB::bind_method(D_METHOD("show"), &NativeAcceptDialog::show);
22 | ClassDB::bind_method(D_METHOD("hide"), &NativeAcceptDialog::hide);
23 |
24 | ADD_SIGNAL(MethodInfo("confirmed"));
25 | ADD_SIGNAL(MethodInfo("canceled"));
26 |
27 | BIND_ENUM_CONSTANT(ICON_INFO);
28 | BIND_ENUM_CONSTANT(ICON_WARNING);
29 | BIND_ENUM_CONSTANT(ICON_ERROR);
30 | BIND_ENUM_CONSTANT(ICON_QUESTION);
31 | }
32 |
33 | NativeAcceptDialog::NativeAcceptDialog() {
34 | title = "Alert!";
35 | text = "";
36 | icon = ICON_WARNING;
37 | }
38 |
39 | NativeAcceptDialog::~NativeAcceptDialog() {
40 | hide();
41 | }
42 |
43 | void NativeAcceptDialog::_process(float delta) {
44 | if (!message || !message->ready(0)) {
45 | return;
46 | }
47 |
48 | pfd::button button = message->result();
49 | if (button == pfd::button::ok || button == pfd::button::yes) {
50 | emit_signal("confirmed");
51 | } else {
52 | emit_signal("canceled");
53 | }
54 |
55 | hide();
56 | }
57 |
58 | void NativeAcceptDialog::_exit_tree() {
59 | hide();
60 | }
61 |
62 | void NativeAcceptDialog::show() {
63 | ERR_FAIL_COND(!is_inside_tree());
64 | ERR_FAIL_COND(!is_processing());
65 |
66 | hide();
67 |
68 | pfd::icon pfd_icon;
69 |
70 | switch (icon) {
71 | case ICON_INFO:
72 | pfd_icon = pfd::icon::info;
73 | break;
74 | case ICON_ERROR:
75 | pfd_icon = pfd::icon::error;
76 | break;
77 | case ICON_QUESTION:
78 | pfd_icon = pfd::icon::question;
79 | break;
80 | default:
81 | pfd_icon = pfd::icon::warning;
82 | }
83 |
84 | message = new pfd::message(
85 | String(TranslationServer::get_singleton()->translate(title)).utf8().get_data(),
86 | String(TranslationServer::get_singleton()->translate(text)).utf8().get_data(),
87 | choice,
88 | pfd_icon);
89 | }
90 |
91 | void NativeAcceptDialog::hide() {
92 | if (!message) {
93 | return;
94 | }
95 |
96 | message->kill();
97 |
98 | delete message;
99 |
100 | message = nullptr;
101 | }
102 |
103 | void NativeAcceptDialog::set_title(const String &p_title) {
104 | title = p_title;
105 | }
106 |
107 | String NativeAcceptDialog::get_title() {
108 | return title;
109 | }
110 |
111 | void NativeAcceptDialog::set_text(const String &p_text) {
112 | text = p_text;
113 | }
114 |
115 | String NativeAcceptDialog::get_text() {
116 | return text;
117 | }
118 |
119 | void NativeAcceptDialog::set_icon(Icon p_icon) {
120 | ERR_FAIL_INDEX((int)p_icon, 4);
121 |
122 | icon = p_icon;
123 | }
124 |
125 | NativeAcceptDialog::Icon NativeAcceptDialog::get_icon() {
126 | return icon;
127 | }
128 |
129 | void NativeAcceptDialog::set_choice(pfd::choice p_choice) {
130 | choice = p_choice;
131 | }
132 |
133 | pfd::choice NativeAcceptDialog::get_choice() {
134 | return choice;
135 | }
136 |
--------------------------------------------------------------------------------
/src/native_accept_dialog.h:
--------------------------------------------------------------------------------
1 | #ifndef NATIVEACCEPTDIALOG_H
2 | #define NATIVEACCEPTDIALOG_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | namespace godot {
11 |
12 | class NativeAcceptDialog : public Node {
13 | GDCLASS(NativeAcceptDialog, Node)
14 |
15 | protected:
16 | static void _bind_methods();
17 |
18 | void set_choice(pfd::choice p_choice);
19 | pfd::choice get_choice();
20 |
21 | public:
22 | enum Icon { ICON_INFO,
23 | ICON_WARNING,
24 | ICON_ERROR,
25 | ICON_QUESTION };
26 |
27 | private:
28 | String title;
29 | String text;
30 | Icon icon;
31 |
32 | pfd::choice choice = pfd::choice::ok;
33 | pfd::message *message = nullptr;
34 |
35 | public:
36 | NativeAcceptDialog();
37 | ~NativeAcceptDialog();
38 |
39 | void _process(float delta);
40 | void _exit_tree();
41 |
42 | void show();
43 | void hide();
44 |
45 | void set_title(const String &p_title);
46 | String get_title();
47 |
48 | void set_text(const String &p_text);
49 | String get_text();
50 |
51 | void set_icon(Icon p_icon);
52 | Icon get_icon();
53 | };
54 |
55 | } // namespace godot
56 |
57 | VARIANT_ENUM_CAST(NativeAcceptDialog::Icon);
58 |
59 | #endif // NATIVEACCEPTDIALOG_H
60 |
--------------------------------------------------------------------------------
/src/native_confirmation_dialog.cpp:
--------------------------------------------------------------------------------
1 | #include "native_confirmation_dialog.h"
2 |
3 | using namespace godot;
4 |
5 | void NativeConfirmationDialog::_bind_methods() {
6 | ClassDB::bind_method(D_METHOD("set_buttons_texts", "buttons_texts"), &NativeConfirmationDialog::set_buttons_texts);
7 | ClassDB::bind_method(D_METHOD("get_buttons_texts"), &NativeConfirmationDialog::get_buttons_texts);
8 | ADD_PROPERTY(PropertyInfo(Variant::INT, "buttons_texts", PROPERTY_HINT_ENUM, "OK Cancel,Yes No"), "set_buttons_texts", "get_buttons_texts");
9 |
10 | BIND_ENUM_CONSTANT(BUTTONS_TEXTS_OK_CANCEL);
11 | BIND_ENUM_CONSTANT(BUTTONS_TEXTS_YES_NO);
12 | }
13 |
14 | NativeConfirmationDialog::NativeConfirmationDialog() {
15 | set_title("Please Confirm...");
16 | set_icon(ICON_QUESTION);
17 | set_buttons_texts(BUTTONS_TEXTS_OK_CANCEL);
18 | }
19 |
20 | void NativeConfirmationDialog::_process(float delta) {
21 | NativeAcceptDialog::_process(delta);
22 | }
23 |
24 | void NativeConfirmationDialog::_exit_tree() {
25 | NativeAcceptDialog::_exit_tree();
26 | }
27 |
28 | void NativeConfirmationDialog::set_buttons_texts(ButtonsTexts p_buttons_texts) {
29 | buttons_texts = p_buttons_texts;
30 |
31 | switch (buttons_texts) {
32 | case BUTTONS_TEXTS_OK_CANCEL:
33 | set_choice(pfd::choice::ok_cancel);
34 | break;
35 | case BUTTONS_TEXTS_YES_NO:
36 | set_choice(pfd::choice::yes_no);
37 | break;
38 | }
39 | }
40 |
41 | NativeConfirmationDialog::ButtonsTexts NativeConfirmationDialog::get_buttons_texts() {
42 | return buttons_texts;
43 | }
44 |
--------------------------------------------------------------------------------
/src/native_confirmation_dialog.h:
--------------------------------------------------------------------------------
1 | #ifndef NATIVECONFIRMATIONDIALOG_H
2 | #define NATIVECONFIRMATIONDIALOG_H
3 |
4 | #include
5 | #include
6 |
7 | #include
8 |
9 | #include "native_accept_dialog.h"
10 |
11 | namespace godot {
12 |
13 | class NativeConfirmationDialog : public NativeAcceptDialog {
14 | GDCLASS(NativeConfirmationDialog, NativeAcceptDialog)
15 |
16 | protected:
17 | static void _bind_methods();
18 |
19 | public:
20 | enum ButtonsTexts {
21 | BUTTONS_TEXTS_OK_CANCEL,
22 | BUTTONS_TEXTS_YES_NO
23 | };
24 |
25 | private:
26 | ButtonsTexts buttons_texts;
27 |
28 | public:
29 | NativeConfirmationDialog();
30 |
31 | void _process(float delta);
32 | void _exit_tree();
33 |
34 | void set_buttons_texts(ButtonsTexts p_texts);
35 | ButtonsTexts get_buttons_texts();
36 | };
37 |
38 | } // namespace godot
39 |
40 | VARIANT_ENUM_CAST(NativeConfirmationDialog::ButtonsTexts);
41 |
42 | #endif // NATIVECONFIRMATIONDIALOG_H
43 |
--------------------------------------------------------------------------------
/src/native_file_dialog.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "native_file_dialog.h"
7 |
8 | using namespace godot;
9 |
10 | void NativeFileDialog::_bind_methods() {
11 | ClassDB::bind_method(D_METHOD("set_title", "title"), &NativeFileDialog::set_title);
12 | ClassDB::bind_method(D_METHOD("get_title"), &NativeFileDialog::get_title);
13 | ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
14 |
15 | ClassDB::bind_method(D_METHOD("set_mode_overrides_title", "override"), &NativeFileDialog::set_mode_overrides_title);
16 | ClassDB::bind_method(D_METHOD("is_mode_overriding_title"), &NativeFileDialog::is_mode_overriding_title);
17 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "mode_overrides_title"), "set_mode_overrides_title", "is_mode_overriding_title");
18 |
19 | ClassDB::bind_method(D_METHOD("set_file_mode", "mode"), &NativeFileDialog::set_file_mode);
20 | ClassDB::bind_method(D_METHOD("get_file_mode"), &NativeFileDialog::get_file_mode);
21 | ADD_PROPERTY(PropertyInfo(Variant::INT, "file_mode", PROPERTY_HINT_ENUM, "Open File,Open Files,Open Folder,Save"), "set_file_mode", "get_file_mode");
22 |
23 | ClassDB::bind_method(D_METHOD("set_access", "access"), &NativeFileDialog::set_access);
24 | ClassDB::bind_method(D_METHOD("get_access"), &NativeFileDialog::get_access);
25 | ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User Data,File System"), "set_access", "get_access");
26 |
27 | ClassDB::bind_method(D_METHOD("set_root_subfolder", "dir"), &NativeFileDialog::set_root_subfolder);
28 | ClassDB::bind_method(D_METHOD("get_root_subfolder"), &NativeFileDialog::get_root_subfolder);
29 | ADD_PROPERTY(PropertyInfo(Variant::STRING, "root_subfolder"), "set_root_subfolder", "get_root_subfolder");
30 |
31 | ClassDB::bind_method(D_METHOD("set_filters", "filter"), &NativeFileDialog::set_filters);
32 | ClassDB::bind_method(D_METHOD("get_filters"), &NativeFileDialog::get_filters);
33 | ClassDB::bind_method(D_METHOD("add_filter", "filter", "description"), &NativeFileDialog::add_filter, DEFVAL(""));
34 | ClassDB::bind_method(D_METHOD("clear_filters"), &NativeFileDialog::clear_filters);
35 | ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "filters"), "set_filters", "get_filters");
36 |
37 | ClassDB::bind_method(D_METHOD("show"), &NativeFileDialog::show);
38 | ClassDB::bind_method(D_METHOD("hide"), &NativeFileDialog::hide);
39 |
40 | ADD_SIGNAL(MethodInfo("file_selected", PropertyInfo(Variant::STRING, "path")));
41 | ADD_SIGNAL(MethodInfo("files_selected", PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths")));
42 | ADD_SIGNAL(MethodInfo("dir_selected", PropertyInfo(Variant::STRING, "dir")));
43 |
44 | ADD_SIGNAL(MethodInfo("canceled"));
45 |
46 | BIND_ENUM_CONSTANT(FILE_MODE_OPEN_FILE);
47 | BIND_ENUM_CONSTANT(FILE_MODE_OPEN_FILES);
48 | BIND_ENUM_CONSTANT(FILE_MODE_OPEN_DIR);
49 | BIND_ENUM_CONSTANT(FILE_MODE_SAVE_FILE);
50 |
51 | BIND_ENUM_CONSTANT(ACCESS_RESOURCES);
52 | BIND_ENUM_CONSTANT(ACCESS_USERDATA);
53 | BIND_ENUM_CONSTANT(ACCESS_FILESYSTEM);
54 | }
55 |
56 | NativeFileDialog::NativeFileDialog() {
57 | mode_overrides_title = true;
58 | mode = FILE_MODE_SAVE_FILE;
59 | access = ACCESS_RESOURCES;
60 | root_subfolder = "";
61 | filters = PackedStringArray();
62 | title = "Save a File";
63 | }
64 |
65 | NativeFileDialog::~NativeFileDialog() {
66 | hide();
67 | }
68 |
69 | void NativeFileDialog::_process(float delta) {
70 | if (open_file && open_file->ready(0)) {
71 | PackedStringArray result = PackedStringArray();
72 | for (int i = 0; i < open_file->result().size(); i++) {
73 | result.append(get_godot_path(open_file->result()[i]));
74 | }
75 |
76 | if (!result.is_empty()) {
77 | if (mode == FILE_MODE_OPEN_FILE && result.size() == 1) {
78 | emit_signal("file_selected", result[0]);
79 | } else {
80 | emit_signal("files_selected", result);
81 | }
82 | } else {
83 | emit_signal("canceled");
84 | }
85 |
86 | hide();
87 | } else if (save_file && save_file->ready(0)) {
88 | String result = get_godot_path(save_file->result());
89 |
90 | if (!result.is_empty()) {
91 | emit_signal("file_selected", result);
92 | } else {
93 | emit_signal("canceled");
94 | }
95 |
96 | hide();
97 | } else if (select_folder && select_folder->ready(0)) {
98 | String result = get_godot_path(select_folder->result());
99 |
100 | if (!result.is_empty()) {
101 | emit_signal("dir_selected", get_godot_path(select_folder->result()));
102 | } else {
103 | emit_signal("canceled");
104 | }
105 |
106 | hide();
107 | }
108 | }
109 |
110 | void NativeFileDialog::_exit_tree() {
111 | hide();
112 | }
113 |
114 | void NativeFileDialog::show() {
115 | ERR_FAIL_COND(!is_inside_tree());
116 | ERR_FAIL_COND(!is_processing());
117 |
118 | hide();
119 |
120 | if (mode == FILE_MODE_OPEN_FILE || mode == FILE_MODE_OPEN_FILES) {
121 | open_file = new pfd::open_file(
122 | String(TranslationServer::get_singleton()->translate(title)).utf8().get_data(),
123 | get_pfd_path(),
124 | get_pfd_filters(),
125 | mode == FILE_MODE_OPEN_FILES ? pfd::opt::multiselect : pfd::opt::none);
126 | }
127 |
128 | if (mode == FILE_MODE_SAVE_FILE) {
129 | save_file = new pfd::save_file(
130 | String(TranslationServer::get_singleton()->translate(title)).utf8().get_data(),
131 | get_pfd_path(),
132 | get_pfd_filters(),
133 | pfd::opt::none);
134 | }
135 |
136 | if (mode == FILE_MODE_OPEN_DIR) {
137 | select_folder = new pfd::select_folder(
138 | String(TranslationServer::get_singleton()->translate(title)).utf8().get_data(),
139 | get_pfd_path(),
140 | pfd::opt::none);
141 | }
142 | }
143 |
144 | void NativeFileDialog::hide() {
145 | if (open_file) {
146 | open_file->kill();
147 |
148 | delete open_file;
149 |
150 | open_file = nullptr;
151 | }
152 |
153 | if (save_file) {
154 | save_file->kill();
155 |
156 | delete save_file;
157 |
158 | save_file = nullptr;
159 | }
160 |
161 | if (select_folder) {
162 | select_folder->kill();
163 |
164 | delete select_folder;
165 |
166 | select_folder = nullptr;
167 | }
168 | }
169 |
170 | void NativeFileDialog::set_title(const String &p_title) {
171 | title = p_title;
172 | }
173 |
174 | String NativeFileDialog::get_title() const {
175 | return title;
176 | }
177 |
178 | void NativeFileDialog::set_mode_overrides_title(bool p_override) {
179 | if (mode_overrides_title == p_override) {
180 | return;
181 | }
182 |
183 | mode_overrides_title = p_override;
184 |
185 | override_title();
186 | }
187 |
188 | bool NativeFileDialog::is_mode_overriding_title() {
189 | return mode_overrides_title;
190 | }
191 |
192 | void NativeFileDialog::set_file_mode(FileMode p_mode) {
193 | ERR_FAIL_INDEX((int)p_mode, 4);
194 |
195 | if (mode == p_mode) {
196 | return;
197 | }
198 |
199 | mode = p_mode;
200 |
201 | override_title();
202 | }
203 |
204 | NativeFileDialog::FileMode NativeFileDialog::get_file_mode() const {
205 | return mode;
206 | }
207 |
208 | void NativeFileDialog::set_access(Access p_access) {
209 | ERR_FAIL_INDEX(p_access, 3);
210 |
211 | if (access == p_access) {
212 | return;
213 | }
214 |
215 | access = p_access;
216 |
217 | set_root_subfolder("");
218 | }
219 |
220 | NativeFileDialog::Access NativeFileDialog::get_access() const {
221 | return access;
222 | }
223 |
224 | void NativeFileDialog::set_root_subfolder(const String &p_root) {
225 | root_subfolder = p_root;
226 | ERR_FAIL_COND_MSG(!DirAccess::dir_exists_absolute(get_root_string() + p_root), "root_subfolder must be an existing sub-directory.");
227 | }
228 |
229 | String NativeFileDialog::get_root_subfolder() const {
230 | return root_subfolder;
231 | }
232 |
233 | void NativeFileDialog::set_filters(const PackedStringArray &p_filters) {
234 | filters = p_filters;
235 | }
236 |
237 | PackedStringArray NativeFileDialog::get_filters() const {
238 | return filters;
239 | }
240 |
241 | void NativeFileDialog::add_filter(const String &p_filter, const String &p_description = "") {
242 | ERR_FAIL_COND_MSG(p_filter.begins_with("."), "Filter must be \"filename.extension\", can't start with dot.");
243 |
244 | if (p_description.is_empty()) {
245 | filters.push_back(p_filter);
246 | } else {
247 | filters.push_back(p_filter + String(" ; ") + p_description);
248 | }
249 | }
250 |
251 | void NativeFileDialog::clear_filters() {
252 | filters.clear();
253 | }
254 |
255 | std::vector NativeFileDialog::get_pfd_filters() const {
256 | std::vector pfd_filters = std::vector();
257 |
258 | for (int i = 0; i < filters.size(); i++) {
259 | PackedStringArray filter = filters[i].split(" ; ");
260 |
261 | String name = TranslationServer::get_singleton()->translate(filter.size() == 2 ? filter[1] : "");
262 | String extensions = filter[0].replace(", ", " ");
263 |
264 | pfd_filters.push_back(name.utf8().get_data());
265 | pfd_filters.push_back(extensions.utf8().get_data());
266 | }
267 |
268 | return pfd_filters;
269 | }
270 |
271 | std::string NativeFileDialog::get_pfd_path() const {
272 | String path = get_root_string() + get_root_subfolder();
273 | String global_path = ProjectSettings::get_singleton()->globalize_path(path);
274 |
275 | // Fixes issue with Open Folder mode, as it requires the string to end with slash
276 | if (!global_path.ends_with("/")) {
277 | global_path = global_path + "/";
278 | }
279 |
280 | #if _WIN32
281 | global_path = global_path.replace("/", "\\");
282 | #endif
283 |
284 | return global_path.utf8().get_data();
285 | }
286 |
287 | String NativeFileDialog::get_godot_path(const std::string &pfd_path) const {
288 | String godot_path = String::utf8(pfd_path.c_str());
289 |
290 | #if _WIN32
291 | godot_path = godot_path.replace("\\", "/");
292 | #endif
293 |
294 | return godot_path;
295 | }
296 |
297 | void NativeFileDialog::override_title() {
298 | if (!mode_overrides_title) {
299 | return;
300 | }
301 |
302 | switch (mode) {
303 | case FILE_MODE_OPEN_FILE:
304 | set_title("Open a File");
305 | break;
306 | case FILE_MODE_OPEN_FILES:
307 | set_title("Open File(s)");
308 | break;
309 | case FILE_MODE_OPEN_DIR:
310 | set_title("Open a Directory");
311 | break;
312 | case FILE_MODE_SAVE_FILE:
313 | set_title("Save a File");
314 | }
315 | }
316 |
317 | String NativeFileDialog::get_root_string() const {
318 | switch (access) {
319 | case ACCESS_RESOURCES:
320 | return "res://";
321 | case ACCESS_USERDATA:
322 | return "user://";
323 | default:
324 | return "";
325 | }
326 | }
327 |
--------------------------------------------------------------------------------
/src/native_file_dialog.h:
--------------------------------------------------------------------------------
1 | #ifndef NATIVEFILEDIALOG_H
2 | #define NATIVEFILEDIALOG_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | namespace godot {
11 |
12 | class NativeFileDialog : public Node {
13 | GDCLASS(NativeFileDialog, Node)
14 |
15 | protected:
16 | static void _bind_methods();
17 |
18 | public:
19 | enum FileMode {
20 | FILE_MODE_OPEN_FILE,
21 | FILE_MODE_OPEN_FILES,
22 | FILE_MODE_OPEN_DIR,
23 | FILE_MODE_SAVE_FILE
24 | };
25 |
26 | enum Access {
27 | ACCESS_RESOURCES,
28 | ACCESS_USERDATA,
29 | ACCESS_FILESYSTEM
30 | };
31 |
32 | private:
33 | String title;
34 | bool mode_overrides_title;
35 | FileMode mode;
36 | Access access;
37 | String root_subfolder;
38 | PackedStringArray filters;
39 |
40 | pfd::open_file *open_file = nullptr;
41 | pfd::save_file *save_file = nullptr;
42 | pfd::select_folder *select_folder = nullptr;
43 |
44 | std::vector get_pfd_filters() const;
45 |
46 | std::string get_pfd_path() const;
47 | String get_godot_path(const std::string &pfd_path) const;
48 |
49 | void override_title();
50 |
51 | String get_root_string() const;
52 |
53 | public:
54 | NativeFileDialog();
55 | ~NativeFileDialog();
56 |
57 | void _process(float delta);
58 | void _exit_tree();
59 |
60 | void show();
61 | void hide();
62 |
63 | void set_title(const String &p_title);
64 | String get_title() const;
65 |
66 | void set_mode_overrides_title(bool p_override);
67 | bool is_mode_overriding_title();
68 |
69 | void set_file_mode(FileMode p_mode);
70 | FileMode get_file_mode() const;
71 |
72 | void set_access(Access p_access);
73 | Access get_access() const;
74 |
75 | void set_root_subfolder(const String &p_root);
76 | String get_root_subfolder() const;
77 |
78 | void set_filters(const PackedStringArray &p_filters);
79 | PackedStringArray get_filters() const;
80 | void add_filter(const String &p_filter, const String &p_description);
81 | void clear_filters();
82 | };
83 |
84 | } // namespace godot
85 |
86 | VARIANT_ENUM_CAST(NativeFileDialog::FileMode);
87 | VARIANT_ENUM_CAST(NativeFileDialog::Access);
88 |
89 | #endif // NATIVEFILEDIALOG_H
90 |
--------------------------------------------------------------------------------
/src/native_notification.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "native_notification.h"
4 |
5 | using namespace godot;
6 |
7 | void NativeNotification::_bind_methods() {
8 | ClassDB::bind_method(D_METHOD("set_title", "title"), &NativeNotification::set_title);
9 | ClassDB::bind_method(D_METHOD("get_title"), &NativeNotification::get_title);
10 | ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
11 |
12 | ADD_GROUP("Notification", "notification");
13 | ClassDB::bind_method(D_METHOD("set_text", "text"), &NativeNotification::set_text);
14 | ClassDB::bind_method(D_METHOD("get_text"), &NativeNotification::get_text);
15 | ADD_PROPERTY(PropertyInfo(Variant::STRING, "notification_text", PROPERTY_HINT_MULTILINE_TEXT, ""), "set_text", "get_text");
16 |
17 | ClassDB::bind_method(D_METHOD("set_icon", "icon"), &NativeNotification::set_icon);
18 | ClassDB::bind_method(D_METHOD("get_icon"), &NativeNotification::get_icon);
19 | ADD_PROPERTY(PropertyInfo(Variant::INT, "notification_icon", PROPERTY_HINT_ENUM, "INFO,WARNING,ERROR"), "set_icon", "get_icon");
20 |
21 | ClassDB::bind_method(D_METHOD("send"), &NativeNotification::send);
22 |
23 | BIND_ENUM_CONSTANT(ICON_INFO);
24 | BIND_ENUM_CONSTANT(ICON_WARNING);
25 | BIND_ENUM_CONSTANT(ICON_ERROR);
26 | }
27 |
28 | NativeNotification::NativeNotification() {
29 | title = "Alert!";
30 | text = "";
31 | icon = ICON_WARNING;
32 | }
33 |
34 | void NativeNotification::send() {
35 | pfd::icon pfd_icon;
36 |
37 | switch (icon) {
38 | case ICON_INFO:
39 | pfd_icon = pfd::icon::info;
40 | break;
41 | case ICON_WARNING:
42 | pfd_icon = pfd::icon::warning;
43 | break;
44 | case ICON_ERROR:
45 | pfd_icon = pfd::icon::error;
46 | break;
47 | }
48 |
49 | pfd::notify(
50 | String(TranslationServer::get_singleton()->translate(title)).utf8().get_data(),
51 | String(TranslationServer::get_singleton()->translate(text)).utf8().get_data(),
52 | pfd_icon);
53 | }
54 |
55 | void NativeNotification::set_title(const String &p_title) {
56 | title = p_title;
57 | }
58 |
59 | String NativeNotification::get_title() {
60 | return title;
61 | }
62 |
63 | void NativeNotification::set_text(const String &p_text) {
64 | text = p_text;
65 | }
66 |
67 | String NativeNotification::get_text() {
68 | return text;
69 | }
70 |
71 | void NativeNotification::set_icon(Icon p_icon) {
72 | ERR_FAIL_INDEX(p_icon, 3);
73 |
74 | icon = p_icon;
75 | }
76 |
77 | NativeNotification::Icon NativeNotification::get_icon() {
78 | return icon;
79 | }
80 |
--------------------------------------------------------------------------------
/src/native_notification.h:
--------------------------------------------------------------------------------
1 | #ifndef NATIVENOTIFICATION_H
2 | #define NATIVENOTIFICATION_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | namespace godot {
11 |
12 | class NativeNotification : public Node {
13 | GDCLASS(NativeNotification, Node);
14 |
15 | protected:
16 | static void _bind_methods();
17 |
18 | public:
19 | enum Icon {
20 | ICON_INFO,
21 | ICON_WARNING,
22 | ICON_ERROR
23 | };
24 |
25 | private:
26 | String title;
27 | String text;
28 | Icon icon;
29 |
30 | public:
31 | NativeNotification();
32 |
33 | void send();
34 |
35 | void set_title(const String &p_title);
36 | String get_title();
37 |
38 | void set_text(const String &p_text);
39 | String get_text();
40 |
41 | void set_icon(Icon p_icon);
42 | Icon get_icon();
43 | };
44 |
45 | } // namespace godot
46 |
47 | VARIANT_ENUM_CAST(NativeNotification::Icon);
48 |
49 | #endif // NATIVENOTIFICATION_H
50 |
--------------------------------------------------------------------------------
/src/register_types.cpp:
--------------------------------------------------------------------------------
1 | #include "register_types.h"
2 |
3 | #include
4 |
5 | #include
6 | #include
7 | #include
8 |
9 | #include "native_accept_dialog.h"
10 | #include "native_confirmation_dialog.h"
11 | #include "native_file_dialog.h"
12 | #include "native_notification.h"
13 |
14 | using namespace godot;
15 |
16 | void register_types(ModuleInitializationLevel p_level) {
17 | if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
18 | return;
19 | }
20 |
21 | ClassDB::register_class();
22 | ClassDB::register_class();
23 | ClassDB::register_class();
24 | ClassDB::register_class();
25 | }
26 |
27 | void unregister_types(ModuleInitializationLevel p_level) {
28 | if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
29 | return;
30 | }
31 | }
32 |
33 | extern "C" {
34 |
35 | // Initialization.
36 |
37 | GDExtensionBool GDE_EXPORT native_dialogs_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
38 | GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
39 |
40 | init_obj.register_initializer(register_types);
41 | init_obj.register_terminator(unregister_types);
42 |
43 | init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
44 |
45 | return init_obj.init();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/register_types.h:
--------------------------------------------------------------------------------
1 | #ifndef NATIVE_DIALOGS_REGISTER_TYPES_H
2 | #define NATIVE_DIALOGS_REGISTER_TYPES_H
3 |
4 | #include
5 |
6 | using namespace godot;
7 |
8 | void register_types(ModuleInitializationLevel p_level);
9 | void unregister_types(ModuleInitializationLevel p_level);
10 |
11 | #endif // NATIVE_DIALOGS_REGISTER_TYPES_H
12 |
--------------------------------------------------------------------------------