Full Code of godotneers/G.U.I.D.E for AI

main c13dd0f7ec61 cached
1272 files
2.3 MB
666.0k tokens
14 symbols
1 requests
Download .txt
Showing preview only (2,654K chars total). Download the full file or copy to clipboard to get everything.
Repository: godotneers/G.U.I.D.E
Branch: main
Commit: c13dd0f7ec61
Files: 1272
Total size: 2.3 MB

Directory structure:
gitextract_ilg710ob/

├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   └── ISSUE_TEMPLATE/
│       ├── bug-.md
│       └── question.md
├── .gitignore
├── .junie/
│   └── guidelines.md
├── CHANGES.md
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── TODO.md
├── _assets/
│   ├── .gdignore
│   ├── action.afdesign
│   ├── arrows.afdesign
│   ├── bg.afdesign
│   ├── boat.afdesign
│   ├── joy.afdesign
│   ├── logo_editor_small.afdesign
│   ├── mouse.afdesign
│   ├── node_icons.afdesign
│   ├── spaceship.afdesign
│   └── touch.afdesign
├── addons/
│   ├── gdUnit4/
│   │   ├── GdUnitRunner.cfg
│   │   ├── LICENSE
│   │   ├── bin/
│   │   │   ├── GdUnitBuildTool.gd
│   │   │   ├── GdUnitBuildTool.gd.uid
│   │   │   ├── GdUnitCmdTool.gd
│   │   │   ├── GdUnitCmdTool.gd.uid
│   │   │   ├── GdUnitCopyLog.gd
│   │   │   └── GdUnitCopyLog.gd.uid
│   │   ├── plugin.cfg
│   │   ├── plugin.gd
│   │   ├── plugin.gd.uid
│   │   ├── runtest.cmd
│   │   ├── runtest.sh
│   │   └── src/
│   │       ├── Comparator.gd
│   │       ├── Comparator.gd.uid
│   │       ├── Fuzzers.gd
│   │       ├── Fuzzers.gd.uid
│   │       ├── GdUnitArrayAssert.gd
│   │       ├── GdUnitArrayAssert.gd.uid
│   │       ├── GdUnitAssert.gd
│   │       ├── GdUnitAssert.gd.uid
│   │       ├── GdUnitAwaiter.gd
│   │       ├── GdUnitAwaiter.gd.uid
│   │       ├── GdUnitBoolAssert.gd
│   │       ├── GdUnitBoolAssert.gd.uid
│   │       ├── GdUnitConstants.gd
│   │       ├── GdUnitConstants.gd.uid
│   │       ├── GdUnitDictionaryAssert.gd
│   │       ├── GdUnitDictionaryAssert.gd.uid
│   │       ├── GdUnitFailureAssert.gd
│   │       ├── GdUnitFailureAssert.gd.uid
│   │       ├── GdUnitFileAssert.gd
│   │       ├── GdUnitFileAssert.gd.uid
│   │       ├── GdUnitFloatAssert.gd
│   │       ├── GdUnitFloatAssert.gd.uid
│   │       ├── GdUnitFuncAssert.gd
│   │       ├── GdUnitFuncAssert.gd.uid
│   │       ├── GdUnitGodotErrorAssert.gd
│   │       ├── GdUnitGodotErrorAssert.gd.uid
│   │       ├── GdUnitIntAssert.gd
│   │       ├── GdUnitIntAssert.gd.uid
│   │       ├── GdUnitObjectAssert.gd
│   │       ├── GdUnitObjectAssert.gd.uid
│   │       ├── GdUnitResultAssert.gd
│   │       ├── GdUnitResultAssert.gd.uid
│   │       ├── GdUnitSceneRunner.gd
│   │       ├── GdUnitSceneRunner.gd.uid
│   │       ├── GdUnitSignalAssert.gd
│   │       ├── GdUnitSignalAssert.gd.uid
│   │       ├── GdUnitStringAssert.gd
│   │       ├── GdUnitStringAssert.gd.uid
│   │       ├── GdUnitTestSuite.gd
│   │       ├── GdUnitTestSuite.gd.uid
│   │       ├── GdUnitTuple.gd
│   │       ├── GdUnitTuple.gd.uid
│   │       ├── GdUnitValueExtractor.gd
│   │       ├── GdUnitValueExtractor.gd.uid
│   │       ├── GdUnitVectorAssert.gd
│   │       ├── GdUnitVectorAssert.gd.uid
│   │       ├── asserts/
│   │       │   ├── CallBackValueProvider.gd
│   │       │   ├── CallBackValueProvider.gd.uid
│   │       │   ├── DefaultValueProvider.gd
│   │       │   ├── DefaultValueProvider.gd.uid
│   │       │   ├── GdAssertMessages.gd
│   │       │   ├── GdAssertMessages.gd.uid
│   │       │   ├── GdAssertReports.gd
│   │       │   ├── GdAssertReports.gd.uid
│   │       │   ├── GdUnitArrayAssertImpl.gd
│   │       │   ├── GdUnitArrayAssertImpl.gd.uid
│   │       │   ├── GdUnitAssertImpl.gd
│   │       │   ├── GdUnitAssertImpl.gd.uid
│   │       │   ├── GdUnitAssertions.gd
│   │       │   ├── GdUnitAssertions.gd.uid
│   │       │   ├── GdUnitBoolAssertImpl.gd
│   │       │   ├── GdUnitBoolAssertImpl.gd.uid
│   │       │   ├── GdUnitDictionaryAssertImpl.gd
│   │       │   ├── GdUnitDictionaryAssertImpl.gd.uid
│   │       │   ├── GdUnitFailureAssertImpl.gd
│   │       │   ├── GdUnitFailureAssertImpl.gd.uid
│   │       │   ├── GdUnitFileAssertImpl.gd
│   │       │   ├── GdUnitFileAssertImpl.gd.uid
│   │       │   ├── GdUnitFloatAssertImpl.gd
│   │       │   ├── GdUnitFloatAssertImpl.gd.uid
│   │       │   ├── GdUnitFuncAssertImpl.gd
│   │       │   ├── GdUnitFuncAssertImpl.gd.uid
│   │       │   ├── GdUnitGodotErrorAssertImpl.gd
│   │       │   ├── GdUnitGodotErrorAssertImpl.gd.uid
│   │       │   ├── GdUnitIntAssertImpl.gd
│   │       │   ├── GdUnitIntAssertImpl.gd.uid
│   │       │   ├── GdUnitObjectAssertImpl.gd
│   │       │   ├── GdUnitObjectAssertImpl.gd.uid
│   │       │   ├── GdUnitResultAssertImpl.gd
│   │       │   ├── GdUnitResultAssertImpl.gd.uid
│   │       │   ├── GdUnitSignalAssertImpl.gd
│   │       │   ├── GdUnitSignalAssertImpl.gd.uid
│   │       │   ├── GdUnitStringAssertImpl.gd
│   │       │   ├── GdUnitStringAssertImpl.gd.uid
│   │       │   ├── GdUnitVectorAssertImpl.gd
│   │       │   ├── GdUnitVectorAssertImpl.gd.uid
│   │       │   ├── ValueProvider.gd
│   │       │   └── ValueProvider.gd.uid
│   │       ├── cmd/
│   │       │   ├── CmdArgumentParser.gd
│   │       │   ├── CmdArgumentParser.gd.uid
│   │       │   ├── CmdCommand.gd
│   │       │   ├── CmdCommand.gd.uid
│   │       │   ├── CmdCommandHandler.gd
│   │       │   ├── CmdCommandHandler.gd.uid
│   │       │   ├── CmdConsole.gd
│   │       │   ├── CmdConsole.gd.uid
│   │       │   ├── CmdOption.gd
│   │       │   ├── CmdOption.gd.uid
│   │       │   ├── CmdOptions.gd
│   │       │   └── CmdOptions.gd.uid
│   │       ├── core/
│   │       │   ├── GdArrayTools.gd
│   │       │   ├── GdArrayTools.gd.uid
│   │       │   ├── GdDiffTool.gd
│   │       │   ├── GdDiffTool.gd.uid
│   │       │   ├── GdFunctionDoubler.gd
│   │       │   ├── GdFunctionDoubler.gd.uid
│   │       │   ├── GdObjects.gd
│   │       │   ├── GdObjects.gd.uid
│   │       │   ├── GdUnit4Version.gd
│   │       │   ├── GdUnit4Version.gd.uid
│   │       │   ├── GdUnitClassDoubler.gd
│   │       │   ├── GdUnitClassDoubler.gd.uid
│   │       │   ├── GdUnitFileAccess.gd
│   │       │   ├── GdUnitFileAccess.gd.uid
│   │       │   ├── GdUnitObjectInteractions.gd
│   │       │   ├── GdUnitObjectInteractions.gd.uid
│   │       │   ├── GdUnitObjectInteractionsTemplate.gd
│   │       │   ├── GdUnitObjectInteractionsTemplate.gd.uid
│   │       │   ├── GdUnitProperty.gd
│   │       │   ├── GdUnitProperty.gd.uid
│   │       │   ├── GdUnitResult.gd
│   │       │   ├── GdUnitResult.gd.uid
│   │       │   ├── GdUnitRunner.gd
│   │       │   ├── GdUnitRunner.gd.uid
│   │       │   ├── GdUnitRunner.tscn
│   │       │   ├── GdUnitRunnerConfig.gd
│   │       │   ├── GdUnitRunnerConfig.gd.uid
│   │       │   ├── GdUnitSceneRunnerImpl.gd
│   │       │   ├── GdUnitSceneRunnerImpl.gd.uid
│   │       │   ├── GdUnitScriptType.gd
│   │       │   ├── GdUnitScriptType.gd.uid
│   │       │   ├── GdUnitSettings.gd
│   │       │   ├── GdUnitSettings.gd.uid
│   │       │   ├── GdUnitSignalAwaiter.gd
│   │       │   ├── GdUnitSignalAwaiter.gd.uid
│   │       │   ├── GdUnitSignalCollector.gd
│   │       │   ├── GdUnitSignalCollector.gd.uid
│   │       │   ├── GdUnitSignals.gd
│   │       │   ├── GdUnitSignals.gd.uid
│   │       │   ├── GdUnitSingleton.gd
│   │       │   ├── GdUnitSingleton.gd.uid
│   │       │   ├── GdUnitTestSuiteBuilder.gd
│   │       │   ├── GdUnitTestSuiteBuilder.gd.uid
│   │       │   ├── GdUnitTestSuiteScanner.gd
│   │       │   ├── GdUnitTestSuiteScanner.gd.uid
│   │       │   ├── GdUnitTools.gd
│   │       │   ├── GdUnitTools.gd.uid
│   │       │   ├── GodotVersionFixures.gd
│   │       │   ├── GodotVersionFixures.gd.uid
│   │       │   ├── LocalTime.gd
│   │       │   ├── LocalTime.gd.uid
│   │       │   ├── _TestCase.gd
│   │       │   ├── _TestCase.gd.uid
│   │       │   ├── assets/
│   │       │   │   └── touch-button.png.import
│   │       │   ├── command/
│   │       │   │   ├── GdUnitCommand.gd
│   │       │   │   ├── GdUnitCommand.gd.uid
│   │       │   │   ├── GdUnitCommandHandler.gd
│   │       │   │   ├── GdUnitCommandHandler.gd.uid
│   │       │   │   ├── GdUnitShortcut.gd
│   │       │   │   ├── GdUnitShortcut.gd.uid
│   │       │   │   ├── GdUnitShortcutAction.gd
│   │       │   │   └── GdUnitShortcutAction.gd.uid
│   │       │   ├── discovery/
│   │       │   │   ├── GdUnitTestDiscoverGuard.gd
│   │       │   │   ├── GdUnitTestDiscoverGuard.gd.uid
│   │       │   │   ├── GdUnitTestDiscoverer.gd
│   │       │   │   └── GdUnitTestDiscoverer.gd.uid
│   │       │   ├── event/
│   │       │   │   ├── GdUnitEvent.gd
│   │       │   │   ├── GdUnitEvent.gd.uid
│   │       │   │   ├── GdUnitEventInit.gd
│   │       │   │   ├── GdUnitEventInit.gd.uid
│   │       │   │   ├── GdUnitEventStop.gd
│   │       │   │   ├── GdUnitEventStop.gd.uid
│   │       │   │   ├── GdUnitEventTestDiscoverEnd.gd
│   │       │   │   ├── GdUnitEventTestDiscoverEnd.gd.uid
│   │       │   │   ├── GdUnitEventTestDiscoverStart.gd
│   │       │   │   ├── GdUnitEventTestDiscoverStart.gd.uid
│   │       │   │   ├── GdUnitEventTestDiscoverTestAdded.gd
│   │       │   │   ├── GdUnitEventTestDiscoverTestAdded.gd.uid
│   │       │   │   ├── GdUnitEventTestDiscoverTestRemoved.gd
│   │       │   │   ├── GdUnitEventTestDiscoverTestRemoved.gd.uid
│   │       │   │   ├── GdUnitEventTestDiscoverTestSuiteAdded.gd
│   │       │   │   └── GdUnitEventTestDiscoverTestSuiteAdded.gd.uid
│   │       │   ├── execution/
│   │       │   │   ├── GdUnitExecutionContext.gd
│   │       │   │   ├── GdUnitExecutionContext.gd.uid
│   │       │   │   ├── GdUnitMemoryObserver.gd
│   │       │   │   ├── GdUnitMemoryObserver.gd.uid
│   │       │   │   ├── GdUnitTestReportCollector.gd
│   │       │   │   ├── GdUnitTestReportCollector.gd.uid
│   │       │   │   ├── GdUnitTestSuiteExecutor.gd
│   │       │   │   ├── GdUnitTestSuiteExecutor.gd.uid
│   │       │   │   └── stages/
│   │       │   │       ├── GdUnitTestCaseAfterStage.gd
│   │       │   │       ├── GdUnitTestCaseAfterStage.gd.uid
│   │       │   │       ├── GdUnitTestCaseBeforeStage.gd
│   │       │   │       ├── GdUnitTestCaseBeforeStage.gd.uid
│   │       │   │       ├── GdUnitTestCaseExecutionStage.gd
│   │       │   │       ├── GdUnitTestCaseExecutionStage.gd.uid
│   │       │   │       ├── GdUnitTestSuiteAfterStage.gd
│   │       │   │       ├── GdUnitTestSuiteAfterStage.gd.uid
│   │       │   │       ├── GdUnitTestSuiteBeforeStage.gd
│   │       │   │       ├── GdUnitTestSuiteBeforeStage.gd.uid
│   │       │   │       ├── GdUnitTestSuiteExecutionStage.gd
│   │       │   │       ├── GdUnitTestSuiteExecutionStage.gd.uid
│   │       │   │       ├── IGdUnitExecutionStage.gd
│   │       │   │       ├── IGdUnitExecutionStage.gd.uid
│   │       │   │       ├── fuzzed/
│   │       │   │       │   ├── GdUnitTestCaseFuzzedExecutionStage.gd
│   │       │   │       │   ├── GdUnitTestCaseFuzzedExecutionStage.gd.uid
│   │       │   │       │   ├── GdUnitTestCaseFuzzedTestStage.gd
│   │       │   │       │   └── GdUnitTestCaseFuzzedTestStage.gd.uid
│   │       │   │       ├── parameterized/
│   │       │   │       │   ├── GdUnitTestCaseParameterSetTestStage.gd
│   │       │   │       │   ├── GdUnitTestCaseParameterSetTestStage.gd.uid
│   │       │   │       │   ├── GdUnitTestCaseParameterizedExecutionStage.gd
│   │       │   │       │   ├── GdUnitTestCaseParameterizedExecutionStage.gd.uid
│   │       │   │       │   ├── GdUnitTestCaseParameterizedTestStage.gd
│   │       │   │       │   └── GdUnitTestCaseParameterizedTestStage.gd.uid
│   │       │   │       └── single/
│   │       │   │           ├── GdUnitTestCaseSingleExecutionStage.gd
│   │       │   │           ├── GdUnitTestCaseSingleExecutionStage.gd.uid
│   │       │   │           ├── GdUnitTestCaseSingleTestStage.gd
│   │       │   │           └── GdUnitTestCaseSingleTestStage.gd.uid
│   │       │   ├── parse/
│   │       │   │   ├── GdClassDescriptor.gd
│   │       │   │   ├── GdClassDescriptor.gd.uid
│   │       │   │   ├── GdDefaultValueDecoder.gd
│   │       │   │   ├── GdDefaultValueDecoder.gd.uid
│   │       │   │   ├── GdFunctionArgument.gd
│   │       │   │   ├── GdFunctionArgument.gd.uid
│   │       │   │   ├── GdFunctionDescriptor.gd
│   │       │   │   ├── GdFunctionDescriptor.gd.uid
│   │       │   │   ├── GdScriptParser.gd
│   │       │   │   ├── GdScriptParser.gd.uid
│   │       │   │   ├── GdUnitExpressionRunner.gd
│   │       │   │   ├── GdUnitExpressionRunner.gd.uid
│   │       │   │   ├── GdUnitTestParameterSetResolver.gd
│   │       │   │   └── GdUnitTestParameterSetResolver.gd.uid
│   │       │   ├── report/
│   │       │   │   ├── GdUnitReport.gd
│   │       │   │   └── GdUnitReport.gd.uid
│   │       │   ├── templates/
│   │       │   │   └── test_suite/
│   │       │   │       ├── GdUnitTestSuiteDefaultTemplate.gd
│   │       │   │       ├── GdUnitTestSuiteDefaultTemplate.gd.uid
│   │       │   │       ├── GdUnitTestSuiteTemplate.gd
│   │       │   │       └── GdUnitTestSuiteTemplate.gd.uid
│   │       │   └── thread/
│   │       │       ├── GdUnitThreadContext.gd
│   │       │       ├── GdUnitThreadContext.gd.uid
│   │       │       ├── GdUnitThreadManager.gd
│   │       │       └── GdUnitThreadManager.gd.uid
│   │       ├── doubler/
│   │       │   ├── CallableDoubler.gd
│   │       │   └── CallableDoubler.gd.uid
│   │       ├── extractors/
│   │       │   ├── GdUnitFuncValueExtractor.gd
│   │       │   └── GdUnitFuncValueExtractor.gd.uid
│   │       ├── fuzzers/
│   │       │   ├── FloatFuzzer.gd
│   │       │   ├── FloatFuzzer.gd.uid
│   │       │   ├── Fuzzer.gd
│   │       │   ├── Fuzzer.gd.uid
│   │       │   ├── IntFuzzer.gd
│   │       │   ├── IntFuzzer.gd.uid
│   │       │   ├── StringFuzzer.gd
│   │       │   ├── StringFuzzer.gd.uid
│   │       │   ├── Vector2Fuzzer.gd
│   │       │   ├── Vector2Fuzzer.gd.uid
│   │       │   ├── Vector3Fuzzer.gd
│   │       │   └── Vector3Fuzzer.gd.uid
│   │       ├── matchers/
│   │       │   ├── AnyArgumentMatcher.gd
│   │       │   ├── AnyArgumentMatcher.gd.uid
│   │       │   ├── AnyBuildInTypeArgumentMatcher.gd
│   │       │   ├── AnyBuildInTypeArgumentMatcher.gd.uid
│   │       │   ├── AnyClazzArgumentMatcher.gd
│   │       │   ├── AnyClazzArgumentMatcher.gd.uid
│   │       │   ├── ChainedArgumentMatcher.gd
│   │       │   ├── ChainedArgumentMatcher.gd.uid
│   │       │   ├── EqualsArgumentMatcher.gd
│   │       │   ├── EqualsArgumentMatcher.gd.uid
│   │       │   ├── GdUnitArgumentMatcher.gd
│   │       │   ├── GdUnitArgumentMatcher.gd.uid
│   │       │   ├── GdUnitArgumentMatchers.gd
│   │       │   └── GdUnitArgumentMatchers.gd.uid
│   │       ├── mocking/
│   │       │   ├── GdUnitMock.gd
│   │       │   ├── GdUnitMock.gd.uid
│   │       │   ├── GdUnitMockBuilder.gd
│   │       │   ├── GdUnitMockBuilder.gd.uid
│   │       │   ├── GdUnitMockFunctionDoubler.gd
│   │       │   ├── GdUnitMockFunctionDoubler.gd.uid
│   │       │   ├── GdUnitMockImpl.gd
│   │       │   └── GdUnitMockImpl.gd.uid
│   │       ├── monitor/
│   │       │   ├── ErrorLogEntry.gd
│   │       │   ├── ErrorLogEntry.gd.uid
│   │       │   ├── GdUnitMonitor.gd
│   │       │   ├── GdUnitMonitor.gd.uid
│   │       │   ├── GdUnitOrphanNodesMonitor.gd
│   │       │   ├── GdUnitOrphanNodesMonitor.gd.uid
│   │       │   ├── GodotGdErrorMonitor.gd
│   │       │   └── GodotGdErrorMonitor.gd.uid
│   │       ├── mono/
│   │       │   ├── GdUnit4CSharpApi.cs
│   │       │   ├── GdUnit4CSharpApi.cs.uid
│   │       │   ├── GdUnit4CSharpApiLoader.gd
│   │       │   └── GdUnit4CSharpApiLoader.gd.uid
│   │       ├── network/
│   │       │   ├── GdUnitServer.gd
│   │       │   ├── GdUnitServer.gd.uid
│   │       │   ├── GdUnitServer.tscn
│   │       │   ├── GdUnitServerConstants.gd
│   │       │   ├── GdUnitServerConstants.gd.uid
│   │       │   ├── GdUnitTask.gd
│   │       │   ├── GdUnitTask.gd.uid
│   │       │   ├── GdUnitTcpClient.gd
│   │       │   ├── GdUnitTcpClient.gd.uid
│   │       │   ├── GdUnitTcpServer.gd
│   │       │   ├── GdUnitTcpServer.gd.uid
│   │       │   └── rpc/
│   │       │       ├── RPC.gd
│   │       │       ├── RPC.gd.uid
│   │       │       ├── RPCClientConnect.gd
│   │       │       ├── RPCClientConnect.gd.uid
│   │       │       ├── RPCClientDisconnect.gd
│   │       │       ├── RPCClientDisconnect.gd.uid
│   │       │       ├── RPCGdUnitEvent.gd
│   │       │       ├── RPCGdUnitEvent.gd.uid
│   │       │       ├── RPCGdUnitTestSuite.gd
│   │       │       ├── RPCGdUnitTestSuite.gd.uid
│   │       │       ├── RPCMessage.gd
│   │       │       ├── RPCMessage.gd.uid
│   │       │       └── dtos/
│   │       │           ├── GdUnitResourceDto.gd
│   │       │           ├── GdUnitResourceDto.gd.uid
│   │       │           ├── GdUnitTestCaseDto.gd
│   │       │           ├── GdUnitTestCaseDto.gd.uid
│   │       │           ├── GdUnitTestSuiteDto.gd
│   │       │           └── GdUnitTestSuiteDto.gd.uid
│   │       ├── report/
│   │       │   ├── GdUnitByPathReport.gd
│   │       │   ├── GdUnitByPathReport.gd.uid
│   │       │   ├── GdUnitHtmlPatterns.gd
│   │       │   ├── GdUnitHtmlPatterns.gd.uid
│   │       │   ├── GdUnitHtmlReport.gd
│   │       │   ├── GdUnitHtmlReport.gd.uid
│   │       │   ├── GdUnitReportSummary.gd
│   │       │   ├── GdUnitReportSummary.gd.uid
│   │       │   ├── GdUnitTestCaseReport.gd
│   │       │   ├── GdUnitTestCaseReport.gd.uid
│   │       │   ├── GdUnitTestSuiteReport.gd
│   │       │   ├── GdUnitTestSuiteReport.gd.uid
│   │       │   ├── JUnitXmlReport.gd
│   │       │   ├── JUnitXmlReport.gd.uid
│   │       │   ├── XmlElement.gd
│   │       │   ├── XmlElement.gd.uid
│   │       │   └── template/
│   │       │       ├── css/
│   │       │       │   ├── breadcrumb.css
│   │       │       │   ├── logo.png.import
│   │       │       │   └── styles.css
│   │       │       ├── folder_report.html
│   │       │       ├── index.html
│   │       │       └── suite_report.html
│   │       ├── spy/
│   │       │   ├── GdUnitSpyBuilder.gd
│   │       │   ├── GdUnitSpyBuilder.gd.uid
│   │       │   ├── GdUnitSpyFunctionDoubler.gd
│   │       │   ├── GdUnitSpyFunctionDoubler.gd.uid
│   │       │   ├── GdUnitSpyImpl.gd
│   │       │   └── GdUnitSpyImpl.gd.uid
│   │       ├── ui/
│   │       │   ├── GdUnitConsole.gd
│   │       │   ├── GdUnitConsole.gd.uid
│   │       │   ├── GdUnitConsole.tscn
│   │       │   ├── GdUnitFonts.gd
│   │       │   ├── GdUnitFonts.gd.uid
│   │       │   ├── GdUnitInspector.gd
│   │       │   ├── GdUnitInspector.gd.uid
│   │       │   ├── GdUnitInspector.tscn
│   │       │   ├── GdUnitInspectorTreeConstants.gd
│   │       │   ├── GdUnitInspectorTreeConstants.gd.uid
│   │       │   ├── GdUnitUiTools.gd
│   │       │   ├── GdUnitUiTools.gd.uid
│   │       │   ├── ScriptEditorControls.gd
│   │       │   ├── ScriptEditorControls.gd.uid
│   │       │   ├── menu/
│   │       │   │   ├── EditorFileSystemContextMenuHandler.gd
│   │       │   │   ├── EditorFileSystemContextMenuHandler.gd.uid
│   │       │   │   ├── GdUnitContextMenuItem.gd
│   │       │   │   ├── GdUnitContextMenuItem.gd.uid
│   │       │   │   ├── ScriptEditorContextMenuHandler.gd
│   │       │   │   └── ScriptEditorContextMenuHandler.gd.uid
│   │       │   ├── parts/
│   │       │   │   ├── InspectorMonitor.gd
│   │       │   │   ├── InspectorMonitor.gd.uid
│   │       │   │   ├── InspectorMonitor.tscn
│   │       │   │   ├── InspectorProgressBar.gd
│   │       │   │   ├── InspectorProgressBar.gd.uid
│   │       │   │   ├── InspectorProgressBar.tscn
│   │       │   │   ├── InspectorStatusBar.gd
│   │       │   │   ├── InspectorStatusBar.gd.uid
│   │       │   │   ├── InspectorStatusBar.tscn
│   │       │   │   ├── InspectorToolBar.gd
│   │       │   │   ├── InspectorToolBar.gd.uid
│   │       │   │   ├── InspectorToolBar.tscn
│   │       │   │   ├── InspectorTreeMainPanel.gd
│   │       │   │   ├── InspectorTreeMainPanel.gd.uid
│   │       │   │   └── InspectorTreePanel.tscn
│   │       │   ├── settings/
│   │       │   │   ├── GdUnitInputCapture.gd
│   │       │   │   ├── GdUnitInputCapture.gd.uid
│   │       │   │   ├── GdUnitInputCapture.tscn
│   │       │   │   ├── GdUnitSettingsDialog.gd
│   │       │   │   ├── GdUnitSettingsDialog.gd.uid
│   │       │   │   ├── GdUnitSettingsDialog.tscn
│   │       │   │   └── logo.png.import
│   │       │   └── templates/
│   │       │       ├── TestSuiteTemplate.gd
│   │       │       ├── TestSuiteTemplate.gd.uid
│   │       │       └── TestSuiteTemplate.tscn
│   │       └── update/
│   │           ├── GdMarkDownReader.gd
│   │           ├── GdMarkDownReader.gd.uid
│   │           ├── GdUnitPatch.gd
│   │           ├── GdUnitPatch.gd.uid
│   │           ├── GdUnitPatcher.gd
│   │           ├── GdUnitPatcher.gd.uid
│   │           ├── GdUnitUpdate.gd
│   │           ├── GdUnitUpdate.gd.uid
│   │           ├── GdUnitUpdate.tscn
│   │           ├── GdUnitUpdateClient.gd
│   │           ├── GdUnitUpdateClient.gd.uid
│   │           ├── GdUnitUpdateNotify.gd
│   │           ├── GdUnitUpdateNotify.gd.uid
│   │           ├── GdUnitUpdateNotify.tscn
│   │           └── assets/
│   │               ├── border_bottom.png.import
│   │               ├── border_top.png.import
│   │               ├── dot1.png.import
│   │               ├── dot2.png.import
│   │               ├── embedded.png.import
│   │               ├── fonts/
│   │               │   ├── LICENSE.txt
│   │               │   ├── README.txt
│   │               │   └── static/
│   │               │       ├── RobotoMono-Bold.ttf.import
│   │               │       ├── RobotoMono-BoldItalic.ttf.import
│   │               │       ├── RobotoMono-ExtraLight.ttf.import
│   │               │       ├── RobotoMono-ExtraLightItalic.ttf.import
│   │               │       ├── RobotoMono-Italic.ttf.import
│   │               │       ├── RobotoMono-Light.ttf.import
│   │               │       ├── RobotoMono-LightItalic.ttf.import
│   │               │       ├── RobotoMono-Medium.ttf.import
│   │               │       ├── RobotoMono-MediumItalic.ttf.import
│   │               │       ├── RobotoMono-Regular.ttf.import
│   │               │       ├── RobotoMono-SemiBold.ttf.import
│   │               │       ├── RobotoMono-SemiBoldItalic.ttf.import
│   │               │       ├── RobotoMono-Thin.ttf.import
│   │               │       └── RobotoMono-ThinItalic.ttf.import
│   │               └── horizontal-line2.png.import
│   └── guide/
│       ├── LICENSE.md
│       ├── debugger/
│       │   ├── guide_debugger.gd
│       │   ├── guide_debugger.gd.uid
│       │   └── guide_debugger.tscn
│       ├── editor/
│       │   ├── action_mapping_editor/
│       │   │   ├── action_mapping_editor.gd
│       │   │   ├── action_mapping_editor.gd.uid
│       │   │   └── action_mapping_editor.tscn
│       │   ├── action_slot/
│       │   │   ├── action_slot.gd
│       │   │   ├── action_slot.gd.uid
│       │   │   ├── action_slot.tscn
│       │   │   ├── action_slot_line_edit.gd
│       │   │   ├── action_slot_line_edit.gd.uid
│       │   │   ├── action_value_type_axis1d.svg.import
│       │   │   ├── action_value_type_axis2d.svg.import
│       │   │   ├── action_value_type_axis3d.svg.import
│       │   │   ├── action_value_type_bool.svg.import
│       │   │   └── missing_action.svg.import
│       │   ├── array_edit/
│       │   │   ├── array_edit.gd
│       │   │   ├── array_edit.gd.uid
│       │   │   ├── array_edit.tscn
│       │   │   ├── array_edit_item.gd
│       │   │   ├── array_edit_item.gd.uid
│       │   │   ├── array_edit_item.tscn
│       │   │   ├── dragger.gd
│       │   │   └── dragger.gd.uid
│       │   ├── binding_dialog/
│       │   │   ├── binding_dialog.gd
│       │   │   ├── binding_dialog.gd.uid
│       │   │   └── binding_dialog.tscn
│       │   ├── class_scanner.gd
│       │   ├── class_scanner.gd.uid
│       │   ├── guide_project_settings.gd
│       │   ├── guide_project_settings.gd.uid
│       │   ├── input_display/
│       │   │   ├── input_display.gd
│       │   │   ├── input_display.gd.uid
│       │   │   └── input_display.tscn
│       │   ├── input_mapping_editor/
│       │   │   ├── input_mapping_editor.gd
│       │   │   ├── input_mapping_editor.gd.uid
│       │   │   └── input_mapping_editor.tscn
│       │   ├── logo_editor_small.svg.import
│       │   ├── mapping_context_editor/
│       │   │   ├── mapping_context_editor.gd
│       │   │   ├── mapping_context_editor.gd.uid
│       │   │   └── mapping_context_editor.tscn
│       │   ├── modifier_slot/
│       │   │   ├── modifier_slot.gd
│       │   │   ├── modifier_slot.gd.uid
│       │   │   └── modifier_slot.tscn
│       │   ├── resource_scanner.gd
│       │   ├── resource_scanner.gd.uid
│       │   ├── resource_slot/
│       │   │   ├── resource_slot.gd
│       │   │   └── resource_slot.gd.uid
│       │   ├── trigger_slot/
│       │   │   ├── trigger_slot.gd
│       │   │   ├── trigger_slot.gd.uid
│       │   │   └── trigger_slot.tscn
│       │   ├── utils.gd
│       │   └── utils.gd.uid
│       ├── guide.gd
│       ├── guide.gd.uid
│       ├── guide_action.gd
│       ├── guide_action.gd.uid
│       ├── guide_action.svg.import
│       ├── guide_action_mapping.gd
│       ├── guide_action_mapping.gd.uid
│       ├── guide_input_mapping.gd
│       ├── guide_input_mapping.gd.uid
│       ├── guide_input_tracker.gd
│       ├── guide_input_tracker.gd.uid
│       ├── guide_internal.svg.import
│       ├── guide_mapping_context.gd
│       ├── guide_mapping_context.gd.uid
│       ├── guide_mapping_context.svg.import
│       ├── guide_reset.gd
│       ├── guide_reset.gd.uid
│       ├── guide_set.gd
│       ├── guide_set.gd.uid
│       ├── inputs/
│       │   ├── guide_input.gd
│       │   ├── guide_input.gd.uid
│       │   ├── guide_input.svg.import
│       │   ├── guide_input_action.gd
│       │   ├── guide_input_action.gd.uid
│       │   ├── guide_input_any.gd
│       │   ├── guide_input_any.gd.uid
│       │   ├── guide_input_joy_axis_1d.gd
│       │   ├── guide_input_joy_axis_1d.gd.uid
│       │   ├── guide_input_joy_axis_2d.gd
│       │   ├── guide_input_joy_axis_2d.gd.uid
│       │   ├── guide_input_joy_base.gd
│       │   ├── guide_input_joy_base.gd.uid
│       │   ├── guide_input_joy_button.gd
│       │   ├── guide_input_joy_button.gd.uid
│       │   ├── guide_input_key.gd
│       │   ├── guide_input_key.gd.uid
│       │   ├── guide_input_mouse_axis_1d.gd
│       │   ├── guide_input_mouse_axis_1d.gd.uid
│       │   ├── guide_input_mouse_axis_2d.gd
│       │   ├── guide_input_mouse_axis_2d.gd.uid
│       │   ├── guide_input_mouse_button.gd
│       │   ├── guide_input_mouse_button.gd.uid
│       │   ├── guide_input_mouse_position.gd
│       │   ├── guide_input_mouse_position.gd.uid
│       │   ├── guide_input_state.gd
│       │   ├── guide_input_state.gd.uid
│       │   ├── guide_input_touch_angle.gd
│       │   ├── guide_input_touch_angle.gd.uid
│       │   ├── guide_input_touch_axis_1d.gd
│       │   ├── guide_input_touch_axis_1d.gd.uid
│       │   ├── guide_input_touch_axis_2d.gd
│       │   ├── guide_input_touch_axis_2d.gd.uid
│       │   ├── guide_input_touch_axis_base.gd
│       │   ├── guide_input_touch_axis_base.gd.uid
│       │   ├── guide_input_touch_base.gd
│       │   ├── guide_input_touch_base.gd.uid
│       │   ├── guide_input_touch_distance.gd
│       │   ├── guide_input_touch_distance.gd.uid
│       │   ├── guide_input_touch_position.gd
│       │   └── guide_input_touch_position.gd.uid
│       ├── modifiers/
│       │   ├── guide_modifier.gd
│       │   ├── guide_modifier.gd.uid
│       │   ├── guide_modifier.svg.import
│       │   ├── guide_modifier_3d_coordinates.gd
│       │   ├── guide_modifier_3d_coordinates.gd.uid
│       │   ├── guide_modifier_8_way_direction.gd
│       │   ├── guide_modifier_8_way_direction.gd.uid
│       │   ├── guide_modifier_canvas_coordinates.gd
│       │   ├── guide_modifier_canvas_coordinates.gd.uid
│       │   ├── guide_modifier_curve.gd
│       │   ├── guide_modifier_curve.gd.uid
│       │   ├── guide_modifier_deadzone.gd
│       │   ├── guide_modifier_deadzone.gd.uid
│       │   ├── guide_modifier_input_swizzle.gd
│       │   ├── guide_modifier_input_swizzle.gd.uid
│       │   ├── guide_modifier_magnitude.gd
│       │   ├── guide_modifier_magnitude.gd.uid
│       │   ├── guide_modifier_map_range.gd
│       │   ├── guide_modifier_map_range.gd.uid
│       │   ├── guide_modifier_negate.gd
│       │   ├── guide_modifier_negate.gd.uid
│       │   ├── guide_modifier_normalize.gd
│       │   ├── guide_modifier_normalize.gd.uid
│       │   ├── guide_modifier_positive_negative.gd
│       │   ├── guide_modifier_positive_negative.gd.uid
│       │   ├── guide_modifier_scale.gd
│       │   ├── guide_modifier_scale.gd.uid
│       │   ├── guide_modifier_virtual_cursor.gd
│       │   ├── guide_modifier_virtual_cursor.gd.uid
│       │   ├── guide_modifier_window_relative.gd
│       │   └── guide_modifier_window_relative.gd.uid
│       ├── plugin.cfg
│       ├── plugin.gd
│       ├── plugin.gd.uid
│       ├── remapping/
│       │   ├── guide_input_detector.gd
│       │   ├── guide_input_detector.gd.uid
│       │   ├── guide_remapper.gd
│       │   ├── guide_remapper.gd.uid
│       │   ├── guide_remapping_config.gd
│       │   └── guide_remapping_config.gd.uid
│       ├── triggers/
│       │   ├── guide_trigger.gd
│       │   ├── guide_trigger.gd.uid
│       │   ├── guide_trigger.svg.import
│       │   ├── guide_trigger_chorded_action.gd
│       │   ├── guide_trigger_chorded_action.gd.uid
│       │   ├── guide_trigger_combo.gd
│       │   ├── guide_trigger_combo.gd.uid
│       │   ├── guide_trigger_combo_cancel_action.gd
│       │   ├── guide_trigger_combo_cancel_action.gd.uid
│       │   ├── guide_trigger_combo_step.gd
│       │   ├── guide_trigger_combo_step.gd.uid
│       │   ├── guide_trigger_down.gd
│       │   ├── guide_trigger_down.gd.uid
│       │   ├── guide_trigger_hair.gd
│       │   ├── guide_trigger_hair.gd.uid
│       │   ├── guide_trigger_hold.gd
│       │   ├── guide_trigger_hold.gd.uid
│       │   ├── guide_trigger_pressed.gd
│       │   ├── guide_trigger_pressed.gd.uid
│       │   ├── guide_trigger_pulse.gd
│       │   ├── guide_trigger_pulse.gd.uid
│       │   ├── guide_trigger_released.gd
│       │   ├── guide_trigger_released.gd.uid
│       │   ├── guide_trigger_stability.gd
│       │   ├── guide_trigger_stability.gd.uid
│       │   ├── guide_trigger_tap.gd
│       │   └── guide_trigger_tap.gd.uid
│       └── ui/
│           ├── guide_formatting_utils.gd
│           ├── guide_formatting_utils.gd.uid
│           ├── guide_icon_renderer.gd
│           ├── guide_icon_renderer.gd.uid
│           ├── guide_input_formatter.gd
│           ├── guide_input_formatter.gd.uid
│           ├── guide_input_formatting_options.gd
│           ├── guide_input_formatting_options.gd.uid
│           ├── guide_text_provider.gd
│           ├── guide_text_provider.gd.uid
│           ├── icon_maker/
│           │   ├── icon_maker.gd
│           │   ├── icon_maker.gd.uid
│           │   └── icon_maker.tscn
│           ├── renderers/
│           │   ├── controllers/
│           │   │   ├── guide_controller_render_style.gd
│           │   │   ├── guide_controller_render_style.gd.uid
│           │   │   ├── guide_controller_renderer.gd
│           │   │   ├── guide_controller_renderer.gd.uid
│           │   │   ├── guide_controller_renderer.tscn
│           │   │   └── styles/
│           │   │       ├── microsoft/
│           │   │       │   ├── XboxSeriesX_A.png.import
│           │   │       │   ├── XboxSeriesX_B.png.import
│           │   │       │   ├── XboxSeriesX_Dpad.png.import
│           │   │       │   ├── XboxSeriesX_Dpad_Down.png.import
│           │   │       │   ├── XboxSeriesX_Dpad_Left.png.import
│           │   │       │   ├── XboxSeriesX_Dpad_Right.png.import
│           │   │       │   ├── XboxSeriesX_Dpad_Up.png.import
│           │   │       │   ├── XboxSeriesX_LB.png.import
│           │   │       │   ├── XboxSeriesX_LT.png.import
│           │   │       │   ├── XboxSeriesX_Left_Stick.png.import
│           │   │       │   ├── XboxSeriesX_Left_Stick_Click.png.import
│           │   │       │   ├── XboxSeriesX_Menu.png.import
│           │   │       │   ├── XboxSeriesX_RB.png.import
│           │   │       │   ├── XboxSeriesX_RT.png.import
│           │   │       │   ├── XboxSeriesX_Right_Stick.png.import
│           │   │       │   ├── XboxSeriesX_Right_Stick_Click.png.import
│           │   │       │   ├── XboxSeriesX_Share.png.import
│           │   │       │   ├── XboxSeriesX_View.png.import
│           │   │       │   ├── XboxSeriesX_X.png.import
│           │   │       │   ├── XboxSeriesX_Y.png.import
│           │   │       │   └── microsoft.tres
│           │   │       ├── nintendo/
│           │   │       │   ├── Switch_A.png.import
│           │   │       │   ├── Switch_B.png.import
│           │   │       │   ├── Switch_Controller_Left.png.import
│           │   │       │   ├── Switch_Controller_Right.png.import
│           │   │       │   ├── Switch_Controllers.png.import
│           │   │       │   ├── Switch_Controllers_Separate.png.import
│           │   │       │   ├── Switch_Down.png.import
│           │   │       │   ├── Switch_Dpad.png.import
│           │   │       │   ├── Switch_Dpad_Down.png.import
│           │   │       │   ├── Switch_Dpad_Left.png.import
│           │   │       │   ├── Switch_Dpad_Right.png.import
│           │   │       │   ├── Switch_Dpad_Up.png.import
│           │   │       │   ├── Switch_Home.png.import
│           │   │       │   ├── Switch_LB.png.import
│           │   │       │   ├── Switch_LT.png.import
│           │   │       │   ├── Switch_Left.png.import
│           │   │       │   ├── Switch_Left_Stick.png.import
│           │   │       │   ├── Switch_Left_Stick_Click.png.import
│           │   │       │   ├── Switch_Minus.png.import
│           │   │       │   ├── Switch_Plus.png.import
│           │   │       │   ├── Switch_RB.png.import
│           │   │       │   ├── Switch_RT.png.import
│           │   │       │   ├── Switch_Right.png.import
│           │   │       │   ├── Switch_Right_Stick.png.import
│           │   │       │   ├── Switch_Right_Stick_Click.png.import
│           │   │       │   ├── Switch_Square.png.import
│           │   │       │   ├── Switch_Up.png.import
│           │   │       │   ├── Switch_X.png.import
│           │   │       │   ├── Switch_Y.png.import
│           │   │       │   └── nintendo.tres
│           │   │       ├── sony/
│           │   │       │   ├── PS5_Circle.png.import
│           │   │       │   ├── PS5_Cross.png.import
│           │   │       │   ├── PS5_Dpad.png.import
│           │   │       │   ├── PS5_Dpad_Down.png.import
│           │   │       │   ├── PS5_Dpad_Left.png.import
│           │   │       │   ├── PS5_Dpad_Right.png.import
│           │   │       │   ├── PS5_Dpad_Up.png.import
│           │   │       │   ├── PS5_L1.png.import
│           │   │       │   ├── PS5_L2.png.import
│           │   │       │   ├── PS5_Left_Stick.png.import
│           │   │       │   ├── PS5_Left_Stick_Click.png.import
│           │   │       │   ├── PS5_Microphone.png.import
│           │   │       │   ├── PS5_Options.png.import
│           │   │       │   ├── PS5_Options_Alt.png.import
│           │   │       │   ├── PS5_R1.png.import
│           │   │       │   ├── PS5_R2.png.import
│           │   │       │   ├── PS5_Right_Stick.png.import
│           │   │       │   ├── PS5_Right_Stick_Click.png.import
│           │   │       │   ├── PS5_Share.png.import
│           │   │       │   ├── PS5_Share_Alt.png.import
│           │   │       │   ├── PS5_Square.png.import
│           │   │       │   ├── PS5_Touch_Pad.png.import
│           │   │       │   ├── PS5_Triangle.png.import
│           │   │       │   └── sony.tres
│           │   │       └── steam_deck/
│           │   │           ├── SteamDeck_A.png.import
│           │   │           ├── SteamDeck_B.png.import
│           │   │           ├── SteamDeck_Dots.png.import
│           │   │           ├── SteamDeck_Dpad.png.import
│           │   │           ├── SteamDeck_Dpad_Down.png.import
│           │   │           ├── SteamDeck_Dpad_Left.png.import
│           │   │           ├── SteamDeck_Dpad_Right.png.import
│           │   │           ├── SteamDeck_Dpad_Up.png.import
│           │   │           ├── SteamDeck_Gyro.png.import
│           │   │           ├── SteamDeck_Inventory.png.import
│           │   │           ├── SteamDeck_L1.png.import
│           │   │           ├── SteamDeck_L2.png.import
│           │   │           ├── SteamDeck_L4.png.import
│           │   │           ├── SteamDeck_L5.png.import
│           │   │           ├── SteamDeck_Left_Stick.png.import
│           │   │           ├── SteamDeck_Left_Stick_Click.png.import
│           │   │           ├── SteamDeck_Left_Track.png.import
│           │   │           ├── SteamDeck_Menu.png.import
│           │   │           ├── SteamDeck_Minus.png.import
│           │   │           ├── SteamDeck_Plus.png.import
│           │   │           ├── SteamDeck_Power.png.import
│           │   │           ├── SteamDeck_R1.png.import
│           │   │           ├── SteamDeck_R2.png.import
│           │   │           ├── SteamDeck_R4.png.import
│           │   │           ├── SteamDeck_R5.png.import
│           │   │           ├── SteamDeck_Right_Stick.png.import
│           │   │           ├── SteamDeck_Right_Stick_Click.png.import
│           │   │           ├── SteamDeck_Right_Track.png.import
│           │   │           ├── SteamDeck_Square.png.import
│           │   │           ├── SteamDeck_Steam.png.import
│           │   │           ├── SteamDeck_X.png.import
│           │   │           ├── SteamDeck_Y.png.import
│           │   │           └── steam_deck.tres
│           │   ├── joy/
│           │   │   ├── guide_joy_render_style.gd
│           │   │   ├── guide_joy_render_style.gd.uid
│           │   │   ├── guide_joy_renderer.gd
│           │   │   ├── guide_joy_renderer.gd.uid
│           │   │   ├── guide_joy_renderer.tscn
│           │   │   └── styles/
│           │   │       ├── button_empty.png.import
│           │   │       ├── default.tres
│           │   │       └── stick_empty.png.import
│           │   ├── keyboard/
│           │   │   ├── guide_key_render_style.gd
│           │   │   ├── guide_key_render_style.gd.uid
│           │   │   ├── guide_key_renderer.gd
│           │   │   ├── guide_key_renderer.gd.uid
│           │   │   ├── guide_key_renderer.tscn
│           │   │   └── styles/
│           │   │       ├── Blank_White_Normal.png.import
│           │   │       ├── Lato-Black.ttf.import
│           │   │       └── default.tres
│           │   ├── misc/
│           │   │   ├── guide_action_renderer.gd
│           │   │   ├── guide_action_renderer.gd.uid
│           │   │   ├── guide_action_renderer.tscn
│           │   │   ├── guide_fallback_renderer.gd
│           │   │   ├── guide_fallback_renderer.gd.uid
│           │   │   └── guide_fallback_renderer.tscn
│           │   ├── mouse/
│           │   │   ├── guide_mouse_render_style.gd
│           │   │   ├── guide_mouse_render_style.gd.uid
│           │   │   ├── guide_mouse_renderer.gd
│           │   │   ├── guide_mouse_renderer.gd.uid
│           │   │   ├── guide_mouse_renderer.tscn
│           │   │   └── styles/
│           │   │       ├── Mouse_Cursor.png.import
│           │   │       ├── Mouse_Left_Key_Light.png.import
│           │   │       ├── Mouse_Middle_Key_Light.png.import
│           │   │       ├── Mouse_Right_Key_Light.png.import
│           │   │       ├── Mouse_Side_Key_1_Light.png.import
│           │   │       ├── Mouse_Side_Key_2_Light.png.import
│           │   │       ├── Mouse_Simple_Key_Light.png.import
│           │   │       └── default.tres
│           │   ├── style.svg.import
│           │   ├── textures/
│           │   │   ├── action.svg.import
│           │   │   ├── arrow_all_directions.svg.import
│           │   │   ├── arrow_down.svg.import
│           │   │   ├── arrow_horizontal.svg.import
│           │   │   ├── arrow_left.svg.import
│           │   │   ├── arrow_right.svg.import
│           │   │   ├── arrow_up.svg.import
│           │   │   └── arrow_vertical.svg.import
│           │   └── touch/
│           │       ├── guide_touch_render_style.gd
│           │       ├── guide_touch_render_style.gd.uid
│           │       ├── guide_touch_renderer.gd
│           │       ├── guide_touch_renderer.gd.uid
│           │       ├── guide_touch_renderer.tscn
│           │       └── styles/
│           │           ├── default.tres
│           │           ├── touch_1_finger.png.import
│           │           ├── touch_2_fingers.png.import
│           │           ├── touch_3_fingers.png.import
│           │           ├── touch_4_fingers.png.import
│           │           ├── touch_rotate.png.import
│           │           └── touch_zoom.png.import
│           ├── text_providers/
│           │   ├── controllers/
│           │   │   ├── guide_controller_label_set.gd
│           │   │   ├── guide_controller_label_set.gd.uid
│           │   │   ├── guide_controller_text_provider.gd
│           │   │   ├── guide_controller_text_provider.gd.uid
│           │   │   └── label_sets/
│           │   │       ├── microsoft.tres
│           │   │       ├── nintendo.tres
│           │   │       ├── sony.tres
│           │   │       └── steam_deck.tres
│           │   ├── default_text_provider.gd
│           │   └── default_text_provider.gd.uid
│           └── virtual_joy/
│               ├── guide_virtual_joy_base.gd
│               ├── guide_virtual_joy_base.gd.uid
│               ├── virtual_button/
│               │   ├── guide_virtual_button.gd
│               │   ├── guide_virtual_button.gd.uid
│               │   ├── guide_virtual_button.svg.import
│               │   ├── guide_virtual_button_renderer.gd
│               │   ├── guide_virtual_button_renderer.gd.uid
│               │   ├── guide_virtual_button_renderer.svg.import
│               │   └── texture_renderer/
│               │       ├── actuated.svg.import
│               │       ├── guide_virtual_button_texture_renderer.gd
│               │       ├── guide_virtual_button_texture_renderer.gd.uid
│               │       └── idle.svg.import
│               └── virtual_stick/
│                   ├── guide_virtual_stick.gd
│                   ├── guide_virtual_stick.gd.uid
│                   ├── guide_virtual_stick.svg.import
│                   ├── guide_virtual_stick_renderer.gd
│                   ├── guide_virtual_stick_renderer.gd.uid
│                   ├── guide_virtual_stick_renderer.svg.import
│                   └── texture_renderer/
│                       ├── guide_virtual_stick_texture_renderer.gd
│                       ├── guide_virtual_stick_texture_renderer.gd.uid
│                       ├── stick.svg.import
│                       ├── stick_hidden.svg.import
│                       └── stick_outline.svg.import
├── asset_library/
│   └── .gdignore
├── docs/
│   ├── .gdignore
│   ├── .gitignore
│   ├── Gemfile
│   ├── _config.yml
│   ├── _data/
│   │   └── toc.yml
│   ├── _docs/
│   │   ├── 01_installation.md
│   │   ├── 02_quick_start.md
│   │   ├── 03_video_tutorials.md
│   │   ├── 06_faq.md
│   │   ├── 07_support.md
│   │   ├── reference/
│   │   │   ├── 03_examples.md
│   │   │   ├── 04_input_reference.md
│   │   │   ├── 05_modifier_reference.md
│   │   │   └── 06_trigger_reference.md
│   │   └── usage/
│   │       ├── 01_concepts.md
│   │       ├── 02_configuration_and_input_handling.md
│   │       ├── 03_input_prompts.md
│   │       ├── 04_extending_guide.md
│   │       ├── 05_remapping_input.md
│   │       ├── 06_virtual_joysticks.md
│   │       └── 07_recipes.md
│   ├── _includes/
│   │   ├── alert.html
│   │   ├── doc.html
│   │   ├── editable.html
│   │   ├── feedback.html
│   │   ├── footer.html
│   │   ├── google-analytics.html
│   │   ├── head.html
│   │   ├── header.html
│   │   ├── navigation.html
│   │   ├── permalinks.html
│   │   ├── quiz/
│   │   │   └── multiple-choice.html
│   │   ├── quiz.html
│   │   ├── scripts.html
│   │   ├── scrolltop.html
│   │   ├── sidebar.html
│   │   ├── tags.html
│   │   ├── toc.html
│   │   └── video.html
│   ├── _layouts/
│   │   ├── default.html
│   │   ├── page.html
│   │   └── post.html
│   ├── _posts/
│   │   └── .gitkeep
│   ├── _recipes/
│   │   ├── 01_driving_a_progress_bar.md
│   │   └── 02_showing_debug_info_with_custom_ui.md
│   ├── assets/
│   │   ├── css/
│   │   │   ├── main.css
│   │   │   └── palette.css
│   │   └── js/
│   │       ├── main.js
│   │       └── search.js
│   ├── docker-compose.yaml
│   └── pages/
│       ├── archive.md
│       ├── feed.xml
│       ├── index.md
│       ├── search.html
│       └── sitemap.xml
├── editorconfig
├── export_presets.cfg
├── ggg.toml
├── guide_examples/
│   ├── 2d_axis_mapping/
│   │   ├── 2d_axis_mapping.gd
│   │   ├── 2d_axis_mapping.gd.uid
│   │   ├── 2d_axis_mapping.tscn
│   │   ├── mapping_contexts/
│   │   │   ├── 2d_axis_mapping.tres
│   │   │   └── move.tres
│   │   ├── player.gd
│   │   └── player.gd.uid
│   ├── action_priority/
│   │   ├── action_priority.gd
│   │   ├── action_priority.gd.uid
│   │   ├── action_priority.tscn
│   │   ├── dpad_spells/
│   │   │   ├── dpad_spells.gd
│   │   │   ├── dpad_spells.gd.uid
│   │   │   └── dpad_spells.tscn
│   │   ├── icons/
│   │   │   ├── enchant-acid-3.png.import
│   │   │   ├── enchant-blue-3.png.import
│   │   │   ├── enchant-jade-3.png.import
│   │   │   ├── enchant-red-3.png.import
│   │   │   ├── fireball-acid-3.png.import
│   │   │   ├── fireball-sky-3.png.import
│   │   │   ├── heal-royal-3.png.import
│   │   │   └── protect-blue-2.png.import
│   │   ├── mapping_contexts/
│   │   │   ├── action_priority.tres
│   │   │   └── actions/
│   │   │       ├── acid_bolt.tres
│   │   │       ├── acid_enchantment.tres
│   │   │       ├── fire_enchantment.tres
│   │   │       ├── heal.tres
│   │   │       ├── healing_enchantment.tres
│   │   │       ├── mana_bolt.tres
│   │   │       ├── mana_enchantment.tres
│   │   │       ├── shield.tres
│   │   │       └── spell_toggle.tres
│   │   └── spell_indicator/
│   │       ├── spell_indicator.gd
│   │       ├── spell_indicator.gd.uid
│   │       └── spell_indicator.tscn
│   ├── combine_contexts/
│   │   ├── combine_contexts.gd
│   │   ├── combine_contexts.gd.uid
│   │   ├── combine_contexts.tscn
│   │   └── mapping_contexts/
│   │       ├── controller.tres
│   │       ├── keyboard_and_mouse.tres
│   │       └── move.tres
│   ├── combos/
│   │   ├── combos.gd
│   │   ├── combos.gd.uid
│   │   ├── combos.tscn
│   │   ├── mapping_contexts/
│   │   │   ├── basic_actions/
│   │   │   │   ├── fire.tres
│   │   │   │   ├── move_horizontal.tres
│   │   │   │   ├── move_left.tres
│   │   │   │   └── move_right.tres
│   │   │   ├── combo_actions/
│   │   │   │   ├── dash_left.tres
│   │   │   │   ├── dash_right.tres
│   │   │   │   ├── fireball_left.tres
│   │   │   │   └── fireball_right.tres
│   │   │   └── combos.tres
│   │   ├── player.gd
│   │   └── player.gd.uid
│   ├── hair_trigger/
│   │   ├── hair_trigger.gd
│   │   ├── hair_trigger.gd.uid
│   │   ├── hair_trigger.tscn
│   │   ├── mapping_contexts/
│   │   │   ├── fire.tres
│   │   │   └── fire_context.tres
│   │   ├── trigger_visualizer.gd
│   │   └── trigger_visualizer.gd.uid
│   ├── input_contexts/
│   │   ├── boat.gd
│   │   ├── boat.gd.uid
│   │   ├── boat.svg.import
│   │   ├── input_contexts.gd
│   │   ├── input_contexts.gd.uid
│   │   ├── input_contexts.tscn
│   │   ├── mapping_contexts/
│   │   │   ├── boat_actions/
│   │   │   │   ├── accelerate.tres
│   │   │   │   ├── leave.tres
│   │   │   │   └── turn.tres
│   │   │   ├── boat_context.tres
│   │   │   ├── player_actions/
│   │   │   │   ├── move.tres
│   │   │   │   └── use.tres
│   │   │   └── player_context.tres
│   │   ├── player.gd
│   │   └── player.gd.uid
│   ├── input_prompts/
│   │   ├── input_prompts.gd
│   │   ├── input_prompts.gd.uid
│   │   ├── input_prompts.tscn
│   │   └── mapping_contexts/
│   │       ├── controller_activated.tres
│   │       ├── fire.tres
│   │       ├── input_prompts.tres
│   │       ├── keyboard_activated.tres
│   │       └── mouse_activated.tres
│   ├── input_scheme_switching/
│   │   ├── input_scheme_switching.gd
│   │   ├── input_scheme_switching.gd.uid
│   │   ├── input_scheme_switching.tscn
│   │   ├── mapping_contexts/
│   │   │   ├── actions/
│   │   │   │   ├── move.tres
│   │   │   │   ├── shoot.tres
│   │   │   │   ├── switch_to_joystick.tres
│   │   │   │   └── switch_to_keyboard.tres
│   │   │   ├── joystick_scheme.tres
│   │   │   └── keyboard_scheme.tres
│   │   ├── player.gd
│   │   └── player.gd.uid
│   ├── mouse_position_2d/
│   │   ├── background.gd
│   │   ├── background.gd.uid
│   │   ├── background.svg.import
│   │   ├── camera_2d.gd
│   │   ├── camera_2d.gd.uid
│   │   ├── godot_head.gd
│   │   ├── godot_head.gd.uid
│   │   ├── godot_head.tscn
│   │   ├── mapping_contexts/
│   │   │   ├── actions/
│   │   │   │   ├── camera_movement.tres
│   │   │   │   ├── camera_zoom.tres
│   │   │   │   ├── cursor.tres
│   │   │   │   └── spawn.tres
│   │   │   ├── modifiers/
│   │   │   │   └── zoom_sensitivity.tres
│   │   │   └── mouse_position.tres
│   │   ├── mouse_position.gd
│   │   ├── mouse_position.gd.uid
│   │   └── mouse_position.tscn
│   ├── mouse_position_3d/
│   │   ├── camera_control.gd
│   │   ├── camera_control.gd.uid
│   │   ├── mapping_context/
│   │   │   ├── actions/
│   │   │   │   ├── camera_move.tres
│   │   │   │   ├── camera_pitch.tres
│   │   │   │   ├── camera_toggle.tres
│   │   │   │   ├── camera_yaw.tres
│   │   │   │   ├── cursor_3d.tres
│   │   │   │   └── select.tres
│   │   │   └── mouse_position_3d.tres
│   │   ├── mou4D8E.tmp
│   │   ├── mouse_indicator.gd
│   │   ├── mouse_indicator.gd.uid
│   │   ├── mouse_position_3d.gd
│   │   ├── mouse_position_3d.gd.uid
│   │   ├── mouse_position_3d.tscn
│   │   ├── player.gd
│   │   └── player.gd.uid
│   ├── quick_start/
│   │   ├── game.gd
│   │   ├── game.gd.uid
│   │   ├── mapping_contexts/
│   │   │   ├── actions/
│   │   │   │   ├── move.tres
│   │   │   │   └── say_hi.tres
│   │   │   └── quickstart.tres
│   │   ├── player.gd
│   │   ├── player.gd.uid
│   │   └── quick_start.tscn
│   ├── remapping/
│   │   ├── mapping_contexts/
│   │   │   ├── binding_controller.tres
│   │   │   ├── binding_keyboard.tres
│   │   │   ├── controller.tres
│   │   │   ├── controller_actions/
│   │   │   │   ├── next_tab.tres
│   │   │   │   ├── player_movement_stick_deadzone.tres
│   │   │   │   ├── player_movement_stick_invert.tres
│   │   │   │   ├── previous_tab.tres
│   │   │   │   ├── switch_to_keyboard.tres
│   │   │   │   └── ui_accept.tres
│   │   │   ├── keyboard.tres
│   │   │   ├── keyboard_actions/
│   │   │   │   └── switch_to_controller.tres
│   │   │   └── shared_actions/
│   │   │       ├── close_menu.tres
│   │   │       ├── fire.tres
│   │   │       ├── open_menu.tres
│   │   │       └── player_movement_2d.tres
│   │   ├── player.gd
│   │   ├── player.gd.uid
│   │   ├── remapping.gd
│   │   ├── remapping.gd.uid
│   │   ├── remapping.tscn
│   │   ├── ui/
│   │   │   ├── binding_row.gd
│   │   │   ├── binding_row.gd.uid
│   │   │   ├── binding_row.tscn
│   │   │   ├── binding_section.gd
│   │   │   ├── binding_section.gd.uid
│   │   │   ├── binding_section.tscn
│   │   │   ├── remapping_dialog.gd
│   │   │   ├── remapping_dialog.gd.uid
│   │   │   └── remapping_dialog.tscn
│   │   ├── utils.gd
│   │   └── utils.gd.uid
│   ├── shared/
│   │   ├── fireball/
│   │   │   ├── fireball.gd
│   │   │   ├── fireball.gd.uid
│   │   │   ├── fireball.svg.import
│   │   │   └── fireball.tscn
│   │   ├── godot_logo.svg.import
│   │   ├── instructions_label.gd
│   │   ├── instructions_label.gd.uid
│   │   └── ui_theme.tres
│   ├── simple_input/
│   │   ├── mapping_contexts/
│   │   │   ├── move_down.tres
│   │   │   ├── move_left.tres
│   │   │   ├── move_right.tres
│   │   │   ├── move_up.tres
│   │   │   └── simple_input.tres
│   │   ├── player.gd
│   │   ├── player.gd.uid
│   │   ├── simple_input.gd
│   │   ├── simple_input.gd.uid
│   │   └── simple_input.tscn
│   ├── tap_and_hold/
│   │   ├── mapping_contexts/
│   │   │   ├── jump.tres
│   │   │   ├── somersault.tres
│   │   │   └── tap_and_hold.tres
│   │   ├── player.gd
│   │   ├── player.gd.uid
│   │   ├── tap_and_hold.gd
│   │   ├── tap_and_hold.gd.uid
│   │   └── tap_and_hold.tscn
│   ├── top_down_shooter/
│   │   ├── bolt/
│   │   │   ├── bolt.gd
│   │   │   ├── bolt.gd.uid
│   │   │   ├── bolt.png.import
│   │   │   └── bolt.tscn
│   │   ├── mapping_contexts/
│   │   │   ├── controller.tres
│   │   │   ├── fire.tres
│   │   │   ├── keyboard_and_mouse.tres
│   │   │   ├── look_absolute.tres
│   │   │   ├── look_relative.tres
│   │   │   ├── move.tres
│   │   │   ├── switch_to_controller.tres
│   │   │   └── switch_to_keyboard_and_mouse.tres
│   │   ├── player/
│   │   │   ├── mrg0000.png.import
│   │   │   ├── player.gd
│   │   │   └── player.gd.uid
│   │   ├── top_down_shooter.gd
│   │   ├── top_down_shooter.gd.uid
│   │   └── top_down_shooter.tscn
│   ├── touch/
│   │   ├── background.gd
│   │   ├── background.gd.uid
│   │   ├── background.svg.import
│   │   ├── camera_2d.gd
│   │   ├── camera_2d.gd.uid
│   │   ├── godot_head.gd
│   │   ├── godot_head.gd.uid
│   │   ├── godot_head.tscn
│   │   ├── mapping_contexts/
│   │   │   ├── actions/
│   │   │   │   ├── camera_movement.tres
│   │   │   │   ├── camera_reset.tres
│   │   │   │   ├── camera_rotation.tres
│   │   │   │   ├── camera_zoom.tres
│   │   │   │   └── spawn.tres
│   │   │   ├── modifiers/
│   │   │   │   └── zoom_sensitivity.tres
│   │   │   └── touch.tres
│   │   ├── placement_indicator/
│   │   │   ├── placement_indicator.gd
│   │   │   ├── placement_indicator.gd.uid
│   │   │   ├── placement_indicator.tscn
│   │   │   └── radial_progress.png.import
│   │   ├── touch.gd
│   │   ├── touch.gd.uid
│   │   └── touch.tscn
│   ├── two_joysticks/
│   │   ├── actions/
│   │   │   ├── player_one_move.tres
│   │   │   └── player_two_move.tres
│   │   ├── modifiers/
│   │   │   └── joystick_deadzone.tres
│   │   ├── player.gd
│   │   ├── player.gd.uid
│   │   ├── two_joysticks.gd
│   │   ├── two_joysticks.gd.uid
│   │   ├── two_joysticks.tres
│   │   └── two_joysticks.tscn
│   ├── virtual_cursor/
│   │   ├── mapping_contexts/
│   │   │   ├── actions/
│   │   │   │   ├── click.tres
│   │   │   │   ├── cursor_2d.tres
│   │   │   │   ├── switch_to_controller.tres
│   │   │   │   └── switch_to_keyboard.tres
│   │   │   ├── controller_mappings.tres
│   │   │   └── keyboard_mappings.tres
│   │   ├── pointable/
│   │   │   ├── pointable.gd
│   │   │   ├── pointable.gd.uid
│   │   │   └── pointable.tscn
│   │   ├── pointer.gd
│   │   ├── pointer.gd.uid
│   │   ├── pointer.svg.import
│   │   ├── virtual_cursor.gd
│   │   ├── virtual_cursor.gd.uid
│   │   └── virtual_cursor.tscn
│   └── virtual_sticks/
│       ├── custom_stick_renderer/
│       │   ├── custom_stick_renderer.gd
│       │   ├── custom_stick_renderer.gd.uid
│       │   ├── custom_stick_renderer.gdshader
│       │   └── custom_stick_renderer.gdshader.uid
│       ├── mapping_contexts/
│       │   ├── fire_projectile.tres
│       │   ├── mapping_context.tres
│       │   ├── move_ship.tres
│       │   └── rotate_ship.tres
│       ├── projectile/
│       │   ├── laser.svg.import
│       │   ├── projectile.gd
│       │   ├── projectile.gd.uid
│       │   └── projectile.tscn
│       ├── ship/
│       │   ├── ship.gd
│       │   ├── ship.gd.uid
│       │   ├── ship.tscn
│       │   └── spaceship.png.import
│       ├── virtual_sticks.gd
│       ├── virtual_sticks.gd.uid
│       └── virtual_sticks.tscn
├── icon.svg.import
├── project.godot
├── run_tests.cmd
└── tests/
    ├── guide_input_matcher.gd
    ├── guide_input_matcher.gd.uid
    ├── guide_test_base.gd
    ├── guide_test_base.gd.uid
    ├── test_action_prioritization.gd
    ├── test_action_prioritization.gd.uid
    ├── test_action_signals.gd
    ├── test_action_signals.gd.uid
    ├── test_any_input.gd
    ├── test_any_input.gd.uid
    ├── test_context_mapping_combine.gd
    ├── test_context_mapping_combine.gd.uid
    ├── test_context_switching.gd
    ├── test_context_switching.gd.uid
    ├── test_down_trigger.gd
    ├── test_down_trigger.gd.uid
    ├── test_guide_default_text_provider.gd
    ├── test_guide_default_text_provider.gd.uid
    ├── test_guide_input_formatter.gd
    ├── test_guide_input_formatter.gd.uid
    ├── test_input_detector.gd
    ├── test_input_detector.gd.uid
    ├── test_input_on_context_change.gd
    ├── test_input_on_context_change.gd.uid
    ├── test_invalid_configuration.gd
    ├── test_invalid_configuration.gd.uid
    ├── test_joy_axis_1d_input.gd
    ├── test_joy_axis_1d_input.gd.uid
    ├── test_joy_axis_2d_input.gd
    ├── test_joy_axis_2d_input.gd.uid
    ├── test_joy_button_input.gd
    ├── test_joy_button_input.gd.uid
    ├── test_key_input.gd
    ├── test_key_input.gd.uid
    ├── test_layered_contexts.gd
    ├── test_layered_contexts.gd.uid
    ├── test_magnitude_modifier.gd
    ├── test_magnitude_modifier.gd.uid
    ├── test_map_range_modifier.gd
    ├── test_map_range_modifier.gd.uid
    ├── test_mouse_axis_1d_input.gd
    ├── test_mouse_axis_1d_input.gd.uid
    ├── test_mouse_axis_2d_input.gd
    ├── test_mouse_axis_2d_input.gd.uid
    ├── test_mouse_button_input.gd
    ├── test_mouse_button_input.gd.uid
    ├── test_multiple_input_events_per_frame.gd
    ├── test_multiple_input_events_per_frame.gd.uid
    ├── test_node_leaks.gd
    ├── test_node_leaks.gd.uid
    ├── test_pause_mode.gd
    ├── test_pause_mode.gd.uid
    ├── test_released_trigger.gd
    ├── test_released_trigger.gd.uid
    ├── test_touch_angle_input.gd
    ├── test_touch_angle_input.gd.uid
    ├── test_touch_axis_1d_input.gd
    ├── test_touch_axis_1d_input.gd.uid
    ├── test_touch_axis_2d_input.gd
    ├── test_touch_axis_2d_input.gd.uid
    ├── test_touch_distance_input.gd
    ├── test_touch_distance_input.gd.uid
    ├── test_touch_position_input.gd
    ├── test_touch_position_input.gd.uid
    ├── test_trigger_hair.gd
    ├── test_trigger_hair.gd.uid
    ├── test_virtual_buttons.gd
    ├── test_virtual_buttons.gd.uid
    ├── test_virtual_cursor.gd
    ├── test_virtual_cursor.gd.uid
    ├── test_virtual_sticks.gd
    └── test_virtual_sticks.gd.uid

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf

# Only include the addons/guide folder when downloading from the Asset Library.
/**        export-ignore
/addons    !export-ignore
/addons/guide !export-ignore
/addons/guide/** !export-ignore
# also include the examples folder
/guide_examples !export-ignore
/guide_examples/** !export-ignore


================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: derkork
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']


================================================
FILE: .github/ISSUE_TEMPLATE/bug-.md
================================================
---
name: 'Bug '
about: I have encountered a bug
title: ''
labels: ''
assignees: ''

---

Godot Version (_e.g. 4.2, 4.3, 4.4beta3_): 
G.U.I.D.E Version (_e.g. 0.3.1_):

**The bug**

Please include the following information as it really helps getting problems solved quicker:
- What were you trying to achieve?
- What happened?
- What would you have expected instead?
- Screenshots and/or minimal examples to reproduce the issue.


================================================
FILE: .github/ISSUE_TEMPLATE/question.md
================================================
---
name: Question
about: I have a question on how to use the library.
title: ''
labels: knowledge
assignees: ''

---

Write your question here. Try to be specific (e.g. "how can I detect from which controller an input comes" is a lot better than "how do i make a  local multiplayer game with this").


================================================
FILE: .gitignore
================================================
# Godot 4+ specific ignores
.godot/
android/
addons/explore-editor-theme/

# IntelliJ IDEA
.idea/

# macOS
.DS_Store

zz-sup/

reports/
progress.md
task_plan.md
findings.md
.ggg.state


================================================
FILE: .junie/guidelines.md
================================================

## Generic code guidelines
Always use tabs for indentation. Always add GDScript type hints everywhere. When doing null checks use `is_instance_valid(object)` rather than `object != null`. GDScripts should always end with an empty line. All `@onready` variables are private and need to start with an underscore. For constructs, that refer to other code, always use the type-safe variant without strings, e.g:

- `my_signal.emit()` rather than `emit_signal("my_signal")`
- `foo.some_signal.connect(_on_foo_some_signal)` rather than `foo.connect("some_signal", self, "_on_foo_some_signal")`

Omit `self` when not stricly needed. GDScript does not support nested named functions. So something like:

```gdscript
func foo():
    func bar():
        print("Hello world!")
    bar()
```

does not work. If needed, you can make a lambda:

```gdscript
func foo():
    var bar = func(): print("Hello world!")
    bar()
    
```

Lambdas should be used sparingly, e.g., in functions that take callables as arguments. For example, `Array.sort_custom()`.
  

## Accessing nodes 
When referring to nodes, always use scene unique names instead of paths. If a node has no scene unique name in a scene, but you need it in a script, then add a scene unique name. Always initialize node references in an `@onready` variable rather than littering the code with inline node references. When getting a node from the scene use the provided `Assure.exists` method to check that the node is there and of the right type (e.g. `@onready var _my_node: Node2D = Assure.exists(%MyNode as Node2D)`). This will ensure that the node exists and is of the correct type, and will throw an error if it is not. This also means that we don't need to check for null or type errors later in the code.

## Documentation
Always document your code using the GDScript documentation style. Use `@param` to document parameters, `@return` to document return values, and `@signal` to document signals. Documentation should focus on the "why" rather than the "how". Don't document the obvious, but rather explain the reasoning behind the code. Write in a simple, clear style avoid fancy language. Documentation for classes always goes in front of the `class_name` line, documentation for methods goes in front of the method definition. Example:

```gdscript
## This class provides utility functions for the project.
class_name Utilties

## Divides an integer number by another integer. 
## @param a The first integer to divide.
## @param b The second integer to divide. This must not be zero.
## @return The result of the division.
static func divide(a: int, b: int) -> int:
    assert(b != 0, "Division by zero is not allowed.")
    return a / b
```

All documentation happens in the code, don't add any extra documentation files.

## UIDs
Never mess with UIDs. They are automatically generated by Godot and should not be changed manually. Use paths to refer to resources, Godot will automatically convert this to UIDs when needed. If you need to refer to a resource in code, use the `load()` function with the path to the resource. Also never generate .uid files manually, they are automatically generated by Godot when the resource is saved. If you refer to resources from other resources always use the path not the uid. Leave out the uid attribute in the resource file, it will be automatically generated by Godot when the resource is saved.

## Writing tests
The test framework does not stop execution on failed assertions, so make sure the code after an assertion doesn't assume that the assertion was successful.

## Running tests
You can run tests using the `.\run_tests.cmd` file in the project root. This will run GDUnit4 in Godot and print the test results. Only run tests when specifically being asked about it.

- To run only a single test suite, you can use the `-a` parameter to specify the test file or method. For example:

    ```
    .\run_tests.cmd -a tests\test_large_trigger_plate\test_large_trigger_plate.gd
    ```

- To run a specific test method, use the format `test_file.gd:test_method_name`:

    ```
    .\run_tests.cmd -a tests\test_large_trigger_plate\test_large_trigger_plate.gd:test_trigger_reacts_to_two_bodies
    ```

================================================
FILE: CHANGES.md
================================================
# Changelog
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- `GUIDEInputFormatter` now has a `for_contexts` factory method which provides a formatter that works on the given contexts. This is useful if you need information from multiple contexts without these contexts currently being active ([#190](https://github.com/godotneers/G.U.I.D.E/issues/190)).

### Improved
- The mapping context editor now has menu options to insert action mappings and input mappings before and after the current item. This makes it easier to work with larger mapping contexts ([#190](https://github.com/godotneers/G.U.I.D.E/issues/190))

### Fixed
- Fixed a bug where the _Any_ input would keep firing continuously after the application loses focus (e.g. by pressing Alt+Tab or the Windows key). This happened because Godot clears its own input state directly without dispatching input events when the application loses focus, causing G.U.I.D.E's internal input state to diverge ([#189](https://github.com/godotneers/G.U.I.D.E/issues/189)).


## [0.12.0] - 2026-03-27
### Improved
- The direction icons for all built-in input renderers (controller, mouse, touch, joy) have been redesigned. Instead of showing the device icon and the direction arrow side by side, the direction arrow is now overlaid on top of a slightly inset device icon, making input prompts more visually compact. A big thanks goes to [SilverWolveGames](https://github.com/SilverWolveGames) for contributing the new icons and the initial implementation ([#179](https://github.com/godotneers/G.U.I.D.E/issues/179),[#182](https://github.com/godotneers/G.U.I.D.E/pull/182))!

### Fixed
- Fixed a bug where the input formatter would not properly format chorded inputs when input filtering was active ([#175](https://github.com/godotneers/G.U.I.D.E/issues/175)).


## [0.12.0-beta1] - 2026-02-23
### Added
- G.U.I.D.E now supports merging of multiple mapping contexts with overlapping actions. This allows you to define multiple mapping contexts that have different inputs bound to the same action. Upon merge, these will be combined into a single action definition. This is useful for supporting multiple different input methods at the same time. Before, only one definition of an action could be active at a time and loading a second one would replace the first one. Because this is quite complex to get right under the hood, this feature is currently only available in beta releases on Github and will only be published to the asset library once there is enough feedback from real-world usage. There are no breaking API changes for this feature, so it should drop right into your project without any changes required. A huge thanks goes out to [ShadowCommander](https://github.com/ShadowCommander) for contributing this feature and helping so much with the debugging ([#168](https://github.com/godotneers/G.U.I.D.E/pull/168))!
- There is now a new method which allows you to quickly replace all existing mapping contexts with a new set. This is often needed in UI dialogues and until now required keeping track of what mapping contexts were active before replacing them. Now you can call `var old_mapping_contexts := GUIDE.set_enabled_mapping_contexts(new_mapping_contexts)`. This will swap the current set of enabled mapping contexts with the new set and return the old set.

## [0.11.2] - 2026-02-17
### Fixed
- The _Any_ input now properly fires continuously when used with a _Down_ trigger. Previously it would only fire once on the initial press rather than every frame while the input was held ([#171](https://github.com/godotneers/G.U.I.D.E/issues/171)).

## [0.11.1] - 2026-02-10
### Fixed
- Fixed a runtime error that could occur when disconnecting and reconnecting controllers during gameplay ([#164](https://github.com/godotneers/G.U.I.D.E/issues/164), [#169](https://github.com/godotneers/G.U.I.D.E/pull/169)). A big thanks goes out to [Phlegmlee](https://github.com/Phlegmlee) for contributing a PR for this!
- Fixed a regression where the input tracker would not work correctly when the game was paused.

## [0.11.0] - 2026-02-06
### Added
- Added a new hair trigger. Hair triggers reduce the travel distance needed to register a full trigger press, enabling faster response times. Useful for quick actions like rapid firing or accelerating in racing games. A huge thanks goes out to [ShadowCommander](https://github.com/ShadowCommander) who contributed this feature ([#24](https://github.com/godotneers/G.U.I.D.E/issues/24), [#167](https://github.com/godotneers/G.U.I.D.E/pull/167))!


## [0.10.1] - 2026-02-02
### Fixed
- The input tracker now handles some edge cases better on UI components that are overridden by the game ([#166](https://github.com/godotneers/G.U.I.D.E/issues/166)) 

## [0.10.0] - 2026-01-16
### Breaking Changes
- The _Released_ trigger now makes the action go into _Ongoing_ state while the input is actuated. Previously it would stay in _Completed_. This is useful for touch input to be able to acquire touch position information while the input is still active ([#144](https://github.com/godotneers/G.U.I.D.E/issues/144)). This change should not affect most users, but since it changes the behavior of this trigger, I still declare this a breaking change.

### Added
- The Steam Deck controller is now supported as its own controller type ([#152](https://github.com/godotneers/G.U.I.D.E/issues/152)). A big thanks goes to [Live, Laugh, Luke](https://github.com/live-laugh-luke) for helping to get this on the road and testing it on their Steam Deck!

### Improved
- The [trigger reference page](https://godotneers.github.io/G.U.I.D.E/reference/triggers) now contains some state diagrams showing the behavior of each trigger type. This makes it easier to understand how each trigger behaves.

## [0.9.1] - 2026-01-11
### Fixed
- The icons for right stick and left stick click are no longer mixed up for Microsoft-style controllers ([#159](https://github.com/godotneers/G.U.I.D.E/issues/159))

## [0.9.0] - 2026-01-03
### Added
- `GUIDEAction` now has a new signal `just_triggered` that is emitted the first frame that the action is triggered. A huge thanks goes to [Josh Taylor](https://github.com/codeinclined) for submitting a PR for this ([#155](https://github.com/godotneers/G.U.I.D.E/pull/155)).

## [0.9.0-beta3] - 2025-12-13
### Fixed
- `GUIDEInputDetector` now again properly emits the `detection_started` signal ([#142](https://github.com/godotneers/G.U.I.D.E/issues/142)).
- Inputs are now properly formatted in exported games again ([#149](https://github.com/godotneers/G.U.I.D.E/issues/149))

## [0.9.0-beta2] - 2025-11-30
### Breaking Changes
- The input formatting system has received an overhaul to make it more flexible. This has been done in a way that is backwards compatible, as long as the game code only uses `GUIDEInputFormatter` to interface with the formatting system. If you have written a custom icon renderer or text provider, you will need to do a few slight adjustments to your code:
  - The functions `GUIDEIconRenderer.supports`, `GUIDEIconRenderer.render` and `GUIDEIconRenderer.cache_key` now take an additional parameter of type `GUIDEInputFormattingOptions`. This parameter contains the newly introduced formatting options that are currently active on the `GUIDEInputFormatter`. Unless you want to make use of these, all you need to do is to add this new parameter to the function signatures.
  - Similarly `GUIDETextProvider.supports` and `GUIDETextProvider.get_text` now take an additional parameter of type `GUIDEInputFormattingOptions`.

### Added
- It is now possible to create render styles for the built-in icon renderers. This allows you to customize the icons used in input prompts to match the style of your game without having to write a custom renderer. See the [documentation](https://godotneers.github.io/G.U.I.D.E/usage/input-prompts#customizing-the-style-of-the-input-prompt-icons) for more information.
- It is now [possible to force a specific set of icons](https://godotneers.github.io/G.U.I.D.E/usage/input-prompts#controlling-the-displayed-controller-icons) to display for controllers, no matter which type of controller is currently connected. This allows you to work around issues with generic controllers not being detected correctly or just to cater for player who want to select which icons they see ([#133](https://github.com/godotneers/G.U.I.D.E/issues/133)). 
- This feature allows you to force the display of specific controller icons in the editor. There is a new project setting for this. Enable _Advanced_ settings and check the _GUIDE/Editor_ section of the project settings to enable this ([#132](https://github.com/godotneers/G.U.I.D.E/discussions/132)).
- It is now possible to [only show input related to certain device types](https://godotneers.github.io/G.U.I.D.E/usage/input-prompts#controlling-the-display-of-mixed-inputs) in the input prompts. This is useful in simple scenarios where you just want to bind multiple different inputs to the same action and don't want to to have input prompts like "press Space, left mouse button or RB to jump" ([#139](https://github.com/godotneers/G.U.I.D.E/issues/139)).
- It is now possible to quickly select a mapping context directly from the mapping context editor without having to search the tree for it ([#124](https://github.com/godotneers/G.U.I.D.E/issues/124)).

### Fixed
- The `GUIDEModifier3DCoordinates` now also works when physics are processed in a separate thread ([#91](https://github.com/godotneers/G.U.I.D.E/issues/91)). A big thanks goes to [elsen0xcc](https://github.com/elsen0xcc) for submitting a PR for this ([#138](https://github.com/godotneers/G.U.I.D.E/pull/138)).
- Type hints are now added to all files, allowing to run the project in strict typing mode ([#130](https://github.com/godotneers/G.U.I.D.E/issues/130)).

## [0.9.0-beta1] - 2025-11-04

### Added
- G.U.I.D.E has now support for virtual on-screen joysticks and buttons. These work both with mouse and touch inputs. This is useful for mobile games and allows steering controls just the touch screen. There is a new demo in the `guide_examples` folder showing how to use this. You can also check the [documentation](https://godotneers.github.io/G.U.I.D.E/usage/virtual-joysticks) for more information on how to use them. 
- `GUIDEMappingContext` now has signals `enabled` and `disabled` which fire when the context is enabled or disabled. This can be useful to trigger some game logic when a context is activated or deactivated. A big thanks goes to [Jonathan Durbin](https://github.com/jonathan-durbin) for providing a PR for this ([#119](https://github.com/godotneers/G.U.I.D.E/pull/119)).

- The virtual cursor modifier now has a setting allowing to synchronize the cursor position with the actual mouse position when activated or deactivated. This is useful when switching between a gamepad and a mouse to avoid jumps in the cursor position. The virtual cursor demo has been updated to make use of this functionality ([#122](https://github.com/godotneers/G.U.I.D.E/issues/122)).

### Improved
- The joy device index in `GUIDEInputJoy*` has been changed from a number to a dropdown. This makes the implicit meaning of `-1` as _Any joystick_ more explicit. It also allows for easy selection of virtual joysticks.

### Fixed
- The input detector will now properly detect abort input even when this input was already pressed when starting the detection ([#123](https://github.com/godotneers/G.U.I.D.E/pull/119)).
- When changing mapping contexts, actions will not intermittently report initial values anymore. Instead actions are guaranteed to have the value of their input after the context switch, within the same frame. This avoids issues where actions would briefly report wrong values after a context switch ([#125](https://github.com/godotneers/G.U.I.D.E/issues/125)).

## [0.8.0] - 2025-09-29
### Added
- Added magnitude modifier. This is useful to determine the strength of an input vector, e.g. to determine how far a joystick is pushed. 

## [0.7.5] - 2025-08-19
### Fixed
- Popup menus should now appear at the correct positions in multi-monitor and wide-screen setups ([#88](https://github.com/godotneers/G.U.I.D.E/issues/88), [#108](https://github.com/godotneers/G.U.I.D.E/issues/108)).


## [0.7.4] - 2025-08-11
### Fixed
- The input formatter should now properly format all keyboard and touch inputs ([#105](https://github.com/godotneers/G.U.I.D.E/issues/105)).

## [0.7.3] - 2025-07-31
### Fixed
- When layering mapping contexts G.U.I.D.E will no longer ignore bound inputs ([#94](https://github.com/godotneers/G.U.I.D.E/issues/94)).

## [0.7.2] - 2025-07-29
### Fixed
- Input detection will now be properly aborted when an abort input is actuated ([#92](https://github.com/godotneers/G.U.I.D.E/issues/92)).

## [0.7.1] - 2025-07-29
### Fixed
- When layering mapping contexts, G.U.I.D.E will no longer duplicate actions ([#89](https://github.com/godotneers/G.U.I.D.E/issues/89), [#93](https://github.com/godotneers/G.U.I.D.E/issues/93)).

## [0.7.0] - 2025-07-01
### Breaking Changes
- G.U.I.D.E will now preserve state of triggers when switching mapping contexts. In addition, triggers that become active as a result of a context being activated, will be initialized with the current input. This will avoid issue with triggers stopping to trigger or triggering too often when switching mapping contexts. This fixes some issues introduced with 0.6.0. Since this changes the behaviour of triggers, I declare this a breaking change. Please check your triggers after updating to ensure they still work as expected ([#81](https://github.com/godotneers/G.U.I.D.E/issues/81)).

## [0.6.4] - 2025-06-14
### Added
- Added support for the PS5 touchpad to the icon renderer and text provider, so this will now properly display in input prompts ([#74](https://github.com/godotneers/G.U.I.D.E/issues/74)).

### Fixed
- When pressing keys or buttons so rapidly that both the press and release happen to occur in the same frame, G.U.I.D.E would ignore the press event. This has now been fixed. So if a key or button changes state multiple times in a frame, the result of the first state change is used for evaluation this frame. At the end of the frame, the last state, which was recorded in the frame, is restored. This will technically still drop events (e.g. if a button state changes five times in a frame, only the first and last state change will influence triggers) however for all practical purposes this should be good enough. ([#77](https://github.com/godotneers/G.U.I.D.E/issues/77)).

## [0.6.3] - 2025-05-20
### Added
- Added a new example showing how to use controller or keyboard & mouse for a top-down shooter ([#64](https://github.com/godotneers/G.U.I.D.E/issues/64)).

### Improved
- The mapping editor now shows the action value type next to the action name. This helps debugging unexpected behaviour when using an unsuitable action value type for an action. A big thanks goes to [Jose Ramon Rodriguez](https://github.com/jramonrod) for submitting a PR for this ([#59](https://github.com/godotneers/G.U.I.D.E/issues/59), [#63](https://github.com/godotneers/G.U.I.D.E/pull/63))!


### Fixed
- When detecting input for re-binding the `GUIDEInputDetector` will ensure that G.U.I.D.E's input state still receives events. This avoids issues where the player re-binds a key and this key will not work correctly afterward, because G.U.I.D.E's input state was not updated and now has diverged from the actual input state.
- G.U.I.D.E will now ignore input mappings with a missing action. A missing action will be shown as a warning in the mapping context editor and at runtime ([#66](https://github.com/godotneers/G.U.I.D.E/issues/66)).
- The icons for the mouse side buttons now properly reflect the physical position of these buttons. If you still get the wrong icons, please delete the `_guide_cache` folder in your user data folder. This will recreate the icons. You can open your user data folder by going to _Project_ > _Open User Data Folder_ in the Godot editor ([#65](https://github.com/godotneers/G.U.I.D.E/issues/65)).

## [0.6.2] - 2025-05-05
### Improved
- The `GUIDEInputDetector` now consumes all input events while it is detecting input. This avoids the problem of input accidentally triggering something else (e.g. the Godot UI) while the input is being detected.

### Fixed
- The input detector no longer shows errors when the detection is started again from outside code while it is already running.


## [0.6.1] - 2025-05-04
### Fixed
- The plugin version inside Godot is now properly updated.
- The plugin now ships with UID files for Godot 4.4. These files have no effect on earlier Godot versions ([#60](https://github.com/godotneers/G.U.I.D.E/issues/60)).

## [0.6.0] - 2025-05-02
### Breaking Changes
- The input collection system has received a major overhaul. G.U.I.D.E now uses a centralized input state from which all built-in `GUIDEInput` get updates. This makes the whole input collection a lot more efficient. Before each input event would be sent to each currently active `GUIDEInput`. Now the input is sent to a single collector which notifies each `GUIDEInput` about events that they have subscribed to. This significantly reduces the amount of work that needs to be done for each processed input. In addition to that, it allows for efficient querying of the current input state, so inputs like `GUIDEInputKey` can now work with a lot less calls into the engine. Another benefit is that input state is kept in a central place even when `GUIDEInput`s are deactivated. This allows a smooth change of mapping contexts without losing the current input state. Finally, this is some groundwork required for virtual joysticks which will be added in a future version.
- `GUIDEInput` no longer have an `_input` method as raw input is now handled in `GUIDEInputState`. Instead `GUIDEInput` now subscribes to signals in `GUIDEInputState`. If you have written your own `GUIDEInput`, this will affect you. Check the [documentation](https://godotneers.github.io/G.U.I.D.E/usage/extending-guide#creating-custom-inputs) for more information on how custom inputs now work. 
- Input is now no longer reset when mapping contexts are swapped out. So if you have two mapping contexts both listening for the key `W` to be pressed down, and you switch from one to the other while the key is pressed down, then the input previously would reset and the player would have to release and press the `W` key again for it to be detected. This is especially annoying in games where you have to hold a key to move or perform an action. Now the input will be kept active and the player can continue to use it without having to press the key again. Since this changes the behaviour of how input is reacting, I declare this a breaking change. If you have mapping contexts which share the same input, carefully check if things still work as intended. You may need to change trigger types (e.g. from _Pressed_ to _Released_) to prevent unwanted input ([#61](https://github.com/godotneers/G.U.I.D.E/issues/61)).

### Improved
- `GUIDEInputDetector` now automatically disables all mapping contexts when detecting input and restores them afterwards. This avoids accidentally triggering actions while detecting input and until now needed to be done manually. 
- The LICENSE file is now part of the packaged add-on. A big thanks goes to [Simply BLG](https://github.com/SimplyBLGDev) for submitting a PR for this!
- The test suite has received a good amount of work. It is still not where it could be, but a nice improvement over the previous version. 

## [0.5.3] - 2025-04-25
### Fixed
- The _Any_ input now properly actuates, if more than one watched input source actuates during the frame in any order ([#57](https://github.com/godotneers/G.U.I.D.E/issues/57)).

## [0.5.2] - 2025-04-14
### Fixed
- The _Remap range_ modifier now properly works when the output range is descending and clamp is enabled. Previously this would always return the left end of the output range ([#53](https://github.com/godotneers/G.U.I.D.E/issues/53)). 

## [0.5.1] - 2025-04-07
### Improved
- `GUIDEInputAny` now has settings to determine minimal mouse and joypad axis motion to be considered as input. This is useful to avoid accidental input when the mouse or joypad only moved slightly ([#26](https://github.com/godotneers/G.U.I.D.E/issues/26), [#52](https://github.com/godotneers/G.U.I.D.E/issues/52)). 

## [0.5.0] - 2025-04-01
### Breaking Change
- The `GUIDEInputDetector` now detects controller trigger buttons when looking for `BOOLEAN` input. Before it would only do this when detecting `AXIS_1D` input. Since triggers are very often used for boolean input, this behaviour was changed to keep it more in line with player expectations. If you want to keep the old behaviour, you can set the `allow_triggers_for_boolean_actions` property of `GUIDEInputDetector` to `false`. 

### Added
- `GUIDEAction` now has a new `elapsed_ratio` property which can be used to drive hold progress bars. When the mapping context is activated G.U.I.D.E will check if the action has any hold trigger bound to it and provide some information for an `elapsed_ratio` property on the action to update.  This `elapsed_ratio` will go from 0 to 1 as the hold time elapses and stay at 1 while the action is triggered. If the action has no hold trigger, then `elapsed_ratio` will stay at 0 while the action is not triggered, and go to 1 when the action is triggered ([#48](https://github.com/godotneers/G.U.I.D.E/issues/48)). 

### Fixed
- Removed a font file that was unnecessarily embedded into the mapping context editor scene, bloating its file size ([#49](https://github.com/godotneers/G.U.I.D.E/issues/49)).


## [0.4.2] - 2025-03-25
### Fixed
- G.U.I.D.E now properly detects the PlayStation DualSense controller range as PlayStation controller. A big thanks goes to [laternRaft](https://github.com/laternRaft) for submitting a PR for this and helping with testing ([#43](https://github.com/godotneers/G.U.I.D.E/pull/43)).

## [0.4.1] - 2025-03-13
### Fixed
- Binding a modifier key as the key input (e.g. shift for running) will now work even if "allow additional modifiers" is set to false ([#34](https://github.com/godotneers/G.U.I.D.E/issues/34)).

## [0.4.0] - 2025-03-06
### Breaking Changes
- Removed `get_display_categories` and `get_remappable_actions` from `GUIDEMappingContext`. These methods were added before `GUIDERemapper` was introduced and are now obsolete. If you used these methods, switch to [using `GUIDERemapper` instead](https://godotneers.github.io/G.U.I.D.E/usage/remapping-input) ([#23](https://github.com/godotneers/G.U.I.D.E/issues/23)).

### Improved
- It is now possible to share both modifiers and triggers between multiple mappings to ensure that all mappings use the same settings. It is also possible to quickly copy a modifier or trigger from one mapping to another with drag & drop ([#31](https://github.com/godotneers/G.U.I.D.E/issues/31)).

### Fixed
- Cleaned up duplicate UIDs to prevent issues with Godot 4.4. ([#28](https://github.com/godotneers/G.U.I.D.E/issues/28)).



## [0.3.1] - 2025-02-14
### Breaking Changes
- G.U.I.D.E will now continue to process input when the tree is in pause mode. Also, the debugger and all icon rendering facilities will continue to work even when the tree is paused. Technically, this should have been the behaviour from the beginning because games need to remain controllable even when paused. Since the behaviour was changed, I'm declaring this a breaking change. Please check if your game still works as expected in pause mode. If you need to disable input when the game is paused, consider calling `GUIDE.disable_mapping_context()` or add specific checks to your game code to prevent actions while the game is paused ([#20](https://github.com/godotneers/G.U.I.D.E/issues/20)).


## [0.3.0] - 2025-02-10
### Breaking Changes
- `GUIDEModifierVirtualCursor` now tracks input as pixels rather than a virtual resolution independent value. This avoids the problem that the cursor movement speed is different for the x and y axes. The new implementation keeps a consistent speed on both axes. To achieve resolution independence, the modifier now has a separate setting which controls the screen scaling. Please check the [documentation](https://godotneers.github.io/G.U.I.D.E/reference/modifiers#virtual-cursor-experimental) for more information. Settings of existing projects will be migrated to the closest equivalent settings. Since the behaviour was changed, I declare this a breaking change. Please check your settings after updating and verify that the cursor behaves as expected ([#15](https://github.com/godotneers/G.U.I.D.E/issues/15)).

### Fixed
- Calling `cleanup` on `GUIDEInputFormatter` will no longer make the instance unusable. Usually it should not be necessary to call `cleanup` manually, but if you do, the formatter will make sure to recreate the necessary nodes when needed.

### Improved
- Further work on the test suite has been done. This is nowhere near complete, but it is a start. 

## [0.2.0] - 2025-01-30 
### Added
- It is now possible to override the action name and category for each input mapping, making it easier to remap actions that are mapped to multiple inputs (e.g. WASD for movement) ([#12](https://github.com/godotneers/G.U.I.D.E/issues/12)).
- `GUIDEInputFormatter` has a new method `cleanup` which allows tearing down the icon rendering infrastructure. This is mainly useful for automated tests, to avoid spurious records of orphan nodes ([#13](https://github.com/godotneers/G.U.I.D.E/issues/13)).

### Improved
- Icons are now set to scale with the editor scale, so they no longer should be too small on high resolution displays.
- The debugger will no longer update the UI when it is not visible. 

### Fixed
- The icon rendering infrastructure is now properly cleaned up when disabling the plugin.

## [0.1.3] - 2025-01-19
### Improved
- The debugger now shows the action priorities which are derived from analyzing overlapping input. This can help find problems in the action mapping and also gives a bit more information about what G.U.I.D.E does internally.

### Fixed
- Chains of chorded actions are now properly handled when calculating action priority from overlapping input ([#9](https://github.com/godotneers/G.U.I.D.E/issues/9))
- The plugin will now only register/unregister the `GUIDE` singleton when being enabled and disabled. This will avoid marking the project as modified just by loading it ([#11](https://github.com/godotneers/G.U.I.D.E/issues/11)).
- A few small bugs in the examples have been fixed.

## [0.1.2] - 2025-01-11
### Breaking Changes
- `GUIDEInputKey` now properly handles modifier keys (like shift, control, etc.). Until now, the handling of additional modifier keys had a bug that allowed you to press the key with a modifier even though _Allow additional modifiers_ was turned off. This has been fixed. However the more common use case is to ignore additional modifiers, so _Allow additional modifiers_ is now `true` by default. G.U.I.D.E cannot reliably migrate this new default for existing bindings, so if you want your existing key bindings to allow additional modifiers, you need to manually enable it for these. All new bindings will allow additional modifiers by default and you can disable this if you don't want it. 

### Improved
- The documentation of `GUIDEInputKey` has been updated to reflect the changes and add missing information about the modifier keys.

### Fixed
- `GUIDEInputKey` would not properly detect a key release if it was done in a certain sequence with modifier keys ([#7](https://github.com/godotneers/G.U.I.D.E/issues/7)). 

## [0.1.1] - 2025-01-10
### Added
- The _Any_ input now supports additional input types (mouse movement, joy axes and touch).

## [0.1.0] - 2025-01-09 
### Breaking Changes
- The `input_detected` signal of `GUIDEInputDetector` had a typo in it (was `input_dectected`) and was renamed to fix this. If your code uses this signal you will need to update it. Also check your scenes if you connected this signal using the editor.

### Added
- Support for touch input:
	- _Touch Position_  - will track the position of one or more fingers, similar to _Mouse Position_
	- _Touch Axis2D_ - will track the position change of one or more fingers, similar to _Mouse Axis2D_
	- _Touch Axis1D_ - similar to _Touch Axis2D_ but tracks a single axis, only.
	- _Touch Distance_ - tracks distance changes between two fingers. Useful for implementing pinch/zoom gestures.
	- _Touch Angle_ - tracks rotation changes between two fingers. Useful for implementing rotation gestures.
- New trigger type _Stability_ which triggers depending on whether the input has changed after initial actuatation. Useful for touch input to detect taps and drags.
- A new `touch` example has been added, showing how to use the new touch features to implement camera drags, pinch/zoom and rotation.
- New modifier _Normalize_ to normalize an input vector.

### Improved
- `GUIDEInputDetector` can now filter for device types, so you can limit detected input to keyboard, mouse or joystick/gamepad input.
- `GUIDEInputDetector` now has a `is_detecting` property to find out whether it is currently detecting input.
- `GUIDEInputDetector` now has a setting determining which joy index should be assigned to detected joy events.
- `GUIDERemapper` can now also filter for single actions, so it is easier to remap input for a specific action.
- The _Canvas Coordinates_ modifier can now also convert relative pixel coordinates into relative world coordinates.
- The `remapping` example's usability for controllers has been improved, showing some techniques on how to make UI more controller friendly.

### Fixed
- Triggers will no longer consider infinite input values as "actuating". Vector.INF is reserved for cases where no value is available.
- Modifiers now handle infinite input values more gracefully instead of producing `NaN` values.
- The text provider will no longer try to translate physical keys to labels on mobile platforms where Godot doesn't support this.
- Inputs of type `GUIDEInputAction` are now properly displayed in the debugger.

## [0.0.4] - 2024-12-28
### Fixed
- Fixed broken equality comparison on `GUIDEInputAny` ([#3](https://github.com/godotneers/G.U.I.D.E/issues/3)).

## [0.0.3] - 2024-12-21
### Added
- New trigger type _Released_ which triggers when the input is released (the opposite of _Pressed_).
- New modifier _Virtual Cursor_ which provides a virtual mouse cursor that can be controlled by any input (experimental).

### Changed
- In the debugger, inputs now show the raw Vector3 coming from the input. This helps understanding modifiers better as we can see the value that is going into the modifier.

### Fixed
- Added missing equality comparison for `GUIDEInputAny` and `GUIDEInputMousePosition` so these inputs are not needlessly duplicated and updated multiple times per frame.
- Triggers do no longer reset the action value to zero when they don't fire. They are intended to be orthogonal to the action values, so they should react to changes of the value, rather than modify it (for that we have modifiers).
- Fixed several smaller rendering problems with rendering items (e.g. broken direction indicator for Xbox controllers and joysticks, right trigger being shown as left trigger, etc.). To clear cached icons, go to _Project_ > _Open user data folder_  and in this folder delete the `_guide_cache` folder. This will recreate icons. 
- Fixed size of the icons which should be 16x16 not 32x32 ([#2](https://github.com/godotneers/G.U.I.D.E/issues/2)).

## [0.0.2] - 2024-12-02
### Breaking Changes
- Removed the leftover`get_value_axis_xxx` methods from the `GUIDEAction` class. Use the `value_axis_xxx` property instead.
- `GUIDEDebugger` is no longer a public node class because it cannot work as a standalone node. Use the provided `guide_debugger.tscn` scene to add a debugger to your project.
### Added
- `GUIDEAction` now has additional functions to check whether it is currently in `Completed` or `Ongoing` state.
- Added two new modifiers: _Curve_ which allows to apply a curve to the input value and _Map range_ which allows to map the input value to a different range. A huge thanks goes to [Regal Media](https://github.com/RegalMedia) for submitting a PR with this feature!
### Improved
- The `input_mappings_changed` signal in `GUIDE` now also fires when any joystick is connected or disconnected.


## [0.0.1] - 2024-11-17
- Initial release of the plugin.


================================================
FILE: CONTRIBUTING.md
================================================
# Contribution guide

First off, thanks for considering a contribution to this project!

The following checklist will help you to get started and make sure your contribution can be merged as quickly as possible:

- Before you start working on a feature or fix, **please create an [issue](https://github.com/godotneers/G.U.I.D.E/issues/new) first**. This way we can discuss the implementation and any potential side effects before you spend time on it. It's no fun to spend hours developing something and then have your PR rejected because it doesn't fit the project goals or because it breaks something else.
- In your PR please make sure you **only change the files that are necessary** for your fix or feature. Changes to unrelated files make it harder to review and merge your PR.
- If you have multiple fixes or features, please **create a separate PR for each**. This makes it easier to review and merge them, and problems with one fix/feature will not block the other fixes/features from being merged.
- Please make sure your code is **formatted according to the [GDScript style guide](https://docs.godotengine.org/en/stable/getting_started/scripting/gdscript/gdscript_styleguide.html)**. It may not be your preferred style, but we really don't want to have multiple styles mixed in the codebase.
- Please **rebase your PR on the latest on the `main`** branch before submitting it. This makes it easier to compare the changes and avoids merge conflicts. 
- Your contribution must be **licensed under the MIT license**. This is the same license as this project uses. See the [LICENSE](LICENSE) file for details.




================================================
FILE: LICENSE.md
================================================
Copyright (c) 2024-present Jan Thomä

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# G.U.I.D.E - Godot Unified Input Detection Engine

G.U.I.D.E is an extension for the Godot Engine that allows you to easily use input from multiple sources, such as keyboard, mouse, gamepad and touch in a unified way. Gone are the days, where mouse input was handled differently from joysticks and touch was a totally different beast. No matter where the input comes from - your game code works the same way.

_Note: While the features work pretty well, this plugin hasn't seen a lot of use yet, so be prepared for a few rough edges. Also the documentation still needs expansion. Please report any issues you encounter._

## Features

- Unified input detection and handling from multiple sources (keyboard, mouse, gamepad, touch, etc.). All inputs are used in the same way in your game code.
- Inputs can be modified before being fed into your game code (e.g. for joystick dead-zones, sensitivity, inversion, conversion to 2D/3D coordinates, etc.).
- Inputs can be assigned to actions and these actions trigger on various conditions (e.g. tap, hold, press, release, combos etc.).
- Multiple input contexts can be defined, which can be enabled/disabled at runtime. This allows you to easily switch between different input schemes (e.g. in-game, menu, driving, flying, walking, etc.).
- Overlapping input is automatically prioritized, such that input like _LT+A_ will have precedence over just  _A_.
- Supports both event-based and polling-based input handling, like Godot's built-in input system.
- Full support for input rebinding at runtime including collision handling. 
- Built-in support for displaying input prompts in your game. These prompts support complex input combinations (e.g. _LT+A_ or combos like _A > B > A > X > Y_). Prompts can be displayed both as text and as icons. Icons will automatically reflect the actual input device being used (e.g. XBox controller, Playstation controller, keyboard, joystick, etc.).
- Works nicely alongside Godot's built-in input system, so you can use both in parallel if needed. Can also inject action events into Godot's input system.


## Documentation

The documentation is availabe on the [documentation site](https://godotneers.github.io/G.U.I.D.E/).


## Acknowledgements / Licenses

The input prompts use the great icons made by Nicolae (Xelu) Berbece (https://thoseawesomeguys.com/prompts/) under CC0 License.


================================================
FILE: TODO.md
================================================
# To Do

This lists the currently open to do items in no particular order.

## Open
- [ ] The stick renderer throws errors about a signal being connected twice. Fix that.
- [ ] Add a C# API.
 
## Done
- [x] Virtual stick device change mid-game support.
- [x] Prepare for asset library (git attributes, page, etc.)
- [x] Icon for "Mouse Position" input.
- [x] document all possible inputs and how they map to action values
- [x] Add icon/text renderers for PS/XBOX/Nintendo controllers
- [x] Make the fallback icons less ugly.
- [x] Add functionality for runtime re-binding.
- [x] Fix icon/text for Any input
- [x] Fix remapping of WASD to ESDF
- [x] Implement input consumption and action prioritization.
- [x] Fix "incomplete format" error popping up when rendering an input icon.
- [x] Implement elapsed/triggered time.
- [x] Make an editor for setting up the system. The inspector is atrocious.
- [x] Decide whether to convert into C++ after the prototyping phase is done (decided against it, GDScript is fast enough, easier to maintain and works on all platforms out of the box).
- [x] Remove get_action_value_xxx from Action (replaced by value_xxx property)
- [x] Documentation
    - [x] document customizing the input prompt rendering
    - [x] document input remapping


================================================
FILE: _assets/.gdignore
================================================


================================================
FILE: addons/gdUnit4/GdUnitRunner.cfg
================================================
{"included":{"res://tests/test_layered_contexts.gd":[]},"server_port":31002,"skipped":{},"version":"1.0"}

================================================
FILE: addons/gdUnit4/LICENSE
================================================
MIT License

Copyright (c) 2023 Mike Schulze

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: addons/gdUnit4/bin/GdUnitBuildTool.gd
================================================
#!/usr/bin/env -S godot -s
extends SceneTree

enum {
	INIT,
	PROCESSING,
	EXIT
}

const RETURN_SUCCESS  =   0
const RETURN_ERROR    = 100
const RETURN_WARNING  = 101

var _console := CmdConsole.new()
var _cmd_options: = CmdOptions.new([
	CmdOption.new(
		"-scp, --src_class_path",
		"-scp <source_path>",
		"The full class path of the source file.",
		TYPE_STRING
	),
	CmdOption.new(
		"-scl, --src_class_line",
		"-scl <line_number>",
		"The selected line number to generate test case.",
		TYPE_INT
	)
])

var _status := INIT
var _source_file :String = ""
var _source_line :int = -1


func _init() -> void:
	var cmd_parser := CmdArgumentParser.new(_cmd_options, "GdUnitBuildTool.gd")
	var result := cmd_parser.parse(OS.get_cmdline_args())
	if result.is_error():
		show_options()
		exit(RETURN_ERROR, result.error_message());
		return

	var cmd_options :Array[CmdCommand] = result.value()
	for cmd in cmd_options:
		if cmd.name() == '-scp':
			_source_file = cmd.arguments()[0]
			_source_file = ProjectSettings.localize_path(ProjectSettings.localize_path(_source_file))
		if cmd.name() == '-scl':
			_source_line = int(cmd.arguments()[0])
	# verify required arguments
	if _source_file == "":
		exit(RETURN_ERROR, "missing required argument -scp <source>")
		return
	if _source_line == -1:
		exit(RETURN_ERROR, "missing required argument -scl <number>")
		return
	_status = PROCESSING


func _idle(_delta :float) -> void:
	if _status == PROCESSING:
		var script := ResourceLoader.load(_source_file) as Script
		if script == null:
			exit(RETURN_ERROR, "Can't load source file %s!" % _source_file)
		var result := GdUnitTestSuiteBuilder.create(script, _source_line)
		if result.is_error():
			print_json_error(result.error_message())
			exit(RETURN_ERROR, result.error_message())
			return
		_console.prints_color("Added testcase: %s" % result.value(), Color.CORNFLOWER_BLUE)
		print_json_result(result.value() as Dictionary)
		exit(RETURN_SUCCESS)


func exit(code :int, message :String = "") -> void:
	_status = EXIT
	if code == RETURN_ERROR:
		if not message.is_empty():
			_console.prints_error(message)
		_console.prints_error("Abnormal exit with %d" % code)
	else:
		_console.prints_color("Exit code: %d" % RETURN_SUCCESS, Color.DARK_SALMON)
	quit(code)


func print_json_result(result :Dictionary) -> void:
	# convert back to system path
	var path := ProjectSettings.globalize_path(result["path"] as String)
	var json := 'JSON_RESULT:{"TestCases" : [{"line":%d, "path": "%s"}]}' % [result["line"], path]
	prints(json)


func print_json_error(error :String) -> void:
	prints('JSON_RESULT:{"Error" : "%s"}' % error)


func show_options() -> void:
	_console.prints_color(" Usage:", Color.DARK_SALMON)
	_console.prints_color("	build -scp <source_path> -scl <line_number>", Color.DARK_SALMON)
	_console.prints_color("-- Options ---------------------------------------------------------------------------------------",
		Color.DARK_SALMON).new_line()
	for option in _cmd_options.default_options():
		descripe_option(option)


func descripe_option(cmd_option :CmdOption) -> void:
	_console.print_color("  %-40s" % str(cmd_option.commands()), Color.CORNFLOWER_BLUE)
	_console.prints_color(cmd_option.description(), Color.LIGHT_GREEN)
	if not cmd_option.help().is_empty():
		_console.prints_color("%-4s %s" % ["", cmd_option.help()], Color.DARK_TURQUOISE)
	_console.new_line()


================================================
FILE: addons/gdUnit4/bin/GdUnitBuildTool.gd.uid
================================================
uid://vidr4ejcbkss


================================================
FILE: addons/gdUnit4/bin/GdUnitCmdTool.gd
================================================
#!/usr/bin/env -S godot -s
extends SceneTree

const GdUnitTools := preload("res://addons/gdUnit4/src/core/GdUnitTools.gd")


#warning-ignore-all:return_value_discarded
class CLIRunner:
	extends Node

	enum {
		READY,
		INIT,
		RUN,
		STOP,
		EXIT
	}

	const DEFAULT_REPORT_COUNT = 20
	const RETURN_SUCCESS = 0
	const RETURN_ERROR = 100
	const RETURN_ERROR_HEADLESS_NOT_SUPPORTED = 103
	const RETURN_ERROR_GODOT_VERSION_NOT_SUPPORTED = 104
	const RETURN_WARNING = 101

	var _state := READY
	var _test_suites_to_process: Array
	var _executor :Variant
	var _cs_executor :Variant
	var _report: GdUnitHtmlReport
	var _report_dir: String
	var _report_max: int = DEFAULT_REPORT_COUNT
	var _headless_mode_ignore := false
	var _runner_config := GdUnitRunnerConfig.new()
	var _runner_config_file := ""
	var _debug_cmd_args: = PackedStringArray()
	var _console := CmdConsole.new()
	var _cmd_options := CmdOptions.new([
			CmdOption.new(
				"-a, --add",
				"-a <directory|path of testsuite>",
				"Adds the given test suite or directory to the execution pipeline.",
				TYPE_STRING
			),
			CmdOption.new(
				"-i, --ignore",
				"-i <testsuite_name|testsuite_name:test-name>",
				"Adds the given test suite or test case to the ignore list.",
				TYPE_STRING
			),
			CmdOption.new(
					"-c, --continue",
					"",
					"""By default GdUnit will abort checked first test failure to be fail fast,
					instead of stop after first failure you can use this option to run the complete test set.""".dedent()
			),
			CmdOption.new(
				"-conf, --config",
				"-conf [testconfiguration.cfg]",
				"Run all tests by given test configuration. Default is 'GdUnitRunner.cfg'",
				TYPE_STRING,
				true
			),
			CmdOption.new(
				"-help", "",
				"Shows this help message."
			),
			CmdOption.new("--help-advanced", "",
				"Shows advanced options."
			)
		],
		[
			# advanced options
			CmdOption.new(
				"-rd, --report-directory",
				"-rd <directory>",
				"Specifies the output directory in which the reports are to be written. The default is res://reports/.",
				TYPE_STRING,
				true
			),
			CmdOption.new(
				"-rc, --report-count",
				"-rc <count>",
				"Specifies how many reports are saved before they are deleted. The default is %s." % str(DEFAULT_REPORT_COUNT),
				TYPE_INT,
				true
			),
			#CmdOption.new("--list-suites", "--list-suites [directory]", "Lists all test suites located in the given directory.", TYPE_STRING),
			#CmdOption.new("--describe-suite", "--describe-suite <suite name>", "Shows the description of selected test suite.", TYPE_STRING),
			CmdOption.new(
				"--info", "",
				"Shows the GdUnit version info"
			),
			CmdOption.new(
				"--selftest", "",
				"Runs the GdUnit self test"
			),
			CmdOption.new(
				"--ignoreHeadlessMode",
				"--ignoreHeadlessMode",
				"By default, running GdUnit4 in headless mode is not allowed. You can switch off the headless mode check by set this property."
			),
		])


	func _ready() -> void:
		_state = INIT
		_report_dir = GdUnitFileAccess.current_dir() + "reports"
		_executor = GdUnitTestSuiteExecutor.new()
		# stop checked first test failure to fail fast
		@warning_ignore("unsafe_cast")
		(_executor as GdUnitTestSuiteExecutor).fail_fast(true)
		if GdUnit4CSharpApiLoader.is_mono_supported():
			prints("GdUnit4Net version '%s' loaded." % GdUnit4CSharpApiLoader.version())
			_cs_executor = GdUnit4CSharpApiLoader.create_executor(self)
		var err := GdUnitSignals.instance().gdunit_event.connect(_on_gdunit_event)
		if err != OK:
			prints("gdUnitSignals failed")
			push_error("Error checked startup, can't connect executor for 'send_event'")
			quit(RETURN_ERROR)


	func _notification(what: int) -> void:
		if what == NOTIFICATION_PREDELETE:
			prints("Finallize .. done")


	@warning_ignore("unsafe_method_access")
	func _process(_delta :float) -> void:
		match _state:
			INIT:
				init_gd_unit()
				_state = RUN
			RUN:
				# all test suites executed
				if _test_suites_to_process.is_empty():
					_state = STOP
				else:
					set_process(false)
					# process next test suite
					var test_suite: Node = _test_suites_to_process.pop_front()

					if _cs_executor != null and _cs_executor.IsExecutable(test_suite):
						_cs_executor.Execute(test_suite)
						await _cs_executor.ExecutionCompleted
					else:
						await _executor.execute(test_suite)
					set_process(true)
			STOP:
				_state = EXIT
				_on_gdunit_event(GdUnitStop.new())
				quit(report_exit_code(_report))


	func quit(code: int) -> void:
		_cs_executor = null
		GdUnitTools.dispose_all()
		await GdUnitMemoryObserver.gc_on_guarded_instances()
		await get_tree().physics_frame
		get_tree().quit(code)


	func set_report_dir(path: String) -> void:
		_report_dir = ProjectSettings.globalize_path(GdUnitFileAccess.make_qualified_path(path))
		_console.prints_color(
			"Set write reports to %s" % _report_dir,
			Color.DEEP_SKY_BLUE
		)


	func set_report_count(count: String) -> void:
		var report_count := count.to_int()
		if report_count < 1:
			_console.prints_error(
				"Invalid report history count '%s' set back to default %d"
				% [count, DEFAULT_REPORT_COUNT]
			)
			_report_max = DEFAULT_REPORT_COUNT
		else:
			_console.prints_color(
				"Set report history count to %s" % count,
				Color.DEEP_SKY_BLUE
			)
			_report_max = report_count


	func disable_fail_fast() -> void:
		_console.prints_color(
			"Disabled fail fast!",
			Color.DEEP_SKY_BLUE
		)
		@warning_ignore("unsafe_method_access")
		_executor.fail_fast(false)


	func run_self_test() -> void:
		_console.prints_color(
			"Run GdUnit4 self tests.",
			Color.DEEP_SKY_BLUE
		)
		disable_fail_fast()
		_runner_config.self_test()


	func show_version() -> void:
		_console.prints_color(
			"Godot %s" % Engine.get_version_info().get("string") as String,
			Color.DARK_SALMON
		)
		var config := ConfigFile.new()
		config.load("addons/gdUnit4/plugin.cfg")
		_console.prints_color(
			"GdUnit4 %s" % config.get_value("plugin", "version") as String,
			Color.DARK_SALMON
		)
		quit(RETURN_SUCCESS)


	func check_headless_mode() -> void:
		_headless_mode_ignore = true


	func show_options(show_advanced: bool = false) -> void:
		_console.prints_color(
			"""
			Usage:
				runtest -a <directory|path of testsuite>
				runtest -a <directory> -i <path of testsuite|testsuite_name|testsuite_name:test_name>
				""".dedent(),
			Color.DARK_SALMON
		).prints_color(
			"-- Options ---------------------------------------------------------------------------------------",
			Color.DARK_SALMON
		).new_line()
		for option in _cmd_options.default_options():
			descripe_option(option)
		if show_advanced:
			_console.prints_color(
				"-- Advanced options --------------------------------------------------------------------------",
				Color.DARK_SALMON
			).new_line()
			for option in _cmd_options.advanced_options():
				descripe_option(option)


	func descripe_option(cmd_option: CmdOption) -> void:
		_console.print_color(
			"  %-40s" % str(cmd_option.commands()),
			Color.CORNFLOWER_BLUE
		)
		_console.prints_color(
			cmd_option.description(),
			Color.LIGHT_GREEN
		)
		if not cmd_option.help().is_empty():
			_console.prints_color(
				"%-4s %s" % ["", cmd_option.help()],
				Color.DARK_TURQUOISE
			)
		_console.new_line()


	func load_test_config(path := GdUnitRunnerConfig.CONFIG_FILE) -> void:
		_console.print_color(
			"Loading test configuration %s\n" % path,
			Color.CORNFLOWER_BLUE
		)
		_runner_config_file = path
		_runner_config.load_config(path)


	func show_help() -> void:
		show_options()
		quit(RETURN_SUCCESS)


	func show_advanced_help() -> void:
		show_options(true)
		quit(RETURN_SUCCESS)


	func get_cmdline_args() -> PackedStringArray:
		if _debug_cmd_args.is_empty():
			return OS.get_cmdline_args()
		return _debug_cmd_args


	func init_gd_unit() -> void:
		_console.prints_color(
			"""
			--------------------------------------------------------------------------------------------------
			GdUnit4 Comandline Tool
			--------------------------------------------------------------------------------------------------""".dedent(),
			Color.DARK_SALMON
		).new_line()

		var cmd_parser := CmdArgumentParser.new(_cmd_options, "GdUnitCmdTool.gd")
		var result := cmd_parser.parse(get_cmdline_args())
		if result.is_error():
			show_options()
			_console.prints_error(result.error_message())
			_console.prints_error("Abnormal exit with %d" % RETURN_ERROR)
			_state = STOP
			quit(RETURN_ERROR)
			return
		if result.is_empty():
			show_help()
			return
		# build runner config by given commands
		var commands :Array[CmdCommand] = []
		@warning_ignore("unsafe_cast")
		commands.append_array(result.value() as Array)
		result = (
			CmdCommandHandler.new(_cmd_options)
				.register_cb("-help", show_help)
				.register_cb("--help-advanced", show_advanced_help)
				.register_cb("-a", _runner_config.add_test_suite)
				.register_cbv("-a", _runner_config.add_test_suites)
				.register_cb("-i", _runner_config.skip_test_suite)
				.register_cbv("-i", _runner_config.skip_test_suites)
				.register_cb("-rd", set_report_dir)
				.register_cb("-rc", set_report_count)
				.register_cb("--selftest", run_self_test)
				.register_cb("-c", disable_fail_fast)
				.register_cb("-conf", load_test_config)
				.register_cb("--info", show_version)
				.register_cb("--ignoreHeadlessMode", check_headless_mode)
				.execute(commands)
		)
		if result.is_error():
			_console.prints_error(result.error_message())
			_state = STOP
			quit(RETURN_ERROR)

		if DisplayServer.get_name() == "headless":
			if _headless_mode_ignore:
				_console.prints_warning("""
					Headless mode is ignored by option '--ignoreHeadlessMode'"

					Please note that tests that use UI interaction do not work correctly in headless mode.
					Godot 'InputEvents' are not transported by the Godot engine in headless mode and therefore
					have no effect in the test!
					""".dedent()
				).new_line()
			else:
				_console.prints_error("""
					Headless mode is not supported!

					Please note that tests that use UI interaction do not work correctly in headless mode.
					Godot 'InputEvents' are not transported by the Godot engine in headless mode and therefore
					have no effect in the test!

					You can run with '--ignoreHeadlessMode' to swtich off this check.
					""".dedent()
				).prints_error(
					"Abnormal exit with %d" % RETURN_ERROR_HEADLESS_NOT_SUPPORTED
				)
				quit(RETURN_ERROR_HEADLESS_NOT_SUPPORTED)
				return

		_test_suites_to_process = load_testsuites(_runner_config)
		if _test_suites_to_process.is_empty():
			_console.prints_warning("No test suites found, abort test run!")
			_console.prints_color("Exit code: %d" % RETURN_SUCCESS, Color.DARK_SALMON)
			_state = STOP
			quit(RETURN_SUCCESS)
		var total_test_count := _collect_test_case_count(_test_suites_to_process)
		_on_gdunit_event(GdUnitInit.new(_test_suites_to_process.size(), total_test_count))


	func load_testsuites(config: GdUnitRunnerConfig) -> Array[Node]:
		var test_suites_to_process: Array[Node] = []
		# Dictionary[String, Dictionary[String, PackedStringArray]]
		var to_execute := config.to_execute()
		# scan for the requested test suites
		var ts_scanner := GdUnitTestSuiteScanner.new()
		for as_resource_path in to_execute.keys() as Array[String]:
			var selected_tests: PackedStringArray = to_execute.get(as_resource_path)
			var scanned_suites := ts_scanner.scan(as_resource_path)
			skip_test_case(scanned_suites, selected_tests)
			test_suites_to_process.append_array(scanned_suites)
		skip_suites(test_suites_to_process, config)
		return test_suites_to_process


	func skip_test_case(test_suites: Array[Node], test_case_names: Array[String]) -> void:
		if test_case_names.is_empty():
			return
		for test_suite in test_suites:
			for test_case in test_suite.get_children():
				if not test_case_names.has(test_case.get_name()):
					test_suite.remove_child(test_case)
					test_case.free()


	func skip_suites(test_suites: Array[Node], config: GdUnitRunnerConfig) -> void:
		var skipped := config.skipped()
		if skipped.is_empty():
			return

		for test_suite in test_suites:
			# skipp c# testsuites for now
			if test_suite.get_script() == null:
				continue
			skip_suite(test_suite, skipped)


	# Dictionary[String, PackedStringArray]
	func skip_suite(test_suite: Node, skipped: Dictionary) -> void:
		var skipped_suites :Array = skipped.keys()
		var suite_name := test_suite.get_name()
		var test_suite_path: String = (
			test_suite.get_meta("ResourcePath") if test_suite.get_script() == null
			else test_suite.get_script().resource_path
		)
		for suite_to_skip: String in skipped_suites:
			# if suite skipped by path or name
			if (
				suite_to_skip == test_suite_path
				or (suite_to_skip.is_valid_filename() and suite_to_skip == suite_name)
			):
				var skipped_tests: PackedStringArray = skipped.get(suite_to_skip)
				var skip_reason := "Excluded by configuration"
				# if no tests skipped test the complete suite is skipped
				if skipped_tests.is_empty():
					_console.prints_warning("Mark the entire test suite '%s' as skipped!" % test_suite_path)
					@warning_ignore("unsafe_property_access")
					test_suite.__is_skipped = true
					@warning_ignore("unsafe_property_access")
					test_suite.__skip_reason = skip_reason
				else:
					# skip tests
					for test_to_skip in skipped_tests:
						var test_case: _TestCase = test_suite.find_child(test_to_skip, true, false)
						if test_case:
							test_case.skip(true, skip_reason)
							_console.prints_warning("Mark test case '%s':%s as skipped" % [suite_to_skip, test_to_skip])
						else:
							_console.prints_error(
								"Can't skip test '%s' checked test suite '%s', no test with given name exists!"
								% [test_to_skip, suite_to_skip]
							)


	func _collect_test_case_count(test_suites: Array[Node]) -> int:
		var total: int = 0
		for test_suite in test_suites:
			total += test_suite.get_child_count()
		return total


	# gdlint: disable=function-name
	func PublishEvent(data: Dictionary) -> void:
		_on_gdunit_event(GdUnitEvent.new().deserialize(data))


	func _on_gdunit_event(event: GdUnitEvent) -> void:
		match event.type():
			GdUnitEvent.INIT:
				_report = GdUnitHtmlReport.new(_report_dir, _report_max)
			GdUnitEvent.STOP:
				var report_path := _report.write()
				_report.delete_history(_report_max)
				JUnitXmlReport.new(_report._report_path, _report.iteration()).write(_report)
				_console.prints_color(
					build_executed_test_suite_msg(_report.suite_executed_count(), _report.suite_count()),
					Color.DARK_SALMON
				).prints_color(
					build_executed_test_case_msg(_report.test_executed_count(), _report.test_count()),
					Color.DARK_SALMON
				).prints_color(
					"Total time:        %s" % LocalTime.elapsed(_report.duration()),
					Color.DARK_SALMON
				).prints_color(
					"Open Report at: file://%s" % report_path,
					Color.CORNFLOWER_BLUE
				)
			GdUnitEvent.TESTSUITE_BEFORE:
				_report.add_testsuite_report(event.resource_path(), event.suite_name(), event.total_count())
			GdUnitEvent.TESTSUITE_AFTER:
				_report.add_testsuite_reports(
					event.resource_path(),
					event.error_count(),
					event.failed_count(),
					event.orphan_nodes(),
					event.elapsed_time(),
					event.reports()
				)
			GdUnitEvent.TESTCASE_BEFORE:
				_report.add_testcase(event.resource_path(), event.suite_name(), event.test_name())
			GdUnitEvent.TESTCASE_AFTER:
				_report.set_testcase_counters(event.resource_path(),
					event.test_name(),
					event.is_error(),
					event.failed_count(),
					event.orphan_nodes(),
					event.is_skipped(),
					event.is_flaky(),
					event.elapsed_time())
				_report.add_testcase_reports(event.resource_path(), event.test_name(), event.reports())
			GdUnitEvent.TESTCASE_STATISTICS:
				_report.update_testsuite_counters(event.resource_path(), event.is_error(), event.failed_count(), event.orphan_nodes(),\
					event.is_skipped(), event.is_flaky(), event.elapsed_time())
		print_status(event)


	func build_executed_test_suite_msg(executed_count :int, total_count :int) -> String:
		if executed_count == total_count:
			return "Executed test suites: (%d/%d)" % [executed_count, total_count]
		return "Executed test suites: (%d/%d), %d skipped" % [executed_count, total_count, (total_count - executed_count)]


	func build_executed_test_case_msg(executed_count :int, total_count :int) -> String:
		if executed_count == total_count:
			return "Executed test cases: (%d/%d)" % [executed_count, total_count]
		return "Executed test cases: (%d/%d), %d skipped" % [executed_count, total_count, (total_count - executed_count)]


	func report_exit_code(report: GdUnitHtmlReport) -> int:
		if report.error_count() + report.failure_count() > 0:
			_console.prints_color("Exit code: %d" % RETURN_ERROR, Color.FIREBRICK)
			return RETURN_ERROR
		if report.orphan_count() > 0:
			_console.prints_color("Exit code: %d" % RETURN_WARNING, Color.GOLDENROD)
			return RETURN_WARNING
		_console.prints_color("Exit code: %d" % RETURN_SUCCESS, Color.DARK_SALMON)
		return RETURN_SUCCESS


	func print_status(event: GdUnitEvent) -> void:
		match event.type():
			GdUnitEvent.TESTSUITE_BEFORE:
				_console.prints_color(
					"Run Test Suite %s " % event.resource_path(),
					Color.ANTIQUE_WHITE
				)
			GdUnitEvent.TESTCASE_BEFORE:
				_console.print_color(
					"	Run Test: %s > %s :" % [event.resource_path(), event.test_name()],
					Color.ANTIQUE_WHITE
				).prints_color(
					"STARTED",
					Color.FOREST_GREEN
				).save_cursor()
			GdUnitEvent.TESTCASE_AFTER:
				#_console.restore_cursor()
				_console.print_color(
					"	Run Test: %s > %s :" % [event.resource_path(), event.test_name()],
					Color.ANTIQUE_WHITE
				)
				_print_status(event)
				_print_failure_report(event.reports())
			GdUnitEvent.TESTSUITE_AFTER:
				_print_failure_report(event.reports())
				_print_status(event)
				_console.prints_color(
					"Statistics: | %d tests cases | %d error | %d failed | %d flaky | %d skipped | %d orphans |\n"
					% [
						_report.test_count(),
						_report.error_count(),
						_report.failure_count(),
						_report.flaky_count(),
						_report.skipped_count(),
						_report.orphan_count()
					],
					Color.ANTIQUE_WHITE
				)


	func _print_failure_report(reports: Array[GdUnitReport]) -> void:
		for report in reports:
			if (
				report.is_failure()
				or report.is_error()
				or report.is_warning()
				or report.is_skipped()
			):
				_console.prints_color(
					"	Report:",
					Color.DARK_TURQUOISE, CmdConsole.BOLD | CmdConsole.UNDERLINE
				)
				var text := GdUnitTools.richtext_normalize(str(report))
				for line in text.split("\n"):
					_console.prints_color("		%s" % line, Color.DARK_TURQUOISE)
		_console.new_line()


	func _print_status(event: GdUnitEvent) -> void:
		if event.is_flaky() and event.is_success():
			var retries :int = event.statistic(GdUnitEvent.RETRY_COUNT)
			_console.print_color("FLAKY (%d retries)" % retries, Color.GREEN_YELLOW, CmdConsole.BOLD | CmdConsole.ITALIC)
		elif event.is_success():
			_console.print_color("PASSED", Color.FOREST_GREEN, CmdConsole.BOLD)
		elif event.is_skipped():
			_console.print_color("SKIPPED", Color.GOLDENROD, CmdConsole.BOLD | CmdConsole.ITALIC)
		elif event.is_failed() or event.is_error():
			var retries :int = event.statistic(GdUnitEvent.RETRY_COUNT)
			if retries > 1:
				_console.print_color("FAILED (retry %d)" % retries, Color.FIREBRICK, CmdConsole.BOLD)
			else:
				_console.print_color("FAILED", Color.FIREBRICK, CmdConsole.BOLD)
		elif event.is_warning():
			_console.print_color("WARNING", Color.GOLDENROD, CmdConsole.BOLD | CmdConsole.UNDERLINE)

		_console.prints_color(
			" %s" % LocalTime.elapsed(event.elapsed_time()), Color.CORNFLOWER_BLUE
		)


var _cli_runner :CLIRunner


func _initialize() -> void:
	if Engine.get_version_info().hex < 0x40200:
		prints("GdUnit4 requires a minimum of Godot 4.2.x Version!")
		quit(CLIRunner.RETURN_ERROR_GODOT_VERSION_NOT_SUPPORTED)
		return
	DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_MINIMIZED)
	_cli_runner = CLIRunner.new()
	root.add_child(_cli_runner)


# do not use print statements on _finalize it results in random crashes
func _finalize() -> void:
	queue_delete(_cli_runner)
	if OS.is_stdout_verbose():
		prints("Finallize ..")
		prints("-Orphan nodes report-----------------------")
		Window.print_orphan_nodes()
		prints("Finallize .. done")


================================================
FILE: addons/gdUnit4/bin/GdUnitCmdTool.gd.uid
================================================
uid://dse8va3nbnsj


================================================
FILE: addons/gdUnit4/bin/GdUnitCopyLog.gd
================================================
#!/usr/bin/env -S godot -s
extends MainLoop

const GdUnitTools := preload("res://addons/gdUnit4/src/core/GdUnitTools.gd")

# gdlint: disable=max-line-length
const LOG_FRAME_TEMPLATE = """
<!DOCTYPE html>
<html style="display: inline-grid;">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Godot Logging</title>
	<link rel="stylesheet" href="css/styles.css">
</head>

<body style="background-color: #eee;">
	<div class="godot-report-frame"">
${content}
	</div>
</body>
</html>
"""

const NO_LOG_MESSAGE = """
<h3>No logging available!</h3>
</br>
<p>In order for logging to take place, you must activate the Activate file logging option in the project settings.</p>
<p>You can enable the logging under:
<b>Project Settings</b> > <b>Debug</b> > <b>File Logging</b> > <b>Enable File Logging</b> in the project settings.</p>
"""

#warning-ignore-all:return_value_discarded
var _cmd_options := CmdOptions.new([
		CmdOption.new(
			"-rd, --report-directory",
			"-rd <directory>",
			"Specifies the output directory in which the reports are to be written. The default is res://reports/.",
			TYPE_STRING,
			true
		)
	])


var _report_root_path: String
var _current_report_path: String
var _debug_cmd_args := PackedStringArray()


func _init() -> void:
	set_report_directory(GdUnitFileAccess.current_dir() + "reports")
	set_current_report_path()


func _process(_delta: float) -> bool:
	# check if reports exists
	if not reports_available():
		prints("no reports found")
		return true

	# only process if godot logging is enabled
	if not GdUnitSettings.is_log_enabled():
		write_report(NO_LOG_MESSAGE, "")
		return true

	# parse possible custom report path,
	var cmd_parser := CmdArgumentParser.new(_cmd_options, "GdUnitCmdTool.gd")
	# ignore erros and exit quitly
	if cmd_parser.parse(get_cmdline_args(), true).is_error():
		return true
	CmdCommandHandler.new(_cmd_options).register_cb("-rd", set_report_directory)

	var godot_log_file := scan_latest_godot_log()
	var result := read_log_file_content(godot_log_file)
	if result.is_error():
		write_report(result.error_message(), godot_log_file)
		return true
	write_report(result.value_as_string(), godot_log_file)
	return true


func set_current_report_path() -> void:
	# scan for latest report directory
	var iteration := GdUnitFileAccess.find_last_path_index(
		_report_root_path, GdUnitHtmlReport.REPORT_DIR_PREFIX
	)
	_current_report_path = "%s/%s%d" % [_report_root_path, GdUnitHtmlReport.REPORT_DIR_PREFIX, iteration]


func set_report_directory(path: String) -> void:
	_report_root_path = path


func get_log_report_html() -> String:
	return _current_report_path + "/godot_report_log.html"


func reports_available() -> bool:
	return DirAccess.dir_exists_absolute(_report_root_path)


func scan_latest_godot_log() -> String:
	var path := GdUnitSettings.get_log_path().get_base_dir()
	var files_sorted := Array()
	for file in GdUnitFileAccess.scan_dir(path):
		var file_name := "%s/%s" % [path, file]
		files_sorted.append(file_name)
	# sort by name, the name contains the timestamp so we sort at the end by timestamp
	files_sorted.sort()
	return files_sorted.back()


func read_log_file_content(log_file: String) -> GdUnitResult:
	var file := FileAccess.open(log_file, FileAccess.READ)
	if file == null:
		return GdUnitResult.error(
			"Can't find log file '%s'. Error: %s"
			% [log_file, error_string(FileAccess.get_open_error())]
		)
	var content := "<pre>" + file.get_as_text()
	# patch out console format codes
	for color_index in range(0, 256):
		var to_replace := "[38;5;%dm" % color_index
		content = content.replace(to_replace, "")
	content += "</pre>"
	content = content\
		.replace("", "")\
		.replace(CmdConsole.CSI_BOLD, "")\
		.replace(CmdConsole.CSI_ITALIC, "")\
		.replace(CmdConsole.CSI_UNDERLINE, "")
	return GdUnitResult.success(content)


func write_report(content: String, godot_log_file: String) -> GdUnitResult:
	var file := FileAccess.open(get_log_report_html(), FileAccess.WRITE)
	if file == null:
		return GdUnitResult.error(
			"Can't open to write '%s'. Error: %s"
			% [get_log_report_html(), error_string(FileAccess.get_open_error())]
		)
	var report_html := LOG_FRAME_TEMPLATE.replace("${content}", content)
	file.store_string(report_html)
	_update_index_html(godot_log_file)
	return GdUnitResult.success(file)


func _update_index_html(godot_log_file: String) -> void:
	var index_file := FileAccess.open("%s/index.html" % _current_report_path, FileAccess.READ_WRITE)
	if index_file == null:
		push_error(
			"Can't add log path to index.html. Error: %s"
			% error_string(FileAccess.get_open_error())
		)
		return
	var content := index_file.get_as_text()\
		.replace("${log_report}", get_log_report_html())\
		.replace("${godot_log_file}", godot_log_file)
	# overide it
	index_file.seek(0)
	index_file.store_string(content)


func get_cmdline_args() -> PackedStringArray:
	if _debug_cmd_args.is_empty():
		return OS.get_cmdline_args()
	return _debug_cmd_args


================================================
FILE: addons/gdUnit4/bin/GdUnitCopyLog.gd.uid
================================================
uid://dy0e4k8e7so0l


================================================
FILE: addons/gdUnit4/plugin.cfg
================================================
[plugin]

name="gdUnit4"
description="Unit Testing Framework for Godot Scripts"
author="Mike Schulze"
version="4.5.0"
script="plugin.gd"


================================================
FILE: addons/gdUnit4/plugin.gd
================================================
@tool
extends EditorPlugin

const GdUnitTools := preload("res://addons/gdUnit4/src/core/GdUnitTools.gd")
const GdUnitTestDiscoverGuard := preload("res://addons/gdUnit4/src/core/discovery/GdUnitTestDiscoverGuard.gd")
const GdUnitConsole := preload("res://addons/gdUnit4/src/ui/GdUnitConsole.gd")


var _gd_inspector: Control
var _gd_console: GdUnitConsole
var _guard: GdUnitTestDiscoverGuard


func _enter_tree() -> void:
	if check_running_in_test_env():
		@warning_ignore("return_value_discarded")
		CmdConsole.new().prints_warning("It was recognized that GdUnit4 is running in a test environment, therefore the GdUnit4 plugin will not be executed!")
		return
	if Engine.get_version_info().hex < 0x40200:
		prints("GdUnit4 plugin requires a minimum of Godot 4.2.x Version!")
		return
	GdUnitSettings.setup()
	# Install the GdUnit Inspector
	_gd_inspector = (load("res://addons/gdUnit4/src/ui/GdUnitInspector.tscn") as PackedScene).instantiate()
	add_control_to_dock(EditorPlugin.DOCK_SLOT_LEFT_UR, _gd_inspector)
	# Install the GdUnit Console
	_gd_console = (load("res://addons/gdUnit4/src/ui/GdUnitConsole.tscn") as PackedScene).instantiate()
	var control := add_control_to_bottom_panel(_gd_console, "gdUnitConsole")
	await _gd_console.setup_update_notification(control)
	if GdUnit4CSharpApiLoader.is_mono_supported():
		prints("GdUnit4Net version '%s' loaded." % GdUnit4CSharpApiLoader.version())
	# Connect to be notified for script changes to be able to discover new tests
	_guard = GdUnitTestDiscoverGuard.new()
	@warning_ignore("return_value_discarded")
	resource_saved.connect(_on_resource_saved)
	prints("Loading GdUnit4 Plugin success")


func _exit_tree() -> void:
	if check_running_in_test_env():
		return
	if is_instance_valid(_gd_inspector):
		remove_control_from_docks(_gd_inspector)
		_gd_inspector.free()
	if is_instance_valid(_gd_console):
		remove_control_from_bottom_panel(_gd_console)
		_gd_console.free()
	GdUnitTools.dispose_all(true)
	prints("Unload GdUnit4 Plugin success")


func check_running_in_test_env() -> bool:
	var args := OS.get_cmdline_args()
	args.append_array(OS.get_cmdline_user_args())
	return DisplayServer.get_name() == "headless" or args.has("--selftest") or args.has("--add") or args.has("-a") or args.has("--quit-after") or args.has("--import")


func _on_resource_saved(resource: Resource) -> void:
	if resource is Script:
		await _guard.discover(resource as Script)


================================================
FILE: addons/gdUnit4/plugin.gd.uid
================================================
uid://d2u6j827llq5e


================================================
FILE: addons/gdUnit4/runtest.cmd
================================================
@ECHO OFF
CLS

IF NOT DEFINED GODOT_BIN (
	ECHO "GODOT_BIN is not set."
	ECHO "Please set the environment variable 'setx GODOT_BIN <path to godot.exe>'"
	EXIT /b -1
)

REM scan if Godot mono used and compile c# classes
for /f "tokens=5 delims=. " %%i in ('%GODOT_BIN% --version') do set GODOT_TYPE=%%i
IF "%GODOT_TYPE%" == "mono" (
	ECHO "Godot mono detected"
	ECHO Compiling c# classes ... Please Wait
	dotnet build --debug
	ECHO done %errorlevel%
)

%GODOT_BIN% -s -d res://addons/gdUnit4/bin/GdUnitCmdTool.gd %*
SET exit_code=%errorlevel%
%GODOT_BIN% --headless --quiet -s -d res://addons/gdUnit4/bin/GdUnitCopyLog.gd %*

ECHO %exit_code%

EXIT /B %exit_code%


================================================
FILE: addons/gdUnit4/runtest.sh
================================================
#!/bin/sh

if [ -z "$GODOT_BIN" ]; then
    echo "'GODOT_BIN' is not set."
    echo "Please set the environment variable  'export GODOT_BIN=/Applications/Godot.app/Contents/MacOS/Godot'"
    exit 1
fi

"$GODOT_BIN" --path . -s -d res://addons/gdUnit4/bin/GdUnitCmdTool.gd $*
exit_code=$?
echo "Run tests ends with $exit_code"

"$GODOT_BIN" --headless --path . --quiet -s -d res://addons/gdUnit4/bin/GdUnitCopyLog.gd $* > /dev/null
exit_code2=$?
exit $exit_code


================================================
FILE: addons/gdUnit4/src/Comparator.gd
================================================
class_name Comparator
extends Resource

enum {
	EQUAL,
	LESS_THAN,
	LESS_EQUAL,
	GREATER_THAN,
	GREATER_EQUAL,
	BETWEEN_EQUAL,
	NOT_BETWEEN_EQUAL,
}


================================================
FILE: addons/gdUnit4/src/Comparator.gd.uid
================================================
uid://ctlh2t38mahwm


================================================
FILE: addons/gdUnit4/src/Fuzzers.gd
================================================
## A fuzzer implementation to provide default implementation
class_name Fuzzers
extends Resource


## Generates an random string with min/max length and given charset
static func rand_str(min_length: int, max_length :int, charset := StringFuzzer.DEFAULT_CHARSET) -> Fuzzer:
	return StringFuzzer.new(min_length, max_length, charset)


## Generates an random integer in a range form to
static func rangei(from: int, to: int) -> Fuzzer:
	return IntFuzzer.new(from, to)

## Generates a randon float within in a given range
static func rangef(from: float, to: float) -> Fuzzer:
	return FloatFuzzer.new(from, to)

## Generates an random Vector2 in a range form to
static func rangev2(from: Vector2, to: Vector2) -> Fuzzer:
	return Vector2Fuzzer.new(from, to)


## Generates an random Vector3 in a range form to
static func rangev3(from: Vector3, to: Vector3) -> Fuzzer:
	return Vector3Fuzzer.new(from, to)

## Generates an integer in a range form to that can be divided exactly by 2
static func eveni(from: int, to: int) -> Fuzzer:
	return IntFuzzer.new(from, to, IntFuzzer.EVEN)

## Generates an integer in a range form to that cannot be divided exactly by 2
static func oddi(from: int, to: int) -> Fuzzer:
	return IntFuzzer.new(from, to, IntFuzzer.ODD)


================================================
FILE: addons/gdUnit4/src/Fuzzers.gd.uid
================================================
uid://byx7ltrjl833o


================================================
FILE: addons/gdUnit4/src/GdUnitArrayAssert.gd
================================================
## An Assertion Tool to verify array values
class_name GdUnitArrayAssert
extends GdUnitAssert


## Verifies that the current value is null.
func is_null() -> GdUnitArrayAssert:
	return self


## Verifies that the current value is not null.
func is_not_null() -> GdUnitArrayAssert:
	return self


## Verifies that the current Array is equal to the given one.
@warning_ignore("unused_parameter")
func is_equal(expected :Variant) -> GdUnitArrayAssert:
	return self


## Verifies that the current Array is equal to the given one, ignoring case considerations.
@warning_ignore("unused_parameter")
func is_equal_ignoring_case(expected :Variant) -> GdUnitArrayAssert:
	return self


## Verifies that the current Array is not equal to the given one.
@warning_ignore("unused_parameter")
func is_not_equal(expected :Variant) -> GdUnitArrayAssert:
	return self


## Verifies that the current Array is not equal to the given one, ignoring case considerations.
@warning_ignore("unused_parameter")
func is_not_equal_ignoring_case(expected :Variant) -> GdUnitArrayAssert:
	return self


## Verifies that the current Array is empty, it has a size of 0.
func is_empty() -> GdUnitArrayAssert:
	return self


## Verifies that the current Array is not empty, it has a size of minimum 1.
func is_not_empty() -> GdUnitArrayAssert:
	return self

## Verifies that the current Array is the same. [br]
## Compares the current by object reference equals
@warning_ignore("unused_parameter", "shadowed_global_identifier")
func is_same(expected :Variant) -> GdUnitArrayAssert:
	return self


## Verifies that the current Array is NOT the same. [br]
## Compares the current by object reference equals
@warning_ignore("unused_parameter", "shadowed_global_identifier")
func is_not_same(expected :Variant) -> GdUnitArrayAssert:
	return self


## Verifies that the current Array has a size of given value.
@warning_ignore("unused_parameter")
func has_size(expectd: int) -> GdUnitArrayAssert:
	return self


## Verifies that the current Array contains the given values, in any order.[br]
## The values are compared by deep parameter comparision, for object reference compare you have to use [method contains_same]
@warning_ignore("unused_parameter")
func contains(expected :Variant) -> GdUnitArrayAssert:
	return self


## Verifies that the current Array contains exactly only the given values and nothing else, in same order.[br]
## The values are compared by deep parameter comparision, for object reference compare you have to use [method contains_same_exactly]
@warning_ignore("unused_parameter")
func contains_exactly(expected :Variant) -> GdUnitArrayAssert:
	return self


## Verifies that the current Array contains exactly only the given values and nothing else, in any order.[br]
## The values are compared by deep parameter comparision, for object reference compare you have to use [method contains_same_exactly_in_any_order]
@warning_ignore("unused_parameter")
func contains_exactly_in_any_order(expected :Variant) -> GdUnitArrayAssert:
	return self


## Verifies that the current Array contains the given values, in any order.[br]
## The values are compared by object reference, for deep parameter comparision use [method contains]
@warning_ignore("unused_parameter")
func contains_same(expected :Variant) -> GdUnitArrayAssert:
	return self


## Verifies that the current Array contains exactly only the given values and nothing else, in same order.[br]
## The values are compared by object reference, for deep parameter comparision use [method contains_exactly]
@warning_ignore("unused_parameter")
func contains_same_exactly(expected :Variant) -> GdUnitArrayAssert:
	return self


## Verifies that the current Array contains exactly only the given values and nothing else, in any order.[br]
## The values are compared by object reference, for deep parameter comparision use [method contains_exactly_in_any_order]
@warning_ignore("unused_parameter")
func contains_same_exactly_in_any_order(expected :Variant) -> GdUnitArrayAssert:
	return self


## Verifies that the current Array do NOT contains the given values, in any order.[br]
## The values are compared by deep parameter comparision, for object reference compare you have to use [method not_contains_same]
## [b]Example:[/b]
## [codeblock]
## # will succeed
## assert_array([1, 2, 3, 4, 5]).not_contains([6])
## # will fail
## assert_array([1, 2, 3, 4, 5]).not_contains([2, 6])
## [/codeblock]
@warning_ignore("unused_parameter")
func not_contains(expected :Variant) -> GdUnitArrayAssert:
	return self


## Verifies that the current Array do NOT contains the given values, in any order.[br]
## The values are compared by object reference, for deep parameter comparision use [method not_contains]
## [b]Example:[/b]
## [codeblock]
## # will succeed
## assert_array([1, 2, 3, 4, 5]).not_contains([6])
## # will fail
## assert_array([1, 2, 3, 4, 5]).not_contains([2, 6])
## [/codeblock]
@warning_ignore("unused_parameter")
func not_contains_same(expected :Variant) -> GdUnitArrayAssert:
	return self


## Extracts all values by given function name and optional arguments into a new ArrayAssert.
## If the elements not accessible by `func_name` the value is converted to `"n.a"`, expecting null values
@warning_ignore("unused_parameter")
func extract(func_name: String, args := Array()) -> GdUnitArrayAssert:
	return self


## Extracts all values by given extractor's into a new ArrayAssert.
## If the elements not extractable than the value is converted to `"n.a"`, expecting null values
@warning_ignore("unused_parameter")
func extractv(
	extractor0 :GdUnitValueExtractor,
	extractor1 :GdUnitValueExtractor = null,
	extractor2 :GdUnitValueExtractor = null,
	extractor3 :GdUnitValueExtractor = null,
	extractor4 :GdUnitValueExtractor = null,
	extractor5 :GdUnitValueExtractor = null,
	extractor6 :GdUnitValueExtractor = null,
	extractor7 :GdUnitValueExtractor = null,
	extractor8 :GdUnitValueExtractor = null,
	extractor9 :GdUnitValueExtractor = null) -> GdUnitArrayAssert:
	return self



@warning_ignore("unused_parameter")
func override_failure_message(message :String) -> GdUnitArrayAssert:
	return self


@warning_ignore("unused_parameter")
func append_failure_message(message :String) -> GdUnitArrayAssert:
	return self


================================================
FILE: addons/gdUnit4/src/GdUnitArrayAssert.gd.uid
================================================
uid://ct0h0f830p6ly


================================================
FILE: addons/gdUnit4/src/GdUnitAssert.gd
================================================
## Base interface of all GdUnit asserts
class_name GdUnitAssert
extends RefCounted


## Verifies that the current value is null.
@warning_ignore("untyped_declaration")
func is_null():
	return self


## Verifies that the current value is not null.
@warning_ignore("untyped_declaration")
func is_not_null():
	return self


## Verifies that the current value is equal to expected one.
@warning_ignore("unused_parameter")
@warning_ignore("untyped_declaration")
func is_equal(expected: Variant):
	return self


## Verifies that the current value is not equal to expected one.
@warning_ignore("unused_parameter")
@warning_ignore("untyped_declaration")
func is_not_equal(expected: Variant):
	return self


@warning_ignore("untyped_declaration")
func do_fail():
	return self


## Overrides the default failure message by given custom message.
@warning_ignore("unused_parameter")
@warning_ignore("untyped_declaration")
func override_failure_message(message :String):
	return self


## Appends a custom message to the failure message.
## This can be used to add additional infromations to the generated failure message.
@warning_ignore("unused_parameter")
@warning_ignore("untyped_declaration")
func append_failure_message(message :String):
	return self


================================================
FILE: addons/gdUnit4/src/GdUnitAssert.gd.uid
================================================
uid://vubel7soheoo


================================================
FILE: addons/gdUnit4/src/GdUnitAwaiter.gd
================================================
class_name GdUnitAwaiter
extends RefCounted


# Waits for a specified signal in an interval of 50ms sent from the <source>, and terminates with an error after the specified timeout has elapsed.
# source: the object from which the signal is emitted
# signal_name: signal name
# args: the expected signal arguments as an array
# timeout: the timeout in ms, default is set to 2000ms
func await_signal_on(source :Object, signal_name :String, args :Array = [], timeout_millis :int = 2000) -> Variant:
	# fail fast if the given source instance invalid
	var assert_that := GdUnitAssertImpl.new(signal_name)
	var line_number := GdUnitAssertions.get_line_number()
	if not is_instance_valid(source):
		@warning_ignore("return_value_discarded")
		assert_that.report_error(GdAssertMessages.error_await_signal_on_invalid_instance(source, signal_name, args), line_number)
		return await (Engine.get_main_loop() as SceneTree).process_frame
	# fail fast if the given source instance invalid
	if not is_instance_valid(source):
		@warning_ignore("return_value_discarded")
		assert_that.report_error(GdAssertMessages.error_await_signal_on_invalid_instance(source, signal_name, args), line_number)
		return await await_idle_frame()
	var awaiter := GdUnitSignalAwaiter.new(timeout_millis)
	var value :Variant = await awaiter.on_signal(source, signal_name, args)
	if awaiter.is_interrupted():
		var failure := "await_signal_on(%s, %s) timed out after %sms" % [signal_name, args, timeout_millis]
		@warning_ignore("return_value_discarded")
		assert_that.report_error(failure, line_number)
	return value


# Waits for a specified signal sent from the <source> between idle frames and aborts with an error after the specified timeout has elapsed
# source: the object from which the signal is emitted
# signal_name: signal name
# args: the expected signal arguments as an array
# timeout: the timeout in ms, default is set to 2000ms
func await_signal_idle_frames(source :Object, signal_name :String, args :Array = [], timeout_millis :int = 2000) -> Variant:
	var line_number := GdUnitAssertions.get_line_number()
	# fail fast if the given source instance invalid
	if not is_instance_valid(source):
		@warning_ignore("return_value_discarded")
		GdUnitAssertImpl.new(signal_name)\
			.report_error(GdAssertMessages.error_await_signal_on_invalid_instance(source, signal_name, args), line_number)
		return await await_idle_frame()
	var awaiter := GdUnitSignalAwaiter.new(timeout_millis, true)
	var value :Variant = await awaiter.on_signal(source, signal_name, args)
	if awaiter.is_interrupted():
		var failure := "await_signal_idle_frames(%s, %s) timed out after %sms" % [signal_name, args, timeout_millis]
		@warning_ignore("return_value_discarded")
		GdUnitAssertImpl.new(signal_name).report_error(failure, line_number)
	return value


# Waits for for a given amount of milliseconds
# example:
#    # waits for 100ms
#    await GdUnitAwaiter.await_millis(myNode, 100).completed
# use this waiter and not `await get_tree().create_timer().timeout to prevent errors when a test case is timed out
func await_millis(milliSec :int) -> void:
	var timer :Timer = Timer.new()
	timer.set_name("gdunit_await_millis_timer_%d" % timer.get_instance_id())
	(Engine.get_main_loop() as SceneTree).root.add_child(timer)
	timer.add_to_group("GdUnitTimers")
	timer.set_one_shot(true)
	timer.start(milliSec / 1000.0)
	await timer.timeout
	timer.queue_free()


# Waits until the next idle frame
func await_idle_frame() -> void:
	await (Engine.get_main_loop() as SceneTree).process_frame


================================================
FILE: addons/gdUnit4/src/GdUnitAwaiter.gd.uid
================================================
uid://cjk17c1p2qiuo


================================================
FILE: addons/gdUnit4/src/GdUnitBoolAssert.gd
================================================
## An Assertion Tool to verify boolean values
class_name GdUnitBoolAssert
extends GdUnitAssert


## Verifies that the current value is null.
func is_null() -> GdUnitBoolAssert:
	return self


## Verifies that the current value is not null.
func is_not_null() -> GdUnitBoolAssert:
	return self


## Verifies that the current value is equal to the given one.
@warning_ignore("unused_parameter")
func is_equal(expected :Variant) -> GdUnitBoolAssert:
	return self


## Verifies that the current value is not equal to the given one.
@warning_ignore("unused_parameter")
func is_not_equal(expected :Variant) -> GdUnitBoolAssert:
	return self


## Verifies that the current value is true.
func is_true() -> GdUnitBoolAssert:
	return self


## Verifies that the current value is false.
func is_false() -> GdUnitBoolAssert:
	return self


## Overrides the default failure message by given custom message.
@warning_ignore("unused_parameter")
func override_failure_message(message :String) -> GdUnitBoolAssert:
	return self


================================================
FILE: addons/gdUnit4/src/GdUnitBoolAssert.gd.uid
================================================
uid://0k6b245p1wiy


================================================
FILE: addons/gdUnit4/src/GdUnitConstants.gd
================================================
class_name GdUnitConstants
extends RefCounted

const NO_ARG :Variant = "<--null-->"

const EXPECT_ASSERT_REPORT_FAILURES := "expect_assert_report_failures"


================================================
FILE: addons/gdUnit4/src/GdUnitConstants.gd.uid
================================================
uid://cgkr776yh0rvd


================================================
FILE: addons/gdUnit4/src/GdUnitDictionaryAssert.gd
================================================
## An Assertion Tool to verify dictionary
class_name GdUnitDictionaryAssert
extends GdUnitAssert


## Verifies that the current value is null.
func is_null() -> GdUnitDictionaryAssert:
	return self


## Verifies that the current value is not null.
func is_not_null() -> GdUnitDictionaryAssert:
	return self


## Verifies that the current dictionary is equal to the given one, ignoring order.
@warning_ignore("unused_parameter")
func is_equal(expected :Variant) -> GdUnitDictionaryAssert:
	return self


## Verifies that the current dictionary is not equal to the given one, ignoring order.
@warning_ignore("unused_parameter")
func is_not_equal(expected :Variant) -> GdUnitDictionaryAssert:
	return self


## Verifies that the current dictionary is empty, it has a size of 0.
func is_empty() -> GdUnitDictionaryAssert:
	return self


## Verifies that the current dictionary is not empty, it has a size of minimum 1.
func is_not_empty() -> GdUnitDictionaryAssert:
	return self


## Verifies that the current dictionary is the same. [br]
## Compares the current by object reference equals
@warning_ignore("unused_parameter", "shadowed_global_identifier")
func is_same(expected :Variant) -> GdUnitDictionaryAssert:
	return self


## Verifies that the current dictionary is NOT the same. [br]
## Compares the current by object reference equals
@warning_ignore("unused_parameter")
func is_not_same(expected :Variant) -> GdUnitDictionaryAssert:
	return self


## Verifies that the current dictionary has a size of given value.
@warning_ignore("unused_parameter")
func has_size(expected: int) -> GdUnitDictionaryAssert:
	return self


## Verifies that the current dictionary contains the given key(s).[br]
## The keys are compared by deep parameter comparision, for object reference compare you have to use [method contains_same_keys]
@warning_ignore("unused_parameter")
func contains_keys(expected :Array) -> GdUnitDictionaryAssert:
	return self


## Verifies that the current dictionary contains the given key and value.[br]
## The key and value are compared by deep parameter comparision, for object reference compare you have to use [method contains_same_key_value]
@warning_ignore("unused_parameter")
func contains_key_value(key :Variant, value :Variant) -> GdUnitDictionaryAssert:
	return self


## Verifies that the current dictionary not contains the given key(s).[br]
## This function is [b]deprecated[/b] you have to use [method not_contains_keys] instead
@warning_ignore("unused_parameter")
func contains_not_keys(expected :Array) -> GdUnitDictionaryAssert:
	push_warning("Deprecated: 'contains_not_keys' is deprectated and will be removed soon, use `not_contains_keys` instead!")
	return not_contains_keys(expected)


## Verifies that the current dictionary not contains the given key(s).[br]
## The keys are compared by deep parameter comparision, for object reference compare you have to use [method not_contains_same_keys]
@warning_ignore("unused_parameter")
func not_contains_keys(expected :Array) -> GdUnitDictionaryAssert:
	return self


## Verifies that the current dictionary contains the given key(s).[br]
## The keys are compared by object reference, for deep parameter comparision use [method contains_keys]
@warning_ignore("unused_parameter")
func contains_same_keys(expected :Array) -> GdUnitDictionaryAssert:
	return self


## Verifies that the current dictionary contains the given key and value.[br]
## The key and value are compared by object reference, for deep parameter comparision use [method contains_key_value]
@warning_ignore("unused_parameter")
func contains_same_key_value(key :Variant, value :Variant) -> GdUnitDictionaryAssert:
	return self


## Verifies that the current dictionary not contains the given key(s).
## The keys are compared by object reference, for deep parameter comparision use [method not_contains_keys]
@warning_ignore("unused_parameter")
func not_contains_same_keys(expected :Array) -> GdUnitDictionaryAssert:
	return self


================================================
FILE: addons/gdUnit4/src/GdUnitDictionaryAssert.gd.uid
================================================
uid://bmhd7n6wxvjfx


================================================
FILE: addons/gdUnit4/src/GdUnitFailureAssert.gd
================================================
## An assertion tool to verify GDUnit asserts.
## This assert is for internal use only, to verify that failed asserts work as expected.
class_name GdUnitFailureAssert
extends GdUnitAssert


## Verifies if the executed assert was successful
func is_success() -> GdUnitFailureAssert:
	return self

## Verifies if the executed assert has failed
func is_failed() -> GdUnitFailureAssert:
	return self


## Verifies the failure line is equal to expected one.
@warning_ignore("unused_parameter")
func has_line(expected :int) -> GdUnitFailureAssert:
	return self


## Verifies the failure message is equal to expected one.
@warning_ignore("unused_parameter")
func has_message(expected: String) -> GdUnitFailureAssert:
	return self


## Verifies that the failure message starts with the expected message.
@warning_ignore("unused_parameter")
func starts_with_message(expected: String) -> GdUnitFailureAssert:
	return self


## Verifies that the failure message contains the expected message.
@warning_ignore("unused_parameter")
func contains_message(expected: String) -> GdUnitFailureAssert:
	return self


================================================
FILE: addons/gdUnit4/src/GdUnitFailureAssert.gd.uid
================================================
uid://ctcktx3fpdslo


================================================
FILE: addons/gdUnit4/src/GdUnitFileAssert.gd
================================================
class_name GdUnitFileAssert
extends GdUnitAssert


func is_file() -> GdUnitFileAssert:
	return self


func exists() -> GdUnitFileAssert:
	return self


func is_script() -> GdUnitFileAssert:
	return self


@warning_ignore("unused_parameter")
func contains_exactly(expected_rows :Array) -> GdUnitFileAssert:
	return self


================================================
FILE: addons/gdUnit4/src/GdUnitFileAssert.gd.uid
================================================
uid://786mnwoxl866


================================================
FILE: addons/gdUnit4/src/GdUnitFloatAssert.gd
================================================
## An Assertion Tool to verify float values
class_name GdUnitFloatAssert
extends GdUnitAssert


## Verifies that the current String is equal to the given one.
@warning_ignore("unused_parameter")
func is_equal(expected :Variant) -> GdUnitFloatAssert:
	return self


## Verifies that the current String is not equal to the given one.
@warning_ignore("unused_parameter")
func is_not_equal(expected :Variant) -> GdUnitFloatAssert:
	return self


## Verifies that the current and expected value are approximately equal.
@warning_ignore("unused_parameter", "shadowed_global_identifier")
func is_equal_approx(expected :float, approx :float) -> GdUnitFloatAssert:
	return self


## Verifies that the current value is less than the given one.
@warning_ignore("unused_parameter")
func is_less(expected :float) -> GdUnitFloatAssert:
	return self


## Verifies that the current value is less than or equal the given one.
@warning_ignore("unused_parameter")
func is_less_equal(expected :float) -> GdUnitFloatAssert:
	return self


## Verifies that the current value is greater than the given one.
@warning_ignore("unused_parameter")
func is_greater(expected :float) -> GdUnitFloatAssert:
	return self


## Verifies that the current value is greater than or equal the given one.
@warning_ignore("unused_parameter")
func is_greater_equal(expected :float) -> GdUnitFloatAssert:
	return self


## Verifies that the current value is negative.
func is_negative() -> GdUnitFloatAssert:
	return self


## Verifies that the current value is not negative.
func is_not_negative() -> GdUnitFloatAssert:
	return self


## Verifies that the current value is equal to zero.
func is_zero() -> GdUnitFloatAssert:
	return self


## Verifies that the current value is not equal to zero.
func is_not_zero() -> GdUnitFloatAssert:
	return self


## Verifies that the current value is in the given set of values.
@warning_ignore("unused_parameter")
func is_in(expected :Array) -> GdUnitFloatAssert:
	return self


## Verifies that the current value is not in the given set of values.
@warning_ignore("unused_parameter")
func is_not_in(expected :Array) -> GdUnitFloatAssert:
	return self


## Verifies that the current value is between the given boundaries (inclusive).
@warning_ignore("unused_parameter")
func is_between(from :float, to :float) -> GdUnitFloatAssert:
	return self


================================================
FILE: addons/gdUnit4/src/GdUnitFloatAssert.gd.uid
================================================
uid://b1pyvxx07ygya


================================================
FILE: addons/gdUnit4/src/GdUnitFuncAssert.gd
================================================
## An Assertion Tool to verify function callback values
class_name GdUnitFuncAssert
extends GdUnitAssert


## Verifies that the current value is null.
func is_null() -> GdUnitFuncAssert:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Verifies that the current value is not null.
func is_not_null() -> GdUnitFuncAssert:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Verifies that the current value is equal to the given one.
@warning_ignore("unused_parameter")
func is_equal(expected :Variant) -> GdUnitFuncAssert:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Verifies that the current value is not equal to the given one.
@warning_ignore("unused_parameter")
func is_not_equal(expected :Variant) -> GdUnitFuncAssert:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Verifies that the current value is true.
func is_true() -> GdUnitFuncAssert:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Verifies that the current value is false.
func is_false() -> GdUnitFuncAssert:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Overrides the default failure message by given custom message.
@warning_ignore("unused_parameter")
func override_failure_message(message :String) -> GdUnitFuncAssert:
	return self


## Sets the timeout in ms to wait the function returnd the expected value, if the time over a failure is emitted.[br]
## e.g.[br]
## do wait until 5s the function `is_state` is returns 10 [br]
## [code]assert_func(instance, "is_state").wait_until(5000).is_equal(10)[/code]
@warning_ignore("unused_parameter")
func wait_until(timeout :int) -> GdUnitFuncAssert:
	return self


================================================
FILE: addons/gdUnit4/src/GdUnitFuncAssert.gd.uid
================================================
uid://c383gmxgtgbmn


================================================
FILE: addons/gdUnit4/src/GdUnitGodotErrorAssert.gd
================================================
## An assertion tool to verify for Godot runtime errors like assert() and push notifications like push_error().
class_name GdUnitGodotErrorAssert
extends GdUnitAssert


## Verifies if the executed code runs without any runtime errors
## Usage:
##     [codeblock]
##		await assert_error(<callable>).is_success()
##     [/codeblock]
func is_success() -> GdUnitGodotErrorAssert:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Verifies if the executed code runs into a runtime error
## Usage:
##     [codeblock]
##		await assert_error(<callable>).is_runtime_error(<expected error message>)
##     [/codeblock]
@warning_ignore("unused_parameter")
func is_runtime_error(expected_error :String) -> GdUnitGodotErrorAssert:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Verifies if the executed code has a push_warning() used
## Usage:
##     [codeblock]
##		await assert_error(<callable>).is_push_warning(<expected push warning message>)
##     [/codeblock]
@warning_ignore("unused_parameter")
func is_push_warning(expected_warning :String) -> GdUnitGodotErrorAssert:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Verifies if the executed code has a push_error() used
## Usage:
##     [codeblock]
##		await assert_error(<callable>).is_push_error(<expected push error message>)
##     [/codeblock]
@warning_ignore("unused_parameter")
func is_push_error(expected_error :String) -> GdUnitGodotErrorAssert:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


================================================
FILE: addons/gdUnit4/src/GdUnitGodotErrorAssert.gd.uid
================================================
uid://cl8u3n4ao8fhg


================================================
FILE: addons/gdUnit4/src/GdUnitIntAssert.gd
================================================
## An Assertion Tool to verify integer values
class_name GdUnitIntAssert
extends GdUnitAssert

## Verifies that the current String is equal to the given one.
@warning_ignore("unused_parameter")
func is_equal(expected :Variant) -> GdUnitIntAssert:
	return self


## Verifies that the current String is not equal to the given one.
@warning_ignore("unused_parameter")
func is_not_equal(expected :Variant) -> GdUnitIntAssert:
	return self


## Verifies that the current value is less than the given one.
@warning_ignore("unused_parameter")
func is_less(expected :int) -> GdUnitIntAssert:
	return self


## Verifies that the current value is less than or equal the given one.
@warning_ignore("unused_parameter")
func is_less_equal(expected :int) -> GdUnitIntAssert:
	return self


## Verifies that the current value is greater than the given one.
@warning_ignore("unused_parameter")
func is_greater(expected :int) -> GdUnitIntAssert:
	return self


## Verifies that the current value is greater than or equal the given one.
@warning_ignore("unused_parameter")
func is_greater_equal(expected :int) -> GdUnitIntAssert:
	return self


## Verifies that the current value is even.
func is_even() -> GdUnitIntAssert:
	return self


## Verifies that the current value is odd.
func is_odd() -> GdUnitIntAssert:
	return self


## Verifies that the current value is negative.
func is_negative() -> GdUnitIntAssert:
	return self


## Verifies that the current value is not negative.
func is_not_negative() -> GdUnitIntAssert:
	return self


## Verifies that the current value is equal to zero.
func is_zero() -> GdUnitIntAssert:
	return self


## Verifies that the current value is not equal to zero.
func is_not_zero() -> GdUnitIntAssert:
	return self


## Verifies that the current value is in the given set of values.
@warning_ignore("unused_parameter")
func is_in(expected :Array) -> GdUnitIntAssert:
	return self


## Verifies that the current value is not in the given set of values.
@warning_ignore("unused_parameter")
func is_not_in(expected :Array) -> GdUnitIntAssert:
	return self


## Verifies that the current value is between the given boundaries (inclusive).
@warning_ignore("unused_parameter")
func is_between(from :int, to :int) -> GdUnitIntAssert:
	return self


================================================
FILE: addons/gdUnit4/src/GdUnitIntAssert.gd.uid
================================================
uid://k651n7cj74d2


================================================
FILE: addons/gdUnit4/src/GdUnitObjectAssert.gd
================================================
## An Assertion Tool to verify Object values
class_name GdUnitObjectAssert
extends GdUnitAssert


## Verifies that the current value is equal to expected one.
@warning_ignore("unused_parameter")
func is_equal(expected :Variant) -> GdUnitObjectAssert:
	return self


## Verifies that the current value is not equal to expected one.
@warning_ignore("unused_parameter")
func is_not_equal(expected :Variant) -> GdUnitObjectAssert:
	return self


## Verifies that the current value is null.
func is_null() -> GdUnitObjectAssert:
	return self


## Verifies that the current value is not null.
func is_not_null() -> GdUnitObjectAssert:
	return self


## Verifies that the current value is the same as the given one.
@warning_ignore("unused_parameter", "shadowed_global_identifier")
func is_same(expected :Variant) -> GdUnitObjectAssert:
	return self


## Verifies that the current value is not the same as the given one.
@warning_ignore("unused_parameter")
func is_not_same(expected :Variant) -> GdUnitObjectAssert:
	return self


## Verifies that the current value is an instance of the given type.
@warning_ignore("unused_parameter")
func is_instanceof(expected :Object) -> GdUnitObjectAssert:
	return self


## Verifies that the current value is not an instance of the given type.
@warning_ignore("unused_parameter")
func is_not_instanceof(expected :Variant) -> GdUnitObjectAssert:
	return self


================================================
FILE: addons/gdUnit4/src/GdUnitObjectAssert.gd.uid
================================================
uid://bqe5pqgo35ub3


================================================
FILE: addons/gdUnit4/src/GdUnitResultAssert.gd
================================================
## An Assertion Tool to verify Results
class_name GdUnitResultAssert
extends GdUnitAssert


## Verifies that the current value is null.
func is_null() -> GdUnitResultAssert:
	return self


## Verifies that the current value is not null.
func is_not_null() -> GdUnitResultAssert:
	return self


## Verifies that the result is ends up with empty
func is_empty() -> GdUnitResultAssert:
	return self


## Verifies that the result is ends up with success
func is_success() -> GdUnitResultAssert:
	return self


## Verifies that the result is ends up with warning
func is_warning() -> GdUnitResultAssert:
	return self


## Verifies that the result is ends up with error
func is_error() -> GdUnitResultAssert:
	return self


## Verifies that the result contains the given message
@warning_ignore("unused_parameter")
func contains_message(expected :String) -> GdUnitResultAssert:
	return self


## Verifies that the result contains the given value
@warning_ignore("unused_parameter")
func is_value(expected :Variant) -> GdUnitResultAssert:
	return self


================================================
FILE: addons/gdUnit4/src/GdUnitResultAssert.gd.uid
================================================
uid://pycd4o660wkt


================================================
FILE: addons/gdUnit4/src/GdUnitSceneRunner.gd
================================================
## The Scene Runner is a tool used for simulating interactions on a scene.
## With this tool, you can simulate input events such as keyboard or mouse input and/or simulate scene processing over a certain number of frames.
## This tool is typically used for integration testing a scene.
class_name GdUnitSceneRunner
extends RefCounted

const NO_ARG = GdUnitConstants.NO_ARG


## Simulates that an action has been pressed.[br]
## [member action] : the action e.g. [code]"ui_up"[/code][br]
@warning_ignore("unused_parameter")
func simulate_action_pressed(action: String) -> GdUnitSceneRunner:
	return self


## Simulates that an action is pressed.[br]
## [member action] : the action e.g. [code]"ui_up"[/code][br]
@warning_ignore("unused_parameter")
func simulate_action_press(action: String) -> GdUnitSceneRunner:
	return self


## Simulates that an action has been released.[br]
## [member action] : the action e.g. [code]"ui_up"[/code][br]
@warning_ignore("unused_parameter")
func simulate_action_release(action: String) -> GdUnitSceneRunner:
	return self


## Simulates that a key has been pressed.[br]
## [member key_code] : the key code e.g. [constant KEY_ENTER][br]
## [member shift_pressed] : false by default set to true if simmulate shift is press[br]
## [member ctrl_pressed] : false by default set to true if simmulate control is press[br]
## [codeblock]
##    func test_key_presssed():
##       var runner = scene_runner("res://scenes/simple_scene.tscn")
##       await runner.simulate_key_pressed(KEY_SPACE)
## [/codeblock]
@warning_ignore("unused_parameter")
func simulate_key_pressed(key_code: int, shift_pressed := false, ctrl_pressed := false) -> GdUnitSceneRunner:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Simulates that a key is pressed.[br]
## [member key_code] : the key code e.g. [constant KEY_ENTER][br]
## [member shift_pressed] : false by default set to true if simmulate shift is press[br]
## [member ctrl_pressed] : false by default set to true if simmulate control is press[br]
@warning_ignore("unused_parameter")
func simulate_key_press(key_code: int, shift_pressed := false, ctrl_pressed := false) -> GdUnitSceneRunner:
	return self


## Simulates that a key has been released.[br]
## [member key_code] : the key code e.g. [constant KEY_ENTER][br]
## [member shift_pressed] : false by default set to true if simmulate shift is press[br]
## [member ctrl_pressed] : false by default set to true if simmulate control is press[br]
@warning_ignore("unused_parameter")
func simulate_key_release(key_code: int, shift_pressed := false, ctrl_pressed := false) -> GdUnitSceneRunner:
	return self


## Sets the mouse cursor to given position relative to the viewport.
## @deprecated: Use [set_mouse_position] instead.
@warning_ignore("unused_parameter")
func set_mouse_pos(position: Vector2) -> GdUnitSceneRunner:
	return self


## Sets the mouse position to the specified vector, provided in pixels and relative to an origin at the upper left corner of the currently focused Window Manager game window.[br]
## [member position] : The absolute position in pixels as Vector2
@warning_ignore("unused_parameter")
func set_mouse_position(position: Vector2) -> GdUnitSceneRunner:
	return self


## Returns the mouse's position in this Viewport using the coordinate system of this Viewport.
func get_mouse_position() -> Vector2:
	return Vector2.ZERO


## Gets the current global mouse position of the current window
func get_global_mouse_position() -> Vector2:
	return Vector2.ZERO


## Simulates a mouse moved to final position.[br]
## [member position] : The final mouse position
@warning_ignore("unused_parameter")
func simulate_mouse_move(position: Vector2) -> GdUnitSceneRunner:
	return self


## Simulates a mouse move to the relative coordinates (offset).[br]
## [color=yellow]You must use [b]await[/b] to wait until the simulated mouse movement is complete.[/color][br]
## [br]
## [member relative] : The relative position, indicating the mouse position offset.[br]
## [member time] : The time to move the mouse by the relative position in seconds (default is 1 second).[br]
## [member trans_type] : Sets the type of transition used (default is TRANS_LINEAR).[br]
## [codeblock]
##    func test_move_mouse():
##       var runner = scene_runner("res://scenes/simple_scene.tscn")
##       await runner.simulate_mouse_move_relative(Vector2(100,100))
## [/codeblock]
@warning_ignore("unused_parameter")
func simulate_mouse_move_relative(relative: Vector2, time: float = 1.0, trans_type: Tween.TransitionType = Tween.TRANS_LINEAR) -> GdUnitSceneRunner:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Simulates a mouse move to the absolute coordinates.[br]
## [color=yellow]You must use [b]await[/b] to wait until the simulated mouse movement is complete.[/color][br]
## [br]
## [member position] : The final position of the mouse.[br]
## [member time] : The time to move the mouse to the final position in seconds (default is 1 second).[br]
## [member trans_type] : Sets the type of transition used (default is TRANS_LINEAR).[br]
## [codeblock]
##    func test_move_mouse():
##       var runner = scene_runner("res://scenes/simple_scene.tscn")
##       await runner.simulate_mouse_move_absolute(Vector2(100,100))
## [/codeblock]
@warning_ignore("unused_parameter")
func simulate_mouse_move_absolute(position: Vector2, time: float = 1.0, trans_type: Tween.TransitionType = Tween.TRANS_LINEAR) -> GdUnitSceneRunner:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Simulates a mouse button pressed.[br]
## [member button_index] : The mouse button identifier, one of the [enum MouseButton] or button wheel constants.
## [member double_click] : Set to true to simulate a double-click
@warning_ignore("unused_parameter")
func simulate_mouse_button_pressed(button_index: MouseButton, double_click := false) -> GdUnitSceneRunner:
	return self


## Simulates a mouse button press (holding)[br]
## [member button_index] : The mouse button identifier, one of the [enum MouseButton] or button wheel constants.
## [member double_click] : Set to true to simulate a double-click
@warning_ignore("unused_parameter")
func simulate_mouse_button_press(button_index: MouseButton, double_click := false) -> GdUnitSceneRunner:
	return self


## Simulates a mouse button released.[br]
## [member button_index] : The mouse button identifier, one of the [enum MouseButton] or button wheel constants.
@warning_ignore("unused_parameter")
func simulate_mouse_button_release(button_index: MouseButton) -> GdUnitSceneRunner:
	return self


## Simulates a screen touch is pressed.[br]
## [member index] : The touch index in the case of a multi-touch event.[br]
## [member position] : The position to touch the screen.[br]
## [member double_tap] : If true, the touch's state is a double tab.
@warning_ignore("unused_parameter")
func simulate_screen_touch_pressed(index: int, position: Vector2, double_tap := false) -> GdUnitSceneRunner:
	return self


## Simulates a screen touch press without releasing it immediately, effectively simulating a "hold" action.[br]
## [member index] : The touch index in the case of a multi-touch event.[br]
## [member position] : The position to touch the screen.[br]
## [member double_tap] : If true, the touch's state is a double tab.
@warning_ignore("unused_parameter")
func simulate_screen_touch_press(index: int, position: Vector2, double_tap := false) -> GdUnitSceneRunner:
	return self


## Simulates a screen touch is released.[br]
## [member index] : The touch index in the case of a multi-touch event.[br]
## [member double_tap] : If true, the touch's state is a double tab.
@warning_ignore("unused_parameter")
func simulate_screen_touch_release(index: int, double_tap := false) -> GdUnitSceneRunner:
	return self


## Simulates a touch drag and drop event to a relative position.[br]
## [color=yellow]You must use [b]await[/b] to wait until the simulated drag&drop is complete.[/color][br]
## [br]
## [member index] : The touch index in the case of a multi-touch event.[br]
## [member relative] : The relative position, indicating the drag&drop position offset.[br]
## [member time] : The time to move to the relative position in seconds (default is 1 second).[br]
## [member trans_type] : Sets the type of transition used (default is TRANS_LINEAR).[br]
## [codeblock]
##    func test_touch_drag_drop():
##       var runner = scene_runner("res://scenes/simple_scene.tscn")
##       # start drag at position 50,50
##       runner.simulate_screen_touch_drag_begin(1, Vector2(50, 50))
##       # and drop it at final at 150,50  relative (50,50 + 100,0)
##       await runner.simulate_screen_touch_drag_relative(1, Vector2(100,0))
## [/codeblock]
@warning_ignore("unused_parameter")
func simulate_screen_touch_drag_relative(index: int, relative: Vector2, time: float = 1.0, trans_type: Tween.TransitionType = Tween.TRANS_LINEAR) -> GdUnitSceneRunner:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Simulates a touch screen drop to the absolute coordinates (offset).[br]
## [color=yellow]You must use [b]await[/b] to wait until the simulated drop is complete.[/color][br]
## [br]
## [member index] : The touch index in the case of a multi-touch event.[br]
## [member position] : The final position, indicating the drop position.[br]
## [member time] : The time to move to the final position in seconds (default is 1 second).[br]
## [member trans_type] : Sets the type of transition used (default is TRANS_LINEAR).[br]
## [codeblock]
##    func test_touch_drag_drop():
##       var runner = scene_runner("res://scenes/simple_scene.tscn")
##       # start drag at position 50,50
##       runner.simulate_screen_touch_drag_begin(1, Vector2(50, 50))
##       # and drop it at 100,50
##       await runner.simulate_screen_touch_drag_absolute(1, Vector2(100,50))
## [/codeblock]
@warning_ignore("unused_parameter")
func simulate_screen_touch_drag_absolute(index: int, position: Vector2, time: float = 1.0, trans_type: Tween.TransitionType = Tween.TRANS_LINEAR) -> GdUnitSceneRunner:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Simulates a complete drag and drop event from one position to another.[br]
## This is ideal for testing complex drag-and-drop scenarios that require a specific start and end position.[br]
## [color=yellow]You must use [b]await[/b] to wait until the simulated drop is complete.[/color][br]
## [br]
## [member index] : The touch index in the case of a multi-touch event.[br]
## [member position] : The drag start position, indicating the drag position.[br]
## [member drop_position] : The drop position, indicating the drop position.[br]
## [member time] : The time to move to the final position in seconds (default is 1 second).[br]
## [member trans_type] : Sets the type of transition used (default is TRANS_LINEAR).[br]
## [codeblock]
##    func test_touch_drag_drop():
##       var runner = scene_runner("res://scenes/simple_scene.tscn")
##       # start drag at position 50,50 and drop it at 100,50
##       await runner.simulate_screen_touch_drag_drop(1, Vector2(50, 50), Vector2(100,50))
## [/codeblock]
@warning_ignore("unused_parameter")
func simulate_screen_touch_drag_drop(index: int, position: Vector2, drop_position: Vector2, time: float = 1.0, trans_type: Tween.TransitionType = Tween.TRANS_LINEAR) -> GdUnitSceneRunner:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Simulates a touch screen drag event to given position.[br]
## [member index] : The touch index in the case of a multi-touch event.[br]
## [member position] : The drag start position, indicating the drag position.[br]
@warning_ignore("unused_parameter")
func simulate_screen_touch_drag(index: int, position: Vector2) -> GdUnitSceneRunner:
	return self


## Returns the actual position of the touchscreen drag position by given index.
## [member index] : The touch index in the case of a multi-touch event.[br]
@warning_ignore("unused_parameter")
func get_screen_touch_drag_position(index: int) -> Vector2:
	return Vector2.ZERO


## Sets how fast or slow the scene simulation is processed (clock ticks versus the real).[br]
## It defaults to 1.0. A value of 2.0 means the game moves twice as fast as real life,
## whilst a value of 0.5 means the game moves at half the regular speed.


## Sets the time factor for the scene simulation.
## [member time_factor] : A float representing the simulation speed.[br]
## - Default is 1.0, meaning the simulation runs at normal speed.[br]
## - A value of 2.0 means the simulation runs twice as fast as real time.[br]
## - A value of 0.5 means the simulation runs at half the regular speed.[br]
@warning_ignore("unused_parameter")
func set_time_factor(time_factor: float = 1.0) -> GdUnitSceneRunner:
	return self


## Simulates scene processing for a certain number of frames.[br]
## [member frames] : amount of frames to process[br]
## [member delta_milli] : the time delta between a frame in milliseconds
@warning_ignore("unused_parameter")
func simulate_frames(frames: int, delta_milli: int = -1) -> GdUnitSceneRunner:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Simulates scene processing until the given signal is emitted by the scene.[br]
## [member signal_name] : the signal to stop the simulation[br]
## [member args] : optional signal arguments to be matched for stop[br]
@warning_ignore("unused_parameter")
func simulate_until_signal(
	signal_name: String,
	arg0: Variant = NO_ARG,
	arg1: Variant = NO_ARG,
	arg2: Variant = NO_ARG,
	arg3: Variant = NO_ARG,
	arg4: Variant = NO_ARG,
	arg5: Variant = NO_ARG,
	arg6: Variant = NO_ARG,
	arg7: Variant = NO_ARG,
	arg8: Variant = NO_ARG,
	arg9: Variant = NO_ARG) -> GdUnitSceneRunner:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Simulates scene processing until the given signal is emitted by the given object.[br]
## [member source] : the object that should emit the signal[br]
## [member signal_name] : the signal to stop the simulation[br]
## [member args] : optional signal arguments to be matched for stop
@warning_ignore("unused_parameter")
func simulate_until_object_signal(
	source: Object,
	signal_name: String,
	arg0: Variant = NO_ARG,
	arg1: Variant = NO_ARG,
	arg2: Variant = NO_ARG,
	arg3: Variant = NO_ARG,
	arg4: Variant = NO_ARG,
	arg5: Variant = NO_ARG,
	arg6: Variant = NO_ARG,
	arg7: Variant = NO_ARG,
	arg8: Variant = NO_ARG,
	arg9: Variant = NO_ARG) -> GdUnitSceneRunner:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Waits for all input events to be processed by flushing any buffered input events
## and then awaiting a full cycle of both the process and physics frames.[br]
## [br]
## This is typically used to ensure that any simulated or queued inputs are fully
## processed before proceeding with the next steps in the scene.[br]
## It's essential for reliable input simulation or when synchronizing logic based
## on inputs.[br]
##
## Usage Example:
## [codeblock]
## 	await await_input_processed()  # Ensure all inputs are processed before continuing
## [/codeblock]
func await_input_processed() -> void:
	if scene() != null and scene().process_mode != Node.PROCESS_MODE_DISABLED:
		Input.flush_buffered_events()
	await (Engine.get_main_loop() as SceneTree).process_frame
	await (Engine.get_main_loop() as SceneTree).physics_frame


## The await_func function pauses execution until a specified function in the scene returns a value.[br]
## It returns a [GdUnitFuncAssert], which provides a suite of assertion methods to verify the returned value.[br]
## [member func_name] : The name of the function to wait for.[br]
## [member args] : Optional function arguments
## [br]
## Usage Example:
## [codeblock]
## 	# Waits for 'calculate_score' function and verifies the result is equal to 100.
## 	await_func("calculate_score").is_equal(100)
## [/codeblock]
@warning_ignore("unused_parameter")
func await_func(func_name: String, args := []) -> GdUnitFuncAssert:
	return null



## The await_func_on function extends the functionality of await_func by allowing you to specify a source node within the scene.[br]
## It waits for a specified function on that node to return a value and returns a [GdUnitFuncAssert] object for assertions.[br]
## [member source] : The object where implements the function.[br]
## [member func_name] : The name of the function to wait for.[br]
## [member args] : optional function arguments
## [br]
## Usage Example:
## [codeblock]
## 	# Waits for 'calculate_score' function and verifies the result is equal to 100.
## 	var my_instance := ScoreCalculator.new()
## 	await_func(my_instance, "calculate_score").is_equal(100)
## [/codeblock]
@warning_ignore("unused_parameter")
func await_func_on(source: Object, func_name: String, args := []) -> GdUnitFuncAssert:
	return null


## Waits for the specified signal to be emitted by the scene. If the signal is not emitted within the given timeout, the operation fails.[br]
## [member signal_name] : The name of the signal to wait for[br]
## [member args] : The signal arguments as an array[br]
## [member timeout] : The maximum duration (in milliseconds) to wait for the signal to be emitted before failing
@warning_ignore("unused_parameter")
func await_signal(signal_name: String, args := [], timeout := 2000 ) -> void:
	await (Engine.get_main_loop() as SceneTree).process_frame
	pass


## Waits for the specified signal to be emitted by a particular source node. If the signal is not emitted within the given timeout, the operation fails.[br]
## [member source] : the object from which the signal is emitted[br]
## [member signal_name] : The name of the signal to wait for[br]
## [member args] : The signal arguments as an array[br]
## [member timeout] : tThe maximum duration (in milliseconds) to wait for the signal to be emitted before failing
@warning_ignore("unused_parameter")
func await_signal_on(source: Object, signal_name: String, args := [], timeout := 2000 ) -> void:
	pass


## Restores the scene window to a windowed mode and brings it to the foreground.[br]
## This ensures that the scene is visible and active during testing, making it easier to observe and interact with.
func move_window_to_foreground() -> GdUnitSceneRunner:
	return self


## Restores the scene window to a windowed mode and brings it to the foreground.[br]
## This ensures that the scene is visible and active during testing, making it easier to observe and interact with.
## @deprecated: Use [move_window_to_foreground] instead.
func maximize_view() -> GdUnitSceneRunner:
	return self


## Return the current value of the property with the name <name>.[br]
## [member name] : name of property[br]
## [member return] : the value of the property
@warning_ignore("unused_parameter")
func get_property(name: String) -> Variant:
	return null

## Set the  value <value> of the property with the name <name>.[br]
## [member name] : name of property[br]
## [member value] : value of property[br]
## [member return] : true|false depending on valid property name.
@warning_ignore("unused_parameter")
func set_property(name: String, value: Variant) -> bool:
	return false


## executes the function specified by <name> in the scene and returns the result.[br]
## [member name] : the name of the function to execute[br]
## [member args] : optional function arguments[br]
## [member return] : the function result
@warning_ignore("unused_parameter")
func invoke(
	name: String,
	arg0: Variant = NO_ARG,
	arg1: Variant = NO_ARG,
	arg2: Variant = NO_ARG,
	arg3: Variant = NO_ARG,
	arg4: Variant = NO_ARG,
	arg5: Variant = NO_ARG,
	arg6: Variant = NO_ARG,
	arg7: Variant = NO_ARG,
	arg8: Variant = NO_ARG,
	arg9: Variant = NO_ARG) -> Variant:
	return null


## Searches for the specified node with the name in the current scene and returns it, otherwise null.[br]
## [member name] : the name of the node to find[br]
## [member recursive] : enables/disables seraching recursive[br]
## [member return] : the node if find otherwise null
@warning_ignore("unused_parameter")
func find_child(name: String, recursive: bool = true, owned: bool = false) -> Node:
	return null


## Access to current running scene
func scene() -> Node:
	return null


================================================
FILE: addons/gdUnit4/src/GdUnitSceneRunner.gd.uid
================================================
uid://blpb5kd1mhqk4


================================================
FILE: addons/gdUnit4/src/GdUnitSignalAssert.gd
================================================
## An Assertion Tool to verify for emitted signals until a waiting time
class_name GdUnitSignalAssert
extends GdUnitAssert


## Verifies that given signal is emitted until waiting time
@warning_ignore("unused_parameter")
func is_emitted(name :String, args := []) -> GdUnitSignalAssert:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Verifies that given signal is NOT emitted until waiting time
@warning_ignore("unused_parameter")
func is_not_emitted(name :String, args := []) -> GdUnitSignalAssert:
	await (Engine.get_main_loop() as SceneTree).process_frame
	return self


## Verifies the signal exists checked the emitter
@warning_ignore("unused_parameter")
func is_signal_exists(name :String) -> GdUnitSignalAssert:
	return self


## Overrides the default failure message by given custom message.
@warning_ignore("unused_parameter")
func override_failure_message(message :String) -> GdUnitSignalAssert:
	return self


## Sets the assert signal timeout in ms, if the time over a failure is reported.[br]
## e.g.[br]
## do wait until 5s the instance has emitted the signal `signal_a`[br]
## [code]assert_signal(instance).wait_until(5000).is_emitted("signal_a")[/code]
@warning_ignore("unused_parameter")
func wait_until(timeout :int) -> GdUnitSignalAssert:
	return self


================================================
FILE: addons/gdUnit4/src/GdUnitSignalAssert.gd.uid
================================================
uid://bk4kqfkqlxokb


================================================
FILE: addons/gdUnit4/src/GdUnitStringAssert.gd
================================================
## An Assertion Tool to verify String values
class_name GdUnitStringAssert
extends GdUnitAssert


## Verifies that the current String is equal to the given one.
@warning_ignore("unused_parameter")
func is_equal(expected :Variant) -> GdUnitStringAssert:
	return self


## Verifies that the current String is equal to the given one, ignoring case considerations.
@warning_ignore("unused_parameter")
func is_equal_ignoring_case(expected :Variant) -> GdUnitStringAssert:
	return self


## Verifies that the current String is not equal to the given one.
@warning_ignore("unused_parameter")
func is_not_equal(expected :Variant) -> GdUnitStringAssert:
	return self


## Verifies that the current String is not equal to the given one, ignoring case considerations.
@warning_ignore("unused_parameter")
func is_not_equal_ignoring_case(expected :Variant) -> GdUnitStringAssert:
	return self


## Verifies that the current String is empty, it has a length of 0.
func is_empty() -> GdUnitStringAssert:
	return self


## Verifies that the current String is not empty, it has a length of minimum 1.
func is_not_empty() -> GdUnitStringAssert:
	return self


## Verifies that the current String contains the given String.
@warning_ignore("unused_parameter")
func contains(expected: String) -> GdUnitStringAssert:
	return self


## Verifies that the current String does not contain the given String.
@warning_ignore("unused_parameter")
func not_contains(expected: String) -> GdUnitStringAssert:
	return self


## Verifies that the current String does not contain the given String, ignoring case considerations.
@warning_ignore("unused_parameter")
func contains_ignoring_case(expected: String) -> GdUnitStringAssert:
	return self


## Verifies that the current String does not contain the given String, ignoring case considerations.
@warning_ignore("unused_parameter")
func not_contains_ignoring_case(expected: String) -> GdUnitStringAssert:
	return self


## Verifies that the current String starts with the given prefix.
@warning_ignore("unused_parameter")
func starts_with(expected: String) -> GdUnitStringAssert:
	return self


## Verifies that the current String ends with the given suffix.
@warning_ignore("unused_parameter")
func ends_with(expected: String) -> GdUnitStringAssert:
	return self


## Verifies that the current String has the expected length by used comparator.
@warning_ignore("unused_parameter")
func has_length(length: int, comparator: int = Comparator.EQUAL) -> GdUnitStringAssert:
	return self


================================================
FILE: addons/gdUnit4/src/GdUnitStringAssert.gd.uid
================================================
uid://cwp5ce5us8wek


================================================
FILE: addons/gdUnit4/src/GdUnitTestSuite.gd
================================================
## The main class for all GdUnit test suites[br]
## This class is the main class to implement your unit tests[br]
## You have to extend and implement your test cases as described[br]
## e.g MyTests.gd [br]
## [codeblock]
##    extends GdUnitTestSuite
##    # testcase
##    func test_case_a():
##       assert_that("value").is_equal("value")
## [/codeblock]
## @tutorial:  https://mikeschulze.github.io/gdUnit4/faq/test-suite/

@icon("res://addons/gdUnit4/src/ui/settings/logo.png")
class_name GdUnitTestSuite
extends Node

const NO_ARG :Variant = GdUnitConstants.NO_ARG

### internal runtime variables that must not be overwritten!!!
@warning_ignore("unused_private_class_variable")
var __is_skipped := false
@warning_ignore("unused_private_class_variable")
var __skip_reason :String = "Unknow."
var __active_test_case :String
var __awaiter := __gdunit_awaiter()


### We now load all used asserts and tool scripts into the cache according to the principle of "lazy loading"
### in order to noticeably reduce the loading time of the test suite.
# We go this hard way to increase the loading performance to avoid reparsing all the used scripts
# for more detailed info -> https://github.com/godotengine/godot/issues/67400
func __lazy_load(script_path :String) -> GDScript:
	return GdUnitAssertions.__lazy_load(script_path)


func __gdunit_assert() -> GDScript:
	return __lazy_load("res://addons/gdUnit4/src/asserts/GdUnitAssertImpl.gd")


func __gdunit_tools() -> GDScript:
	return __lazy_load("res://addons/gdUnit4/src/core/GdUnitTools.gd")


func __gdunit_file_access() -> GDScript:
	return __lazy_load("res://addons/gdUnit4/src/core/GdUnitFileAccess.gd")


func __gdunit_awaiter() -> Object:
	return __lazy_load("res://addons/gdUnit4/src/GdUnitAwaiter.gd").new()


func __gdunit_argument_matchers() -> GDScript:
	return __lazy_load("res://addons/gdUnit4/src/matchers/GdUnitArgumentMatchers.gd")


func __gdunit_object_interactions() -> GDScript:
	return __lazy_load("res://addons/gdUnit4/src/core/GdUnitObjectInteractions.gd")


## This function is called before a test suite starts[br]
## You can overwrite to prepare test data or initalizize necessary variables
func before() -> void:
	pass


## This function is called at least when a test suite is finished[br]
## You can overwrite to cleanup data created during test running
func after() -> void:
	pass


## This function is called before a test case starts[br]
## You can overwrite to prepare test case specific data
func before_test() -> void:
	pass


## This function is called after the test case is finished[br]
## You can overwrite to cleanup your test case specific data
func after_test() -> void:
	pass


func is_failure(_expected_failure :String = NO_ARG) -> bool:
	return Engine.get_meta("GD_TEST_FAILURE") if Engine.has_meta("GD_TEST_FAILURE") else false


func set_active_test_case(test_case :String) -> void:
	__active_test_case = test_case


# === Tools ====================================================================
# Mapps Godot error number to a readable error message. See at ERROR
# https://docs.godotengine.org/de/stable/classes/class_@globalscope.html#enum-globalscope-error
func error_as_string(error_number :int) -> String:
	return error_string(error_number)


## A litle helper to auto freeing your created objects after test execution
func auto_free(obj :Variant) -> Variant:
	var execution_context := GdUnitThreadManager.get_current_context().get_execution_context()

	assert(execution_context != null, "INTERNAL ERROR: The current execution_context is null! Please report this as bug.")
	return execution_context.register_auto_free(obj)


@warning_ignore("native_method_override")
func add_child(node :Node, force_readable_name := false, internal := Node.INTERNAL_MODE_DISABLED) -> void:
	super.add_child(node, force_readable_name, internal)
	var execution_context := GdUnitThreadManager.get_current_context().get_execution_context()
	if execution_context != null:
		execution_context.orphan_monitor_start()


## Discard the error message triggered by a timeout (interruption).[br]
## By default, an interrupted test is reported as an error.[br]
## This function allows you to change the message to Success when an interrupted error is reported.
func discard_error_interupted_by_timeout() -> void:
	@warning_ignore("unsafe_method_access")
	__gdunit_tools().register_expect_interupted_by_timeout(self, __active_test_case)


## Creates a new directory under the temporary directory *user://tmp*[br]
## Useful for storing data during test execution. [br]
## The directory is automatically deleted after test suite execution
func create_temp_dir(relative_path :String) -> String:
	@warning_ignore("unsafe_method_access")
	return __gdunit_file_access().create_temp_dir(relative_path)


## Deletes the temporary base directory[br]
## Is called automatically after each execution of the test suite
func clean_temp_dir() -> void:
	@warning_ignore("unsafe_method_access")
	__gdunit_file_access().clear_tmp()


## Creates a new file under the temporary directory *user://tmp* + <relative_path>[br]
## with given name <file_name> and given file <mode> (default = File.WRITE)[br]
## If success the returned File is automatically closed after the execution of the test suite
func create_temp_file(relative_path :String, file_name :String, mode := FileAccess.WRITE) -> FileAccess:
	@warning_ignore("unsafe_method_access")
	return __gdunit_file_access().create_temp_file(relative_path, file_name, mode)


## Reads a resource by given path <resource_path> into a PackedStringArray.
func resource_as_array(resource_path :String) -> PackedStringArray:
	@warning_ignore("unsafe_method_access")
	return __gdunit_file_access().resource_as_array(resource_path)


## Reads a resource by given path <resource_path> and returned the content as String.
func resource_as_string(resource_path :String) -> String:
	@warning_ignore("unsafe_method_access")
	return __gdunit_file_access().resource_as_string(resource_path)


## Reads a resource by given path <resource_path> and return Variand translated by str_to_var
func resource_as_var(resource_path :String) -> Variant:
	@warning_ignore("unsafe_method_access", "unsafe_cast")
	return str_to_var(__gdunit_file_access().resource_as_string(resource_path) as String)


## Waits for given signal is emited by the <source> until a specified timeout to fail[br]
## source: the object from which the signal is emitted[br]
## signal_name: signal name[br]
## args: the expected signal arguments as an array[br]
## timeout: the timeout in ms, default is set to 2000ms
func await_signal_on(source :Object, signal_name :String, args :Array = [], timeout :int = 2000) -> Variant:
	@warning_ignore("unsafe_method_access")
	return await __awaiter.await_signal_on(source, signal_name, args, timeout)


## Waits until the next idle frame
func await_idle_frame() -> void:
	@warning_ignore("unsafe_method_access")
	await __awaiter.await_idle_frame()


## Waits for for a given amount of milliseconds[br]
## example:[br]
## [codeblock]
##    # waits for 100ms
##    await await_millis(myNode, 100).completed
## [/codeblock][br]
## use this waiter and not `await get_tree().create_timer().timeout to prevent errors when a test case is timed out
func await_millis(timeout :int) -> void:
	@warning_ignore("unsafe_method_access")
	await __awaiter.await_millis(timeout)


## Creates a new scene runner to allow simulate interactions checked a scene.[br]
## The runner will manage the scene instance and release after the runner is released[br]
## example:[br]
## [codeblock]
##    # creates a runner by using a instanciated scene
##    var scene = load("res://foo/my_scne.tscn").instantiate()
##    var runner := scene_runner(scene)
##
##    # or simply creates a runner by using the scene resource path
##    var runner := scene_runner("res://foo/my_scne.tscn")
## [/codeblock]
func scene_runner(scene :Variant, verbose := false) -> GdUnitSceneRunner:
	return auto_free(__lazy_load("res://addons/gdUnit4/src/core/GdUnitSceneRunnerImpl.gd").new(scene, verbose))


# === Mocking  & Spy ===========================================================

## do return a default value for primitive types or null
const RETURN_DEFAULTS = GdUnitMock.RETURN_DEFAULTS
## do call the real implementation
const CALL_REAL_FUNC = GdUnitMock.CALL_REAL_FUNC
## do return a default value for primitive types and a fully mocked value for Object types
## builds full deep mocked object
const RETURN_DEEP_STUB = GdUnitMock.RETURN_DEEP_STUB


## Creates a mock for given class name
func mock(clazz :Variant, mock_mode := RETURN_DEFAULTS) -> Variant:
	@warning_ignore("unsafe_method_access")
	return __lazy_load("res://addons/gdUnit4/src/mocking/GdUnitMockBuilder.gd").build(clazz, mock_mode)


## Creates a spy checked given object instance
func spy(instance :Variant) -> Variant:
	@warning_ignore("unsafe_method_access")
	return __lazy_load("res://addons/gdUnit4/src/spy/GdUnitSpyBuilder.gd").build(instance)


## Configures a return value for the specified function and used arguments.[br]
## [b]Example:
## 	[codeblock]
## 		# overrides the return value of myMock.is_selected() to false
## 		do_return(false).on(myMock).is_selected()
## 	[/codeblock]
func do_return(value :Variant) -> GdUnitMock:
	return GdUnitMock.new(value)


## Verifies certain behavior happened at least once or exact number of times
func verify(obj :Variant, times := 1) -> Variant:
	@warning_ignore("unsafe_method_access")
	return __gdunit_object_interactions().verify(obj, times)


## Verifies no interactions is happen checked this mock or spy
func verify_no_interactions(obj :Variant) -> GdUnitAssert:
	@warning_ignore("unsafe_method_access")
	return __gdunit_object_interactions().verify_no_interactions(obj)


## Verifies the given mock or spy has any unverified interaction.
func verify_no_more_interactions(obj :Variant) -> GdUnitAssert:
	@warning_ignore("unsafe_method_access")
	return __gdunit_object_interactions().verify_no_more_interactions(obj)


## Resets the saved function call counters checked a mock or spy
func reset(obj :Variant) -> void:
	@warning_ignore("unsafe_method_access")
	__gdunit_object_interactions().reset(obj)


## Starts monitoring the specified source to collect all transmitted signals.[br]
## The collected signals can then be checked with 'assert_signal'.[br]
## By default, the specified source is automatically released when the test ends.
## You can control this behavior by setting auto_free to false if you do not want the source to be automatically freed.[br]
## Usage:
##	[codeblock]
##		var emitter := monitor_signals(MyEmitter.new())
##		# call the function to send the signal
##		emitter.do_it()
##		# verify the signial is emitted
##		await assert_signal(emitter).is_emitted('my_signal')
##	[/codeblock]
func monitor_signals(source :Object, _auto_free := true) -> Object:
	@warning_ignore("unsafe_method_access")
	__lazy_load("res://addons/gdUnit4/src/core/thread/GdUnitThreadManager.gd")\
		.get_current_context()\
		.get_signal_collector()\
		.register_emitter(source)
	return auto_free(source) if _auto_free else source


# === Argument matchers ========================================================
## Argument matcher to match any argument
func any() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().any()


## Argument matcher to match any boolean value
func any_bool() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_BOOL)


## Argument matcher to match any integer value
func any_int() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_INT)


## Argument matcher to match any float value
func any_float() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_FLOAT)


## Argument matcher to match any string value
func any_string() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_STRING)


## Argument matcher to match any Color value
func any_color() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_COLOR)


## Argument matcher to match any Vector typed value
func any_vector() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_types([
		TYPE_VECTOR2,
		TYPE_VECTOR2I,
		TYPE_VECTOR3,
		TYPE_VECTOR3I,
		TYPE_VECTOR4,
		TYPE_VECTOR4I,
	])


## Argument matcher to match any Vector2 value
func any_vector2() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_VECTOR2)


## Argument matcher to match any Vector2i value
func any_vector2i() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_VECTOR2I)


## Argument matcher to match any Vector3 value
func any_vector3() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_VECTOR3)


## Argument matcher to match any Vector3i value
func any_vector3i() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_VECTOR3I)


## Argument matcher to match any Vector4 value
func any_vector4() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_VECTOR4)


## Argument matcher to match any Vector3i value
func any_vector4i() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_VECTOR4I)


## Argument matcher to match any Rect2 value
func any_rect2() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_RECT2)


## Argument matcher to match any Plane value
func any_plane() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_PLANE)


## Argument matcher to match any Quaternion value
func any_quat() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_QUATERNION)


## Argument matcher to match any AABB value
func any_aabb() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_AABB)


## Argument matcher to match any Basis value
func any_basis() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_BASIS)


## Argument matcher to match any Transform2D value
func any_transform_2d() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_TRANSFORM2D)


## Argument matcher to match any Transform3D value
func any_transform_3d() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_TRANSFORM3D)


## Argument matcher to match any NodePath value
func any_node_path() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_NODE_PATH)


## Argument matcher to match any RID value
func any_rid() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_RID)


## Argument matcher to match any Object value
func any_object() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_OBJECT)


## Argument matcher to match any Dictionary value
func any_dictionary() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_DICTIONARY)


## Argument matcher to match any Array value
func any_array() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_ARRAY)


## Argument matcher to match any PackedByteArray value
func any_packed_byte_array() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_PACKED_BYTE_ARRAY)


## Argument matcher to match any PackedInt32Array value
func any_packed_int32_array() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_PACKED_INT32_ARRAY)


## Argument matcher to match any PackedInt64Array value
func any_packed_int64_array() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_PACKED_INT64_ARRAY)


## Argument matcher to match any PackedFloat32Array value
func any_packed_float32_array() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_PACKED_FLOAT32_ARRAY)


## Argument matcher to match any PackedFloat64Array value
func any_packed_float64_array() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_PACKED_FLOAT64_ARRAY)


## Argument matcher to match any PackedStringArray value
func any_packed_string_array() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_PACKED_STRING_ARRAY)


## Argument matcher to match any PackedVector2Array value
func any_packed_vector2_array() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_PACKED_VECTOR2_ARRAY)


## Argument matcher to match any PackedVector3Array value
func any_packed_vector3_array() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_PACKED_VECTOR3_ARRAY)


## Argument matcher to match any PackedColorArray value
func any_packed_color_array() -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().by_type(TYPE_PACKED_COLOR_ARRAY)


## Argument matcher to match any instance of given class
func any_class(clazz :Object) -> GdUnitArgumentMatcher:
	@warning_ignore("unsafe_method_access")
	return __gdunit_argument_matchers().any_class(clazz)


# === value extract utils ======================================================
## Builds an extractor by given function name and optional arguments
func extr(func_name :String, args := Array()) -> GdUnitValueExtractor:
	return __lazy_load("res://addons/gdUnit4/src/extractors/GdUnitFuncValueExtractor.gd").new(func_name, args)


## Constructs a tuple by given arguments
func tuple(arg0 :Variant,
	arg1 :Variant=NO_ARG,
	arg2 :Variant=NO_ARG,
	arg3 :Variant=NO_ARG,
	arg4 :Variant=NO_ARG,
	arg5 :Variant=NO_ARG,
	arg6 :Variant=NO_ARG,
	arg7 :Variant=NO_ARG,
	arg8 :Variant=NO_ARG,
	arg9 :Variant=NO_ARG) -> GdUnitTuple:
	return GdUnitTuple.new(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)


# === Asserts ==================================================================

## The common assertion tool to verify values.
## It checks the given value by type to fit to the best assert
func assert_that(current :Variant) -> GdUnitAssert:
	match typeof(current):
		TYPE_BOOL:
			return assert_bool(current)
		TYPE_INT:
			return assert_int(current)
		TYPE_FLOAT:
			return assert_float(current)
		TYPE_STRING:
			return assert_str(current)
		TYPE_VECTOR2, TYPE_VECTOR2I, TYPE_VECTOR3, TYPE_VECTOR3I, TYPE_VECTOR4, TYPE_VECTOR4I:
			return assert_vector(current, false)
		TYPE_DICTIONARY:
			return assert_dict(current)
		TYPE_ARRAY, TYPE_PACKED_BYTE_ARRAY, TYPE_PACKED_INT32_ARRAY, TYPE_PACKED_INT64_ARRAY,\
		TYPE_PACKED_FLOAT32_ARRAY, TYPE_PACKED_FLOAT64_ARRAY, TYPE_PACKED_STRING_ARRAY,\
		TYPE_PACKED_VECTOR2_ARRAY, TYPE_PACKED_VECTOR3_ARRAY, TYPE_PACKED_COLOR_ARRAY:
			return assert_array(current, false)
		TYPE_OBJECT, TYPE_NIL:
			return assert_object(current)
		_:
			return __gdunit_assert().new(current)


## An assertion tool to verify boolean values.
func assert_bool(current :Variant) -> GdUnitBoolAssert:
	return __lazy_load("res://addons/gdUnit4/src/asserts/GdUnitBoolAssertImpl.gd").new(current)


## An assertion tool to verify String values.
func assert_str(current :Variant) -> GdUnitStringAssert:
	return __lazy_load("res://addons/gdUnit4/src/asserts/GdUnitStringAssertImpl.gd").new(current)


## An assertion tool to verify integer values.
func assert_int(current :Variant) -> GdUnitIntAssert:
	return __lazy_load("res://addons/gdUnit4/src/asserts/GdUnitIntAssertImpl.gd").new(current)


## An assertion tool to verify float values.
func assert_float(current :Variant) -> GdUnitFloatAssert:
	return __lazy_load("res://addons/gdUnit4/src/asserts/GdUnitFloatAssertImpl.gd").new(current)


## An assertion tool to verify Vector values.[br]
## This assertion supports all vector types.[br]
## Usage:
##     [codeblock]
##		assert_vector(Vector2(1.2, 1.000001)).is_equal(Vector2(1.2, 1.000001))
##     [/codeblock]
func assert_vector(current :Variant, type_check := true) -> GdUnitVectorAssert:
	return __lazy_load("res://addons/gdUnit4/src/asserts/GdUnitVectorAssertImpl.gd").new(current, type_check)


## An assertion tool to verify arrays.
func assert_array(current :Variant, type_check := true) -> GdUnitArrayAssert:
	return __lazy_load("res://addons/gdUnit4/src/asserts/GdUnitArrayAssertImpl.gd").new(current, type_check)


## An assertion tool to verify dictionaries.
func assert_dict(current :Variant) -> GdUnitDictionaryAssert:
	return __lazy_load("res://addons/gdUnit4/src/asserts/GdUnitDictionaryAssertImpl.gd").new(current)


## An assertion tool to verify FileAccess.
func assert_file(current :Variant) -> GdUnitFileAssert:
	return __lazy_load("res://addons/gdUnit4/src/asserts/GdUnitFileAssertImpl.gd").new(current)


## An assertion tool to verify Objects.
func assert_object(current :Variant) -> GdUnitObjectAssert:
	return __lazy_load("res://addons/gdUnit4/src/asserts/GdUnitObjectAssertImpl.gd").new(current)


func assert_result(current :Variant) -> GdUnitResultAssert:
	return __lazy_load("res://addons/gdUnit4/src/asserts/GdUnitResultAssertImpl.gd").new(current)


## An assertion tool that waits until a certain time for an expected function return value
func assert_func(instance :Object, func_name :String, args := Array()) -> GdUnitFuncAssert:
	return __lazy_load("res://addons/gdUnit4/src/asserts/GdUnitFuncAssertImpl.gd").new(instance, func_name, args)


## An Assertion Tool to verify for emitted signals until a certain time.
func assert_signal(instance :Object) -> GdUnitSignalAssert:
	return __lazy_load("res://addons/gdUnit4/src/asserts/GdUnitSignalAssertImpl.gd").new(instance)


## An assertion tool to test for failing assertions.[br]
## This assert is only designed for internal use to verify failing asserts working as expected.[br]
## Usage:
##     [codeblock]
##		assert_failure(func(): assert_bool(true).is_not_equal(true)) \
##		    .has_message("Expecting:\n 'true'\n not equal to\n 'true'")
##     [/codeblock]
func assert_failure(assertion :Callable) -> GdUnitFailureAssert:
	@warning_ignore("unsafe_method_access")
	return __lazy_load("res://addons/gdUnit4/src/asserts/GdUnitFailureAssertImpl.gd").new().execute(assertion)


## An assertion tool to test for failing assertions.[br]
## This assert is only designed for internal use to verify failing asserts working as expected.[br]
## Usage:
##     [codeblock]
##		await assert_failure_await(func(): assert_bool(true).is_not_equal(true)) \
##		    .has_message("Expecting:\n 'true'\n not equal to\n 'true'")
##     [/codeblock]
func assert_failure_await(assertion :Callable) -> GdUnitFailureAssert:
	@warning_ignore("unsafe_method_access")
	return await __lazy_load("res://addons/gdUnit4/src/asserts/GdUnitFailureAssertImpl.gd").new().execute_and_await(assertion)


## An assertion tool to verify for Godot errors.[br]
## You can use to verify for certain Godot erros like failing assertions, push_error, push_warn.[br]
## Usage:
##     [codeblock]
##		# tests no error was occured during execution the code
##		await assert_error(func (): return 0 )\
##		    .is_success()
##
##		# tests an push_error('test error') was occured during execution the code
##		await assert_error(func (): push_error('test error') )\
##		    .is_push_error('test error')
##     [/codeblock]
func assert_error(current :Callable) -> GdUnitGodotErrorAssert:
	return __lazy_load("res://addons/gdUnit4/src/asserts/GdUnitGodotErrorAssertImpl.gd").new(current)


func assert_not_yet_implemented() -> void:
	@warning_ignore("unsafe_method_access")
	__gdunit_assert().new(null).do_fail()


func fail(message :String) -> void:
	@warning_ignore("unsafe_method_access")
	__gdunit_assert().new(null).report_error(message)


# --- internal stuff do not override!!!
func ResourcePath() -> String:
	return get_script().resource_path


================================================
FILE: addons/gdUnit4/src/GdUnitTestSuite.gd.uid
================================================
uid://bbsow5k2y0q4p


================================================
FILE: addons/gdUnit4/src/GdUnitTuple.gd
================================================
## A tuple implementation to hold two or many values
class_name GdUnitTuple
extends RefCounted

const NO_ARG :Variant = GdUnitConstants.NO_ARG

var __values :Array = Array()


func _init(arg0:Variant,
	arg1 :Variant=NO_ARG,
	arg2 :Variant=NO_ARG,
	arg3 :Variant=NO_ARG,
	arg4 :Variant=NO_ARG,
	arg5 :Variant=NO_ARG,
	arg6 :Variant=NO_ARG,
	arg7 :Variant=NO_ARG,
	arg8 :Variant=NO_ARG,
	arg9 :Variant=NO_ARG) -> void:
	__values = GdArrayTools.filter_value([arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9], NO_ARG)


func values() -> Array:
	return __values


func _to_string() -> String:
	return "tuple(%s)" % str(__values)


================================================
FILE: addons/gdUnit4/src/GdUnitTuple.gd.uid
================================================
uid://cwcalyadq4276


================================================
FILE: addons/gdUnit4/src/GdUnitValueExtractor.gd
================================================
## This is the base interface for value extraction
class_name GdUnitValueExtractor
extends RefCounted


## Extracts a value by given implementation
func extract_value(value :Variant) -> Variant:
	push_error("Uninplemented func 'extract_value'")
	return value


================================================
FILE: addons/gdUnit4/src/GdUnitValueExtractor.gd.uid
================================================
uid://dd6wo43cc7s5x


================================================
FILE: addons/gdUnit4/src/GdUnitVectorAssert.gd
================================================
## An Assertion Tool to verify Vector values
class_name GdUnitVectorAssert
extends GdUnitAssert


## Verifies that the current value is equal to expected one.
@warning_ignore("unused_parameter")
func is_equal(expected :Variant) -> GdUnitVectorAssert:
	return self


## Verifies that the current value is not equal to expected one.
@warning_ignore("unused_parameter")
func is_not_equal(expected :Variant) -> GdUnitVectorAssert:
	return self


## Verifies that the current and expected value are approximately equal.
@warning_ignore("unused_parameter", "shadowed_global_identifier")
func is_equal_approx(expected :Variant, approx :Variant) -> GdUnitVectorAssert:
	return self


## Verifies that the current value is less than the given one.
@warning_ignore("unused_parameter")
func is_less(expected :Variant) -> GdUnitVectorAssert:
	return self


## Verifies that the current value is less than or equal the given one.
@warning_ignore("unused_parameter")
func is_less_equal(expected :Variant) -> GdUnitVectorAssert:
	return self


## Verifies that the current value is greater than the given one.
@warning_ignore("unused_parameter")
func is_greater(expected :Variant) -> GdUnitVectorAssert:
	return self


## Verifies that the current value is greater than or equal the given one.
@warning_ignore("unused_parameter")
func is_greater_equal(expected :Variant) -> GdUnitVectorAssert:
	return self


## Verifies that the current value is between the given boundaries (inclusive).
@warning_ignore("unused_parameter")
func is_between(from :Variant, to :Variant) -> GdUnitVectorAssert:
	return self


## Verifies that the current value is not between the given boundaries (inclusive).
@warning_ignore("unused_parameter")
func is_not_between(from :Variant, to :Variant) -> GdUnitVectorAssert:
	return self


================================================
FILE: addons/gdUnit4/src/GdUnitVectorAssert.gd.uid
================================================
uid://d0jl2n5k6xvfn


================================================
FILE: addons/gdUnit4/src/asserts/CallBackValueProvider.gd
================================================
# a value provider unsing a callback to get `next` value from a certain function
class_name CallBackValueProvider
extends ValueProvider

var _cb :Callable
var _args :Array


func _init(instance :Object, func_name :String, args :Array = Array(), force_error := true) -> void:
	_cb = Callable(instance, func_name);
	_args = args
	if force_error and not _cb.is_valid():
		push_error("Can't find function '%s' checked instance %s" % [func_name, instance])


func get_value() -> Variant:
	if not _cb.is_valid():
		return null
	if _args.is_empty():
		return await _cb.call()
	return await _cb.callv(_args)


func dispose() -> void:
	_cb = Callable()


================================================
FILE: addons/gdUnit4/src/asserts/CallBackValueProvider.gd.uid
================================================
uid://djwh83x3xq1qa


================================================
FILE: addons/gdUnit4/src/asserts/DefaultValueProvider.gd
================================================
# default value provider, simple returns the initial value
class_name DefaultValueProvider
extends ValueProvider

var _value: Variant


func _init(value: Variant) -> void:
	_value = value


func get_value() -> Variant:
	return _value


================================================
FILE: addons/gdUnit4/src/asserts/DefaultValueProvider.gd.uid
================================================
uid://b0an8wdbprin0


================================================
FILE: addons/gdUnit4/src/asserts/GdAssertMessages.gd
================================================
class_name GdAssertMessages
extends Resource

const WARN_COLOR = "#EFF883"
const ERROR_COLOR = "#CD5C5C"
const VALUE_COLOR = "#1E90FF"
const SUB_COLOR :=  Color(1, 0, 0, .3)
const ADD_COLOR :=  Color(0, 1, 0, .3)


static func format_dict(value :Variant) -> String:
	if not value is Dictionary:
		return str(value)

	var dict_value: Dictionary = value
	if dict_value.is_empty():
		return "{ }"
	var as_rows := var_to_str(value).split("\n")
	for index in range( 1, as_rows.size()-1):
		as_rows[index] = "	" + as_rows[index]
	as_rows[-1] = "  " + as_rows[-1]
	return "\n".join(as_rows)


# improved version of InputEvent as text
static func input_event_as_text(event :InputEvent) -> String:
	var text := ""
	if event is InputEventKey:
		var key_event := event as InputEventKey
		text += "InputEventKey : key='%s', pressed=%s, keycode=%d, physical_keycode=%s" % [
					event.as_text(), key_event.pressed, key_event.keycode, key_event.physical_keycode]
	else:
		text += event.as_text()
	if event is InputEventMouse:
		var mouse_event := event as InputEventMouse
		text += ", global_position %s" % mouse_event.global_position
	if event is InputEventWithModifiers:
		var mouse_event := event as InputEventWithModifiers
		text += ", shift=%s, alt=%s, control=%s, meta=%s, command=%s" % [
					mouse_event.shift_pressed,
					mouse_event.alt_pressed,
					mouse_event.ctrl_pressed,
					mouse_event.meta_pressed,
					mouse_event.command_or_control_autoremap]
	return text


static func _colored_string_div(characters :String) -> String:
	return colored_array_div(characters.to_utf8_buffer())


static func colored_array_div(characters :PackedByteArray) -> String:
	if characters.is_empty():
		return "<empty>"
	var result := PackedByteArray()
	var index := 0
	var missing_chars := PackedByteArray()
	var additional_chars := PackedByteArray()

	while index < characters.size():
		var character := characters[index]
		match character:
			GdDiffTool.DIV_ADD:
				index += 1
				@warning_ignore("return_value_discarded")
				additional_chars.append(characters[index])
			GdDiffTool.DIV_SUB:
				index += 1
				@warning_ignore("return_value_discarded")
				missing_chars.append(characters[index])
			_:
				if not missing_chars.is_empty():
					result.append_array(format_chars(missing_chars, SUB_COLOR))
					missing_chars = PackedByteArray()
				if not additional_chars.is_empty():
					result.append_array(format_chars(additional_chars, ADD_COLOR))
					additional_chars = PackedByteArray()
				@warning_ignore("return_value_discarded")
				result.append(character)
		index += 1

	result.append_array(format_chars(missing_chars, SUB_COLOR))
	result.append_array(format_chars(additional_chars, ADD_COLOR))
	return result.get_string_from_utf8()


static func _typed_value(value :Variant) -> String:
	return GdDefaultValueDecoder.decode(value)


static func _warning(error :String) -> String:
	return "[color=%s]%s[/color]" % [WARN_COLOR, error]


static func _error(error :String) -> String:
	return "[color=%s]%s[/color]" % [ERROR_COLOR, error]


static func _nerror(number :Variant) -> String:
	match typeof(number):
		TYPE_INT:
			return "[color=%s]%d[/color]" % [ERROR_COLOR, number]
		TYPE_FLOAT:
			return "[color=%s]%f[/color]" % [ERROR_COLOR, number]
		_:
			return "[color=%s]%s[/color]" % [ERROR_COLOR, str(number)]


static func _colored_value(value :Variant) -> String:
	match typeof(value):
		TYPE_STRING, TYPE_STRING_NAME:
			return "'[color=%s]%s[/color]'" % [VALUE_COLOR, _colored_string_div(str(value))]
		TYPE_INT:
			return "'[color=%s]%d[/color]'" % [VALUE_COLOR, value]
		TYPE_FLOAT:
			return "'[color=%s]%s[/color]'" % [VALUE_COLOR, _typed_value(value)]
		TYPE_COLOR:
			return "'[color=%s]%s[/color]'" % [VALUE_COLOR, _typed_value(value)]
		TYPE_OBJECT:
			if value == null:
				return "'[color=%s]<null>[/color]'" % [VALUE_COLOR]
			if value is InputEvent:
				var ie: InputEvent = value
				return "[color=%s]<%s>[/color]" % [VALUE_COLOR, input_event_as_text(ie)]
			var obj_value: Object = value
			if obj_value.has_method("_to_string"):
				return "[color=%s]<%s>[/color]" % [VALUE_COLOR, str(value)]
			return "[color=%s]<%s>[/color]" % [VALUE_COLOR, obj_value.get_class()]
		TYPE_DICTIONARY:
			return "'[color=%s]%s[/color]'" % [VALUE_COLOR, format_dict(value)]
		_:
			if GdArrayTools.is_array_type(value):
				return "'[color=%s]%s[/color]'" % [VALUE_COLOR, _typed_value(value)]
			return "'[color=%s]%s[/color]'" % [VALUE_COLOR, value]



static func _index_report_as_table(index_reports :Array) -> String:
	var table := "[table=3]$cells[/table]"
	var header := "[cell][right][b]$text[/b][/right]\t[/cell]"
	var cell := "[cell][right]$text[/right]\t[/cell]"
	var cells := header.replace("$text", "Index") + header.replace("$text", "Current") + header.replace("$text", "Expected")
	for report :Variant in index_reports:
		var index :String = str(report["index"])
		var current :String = str(report["current"])
		var expected :String = str(report["expected"])
		cells += cell.replace("$text", index) + cell.replace("$text", current) + cell.replace("$text", expected)
	return table.replace("$cells", cells)


static func orphan_detected_on_suite_setup(count :int) -> String:
	return "%s\n Detected <%d> orphan nodes during test suite setup stage! [b]Check before() and after()![/b]" % [
		_warning("WARNING:"), count]


static func orphan_detected_on_test_setup(count :int) -> String:
	return "%s\n Detected <%d> orphan nodes during test setup! [b]Check before_test() and after_test()![/b]" % [
		_warning("WARNING:"), count]


static func orphan_detected_on_test(count :int) -> String:
	return "%s\n Detected <%d> orphan nodes during test execution!" % [
		_warning("WARNING:"), count]


static func fuzzer_interuped(iterations: int, error: String) -> String:
	return "%s %s %s\n %s" % [
		_error("Found an error after"),
		_colored_value(iterations + 1),
		_error("test iterations"),
		error]


static func test_timeout(timeout :int) -> String:
	return "%s\n %s" % [_error("Timeout !"), _colored_value("Test timed out after %s" %  LocalTime.elapsed(timeout))]


# gdlint:disable = mixed-tabs-and-spaces
static func test_suite_skipped(hint :String, skip_count :int) -> String:
	return """
		%s
		  Skipped %s tests
		  Reason: %s
		""".dedent().trim_prefix("\n")\
		% [_error("The Entire test-suite is skipped!"), _colored_value(skip_count), _colored_value(hint)]


static func test_skipped(hint :String) -> String:
	return """
		%s
		  Reason: %s
		""".dedent().trim_prefix("\n")\
		% [_error("This test is skipped!"), _colored_value(hint)]


static func error_not_implemented() -> String:
	return _error("Test not implemented!")


static func error_is_null(current :Variant) -> String:
	return "%s %s but was %s" % [_error("Expecting:"), _colored_value(null), _colored_value(current)]


static func error_is_not_null() -> String:
	return "%s %s" % [_error("Expecting: not to be"), _colored_value(null)]


static func error_equal(current :Variant, expected :Variant, index_reports :Array = []) -> String:
	var report := """
		%s
		 %s
		 but was
		 %s""".dedent().trim_prefix("\n") % [_error("Expecting:"), _colored_value(expected), _colored_value(current)]
	if not index_reports.is_empty():
		report += "\n\n%s\n%s" % [_error("Differences found:"), _index_report_as_table(index_reports)]
	return report


static func error_not_equal(current :Variant, expected :Variant) -> String:
	return "%s\n %s\n not equal to\n %s" % [_error("Expecting:"), _colored_value(expected), _colored_value(current)]


static func error_not_equal_case_insensetiv(current :Variant, expected :Variant) -> String:
	return "%s\n %s\n not equal to (case insensitiv)\n %s" % [
			_error("Expecting:"), _colored_value(expected), _colored_value(current)]


static func error_is_empty(current :Variant) -> String:
	return "%s\n must be empty but was\n %s" % [_error("Expecting:"), _colored_value(current)]


static func error_is_not_empty() -> String:
	return "%s\n must not be empty" % [_error("Expecting:")]


static func error_is_same(current :Variant, expected :Variant) -> String:
	return "%s\n %s\n to refer to the same object\n %s" % [_error("Expecting:"), _colored_value(expected), _colored_value(current)]


@warning_ignore("unused_parameter")
static func error_not_same(_current :Variant, expected :Variant) -> String:
	return "%s\n %s" % [_error("Expecting not same:"), _colored_value(expected)]


static func error_not_same_error(current :Variant, expected :Variant) -> String:
	return "%s\n %s\n but was\n %s" % [_error("Expecting error message:"), _colored_value(expected), _colored_value(current)]


static func error_is_instanceof(current: GdUnitResult, expected :GdUnitResult) -> String:
	return "%s\n %s\n But it was %s" % [_error("Expected instance of:"),\
		_colored_value(expected.or_else(null)), _colored_value(current.or_else(null))]


# -- Boolean Assert specific messages -----------------------------------------------------
static func error_is_true(current :Variant) -> String:
	return "%s %s but is %s" % [_error("Expecting:"), _colored_value(true), _colored_value(current)]


static func error_is_false(current :Variant) -> String:
	return "%s %s but is %s" % [_error("Expecting:"), _colored_value(false), _colored_value(current)]


# - Integer/Float Assert specific messages -----------------------------------------------------

static func error_is_even(current :Variant) -> String:
	return "%s\n %s must be even" % [_error("Expecting:"), _colored_value(current)]


static func error_is_odd(current :Variant) -> String:
	return "%s\n %s must be odd" % [_error("Expecting:"), _colored_value(current)]


static func error_is_negative(current :Variant) -> String:
	return "%s\n %s be negative" % [_error("Expecting:"), _colored_value(current)]


static func error_is_not_negative(current :Variant) -> String:
	return "%s\n %s be not negative" % [_error("Expecting:"), _colored_value(current)]


static func error_is_zero(current :Variant) -> String:
	return "%s\n equal to 0 but is %s" % [_error("Expecting:"), _colored_value(current)]


static func error_is_not_zero() -> String:
	return "%s\n not equal to 0" % [_error("Expecting:")]


static func error_is_wrong_type(current_type :Variant.Type, expected_type :Variant.Type) -> String:
	return "%s\n Expecting type %s but is %s" % [
		_error("Unexpected type comparison:"),
		_colored_value(GdObjects.type_as_string(current_type)),
		_colored_value(GdObjects.type_as_string(expected_type))]


static func error_is_value(operation :int, current :Variant, expected :Variant, expected2 :Variant = null) -> String:
	match operation:
		Comparator.EQUAL:
			return "%s\n %s but was '%s'" % [_error("Expecting:"), _colored_value(expected), _nerror(current)]
		Comparator.LESS_THAN:
			return "%s\n %s but was '%s'" % [_error("Expecting to be less than:"), _colored_value(expected), _nerror(current)]
		Comparator.LESS_EQUAL:
			return "%s\n %s but was '%s'" % [_error("Expecting to be less than or equal:"), _colored_value(expected), _nerror(current)]
		Comparator.GREATER_THAN:
			return "%s\n %s but was '%s'" % [_error("Expecting to be greater than:"), _colored_value(expected), _nerror(current)]
		Comparator.GREATER_EQUAL:
			return "%s\n %s but was '%s'" % [_error("Expecting to be greater than or equal:"), _colored_value(expected), _nerror(current)]
		Comparator.BETWEEN_EQUAL:
			return "%s\n %s\n in range between\n %s <> %s" % [
					_error("Expecting:"), _colored_value(current), _colored_value(expected), _colored_value(expected2)]
		Comparator.NOT_BETWEEN_EQUAL:
			return "%s\n %s\n not in range between\n %s <> %s" % [
					_error("Expecting:"), _colored_value(current), _colored_value(expected), _colored_value(expected2)]
	return "TODO create expected message"


static func error_is_in(current :Variant, expected :Array) -> String:
	return "%s\n %s\n is in\n %s" % [_error("Expecting:"), _colored_value(current), _colored_value(str(expected))]


static func error_is_not_in(current :Variant, expected :Array) -> String:
	return "%s\n %s\n is not in\n %s" % [_error("Expecting:"), _colored_value(current), _colored_value(str(expected))]


# - StringAssert ---------------------------------------------------------------------------------
static func error_equal_ignoring_case(current :Variant, expected :Variant) -> String:
	return "%s\n %s\n but was\n %s (ignoring case)" % [_error("Expecting:"), _colored_value(expected), _colored_value(current)]


static func error_contains(current :Variant, expected :Variant) -> String:
	return "%s\n %s\n do contains\n %s" % [_error("Expecting:"), _colored_value(current), _colored_value(expected)]


static func error_not_contains(current :Variant, expected :Variant) -> String:
	return "%s\n %s\n not do contain\n %s" % [_error("Expecting:"), _colored_value(current), _colored_value(expected)]


static func error_contains_ignoring_case(current :Variant, expected :Variant) -> String:
	return "%s\n %s\n contains\n %s\n (ignoring case)" % [_error("Expecting:"), _colored_value(current), _colored_value(expected)]


static func error_not_contains_ignoring_case(current :Variant, expected :Variant) -> String:
	return "%s\n %s\n not do contains\n %s\n (ignoring case)" % [_error("Expecting:"), _colored_value(current), _colored_value(expected)]


static func error_starts_with(current :Variant, expected :Variant) -> String:
	return "%s\n %s\n to start with\n %s" % [_error("Expecting:"), _colored_value(current), _colored_value(expected)]


static func error_ends_with(current :Variant, expected :Variant) -> String:
	return "%s\n %s\n to end with\n %s" % [_error("Expecting:"), _colored_value(current), _colored_value(expected)]


static func error_has_length(current :Variant, expected: int, compare_operator :int) -> String:
	@warning_ignore("unsafe_method_access")
	var current_length :Variant = current.length() if current != null else null
	match compare_operator:
		Comparator.EQUAL:
			return "%s\n %s but was '%s' in\n %s" % [
					_error("Expecting size:"), _colored_value(expected), _nerror(current_length), _colored_value(current)]
		Comparator.LESS_THAN:
			return "%s\n %s but was '%s' in\n %s" % [
					_error("Expecting size to be less than:"), _colored_value(expected), _nerror(current_length), _colored_value(current)]
		Comparator.LESS_EQUAL:
			return "%s\n %s but was '%s' in\n %s" % [
					_error("Expecting size to be less than or equal:"), _colored_value(expected),
					_nerror(current_length), _colored_value(current)]
		Comparator.GREATER_THAN:
			return "%s\n %s but was '%s' in\n %s" % [
					_error("Expecting size to be greater than:"), _colored_value(expected),
					_nerror(current_length), _colored_value(current)]
		Comparator.GREATER_EQUAL:
			return "%s\n %s but was '%s' in\n %s" % [
					_error("Expecting size to be greater than or equal:"), _colored_value(expected),
					_nerror(current_length), _colored_value(current)]
	return "TODO create expected message"


# - ArrayAssert specific messgaes ---------------------------------------------------

static func error_arr_contains(current: Variant, expected: Variant, not_expect: Variant, not_found: Variant, by_reference: bool) -> String:
	var failure_message := "Expecting contains SAME elements:" if by_reference else "Expecting contains elements:"
	var error := "%s\n %s\n do contains (in any order)\n %s" % [
					_error(failure_message), _colored_value(current), _colored_value(expected)]
	if not is_empty(not_expect):
		error += "\nbut some elements where not expected:\n %s" % _colored_value(not_expect)
	if not is_empty(not_found):
		var prefix := "but" if is_empty(not_expect) else "and"
		error += "\n%s could not find elements:\n %s" % [prefix, _colored_value(not_found)]
	return error


static func error_arr_contains_exactly(
	current: Variant,
	expected: Variant,
	not_expect: Variant,
	not_found: Variant, compare_mode: GdObjects.COMPARE_MODE) -> String:
	var failure_message := (
		"Expecting contains exactly elements:" if compare_mode == GdObjects.COMPARE_MODE.PARAMETER_DEEP_TEST
		else "Expecting contains SAME exactly elements:"
	)
	if is_empty(not_expect) and is_empty(not_found):
		var arr_current: Array = current
		var arr_expected: Array = expected
		var diff := _find_first_diff(arr_current, arr_expected)
		return "%s\n %s\n do contains (in same order)\n %s\n but has different order %s"  % [
					_error(failure_message), _colored_value(current), _colored_value(expected), diff]

	var error := "%s\n %s\n do contains (in same order)\n %s" % [
					_error(failure_message), _colored_value(current), _colored_value(expected)]
	if not is_empty(not_expect):
		error += "\nbut some elements where not expected:\n %s" % _colored_value(not_expect)
	if not is_empty(not_found):
		var prefix := "but" if is_empty(not_expect) else "and"
		error += "\n%s could not find elements:\n %s" % [prefix, _colored_value(not_found)]
	return error


static func error_arr_contains_exactly_in_any_order(
	current: Variant,
	expected: Variant,
	not_expect: Variant,
	not_found: Variant,
	compare_mode: GdObjects.COMPARE_MODE) -> String:

	var failure_message := (
		"Expecting contains exactly elements:" if compare_mode == GdObjects.COMPARE_MODE.PARAMETER_DEEP_TEST
		else "Expecting contains SAME exactly elements:"
	)
	var error := "%s\n %s\n do contains exactly (in any order)\n %s" % [
					_error(failure_message), _colored_value(current), _colored_value(expected)]
	if not is_empty(not_expect):
		error += "\nbut some elements where not expected:\n %s" % _colored_value(not_expect)
	if not is_empty(not_found):
		var prefix := "but" if is_empty(not_expect) else "and"
		error += "\n%s could not find elements:\n %s" % [prefix, _colored_value(not_found)]
	return error


static func error_arr_not_contains(current: Variant, expected: Variant, found: Variant, compare_mode: GdObjects.COMPARE_MODE) -> String:
	var failure_message := "Expecting:" if compare_mode == GdObjects.COMPARE_MODE.PARAMETER_DEEP_TEST else "Expecting SAME:"
	var error := "%s\n %s\n do not contains\n %s" % [
					_error(failure_message), _colored_value(current), _colored_value(expected)]
	if not is_empty(found):
		error += "\n but found elements:\n %s" % _colored_value(found)
	return error


# - DictionaryAssert specific messages ----------------------------------------------
static func error_contains_keys(current :Array, expected :Array, keys_not_found :Array, compare_mode :GdObjects.COMPARE_MODE) -> String:
	var failure := (
		"Expecting contains keys:" if compare_mode == GdObjects.COMPARE_MODE.PARAMETER_DEEP_TEST
		else "Expecting contains SAME keys:"
	)
	return "%s\n %s\n to contains:\n %s\n but can't find key's:\n %s" % [
			_error(failure), _colored_value(current), _colored_value(expected), _colored_value(keys_not_found)]


static func error_not_contains_keys(current :Array, expected :Array, keys_not_found :Array, compare_mode :GdObjects.COMPARE_MODE) -> String:
	var failure := (
		"Expecting NOT contains keys:" if compare_mode == GdObjects.COMPARE_MODE.PARAMETER_DEEP_TEST
		else "Expecting NOT contains SAME keys"
	)
	return "%s\n %s\n do not contains:\n %s\n but contains key's:\n %s" % [
			_error(failure), _colored_value(current), _colored_value(expected), _colored_value(keys_not_found)]


static func error_contains_key_value(key :Variant, value :Variant, current_value :Variant, compare_mode :GdObjects.COMPARE_MODE) -> String:
	var failure := (
		"Expecting contains key and value:" if compare_mode == GdObjects.COMPARE_MODE.PARAMETER_DEEP_TEST
		else "Expecting contains SAME key and value:"
	)
	return "%s\n %s : %s\n but contains\n %s : %s" % [
			_error(failure), _colored_value(key), _colored_value(value), _colored_value(key), _colored_value(current_value)]


# - ResultAssert specific errors ----------------------------------------------------
static func error_result_is_empty(current :GdUnitResult) -> String:
	return _result_error_message(current, GdUnitResult.EMPTY)


static func error_result_is_success(current :GdUnitResult) -> String:
	return _result_error_message(current, GdUnitResult.SUCCESS)


static func error_result_is_warning(current :GdUnitResult) -> String:
	return _result_error_message(current, GdUnitResult.WARN)


static func error_result_is_error(current :GdUnitResult) -> String:
	return _result_error_message(current, GdUnitResult.ERROR)


static func error_result_has_message(current :String, expected :String) -> String:
	return "%s\n %s\n but was\n %s." % [_error("Expecting:"), _colored_value(expected), _colored_value(current)]


static func error_result_has_message_on_success(expected :String) -> String:
	return "%s\n %s\n but the GdUnitResult is a success." % [_error("Expecting:"), _colored_value(expected)]


static func error_result_is_value(current :Variant, expected :Variant) -> String:
	return "%s\n %s\n but was\n %s." % [_error("Expecting to contain same value:"), _colored_value(expected), _colored_value(current)]


static func _result_error_message(current :GdUnitResult, expected_type :int) -> String:
	if current == null:
		return _error("Expecting the result must be a %s but was <null>." % result_type(expected_type))
	if current.is_success():
		return _error("Expecting the result must be a %s but was SUCCESS." % result_type(expected_type))
	var error := "Expecting the result must be a %s but was %s:" % [result_type(expected_type), result_type(current._state)]
	return "%s\n %s" % [_error(error), _colored_value(result_message(current))]


static func error_interrupted(func_name :String, expected :Variant, elapsed :String) -> String:
	func_name = humanized(func_name)
	if expected == null:
		return "%s %s but timed out after %s" % [_error("Expected:"), func_name, elapsed]
	return "%s %s %s but timed out after %s" % [_error("Expected:"), func_name, _colored_value(expected), elapsed]


static func error_wait_signal(signal_name :String, args :Array, elapsed :String) -> String:
	if args.is_empty():
		return "%s %s but timed out after %s" % [
				_error("Expecting emit signal:"), _colored_value(signal_name + "()"), elapsed]
	return "%s %s but timed out after %s" % [
			_error("Expecting emit signal:"), _colored_value(signal_name + "(" + str(args) + ")"), elapsed]


static func error_signal_emitted(signal_name :String, args :Array, elapsed :String) -> String:
	if args.is_empty():
		return "%s %s but is emitted after %s" % [
				_error("Expecting do not emit signal:"), _colored_value(signal_name + "()"), elapsed]
	return "%s %s but is emitted after %s" % [
			_error("Expecting do not emit signal:"), _colored_value(signal_name + "(" + str(args) + ")"), elapsed]


static func error_await_signal_on_invalid_instance(source :Variant, signal_name :String, args :Array) -> String:
	return "%s\n await_signal_on(%s, %s, %s)" % [
			_error("Invalid source! Can't await on signal:"), _colored_value(source), signal_name, args]


static func result_type(type :int) -> String:
	match type:
		GdUnitResult.SUCCESS: return "SUCCESS"
		GdUnitResult.WARN: return "WARNING"
		GdUnitResult.ERROR: return "ERROR"
		GdUnitResult.EMPTY: return "EMPTY"
	return "UNKNOWN"


static func result_message(result :GdUnitResult) -> String:
	match result._state:
		GdUnitResult.SUCCESS: return ""
		GdUnitResult.WARN: return result.warn_message()
		GdUnitResult.ERROR: return result.error_message()
		GdUnitResult.EMPTY: return ""
	return "UNKNOWN"
# -----------------------------------------------------------------------------------

# - Spy|Mock specific errors ----------------------------------------------------
static func error_no_more_interactions(summary :Dictionary) -> String:
	var interactions := PackedStringArray()
	for args :Array in summary.keys():
		var times :int = summary[args]
		@warning_ignore("return_value_discarded")
		interactions.append(_format_arguments(args, times))
	return "%s\n%s\n%s" % [_error("Expecting no more interactions!"), _error("But found interactions on:"), "\n".join(interactions)]


static func error_validate_interactions(current_interactions: Dictionary, expected_interactions: Dictionary) -> String:
	var collected_interactions := PackedStringArray()
	for args: Array in current_interactions.keys():
		var times: int = current_interactions[args]
		@warning_ignore("return_value_discarded")
		collected_interactions.append(_format_arguments(args, times))

	var arguments: Array = expected_interactions.keys()[0]
	var interactions: int = expected_interactions.values()[0]
	var expected_interaction := _format_arguments(arguments, interactions)
	return "%s\n%s\n%s\n%s" % [
			_error("Expecting interaction on:"), expected_interaction, _error("But found interactions on:"), "\n".join(collected_interactions)]


static func _format_arguments(args :Array, times :int) -> String:
	var fname :String = args[0]
	var fargs := args.slice(1) as Array
	var typed_args := _to_typed_args(fargs)
	var fsignature := _colored_value("%s(%s)" % [fname, ", ".join(typed_args)])
	return "	%s	%d time's" % [fsignature, times]


static func _to_typed_args(args :Array) -> PackedStringArray:
	var typed := PackedStringArray()
	for arg :Variant in args:
		@warning_ignore("return_value_discarded")
		typed.append(_format_arg(arg) + " :" + GdObjects.type_as_string(typeof(arg)))
	return typed


static func _format_arg(arg :Variant) -> String:
	if arg is InputEvent:
		var ie: InputEvent = arg
		return input_event_as_text(ie)
	return str(arg)


static func _find_first_diff(left :Array, right :Array) -> String:
	for index in left.size():
		var l :Variant = left[index]
		var r :Variant = "<no entry>" if index >= right.size() else right[index]
		if not GdObjects.equals(l, r):
			return "at position %s\n '%s' vs '%s'" % [_colored_value(index), _typed_value(l), _typed_value(r)]
	return ""


static func error_has_size(current :Variant, expected: int) -> String:
	@warning_ignore("unsafe_method_access")
	var current_size :Variant = null if current == null else current.size()
	return "%s\n %s\n but was\n %s" % [_error("Expecting size:"), _colored_value(expected), _colored_value(current_size)]


static func error_contains_exactly(current: Array, expected: Array) -> String:
	return "%s\n %s\n but was\n %s" % [_error("Expecting exactly equal:"), _colored_value(expected), _colored_value(current)]


static func format_chars(characters :PackedByteArray, type :Color) -> PackedByteArray:
	if characters.size() == 0:# or characters[0] == 10:
		return characters
	var result := PackedByteArray()
	var message := "[bgcolor=#%s][color=with]%s[/color][/bgcolor]" % [
					type.to_html(), characters.get_string_from_utf8().replace("\n", "<LF>")]
	result.append_array(message.to_utf8_buffer())
	return result


static func format_invalid(value :String) -> String:
	return "[bgcolor=#%s][color=with]%s[/color][/bgcolor]" % [SUB_COLOR.to_html(), value]


static func humanized(value :String) -> String:
	return value.replace("_", " ")


static func build_failure_message(failure :String, additional_failure_message: String, custom_failure_message: String) -> String:
	var message := failure if custom_failure_message.is_empty() else custom_failure_message
	if additional_failure_message.is_empty():
		return message
	return """
		%s
		[color=LIME_GREEN][b]Additional info:[/b][/color]
		 %s""".dedent().trim_prefix("\n") % [message, additional_failure_message]


static func is_empty(value: Variant) -> bool:
	var arry_value: Array = value
	return arry_value != null and arry_value.is_empty()


================================================
FILE: addons/gdUnit4/src/asserts/GdAssertMessages.gd.uid
==================================
Download .txt
gitextract_ilg710ob/

├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   └── ISSUE_TEMPLATE/
│       ├── bug-.md
│       └── question.md
├── .gitignore
├── .junie/
│   └── guidelines.md
├── CHANGES.md
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── TODO.md
├── _assets/
│   ├── .gdignore
│   ├── action.afdesign
│   ├── arrows.afdesign
│   ├── bg.afdesign
│   ├── boat.afdesign
│   ├── joy.afdesign
│   ├── logo_editor_small.afdesign
│   ├── mouse.afdesign
│   ├── node_icons.afdesign
│   ├── spaceship.afdesign
│   └── touch.afdesign
├── addons/
│   ├── gdUnit4/
│   │   ├── GdUnitRunner.cfg
│   │   ├── LICENSE
│   │   ├── bin/
│   │   │   ├── GdUnitBuildTool.gd
│   │   │   ├── GdUnitBuildTool.gd.uid
│   │   │   ├── GdUnitCmdTool.gd
│   │   │   ├── GdUnitCmdTool.gd.uid
│   │   │   ├── GdUnitCopyLog.gd
│   │   │   └── GdUnitCopyLog.gd.uid
│   │   ├── plugin.cfg
│   │   ├── plugin.gd
│   │   ├── plugin.gd.uid
│   │   ├── runtest.cmd
│   │   ├── runtest.sh
│   │   └── src/
│   │       ├── Comparator.gd
│   │       ├── Comparator.gd.uid
│   │       ├── Fuzzers.gd
│   │       ├── Fuzzers.gd.uid
│   │       ├── GdUnitArrayAssert.gd
│   │       ├── GdUnitArrayAssert.gd.uid
│   │       ├── GdUnitAssert.gd
│   │       ├── GdUnitAssert.gd.uid
│   │       ├── GdUnitAwaiter.gd
│   │       ├── GdUnitAwaiter.gd.uid
│   │       ├── GdUnitBoolAssert.gd
│   │       ├── GdUnitBoolAssert.gd.uid
│   │       ├── GdUnitConstants.gd
│   │       ├── GdUnitConstants.gd.uid
│   │       ├── GdUnitDictionaryAssert.gd
│   │       ├── GdUnitDictionaryAssert.gd.uid
│   │       ├── GdUnitFailureAssert.gd
│   │       ├── GdUnitFailureAssert.gd.uid
│   │       ├── GdUnitFileAssert.gd
│   │       ├── GdUnitFileAssert.gd.uid
│   │       ├── GdUnitFloatAssert.gd
│   │       ├── GdUnitFloatAssert.gd.uid
│   │       ├── GdUnitFuncAssert.gd
│   │       ├── GdUnitFuncAssert.gd.uid
│   │       ├── GdUnitGodotErrorAssert.gd
│   │       ├── GdUnitGodotErrorAssert.gd.uid
│   │       ├── GdUnitIntAssert.gd
│   │       ├── GdUnitIntAssert.gd.uid
│   │       ├── GdUnitObjectAssert.gd
│   │       ├── GdUnitObjectAssert.gd.uid
│   │       ├── GdUnitResultAssert.gd
│   │       ├── GdUnitResultAssert.gd.uid
│   │       ├── GdUnitSceneRunner.gd
│   │       ├── GdUnitSceneRunner.gd.uid
│   │       ├── GdUnitSignalAssert.gd
│   │       ├── GdUnitSignalAssert.gd.uid
│   │       ├── GdUnitStringAssert.gd
│   │       ├── GdUnitStringAssert.gd.uid
│   │       ├── GdUnitTestSuite.gd
│   │       ├── GdUnitTestSuite.gd.uid
│   │       ├── GdUnitTuple.gd
│   │       ├── GdUnitTuple.gd.uid
│   │       ├── GdUnitValueExtractor.gd
│   │       ├── GdUnitValueExtractor.gd.uid
│   │       ├── GdUnitVectorAssert.gd
│   │       ├── GdUnitVectorAssert.gd.uid
│   │       ├── asserts/
│   │       │   ├── CallBackValueProvider.gd
│   │       │   ├── CallBackValueProvider.gd.uid
│   │       │   ├── DefaultValueProvider.gd
│   │       │   ├── DefaultValueProvider.gd.uid
│   │       │   ├── GdAssertMessages.gd
│   │       │   ├── GdAssertMessages.gd.uid
│   │       │   ├── GdAssertReports.gd
│   │       │   ├── GdAssertReports.gd.uid
│   │       │   ├── GdUnitArrayAssertImpl.gd
│   │       │   ├── GdUnitArrayAssertImpl.gd.uid
│   │       │   ├── GdUnitAssertImpl.gd
│   │       │   ├── GdUnitAssertImpl.gd.uid
│   │       │   ├── GdUnitAssertions.gd
│   │       │   ├── GdUnitAssertions.gd.uid
│   │       │   ├── GdUnitBoolAssertImpl.gd
│   │       │   ├── GdUnitBoolAssertImpl.gd.uid
│   │       │   ├── GdUnitDictionaryAssertImpl.gd
│   │       │   ├── GdUnitDictionaryAssertImpl.gd.uid
│   │       │   ├── GdUnitFailureAssertImpl.gd
│   │       │   ├── GdUnitFailureAssertImpl.gd.uid
│   │       │   ├── GdUnitFileAssertImpl.gd
│   │       │   ├── GdUnitFileAssertImpl.gd.uid
│   │       │   ├── GdUnitFloatAssertImpl.gd
│   │       │   ├── GdUnitFloatAssertImpl.gd.uid
│   │       │   ├── GdUnitFuncAssertImpl.gd
│   │       │   ├── GdUnitFuncAssertImpl.gd.uid
│   │       │   ├── GdUnitGodotErrorAssertImpl.gd
│   │       │   ├── GdUnitGodotErrorAssertImpl.gd.uid
│   │       │   ├── GdUnitIntAssertImpl.gd
│   │       │   ├── GdUnitIntAssertImpl.gd.uid
│   │       │   ├── GdUnitObjectAssertImpl.gd
│   │       │   ├── GdUnitObjectAssertImpl.gd.uid
│   │       │   ├── GdUnitResultAssertImpl.gd
│   │       │   ├── GdUnitResultAssertImpl.gd.uid
│   │       │   ├── GdUnitSignalAssertImpl.gd
│   │       │   ├── GdUnitSignalAssertImpl.gd.uid
│   │       │   ├── GdUnitStringAssertImpl.gd
│   │       │   ├── GdUnitStringAssertImpl.gd.uid
│   │       │   ├── GdUnitVectorAssertImpl.gd
│   │       │   ├── GdUnitVectorAssertImpl.gd.uid
│   │       │   ├── ValueProvider.gd
│   │       │   └── ValueProvider.gd.uid
│   │       ├── cmd/
│   │       │   ├── CmdArgumentParser.gd
│   │       │   ├── CmdArgumentParser.gd.uid
│   │       │   ├── CmdCommand.gd
│   │       │   ├── CmdCommand.gd.uid
│   │       │   ├── CmdCommandHandler.gd
│   │       │   ├── CmdCommandHandler.gd.uid
│   │       │   ├── CmdConsole.gd
│   │       │   ├── CmdConsole.gd.uid
│   │       │   ├── CmdOption.gd
│   │       │   ├── CmdOption.gd.uid
│   │       │   ├── CmdOptions.gd
│   │       │   └── CmdOptions.gd.uid
│   │       ├── core/
│   │       │   ├── GdArrayTools.gd
│   │       │   ├── GdArrayTools.gd.uid
│   │       │   ├── GdDiffTool.gd
│   │       │   ├── GdDiffTool.gd.uid
│   │       │   ├── GdFunctionDoubler.gd
│   │       │   ├── GdFunctionDoubler.gd.uid
│   │       │   ├── GdObjects.gd
│   │       │   ├── GdObjects.gd.uid
│   │       │   ├── GdUnit4Version.gd
│   │       │   ├── GdUnit4Version.gd.uid
│   │       │   ├── GdUnitClassDoubler.gd
│   │       │   ├── GdUnitClassDoubler.gd.uid
│   │       │   ├── GdUnitFileAccess.gd
│   │       │   ├── GdUnitFileAccess.gd.uid
│   │       │   ├── GdUnitObjectInteractions.gd
│   │       │   ├── GdUnitObjectInteractions.gd.uid
│   │       │   ├── GdUnitObjectInteractionsTemplate.gd
│   │       │   ├── GdUnitObjectInteractionsTemplate.gd.uid
│   │       │   ├── GdUnitProperty.gd
│   │       │   ├── GdUnitProperty.gd.uid
│   │       │   ├── GdUnitResult.gd
│   │       │   ├── GdUnitResult.gd.uid
│   │       │   ├── GdUnitRunner.gd
│   │       │   ├── GdUnitRunner.gd.uid
│   │       │   ├── GdUnitRunner.tscn
│   │       │   ├── GdUnitRunnerConfig.gd
│   │       │   ├── GdUnitRunnerConfig.gd.uid
│   │       │   ├── GdUnitSceneRunnerImpl.gd
│   │       │   ├── GdUnitSceneRunnerImpl.gd.uid
│   │       │   ├── GdUnitScriptType.gd
│   │       │   ├── GdUnitScriptType.gd.uid
│   │       │   ├── GdUnitSettings.gd
│   │       │   ├── GdUnitSettings.gd.uid
│   │       │   ├── GdUnitSignalAwaiter.gd
│   │       │   ├── GdUnitSignalAwaiter.gd.uid
│   │       │   ├── GdUnitSignalCollector.gd
│   │       │   ├── GdUnitSignalCollector.gd.uid
│   │       │   ├── GdUnitSignals.gd
│   │       │   ├── GdUnitSignals.gd.uid
│   │       │   ├── GdUnitSingleton.gd
│   │       │   ├── GdUnitSingleton.gd.uid
│   │       │   ├── GdUnitTestSuiteBuilder.gd
│   │       │   ├── GdUnitTestSuiteBuilder.gd.uid
│   │       │   ├── GdUnitTestSuiteScanner.gd
│   │       │   ├── GdUnitTestSuiteScanner.gd.uid
│   │       │   ├── GdUnitTools.gd
│   │       │   ├── GdUnitTools.gd.uid
│   │       │   ├── GodotVersionFixures.gd
│   │       │   ├── GodotVersionFixures.gd.uid
│   │       │   ├── LocalTime.gd
│   │       │   ├── LocalTime.gd.uid
│   │       │   ├── _TestCase.gd
│   │       │   ├── _TestCase.gd.uid
│   │       │   ├── assets/
│   │       │   │   └── touch-button.png.import
│   │       │   ├── command/
│   │       │   │   ├── GdUnitCommand.gd
│   │       │   │   ├── GdUnitCommand.gd.uid
│   │       │   │   ├── GdUnitCommandHandler.gd
│   │       │   │   ├── GdUnitCommandHandler.gd.uid
│   │       │   │   ├── GdUnitShortcut.gd
│   │       │   │   ├── GdUnitShortcut.gd.uid
│   │       │   │   ├── GdUnitShortcutAction.gd
│   │       │   │   └── GdUnitShortcutAction.gd.uid
│   │       │   ├── discovery/
│   │       │   │   ├── GdUnitTestDiscoverGuard.gd
│   │       │   │   ├── GdUnitTestDiscoverGuard.gd.uid
│   │       │   │   ├── GdUnitTestDiscoverer.gd
│   │       │   │   └── GdUnitTestDiscoverer.gd.uid
│   │       │   ├── event/
│   │       │   │   ├── GdUnitEvent.gd
│   │       │   │   ├── GdUnitEvent.gd.uid
│   │       │   │   ├── GdUnitEventInit.gd
│   │       │   │   ├── GdUnitEventInit.gd.uid
│   │       │   │   ├── GdUnitEventStop.gd
│   │       │   │   ├── GdUnitEventStop.gd.uid
│   │       │   │   ├── GdUnitEventTestDiscoverEnd.gd
│   │       │   │   ├── GdUnitEventTestDiscoverEnd.gd.uid
│   │       │   │   ├── GdUnitEventTestDiscoverStart.gd
│   │       │   │   ├── GdUnitEventTestDiscoverStart.gd.uid
│   │       │   │   ├── GdUnitEventTestDiscoverTestAdded.gd
│   │       │   │   ├── GdUnitEventTestDiscoverTestAdded.gd.uid
│   │       │   │   ├── GdUnitEventTestDiscoverTestRemoved.gd
│   │       │   │   ├── GdUnitEventTestDiscoverTestRemoved.gd.uid
│   │       │   │   ├── GdUnitEventTestDiscoverTestSuiteAdded.gd
│   │       │   │   └── GdUnitEventTestDiscoverTestSuiteAdded.gd.uid
│   │       │   ├── execution/
│   │       │   │   ├── GdUnitExecutionContext.gd
│   │       │   │   ├── GdUnitExecutionContext.gd.uid
│   │       │   │   ├── GdUnitMemoryObserver.gd
│   │       │   │   ├── GdUnitMemoryObserver.gd.uid
│   │       │   │   ├── GdUnitTestReportCollector.gd
│   │       │   │   ├── GdUnitTestReportCollector.gd.uid
│   │       │   │   ├── GdUnitTestSuiteExecutor.gd
│   │       │   │   ├── GdUnitTestSuiteExecutor.gd.uid
│   │       │   │   └── stages/
│   │       │   │       ├── GdUnitTestCaseAfterStage.gd
│   │       │   │       ├── GdUnitTestCaseAfterStage.gd.uid
│   │       │   │       ├── GdUnitTestCaseBeforeStage.gd
│   │       │   │       ├── GdUnitTestCaseBeforeStage.gd.uid
│   │       │   │       ├── GdUnitTestCaseExecutionStage.gd
│   │       │   │       ├── GdUnitTestCaseExecutionStage.gd.uid
│   │       │   │       ├── GdUnitTestSuiteAfterStage.gd
│   │       │   │       ├── GdUnitTestSuiteAfterStage.gd.uid
│   │       │   │       ├── GdUnitTestSuiteBeforeStage.gd
│   │       │   │       ├── GdUnitTestSuiteBeforeStage.gd.uid
│   │       │   │       ├── GdUnitTestSuiteExecutionStage.gd
│   │       │   │       ├── GdUnitTestSuiteExecutionStage.gd.uid
│   │       │   │       ├── IGdUnitExecutionStage.gd
│   │       │   │       ├── IGdUnitExecutionStage.gd.uid
│   │       │   │       ├── fuzzed/
│   │       │   │       │   ├── GdUnitTestCaseFuzzedExecutionStage.gd
│   │       │   │       │   ├── GdUnitTestCaseFuzzedExecutionStage.gd.uid
│   │       │   │       │   ├── GdUnitTestCaseFuzzedTestStage.gd
│   │       │   │       │   └── GdUnitTestCaseFuzzedTestStage.gd.uid
│   │       │   │       ├── parameterized/
│   │       │   │       │   ├── GdUnitTestCaseParameterSetTestStage.gd
│   │       │   │       │   ├── GdUnitTestCaseParameterSetTestStage.gd.uid
│   │       │   │       │   ├── GdUnitTestCaseParameterizedExecutionStage.gd
│   │       │   │       │   ├── GdUnitTestCaseParameterizedExecutionStage.gd.uid
│   │       │   │       │   ├── GdUnitTestCaseParameterizedTestStage.gd
│   │       │   │       │   └── GdUnitTestCaseParameterizedTestStage.gd.uid
│   │       │   │       └── single/
│   │       │   │           ├── GdUnitTestCaseSingleExecutionStage.gd
│   │       │   │           ├── GdUnitTestCaseSingleExecutionStage.gd.uid
│   │       │   │           ├── GdUnitTestCaseSingleTestStage.gd
│   │       │   │           └── GdUnitTestCaseSingleTestStage.gd.uid
│   │       │   ├── parse/
│   │       │   │   ├── GdClassDescriptor.gd
│   │       │   │   ├── GdClassDescriptor.gd.uid
│   │       │   │   ├── GdDefaultValueDecoder.gd
│   │       │   │   ├── GdDefaultValueDecoder.gd.uid
│   │       │   │   ├── GdFunctionArgument.gd
│   │       │   │   ├── GdFunctionArgument.gd.uid
│   │       │   │   ├── GdFunctionDescriptor.gd
│   │       │   │   ├── GdFunctionDescriptor.gd.uid
│   │       │   │   ├── GdScriptParser.gd
│   │       │   │   ├── GdScriptParser.gd.uid
│   │       │   │   ├── GdUnitExpressionRunner.gd
│   │       │   │   ├── GdUnitExpressionRunner.gd.uid
│   │       │   │   ├── GdUnitTestParameterSetResolver.gd
│   │       │   │   └── GdUnitTestParameterSetResolver.gd.uid
│   │       │   ├── report/
│   │       │   │   ├── GdUnitReport.gd
│   │       │   │   └── GdUnitReport.gd.uid
│   │       │   ├── templates/
│   │       │   │   └── test_suite/
│   │       │   │       ├── GdUnitTestSuiteDefaultTemplate.gd
│   │       │   │       ├── GdUnitTestSuiteDefaultTemplate.gd.uid
│   │       │   │       ├── GdUnitTestSuiteTemplate.gd
│   │       │   │       └── GdUnitTestSuiteTemplate.gd.uid
│   │       │   └── thread/
│   │       │       ├── GdUnitThreadContext.gd
│   │       │       ├── GdUnitThreadContext.gd.uid
│   │       │       ├── GdUnitThreadManager.gd
│   │       │       └── GdUnitThreadManager.gd.uid
│   │       ├── doubler/
│   │       │   ├── CallableDoubler.gd
│   │       │   └── CallableDoubler.gd.uid
│   │       ├── extractors/
│   │       │   ├── GdUnitFuncValueExtractor.gd
│   │       │   └── GdUnitFuncValueExtractor.gd.uid
│   │       ├── fuzzers/
│   │       │   ├── FloatFuzzer.gd
│   │       │   ├── FloatFuzzer.gd.uid
│   │       │   ├── Fuzzer.gd
│   │       │   ├── Fuzzer.gd.uid
│   │       │   ├── IntFuzzer.gd
│   │       │   ├── IntFuzzer.gd.uid
│   │       │   ├── StringFuzzer.gd
│   │       │   ├── StringFuzzer.gd.uid
│   │       │   ├── Vector2Fuzzer.gd
│   │       │   ├── Vector2Fuzzer.gd.uid
│   │       │   ├── Vector3Fuzzer.gd
│   │       │   └── Vector3Fuzzer.gd.uid
│   │       ├── matchers/
│   │       │   ├── AnyArgumentMatcher.gd
│   │       │   ├── AnyArgumentMatcher.gd.uid
│   │       │   ├── AnyBuildInTypeArgumentMatcher.gd
│   │       │   ├── AnyBuildInTypeArgumentMatcher.gd.uid
│   │       │   ├── AnyClazzArgumentMatcher.gd
│   │       │   ├── AnyClazzArgumentMatcher.gd.uid
│   │       │   ├── ChainedArgumentMatcher.gd
│   │       │   ├── ChainedArgumentMatcher.gd.uid
│   │       │   ├── EqualsArgumentMatcher.gd
│   │       │   ├── EqualsArgumentMatcher.gd.uid
│   │       │   ├── GdUnitArgumentMatcher.gd
│   │       │   ├── GdUnitArgumentMatcher.gd.uid
│   │       │   ├── GdUnitArgumentMatchers.gd
│   │       │   └── GdUnitArgumentMatchers.gd.uid
│   │       ├── mocking/
│   │       │   ├── GdUnitMock.gd
│   │       │   ├── GdUnitMock.gd.uid
│   │       │   ├── GdUnitMockBuilder.gd
│   │       │   ├── GdUnitMockBuilder.gd.uid
│   │       │   ├── GdUnitMockFunctionDoubler.gd
│   │       │   ├── GdUnitMockFunctionDoubler.gd.uid
│   │       │   ├── GdUnitMockImpl.gd
│   │       │   └── GdUnitMockImpl.gd.uid
│   │       ├── monitor/
│   │       │   ├── ErrorLogEntry.gd
│   │       │   ├── ErrorLogEntry.gd.uid
│   │       │   ├── GdUnitMonitor.gd
│   │       │   ├── GdUnitMonitor.gd.uid
│   │       │   ├── GdUnitOrphanNodesMonitor.gd
│   │       │   ├── GdUnitOrphanNodesMonitor.gd.uid
│   │       │   ├── GodotGdErrorMonitor.gd
│   │       │   └── GodotGdErrorMonitor.gd.uid
│   │       ├── mono/
│   │       │   ├── GdUnit4CSharpApi.cs
│   │       │   ├── GdUnit4CSharpApi.cs.uid
│   │       │   ├── GdUnit4CSharpApiLoader.gd
│   │       │   └── GdUnit4CSharpApiLoader.gd.uid
│   │       ├── network/
│   │       │   ├── GdUnitServer.gd
│   │       │   ├── GdUnitServer.gd.uid
│   │       │   ├── GdUnitServer.tscn
│   │       │   ├── GdUnitServerConstants.gd
│   │       │   ├── GdUnitServerConstants.gd.uid
│   │       │   ├── GdUnitTask.gd
│   │       │   ├── GdUnitTask.gd.uid
│   │       │   ├── GdUnitTcpClient.gd
│   │       │   ├── GdUnitTcpClient.gd.uid
│   │       │   ├── GdUnitTcpServer.gd
│   │       │   ├── GdUnitTcpServer.gd.uid
│   │       │   └── rpc/
│   │       │       ├── RPC.gd
│   │       │       ├── RPC.gd.uid
│   │       │       ├── RPCClientConnect.gd
│   │       │       ├── RPCClientConnect.gd.uid
│   │       │       ├── RPCClientDisconnect.gd
│   │       │       ├── RPCClientDisconnect.gd.uid
│   │       │       ├── RPCGdUnitEvent.gd
│   │       │       ├── RPCGdUnitEvent.gd.uid
│   │       │       ├── RPCGdUnitTestSuite.gd
│   │       │       ├── RPCGdUnitTestSuite.gd.uid
│   │       │       ├── RPCMessage.gd
│   │       │       ├── RPCMessage.gd.uid
│   │       │       └── dtos/
│   │       │           ├── GdUnitResourceDto.gd
│   │       │           ├── GdUnitResourceDto.gd.uid
│   │       │           ├── GdUnitTestCaseDto.gd
│   │       │           ├── GdUnitTestCaseDto.gd.uid
│   │       │           ├── GdUnitTestSuiteDto.gd
│   │       │           └── GdUnitTestSuiteDto.gd.uid
│   │       ├── report/
│   │       │   ├── GdUnitByPathReport.gd
│   │       │   ├── GdUnitByPathReport.gd.uid
│   │       │   ├── GdUnitHtmlPatterns.gd
│   │       │   ├── GdUnitHtmlPatterns.gd.uid
│   │       │   ├── GdUnitHtmlReport.gd
│   │       │   ├── GdUnitHtmlReport.gd.uid
│   │       │   ├── GdUnitReportSummary.gd
│   │       │   ├── GdUnitReportSummary.gd.uid
│   │       │   ├── GdUnitTestCaseReport.gd
│   │       │   ├── GdUnitTestCaseReport.gd.uid
│   │       │   ├── GdUnitTestSuiteReport.gd
│   │       │   ├── GdUnitTestSuiteReport.gd.uid
│   │       │   ├── JUnitXmlReport.gd
│   │       │   ├── JUnitXmlReport.gd.uid
│   │       │   ├── XmlElement.gd
│   │       │   ├── XmlElement.gd.uid
│   │       │   └── template/
│   │       │       ├── css/
│   │       │       │   ├── breadcrumb.css
│   │       │       │   ├── logo.png.import
│   │       │       │   └── styles.css
│   │       │       ├── folder_report.html
│   │       │       ├── index.html
│   │       │       └── suite_report.html
│   │       ├── spy/
│   │       │   ├── GdUnitSpyBuilder.gd
│   │       │   ├── GdUnitSpyBuilder.gd.uid
│   │       │   ├── GdUnitSpyFunctionDoubler.gd
│   │       │   ├── GdUnitSpyFunctionDoubler.gd.uid
│   │       │   ├── GdUnitSpyImpl.gd
│   │       │   └── GdUnitSpyImpl.gd.uid
│   │       ├── ui/
│   │       │   ├── GdUnitConsole.gd
│   │       │   ├── GdUnitConsole.gd.uid
│   │       │   ├── GdUnitConsole.tscn
│   │       │   ├── GdUnitFonts.gd
│   │       │   ├── GdUnitFonts.gd.uid
│   │       │   ├── GdUnitInspector.gd
│   │       │   ├── GdUnitInspector.gd.uid
│   │       │   ├── GdUnitInspector.tscn
│   │       │   ├── GdUnitInspectorTreeConstants.gd
│   │       │   ├── GdUnitInspectorTreeConstants.gd.uid
│   │       │   ├── GdUnitUiTools.gd
│   │       │   ├── GdUnitUiTools.gd.uid
│   │       │   ├── ScriptEditorControls.gd
│   │       │   ├── ScriptEditorControls.gd.uid
│   │       │   ├── menu/
│   │       │   │   ├── EditorFileSystemContextMenuHandler.gd
│   │       │   │   ├── EditorFileSystemContextMenuHandler.gd.uid
│   │       │   │   ├── GdUnitContextMenuItem.gd
│   │       │   │   ├── GdUnitContextMenuItem.gd.uid
│   │       │   │   ├── ScriptEditorContextMenuHandler.gd
│   │       │   │   └── ScriptEditorContextMenuHandler.gd.uid
│   │       │   ├── parts/
│   │       │   │   ├── InspectorMonitor.gd
│   │       │   │   ├── InspectorMonitor.gd.uid
│   │       │   │   ├── InspectorMonitor.tscn
│   │       │   │   ├── InspectorProgressBar.gd
│   │       │   │   ├── InspectorProgressBar.gd.uid
│   │       │   │   ├── InspectorProgressBar.tscn
│   │       │   │   ├── InspectorStatusBar.gd
│   │       │   │   ├── InspectorStatusBar.gd.uid
│   │       │   │   ├── InspectorStatusBar.tscn
│   │       │   │   ├── InspectorToolBar.gd
│   │       │   │   ├── InspectorToolBar.gd.uid
│   │       │   │   ├── InspectorToolBar.tscn
│   │       │   │   ├── InspectorTreeMainPanel.gd
│   │       │   │   ├── InspectorTreeMainPanel.gd.uid
│   │       │   │   └── InspectorTreePanel.tscn
│   │       │   ├── settings/
│   │       │   │   ├── GdUnitInputCapture.gd
│   │       │   │   ├── GdUnitInputCapture.gd.uid
│   │       │   │   ├── GdUnitInputCapture.tscn
│   │       │   │   ├── GdUnitSettingsDialog.gd
│   │       │   │   ├── GdUnitSettingsDialog.gd.uid
│   │       │   │   ├── GdUnitSettingsDialog.tscn
│   │       │   │   └── logo.png.import
│   │       │   └── templates/
│   │       │       ├── TestSuiteTemplate.gd
│   │       │       ├── TestSuiteTemplate.gd.uid
│   │       │       └── TestSuiteTemplate.tscn
│   │       └── update/
│   │           ├── GdMarkDownReader.gd
│   │           ├── GdMarkDownReader.gd.uid
│   │           ├── GdUnitPatch.gd
│   │           ├── GdUnitPatch.gd.uid
│   │           ├── GdUnitPatcher.gd
│   │           ├── GdUnitPatcher.gd.uid
│   │           ├── GdUnitUpdate.gd
│   │           ├── GdUnitUpdate.gd.uid
│   │           ├── GdUnitUpdate.tscn
│   │           ├── GdUnitUpdateClient.gd
│   │           ├── GdUnitUpdateClient.gd.uid
│   │           ├── GdUnitUpdateNotify.gd
│   │           ├── GdUnitUpdateNotify.gd.uid
│   │           ├── GdUnitUpdateNotify.tscn
│   │           └── assets/
│   │               ├── border_bottom.png.import
│   │               ├── border_top.png.import
│   │               ├── dot1.png.import
│   │               ├── dot2.png.import
│   │               ├── embedded.png.import
│   │               ├── fonts/
│   │               │   ├── LICENSE.txt
│   │               │   ├── README.txt
│   │               │   └── static/
│   │               │       ├── RobotoMono-Bold.ttf.import
│   │               │       ├── RobotoMono-BoldItalic.ttf.import
│   │               │       ├── RobotoMono-ExtraLight.ttf.import
│   │               │       ├── RobotoMono-ExtraLightItalic.ttf.import
│   │               │       ├── RobotoMono-Italic.ttf.import
│   │               │       ├── RobotoMono-Light.ttf.import
│   │               │       ├── RobotoMono-LightItalic.ttf.import
│   │               │       ├── RobotoMono-Medium.ttf.import
│   │               │       ├── RobotoMono-MediumItalic.ttf.import
│   │               │       ├── RobotoMono-Regular.ttf.import
│   │               │       ├── RobotoMono-SemiBold.ttf.import
│   │               │       ├── RobotoMono-SemiBoldItalic.ttf.import
│   │               │       ├── RobotoMono-Thin.ttf.import
│   │               │       └── RobotoMono-ThinItalic.ttf.import
│   │               └── horizontal-line2.png.import
│   └── guide/
│       ├── LICENSE.md
│       ├── debugger/
│       │   ├── guide_debugger.gd
│       │   ├── guide_debugger.gd.uid
│       │   └── guide_debugger.tscn
│       ├── editor/
│       │   ├── action_mapping_editor/
│       │   │   ├── action_mapping_editor.gd
│       │   │   ├── action_mapping_editor.gd.uid
│       │   │   └── action_mapping_editor.tscn
│       │   ├── action_slot/
│       │   │   ├── action_slot.gd
│       │   │   ├── action_slot.gd.uid
│       │   │   ├── action_slot.tscn
│       │   │   ├── action_slot_line_edit.gd
│       │   │   ├── action_slot_line_edit.gd.uid
│       │   │   ├── action_value_type_axis1d.svg.import
│       │   │   ├── action_value_type_axis2d.svg.import
│       │   │   ├── action_value_type_axis3d.svg.import
│       │   │   ├── action_value_type_bool.svg.import
│       │   │   └── missing_action.svg.import
│       │   ├── array_edit/
│       │   │   ├── array_edit.gd
│       │   │   ├── array_edit.gd.uid
│       │   │   ├── array_edit.tscn
│       │   │   ├── array_edit_item.gd
│       │   │   ├── array_edit_item.gd.uid
│       │   │   ├── array_edit_item.tscn
│       │   │   ├── dragger.gd
│       │   │   └── dragger.gd.uid
│       │   ├── binding_dialog/
│       │   │   ├── binding_dialog.gd
│       │   │   ├── binding_dialog.gd.uid
│       │   │   └── binding_dialog.tscn
│       │   ├── class_scanner.gd
│       │   ├── class_scanner.gd.uid
│       │   ├── guide_project_settings.gd
│       │   ├── guide_project_settings.gd.uid
│       │   ├── input_display/
│       │   │   ├── input_display.gd
│       │   │   ├── input_display.gd.uid
│       │   │   └── input_display.tscn
│       │   ├── input_mapping_editor/
│       │   │   ├── input_mapping_editor.gd
│       │   │   ├── input_mapping_editor.gd.uid
│       │   │   └── input_mapping_editor.tscn
│       │   ├── logo_editor_small.svg.import
│       │   ├── mapping_context_editor/
│       │   │   ├── mapping_context_editor.gd
│       │   │   ├── mapping_context_editor.gd.uid
│       │   │   └── mapping_context_editor.tscn
│       │   ├── modifier_slot/
│       │   │   ├── modifier_slot.gd
│       │   │   ├── modifier_slot.gd.uid
│       │   │   └── modifier_slot.tscn
│       │   ├── resource_scanner.gd
│       │   ├── resource_scanner.gd.uid
│       │   ├── resource_slot/
│       │   │   ├── resource_slot.gd
│       │   │   └── resource_slot.gd.uid
│       │   ├── trigger_slot/
│       │   │   ├── trigger_slot.gd
│       │   │   ├── trigger_slot.gd.uid
│       │   │   └── trigger_slot.tscn
│       │   ├── utils.gd
│       │   └── utils.gd.uid
│       ├── guide.gd
│       ├── guide.gd.uid
│       ├── guide_action.gd
│       ├── guide_action.gd.uid
│       ├── guide_action.svg.import
│       ├── guide_action_mapping.gd
│       ├── guide_action_mapping.gd.uid
│       ├── guide_input_mapping.gd
│       ├── guide_input_mapping.gd.uid
│       ├── guide_input_tracker.gd
│       ├── guide_input_tracker.gd.uid
│       ├── guide_internal.svg.import
│       ├── guide_mapping_context.gd
│       ├── guide_mapping_context.gd.uid
│       ├── guide_mapping_context.svg.import
│       ├── guide_reset.gd
│       ├── guide_reset.gd.uid
│       ├── guide_set.gd
│       ├── guide_set.gd.uid
│       ├── inputs/
│       │   ├── guide_input.gd
│       │   ├── guide_input.gd.uid
│       │   ├── guide_input.svg.import
│       │   ├── guide_input_action.gd
│       │   ├── guide_input_action.gd.uid
│       │   ├── guide_input_any.gd
│       │   ├── guide_input_any.gd.uid
│       │   ├── guide_input_joy_axis_1d.gd
│       │   ├── guide_input_joy_axis_1d.gd.uid
│       │   ├── guide_input_joy_axis_2d.gd
│       │   ├── guide_input_joy_axis_2d.gd.uid
│       │   ├── guide_input_joy_base.gd
│       │   ├── guide_input_joy_base.gd.uid
│       │   ├── guide_input_joy_button.gd
│       │   ├── guide_input_joy_button.gd.uid
│       │   ├── guide_input_key.gd
│       │   ├── guide_input_key.gd.uid
│       │   ├── guide_input_mouse_axis_1d.gd
│       │   ├── guide_input_mouse_axis_1d.gd.uid
│       │   ├── guide_input_mouse_axis_2d.gd
│       │   ├── guide_input_mouse_axis_2d.gd.uid
│       │   ├── guide_input_mouse_button.gd
│       │   ├── guide_input_mouse_button.gd.uid
│       │   ├── guide_input_mouse_position.gd
│       │   ├── guide_input_mouse_position.gd.uid
│       │   ├── guide_input_state.gd
│       │   ├── guide_input_state.gd.uid
│       │   ├── guide_input_touch_angle.gd
│       │   ├── guide_input_touch_angle.gd.uid
│       │   ├── guide_input_touch_axis_1d.gd
│       │   ├── guide_input_touch_axis_1d.gd.uid
│       │   ├── guide_input_touch_axis_2d.gd
│       │   ├── guide_input_touch_axis_2d.gd.uid
│       │   ├── guide_input_touch_axis_base.gd
│       │   ├── guide_input_touch_axis_base.gd.uid
│       │   ├── guide_input_touch_base.gd
│       │   ├── guide_input_touch_base.gd.uid
│       │   ├── guide_input_touch_distance.gd
│       │   ├── guide_input_touch_distance.gd.uid
│       │   ├── guide_input_touch_position.gd
│       │   └── guide_input_touch_position.gd.uid
│       ├── modifiers/
│       │   ├── guide_modifier.gd
│       │   ├── guide_modifier.gd.uid
│       │   ├── guide_modifier.svg.import
│       │   ├── guide_modifier_3d_coordinates.gd
│       │   ├── guide_modifier_3d_coordinates.gd.uid
│       │   ├── guide_modifier_8_way_direction.gd
│       │   ├── guide_modifier_8_way_direction.gd.uid
│       │   ├── guide_modifier_canvas_coordinates.gd
│       │   ├── guide_modifier_canvas_coordinates.gd.uid
│       │   ├── guide_modifier_curve.gd
│       │   ├── guide_modifier_curve.gd.uid
│       │   ├── guide_modifier_deadzone.gd
│       │   ├── guide_modifier_deadzone.gd.uid
│       │   ├── guide_modifier_input_swizzle.gd
│       │   ├── guide_modifier_input_swizzle.gd.uid
│       │   ├── guide_modifier_magnitude.gd
│       │   ├── guide_modifier_magnitude.gd.uid
│       │   ├── guide_modifier_map_range.gd
│       │   ├── guide_modifier_map_range.gd.uid
│       │   ├── guide_modifier_negate.gd
│       │   ├── guide_modifier_negate.gd.uid
│       │   ├── guide_modifier_normalize.gd
│       │   ├── guide_modifier_normalize.gd.uid
│       │   ├── guide_modifier_positive_negative.gd
│       │   ├── guide_modifier_positive_negative.gd.uid
│       │   ├── guide_modifier_scale.gd
│       │   ├── guide_modifier_scale.gd.uid
│       │   ├── guide_modifier_virtual_cursor.gd
│       │   ├── guide_modifier_virtual_cursor.gd.uid
│       │   ├── guide_modifier_window_relative.gd
│       │   └── guide_modifier_window_relative.gd.uid
│       ├── plugin.cfg
│       ├── plugin.gd
│       ├── plugin.gd.uid
│       ├── remapping/
│       │   ├── guide_input_detector.gd
│       │   ├── guide_input_detector.gd.uid
│       │   ├── guide_remapper.gd
│       │   ├── guide_remapper.gd.uid
│       │   ├── guide_remapping_config.gd
│       │   └── guide_remapping_config.gd.uid
│       ├── triggers/
│       │   ├── guide_trigger.gd
│       │   ├── guide_trigger.gd.uid
│       │   ├── guide_trigger.svg.import
│       │   ├── guide_trigger_chorded_action.gd
│       │   ├── guide_trigger_chorded_action.gd.uid
│       │   ├── guide_trigger_combo.gd
│       │   ├── guide_trigger_combo.gd.uid
│       │   ├── guide_trigger_combo_cancel_action.gd
│       │   ├── guide_trigger_combo_cancel_action.gd.uid
│       │   ├── guide_trigger_combo_step.gd
│       │   ├── guide_trigger_combo_step.gd.uid
│       │   ├── guide_trigger_down.gd
│       │   ├── guide_trigger_down.gd.uid
│       │   ├── guide_trigger_hair.gd
│       │   ├── guide_trigger_hair.gd.uid
│       │   ├── guide_trigger_hold.gd
│       │   ├── guide_trigger_hold.gd.uid
│       │   ├── guide_trigger_pressed.gd
│       │   ├── guide_trigger_pressed.gd.uid
│       │   ├── guide_trigger_pulse.gd
│       │   ├── guide_trigger_pulse.gd.uid
│       │   ├── guide_trigger_released.gd
│       │   ├── guide_trigger_released.gd.uid
│       │   ├── guide_trigger_stability.gd
│       │   ├── guide_trigger_stability.gd.uid
│       │   ├── guide_trigger_tap.gd
│       │   └── guide_trigger_tap.gd.uid
│       └── ui/
│           ├── guide_formatting_utils.gd
│           ├── guide_formatting_utils.gd.uid
│           ├── guide_icon_renderer.gd
│           ├── guide_icon_renderer.gd.uid
│           ├── guide_input_formatter.gd
│           ├── guide_input_formatter.gd.uid
│           ├── guide_input_formatting_options.gd
│           ├── guide_input_formatting_options.gd.uid
│           ├── guide_text_provider.gd
│           ├── guide_text_provider.gd.uid
│           ├── icon_maker/
│           │   ├── icon_maker.gd
│           │   ├── icon_maker.gd.uid
│           │   └── icon_maker.tscn
│           ├── renderers/
│           │   ├── controllers/
│           │   │   ├── guide_controller_render_style.gd
│           │   │   ├── guide_controller_render_style.gd.uid
│           │   │   ├── guide_controller_renderer.gd
│           │   │   ├── guide_controller_renderer.gd.uid
│           │   │   ├── guide_controller_renderer.tscn
│           │   │   └── styles/
│           │   │       ├── microsoft/
│           │   │       │   ├── XboxSeriesX_A.png.import
│           │   │       │   ├── XboxSeriesX_B.png.import
│           │   │       │   ├── XboxSeriesX_Dpad.png.import
│           │   │       │   ├── XboxSeriesX_Dpad_Down.png.import
│           │   │       │   ├── XboxSeriesX_Dpad_Left.png.import
│           │   │       │   ├── XboxSeriesX_Dpad_Right.png.import
│           │   │       │   ├── XboxSeriesX_Dpad_Up.png.import
│           │   │       │   ├── XboxSeriesX_LB.png.import
│           │   │       │   ├── XboxSeriesX_LT.png.import
│           │   │       │   ├── XboxSeriesX_Left_Stick.png.import
│           │   │       │   ├── XboxSeriesX_Left_Stick_Click.png.import
│           │   │       │   ├── XboxSeriesX_Menu.png.import
│           │   │       │   ├── XboxSeriesX_RB.png.import
│           │   │       │   ├── XboxSeriesX_RT.png.import
│           │   │       │   ├── XboxSeriesX_Right_Stick.png.import
│           │   │       │   ├── XboxSeriesX_Right_Stick_Click.png.import
│           │   │       │   ├── XboxSeriesX_Share.png.import
│           │   │       │   ├── XboxSeriesX_View.png.import
│           │   │       │   ├── XboxSeriesX_X.png.import
│           │   │       │   ├── XboxSeriesX_Y.png.import
│           │   │       │   └── microsoft.tres
│           │   │       ├── nintendo/
│           │   │       │   ├── Switch_A.png.import
│           │   │       │   ├── Switch_B.png.import
│           │   │       │   ├── Switch_Controller_Left.png.import
│           │   │       │   ├── Switch_Controller_Right.png.import
│           │   │       │   ├── Switch_Controllers.png.import
│           │   │       │   ├── Switch_Controllers_Separate.png.import
│           │   │       │   ├── Switch_Down.png.import
│           │   │       │   ├── Switch_Dpad.png.import
│           │   │       │   ├── Switch_Dpad_Down.png.import
│           │   │       │   ├── Switch_Dpad_Left.png.import
│           │   │       │   ├── Switch_Dpad_Right.png.import
│           │   │       │   ├── Switch_Dpad_Up.png.import
│           │   │       │   ├── Switch_Home.png.import
│           │   │       │   ├── Switch_LB.png.import
│           │   │       │   ├── Switch_LT.png.import
│           │   │       │   ├── Switch_Left.png.import
│           │   │       │   ├── Switch_Left_Stick.png.import
│           │   │       │   ├── Switch_Left_Stick_Click.png.import
│           │   │       │   ├── Switch_Minus.png.import
│           │   │       │   ├── Switch_Plus.png.import
│           │   │       │   ├── Switch_RB.png.import
│           │   │       │   ├── Switch_RT.png.import
│           │   │       │   ├── Switch_Right.png.import
│           │   │       │   ├── Switch_Right_Stick.png.import
│           │   │       │   ├── Switch_Right_Stick_Click.png.import
│           │   │       │   ├── Switch_Square.png.import
│           │   │       │   ├── Switch_Up.png.import
│           │   │       │   ├── Switch_X.png.import
│           │   │       │   ├── Switch_Y.png.import
│           │   │       │   └── nintendo.tres
│           │   │       ├── sony/
│           │   │       │   ├── PS5_Circle.png.import
│           │   │       │   ├── PS5_Cross.png.import
│           │   │       │   ├── PS5_Dpad.png.import
│           │   │       │   ├── PS5_Dpad_Down.png.import
│           │   │       │   ├── PS5_Dpad_Left.png.import
│           │   │       │   ├── PS5_Dpad_Right.png.import
│           │   │       │   ├── PS5_Dpad_Up.png.import
│           │   │       │   ├── PS5_L1.png.import
│           │   │       │   ├── PS5_L2.png.import
│           │   │       │   ├── PS5_Left_Stick.png.import
│           │   │       │   ├── PS5_Left_Stick_Click.png.import
│           │   │       │   ├── PS5_Microphone.png.import
│           │   │       │   ├── PS5_Options.png.import
│           │   │       │   ├── PS5_Options_Alt.png.import
│           │   │       │   ├── PS5_R1.png.import
│           │   │       │   ├── PS5_R2.png.import
│           │   │       │   ├── PS5_Right_Stick.png.import
│           │   │       │   ├── PS5_Right_Stick_Click.png.import
│           │   │       │   ├── PS5_Share.png.import
│           │   │       │   ├── PS5_Share_Alt.png.import
│           │   │       │   ├── PS5_Square.png.import
│           │   │       │   ├── PS5_Touch_Pad.png.import
│           │   │       │   ├── PS5_Triangle.png.import
│           │   │       │   └── sony.tres
│           │   │       └── steam_deck/
│           │   │           ├── SteamDeck_A.png.import
│           │   │           ├── SteamDeck_B.png.import
│           │   │           ├── SteamDeck_Dots.png.import
│           │   │           ├── SteamDeck_Dpad.png.import
│           │   │           ├── SteamDeck_Dpad_Down.png.import
│           │   │           ├── SteamDeck_Dpad_Left.png.import
│           │   │           ├── SteamDeck_Dpad_Right.png.import
│           │   │           ├── SteamDeck_Dpad_Up.png.import
│           │   │           ├── SteamDeck_Gyro.png.import
│           │   │           ├── SteamDeck_Inventory.png.import
│           │   │           ├── SteamDeck_L1.png.import
│           │   │           ├── SteamDeck_L2.png.import
│           │   │           ├── SteamDeck_L4.png.import
│           │   │           ├── SteamDeck_L5.png.import
│           │   │           ├── SteamDeck_Left_Stick.png.import
│           │   │           ├── SteamDeck_Left_Stick_Click.png.import
│           │   │           ├── SteamDeck_Left_Track.png.import
│           │   │           ├── SteamDeck_Menu.png.import
│           │   │           ├── SteamDeck_Minus.png.import
│           │   │           ├── SteamDeck_Plus.png.import
│           │   │           ├── SteamDeck_Power.png.import
│           │   │           ├── SteamDeck_R1.png.import
│           │   │           ├── SteamDeck_R2.png.import
│           │   │           ├── SteamDeck_R4.png.import
│           │   │           ├── SteamDeck_R5.png.import
│           │   │           ├── SteamDeck_Right_Stick.png.import
│           │   │           ├── SteamDeck_Right_Stick_Click.png.import
│           │   │           ├── SteamDeck_Right_Track.png.import
│           │   │           ├── SteamDeck_Square.png.import
│           │   │           ├── SteamDeck_Steam.png.import
│           │   │           ├── SteamDeck_X.png.import
│           │   │           ├── SteamDeck_Y.png.import
│           │   │           └── steam_deck.tres
│           │   ├── joy/
│           │   │   ├── guide_joy_render_style.gd
│           │   │   ├── guide_joy_render_style.gd.uid
│           │   │   ├── guide_joy_renderer.gd
│           │   │   ├── guide_joy_renderer.gd.uid
│           │   │   ├── guide_joy_renderer.tscn
│           │   │   └── styles/
│           │   │       ├── button_empty.png.import
│           │   │       ├── default.tres
│           │   │       └── stick_empty.png.import
│           │   ├── keyboard/
│           │   │   ├── guide_key_render_style.gd
│           │   │   ├── guide_key_render_style.gd.uid
│           │   │   ├── guide_key_renderer.gd
│           │   │   ├── guide_key_renderer.gd.uid
│           │   │   ├── guide_key_renderer.tscn
│           │   │   └── styles/
│           │   │       ├── Blank_White_Normal.png.import
│           │   │       ├── Lato-Black.ttf.import
│           │   │       └── default.tres
│           │   ├── misc/
│           │   │   ├── guide_action_renderer.gd
│           │   │   ├── guide_action_renderer.gd.uid
│           │   │   ├── guide_action_renderer.tscn
│           │   │   ├── guide_fallback_renderer.gd
│           │   │   ├── guide_fallback_renderer.gd.uid
│           │   │   └── guide_fallback_renderer.tscn
│           │   ├── mouse/
│           │   │   ├── guide_mouse_render_style.gd
│           │   │   ├── guide_mouse_render_style.gd.uid
│           │   │   ├── guide_mouse_renderer.gd
│           │   │   ├── guide_mouse_renderer.gd.uid
│           │   │   ├── guide_mouse_renderer.tscn
│           │   │   └── styles/
│           │   │       ├── Mouse_Cursor.png.import
│           │   │       ├── Mouse_Left_Key_Light.png.import
│           │   │       ├── Mouse_Middle_Key_Light.png.import
│           │   │       ├── Mouse_Right_Key_Light.png.import
│           │   │       ├── Mouse_Side_Key_1_Light.png.import
│           │   │       ├── Mouse_Side_Key_2_Light.png.import
│           │   │       ├── Mouse_Simple_Key_Light.png.import
│           │   │       └── default.tres
│           │   ├── style.svg.import
│           │   ├── textures/
│           │   │   ├── action.svg.import
│           │   │   ├── arrow_all_directions.svg.import
│           │   │   ├── arrow_down.svg.import
│           │   │   ├── arrow_horizontal.svg.import
│           │   │   ├── arrow_left.svg.import
│           │   │   ├── arrow_right.svg.import
│           │   │   ├── arrow_up.svg.import
│           │   │   └── arrow_vertical.svg.import
│           │   └── touch/
│           │       ├── guide_touch_render_style.gd
│           │       ├── guide_touch_render_style.gd.uid
│           │       ├── guide_touch_renderer.gd
│           │       ├── guide_touch_renderer.gd.uid
│           │       ├── guide_touch_renderer.tscn
│           │       └── styles/
│           │           ├── default.tres
│           │           ├── touch_1_finger.png.import
│           │           ├── touch_2_fingers.png.import
│           │           ├── touch_3_fingers.png.import
│           │           ├── touch_4_fingers.png.import
│           │           ├── touch_rotate.png.import
│           │           └── touch_zoom.png.import
│           ├── text_providers/
│           │   ├── controllers/
│           │   │   ├── guide_controller_label_set.gd
│           │   │   ├── guide_controller_label_set.gd.uid
│           │   │   ├── guide_controller_text_provider.gd
│           │   │   ├── guide_controller_text_provider.gd.uid
│           │   │   └── label_sets/
│           │   │       ├── microsoft.tres
│           │   │       ├── nintendo.tres
│           │   │       ├── sony.tres
│           │   │       └── steam_deck.tres
│           │   ├── default_text_provider.gd
│           │   └── default_text_provider.gd.uid
│           └── virtual_joy/
│               ├── guide_virtual_joy_base.gd
│               ├── guide_virtual_joy_base.gd.uid
│               ├── virtual_button/
│               │   ├── guide_virtual_button.gd
│               │   ├── guide_virtual_button.gd.uid
│               │   ├── guide_virtual_button.svg.import
│               │   ├── guide_virtual_button_renderer.gd
│               │   ├── guide_virtual_button_renderer.gd.uid
│               │   ├── guide_virtual_button_renderer.svg.import
│               │   └── texture_renderer/
│               │       ├── actuated.svg.import
│               │       ├── guide_virtual_button_texture_renderer.gd
│               │       ├── guide_virtual_button_texture_renderer.gd.uid
│               │       └── idle.svg.import
│               └── virtual_stick/
│                   ├── guide_virtual_stick.gd
│                   ├── guide_virtual_stick.gd.uid
│                   ├── guide_virtual_stick.svg.import
│                   ├── guide_virtual_stick_renderer.gd
│                   ├── guide_virtual_stick_renderer.gd.uid
│                   ├── guide_virtual_stick_renderer.svg.import
│                   └── texture_renderer/
│                       ├── guide_virtual_stick_texture_renderer.gd
│                       ├── guide_virtual_stick_texture_renderer.gd.uid
│                       ├── stick.svg.import
│                       ├── stick_hidden.svg.import
│                       └── stick_outline.svg.import
├── asset_library/
│   └── .gdignore
├── docs/
│   ├── .gdignore
│   ├── .gitignore
│   ├── Gemfile
│   ├── _config.yml
│   ├── _data/
│   │   └── toc.yml
│   ├── _docs/
│   │   ├── 01_installation.md
│   │   ├── 02_quick_start.md
│   │   ├── 03_video_tutorials.md
│   │   ├── 06_faq.md
│   │   ├── 07_support.md
│   │   ├── reference/
│   │   │   ├── 03_examples.md
│   │   │   ├── 04_input_reference.md
│   │   │   ├── 05_modifier_reference.md
│   │   │   └── 06_trigger_reference.md
│   │   └── usage/
│   │       ├── 01_concepts.md
│   │       ├── 02_configuration_and_input_handling.md
│   │       ├── 03_input_prompts.md
│   │       ├── 04_extending_guide.md
│   │       ├── 05_remapping_input.md
│   │       ├── 06_virtual_joysticks.md
│   │       └── 07_recipes.md
│   ├── _includes/
│   │   ├── alert.html
│   │   ├── doc.html
│   │   ├── editable.html
│   │   ├── feedback.html
│   │   ├── footer.html
│   │   ├── google-analytics.html
│   │   ├── head.html
│   │   ├── header.html
│   │   ├── navigation.html
│   │   ├── permalinks.html
│   │   ├── quiz/
│   │   │   └── multiple-choice.html
│   │   ├── quiz.html
│   │   ├── scripts.html
│   │   ├── scrolltop.html
│   │   ├── sidebar.html
│   │   ├── tags.html
│   │   ├── toc.html
│   │   └── video.html
│   ├── _layouts/
│   │   ├── default.html
│   │   ├── page.html
│   │   └── post.html
│   ├── _posts/
│   │   └── .gitkeep
│   ├── _recipes/
│   │   ├── 01_driving_a_progress_bar.md
│   │   └── 02_showing_debug_info_with_custom_ui.md
│   ├── assets/
│   │   ├── css/
│   │   │   ├── main.css
│   │   │   └── palette.css
│   │   └── js/
│   │       ├── main.js
│   │       └── search.js
│   ├── docker-compose.yaml
│   └── pages/
│       ├── archive.md
│       ├── feed.xml
│       ├── index.md
│       ├── search.html
│       └── sitemap.xml
├── editorconfig
├── export_presets.cfg
├── ggg.toml
├── guide_examples/
│   ├── 2d_axis_mapping/
│   │   ├── 2d_axis_mapping.gd
│   │   ├── 2d_axis_mapping.gd.uid
│   │   ├── 2d_axis_mapping.tscn
│   │   ├── mapping_contexts/
│   │   │   ├── 2d_axis_mapping.tres
│   │   │   └── move.tres
│   │   ├── player.gd
│   │   └── player.gd.uid
│   ├── action_priority/
│   │   ├── action_priority.gd
│   │   ├── action_priority.gd.uid
│   │   ├── action_priority.tscn
│   │   ├── dpad_spells/
│   │   │   ├── dpad_spells.gd
│   │   │   ├── dpad_spells.gd.uid
│   │   │   └── dpad_spells.tscn
│   │   ├── icons/
│   │   │   ├── enchant-acid-3.png.import
│   │   │   ├── enchant-blue-3.png.import
│   │   │   ├── enchant-jade-3.png.import
│   │   │   ├── enchant-red-3.png.import
│   │   │   ├── fireball-acid-3.png.import
│   │   │   ├── fireball-sky-3.png.import
│   │   │   ├── heal-royal-3.png.import
│   │   │   └── protect-blue-2.png.import
│   │   ├── mapping_contexts/
│   │   │   ├── action_priority.tres
│   │   │   └── actions/
│   │   │       ├── acid_bolt.tres
│   │   │       ├── acid_enchantment.tres
│   │   │       ├── fire_enchantment.tres
│   │   │       ├── heal.tres
│   │   │       ├── healing_enchantment.tres
│   │   │       ├── mana_bolt.tres
│   │   │       ├── mana_enchantment.tres
│   │   │       ├── shield.tres
│   │   │       └── spell_toggle.tres
│   │   └── spell_indicator/
│   │       ├── spell_indicator.gd
│   │       ├── spell_indicator.gd.uid
│   │       └── spell_indicator.tscn
│   ├── combine_contexts/
│   │   ├── combine_contexts.gd
│   │   ├── combine_contexts.gd.uid
│   │   ├── combine_contexts.tscn
│   │   └── mapping_contexts/
│   │       ├── controller.tres
│   │       ├── keyboard_and_mouse.tres
│   │       └── move.tres
│   ├── combos/
│   │   ├── combos.gd
│   │   ├── combos.gd.uid
│   │   ├── combos.tscn
│   │   ├── mapping_contexts/
│   │   │   ├── basic_actions/
│   │   │   │   ├── fire.tres
│   │   │   │   ├── move_horizontal.tres
│   │   │   │   ├── move_left.tres
│   │   │   │   └── move_right.tres
│   │   │   ├── combo_actions/
│   │   │   │   ├── dash_left.tres
│   │   │   │   ├── dash_right.tres
│   │   │   │   ├── fireball_left.tres
│   │   │   │   └── fireball_right.tres
│   │   │   └── combos.tres
│   │   ├── player.gd
│   │   └── player.gd.uid
│   ├── hair_trigger/
│   │   ├── hair_trigger.gd
│   │   ├── hair_trigger.gd.uid
│   │   ├── hair_trigger.tscn
│   │   ├── mapping_contexts/
│   │   │   ├── fire.tres
│   │   │   └── fire_context.tres
│   │   ├── trigger_visualizer.gd
│   │   └── trigger_visualizer.gd.uid
│   ├── input_contexts/
│   │   ├── boat.gd
│   │   ├── boat.gd.uid
│   │   ├── boat.svg.import
│   │   ├── input_contexts.gd
│   │   ├── input_contexts.gd.uid
│   │   ├── input_contexts.tscn
│   │   ├── mapping_contexts/
│   │   │   ├── boat_actions/
│   │   │   │   ├── accelerate.tres
│   │   │   │   ├── leave.tres
│   │   │   │   └── turn.tres
│   │   │   ├── boat_context.tres
│   │   │   ├── player_actions/
│   │   │   │   ├── move.tres
│   │   │   │   └── use.tres
│   │   │   └── player_context.tres
│   │   ├── player.gd
│   │   └── player.gd.uid
│   ├── input_prompts/
│   │   ├── input_prompts.gd
│   │   ├── input_prompts.gd.uid
│   │   ├── input_prompts.tscn
│   │   └── mapping_contexts/
│   │       ├── controller_activated.tres
│   │       ├── fire.tres
│   │       ├── input_prompts.tres
│   │       ├── keyboard_activated.tres
│   │       └── mouse_activated.tres
│   ├── input_scheme_switching/
│   │   ├── input_scheme_switching.gd
│   │   ├── input_scheme_switching.gd.uid
│   │   ├── input_scheme_switching.tscn
│   │   ├── mapping_contexts/
│   │   │   ├── actions/
│   │   │   │   ├── move.tres
│   │   │   │   ├── shoot.tres
│   │   │   │   ├── switch_to_joystick.tres
│   │   │   │   └── switch_to_keyboard.tres
│   │   │   ├── joystick_scheme.tres
│   │   │   └── keyboard_scheme.tres
│   │   ├── player.gd
│   │   └── player.gd.uid
│   ├── mouse_position_2d/
│   │   ├── background.gd
│   │   ├── background.gd.uid
│   │   ├── background.svg.import
│   │   ├── camera_2d.gd
│   │   ├── camera_2d.gd.uid
│   │   ├── godot_head.gd
│   │   ├── godot_head.gd.uid
│   │   ├── godot_head.tscn
│   │   ├── mapping_contexts/
│   │   │   ├── actions/
│   │   │   │   ├── camera_movement.tres
│   │   │   │   ├── camera_zoom.tres
│   │   │   │   ├── cursor.tres
│   │   │   │   └── spawn.tres
│   │   │   ├── modifiers/
│   │   │   │   └── zoom_sensitivity.tres
│   │   │   └── mouse_position.tres
│   │   ├── mouse_position.gd
│   │   ├── mouse_position.gd.uid
│   │   └── mouse_position.tscn
│   ├── mouse_position_3d/
│   │   ├── camera_control.gd
│   │   ├── camera_control.gd.uid
│   │   ├── mapping_context/
│   │   │   ├── actions/
│   │   │   │   ├── camera_move.tres
│   │   │   │   ├── camera_pitch.tres
│   │   │   │   ├── camera_toggle.tres
│   │   │   │   ├── camera_yaw.tres
│   │   │   │   ├── cursor_3d.tres
│   │   │   │   └── select.tres
│   │   │   └── mouse_position_3d.tres
│   │   ├── mou4D8E.tmp
│   │   ├── mouse_indicator.gd
│   │   ├── mouse_indicator.gd.uid
│   │   ├── mouse_position_3d.gd
│   │   ├── mouse_position_3d.gd.uid
│   │   ├── mouse_position_3d.tscn
│   │   ├── player.gd
│   │   └── player.gd.uid
│   ├── quick_start/
│   │   ├── game.gd
│   │   ├── game.gd.uid
│   │   ├── mapping_contexts/
│   │   │   ├── actions/
│   │   │   │   ├── move.tres
│   │   │   │   └── say_hi.tres
│   │   │   └── quickstart.tres
│   │   ├── player.gd
│   │   ├── player.gd.uid
│   │   └── quick_start.tscn
│   ├── remapping/
│   │   ├── mapping_contexts/
│   │   │   ├── binding_controller.tres
│   │   │   ├── binding_keyboard.tres
│   │   │   ├── controller.tres
│   │   │   ├── controller_actions/
│   │   │   │   ├── next_tab.tres
│   │   │   │   ├── player_movement_stick_deadzone.tres
│   │   │   │   ├── player_movement_stick_invert.tres
│   │   │   │   ├── previous_tab.tres
│   │   │   │   ├── switch_to_keyboard.tres
│   │   │   │   └── ui_accept.tres
│   │   │   ├── keyboard.tres
│   │   │   ├── keyboard_actions/
│   │   │   │   └── switch_to_controller.tres
│   │   │   └── shared_actions/
│   │   │       ├── close_menu.tres
│   │   │       ├── fire.tres
│   │   │       ├── open_menu.tres
│   │   │       └── player_movement_2d.tres
│   │   ├── player.gd
│   │   ├── player.gd.uid
│   │   ├── remapping.gd
│   │   ├── remapping.gd.uid
│   │   ├── remapping.tscn
│   │   ├── ui/
│   │   │   ├── binding_row.gd
│   │   │   ├── binding_row.gd.uid
│   │   │   ├── binding_row.tscn
│   │   │   ├── binding_section.gd
│   │   │   ├── binding_section.gd.uid
│   │   │   ├── binding_section.tscn
│   │   │   ├── remapping_dialog.gd
│   │   │   ├── remapping_dialog.gd.uid
│   │   │   └── remapping_dialog.tscn
│   │   ├── utils.gd
│   │   └── utils.gd.uid
│   ├── shared/
│   │   ├── fireball/
│   │   │   ├── fireball.gd
│   │   │   ├── fireball.gd.uid
│   │   │   ├── fireball.svg.import
│   │   │   └── fireball.tscn
│   │   ├── godot_logo.svg.import
│   │   ├── instructions_label.gd
│   │   ├── instructions_label.gd.uid
│   │   └── ui_theme.tres
│   ├── simple_input/
│   │   ├── mapping_contexts/
│   │   │   ├── move_down.tres
│   │   │   ├── move_left.tres
│   │   │   ├── move_right.tres
│   │   │   ├── move_up.tres
│   │   │   └── simple_input.tres
│   │   ├── player.gd
│   │   ├── player.gd.uid
│   │   ├── simple_input.gd
│   │   ├── simple_input.gd.uid
│   │   └── simple_input.tscn
│   ├── tap_and_hold/
│   │   ├── mapping_contexts/
│   │   │   ├── jump.tres
│   │   │   ├── somersault.tres
│   │   │   └── tap_and_hold.tres
│   │   ├── player.gd
│   │   ├── player.gd.uid
│   │   ├── tap_and_hold.gd
│   │   ├── tap_and_hold.gd.uid
│   │   └── tap_and_hold.tscn
│   ├── top_down_shooter/
│   │   ├── bolt/
│   │   │   ├── bolt.gd
│   │   │   ├── bolt.gd.uid
│   │   │   ├── bolt.png.import
│   │   │   └── bolt.tscn
│   │   ├── mapping_contexts/
│   │   │   ├── controller.tres
│   │   │   ├── fire.tres
│   │   │   ├── keyboard_and_mouse.tres
│   │   │   ├── look_absolute.tres
│   │   │   ├── look_relative.tres
│   │   │   ├── move.tres
│   │   │   ├── switch_to_controller.tres
│   │   │   └── switch_to_keyboard_and_mouse.tres
│   │   ├── player/
│   │   │   ├── mrg0000.png.import
│   │   │   ├── player.gd
│   │   │   └── player.gd.uid
│   │   ├── top_down_shooter.gd
│   │   ├── top_down_shooter.gd.uid
│   │   └── top_down_shooter.tscn
│   ├── touch/
│   │   ├── background.gd
│   │   ├── background.gd.uid
│   │   ├── background.svg.import
│   │   ├── camera_2d.gd
│   │   ├── camera_2d.gd.uid
│   │   ├── godot_head.gd
│   │   ├── godot_head.gd.uid
│   │   ├── godot_head.tscn
│   │   ├── mapping_contexts/
│   │   │   ├── actions/
│   │   │   │   ├── camera_movement.tres
│   │   │   │   ├── camera_reset.tres
│   │   │   │   ├── camera_rotation.tres
│   │   │   │   ├── camera_zoom.tres
│   │   │   │   └── spawn.tres
│   │   │   ├── modifiers/
│   │   │   │   └── zoom_sensitivity.tres
│   │   │   └── touch.tres
│   │   ├── placement_indicator/
│   │   │   ├── placement_indicator.gd
│   │   │   ├── placement_indicator.gd.uid
│   │   │   ├── placement_indicator.tscn
│   │   │   └── radial_progress.png.import
│   │   ├── touch.gd
│   │   ├── touch.gd.uid
│   │   └── touch.tscn
│   ├── two_joysticks/
│   │   ├── actions/
│   │   │   ├── player_one_move.tres
│   │   │   └── player_two_move.tres
│   │   ├── modifiers/
│   │   │   └── joystick_deadzone.tres
│   │   ├── player.gd
│   │   ├── player.gd.uid
│   │   ├── two_joysticks.gd
│   │   ├── two_joysticks.gd.uid
│   │   ├── two_joysticks.tres
│   │   └── two_joysticks.tscn
│   ├── virtual_cursor/
│   │   ├── mapping_contexts/
│   │   │   ├── actions/
│   │   │   │   ├── click.tres
│   │   │   │   ├── cursor_2d.tres
│   │   │   │   ├── switch_to_controller.tres
│   │   │   │   └── switch_to_keyboard.tres
│   │   │   ├── controller_mappings.tres
│   │   │   └── keyboard_mappings.tres
│   │   ├── pointable/
│   │   │   ├── pointable.gd
│   │   │   ├── pointable.gd.uid
│   │   │   └── pointable.tscn
│   │   ├── pointer.gd
│   │   ├── pointer.gd.uid
│   │   ├── pointer.svg.import
│   │   ├── virtual_cursor.gd
│   │   ├── virtual_cursor.gd.uid
│   │   └── virtual_cursor.tscn
│   └── virtual_sticks/
│       ├── custom_stick_renderer/
│       │   ├── custom_stick_renderer.gd
│       │   ├── custom_stick_renderer.gd.uid
│       │   ├── custom_stick_renderer.gdshader
│       │   └── custom_stick_renderer.gdshader.uid
│       ├── mapping_contexts/
│       │   ├── fire_projectile.tres
│       │   ├── mapping_context.tres
│       │   ├── move_ship.tres
│       │   └── rotate_ship.tres
│       ├── projectile/
│       │   ├── laser.svg.import
│       │   ├── projectile.gd
│       │   ├── projectile.gd.uid
│       │   └── projectile.tscn
│       ├── ship/
│       │   ├── ship.gd
│       │   ├── ship.gd.uid
│       │   ├── ship.tscn
│       │   └── spaceship.png.import
│       ├── virtual_sticks.gd
│       ├── virtual_sticks.gd.uid
│       └── virtual_sticks.tscn
├── icon.svg.import
├── project.godot
├── run_tests.cmd
└── tests/
    ├── guide_input_matcher.gd
    ├── guide_input_matcher.gd.uid
    ├── guide_test_base.gd
    ├── guide_test_base.gd.uid
    ├── test_action_prioritization.gd
    ├── test_action_prioritization.gd.uid
    ├── test_action_signals.gd
    ├── test_action_signals.gd.uid
    ├── test_any_input.gd
    ├── test_any_input.gd.uid
    ├── test_context_mapping_combine.gd
    ├── test_context_mapping_combine.gd.uid
    ├── test_context_switching.gd
    ├── test_context_switching.gd.uid
    ├── test_down_trigger.gd
    ├── test_down_trigger.gd.uid
    ├── test_guide_default_text_provider.gd
    ├── test_guide_default_text_provider.gd.uid
    ├── test_guide_input_formatter.gd
    ├── test_guide_input_formatter.gd.uid
    ├── test_input_detector.gd
    ├── test_input_detector.gd.uid
    ├── test_input_on_context_change.gd
    ├── test_input_on_context_change.gd.uid
    ├── test_invalid_configuration.gd
    ├── test_invalid_configuration.gd.uid
    ├── test_joy_axis_1d_input.gd
    ├── test_joy_axis_1d_input.gd.uid
    ├── test_joy_axis_2d_input.gd
    ├── test_joy_axis_2d_input.gd.uid
    ├── test_joy_button_input.gd
    ├── test_joy_button_input.gd.uid
    ├── test_key_input.gd
    ├── test_key_input.gd.uid
    ├── test_layered_contexts.gd
    ├── test_layered_contexts.gd.uid
    ├── test_magnitude_modifier.gd
    ├── test_magnitude_modifier.gd.uid
    ├── test_map_range_modifier.gd
    ├── test_map_range_modifier.gd.uid
    ├── test_mouse_axis_1d_input.gd
    ├── test_mouse_axis_1d_input.gd.uid
    ├── test_mouse_axis_2d_input.gd
    ├── test_mouse_axis_2d_input.gd.uid
    ├── test_mouse_button_input.gd
    ├── test_mouse_button_input.gd.uid
    ├── test_multiple_input_events_per_frame.gd
    ├── test_multiple_input_events_per_frame.gd.uid
    ├── test_node_leaks.gd
    ├── test_node_leaks.gd.uid
    ├── test_pause_mode.gd
    ├── test_pause_mode.gd.uid
    ├── test_released_trigger.gd
    ├── test_released_trigger.gd.uid
    ├── test_touch_angle_input.gd
    ├── test_touch_angle_input.gd.uid
    ├── test_touch_axis_1d_input.gd
    ├── test_touch_axis_1d_input.gd.uid
    ├── test_touch_axis_2d_input.gd
    ├── test_touch_axis_2d_input.gd.uid
    ├── test_touch_distance_input.gd
    ├── test_touch_distance_input.gd.uid
    ├── test_touch_position_input.gd
    ├── test_touch_position_input.gd.uid
    ├── test_trigger_hair.gd
    ├── test_trigger_hair.gd.uid
    ├── test_virtual_buttons.gd
    ├── test_virtual_buttons.gd.uid
    ├── test_virtual_cursor.gd
    ├── test_virtual_cursor.gd.uid
    ├── test_virtual_sticks.gd
    └── test_virtual_sticks.gd.uid
Download .txt
SYMBOL INDEX (14 symbols across 3 files)

FILE: addons/gdUnit4/src/mono/GdUnit4CSharpApi.cs
  class GdUnit4CSharpApi (line 11) | public partial class GdUnit4CSharpApi : Godot.GodotObject
    method GetApiType (line 15) | private static Type GetApiType()
    method GdUnit4NetVersion (line 28) | private static Version GdUnit4NetVersion()
    method InvokeApiMethod (line 34) | private static T InvokeApiMethod<T>(string methodName, params object[]...
    method Version (line 40) | public static string Version() => GdUnit4NetVersion().ToString();
    method IsTestSuite (line 42) | public static bool IsTestSuite(string classPath) => InvokeApiMethod<bo...
    method Executor (line 44) | public static RefCounted Executor(Node listener) => InvokeApiMethod<Re...
    method ParseTestSuite (line 46) | public static CsNode? ParseTestSuite(string classPath) => InvokeApiMet...
    method CreateTestSuite (line 48) | public static Dictionary CreateTestSuite(string sourcePath, int lineNu...

FILE: docs/assets/js/main.js
  function bottomPos (line 15) | function bottomPos(element) {
  function addLinksToAnchors (line 62) | function addLinksToAnchors() {

FILE: docs/assets/js/search.js
  function getQueryVariable (line 6) | function getQueryVariable(variable) {
  function getPreview (line 19) | function getPreview(query, content, previewLength) {
  function displaySearchResults (line 62) | function displaySearchResults(results, query) {
Condensed preview — 1272 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,621K chars).
[
  {
    "path": ".gitattributes",
    "chars": 373,
    "preview": "# Normalize EOL for all files that Git considers text files.\n* text=auto eol=lf\n\n# Only include the addons/guide folder "
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 772,
    "preview": "# These are supported funding model platforms\n\ngithub: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [u"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-.md",
    "chars": 429,
    "preview": "---\nname: 'Bug '\nabout: I have encountered a bug\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\nGodot Version (_e.g. 4.2, 4.3,"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.md",
    "chars": 301,
    "preview": "---\nname: Question\nabout: I have a question on how to use the library.\ntitle: ''\nlabels: knowledge\nassignees: ''\n\n---\n\nW"
  },
  {
    "path": ".gitignore",
    "chars": 184,
    "preview": "# Godot 4+ specific ignores\n.godot/\nandroid/\naddons/explore-editor-theme/\n\n# IntelliJ IDEA\n.idea/\n\n# macOS\n.DS_Store\n\nzz"
  },
  {
    "path": ".junie/guidelines.md",
    "chars": 4206,
    "preview": "\n## Generic code guidelines\nAlways use tabs for indentation. Always add GDScript type hints everywhere. When doing null"
  },
  {
    "path": "CHANGES.md",
    "chars": 32870,
    "preview": "# Changelog\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changel"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 1619,
    "preview": "# Contribution guide\n\nFirst off, thanks for considering a contribution to this project!\n\nThe following checklist will he"
  },
  {
    "path": "LICENSE.md",
    "chars": 1061,
    "preview": "Copyright (c) 2024-present Jan Thomä\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof th"
  },
  {
    "path": "README.md",
    "chars": 2367,
    "preview": "# G.U.I.D.E - Godot Unified Input Detection Engine\n\nG.U.I.D.E is an extension for the Godot Engine that allows you to ea"
  },
  {
    "path": "TODO.md",
    "chars": 1276,
    "preview": "# To Do\n\nThis lists the currently open to do items in no particular order.\n\n## Open\n- [ ] The stick renderer throws erro"
  },
  {
    "path": "_assets/.gdignore",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "addons/gdUnit4/GdUnitRunner.cfg",
    "chars": 105,
    "preview": "{\"included\":{\"res://tests/test_layered_contexts.gd\":[]},\"server_port\":31002,\"skipped\":{},\"version\":\"1.0\"}"
  },
  {
    "path": "addons/gdUnit4/LICENSE",
    "chars": 1069,
    "preview": "MIT License\n\nCopyright (c) 2023 Mike Schulze\n\nPermission is hereby granted, free of charge, to any person obtaining a co"
  },
  {
    "path": "addons/gdUnit4/bin/GdUnitBuildTool.gd",
    "chars": 3374,
    "preview": "#!/usr/bin/env -S godot -s\nextends SceneTree\n\nenum {\n\tINIT,\n\tPROCESSING,\n\tEXIT\n}\n\nconst RETURN_SUCCESS  =   0\nconst RETU"
  },
  {
    "path": "addons/gdUnit4/bin/GdUnitBuildTool.gd.uid",
    "chars": 19,
    "preview": "uid://vidr4ejcbkss\n"
  },
  {
    "path": "addons/gdUnit4/bin/GdUnitCmdTool.gd",
    "chars": 20389,
    "preview": "#!/usr/bin/env -S godot -s\nextends SceneTree\n\nconst GdUnitTools := preload(\"res://addons/gdUnit4/src/core/GdUnitTools.gd"
  },
  {
    "path": "addons/gdUnit4/bin/GdUnitCmdTool.gd.uid",
    "chars": 19,
    "preview": "uid://dse8va3nbnsj\n"
  },
  {
    "path": "addons/gdUnit4/bin/GdUnitCopyLog.gd",
    "chars": 5011,
    "preview": "#!/usr/bin/env -S godot -s\nextends MainLoop\n\nconst GdUnitTools := preload(\"res://addons/gdUnit4/src/core/GdUnitTools.gd\""
  },
  {
    "path": "addons/gdUnit4/bin/GdUnitCopyLog.gd.uid",
    "chars": 20,
    "preview": "uid://dy0e4k8e7so0l\n"
  },
  {
    "path": "addons/gdUnit4/plugin.cfg",
    "chars": 137,
    "preview": "[plugin]\n\nname=\"gdUnit4\"\ndescription=\"Unit Testing Framework for Godot Scripts\"\nauthor=\"Mike Schulze\"\nversion=\"4.5.0\"\nsc"
  },
  {
    "path": "addons/gdUnit4/plugin.gd",
    "chars": 2411,
    "preview": "@tool\nextends EditorPlugin\n\nconst GdUnitTools := preload(\"res://addons/gdUnit4/src/core/GdUnitTools.gd\")\nconst GdUnitTes"
  },
  {
    "path": "addons/gdUnit4/plugin.gd.uid",
    "chars": 20,
    "preview": "uid://d2u6j827llq5e\n"
  },
  {
    "path": "addons/gdUnit4/runtest.cmd",
    "chars": 663,
    "preview": "@ECHO OFF\nCLS\n\nIF NOT DEFINED GODOT_BIN (\n\tECHO \"GODOT_BIN is not set.\"\n\tECHO \"Please set the environment variable 'setx"
  },
  {
    "path": "addons/gdUnit4/runtest.sh",
    "chars": 461,
    "preview": "#!/bin/sh\n\nif [ -z \"$GODOT_BIN\" ]; then\n    echo \"'GODOT_BIN' is not set.\"\n    echo \"Please set the environment variable"
  },
  {
    "path": "addons/gdUnit4/src/Comparator.gd",
    "chars": 149,
    "preview": "class_name Comparator\nextends Resource\n\nenum {\n\tEQUAL,\n\tLESS_THAN,\n\tLESS_EQUAL,\n\tGREATER_THAN,\n\tGREATER_EQUAL,\n\tBETWEEN_"
  },
  {
    "path": "addons/gdUnit4/src/Comparator.gd.uid",
    "chars": 20,
    "preview": "uid://ctlh2t38mahwm\n"
  },
  {
    "path": "addons/gdUnit4/src/Fuzzers.gd",
    "chars": 1249,
    "preview": "## A fuzzer implementation to provide default implementation\nclass_name Fuzzers\nextends Resource\n\n\n## Generates an rando"
  },
  {
    "path": "addons/gdUnit4/src/Fuzzers.gd.uid",
    "chars": 20,
    "preview": "uid://byx7ltrjl833o\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitArrayAssert.gd",
    "chars": 6256,
    "preview": "## An Assertion Tool to verify array values\nclass_name GdUnitArrayAssert\nextends GdUnitAssert\n\n\n## Verifies that the cur"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitArrayAssert.gd.uid",
    "chars": 20,
    "preview": "uid://ct0h0f830p6ly\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitAssert.gd",
    "chars": 1244,
    "preview": "## Base interface of all GdUnit asserts\nclass_name GdUnitAssert\nextends RefCounted\n\n\n## Verifies that the current value "
  },
  {
    "path": "addons/gdUnit4/src/GdUnitAssert.gd.uid",
    "chars": 19,
    "preview": "uid://vubel7soheoo\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitAwaiter.gd",
    "chars": 3537,
    "preview": "class_name GdUnitAwaiter\nextends RefCounted\n\n\n# Waits for a specified signal in an interval of 50ms sent from the <sourc"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitAwaiter.gd.uid",
    "chars": 20,
    "preview": "uid://cjk17c1p2qiuo\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitBoolAssert.gd",
    "chars": 1012,
    "preview": "## An Assertion Tool to verify boolean values\nclass_name GdUnitBoolAssert\nextends GdUnitAssert\n\n\n## Verifies that the cu"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitBoolAssert.gd.uid",
    "chars": 19,
    "preview": "uid://0k6b245p1wiy\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitConstants.gd",
    "chars": 156,
    "preview": "class_name GdUnitConstants\nextends RefCounted\n\nconst NO_ARG :Variant = \"<--null-->\"\n\nconst EXPECT_ASSERT_REPORT_FAILURES"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitConstants.gd.uid",
    "chars": 20,
    "preview": "uid://cgkr776yh0rvd\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitDictionaryAssert.gd",
    "chars": 3975,
    "preview": "## An Assertion Tool to verify dictionary\nclass_name GdUnitDictionaryAssert\nextends GdUnitAssert\n\n\n## Verifies that the "
  },
  {
    "path": "addons/gdUnit4/src/GdUnitDictionaryAssert.gd.uid",
    "chars": 20,
    "preview": "uid://bmhd7n6wxvjfx\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitFailureAssert.gd",
    "chars": 1095,
    "preview": "## An assertion tool to verify GDUnit asserts.\n## This assert is for internal use only, to verify that failed asserts wo"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitFailureAssert.gd.uid",
    "chars": 20,
    "preview": "uid://ctcktx3fpdslo\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitFileAssert.gd",
    "chars": 319,
    "preview": "class_name GdUnitFileAssert\nextends GdUnitAssert\n\n\nfunc is_file() -> GdUnitFileAssert:\n\treturn self\n\n\nfunc exists() -> G"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitFileAssert.gd.uid",
    "chars": 19,
    "preview": "uid://786mnwoxl866\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitFloatAssert.gd",
    "chars": 2344,
    "preview": "## An Assertion Tool to verify float values\nclass_name GdUnitFloatAssert\nextends GdUnitAssert\n\n\n## Verifies that the cur"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitFloatAssert.gd.uid",
    "chars": 20,
    "preview": "uid://b1pyvxx07ygya\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitFuncAssert.gd",
    "chars": 1751,
    "preview": "## An Assertion Tool to verify function callback values\nclass_name GdUnitFuncAssert\nextends GdUnitAssert\n\n\n## Verifies t"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitFuncAssert.gd.uid",
    "chars": 20,
    "preview": "uid://c383gmxgtgbmn\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitGodotErrorAssert.gd",
    "chars": 1559,
    "preview": "## An assertion tool to verify for Godot runtime errors like assert() and push notifications like push_error().\nclass_na"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitGodotErrorAssert.gd.uid",
    "chars": 20,
    "preview": "uid://cl8u3n4ao8fhg\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitIntAssert.gd",
    "chars": 2262,
    "preview": "## An Assertion Tool to verify integer values\nclass_name GdUnitIntAssert\nextends GdUnitAssert\n\n## Verifies that the curr"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitIntAssert.gd.uid",
    "chars": 19,
    "preview": "uid://k651n7cj74d2\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitObjectAssert.gd",
    "chars": 1391,
    "preview": "## An Assertion Tool to verify Object values\nclass_name GdUnitObjectAssert\nextends GdUnitAssert\n\n\n## Verifies that the c"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitObjectAssert.gd.uid",
    "chars": 20,
    "preview": "uid://bqe5pqgo35ub3\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitResultAssert.gd",
    "chars": 1045,
    "preview": "## An Assertion Tool to verify Results\nclass_name GdUnitResultAssert\nextends GdUnitAssert\n\n\n## Verifies that the current"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitResultAssert.gd.uid",
    "chars": 19,
    "preview": "uid://pycd4o660wkt\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitSceneRunner.gd",
    "chars": 20308,
    "preview": "## The Scene Runner is a tool used for simulating interactions on a scene.\n## With this tool, you can simulate input eve"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitSceneRunner.gd.uid",
    "chars": 20,
    "preview": "uid://blpb5kd1mhqk4\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitSignalAssert.gd",
    "chars": 1300,
    "preview": "## An Assertion Tool to verify for emitted signals until a waiting time\nclass_name GdUnitSignalAssert\nextends GdUnitAsse"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitSignalAssert.gd.uid",
    "chars": 20,
    "preview": "uid://bk4kqfkqlxokb\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitStringAssert.gd",
    "chars": 2501,
    "preview": "## An Assertion Tool to verify String values\nclass_name GdUnitStringAssert\nextends GdUnitAssert\n\n\n## Verifies that the c"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitStringAssert.gd.uid",
    "chars": 20,
    "preview": "uid://cwp5ce5us8wek\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitTestSuite.gd",
    "chars": 24967,
    "preview": "## The main class for all GdUnit test suites[br]\n## This class is the main class to implement your unit tests[br]\n## You"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitTestSuite.gd.uid",
    "chars": 20,
    "preview": "uid://bbsow5k2y0q4p\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitTuple.gd",
    "chars": 626,
    "preview": "## A tuple implementation to hold two or many values\nclass_name GdUnitTuple\nextends RefCounted\n\nconst NO_ARG :Variant = "
  },
  {
    "path": "addons/gdUnit4/src/GdUnitTuple.gd.uid",
    "chars": 20,
    "preview": "uid://cwcalyadq4276\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitValueExtractor.gd",
    "chars": 259,
    "preview": "## This is the base interface for value extraction\nclass_name GdUnitValueExtractor\nextends RefCounted\n\n\n## Extracts a va"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitValueExtractor.gd.uid",
    "chars": 20,
    "preview": "uid://dd6wo43cc7s5x\n"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitVectorAssert.gd",
    "chars": 1796,
    "preview": "## An Assertion Tool to verify Vector values\nclass_name GdUnitVectorAssert\nextends GdUnitAssert\n\n\n## Verifies that the c"
  },
  {
    "path": "addons/gdUnit4/src/GdUnitVectorAssert.gd.uid",
    "chars": 20,
    "preview": "uid://d0jl2n5k6xvfn\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/CallBackValueProvider.gd",
    "chars": 644,
    "preview": "# a value provider unsing a callback to get `next` value from a certain function\nclass_name CallBackValueProvider\nextend"
  },
  {
    "path": "addons/gdUnit4/src/asserts/CallBackValueProvider.gd.uid",
    "chars": 20,
    "preview": "uid://djwh83x3xq1qa\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/DefaultValueProvider.gd",
    "chars": 234,
    "preview": "# default value provider, simple returns the initial value\nclass_name DefaultValueProvider\nextends ValueProvider\n\nvar _v"
  },
  {
    "path": "addons/gdUnit4/src/asserts/DefaultValueProvider.gd.uid",
    "chars": 20,
    "preview": "uid://b0an8wdbprin0\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdAssertMessages.gd",
    "chars": 27396,
    "preview": "class_name GdAssertMessages\nextends Resource\n\nconst WARN_COLOR = \"#EFF883\"\nconst ERROR_COLOR = \"#CD5C5C\"\nconst VALUE_COL"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdAssertMessages.gd.uid",
    "chars": 20,
    "preview": "uid://c0t4vvxotq3bh\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdAssertReports.gd",
    "chars": 1715,
    "preview": "class_name GdAssertReports\nextends RefCounted\n\nconst LAST_ERROR = \"last_assert_error_message\"\nconst LAST_ERROR_LINE = \"l"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdAssertReports.gd.uid",
    "chars": 19,
    "preview": "uid://7iaiuyltmrq4\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitArrayAssertImpl.gd",
    "chars": 16500,
    "preview": "class_name GdUnitArrayAssertImpl\nextends GdUnitArrayAssert\n\n\nvar _base: GdUnitAssertImpl\nvar _current_value_provider: Va"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitArrayAssertImpl.gd.uid",
    "chars": 19,
    "preview": "uid://ws7gw7v5ooho\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitAssertImpl.gd",
    "chars": 2313,
    "preview": "class_name GdUnitAssertImpl\nextends GdUnitAssert\n\n\nvar _current :Variant\nvar _current_failure_message :String = \"\"\nvar _"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitAssertImpl.gd.uid",
    "chars": 20,
    "preview": "uid://degy1ximnodhd\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitAssertions.gd",
    "chars": 3325,
    "preview": "# Preloads all GdUnit assertions\nclass_name GdUnitAssertions\nextends RefCounted\n\n\n@warning_ignore(\"return_value_discarde"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitAssertions.gd.uid",
    "chars": 20,
    "preview": "uid://dvvf5ab6g1340\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitBoolAssertImpl.gd",
    "chars": 2220,
    "preview": "extends GdUnitBoolAssert\n\nvar _base: GdUnitAssertImpl\n\n\nfunc _init(current :Variant) -> void:\n\t_base = GdUnitAssertImpl."
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitBoolAssertImpl.gd.uid",
    "chars": 20,
    "preview": "uid://cpjmy6h7cmpug\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitDictionaryAssertImpl.gd",
    "chars": 7308,
    "preview": "extends GdUnitDictionaryAssert\n\nvar _base: GdUnitAssertImpl\n\n\nfunc _init(current :Variant) -> void:\n\t_base = GdUnitAsser"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitDictionaryAssertImpl.gd.uid",
    "chars": 19,
    "preview": "uid://o1uqndxexyaf\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitFailureAssertImpl.gd",
    "chars": 4339,
    "preview": "extends GdUnitFailureAssert\n\nconst GdUnitTools := preload(\"res://addons/gdUnit4/src/core/GdUnitTools.gd\")\n\nvar _is_faile"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitFailureAssertImpl.gd.uid",
    "chars": 20,
    "preview": "uid://dirorofm3wv1d\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitFileAssertImpl.gd",
    "chars": 2971,
    "preview": "extends GdUnitFileAssert\n\nconst GdUnitTools := preload(\"res://addons/gdUnit4/src/core/GdUnitTools.gd\")\n\nvar _base: GdUni"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitFileAssertImpl.gd.uid",
    "chars": 20,
    "preview": "uid://c1lt173ig6uup\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitFloatAssertImpl.gd",
    "chars": 4726,
    "preview": "extends GdUnitFloatAssert\n\nvar _base: GdUnitAssertImpl\n\n\nfunc _init(current :Variant) -> void:\n\t_base = GdUnitAssertImpl"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitFloatAssertImpl.gd.uid",
    "chars": 19,
    "preview": "uid://pcig0tou0srk\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitFuncAssertImpl.gd",
    "chars": 5525,
    "preview": "extends GdUnitFuncAssert\n\n\nconst GdUnitTools := preload(\"res://addons/gdUnit4/src/core/GdUnitTools.gd\")\nconst DEFAULT_TI"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitFuncAssertImpl.gd.uid",
    "chars": 20,
    "preview": "uid://bgttxwcyis3mu\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitGodotErrorAssertImpl.gd",
    "chars": 3599,
    "preview": "extends GdUnitGodotErrorAssert\n\nvar _current_error_message :String\nvar _callable :Callable\n\n\nfunc _init(callable :Callab"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitGodotErrorAssertImpl.gd.uid",
    "chars": 20,
    "preview": "uid://bgrbjg0rqe188\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitIntAssertImpl.gd",
    "chars": 4727,
    "preview": "extends GdUnitIntAssert\n\nvar _base: GdUnitAssertImpl\n\n\nfunc _init(current :Variant) -> void:\n\t_base = GdUnitAssertImpl.n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitIntAssertImpl.gd.uid",
    "chars": 20,
    "preview": "uid://bhcsxb02dv1vj\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitObjectAssertImpl.gd",
    "chars": 3310,
    "preview": "extends GdUnitObjectAssert\n\nvar _base: GdUnitAssertImpl\n\n\nfunc _init(current :Variant) -> void:\n\t_base = GdUnitAssertImp"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitObjectAssertImpl.gd.uid",
    "chars": 20,
    "preview": "uid://c4tlt0w3jkdal\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitResultAssertImpl.gd",
    "chars": 3482,
    "preview": "extends GdUnitResultAssert\n\nvar _base: GdUnitAssertImpl\n\n\nfunc _init(current :Variant) -> void:\n\t_base = GdUnitAssertImp"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitResultAssertImpl.gd.uid",
    "chars": 20,
    "preview": "uid://dos1pgw6u4kur\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitSignalAssertImpl.gd",
    "chars": 4441,
    "preview": "extends GdUnitSignalAssert\n\nconst DEFAULT_TIMEOUT := 2000\n\nvar _signal_collector :GdUnitSignalCollector\nvar _emitter :Ob"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitSignalAssertImpl.gd.uid",
    "chars": 19,
    "preview": "uid://8s5hipbagsfw\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitStringAssertImpl.gd",
    "chars": 6788,
    "preview": "extends GdUnitStringAssert\n\nvar _base: GdUnitAssertImpl\n\n\nfunc _init(current :Variant) -> void:\n\t_base = GdUnitAssertImp"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitStringAssertImpl.gd.uid",
    "chars": 20,
    "preview": "uid://bnq8nk54ke5hi\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitVectorAssertImpl.gd",
    "chars": 5934,
    "preview": "extends GdUnitVectorAssert\n\nvar _base: GdUnitAssertImpl\nvar _current_type: int\nvar _type_check: bool\n\nfunc _init(current"
  },
  {
    "path": "addons/gdUnit4/src/asserts/GdUnitVectorAssertImpl.gd.uid",
    "chars": 20,
    "preview": "uid://cq6iem471uog7\n"
  },
  {
    "path": "addons/gdUnit4/src/asserts/ValueProvider.gd",
    "chars": 162,
    "preview": "# base interface for assert value provider\nclass_name ValueProvider\nextends RefCounted\n\nfunc get_value() -> Variant:\n\tre"
  },
  {
    "path": "addons/gdUnit4/src/asserts/ValueProvider.gd.uid",
    "chars": 20,
    "preview": "uid://bw62dgu2b1aok\n"
  },
  {
    "path": "addons/gdUnit4/src/cmd/CmdArgumentParser.gd",
    "chars": 1709,
    "preview": "class_name CmdArgumentParser\nextends RefCounted\n\nvar _options :CmdOptions\nvar _tool_name :String\nvar _parsed_commands :D"
  },
  {
    "path": "addons/gdUnit4/src/cmd/CmdArgumentParser.gd.uid",
    "chars": 20,
    "preview": "uid://bos3yyqltyx8a\n"
  },
  {
    "path": "addons/gdUnit4/src/cmd/CmdCommand.gd",
    "chars": 500,
    "preview": "class_name CmdCommand\nextends RefCounted\n\nvar _name: String\nvar _arguments: PackedStringArray\n\n\nfunc _init(p_name :Strin"
  },
  {
    "path": "addons/gdUnit4/src/cmd/CmdCommand.gd.uid",
    "chars": 20,
    "preview": "uid://drrvmtivvquyj\n"
  },
  {
    "path": "addons/gdUnit4/src/cmd/CmdCommandHandler.gd",
    "chars": 4725,
    "preview": "class_name CmdCommandHandler\nextends RefCounted\n\nconst CB_SINGLE_ARG = 0\nconst CB_MULTI_ARGS = 1\nconst NO_CB := Callable"
  },
  {
    "path": "addons/gdUnit4/src/cmd/CmdCommandHandler.gd.uid",
    "chars": 19,
    "preview": "uid://uo2m211sso00\n"
  },
  {
    "path": "addons/gdUnit4/src/cmd/CmdConsole.gd",
    "chars": 3350,
    "preview": "# prototype of console with CSI support\n# https://notes.burke.libbey.me/ansi-escape-codes/\nclass_name CmdConsole\nextends"
  },
  {
    "path": "addons/gdUnit4/src/cmd/CmdConsole.gd.uid",
    "chars": 19,
    "preview": "uid://1w10f5i1ybih\n"
  },
  {
    "path": "addons/gdUnit4/src/cmd/CmdOption.gd",
    "chars": 1365,
    "preview": "class_name CmdOption\nextends RefCounted\n\n\nvar _commands :PackedStringArray\nvar _help :String\nvar _description :String\nva"
  },
  {
    "path": "addons/gdUnit4/src/cmd/CmdOption.gd.uid",
    "chars": 19,
    "preview": "uid://4xs88x0hyv5b\n"
  },
  {
    "path": "addons/gdUnit4/src/cmd/CmdOptions.gd",
    "chars": 685,
    "preview": "class_name CmdOptions\nextends RefCounted\n\n\nvar _default_options :Array[CmdOption]\nvar _advanced_options :Array[CmdOption"
  },
  {
    "path": "addons/gdUnit4/src/cmd/CmdOptions.gd.uid",
    "chars": 19,
    "preview": "uid://42l0nbnkkbtk\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdArrayTools.gd",
    "chars": 3494,
    "preview": "## Small helper tool to work with Godot Arrays\nclass_name GdArrayTools\nextends RefCounted\n\n\nconst max_elements := 32\ncon"
  },
  {
    "path": "addons/gdUnit4/src/core/GdArrayTools.gd.uid",
    "chars": 20,
    "preview": "uid://dy4au3f07f8wa\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdDiffTool.gd",
    "chars": 5367,
    "preview": "# A tool to find differences between two objects\nclass_name GdDiffTool\nextends RefCounted\n\n\nconst DIV_ADD :int = 214\ncon"
  },
  {
    "path": "addons/gdUnit4/src/core/GdDiffTool.gd.uid",
    "chars": 20,
    "preview": "uid://b16qmpeok3it5\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdFunctionDoubler.gd",
    "chars": 8346,
    "preview": "class_name GdFunctionDoubler\nextends RefCounted\n\nconst DEFAULT_TYPED_RETURN_VALUES := {\n\tTYPE_NIL: \"null\",\n\tTYPE_BOOL: \""
  },
  {
    "path": "addons/gdUnit4/src/core/GdFunctionDoubler.gd.uid",
    "chars": 20,
    "preview": "uid://dk4epec08vtj2\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdObjects.gd",
    "chars": 25164,
    "preview": "# This is a helper class to compare two objects by equals\nclass_name GdObjects\nextends Resource\n\nconst GdUnitTools := pr"
  },
  {
    "path": "addons/gdUnit4/src/core/GdObjects.gd.uid",
    "chars": 20,
    "preview": "uid://dc02g2g1th4oy\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnit4Version.gd",
    "chars": 1862,
    "preview": "class_name GdUnit4Version\nextends RefCounted\n\nconst VERSION_PATTERN = \"[center][color=#9887c4]gd[/color][color=#7a57d6]U"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnit4Version.gd.uid",
    "chars": 20,
    "preview": "uid://cd1awsisgh3uq\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitClassDoubler.gd",
    "chars": 5539,
    "preview": "# A class doubler used to mock and spy checked implementations\nclass_name GdUnitClassDoubler\nextends RefCounted\n\n\nconst "
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitClassDoubler.gd.uid",
    "chars": 20,
    "preview": "uid://b611k0ri8qpm6\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitFileAccess.gd",
    "chars": 7281,
    "preview": "class_name GdUnitFileAccess\nextends RefCounted\n\nconst GDUNIT_TEMP := \"user://tmp\"\n\n\nstatic func current_dir() -> String:"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitFileAccess.gd.uid",
    "chars": 20,
    "preview": "uid://ctwcjgw3wr3db\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitObjectInteractions.gd",
    "chars": 1915,
    "preview": "class_name GdUnitObjectInteractions\nextends RefCounted\n\n\nstatic func verify(interaction_object :Object, interactions_tim"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitObjectInteractions.gd.uid",
    "chars": 19,
    "preview": "uid://07uhodm4ysvl\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitObjectInteractionsTemplate.gd",
    "chars": 3360,
    "preview": "\nvar __expected_interactions :int = -1\nvar __saved_interactions := Dictionary()\nvar __verified_interactions := Array()\n\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitObjectInteractionsTemplate.gd.uid",
    "chars": 20,
    "preview": "uid://d30lgjpg21aut\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitProperty.gd",
    "chars": 1363,
    "preview": "class_name GdUnitProperty\nextends RefCounted\n\n\nvar _name :String\nvar _help :String\nvar _type :int\nvar _value :Variant\nva"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitProperty.gd.uid",
    "chars": 20,
    "preview": "uid://c0nnmmmyuv18v\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitResult.gd",
    "chars": 2293,
    "preview": "class_name GdUnitResult\nextends RefCounted\n\nenum {\n\tSUCCESS,\n\tWARN,\n\tERROR,\n\tEMPTY\n}\n\nvar _state: int\nvar _warn_message "
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitResult.gd.uid",
    "chars": 20,
    "preview": "uid://dyg2klxre6ly7\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitRunner.gd",
    "chars": 5464,
    "preview": "extends Node\n\n@onready var _client :GdUnitTcpClient = $GdUnitTcpClient\n@onready var _executor :GdUnitTestSuiteExecutor ="
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitRunner.gd.uid",
    "chars": 20,
    "preview": "uid://c7wu0u21yncv5\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitRunner.tscn",
    "chars": 385,
    "preview": "[gd_scene load_steps=3 format=3 uid=\"uid://belidlfknh74r\"]\n\n[ext_resource type=\"Script\" path=\"res://addons/gdUnit4/src/c"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitRunnerConfig.gd",
    "chars": 5607,
    "preview": "class_name GdUnitRunnerConfig\nextends Resource\n\nconst GdUnitTools := preload(\"res://addons/gdUnit4/src/core/GdUnitTools."
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitRunnerConfig.gd.uid",
    "chars": 20,
    "preview": "uid://dhcoabne4hy87\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitSceneRunnerImpl.gd",
    "chars": 23945,
    "preview": "# This class provides a runner for scense to simulate interactions like keyboard or mouse\nclass_name GdUnitSceneRunnerIm"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitSceneRunnerImpl.gd.uid",
    "chars": 20,
    "preview": "uid://ba3nuheatpt6y\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitScriptType.gd",
    "chars": 300,
    "preview": "class_name GdUnitScriptType\nextends RefCounted\n\nconst UNKNOWN := \"\"\nconst CS := \"cs\"\nconst GD := \"gd\"\n\n\nstatic func type"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitScriptType.gd.uid",
    "chars": 20,
    "preview": "uid://clunbra827ekj\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitSettings.gd",
    "chars": 16913,
    "preview": "@tool\nclass_name GdUnitSettings\nextends RefCounted\n\n\nconst MAIN_CATEGORY = \"gdunit4\"\n# Common Settings\nconst COMMON_SETT"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitSettings.gd.uid",
    "chars": 20,
    "preview": "uid://b2d7jj4pvo14x\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitSignalAwaiter.gd",
    "chars": 2188,
    "preview": "class_name GdUnitSignalAwaiter\nextends RefCounted\n\nsignal signal_emitted(action :Variant)\n\nconst NO_ARG :Variant = GdUni"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitSignalAwaiter.gd.uid",
    "chars": 20,
    "preview": "uid://c65sgy1avbnbl\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitSignalCollector.gd",
    "chars": 4838,
    "preview": "# It connects to all signals of given emitter and collects received signals and arguments\n# The collected signals are cl"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitSignalCollector.gd.uid",
    "chars": 19,
    "preview": "uid://xgc30hv7dy8h\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitSignals.gd",
    "chars": 1431,
    "preview": "class_name GdUnitSignals\nextends RefCounted\n\n@warning_ignore(\"unused_signal\")\nsignal gdunit_client_connected(client_id :"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitSignals.gd.uid",
    "chars": 20,
    "preview": "uid://dwtotu432whd8\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitSingleton.gd",
    "chars": 2520,
    "preview": "################################################################################\n# Provides access to a global accessibl"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitSingleton.gd.uid",
    "chars": 20,
    "preview": "uid://blkbl1d8o6h6w\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitTestSuiteBuilder.gd",
    "chars": 1073,
    "preview": "class_name GdUnitTestSuiteBuilder\nextends RefCounted\n\n\nstatic func create(source :Script, line_number :int) -> GdUnitRes"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitTestSuiteBuilder.gd.uid",
    "chars": 19,
    "preview": "uid://pxvyod2o5cs4\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitTestSuiteScanner.gd",
    "chars": 15275,
    "preview": "class_name GdUnitTestSuiteScanner\nextends RefCounted\n\nconst TEST_FUNC_TEMPLATE =\"\"\"\n\nfunc test_${func_name}() -> void:\n\t"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitTestSuiteScanner.gd.uid",
    "chars": 20,
    "preview": "uid://dvoleq3hg4218\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitTools.gd",
    "chars": 4364,
    "preview": "extends RefCounted\n\n\nstatic var _richtext_normalize: RegEx\n\n\nstatic func normalize_text(text :String) -> String:\n\treturn"
  },
  {
    "path": "addons/gdUnit4/src/core/GdUnitTools.gd.uid",
    "chars": 20,
    "preview": "uid://baklr6vat4021\n"
  },
  {
    "path": "addons/gdUnit4/src/core/GodotVersionFixures.gd",
    "chars": 827,
    "preview": "## This service class contains helpers to wrap Godot functions and handle them carefully depending on the current Godot "
  },
  {
    "path": "addons/gdUnit4/src/core/GodotVersionFixures.gd.uid",
    "chars": 20,
    "preview": "uid://dkqo6k5uvv180\n"
  },
  {
    "path": "addons/gdUnit4/src/core/LocalTime.gd",
    "chars": 2751,
    "preview": "# This class provides Date/Time functionallity to Godot\nclass_name LocalTime\nextends Resource\n\nenum TimeUnit {\n\tDEFAULT "
  },
  {
    "path": "addons/gdUnit4/src/core/LocalTime.gd.uid",
    "chars": 20,
    "preview": "uid://b0j7bpvdh6tve\n"
  },
  {
    "path": "addons/gdUnit4/src/core/_TestCase.gd",
    "chars": 6145,
    "preview": "class_name _TestCase\nextends Node\n\nsignal completed()\n\n# default timeout 5min\nconst DEFAULT_TIMEOUT := -1\nconst ARGUMENT"
  },
  {
    "path": "addons/gdUnit4/src/core/_TestCase.gd.uid",
    "chars": 19,
    "preview": "uid://4u8xyk0gp46u\n"
  },
  {
    "path": "addons/gdUnit4/src/core/assets/touch-button.png.import",
    "chars": 801,
    "preview": "[remap]\n\nimporter=\"texture\"\ntype=\"CompressedTexture2D\"\nuid=\"uid://btx5kcrsngasl\"\npath=\"res://.godot/imported/touch-butto"
  },
  {
    "path": "addons/gdUnit4/src/core/command/GdUnitCommand.gd",
    "chars": 931,
    "preview": "class_name GdUnitCommand\nextends RefCounted\n\n\nfunc _init(p_name :String, p_is_enabled: Callable, p_runnable: Callable, p"
  },
  {
    "path": "addons/gdUnit4/src/core/command/GdUnitCommand.gd.uid",
    "chars": 19,
    "preview": "uid://61ky27ug1ray\n"
  },
  {
    "path": "addons/gdUnit4/src/core/command/GdUnitCommandHandler.gd",
    "chars": 14586,
    "preview": "class_name GdUnitCommandHandler\nextends Object\n\nsignal gdunit_runner_start()\nsignal gdunit_runner_stop(client_id :int)\n\n"
  },
  {
    "path": "addons/gdUnit4/src/core/command/GdUnitCommandHandler.gd.uid",
    "chars": 20,
    "preview": "uid://bmxpnufp6mt7s\n"
  },
  {
    "path": "addons/gdUnit4/src/core/command/GdUnitShortcut.gd",
    "chars": 1884,
    "preview": "class_name GdUnitShortcut\nextends RefCounted\n\n\nenum ShortCut {\n\tNONE,\n\tRUN_TESTS_OVERALL,\n\tRUN_TESTCASE,\n\tRUN_TESTCASE_D"
  },
  {
    "path": "addons/gdUnit4/src/core/command/GdUnitShortcut.gd.uid",
    "chars": 19,
    "preview": "uid://tlwbwprvc14u\n"
  },
  {
    "path": "addons/gdUnit4/src/core/command/GdUnitShortcutAction.gd",
    "chars": 786,
    "preview": "class_name GdUnitShortcutAction\nextends RefCounted\n\n\nfunc _init(p_type :GdUnitShortcut.ShortCut, p_shortcut :Shortcut, p"
  },
  {
    "path": "addons/gdUnit4/src/core/command/GdUnitShortcutAction.gd.uid",
    "chars": 20,
    "preview": "uid://c04l7ol71n4bu\n"
  },
  {
    "path": "addons/gdUnit4/src/core/discovery/GdUnitTestDiscoverGuard.gd",
    "chars": 6690,
    "preview": "extends RefCounted\n\n\n# Caches all test indices for parameterized tests\nclass TestCaseIndicesCache:\n\tvar _cache := {}\n\n\tf"
  },
  {
    "path": "addons/gdUnit4/src/core/discovery/GdUnitTestDiscoverGuard.gd.uid",
    "chars": 20,
    "preview": "uid://bij4y2rn8dykj\n"
  },
  {
    "path": "addons/gdUnit4/src/core/discovery/GdUnitTestDiscoverer.gd",
    "chars": 1620,
    "preview": "class_name GdUnitTestDiscoverer\nextends RefCounted\n\n\nstatic func run() -> void:\n\tprints(\"Running test discovery ..\")\n\tGd"
  },
  {
    "path": "addons/gdUnit4/src/core/discovery/GdUnitTestDiscoverer.gd.uid",
    "chars": 20,
    "preview": "uid://bgv52sic586h3\n"
  },
  {
    "path": "addons/gdUnit4/src/core/event/GdUnitEvent.gd",
    "chars": 5216,
    "preview": "class_name GdUnitEvent\nextends Resource\n\nconst WARNINGS = \"warnings\"\nconst FAILED = \"failed\"\nconst FLAKY = \"flaky\"\nconst"
  },
  {
    "path": "addons/gdUnit4/src/core/event/GdUnitEvent.gd.uid",
    "chars": 20,
    "preview": "uid://dtevq4bpw7wu7\n"
  },
  {
    "path": "addons/gdUnit4/src/core/event/GdUnitEventInit.gd",
    "chars": 339,
    "preview": "class_name GdUnitInit\nextends GdUnitEvent\n\n\nvar _total_testsuites :int\n\n\nfunc _init(p_total_testsuites :int, p_total_cou"
  },
  {
    "path": "addons/gdUnit4/src/core/event/GdUnitEventInit.gd.uid",
    "chars": 18,
    "preview": "uid://ne3d7ha8m6r\n"
  },
  {
    "path": "addons/gdUnit4/src/core/event/GdUnitEventStop.gd",
    "chars": 86,
    "preview": "class_name GdUnitStop\nextends GdUnitEvent\n\n\nfunc _init() -> void:\n\t_event_type = STOP\n"
  },
  {
    "path": "addons/gdUnit4/src/core/event/GdUnitEventStop.gd.uid",
    "chars": 20,
    "preview": "uid://dalj3bau3dnu7\n"
  },
  {
    "path": "addons/gdUnit4/src/core/event/GdUnitEventTestDiscoverEnd.gd",
    "chars": 351,
    "preview": "class_name GdUnitEventTestDiscoverEnd\nextends GdUnitEvent\n\n\nvar _total_testsuites: int\n\n\nfunc _init(testsuite_count: int"
  },
  {
    "path": "addons/gdUnit4/src/core/event/GdUnitEventTestDiscoverEnd.gd.uid",
    "chars": 20,
    "preview": "uid://co2w6mhr7n2q7\n"
  },
  {
    "path": "addons/gdUnit4/src/core/event/GdUnitEventTestDiscoverStart.gd",
    "chars": 114,
    "preview": "class_name GdUnitEventTestDiscoverStart\nextends GdUnitEvent\n\n\nfunc _init() -> void:\n\t_event_type = DISCOVER_START\n"
  }
]

// ... and 1072 more files (download for full content)

About this extraction

This page contains the full source code of the godotneers/G.U.I.D.E GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1272 files (2.3 MB), approximately 666.0k tokens, and a symbol index with 14 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!