├── .github
└── workflows
│ ├── deploy.yml
│ └── tests.yml
├── .gitignore
├── .gitmodules
├── CSharpScriptsTable.json
├── GodotFixedVolatilePhysics.csproj
├── GodotFixedVolatilePhysics.sln
├── LICENSE
├── README.md
├── ReadmeAssets
├── FullPhysicsTest.gif
├── KinematicBody.gif
└── PhysicsTest.gif
├── addons
├── GodotFixedVolatilePhysics
│ ├── Assets
│ │ ├── SimpleForce.svg
│ │ ├── SimpleForce.svg.import
│ │ ├── VoltArea.svg
│ │ ├── VoltArea.svg.import
│ │ ├── VoltKinematicBody.svg
│ │ ├── VoltKinematicBody.svg.import
│ │ ├── VoltNode2D.svg
│ │ ├── VoltNode2D.svg.import
│ │ ├── VoltPolygon.svg
│ │ ├── VoltPolygon.svg.import
│ │ ├── VoltRect.svg
│ │ ├── VoltRect.svg.import
│ │ ├── VoltRigidBody.svg
│ │ ├── VoltRigidBody.svg.import
│ │ ├── VoltStaticBody.svg
│ │ ├── VoltStaticBody.svg.import
│ │ ├── VoltWorld.svg
│ │ └── VoltWorld.svg.import
│ ├── Core
│ │ ├── Palette.cs
│ │ ├── SimpleForce.cs
│ │ ├── Test.cs
│ │ ├── TypeSerializers
│ │ │ ├── ArraySerializer.cs
│ │ │ ├── TypeSerializer.cs
│ │ │ └── TypeSerializers.cs
│ │ ├── Types
│ │ │ ├── VoltMatrix.cs
│ │ │ ├── VoltRect2.cs
│ │ │ └── VoltTransform2D.cs
│ │ ├── Utils.cs
│ │ ├── VolatileBodies
│ │ │ ├── VolatileArea.cs
│ │ │ ├── VolatileBody.cs
│ │ │ ├── VolatileKinematicBody.cs
│ │ │ ├── VolatileRigidBody.cs
│ │ │ └── VolatileStaticBody.cs
│ │ ├── VolatileExtensions.cs
│ │ ├── VolatileShapes
│ │ │ ├── VolatileCircle.cs
│ │ │ ├── VolatilePolygon.cs
│ │ │ ├── VolatileRect.cs
│ │ │ └── VolatileShape.cs
│ │ ├── VolatileWorld.cs
│ │ ├── VoltNode2D.cs
│ │ └── VoltType.cs
│ ├── Libraries
│ │ ├── FixedMath.Net
│ │ │ ├── LICENSE.txt
│ │ │ ├── README.txt
│ │ │ └── src
│ │ │ │ ├── Fix64.cs
│ │ │ │ ├── Fix64SinLut.cs
│ │ │ │ └── Fix64TanLut.cs
│ │ └── VolatilePhysics
│ │ │ ├── Extensions
│ │ │ └── VoltExplosion.cs
│ │ │ ├── Internals
│ │ │ ├── Axis.cs
│ │ │ ├── Broadphase
│ │ │ │ ├── IBroadphase.cs
│ │ │ │ ├── NaiveBroadphase.cs
│ │ │ │ └── TreeBroadphase.cs
│ │ │ ├── CheapList.cs
│ │ │ ├── Collision
│ │ │ │ ├── Collision.cs
│ │ │ │ ├── Contact.cs
│ │ │ │ └── Manifold.cs
│ │ │ ├── History
│ │ │ │ ├── HistoryBuffer.cs
│ │ │ │ └── HistoryRecord.cs
│ │ │ └── IIndexedValue.cs
│ │ │ ├── RayCast
│ │ │ ├── VoltRayCast.cs
│ │ │ └── VoltRayResult.cs
│ │ │ ├── Shapes
│ │ │ ├── VoltCircle.cs
│ │ │ └── VoltPolygon.cs
│ │ │ ├── Structs
│ │ │ └── VoltShapeCollision.cs
│ │ │ ├── Util
│ │ │ ├── Debug
│ │ │ │ └── VoltDebug.cs
│ │ │ ├── Pooling
│ │ │ │ ├── IVoltPoolable.cs
│ │ │ │ └── VoltPool.cs
│ │ │ └── VoltUtil.cs
│ │ │ ├── VoltAABB.cs
│ │ │ ├── VoltBody.cs
│ │ │ ├── VoltBuffer.cs
│ │ │ ├── VoltCollisionFilters.cs
│ │ │ ├── VoltConfig.cs
│ │ │ ├── VoltMath.cs
│ │ │ ├── VoltShape.cs
│ │ │ ├── VoltVector2.cs
│ │ │ └── VoltWorld.cs
│ ├── Plugin.cs
│ ├── Plugins
│ │ ├── VolatileNodesPlugin
│ │ │ └── VolatileNodesPlugin.cs
│ │ ├── VolatileShapePlugins
│ │ │ ├── PointsEditorPlugin.cs
│ │ │ ├── VolatileCirclePlugin.cs
│ │ │ ├── VolatilePolygonPlugin.cs
│ │ │ ├── VolatileRectPlugin.cs
│ │ │ └── VolatileShapeEditorPlugin.cs
│ │ └── VoltTypesPlugin
│ │ │ ├── EditorProperties
│ │ │ ├── CompoundSerializedEditorProperty.cs
│ │ │ ├── EditorPropertyExtens.cs
│ │ │ ├── ExtendedEditorProperty.cs
│ │ │ ├── ExtendedEditorPropertyParser.cs
│ │ │ ├── Fix64EditorProperty.cs
│ │ │ ├── SerializedEditorProperty.cs
│ │ │ ├── SerializedEditorPropertyParser.cs
│ │ │ ├── VoltArrayEditorProperty.cs
│ │ │ ├── VoltRect2EditorProperty.cs
│ │ │ ├── VoltTransform2DEditorProperty.cs
│ │ │ └── VoltVector2EditorProperty.cs
│ │ │ ├── VoltPropertyHint.cs
│ │ │ ├── VoltTypesInspectorPlugin.cs
│ │ │ └── VoltTypesPlugin.cs
│ └── plugin.cfg
├── GodotVisualStudioStub
│ └── StubProject.csproj
├── VirtualJoystick
│ ├── VirtualJoystick.cs
│ ├── textures
│ │ ├── joystick_base_outline.png
│ │ ├── joystick_base_outline.png.import
│ │ ├── joystick_tip.png
│ │ ├── joystick_tip.png.import
│ │ ├── joystick_tip_arrows.png
│ │ └── joystick_tip_arrows.png.import
│ ├── virtual_joystick.gd
│ └── virtual_joystick.tscn
└── WAT
│ ├── LICENSE
│ ├── assertions
│ ├── .idea
│ │ └── .idea.assertions.dir
│ │ │ └── .idea
│ │ │ ├── encodings.xml
│ │ │ ├── indexLayout.xml
│ │ │ ├── projectSettingsUpdater.xml
│ │ │ ├── vcs.xml
│ │ │ └── workspace.xml
│ ├── assertion.gd
│ ├── assertions.gd
│ ├── boolean.gd
│ ├── collections.gd
│ ├── double.gd
│ ├── equality.gd
│ ├── file.gd
│ ├── folder.gd
│ ├── is.gd
│ ├── is_not.gd
│ ├── null.gd
│ ├── object.gd
│ ├── property.gd
│ ├── range.gd
│ ├── signal.gd
│ ├── string.gd
│ └── utility.gd
│ ├── assets
│ ├── debug_failed.png
│ ├── debug_failed.png.import
│ ├── docs.svg
│ ├── docs.svg.import
│ ├── failed.png
│ ├── failed.png.import
│ ├── folder.png
│ ├── folder.png.import
│ ├── function.png
│ ├── function.png.import
│ ├── issue.svg
│ ├── issue.svg.import
│ ├── kofi.png
│ ├── kofi.png.import
│ ├── label.png
│ ├── label.png.import
│ ├── passed.png
│ ├── passed.png.import
│ ├── play.png
│ ├── play.png.import
│ ├── play_debug.png
│ ├── play_debug.png.import
│ ├── play_failed.png
│ ├── play_failed.png.import
│ ├── request_docs.svg
│ ├── request_docs.svg.import
│ ├── script.png
│ ├── script.png.import
│ ├── timer.png
│ └── timer.png.import
│ ├── cli.tscn
│ ├── double
│ ├── factory.gd
│ ├── method.gd
│ ├── methods.gd
│ ├── registry.gd
│ ├── scene_director.gd
│ ├── script_director.gd
│ └── script_writer.gd
│ ├── filesystem
│ ├── directory.gd
│ ├── failed.gd
│ ├── filesystem.gd
│ ├── method.gd
│ ├── script.gd
│ ├── tagged.gd
│ ├── tracker.gd
│ ├── validator.gd
│ └── yield_calculator.gd
│ ├── gui.tscn
│ ├── io
│ ├── junit_xml.gd
│ └── metadata.gd
│ ├── mono
│ ├── Attributes.cs
│ ├── BuildScene.cs
│ ├── BuildScene.tscn
│ ├── GDScriptWrapper.cs
│ ├── Test.cs
│ └── assertions
│ │ ├── Assertion.cs
│ │ ├── Assertions.cs
│ │ ├── Boolean.cs
│ │ ├── Equality.cs
│ │ ├── File.cs
│ │ ├── Is.cs
│ │ ├── Null.cs
│ │ ├── ObjectX.cs
│ │ ├── Property.cs
│ │ ├── Range.cs
│ │ ├── Signal.cs
│ │ ├── StringX.cs
│ │ └── Utility.cs
│ ├── namespace.gd
│ ├── network
│ ├── test_client.gd
│ ├── test_network.gd
│ └── test_server.gd
│ ├── plugin.cfg
│ ├── plugin.gd
│ ├── runner
│ ├── TestRunner.gd
│ ├── TestRunner.tscn
│ ├── splitter.gd
│ └── test_controller.gd
│ ├── settings.gd
│ ├── test
│ ├── any.gd
│ ├── case.gd
│ ├── parameters.gd
│ ├── recorder.gd
│ ├── test.gd
│ ├── watcher.gd
│ └── yielder.gd
│ └── ui
│ ├── cli.gd
│ ├── docker.gd
│ ├── gui.gd
│ ├── links.gd
│ ├── results
│ ├── assertion.gd
│ ├── counter.gd
│ ├── method.gd
│ ├── script.gd
│ ├── tab.gd
│ ├── tab_container.gd
│ └── tree.gd
│ ├── scaling
│ ├── dynamic_size_spinbox.gd
│ ├── icons.gd
│ ├── plugin_assets_registry.gd
│ └── scene_tree_adjuster.gd
│ ├── summary.gd
│ └── test_menu.gd
├── bootsplash.png
├── bootsplash.png.import
├── default_env.tres
├── icon.png
├── icon.png.import
├── project.godot
└── tests
├── Manual
├── Physics
│ ├── CompleteTest.tscn
│ ├── FPSCounter.cs
│ ├── GDKinematicMovement.cs
│ ├── GDPhysics2DTesting.tscn
│ ├── PhysicsHighEndTest.tscn
│ ├── PhysicsLowEndTest.tscn
│ ├── PolygonTests.tscn
│ └── Prefabs
│ │ ├── DispersedDynamicGroupPrefab.tscn
│ │ ├── DynamicGroupPrefab.tscn
│ │ ├── VolatileAreaTestPrefab.tscn
│ │ └── VolatileKinematicMovementPrefab.tscn
└── VoltNode2D
│ ├── FixedMovement.cs
│ ├── VolatileAreaTest.cs
│ ├── VolatileKinematicBodyMovement.cs
│ └── VoltNode2DTest.tscn
├── VoltMatrixTests.cs
├── VoltNode2DTests.cs
└── VoltTransform2DTests.cs
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: 🚀 Deploy Release
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | tags:
8 | - "v*.*.*"
9 |
10 | jobs:
11 | deploy:
12 | name: Deploy
13 | runs-on: ubuntu-latest
14 | steps:
15 | - name: Checkout Repository
16 | uses: actions/checkout@v3
17 |
18 | - name: Update Submodules
19 | run: git submodule update --init
20 |
21 | # Deploy to local repo
22 | - name: Deploy to Release Branch
23 | uses: s0/git-publish-subdir-action@develop
24 | env:
25 | REPO: self
26 | BRANCH: release
27 | FOLDER: addons/GodotFixedVolatilePhysics
28 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29 |
30 | - name: Create Release
31 | run: |
32 | mkdir release
33 | mv addons/GodotFixedVolatilePhysics release
34 | pushd release
35 | zip -r ../Release.zip *
36 | popd
37 |
38 | - name: Upload Release
39 | uses: actions/upload-artifact@v2
40 | with:
41 | name: Release
42 | path: release
43 |
44 | - name: Tagged Release
45 | uses: softprops/action-gh-release@v1
46 | if: startsWith(github.ref, 'refs/tags/')
47 | with:
48 | files: Release.zip
49 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: 🧪 Run Unit Tests
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | Tests:
7 | name: Run All Tests on 3.5
8 | runs-on: ubuntu-latest
9 | container: barichello/godot-ci:mono-3.5
10 | steps:
11 | - name: Checkout Repository
12 | uses: actions/checkout@v3
13 | with:
14 | submodules: recursive
15 |
16 | - name: Install Dependencies
17 | run: |
18 | nuget restore
19 | mkdir -p .mono/assemblies/Debug
20 | cp /usr/local/bin/GodotSharp/Api/Release/* .mono/assemblies/Debug
21 |
22 | - name: Compile
23 | run: msbuild
24 |
25 | - name: Run
26 | run: godot addons/WAT/cli.tscn run=all
27 |
28 | - name: Upload Test Results
29 | if: always()
30 | uses: actions/upload-artifact@v2
31 | with:
32 | name: Test Results
33 | path: tests/results.xml
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Godot-specific ignores
2 | .import/
3 | export.cfg
4 | export_presets.cfg
5 |
6 | # Mono-specific ignores
7 | .mono/
8 | data_*/
9 |
10 | # VSCode Settings
11 | .vscode/
12 |
13 | # Visual studio
14 | .vs/
15 |
16 | Builds/
17 |
18 | # Ignore stub bin and obj folders
19 | bin/
20 | obj/
21 |
22 | # Tests
23 | tests/results.xml
24 | tests/metadata.json
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "addons/FracturalCommons"]
2 | path = addons/FracturalCommons
3 | url = https://github.com/Fractural/FracturalCommons.git
4 | branch = release
5 |
--------------------------------------------------------------------------------
/GodotFixedVolatilePhysics.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net472
4 |
5 |
6 |
7 | $(DefineConstants);GODOT_3_4_0_OR_NEWER
8 | $(DefineConstants);GODOT_3_4_1_OR_NEWER
9 | $(DefineConstants);GODOT_3_4_2_OR_NEWER
10 | $(DefineConstants);GODOT_3_4_3_OR_NEWER
11 | $(DefineConstants);GODOT_3_4_4_OR_NEWER
12 | $(DefineConstants);GODOT_3_4_5_OR_NEWER
13 | $(DefineConstants);GODOT_3_5_0_OR_NEWER
14 | $(DefineConstants);GODOT_3_0_0_OR_NEWER
15 | $(DefineConstants);GODOT_3_0_1_OR_NEWER
16 | $(DefineConstants);GODOT_3_0_2_OR_NEWER
17 | $(DefineConstants);GODOT_3_0_3_OR_NEWER
18 | $(DefineConstants);GODOT_3_0_4_OR_NEWER
19 | $(DefineConstants);GODOT_3_0_5_OR_NEWER
20 | $(DefineConstants);GODOT_3_0_6_OR_NEWER
21 | $(DefineConstants);GODOT_3_1_0_OR_NEWER
22 | $(DefineConstants);GODOT_3_1_1_OR_NEWER
23 | $(DefineConstants);GODOT_3_1_2_OR_NEWER
24 | $(DefineConstants);GODOT_3_2_0_OR_NEWER
25 | $(DefineConstants);GODOT_3_2_1_OR_NEWER
26 | $(DefineConstants);GODOT_3_2_2_OR_NEWER
27 | $(DefineConstants);GODOT_3_2_3_OR_NEWER
28 | $(DefineConstants);GODOT_3_3_0_OR_NEWER
29 | $(DefineConstants);GODOT_3_3_1_OR_NEWER
30 | $(DefineConstants);GODOT_3_3_2_OR_NEWER
31 | $(DefineConstants);GODOT_3_3_3_OR_NEWER
32 | $(DefineConstants);GODOT_3_5
33 | $(DefineConstants);GODOT_3
34 | $(DefineConstants);GODOT_3_5_0
35 |
36 |
--------------------------------------------------------------------------------
/GodotFixedVolatilePhysics.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.32630.194
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GodotFixedVolatilePhysics", "GodotFixedVolatilePhysics.csproj", "{0BB5CFC8-534D-4408-B29A-50C9FDEE65C1}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StubProject", "addons\GodotVisualStudioStub\StubProject.csproj", "{B83A5A30-7D9A-4BCC-BB56-2974A2AAE767}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | ExportDebug|Any CPU = ExportDebug|Any CPU
14 | ExportRelease|Any CPU = ExportRelease|Any CPU
15 | EndGlobalSection
16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
17 | {0BB5CFC8-534D-4408-B29A-50C9FDEE65C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
18 | {0BB5CFC8-534D-4408-B29A-50C9FDEE65C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
19 | {0BB5CFC8-534D-4408-B29A-50C9FDEE65C1}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU
20 | {0BB5CFC8-534D-4408-B29A-50C9FDEE65C1}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU
21 | {0BB5CFC8-534D-4408-B29A-50C9FDEE65C1}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU
22 | {0BB5CFC8-534D-4408-B29A-50C9FDEE65C1}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU
23 | {B83A5A30-7D9A-4BCC-BB56-2974A2AAE767}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {B83A5A30-7D9A-4BCC-BB56-2974A2AAE767}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {B83A5A30-7D9A-4BCC-BB56-2974A2AAE767}.ExportDebug|Any CPU.ActiveCfg = Debug|Any CPU
26 | {B83A5A30-7D9A-4BCC-BB56-2974A2AAE767}.ExportDebug|Any CPU.Build.0 = Debug|Any CPU
27 | {B83A5A30-7D9A-4BCC-BB56-2974A2AAE767}.ExportRelease|Any CPU.ActiveCfg = Debug|Any CPU
28 | {B83A5A30-7D9A-4BCC-BB56-2974A2AAE767}.ExportRelease|Any CPU.Build.0 = Debug|Any CPU
29 | EndGlobalSection
30 | GlobalSection(SolutionProperties) = preSolution
31 | HideSolutionNode = FALSE
32 | EndGlobalSection
33 | GlobalSection(ExtensibilityGlobals) = postSolution
34 | SolutionGuid = {EC9A5306-CD19-4736-B1F2-7CF06944D688}
35 | EndGlobalSection
36 | EndGlobal
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Fractural
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Godot Fixed Volatile Physics 💥
2 |
3 |  
4 |
5 | Fixed-point 2D physics in Godot C# using a modified version of [cathei's Fixed point fork of VolatilePhysics](https://github.com/cathei/VolatilePhysics-FixedMath).
6 |
7 | ## Features
8 | - Dynamic rigid bodies
9 | - Kinematic bodies
10 | - Static bodies
11 | - Area bodies
12 | - Shape editors
13 | - Debug drawing
14 | - Collision layers and masks
15 |
16 | ## Examples
17 |
18 | 
19 | 
20 | 
21 |
--------------------------------------------------------------------------------
/ReadmeAssets/FullPhysicsTest.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/ReadmeAssets/FullPhysicsTest.gif
--------------------------------------------------------------------------------
/ReadmeAssets/KinematicBody.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/ReadmeAssets/KinematicBody.gif
--------------------------------------------------------------------------------
/ReadmeAssets/PhysicsTest.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/ReadmeAssets/PhysicsTest.gif
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/SimpleForce.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/SimpleForce.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/SimpleForce.svg-ddab30616003e6d80a476d7ee8ad700e.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/GodotFixedVolatilePhysics/Assets/SimpleForce.svg"
13 | dest_files=[ "res://.import/SimpleForce.svg-ddab30616003e6d80a476d7ee8ad700e.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/VoltArea.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/VoltArea.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/VoltArea.svg-6f308530d7fb20a6323be50a206fbcef.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/GodotFixedVolatilePhysics/Assets/VoltArea.svg"
13 | dest_files=[ "res://.import/VoltArea.svg-6f308530d7fb20a6323be50a206fbcef.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/VoltKinematicBody.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/VoltKinematicBody.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/VoltKinematicBody.svg-876a52416679eaa23c269e98bd58a9d9.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/GodotFixedVolatilePhysics/Assets/VoltKinematicBody.svg"
13 | dest_files=[ "res://.import/VoltKinematicBody.svg-876a52416679eaa23c269e98bd58a9d9.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/VoltNode2D.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/VoltNode2D.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/VoltNode2D.svg-b53f68da92fe909dd218e942582e08b7.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/GodotFixedVolatilePhysics/Assets/VoltNode2D.svg"
13 | dest_files=[ "res://.import/VoltNode2D.svg-b53f68da92fe909dd218e942582e08b7.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/VoltPolygon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/VoltPolygon.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/VoltPolygon.svg-6e383c4108bed18e7d7bac33f302de9f.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/GodotFixedVolatilePhysics/Assets/VoltPolygon.svg"
13 | dest_files=[ "res://.import/VoltPolygon.svg-6e383c4108bed18e7d7bac33f302de9f.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/VoltRect.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/VoltRect.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/VoltRect.svg-cf93039269bef17d4e32c7ec486e9bd6.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/GodotFixedVolatilePhysics/Assets/VoltRect.svg"
13 | dest_files=[ "res://.import/VoltRect.svg-cf93039269bef17d4e32c7ec486e9bd6.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/VoltRigidBody.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/VoltRigidBody.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/VoltRigidBody.svg-9c53786d162056b3bd2a3f5caab2a5a6.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/GodotFixedVolatilePhysics/Assets/VoltRigidBody.svg"
13 | dest_files=[ "res://.import/VoltRigidBody.svg-9c53786d162056b3bd2a3f5caab2a5a6.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/VoltStaticBody.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/VoltStaticBody.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/VoltStaticBody.svg-dfc5982df2af1c208528a225925cc8e7.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/GodotFixedVolatilePhysics/Assets/VoltStaticBody.svg"
13 | dest_files=[ "res://.import/VoltStaticBody.svg-dfc5982df2af1c208528a225925cc8e7.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/VoltWorld.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Assets/VoltWorld.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/VoltWorld.svg-5b858ec866258a9839b45c7193974ce1.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/GodotFixedVolatilePhysics/Assets/VoltWorld.svg"
13 | dest_files=[ "res://.import/VoltWorld.svg-5b858ec866258a9839b45c7193974ce1.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Core/Palette.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace Volatile.GodotEngine
4 | {
5 | public static class Palette
6 | {
7 | public static readonly Color Main = new Color("c93294");
8 | public static readonly Color Accent = new Color("c91850");
9 | public static readonly Color Blank = Colors.White;
10 |
11 | public static readonly Color DynamicBody = new Color("c93294");
12 | public static readonly Color KinematicBody = new Color("eb3144");
13 | public static readonly Color StaticBody = new Color("b935de");
14 | public static readonly Color AreaBody = new Color("3299c9");
15 | }
16 | }
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Core/SimpleForce.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace Volatile.GodotEngine
4 | {
5 | [Tool]
6 | public class SimpleForce : VoltNode2D
7 | {
8 | #region Force
9 | private VoltVector2 force;
10 | public VoltVector2 Force
11 | {
12 | get
13 | {
14 | #if TOOLS
15 | if (Engine.EditorHint)
16 | return VoltType.DeserializeOrDefault(_force);
17 | else
18 | #endif
19 | return force;
20 | }
21 | set
22 | {
23 | #if TOOLS
24 | if (Engine.EditorHint)
25 | _force = VoltType.Serialize(value);
26 | else
27 | #endif
28 | force = value;
29 | }
30 | }
31 | [Export(hintString: VoltPropertyHint.VoltVector2)]
32 | private byte[] _force;
33 | #endregion
34 |
35 | private IVolatileRigidBody body;
36 |
37 | public override void _Ready()
38 | {
39 | base._Ready();
40 | Force = VoltType.DeserializeOrDefault(_force);
41 |
42 | if (Engine.EditorHint)
43 | {
44 | SetPhysicsProcess(false);
45 | return;
46 | }
47 | body = GetParent();
48 | }
49 |
50 | public override string _GetConfigurationWarning()
51 | {
52 | if (!(GetParent() is IVolatileRigidBody))
53 | return $"{nameof(SimpleForce)} must be a child of a {nameof(IVolatileRigidBody)}!";
54 | return "";
55 | }
56 |
57 | public override void _PhysicsProcess(float delta)
58 | {
59 | if (body != null) body.AddForce(Force);
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Core/Test.cs:
--------------------------------------------------------------------------------
1 | using FixMath.NET;
2 | using Godot;
3 |
4 | namespace Volatile.GodotEngine
5 | {
6 | public class Test : Node2D
7 | {
8 | [Export(hintString: VoltPropertyHint.Fix64)]
9 | public byte[] fix64Number = VoltType.Serialize(Fix64.From("3384.4390"));
10 | [Export(hintString: VoltPropertyHint.VoltVector2)]
11 | public byte[] fixedVector = VoltType.Serialize(VoltVector2.From("3.430", "-234.03999"));
12 | [Export(hintString: VoltPropertyHint.Array + "," + VoltPropertyHint.Fix64)]
13 | public byte[] fixed64Array = VoltType.Serialize(new[]
14 | {
15 | Fix64.From("303.43003"),
16 | Fix64.From("40.34939"),
17 | Fix64.From("9348.2340"),
18 | Fix64.From("23.34029"),
19 | });
20 | [Export(hintString: VoltPropertyHint.Array + "," + VoltPropertyHint.VoltVector2)]
21 | public byte[] fixedVectorArray = VoltType.Serialize(new[]
22 | {
23 | VoltVector2.From("303.43003", "230.3409"),
24 | VoltVector2.From("40.34939", "9348.2340"),
25 | VoltVector2.From("23.34029", "24.34038"),
26 | });
27 | [Export]
28 | public byte[] regularByteArray = new byte[0];
29 | [Export(hintString: VoltPropertyHint.Array + "," + VoltPropertyHint.VoltRect2)]
30 | public byte[] voltRectArray = VoltType.Serialize(new VoltRect2[] { });
31 | [Export(hintString: VoltPropertyHint.VoltRect2)]
32 | public byte[] voltRect = VoltType.Serialize(new VoltRect2());
33 | [Export]
34 | public string tests;
35 | [Export]
36 | public Rect2 rect;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Core/TypeSerializers/ArraySerializer.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 | using System;
3 |
4 | namespace Volatile.GodotEngine
5 | {
6 | public class ArraySerializer
7 | {
8 | public static readonly ArraySerializer Global = new ArraySerializer();
9 |
10 | public Array Deserialize(Type elementType, byte[] data)
11 | {
12 | var buffer = new StreamPeerBuffer();
13 | buffer.PutData(data);
14 | buffer.Seek(0);
15 | return Deserialize(elementType, buffer);
16 | }
17 |
18 | public byte[] Serialize(Type elementType, Array value)
19 | {
20 | var buffer = new StreamPeerBuffer();
21 | Serialize(elementType, buffer, value);
22 | return buffer.DataArray;
23 | }
24 |
25 | public Array Deserialize(Type elementType, StreamPeerBuffer buffer)
26 | {
27 | var length = buffer.GetU32();
28 | var array = Array.CreateInstance(elementType, length);
29 | for (int i = 0; i < length; i++)
30 | {
31 | // We don't to use the bytes for anything.
32 | // We can store at most 255 bytes per type.
33 | buffer.GetU8();
34 | array.SetValue(VoltType.Deserialize(elementType, buffer), i);
35 | }
36 | return array;
37 | }
38 |
39 | public Array Default(Type elementType) => Array.CreateInstance(elementType, 0);
40 | public byte[] DefaultAsBytes(Type elementType) => Serialize(elementType, Default(elementType));
41 |
42 | public void Serialize(Type elementType, StreamPeerBuffer buffer, Array array)
43 | {
44 | buffer.PutU32((uint)array.Length);
45 | for (int i = 0; i < array.Length; i++)
46 | {
47 | var byteArray = VoltType.Serialize(elementType, array.GetValue(i));
48 | // By storing the byte length per element, we can dynamically omit
49 | // unecessary data in each type serializer. But the caveat is that
50 | // every element will take up an extra byte.
51 | buffer.PutU8((byte)byteArray.Length);
52 | buffer.PutData(byteArray);
53 | }
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Core/TypeSerializers/TypeSerializers.cs:
--------------------------------------------------------------------------------
1 | using FixMath.NET;
2 | using Godot;
3 |
4 | namespace Volatile.GodotEngine
5 | {
6 | public class Fix64Serializer : TypeSerializer
7 | {
8 | public static readonly Fix64Serializer Global = new Fix64Serializer();
9 |
10 | public override void Serialize(StreamPeerBuffer buffer, Fix64 value) => buffer.PutFix64(value);
11 | public override Fix64 Deserialize(StreamPeerBuffer buffer) => buffer.GetFix64();
12 | public override Fix64 Default() => Fix64.Zero;
13 | }
14 |
15 | public class VoltVector2Serializer : TypeSerializer
16 | {
17 | public static readonly VoltVector2Serializer Global = new VoltVector2Serializer();
18 |
19 | public override void Serialize(StreamPeerBuffer buffer, VoltVector2 value) => buffer.PutVoltVector2(value);
20 | public override VoltVector2 Deserialize(StreamPeerBuffer buffer) => buffer.GetVoltVector2();
21 | public override VoltVector2 Default() => VoltVector2.Zero;
22 | }
23 |
24 | public class VoltTransform2DSerializer : TypeSerializer
25 | {
26 | public static readonly VoltTransform2DSerializer Global = new VoltTransform2DSerializer();
27 |
28 | public override void Serialize(StreamPeerBuffer buffer, VoltTransform2D value) => buffer.PutVoltTransform2D(value);
29 | public override VoltTransform2D Deserialize(StreamPeerBuffer buffer) => buffer.GetVoltTransform2D();
30 | public override VoltTransform2D Default() => VoltTransform2D.Default();
31 | }
32 |
33 | public class VoltRect2Serializer : TypeSerializer
34 | {
35 | public static readonly VoltRect2Serializer Global = new VoltRect2Serializer();
36 |
37 | public override void Serialize(StreamPeerBuffer buffer, VoltRect2 value) => buffer.PutVoltRect2(value);
38 | public override VoltRect2 Deserialize(StreamPeerBuffer buffer) => buffer.GetVoltRect2();
39 | public override VoltRect2 Default() => new VoltRect2();
40 | }
41 |
42 | public class VoltMatrixSerializer : TypeSerializer
43 | {
44 | public static readonly VoltMatrixSerializer Global = new VoltMatrixSerializer();
45 |
46 | public override void Serialize(StreamPeerBuffer buffer, VoltMatrix value) => buffer.PutVoltMatrix(value);
47 | public override VoltMatrix Deserialize(StreamPeerBuffer buffer) => buffer.GetVoltMatrix();
48 | public override VoltMatrix Default() => new VoltMatrix(1, 1);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Core/Types/VoltRect2.cs:
--------------------------------------------------------------------------------
1 | using FixMath.NET;
2 | using System.Text;
3 | using Volatile;
4 |
5 | namespace Volatile.GodotEngine
6 | {
7 | public struct VoltRect2
8 | {
9 | public VoltRect2(VoltVector2 position, VoltVector2 size)
10 | {
11 | Size = size;
12 | Position = position;
13 | }
14 |
15 | public VoltVector2 Size { get; set; }
16 | public VoltVector2 Position { get; set; }
17 |
18 | public VoltVector2 TopLeft => Position;
19 | public VoltVector2 TopRight => new VoltVector2(Position.x + Size.x, Position.y);
20 | public VoltVector2 BottomRight => new VoltVector2(Position.x + Size.x, Position.y + Size.y);
21 | public VoltVector2 BottomLeft => new VoltVector2(Position.x, Position.y + Size.y);
22 |
23 | public VoltVector2[] Points => new VoltVector2[]
24 | {
25 | TopLeft,
26 | TopRight,
27 | BottomRight,
28 | BottomLeft
29 | };
30 |
31 | private static readonly Fix64 FIX_2 = Fix64.From(2);
32 |
33 | public VoltVector2 GetCenter()
34 | {
35 | return Position + Size / FIX_2;
36 | }
37 |
38 | public override string ToString()
39 | {
40 | return $"[Position: {Position}, Size: {Size}]";
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Core/Utils.cs:
--------------------------------------------------------------------------------
1 | using FixMath.NET;
2 | using System.Linq;
3 |
4 | namespace Volatile.GodotEngine
5 | {
6 | public static class Utils
7 | {
8 | public static Fix64 SignedArea(this VoltVector2[] points)
9 | {
10 | Fix64 sum = Fix64.Zero;
11 |
12 | for (int i = 0; i < points.Length; i++)
13 | {
14 | VoltVector2 v = points[i];
15 | VoltVector2 u = points[(i + 1) % points.Length];
16 | VoltVector2 w = points[(i + 2) % points.Length];
17 |
18 | sum += u.x * (v.y - w.y);
19 | }
20 |
21 | return sum / (Fix64)2;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Core/VolatileBodies/VolatileKinematicBody.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace Volatile.GodotEngine
4 | {
5 | public interface IVolatileKinematicBody : IVolatileBody
6 | {
7 | VoltKinematicCollisionResult MoveAndCollide(VoltVector2 linearVelocity);
8 | VoltVector2 MoveAndSlide(VoltVector2 linearVelocity, int maxSlides = 4);
9 | }
10 |
11 | [Tool]
12 | public class VolatileKinematicBody : VolatileBody, IVolatileKinematicBody
13 | {
14 | protected override VoltBody CreateBody(VoltWorld world, VoltShape[] shapes)
15 | => world.CreateKinematicBody(GlobalFixedPosition, GlobalFixedRotation, shapes, Layer, Mask);
16 |
17 | public VoltKinematicCollisionResult MoveAndCollide(VoltVector2 linearVelocity)
18 | {
19 | return Body.MoveAndCollide(linearVelocity);
20 | }
21 |
22 | public VoltVector2 MoveAndSlide(VoltVector2 linearVelocity, int maxSlides = 4)
23 | {
24 | return Body.MoveAndSlide(linearVelocity, maxSlides);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Core/VolatileBodies/VolatileRigidBody.cs:
--------------------------------------------------------------------------------
1 | using FixMath.NET;
2 | using Godot;
3 |
4 | namespace Volatile.GodotEngine
5 | {
6 | public interface IVolatileRigidBody : IVolatileBody
7 | {
8 | void AddForce(VoltVector2 force);
9 | void AddTorque(Fix64 radians);
10 |
11 | void Set(VoltVector2 position, Fix64 radians);
12 |
13 | void SetVelocity(VoltVector2 linearVelocity, Fix64 angularVelocity);
14 |
15 | void SetForce(VoltVector2 force, Fix64 torque, VoltVector2 biasVelocity, Fix64 biasRotation);
16 | }
17 |
18 | [Tool]
19 | public class VolatileRigidBody : VolatileBody, IVolatileRigidBody
20 | {
21 | protected override VoltBody CreateBody(VoltWorld world, VoltShape[] shapes)
22 | => world.CreateDynamicBody(GlobalFixedPosition, GlobalFixedRotation, shapes, Layer, Mask);
23 |
24 | public void AddForce(VoltVector2 force)
25 | {
26 | Body.AddForce(force);
27 | }
28 |
29 | public void AddTorque(Fix64 radians)
30 | {
31 | Body.AddTorque(radians);
32 | }
33 |
34 | public void Set(VoltVector2 position, Fix64 radians)
35 | {
36 | Body.Set(position, radians);
37 | }
38 |
39 | public void SetVelocity(VoltVector2 linearVelocity, Fix64 angularVelocity)
40 | {
41 | Body.LinearVelocity = linearVelocity;
42 | Body.AngularVelocity = angularVelocity;
43 | }
44 |
45 | public void SetForce(VoltVector2 force, Fix64 torque, VoltVector2 biasVelocity, Fix64 biasRotation)
46 | {
47 | Body.SetForce(force, torque, biasVelocity, biasRotation);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Core/VolatileBodies/VolatileStaticBody.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace Volatile.GodotEngine
4 | {
5 | public interface IVolatileStaticBody : IVolatileBody { }
6 |
7 | [Tool]
8 | public class VolatileStaticBody : VolatileBody, IVolatileStaticBody
9 | {
10 | protected override VoltBody CreateBody(VoltWorld world, VoltShape[] shapes)
11 | => world.CreateStaticBody(GlobalFixedPosition, GlobalFixedRotation, shapes, Layer, Mask);
12 |
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Core/VolatileShapes/VolatileCircle.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 | using Godot.Collections;
3 | using Fractural;
4 | using FixMath.NET;
5 | #if TOOLS
6 | using Volatile.GodotEngine.Plugin;
7 | #endif
8 |
9 | namespace Volatile.GodotEngine
10 | {
11 | [Tool]
12 | public class VolatileCircle : VolatileShape
13 | {
14 | public override VoltShape PrepareShape(VoltWorld world)
15 | {
16 | return world.CreateCircleWorldSpace(GlobalFixedPosition, Radius);
17 | }
18 |
19 | public override Vector2 ComputeLocalCenterOfMass()
20 | {
21 | return Vector2.Zero;
22 | }
23 |
24 | public override void _Ready()
25 | {
26 | base._Ready();
27 | _OnRadiusSet = VoltType.DeserializeOrDefault(_radius);
28 | if (!Engine.EditorHint)
29 | Radius = VoltType.DeserializeOrDefault(_radius);
30 | }
31 |
32 | #region Radius
33 | protected Fix64 radius;
34 | public Fix64 Radius
35 | {
36 | get
37 | {
38 | #if TOOLS
39 | if (Engine.EditorHint)
40 | return VoltType.DeserializeOrDefault(_radius);
41 | else
42 | #endif
43 | return radius;
44 | }
45 | set
46 | {
47 | #if TOOLS
48 | if (Engine.EditorHint)
49 | _radius = VoltType.Serialize(value);
50 | else
51 | #endif
52 | radius = value;
53 | }
54 | }
55 | [Export(hintString: VoltPropertyHint.Fix64 + ",set:" + nameof(_OnRadiusSet))]
56 | public byte[] _radius = VoltType.Serialize(Fix64.From(1));
57 |
58 | public float EditorRadius { get; set; }
59 | private Fix64 _OnRadiusSet
60 | {
61 | set
62 | {
63 | EditorRadius = (float)value;
64 | Update();
65 | }
66 | }
67 | #endregion
68 |
69 | public override void _Draw()
70 | {
71 | base._Draw();
72 | if (!DebugDraw && (!Engine.EditorHint || EditorRadius == 0)) return;
73 | var radius = EditorRadius;
74 |
75 | var color = GetShapeDrawColor();
76 | var fill = color;
77 | fill.a = 0.075f;
78 |
79 | var circumference = 2 * Mathf.Pi * radius;
80 | var points = Mathf.Max((int)(circumference * 10), 10);
81 | DrawLine(Vector2.Zero, new Vector2(radius, 0), color);
82 | DrawArc(Vector2.Zero, radius, 0, 2 * Mathf.Pi, points, color);
83 | DrawCircle(Vector2.Zero, radius, fill);
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Core/VolatileWorld.cs:
--------------------------------------------------------------------------------
1 | using FixMath.NET;
2 | using Godot;
3 |
4 | namespace Volatile.GodotEngine
5 | {
6 | public interface IVolatileWorld
7 | {
8 | VoltWorld World { get; }
9 | }
10 |
11 | // Tool tag is required to make VolatileWorld discoverable in the editor by VolatileBody,
12 | // which checks if it's a child of a VolatileWorld when generating configuration warnings.
13 | [Tool]
14 | public class VolatileWorld : VoltNode2D, IVolatileWorld
15 | {
16 | [Export]
17 | public int HistoryLength = 0;
18 | [Export]
19 | public bool ProcessSelf { get; set; } = true;
20 | [Export]
21 | public bool DebugDraw { get; set; } = false;
22 | public VoltWorld World { get; private set; }
23 |
24 | public override void _EnterTree()
25 | {
26 | base._EnterTree();
27 |
28 | if (Engine.EditorHint)
29 | {
30 | SetPhysicsProcess(false);
31 | return;
32 | }
33 | World = new VoltWorld(HistoryLength);
34 | SetPhysicsProcess(ProcessSelf);
35 | World.DeltaTime = Fix64.One / (Fix64)Engine.IterationsPerSecond;
36 | }
37 |
38 | public override void _Ready()
39 | {
40 | base._Ready();
41 |
42 | if (Engine.EditorHint)
43 | {
44 | SetPhysicsProcess(false);
45 | return;
46 | }
47 | }
48 |
49 | public override void _PhysicsProcess(float delta)
50 | {
51 | World.Update();
52 | Update();
53 | }
54 |
55 | public override void _Draw()
56 | {
57 | base._Draw();
58 | if (Engine.EditorHint || !DebugDraw) return;
59 | var color = Palette.Accent;
60 | foreach (var body in World.Bodies)
61 | {
62 | DrawRect(new Rect2(body.AABB.BottomLeft.ToGDVector2(), body.AABB.Size.ToGDVector2()), color, false);
63 | for (int i = 0; i < body.shapeCount; i++)
64 | {
65 | var AABB = body.shapes[i].AABB;
66 | DrawRect(new Rect2(AABB.BottomLeft.ToGDVector2(), AABB.Size.ToGDVector2()), color, false);
67 | }
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Libraries/FixedMath.Net/README.txt:
--------------------------------------------------------------------------------
1 | This library implements "Fix64", a 64 bit fixed point 31.32 numeric type and transcendent operations on it (square root, trig, etc). It is well covered by unit tests. However, it is still missing some operations; in particular, Tangent is not well tested yet.
2 |
3 | In the unit tests you'll find implementations for Int32-based (Q15.16) and Byte-based (Q3.4) numeric types. These were used for exploration of boundary conditions etc., but I'm keeping the code there only for reference.
4 |
5 | This project started as a port of libfixmath (http://code.google.com/p/libfixmath/).
6 |
7 | Note that the type requires explicit casts to convert to floating point and this is intentional, the difference between fixed point and floating point math is as important as the one between floating point and integral math.
8 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Libraries/VolatilePhysics/Internals/Axis.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * VolatilePhysics - A 2D Physics Library for Networked Games
3 | * Copyright (c) 2015-2016 - Alexander Shoulson - http://ashoulson.com
4 | *
5 | * This software is provided 'as-is', without any express or implied
6 | * warranty. In no event will the authors be held liable for any damages
7 | * arising from the use of this software.
8 | * Permission is granted to anyone to use this software for any purpose,
9 | * including commercial applications, and to alter it and redistribute it
10 | * freely, subject to the following restrictions:
11 | *
12 | * 1. The origin of this software must not be misrepresented; you must not
13 | * claim that you wrote the original software. If you use this software
14 | * in a product, an acknowledgment in the product documentation would be
15 | * appreciated but is not required.
16 | * 2. Altered source versions must be plainly marked as such, and must not be
17 | * misrepresented as being the original software.
18 | * 3. This notice may not be removed or altered from any source distribution.
19 | */
20 |
21 | using FixMath.NET;
22 | using System;
23 | using System.Collections.Generic;
24 |
25 | #if UNITY
26 | using UnityEngine;
27 | #endif
28 |
29 | namespace Volatile
30 | {
31 | ///
32 | /// The Axis data structure represents a "slab" between the given edge and
33 | /// a parallel edge drawn at the origin. The "width" value gives the width
34 | /// of that axis slab, defined as follows: For an edge AB with normal N,
35 | /// this width w is given by Dot(A, N). If you take edge AB, and draw an
36 | /// edge CD parallel to AB that intersects the origin, the width w is equal
37 | /// to the minimum distance between edges AB and CD.
38 | ///
39 | /// |
40 | /// | C
41 | /// | /
42 | /// | / A
43 | /// | /ヽ /
44 | /// | / ヽ /
45 | /// |/ w ヽ /
46 | /// -----------+---------ヽ/----
47 | /// /| /
48 | /// D | /
49 | /// | /
50 | /// | B
51 | /// |
52 | ///
53 | ///
54 | internal struct Axis
55 | {
56 | internal VoltVector2 Normal { get { return this.normal; } }
57 | internal Fix64 Width { get { return this.width; } }
58 |
59 | private readonly VoltVector2 normal;
60 | private readonly Fix64 width;
61 |
62 | internal Axis(VoltVector2 normal, Fix64 width)
63 | {
64 | this.normal = normal;
65 | this.width = width;
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Libraries/VolatilePhysics/Internals/Broadphase/IBroadphase.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * VolatilePhysics - A 2D Physics Library for Networked Games
3 | * Copyright (c) 2015-2016 - Alexander Shoulson - http://ashoulson.com
4 | *
5 | * This software is provided 'as-is', without any express or implied
6 | * warranty. In no event will the authors be held liable for any damages
7 | * arising from the use of this software.
8 | * Permission is granted to anyone to use this software for any purpose,
9 | * including commercial applications, and to alter it and redistribute it
10 | * freely, subject to the following restrictions:
11 | *
12 | * 1. The origin of this software must not be misrepresented; you must not
13 | * claim that you wrote the original software. If you use this software
14 | * in a product, an acknowledgment in the product documentation would be
15 | * appreciated but is not required.
16 | * 2. Altered source versions must be plainly marked as such, and must not be
17 | * misrepresented as being the original software.
18 | * 3. This notice may not be removed or altered from any source distribution.
19 | */
20 |
21 | using FixMath.NET;
22 | using System;
23 | using System.Collections.Generic;
24 |
25 | #if UNITY
26 | using UnityEngine;
27 | #endif
28 |
29 | namespace Volatile
30 | {
31 | internal interface IBroadPhase
32 | {
33 | void AddBody(VoltBody body);
34 | void RemoveBody(VoltBody body);
35 | void UpdateBody(VoltBody body);
36 |
37 | // Note that these should return bodies that meet the criteria within the
38 | // spaces defined by the structure itself. These tests should not test the
39 | // actual body's bounding box, as that will happen in the beginning of the
40 | // narrowphase test.
41 | void QueryOverlap(VoltAABB aabb, VoltBuffer outBuffer);
42 | void QueryPoint(VoltVector2 point, VoltBuffer outBuffer);
43 | void QueryCircle(VoltVector2 point, Fix64 radius, VoltBuffer outBuffer);
44 | void RayCast(ref VoltRayCast ray, VoltBuffer outBuffer);
45 | void CircleCast(ref VoltRayCast ray, Fix64 radius, VoltBuffer outBuffer);
46 | }
47 | }
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Libraries/VolatilePhysics/Internals/IIndexedValue.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * VolatilePhysics - A 2D Physics Library for Networked Games
3 | * Copyright (c) 2015-2016 - Alexander Shoulson - http://ashoulson.com
4 | *
5 | * This software is provided 'as-is', without any express or implied
6 | * warranty. In no event will the authors be held liable for any damages
7 | * arising from the use of this software.
8 | * Permission is granted to anyone to use this software for any purpose,
9 | * including commercial applications, and to alter it and redistribute it
10 | * freely, subject to the following restrictions:
11 | *
12 | * 1. The origin of this software must not be misrepresented; you must not
13 | * claim that you wrote the original software. If you use this software
14 | * in a product, an acknowledgment in the product documentation would be
15 | * appreciated but is not required.
16 | * 2. Altered source versions must be plainly marked as such, and must not be
17 | * misrepresented as being the original software.
18 | * 3. This notice may not be removed or altered from any source distribution.
19 | */
20 |
21 | using System;
22 | using System.Collections.Generic;
23 |
24 | namespace Volatile
25 | {
26 | internal interface IIndexedValue
27 | {
28 | int Index { get; set; }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Libraries/VolatilePhysics/RayCast/VoltRayCast.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * VolatilePhysics - A 2D Physics Library for Networked Games
3 | * Copyright (c) 2015-2016 - Alexander Shoulson - http://ashoulson.com
4 | *
5 | * This software is provided 'as-is', without any express or implied
6 | * warranty. In no event will the authors be held liable for any damages
7 | * arising from the use of this software.
8 | * Permission is granted to anyone to use this software for any purpose,
9 | * including commercial applications, and to alter it and redistribute it
10 | * freely, subject to the following restrictions:
11 | *
12 | * 1. The origin of this software must not be misrepresented; you must not
13 | * claim that you wrote the original software. If you use this software
14 | * in a product, an acknowledgment in the product documentation would be
15 | * appreciated but is not required.
16 | * 2. Altered source versions must be plainly marked as such, and must not be
17 | * misrepresented as being the original software.
18 | * 3. This notice may not be removed or altered from any source distribution.
19 | */
20 |
21 | using FixMath.NET;
22 | using System;
23 | using System.Collections.Generic;
24 |
25 | #if UNITY
26 | using UnityEngine;
27 | #endif
28 |
29 | namespace Volatile
30 | {
31 | ///
32 | /// A semi-precomputed ray optimized for fast AABB tests.
33 | ///
34 | public struct VoltRayCast
35 | {
36 | internal readonly VoltVector2 origin;
37 | internal readonly VoltVector2 direction;
38 | internal readonly VoltVector2 invDirection;
39 | internal readonly Fix64 distance;
40 | internal readonly bool signX;
41 | internal readonly bool signY;
42 |
43 | public VoltRayCast(VoltVector2 origin, VoltVector2 destination)
44 | {
45 | VoltVector2 delta = destination - origin;
46 |
47 | this.origin = origin;
48 | this.direction = delta.Normalized;
49 | this.distance = delta.Magnitude;
50 | this.signX = direction.x < Fix64.Zero;
51 | this.signY = direction.y < Fix64.Zero;
52 | this.invDirection =
53 | new VoltVector2(Fix64.One / direction.x, Fix64.One / direction.y);
54 | }
55 |
56 | public VoltRayCast(VoltVector2 origin, VoltVector2 direction, Fix64 distance)
57 | {
58 | this.origin = origin;
59 | this.direction = direction;
60 | this.distance = distance;
61 | this.signX = direction.x < Fix64.Zero;
62 | this.signY = direction.y < Fix64.Zero;
63 | this.invDirection =
64 | new VoltVector2(Fix64.One / direction.x, Fix64.One / direction.y);
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Libraries/VolatilePhysics/Util/Pooling/IVoltPoolable.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * VolatilePhysics - A 2D Physics Library for Networked Games
3 | * Copyright (c) 2015-2016 - Alexander Shoulson - http://ashoulson.com
4 | *
5 | * This software is provided 'as-is', without any express or implied
6 | * warranty. In no event will the authors be held liable for any damages
7 | * arising from the use of this software.
8 | * Permission is granted to anyone to use this software for any purpose,
9 | * including commercial applications, and to alter it and redistribute it
10 | * freely, subject to the following restrictions:
11 | *
12 | * 1. The origin of this software must not be misrepresented; you must not
13 | * claim that you wrote the original software. If you use this software
14 | * in a product, an acknowledgment in the product documentation would be
15 | * appreciated but is not required.
16 | * 2. Altered source versions must be plainly marked as such, and must not be
17 | * misrepresented as being the original software.
18 | * 3. This notice may not be removed or altered from any source distribution.
19 | */
20 |
21 | namespace Volatile
22 | {
23 | public interface IVoltPoolable
24 | where T : IVoltPoolable
25 | {
26 | IVoltPool Pool { get; set; }
27 | void Reset();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Libraries/VolatilePhysics/Util/VoltUtil.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * VolatilePhysics - A 2D Physics Library for Networked Games
3 | * Copyright (c) 2015-2016 - Alexander Shoulson - http://ashoulson.com
4 | *
5 | * This software is provided 'as-is', without any express or implied
6 | * warranty. In no event will the authors be held liable for any damages
7 | * arising from the use of this software.
8 | * Permission is granted to anyone to use this software for any purpose,
9 | * including commercial applications, and to alter it and redistribute it
10 | * freely, subject to the following restrictions:
11 | *
12 | * 1. The origin of this software must not be misrepresented; you must not
13 | * claim that you wrote the original software. If you use this software
14 | * in a product, an acknowledgment in the product documentation would be
15 | * appreciated but is not required.
16 | * 2. Altered source versions must be plainly marked as such, and must not be
17 | * misrepresented as being the original software.
18 | * 3. This notice may not be removed or altered from any source distribution.
19 | */
20 |
21 | using System;
22 |
23 | namespace Volatile
24 | {
25 | public static class VoltUtil
26 | {
27 | public static void Swap(ref T a, ref T b)
28 | {
29 | T temp = b;
30 | b = a;
31 | a = temp;
32 | }
33 |
34 | public static int ExpandArray(ref T[] oldArray, int minSize = 1)
35 | {
36 | // TODO: Revisit this using next-largest primes like built-in lists do
37 | int newCapacity = Math.Max(oldArray.Length * 2, minSize);
38 | T[] newArray = new T[newCapacity];
39 | Array.Copy(oldArray, newArray, oldArray.Length);
40 | oldArray = newArray;
41 | return newCapacity;
42 | }
43 |
44 | public static bool Filter_StaticOnly(VoltBody body)
45 | {
46 | return body.IsStatic;
47 | }
48 |
49 | public static bool Filter_DynamicOnly(VoltBody body)
50 | {
51 | return (body.IsStatic == false);
52 | }
53 |
54 | public static bool Filter_All(VoltBody body)
55 | {
56 | return true;
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Libraries/VolatilePhysics/VoltBuffer.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * VolatilePhysics - A 2D Physics Library for Networked Games
3 | * Copyright (c) 2015-2016 - Alexander Shoulson - http://ashoulson.com
4 | *
5 | * This software is provided 'as-is', without any express or implied
6 | * warranty. In no event will the authors be held liable for any damages
7 | * arising from the use of this software.
8 | * Permission is granted to anyone to use this software for any purpose,
9 | * including commercial applications, and to alter it and redistribute it
10 | * freely, subject to the following restrictions:
11 | *
12 | * 1. The origin of this software must not be misrepresented; you must not
13 | * claim that you wrote the original software. If you use this software
14 | * in a product, an acknowledgment in the product documentation would be
15 | * appreciated but is not required.
16 | * 2. Altered source versions must be plainly marked as such, and must not be
17 | * misrepresented as being the original software.
18 | * 3. This notice may not be removed or altered from any source distribution.
19 | */
20 |
21 | using System;
22 | using System.Collections;
23 | using System.Collections.Generic;
24 |
25 | namespace Volatile
26 | {
27 | public class VoltBuffer : IEnumerable
28 | {
29 | public int Count { get { return this.count; } }
30 | public T this[int key] { get { return this.items[key]; } }
31 |
32 | private T[] items;
33 | private int count;
34 |
35 | public VoltBuffer(int capacity = 256)
36 | {
37 | this.items = new T[capacity];
38 | this.count = 0;
39 | }
40 |
41 | ///
42 | /// Adds a new element to the end of the list. Returns the index of the
43 | /// newly-indexed object.
44 | ///
45 | internal void Add(T body)
46 | {
47 | if (this.count >= this.items.Length)
48 | VoltUtil.ExpandArray(ref this.items);
49 |
50 | this.items[this.count] = body;
51 | this.count++;
52 | }
53 |
54 | internal void Add(T[] bodies, int count)
55 | {
56 | if ((this.count + count) >= this.items.Length)
57 | VoltUtil.ExpandArray(ref this.items, (this.count + count));
58 |
59 | Array.Copy(bodies, 0, this.items, this.count, count);
60 | this.count += count;
61 | }
62 |
63 | public void Clear()
64 | {
65 | this.count = 0;
66 | }
67 |
68 | public IEnumerator GetEnumerator()
69 | {
70 | for (int i = 0; i < this.count; i++)
71 | yield return this.items[i];
72 | }
73 |
74 | IEnumerator IEnumerable.GetEnumerator()
75 | {
76 | for (int i = 0; i < this.count; i++)
77 | yield return this.items[i];
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Libraries/VolatilePhysics/VoltConfig.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * VolatilePhysics - A 2D Physics Library for Networked Games
3 | * Copyright (c) 2015-2016 - Alexander Shoulson - http://ashoulson.com
4 | *
5 | * This software is provided 'as-is', without any express or implied
6 | * warranty. In no event will the authors be held liable for any damages
7 | * arising from the use of this software.
8 | * Permission is granted to anyone to use this software for any purpose,
9 | * including commercial applications, and to alter it and redistribute it
10 | * freely, subject to the following restrictions:
11 | *
12 | * 1. The origin of this software must not be misrepresented; you must not
13 | * claim that you wrote the original software. If you use this software
14 | * in a product, an acknowledgment in the product documentation would be
15 | * appreciated but is not required.
16 | * 2. Altered source versions must be plainly marked as such, and must not be
17 | * misrepresented as being the original software.
18 | * 3. This notice may not be removed or altered from any source distribution.
19 | */
20 |
21 | using FixMath.NET;
22 | using System;
23 | using System.Collections.Generic;
24 |
25 | #if UNITY
26 | using UnityEngine;
27 | #endif
28 |
29 | namespace Volatile
30 | {
31 | public static class VoltConfig
32 | {
33 | public static Fix64 ResolveSlop = (Fix64)0.01M;
34 | public static Fix64 ResolveRate = (Fix64)0.1M;
35 | public static Fix64 AreaMassRatio = (Fix64)0.01M;
36 |
37 | // Defaults
38 | public static readonly Fix64 DEFAULT_DENSITY = Fix64.One;
39 | public static readonly Fix64 DEFAULT_RESTITUTION = (Fix64)0.5M;
40 | public static readonly Fix64 DEFAULT_FRICTION = (Fix64)0.8M;
41 |
42 | internal static readonly Fix64 DEFAULT_DELTA_TIME = (Fix64)0.02M;
43 | internal static readonly Fix64 DEFAULT_DAMPING = (Fix64)0.999M;
44 | internal const int DEFAULT_ITERATION_COUNT = 20;
45 |
46 | // AABB extension for the dynamic tree
47 | internal static readonly Fix64 AABB_EXTENSION = (Fix64)0.2M;
48 |
49 | // Maximum contacts for collision resolution.
50 | internal const int MAX_CONTACTS = 3;
51 |
52 | // Used for initializing timesteps
53 | internal const int INVALID_TIME = -1;
54 |
55 | // The minimum mass a dynamic object can have before it is
56 | // converted to a static object
57 | internal static readonly Fix64 MINIMUM_DYNAMIC_MASS = (Fix64)0.00001M;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Plugin.cs:
--------------------------------------------------------------------------------
1 | using Fractural.Plugin;
2 | using Fractural.Plugin.AssetsRegistry;
3 | using Godot;
4 |
5 | #if TOOLS
6 | namespace Volatile.GodotEngine.Plugin
7 | {
8 | [Tool]
9 | public class Plugin : ExtendedPlugin
10 | {
11 | public override string PluginName => "Godot Fixed Volatile Physics";
12 |
13 | protected override void Load()
14 | {
15 | AssetsRegistry = new EditorAssetsRegistry(this);
16 | AddSubPlugin(new VolatilePolygonPlugin());
17 | AddSubPlugin(new VolatileRectPlugin());
18 | AddSubPlugin(new VolatileCirclePlugin());
19 | AddSubPlugin(new VoltTypesPlugin());
20 | AddSubPlugin(new VolatileNodesPlugin());
21 | }
22 |
23 | protected override void Unload()
24 | {
25 |
26 | }
27 | }
28 | }
29 | #endif
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Plugins/VolatileShapePlugins/VolatileShapeEditorPlugin.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | #if TOOLS
4 | namespace Volatile.GodotEngine.Plugin
5 | {
6 | [Tool]
7 | public abstract class VolatileShapeEditorPlugin : PointsEditorPlugin
8 | {
9 | public override void AddAndDrawAnchor(Anchor anchor)
10 | {
11 | if (EditedTarget is VolatileShape shape)
12 | AddAndDrawAnchor(anchor, CIRCLE_RADIUS, STROKE_RADIUS, FILL_COLOR, shape.GetShapeDrawColor());
13 | }
14 | }
15 | }
16 | #endif
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Plugins/VoltTypesPlugin/EditorProperties/CompoundSerializedEditorProperty.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | #if TOOLS
4 | namespace Volatile.GodotEngine.Plugin
5 | {
6 | [Tool]
7 | public abstract class CompoundSerializedEditorProperty : SerializedEditorProperty where TTypeSerializer : TypeSerializer, new()
8 | {
9 | public const int INDENTATION = 10;
10 |
11 | protected VBoxContainer propertiesVBox;
12 |
13 | public CompoundSerializedEditorProperty() { }
14 | public CompoundSerializedEditorProperty(float scale)
15 | {
16 | propertiesVBox = new VBoxContainer();
17 |
18 | var marginContainer = new MarginContainer();
19 | marginContainer.AddChild(propertiesVBox);
20 | marginContainer.AddConstantOverride("margin_left", (int)(INDENTATION * scale));
21 |
22 | InitSubProperties();
23 |
24 | AddChild(marginContainer);
25 | AddFocusable(marginContainer);
26 | SetBottomEditor(marginContainer);
27 | }
28 |
29 | protected abstract void InitSubProperties();
30 | protected void AddProperty(SerializedEditorProperty property, string label, string manualEditedProperty = "", bool supressFocusable = true, bool useManualValue = true) where LTTypeSerializer : TypeSerializer, new()
31 | {
32 | if (label != "" && manualEditedProperty == "")
33 | manualEditedProperty = label;
34 | property.SupressFocusable = true;
35 | property.UseManualValue = true;
36 | property.Label = label;
37 | property.ManualEditedProperty = manualEditedProperty;
38 | property.Connect("property_changed", this, nameof(OnPropertyChanged));
39 | propertiesVBox.AddChild(property);
40 | }
41 |
42 | private void OnPropertyChanged(string property, object value, string field, bool changing)
43 | {
44 | if (updating) return;
45 | OnSubPropertyChanged(property);
46 | SerializeWorkingValueToEditor();
47 | }
48 |
49 | protected abstract void OnSubPropertyChanged(string property);
50 | }
51 | }
52 | #endif
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Plugins/VoltTypesPlugin/EditorProperties/EditorPropertyExtens.cs:
--------------------------------------------------------------------------------
1 | #if TOOLS
2 | namespace Volatile.GodotEngine.Plugin
3 | {
4 | public static class EditorPropertyExtens
5 | {
6 | ///
7 | /// Configures the to override regular editor functionality. This is used for embedding this editor property inside of another editor proeprty.
8 | ///
9 | ///
10 | ///
11 | ///
12 | ///
13 | public static void ConfigureOverrides(this IExtendedEditorProperty property, string manualEditedProperty = "", Godot.Object manualEditedObject = null, bool suppressFocusable = false, string label = "")
14 | {
15 | property.ManualEditedProperty = manualEditedProperty;
16 | property.ManualEditedObject = manualEditedObject;
17 | property.SupressFocusable = suppressFocusable;
18 | property.Label = label;
19 | }
20 |
21 | ///
22 | /// Configures the to override regular editor functionality. This is used for embedding this editor property inside of another editor proeprty.
23 | ///
24 | ///
25 | ///
26 | ///
27 | ///
28 | ///
29 | public static void ConfigureOverrides(this ISerializedEditorProperty property, string manualEditedProperty = "", Godot.Object manualEditedObject = null, bool suppressFocusable = false, string label = "", bool useManualValue = false)
30 | {
31 | ((IExtendedEditorProperty)property).ConfigureOverrides(manualEditedProperty, manualEditedObject, suppressFocusable, label);
32 | property.UseManualValue = useManualValue;
33 | }
34 | }
35 | }
36 | #endif
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Plugins/VoltTypesPlugin/EditorProperties/ExtendedEditorProperty.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 | using GDC = Godot.Collections;
3 |
4 | #if TOOLS
5 | namespace Volatile.GodotEngine.Plugin
6 | {
7 | public interface IEditorProperty
8 | {
9 | string GetEditedProperty();
10 | Godot.Object GetEditedObject();
11 | void AddFocusable(Control control);
12 | void UpdateProperty();
13 | string Label { get; set; }
14 | Error Connect(string signal, Godot.Object target, string method, GDC.Array binds = null, uint flags = 0);
15 | }
16 |
17 | public interface IExtendedEditorProperty : IEditorProperty
18 | {
19 | bool SupressFocusable { get; set; }
20 | string ManualEditedProperty { get; set; }
21 | Godot.Object ManualEditedObject { get; set; }
22 | }
23 |
24 | [Tool]
25 | public abstract class ExtendedEditorProperty : EditorProperty, IExtendedEditorProperty
26 | {
27 | public bool SupressFocusable { get; set; } = false;
28 | public string ManualEditedProperty { get; set; } = "";
29 | public Godot.Object ManualEditedObject { get; set; }
30 | public new string GetEditedProperty()
31 | {
32 | if (ManualEditedProperty != "")
33 | return ManualEditedProperty;
34 | return base.GetEditedProperty();
35 | }
36 |
37 | public new Godot.Object GetEditedObject()
38 | {
39 | if (ManualEditedObject != null)
40 | return ManualEditedObject;
41 | return base.GetEditedObject();
42 | }
43 |
44 | public new void AddFocusable(Control control)
45 | {
46 | // We don't want to add focus if we're
47 | // not using this as an editor property
48 | // inside the inspector. (ie. being
49 | // using inside of an array editor
50 | // property)
51 | if (SupressFocusable)
52 | base.AddFocusable(control);
53 | }
54 |
55 | protected bool updating;
56 |
57 | public override void UpdateProperty()
58 | {
59 | updating = true;
60 | InternalUpdateProperty();
61 | updating = false;
62 | }
63 |
64 | protected abstract void InternalUpdateProperty();
65 |
66 | public void ConfigureOverrides(string manualEditedProperty = "", Object manualEditedObject = null, bool supressFocusable = false)
67 | {
68 | ManualEditedProperty = manualEditedProperty;
69 | ManualEditedObject = manualEditedObject;
70 | SupressFocusable = supressFocusable;
71 | }
72 | }
73 | }
74 | #endif
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Plugins/VoltTypesPlugin/EditorProperties/ExtendedEditorPropertyParser.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | #if TOOLS
4 | namespace Volatile.GodotEngine.Plugin
5 | {
6 | ///
7 | /// Parser for . It can return the default object for a type, and can also parse properties for the type.
8 | ///
9 | [Tool]
10 | public abstract class ExtendedEditorPropertyParser : Godot.Reference
11 | {
12 | public virtual ExtendedEditorProperty ParseProperty(Godot.Object @object, int type, string path, int hint, string hintText, int usage, string[] args)
13 | {
14 | var property = ParseProperty(args);
15 | if (property != null)
16 | return property;
17 | return null;
18 | }
19 | public abstract ExtendedEditorProperty ParseProperty(string[] args);
20 |
21 | public abstract object GetDefaultObject(string[] args);
22 | }
23 | }
24 | #endif
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Plugins/VoltTypesPlugin/EditorProperties/VoltRect2EditorProperty.cs:
--------------------------------------------------------------------------------
1 | using Fractural.Utils;
2 | using Godot;
3 |
4 | #if TOOLS
5 | namespace Volatile.GodotEngine.Plugin
6 | {
7 | [Tool]
8 | public class VoltRect2EditorProperty : CompoundSerializedEditorProperty
9 | {
10 | private VoltVector2EditorProperty positionProperty;
11 | private VoltVector2EditorProperty sizeProperty;
12 |
13 | public VoltRect2EditorProperty() { }
14 | public VoltRect2EditorProperty(float scale) : base(scale) { }
15 |
16 | protected override void InitSubProperties()
17 | {
18 | positionProperty = new VoltVector2EditorProperty();
19 | AddProperty(positionProperty, "Position");
20 |
21 | sizeProperty = new VoltVector2EditorProperty();
22 | AddProperty(sizeProperty, "Size");
23 | }
24 |
25 | protected override void InternalUpdateProperty()
26 | {
27 | positionProperty.UpdateProperty(workingValue.Position);
28 | sizeProperty.UpdateProperty(workingValue.Size);
29 | }
30 |
31 | protected override void OnSubPropertyChanged(string property)
32 | {
33 | switch (property)
34 | {
35 | case "Position":
36 | workingValue.Position = positionProperty.Value;
37 | break;
38 | case "Size":
39 | workingValue.Size = sizeProperty.Value;
40 | break;
41 | }
42 | }
43 | }
44 |
45 | [Tool]
46 | public class VoltRect2EditorPropertyParser : SerializedEditorPropertyParser
47 | {
48 | private float scale;
49 |
50 | public VoltRect2EditorPropertyParser() { }
51 | public VoltRect2EditorPropertyParser(float scale)
52 | {
53 | this.scale = scale;
54 | }
55 |
56 | public override ISerializedEditorProperty ParseSerializedProperty(string[] args)
57 | {
58 | if (args.TryGet(0) == VoltPropertyHint.VoltRect2)
59 | return new VoltRect2EditorProperty(scale);
60 | return null;
61 | }
62 |
63 | public override object GetDefaultObject(string[] args)
64 | {
65 | if (args.TryGet(0) == VoltPropertyHint.VoltRect2)
66 | return VoltRect2Serializer.Global.Default();
67 | return null;
68 | }
69 | }
70 | }
71 | #endif
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Plugins/VoltTypesPlugin/VoltPropertyHint.cs:
--------------------------------------------------------------------------------
1 | using FixMath.NET;
2 | using System;
3 | using System.Collections.Generic;
4 |
5 | namespace Volatile.GodotEngine
6 | {
7 | public static class VoltPropertyHint
8 | {
9 | static VoltPropertyHint()
10 | {
11 | HintToType = new Dictionary();
12 | HintToType.Add(Fix64, typeof(Fix64));
13 | HintToType.Add(VoltVector2, typeof(VoltVector2));
14 | HintToType.Add(VoltTransform2D, typeof(VoltTransform2D));
15 | HintToType.Add(VoltRect2, typeof(VoltRect2));
16 | }
17 |
18 | public static readonly Dictionary HintToType;
19 |
20 | public const string Array = nameof(Array);
21 | public const string Fix64 = nameof(Fix64);
22 | public const string VoltVector2 = nameof(VoltVector2);
23 | public const string VoltTransform2D = nameof(VoltTransform2D);
24 | public const string VoltRect2 = nameof(VoltRect2);
25 |
26 | public static readonly string[] Values =
27 | {
28 | Array,
29 | Fix64,
30 | VoltVector2,
31 | VoltTransform2D,
32 | VoltRect2
33 | };
34 | }
35 | }
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/Plugins/VoltTypesPlugin/VoltTypesPlugin.cs:
--------------------------------------------------------------------------------
1 | using FixMath.NET;
2 | using Fractural.Plugin;
3 | using Godot;
4 |
5 | #if TOOLS
6 | namespace Volatile.GodotEngine.Plugin
7 | {
8 | [Tool]
9 | public class VoltTypesPlugin : SubPlugin
10 | {
11 | public override string PluginName => nameof(VoltTypesPlugin);
12 |
13 | public override void Load()
14 | {
15 | Plugin.AddManagedInspectorPlugin(new VoltTypesInspectorPlugin(Plugin));
16 | }
17 | }
18 | }
19 | #endif
--------------------------------------------------------------------------------
/addons/GodotFixedVolatilePhysics/plugin.cfg:
--------------------------------------------------------------------------------
1 | [plugin]
2 |
3 | name="GodotFixedVoltailePhysics"
4 | description="Deterministic 2D physics"
5 | author="github/Fractural"
6 | version="1"
7 | script="Plugin.cs"
8 |
--------------------------------------------------------------------------------
/addons/VirtualJoystick/VirtualJoystick.cs:
--------------------------------------------------------------------------------
1 | using Fractural;
2 | using Godot;
3 | using System;
4 |
5 | namespace VirtualJoystickAddon
6 | {
7 | public class VirtualJoystick : GDScriptWrapper
8 | {
9 | public Vector2 Output => (Vector2)Source.Call("get_output");
10 |
11 | public VirtualJoystick() { }
12 | public VirtualJoystick(Godot.Object source) : base(source) { }
13 | }
14 | }
--------------------------------------------------------------------------------
/addons/VirtualJoystick/textures/joystick_base_outline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/addons/VirtualJoystick/textures/joystick_base_outline.png
--------------------------------------------------------------------------------
/addons/VirtualJoystick/textures/joystick_base_outline.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/joystick_base_outline.png-8bce810e25ebae6c114da91476c57ba4.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/VirtualJoystick/textures/joystick_base_outline.png"
13 | dest_files=[ "res://.import/joystick_base_outline.png-8bce810e25ebae6c114da91476c57ba4.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/VirtualJoystick/textures/joystick_tip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/addons/VirtualJoystick/textures/joystick_tip.png
--------------------------------------------------------------------------------
/addons/VirtualJoystick/textures/joystick_tip.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/joystick_tip.png-ac60c6cfef593f7dae0e1ae25a43d07c.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/VirtualJoystick/textures/joystick_tip.png"
13 | dest_files=[ "res://.import/joystick_tip.png-ac60c6cfef593f7dae0e1ae25a43d07c.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/VirtualJoystick/textures/joystick_tip_arrows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/addons/VirtualJoystick/textures/joystick_tip_arrows.png
--------------------------------------------------------------------------------
/addons/VirtualJoystick/textures/joystick_tip_arrows.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/joystick_tip_arrows.png-6c3dca4e1ae282e1a063fa009c1ecb1c.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/VirtualJoystick/textures/joystick_tip_arrows.png"
13 | dest_files=[ "res://.import/joystick_tip_arrows.png-6c3dca4e1ae282e1a063fa009c1ecb1c.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/VirtualJoystick/virtual_joystick.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=2]
2 |
3 | [ext_resource path="res://addons/VirtualJoystick/textures/joystick_base_outline.png" type="Texture" id=1]
4 | [ext_resource path="res://addons/VirtualJoystick/textures/joystick_tip_arrows.png" type="Texture" id=2]
5 | [ext_resource path="res://addons/VirtualJoystick/virtual_joystick.gd" type="Script" id=3]
6 |
7 | [node name="Virtual joystick" type="Control"]
8 | modulate = Color( 1, 1, 1, 0.509804 )
9 | anchor_top = 1.0
10 | anchor_bottom = 1.0
11 | margin_left = 50.0
12 | margin_top = -250.0
13 | margin_right = 250.0
14 | margin_bottom = -50.0
15 | script = ExtResource( 3 )
16 |
17 | [node name="Base" type="TextureRect" parent="."]
18 | anchor_left = 0.5
19 | anchor_top = 0.5
20 | anchor_right = 0.5
21 | anchor_bottom = 0.5
22 | margin_left = -100.0
23 | margin_top = -100.0
24 | margin_right = 100.0
25 | margin_bottom = 100.0
26 | grow_horizontal = 2
27 | grow_vertical = 2
28 | rect_pivot_offset = Vector2( 100, 100 )
29 | size_flags_horizontal = 4
30 | size_flags_vertical = 4
31 | texture = ExtResource( 1 )
32 | stretch_mode = 6
33 | __meta__ = {
34 | "_edit_use_anchors_": false
35 | }
36 |
37 | [node name="Tip" type="TextureRect" parent="Base"]
38 | anchor_left = 0.5
39 | anchor_top = 0.5
40 | anchor_right = 0.5
41 | anchor_bottom = 0.5
42 | margin_left = -50.0
43 | margin_top = -50.0
44 | margin_right = 50.0
45 | margin_bottom = 50.0
46 | grow_horizontal = 2
47 | grow_vertical = 2
48 | rect_pivot_offset = Vector2( 50, 50 )
49 | size_flags_horizontal = 4
50 | size_flags_vertical = 4
51 | texture = ExtResource( 2 )
52 | stretch_mode = 6
53 | __meta__ = {
54 | "_edit_use_anchors_": false
55 | }
56 |
--------------------------------------------------------------------------------
/addons/WAT/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 CodeDarigan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/.idea/.idea.assertions.dir/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/.idea/.idea.assertions.dir/.idea/indexLayout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/.idea/.idea.assertions.dir/.idea/projectSettingsUpdater.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/.idea/.idea.assertions.dir/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/.idea/.idea.assertions.dir/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | 1614470179608
34 |
35 |
36 | 1614470179608
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/assertion.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | var success: bool
4 | var expected: String = "NULL"
5 | var result: String
6 | var notes: String = "No Notes"
7 | var context
8 |
9 | static func _result(success: bool, expected: String, actual: String, context: String, notes: String = "No Notes"):
10 | return {
11 | "success": success,
12 | "expected": expected,
13 | "actual": actual,
14 | "context": context
15 | }
16 |
17 | static func type2str(property) -> String:
18 | match typeof(property):
19 | TYPE_NIL:
20 | return "null"
21 | TYPE_BOOL:
22 | return "bool"
23 | TYPE_INT:
24 | return "int"
25 | TYPE_REAL:
26 | return "float"
27 | TYPE_STRING:
28 | return "String"
29 | TYPE_VECTOR2:
30 | return "Vector2"
31 | TYPE_RECT2:
32 | return "Rect2"
33 | TYPE_VECTOR3:
34 | return "Vector3"
35 | TYPE_TRANSFORM2D:
36 | return "Transform2D"
37 | TYPE_PLANE:
38 | return "Plane"
39 | TYPE_QUAT:
40 | return "Quat"
41 | TYPE_AABB:
42 | return "AABB"
43 | TYPE_BASIS:
44 | return "Basis"
45 | TYPE_TRANSFORM:
46 | return "Transform"
47 | TYPE_COLOR:
48 | return "Color"
49 | TYPE_NODE_PATH:
50 | return "NodePath"
51 | TYPE_RID:
52 | return "RID"
53 | TYPE_OBJECT:
54 | return "Object"
55 | TYPE_DICTIONARY:
56 | return "Dictionary"
57 | TYPE_ARRAY:
58 | return "Array"
59 | TYPE_RAW_ARRAY:
60 | return "PoolByteArray"
61 | TYPE_INT_ARRAY:
62 | return "PoolIntArray"
63 | TYPE_REAL_ARRAY:
64 | return "PoolRealArray"
65 | TYPE_STRING_ARRAY:
66 | return "PoolStringArray"
67 | TYPE_VECTOR2_ARRAY:
68 | return "PoolVector2Array"
69 | TYPE_VECTOR3_ARRAY:
70 | return "PoolVector3Array"
71 | TYPE_COLOR_ARRAY:
72 | return "PoolColorArray"
73 | return "OutOfBounds"
74 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/boolean.gd:
--------------------------------------------------------------------------------
1 | extends "assertion.gd"
2 |
3 | static func is_true(value, context: String) -> Dictionary:
4 | var type = type2str(value)
5 | var passed: String = "|%s| %s == true" % [type, value]
6 | var failed: String = "|%s| %s != true" % [type, value]
7 | var success: bool = (value == true)
8 | var result = passed if success else failed
9 | return _result(success, passed, result, context)
10 |
11 | static func is_false(value, context: String) -> Dictionary:
12 | var type = type2str(value)
13 | var passed: String = "|%s| %s == false" % [type, value]
14 | var failed: String = "|%s| %s != false" % [type, value]
15 | var success = (value == false)
16 | var expected = passed
17 | var result = passed if success else failed
18 | return _result(success, expected, result, context)
19 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/collections.gd:
--------------------------------------------------------------------------------
1 | extends "assertion.gd"
2 |
3 | static func is_empty(value, context: String) -> Dictionary:
4 | var passed: String = "Array is empty"
5 | var failed: String = "Collection is not empty (%s)" % str(value)
6 | var success = value.empty()
7 | var expected = passed
8 | var result = passed if success else failed
9 | return _result(success, expected, result, context)
10 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/double.gd:
--------------------------------------------------------------------------------
1 | extends "assertion.gd"
2 |
3 | static func called_with_arguments(double, method: String, args: Array, context: String) -> Dictionary:
4 | var passed: String = "method: %s was called with arguments: %s" % [method, args]
5 | var failed: String = "method: %s was not called with arguments: %s" % [method, args]
6 | var alt_failed: String = "method: %s was not called at all" % method
7 | var expected = passed
8 |
9 | var success: bool
10 | var result: String
11 | if double.call_count(method) == 0:
12 | success = false
13 | result = alt_failed
14 | elif double.found_matching_call(method, args):
15 | success = true
16 | result = passed
17 | else:
18 | success = false
19 | result = failed
20 | return _result(success, expected, result, context)
21 |
22 | static func was_called(double, method: String, context: String) -> Dictionary:
23 | var passed: String = "%s was called" % method
24 | var failed: String = "%s was not called" % method
25 | var success = double.call_count(method) > 0
26 | var expected = passed
27 | var result = passed if success else failed
28 | return _result(success, expected, result, context)
29 |
30 | static func was_not_called(double, method: String, context: String) -> Dictionary:
31 | var passed: String = "%s was not called" % method
32 | var failed: String = "%s was called" % method
33 | var success = double.call_count(method) <= 0
34 | var expected = passed
35 | var result = passed if success else failed
36 | return _result(success, expected, result, context)
37 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/file.gd:
--------------------------------------------------------------------------------
1 | extends "assertion.gd"
2 |
3 | static func exists(path: String, context: String) -> Dictionary:
4 | var passed: String = "%s exists" % path
5 | var failed: String = "%s does not exist" % path
6 | var success = File.new().file_exists(path)
7 | var expected = "%s exists" % path
8 | var result = passed if success else failed
9 | return _result(success, expected, result, context)
10 |
11 | static func does_not_exist(path: String, context: String) -> Dictionary:
12 | var passed: String = "%s does not exist" % path
13 | var failed: String = "%s exists" % path
14 | var success = not File.new().file_exists(path)
15 | var expected = "%s does not exist" % path
16 | var result = passed if success else failed
17 | return _result(success, expected, result, context)
18 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/folder.gd:
--------------------------------------------------------------------------------
1 | extends "assertion.gd"
2 |
3 | static func exists(path: String, context: String) -> Dictionary:
4 | var passed: String = "%s exists" % path
5 | var failed: String = "%s does not exist" % path
6 | var success = not path.empty() and Directory.new().dir_exists(path)
7 | var expected = "%s exists" % path
8 | var result = passed if success else failed
9 | return _result(success, expected, result, context)
10 |
11 | static func does_not_exist(path: String, context: String) -> Dictionary:
12 | var passed: String = "%s does not exist" % path
13 | var failed: String = "%s exists" % path
14 | var success = path.empty() or not Directory.new().dir_exists(path)
15 | var expected = "%s does not exist" % path
16 | var result = passed if success else failed
17 | return _result(success, expected, result, context)
18 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/null.gd:
--------------------------------------------------------------------------------
1 | extends "assertion.gd"
2 |
3 |
4 | static func is_null(value, context: String) -> Dictionary:
5 | var type = type2str(value)
6 | var passed: String = "|%s| %s == null" % [type, value]
7 | var failed: String = "|%s| %s != null" % [type, value]
8 | var success = (value == null)
9 | var expected = passed
10 | var result = passed if success else failed
11 | return _result(success, expected, result, context)
12 |
13 | static func is_not_null(value, context: String) -> Dictionary:
14 | var type = type2str(value)
15 | var passed: String = "|%s| %s != null" % [type, value]
16 | var failed: String = "|%s| %s == null" % [type, value]
17 | var success = (value != null)
18 | var expected = passed
19 | var result = passed if success else failed
20 | return _result(success, expected, result, context)
21 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/property.gd:
--------------------------------------------------------------------------------
1 | extends "assertion.gd"
2 |
3 | # ONLY FOR CONTAINER CLASSES. NOT FOR OBJECTS
4 | static func has(value, container, context: String) -> Dictionary:
5 | var passed: String = "%s has %s" % [container, value]
6 | var failed: String = "%s has %s" % [container, value]
7 | var success = container.has(value)
8 | var expected = "%s has %s" % [container, value]
9 | var result = passed if success else failed
10 | return _result(success, expected, result, context)
11 |
12 | static func does_not_have(value, container, context: String) -> Dictionary:
13 | var passed: String = "%s does not have %s" % [container, value]
14 | var failed: String = "%s has %s" % [container, value]
15 | var success = not container.has(value)
16 | var expected = "%s does not have %s" % [container, value]
17 | var result = passed if success else failed
18 | return _result(success, expected, result, context)
19 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/range.gd:
--------------------------------------------------------------------------------
1 | extends "assertion.gd"
2 |
3 | static func is_in_range(value, low, high, context: String) -> Dictionary:
4 | var passed: String = "%s is in range(%s, %s)" % [value, low, high]
5 | var failed: String = "%s is not in range(%s, %s)" % [value, low, high]
6 | var success = low <= value and value < high
7 | var expected = passed
8 | var result = passed if success else failed
9 | return _result(success, expected, result, context)
10 |
11 | static func is_not_in_range(value, low, high, context: String) -> Dictionary:
12 | var passed: String = "%s is not in range(%s, %s)" % [value, low, high]
13 | var failed: String = "%s is in range(%s, %s)" % [value, low, high]
14 | var success = low > value or value >= high
15 | var expected = passed
16 | var result = passed if success else failed
17 | return _result(success, expected, result, context)
18 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/signal.gd:
--------------------------------------------------------------------------------
1 | extends "assertion.gd"
2 |
3 | static func was_emitted(emitter, event: String, context: String) -> Dictionary:
4 | var passed: String = "signal: %s was emitted from %s" % [event, emitter]
5 | var failed: String = "signal: %s was not emitted from %s" % [event, emitter]
6 | var success = emitter.get_meta("watcher").watching[event].emit_count > 0
7 | var expected = passed
8 | var result = passed if success else failed
9 | return _result(success, expected, result, context)
10 |
11 | static func was_not_emitted(emitter, _signal: String, context: String) -> Dictionary:
12 | var success = emitter.get_meta("watcher").watching[_signal].emit_count <= 0
13 | var passed = "Signal: %s was not emitted from %s" % [_signal, emitter]
14 | var failed = "Signal: %s was emitted from %s" % [_signal, emitter]
15 | var expected = passed
16 | var result = passed if success else failed
17 | return _result(success, expected, result, context)
18 |
19 | static func was_emitted_x_times(emitter, event: String, times: int, context: String) -> Dictionary:
20 | var passed: String = "signal: %s was emitted from %s %s" % [event, emitter, times as String]
21 | var failed: String = "signal: %s was not emitted from %s %s" % [event, emitter, times as String]
22 | var success = emitter.get_meta("watcher").watching[event].emit_count == times
23 | var expected = passed
24 | var result = passed if success else failed
25 | return _result(success, expected, result, context)
26 |
27 | static func was_emitted_with_args(emitter: Object, event: String, arguments: Array, context: String) -> Dictionary:
28 | var passed: String = "Signal: %s was emitted from %s with arguments: %s" % [event, emitter, arguments]
29 | var failed: String = "Signal: %s was not emitted from %s with arguments: %s" % [event, emitter, arguments]
30 | var alt_failure: String = "Signal: %s was not emitted from %s" % [event, emitter]
31 | var expected = passed
32 |
33 | var success: bool
34 | var result: String
35 | var data = emitter.get_meta("watcher").watching[event]
36 | if data.emit_count <= 0:
37 | success = false
38 | result = alt_failure
39 |
40 | elif _found_matching_call(arguments, data.calls):
41 | success = true
42 | result = passed
43 |
44 | else:
45 | success = false
46 | result = failed
47 |
48 | return _result(success, expected, result, context)
49 |
50 | static func _found_matching_call(args, calls) -> bool:
51 | for call in calls:
52 | if _match(args, call.args):
53 | return true
54 | return false
55 |
56 | static func _match(args, call_args) -> bool:
57 | for i in args.size():
58 | if args[i] != call_args[i]:
59 | return false
60 | return true
61 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/string.gd:
--------------------------------------------------------------------------------
1 | extends "assertion.gd"
2 |
3 | static func begins_with(value: String, string: String, context: String) -> Dictionary:
4 | var passed: String = "%s begins with %s" % [string, value]
5 | var failed: String = "%s does not begins with %s" % [string, value]
6 | var success = string.begins_with(value)
7 | var expected = passed
8 | var result = passed if success else failed
9 | return _result(success, expected, result, context)
10 |
11 | static func contains(value: String, string: String, context: String) -> Dictionary:
12 | var passed: String = "%s contains %s" % [string, value]
13 | var failed: String = "%s does not contain %s" % [string, value]
14 | var success = value in string
15 | var expected = passed
16 | var result = passed if success else failed
17 | return _result(success, expected, result, context)
18 |
19 | static func does_not_begin_with(value: String, string: String, context: String) -> Dictionary:
20 | var passed: String = "%s does not begin with %s" % [string, value]
21 | var failed: String = "%s begins with %s" % [string, value]
22 | var success = not string.begins_with(value)
23 | var expected = passed
24 | var result = passed if success else failed
25 | return _result(success, expected, result, context)
26 |
27 | static func does_not_contain(value: String, string: String, context: String) -> Dictionary:
28 | var passed: String = "%s does not contain %s" % [string, value]
29 | var failed: String = "%s contains %s" % [string, value]
30 | var success = not value in string
31 | var expected = passed
32 | var result = passed if success else failed
33 | return _result(success, expected, result, context)
34 |
35 | static func does_not_end_with(value: String, string: String, context: String) -> Dictionary:
36 | var passed: String = "%s does not end with %s" % [string, value]
37 | var failed: String = "%s ends with %s" % [string, value]
38 | var success = not string.ends_with(value)
39 | var expected = passed
40 | var result = passed if success else failed
41 | return _result(success, expected, result, context)
42 |
43 | static func ends_with(value: String, string: String, context: String) -> Dictionary:
44 | var passed: String = "%s ends with %s" % [string, value]
45 | var failed: String = "%s does not end with %s" % [string, value]
46 | var success = string.ends_with(value)
47 | var expected = passed
48 | var result = passed if success else failed
49 | return _result(success, expected, result, context)
50 |
51 | static func is_empty(value: String, context: String) -> Dictionary:
52 | var passed: String = "String is empty"
53 | var failed: String = "String %s is not empty" % [value]
54 | var success = value.empty()
55 | var expected = passed
56 | var result = passed if success else failed
57 | return _result(success, expected, result, context)
58 |
59 |
--------------------------------------------------------------------------------
/addons/WAT/assertions/utility.gd:
--------------------------------------------------------------------------------
1 | extends "assertion.gd"
2 |
3 | static func fail(context: String = "Test Not Implemented") -> Dictionary:
4 | # Intentionally Fails Test
5 | return _result(false, "N/A", "N/A", context)
6 |
7 | static func auto_pass(context: String = "Auto Pass") -> Dictionary:
8 | return _result(true, "N/A", "N/A", context)
9 |
10 | # Callv does not work on virtual classes (Array etc)
11 | static func that(obj, method: String, arguments: Array = [], context: String = "", passed: String = "", failed: String = "") -> Dictionary:
12 | var success = obj.callv(method, arguments)
13 | var expected = passed
14 | var result = passed if success else failed
15 | return _result(success, expected, result, context)
16 |
17 | # asserts.that(array, "empty", [], "Array is empty", "Empty", "Found %s items" % array.size())
18 |
--------------------------------------------------------------------------------
/addons/WAT/assets/debug_failed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/addons/WAT/assets/debug_failed.png
--------------------------------------------------------------------------------
/addons/WAT/assets/debug_failed.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/debug_failed.png-0deb1d1782c19daaffc5af47aba4eafc.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/WAT/assets/debug_failed.png"
13 | dest_files=[ "res://.import/debug_failed.png-0deb1d1782c19daaffc5af47aba4eafc.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=true
25 | flags/anisotropic=false
26 | flags/srgb=1
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/WAT/assets/docs.svg:
--------------------------------------------------------------------------------
1 |
2 |
39 |
--------------------------------------------------------------------------------
/addons/WAT/assets/docs.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/docs.svg-a649391eeb4006a0bb13c9007d30760f.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/WAT/assets/docs.svg"
13 | dest_files=[ "res://.import/docs.svg-a649391eeb4006a0bb13c9007d30760f.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/WAT/assets/failed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/addons/WAT/assets/failed.png
--------------------------------------------------------------------------------
/addons/WAT/assets/failed.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/failed.png-18188bee7d18ad72bc7cbc6222c355b1.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/WAT/assets/failed.png"
13 | dest_files=[ "res://.import/failed.png-18188bee7d18ad72bc7cbc6222c355b1.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=true
25 | flags/anisotropic=true
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/WAT/assets/folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/addons/WAT/assets/folder.png
--------------------------------------------------------------------------------
/addons/WAT/assets/folder.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/folder.png-f6fa55e0795097315a7c899b7b15ee27.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/WAT/assets/folder.png"
13 | dest_files=[ "res://.import/folder.png-f6fa55e0795097315a7c899b7b15ee27.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/WAT/assets/function.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/addons/WAT/assets/function.png
--------------------------------------------------------------------------------
/addons/WAT/assets/function.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/function.png-b5f751bc93a3ee5a29c4d32864c250fc.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/WAT/assets/function.png"
13 | dest_files=[ "res://.import/function.png-b5f751bc93a3ee5a29c4d32864c250fc.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/WAT/assets/issue.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/addons/WAT/assets/issue.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/issue.svg-0e50d01edf27a6e481699d3b4373a6f9.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/WAT/assets/issue.svg"
13 | dest_files=[ "res://.import/issue.svg-0e50d01edf27a6e481699d3b4373a6f9.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/WAT/assets/kofi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/addons/WAT/assets/kofi.png
--------------------------------------------------------------------------------
/addons/WAT/assets/kofi.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/kofi.png-25130db51d1b80d6426df72322b3f642.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/WAT/assets/kofi.png"
13 | dest_files=[ "res://.import/kofi.png-25130db51d1b80d6426df72322b3f642.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/WAT/assets/label.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/addons/WAT/assets/label.png
--------------------------------------------------------------------------------
/addons/WAT/assets/label.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/label.png-6b04b72410cd91559f10027900e1c444.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/WAT/assets/label.png"
13 | dest_files=[ "res://.import/label.png-6b04b72410cd91559f10027900e1c444.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/WAT/assets/passed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/addons/WAT/assets/passed.png
--------------------------------------------------------------------------------
/addons/WAT/assets/passed.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/passed.png-1606da9dc4505c2bac72d61e0f5f988c.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/WAT/assets/passed.png"
13 | dest_files=[ "res://.import/passed.png-1606da9dc4505c2bac72d61e0f5f988c.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/WAT/assets/play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/addons/WAT/assets/play.png
--------------------------------------------------------------------------------
/addons/WAT/assets/play.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/play.png-2962300029223d688c79411a6cda4a6d.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/WAT/assets/play.png"
13 | dest_files=[ "res://.import/play.png-2962300029223d688c79411a6cda4a6d.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=true
25 | flags/anisotropic=false
26 | flags/srgb=0
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/WAT/assets/play_debug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/addons/WAT/assets/play_debug.png
--------------------------------------------------------------------------------
/addons/WAT/assets/play_debug.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/play_debug.png-b9aaa3991495e16a0dfe9e46268ae0a2.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/WAT/assets/play_debug.png"
13 | dest_files=[ "res://.import/play_debug.png-b9aaa3991495e16a0dfe9e46268ae0a2.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/WAT/assets/play_failed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/addons/WAT/assets/play_failed.png
--------------------------------------------------------------------------------
/addons/WAT/assets/play_failed.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/play_failed.png-206503f73ae232b267852de2008ff514.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/WAT/assets/play_failed.png"
13 | dest_files=[ "res://.import/play_failed.png-206503f73ae232b267852de2008ff514.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/WAT/assets/request_docs.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/addons/WAT/assets/request_docs.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/request_docs.svg-66a60c4eba54402104d46cbe772a490e.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/WAT/assets/request_docs.svg"
13 | dest_files=[ "res://.import/request_docs.svg-66a60c4eba54402104d46cbe772a490e.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/WAT/assets/script.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/addons/WAT/assets/script.png
--------------------------------------------------------------------------------
/addons/WAT/assets/script.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/script.png-6590c0f9543eaeb2a6b5b8ca50aae436.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/WAT/assets/script.png"
13 | dest_files=[ "res://.import/script.png-6590c0f9543eaeb2a6b5b8ca50aae436.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/WAT/assets/timer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/addons/WAT/assets/timer.png
--------------------------------------------------------------------------------
/addons/WAT/assets/timer.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/timer.png-16c233793d4e507805f02aeac7ec3915.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://addons/WAT/assets/timer.png"
13 | dest_files=[ "res://.import/timer.png-16c233793d4e507805f02aeac7ec3915.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/addons/WAT/cli.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=2 format=2]
2 |
3 | [ext_resource path="res://addons/WAT/ui/cli.gd" type="Script" id=1]
4 |
5 | [node name="Commandline" type="Node"]
6 | script = ExtResource( 1 )
7 |
--------------------------------------------------------------------------------
/addons/WAT/double/factory.gd:
--------------------------------------------------------------------------------
1 | extends Node
2 |
3 | const ScriptDirector = preload("script_director.gd")
4 | const SceneDirector = preload("scene_director.gd")
5 | var registry
6 |
7 | func clear() -> void:
8 | # Allow users to clear registry in the post hook if they want fresh values between runs
9 | registry.clear()
10 | for director in registry.test_directors.values() :
11 | director.free()
12 | registry.test_directors.clear()
13 |
14 | func script(path, inner: String = "", deps: Array = []) -> ScriptDirector:
15 | if path is GDScript: path = path.resource_path
16 | return ScriptDirector.new(registry, path, inner, deps)
17 |
18 | func scene(tscn) -> SceneDirector:
19 | # Must be String.tscn or PackedScene
20 | var scene: PackedScene = load(tscn) if tscn is String else tscn
21 | var instance: Node = scene.instance()
22 | var nodes: Dictionary = {}
23 | var frontier: Array = []
24 | frontier.append(instance)
25 | while not frontier.empty():
26 | var next: Node = frontier.pop_front()
27 | if next.name.begins_with("@@"):
28 | # Don't double engine-generated classes (usually begin with @@)
29 | continue
30 | frontier += next.get_children()
31 | var path: String = instance.get_path_to(next)
32 | if next.get_script() != null:
33 | nodes[path] = script(next.get_script().resource_path)
34 | elif ClassDB.class_exists(next.get_class()):
35 | nodes[path] = script(next.get_class())
36 | _set_nodepath_variables(instance, nodes)
37 | var export_values = _get_exported_variable_values(instance)
38 | instance.queue_free()
39 | return SceneDirector.new(nodes, export_values)
40 |
41 | func _set_nodepath_variables(instance, nodes: Dictionary):
42 | # Nodepath Variables Are Exported
43 | # Which means they are typically not shared by instances
44 | # Therefore we got to do it manually
45 | for path in nodes:
46 | var source = instance.get_node(path)
47 | var copy = nodes[path]
48 | for prop in source.get_property_list():
49 | if(prop.type == TYPE_NODE_PATH and prop.name != "_import_path"):
50 | var exported_value = source.get(prop.name) as NodePath
51 | copy.nodepaths[prop.name] = exported_value as NodePath
52 |
53 | # We need this script to be inside the tree to prevent some errors...
54 | # ..everything should be fine if the instance isn't a tool script I think..
55 | # ..at least in editor
56 | func _get_exported_variable_values(instance) -> Dictionary:
57 | var exported: Dictionary = {}
58 | add_child(instance)
59 | for prop in instance.get_property_list():
60 | if _is_exported_variable(prop.usage):
61 | exported[prop.name] = instance.get(prop.name)
62 | remove_child(instance)
63 | return exported
64 |
65 | func _is_exported_variable(usage: int) -> bool:
66 | return usage == PROPERTY_USAGE_DEFAULT + PROPERTY_USAGE_SCRIPT_VARIABLE
67 |
--------------------------------------------------------------------------------
/addons/WAT/double/method.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | var name: String = ""
4 | var spying: bool = false
5 | var stubbed: bool = false
6 | var calls_super: bool = false
7 | var args: String = ""
8 | var args_with_defaults: String = ""
9 | var keyword: String = ""
10 | var calls: Array = []
11 | var stubs: Array = []
12 | var supers: Array = []
13 | var callables: Array = []
14 | var default
15 | var double
16 |
17 | func _init(name: String, keyword: String, args: String, defaults: String) -> void:
18 | self.name = name
19 | self.keyword = keyword
20 | self.args = args
21 | self.args_with_defaults = defaults
22 |
23 | func dummy() -> Reference:
24 | stubbed = true
25 | default = null
26 | return self
27 |
28 | func spy() -> Reference:
29 | push_warning("Deprecated. Spying on Methods is now Automatic. Please Remove")
30 | spying = true
31 | return self
32 |
33 | func stub(return_value, arguments: Array = []):
34 | stubbed = true
35 | if arguments.empty():
36 | default = return_value
37 | else:
38 | stubs.append({args = arguments, "return_value": return_value})
39 | return self
40 |
41 | func primary(args: Array):
42 | if stubbed:
43 | return get_stub(args)
44 | elif calls.size() > 0:
45 | for call in callables:
46 | return call.call_func(double, args)
47 | else:
48 | return null
49 |
50 | func add_call(args: Array = []) -> void:
51 | calls.append(args)
52 |
53 | func subcall(function: Object, deprecated_var = null) -> void:
54 | if deprecated_var != null:
55 | push_warning("Users no longer need to pass in the return boolean")
56 | callables.append(function)
57 |
58 | func get_stub(args: Array = []):
59 | for stub in stubs:
60 | if _pattern_matched(stub.args, args):
61 | return stub.return_value
62 | return default
63 |
64 | func executes(args: Array) -> bool:
65 | for s in supers:
66 | if _pattern_matched(s, args):
67 | return true
68 | for s in stubs:
69 | if _pattern_matched(s.args, args):
70 | return false
71 | if supers.has([]):
72 | return true
73 | return false
74 |
75 | func call_super(args: Array = []) -> void:
76 | supers.append(args)
77 | calls_super = true
78 |
79 | func found_matching_call(expected_args: Array = []) -> bool:
80 | for call in calls:
81 | if _pattern_matched(expected_args, call):
82 | return true
83 | return false
84 |
85 | func _pattern_matched(pattern: Array = [], args: Array = []) -> bool:
86 | var indices: Array = []
87 | if pattern.size() != args.size():
88 | return false
89 | for index in pattern.size():
90 | if pattern[index] is Object and pattern[index].get_class() == "Any":
91 | continue
92 | indices.append(index)
93 | for i in indices:
94 | # We check based on type first otherwise some errors occur (ie object can't be compared to int)
95 | if typeof(pattern[i]) != typeof(args[i]) or pattern[i] != args[i]:
96 | return false
97 | return true
98 |
--------------------------------------------------------------------------------
/addons/WAT/double/methods.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | var base: Array = []
4 |
5 | func set_base_methods(director: Reference) -> void:
6 | pass
7 |
8 | func call_count():
9 | pass
10 |
--------------------------------------------------------------------------------
/addons/WAT/double/registry.gd:
--------------------------------------------------------------------------------
1 | extends Object
2 |
3 | var test_directors: Dictionary = {}
4 |
5 | func register(director) -> void:
6 | # This probably doesn't need to exist as a singleton?
7 | # We could likely store a cache within each test
8 | # This way we can isolate it from other caches
9 | # (We could even probably store it directly within the factory)
10 | if director.get_instance_id() in test_directors:
11 | push_warning("Director Object is already registered")
12 | return
13 | test_directors[director.get_instance_id()] = director
14 |
15 | func method(instance_id: int, method: String) -> Object:
16 | return test_directors[instance_id].methods[method]
17 |
18 | func clear() -> void:
19 | var directors = test_directors.values()
20 | while not directors.empty():
21 | var director = directors.pop_back()
22 | director.clear()
23 |
24 | func _notification(what):
25 | if what == NOTIFICATION_PREDELETE:
26 | clear()
27 |
--------------------------------------------------------------------------------
/addons/WAT/double/scene_director.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 | tool
3 | # We don't seem to need tool here yet but I'm keeping this comment JIC
4 |
5 | var nodes: Dictionary = {}
6 | var _created: bool = false
7 | var cache: Array = []
8 | var _export_vars = {}
9 |
10 | func _init(nodes: Dictionary = {}, export_vars = {}) -> void:
11 | self.nodes = nodes
12 | _export_vars = export_vars
13 |
14 | func get_node(path: String) -> Node:
15 | return nodes[path]
16 |
17 | func double() -> Node:
18 | if _created:
19 | push_error("WAT: You can only create one instance of a double"
20 | + "Create a new doubler Object for new Test Doubles")
21 | return nodes["."]
22 | _created = true
23 | var root: Node = nodes["."].double()
24 | for nodepath in nodes:
25 | var path: PoolStringArray = nodepath.split("/")
26 | if nodepath == ".":
27 | # Skip if root node since already defined
28 | continue
29 | elif path.size() == 1:
30 | _add_child(path, nodepath, root)
31 | elif path.size() > 1:
32 | _add_grandchild(path, nodepath, root)
33 | for prop_name in _export_vars:
34 | root.set(prop_name, _export_vars[prop_name])
35 | return root
36 |
37 | func _add_child(path: PoolStringArray, nodepath: String, root: Node) -> void:
38 | var node: Node = nodes[nodepath].double()
39 | node.name = path[0]
40 | root.add_child(node)
41 |
42 | func _add_grandchild(path: PoolStringArray, nodepath: String, root: Node) -> void:
43 | var node: Node = nodes[nodepath].double()
44 | var p = Array(path)
45 | node.name = p.pop_back()
46 | var parent = ""
47 | for element in p:
48 | parent += "%s/" % element
49 | parent = parent.rstrip("/")
50 | var grandparent = root.get_node(parent)
51 | grandparent.add_child(node)
52 |
53 | func clear() -> void:
54 | nodes = {}
55 |
--------------------------------------------------------------------------------
/addons/WAT/double/script_writer.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 |
4 | func write(double) -> String:
5 | var source: String = ""
6 | source += _extension_to_string(double)
7 | source += "\nconst WATRegistry = []\n"
8 | if double.base_methods.has("_init"):
9 | source += _constructor_to_string(double.base_methods["_init"].arguments)
10 |
11 | for name in double.methods:
12 | var m = double.methods[name]
13 | source += _method_to_string(double.get_instance_id(), m)
14 | for klass in double.klasses:
15 | source += _inner_class(klass)
16 | source = source.replace(",)", ")")
17 | return source
18 |
19 | func _extension_to_string(double) -> String:
20 | if double.is_built_in:
21 | return 'extends %s' % double.klass
22 | if double.inner_klass != "":
23 | return 'extends "%s".%s\n' % [double.klass, double.inner_klass]
24 | return 'extends "%s"\n' % double.klass
25 |
26 | func _constructor_to_string(parameters: String) -> String:
27 | var constructor: String = ""
28 | constructor += "\nfunc _init(%s).(%s):" % [parameters, parameters]
29 | constructor += "\n\tpass\n"
30 | return constructor
31 |
32 | func _method_to_string(id: int, method: Object) -> String:
33 | var text: String
34 | text += "{keyword}func {name}({args_with_defaults}):"
35 | text += "\n\tvar args = [{args}]"
36 | text += "\n\tvar method = WATRegistry[0].method({id}, '{name}')"
37 | text += "\n\tmethod.add_call(args)"
38 | text += "\n\tif method.executes(args):"
39 | text += "\n\t\treturn .{name}({args})" # We may want to add a retval check here
40 | text += "\n\treturn method.primary(args)\n\n"
41 | text = text.format({"id": id, "keyword": method.keyword,
42 | "name": method.name, "args_with_defaults": method.args_with_defaults,
43 | "args": method.args})
44 | return text
45 |
46 | func _inner_class(klass: Dictionary) -> String:
47 | return "\nclass %s extends '%s'.%s:\n\tconst PLACEHOLDER = 0" % [klass.name, klass.director.klass, klass.name]
48 |
--------------------------------------------------------------------------------
/addons/WAT/filesystem/directory.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | var is_root: bool = false
4 | var name: String setget ,_get_sanitized_name
5 | var path: String setget ,_get_path
6 | var relative_subdirs: Array
7 | var nested_subdirs: Array
8 | var tests: Array = []
9 |
10 | func _get_sanitized_name() -> String:
11 | # Required for interface compability
12 | return path
13 |
14 | func _get_path() -> String:
15 | # res:/// should be res://f
16 | return path.replace("///", "//") #
17 |
18 | func get_tests() -> Array:
19 | var requested: Array = []
20 | if is_root:
21 | for subdir in nested_subdirs:
22 | requested += subdir.get_tests()
23 | for script in tests:
24 | requested += script.get_tests()
25 | return requested
26 |
27 | func is_empty() -> bool:
28 | return tests.empty()
29 |
--------------------------------------------------------------------------------
/addons/WAT/filesystem/failed.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | var paths: Array = []
4 | var _tests: Array = []
5 |
6 | func update(results: Array) -> void:
7 | paths.clear()
8 | for result in results:
9 | if not result["success"]:
10 | paths.append(result["path"])
11 |
12 | func set_tests(root: Reference) -> void:
13 | _tests.clear()
14 | for test in root.get_tests():
15 | if paths.has(test["path"]):
16 | _tests.append(test)
17 |
18 | func get_tests() -> Array:
19 | return _tests
20 |
--------------------------------------------------------------------------------
/addons/WAT/filesystem/method.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | var path: String
4 | var dir: String setget ,_get_path
5 | var name: String setget ,_get_sanitized_name
6 |
7 | func _init(method_path: String = "", method_name: String = ""):
8 | path = method_path
9 | name = method_name
10 |
11 | # Method Name != test name
12 | func get_tests() -> Array:
13 | return [{"dir": dir, "name": name, "path": self.path, "methods": [name], "time": 0.0}]
14 |
15 | func _get_sanitized_name() -> String:
16 | var n: String = name.replace("test_", "").replace("_", " ")
17 | return n
18 |
19 | func _get_path() -> String:
20 | # res:/// should be res://
21 | return path.replace("///", "//") #
22 |
--------------------------------------------------------------------------------
/addons/WAT/filesystem/script.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | var name: String setget ,_get_sanitized_name
4 | var dir: String
5 | var path: String setget ,_get_path
6 | var methods: Array # TestMethods
7 | var names: Array # MethodNames
8 | var time: float = 0.0 # YieldTime
9 | var parse: int # stores error code (int) of last load()
10 |
11 | # Constructor for script.gd reference.
12 | # script_path: Resource path of the script.
13 | # load_result: Error code when resource path is reloaded.
14 | func _init(script_path: String = "", load_result: int = OK):
15 | path = script_path
16 | parse = load_result
17 |
18 | func _get_sanitized_name() -> String:
19 | var n: String = path.substr(path.find_last("/") + 1)
20 | n = n.replace(".gd", "").replace(".gdc", "").replace(".cs", "")
21 | n = n.replace(".test", "").replace("test", "").replace("_", " ")
22 | n[0] = n[0].to_upper()
23 | return n
24 |
25 | func _get_path() -> String:
26 | # res:/// should be res://
27 | return path.replace("///", "//") #
28 |
29 | func get_tests() -> Array:
30 | return [{"dir": dir, "name": self.name, "path": self.path, "methods": names, "time": time, "parse": parse}]
31 |
--------------------------------------------------------------------------------
/addons/WAT/filesystem/tagged.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 | # Tag / Resource Path
3 | var tagged: Dictionary = {}
4 | var _settings: GDScript
5 | var _tests: Array = []
6 |
7 | func _init(settings: GDScript) -> void:
8 | _settings = settings
9 | update()
10 |
11 | func tag(tag: String, path: String) -> void:
12 | update()
13 | if not tagged[tag].has(path):
14 | tagged[tag].append(path)
15 |
16 | func untag(tag: String, path: String) -> void:
17 | update()
18 | if tagged[tagged].has(path):
19 | tagged[tag].erase(path)
20 |
21 | func is_tagged(tag: String, path: String) -> bool:
22 | update()
23 | return tagged[tag].has(path)
24 |
25 | func swap(old: String, new: String) -> void:
26 | for tag in tagged:
27 | if tagged[tag].has(old):
28 | tagged[tag].erase(old)
29 | tagged[tag].append(new)
30 |
31 | func update() -> void:
32 | for tag in _settings.tags():
33 | if not tagged.has(tag):
34 | tagged[tag] = []
35 |
36 | func set_tests(tag: String, root: Reference) -> void:
37 | _tests.clear()
38 | for test in root.get_tests():
39 | if tagged[tag].has(test["path"]):
40 | _tests.append(test)
41 |
42 | func get_tests() -> Array:
43 | return _tests
44 |
45 |
46 |
--------------------------------------------------------------------------------
/addons/WAT/filesystem/tracker.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Reference
3 |
4 | ### This only works in the Editor Context. There are no similair methods..
5 | ### ..available for the Scene Context.
6 |
7 | const Settings: GDScript = preload("res://addons/WAT/settings.gd")
8 | var _file_system
9 |
10 | func _init(filesystem) -> void:
11 | _file_system = filesystem
12 |
13 | func start_tracking_files(plugin: EditorPlugin) -> void:
14 | var dock: FileSystemDock = plugin.get_editor_interface().get_file_system_dock()
15 | for event in ["file_removed", "files_moved", "folder_moved", "folder_removed"]:
16 | var callback: String = "_on_%s" % event
17 | if not dock.is_connected(event, self, callback):
18 | dock.connect(event, self, callback)
19 | if not plugin.is_connected("resource_saved", self, "_on_resource_saved"):
20 | plugin.connect("resource_saved", self, "_on_resource_saved")
21 |
22 | func _stop_tracking_files(plugin: EditorPlugin) -> void:
23 | var dock: FileSystemDock = plugin.get_editor_interface().get_file_system_dock()
24 | for event in ["file_removed", "files_moved", "folder_moved", "folder_removed"]:
25 | var callback: String = "_on_%s" % event
26 | if dock.is_connected(event, self, callback):
27 | dock.disconnect(event, self, callback)
28 | if plugin.is_connected("resource_saved", self, "_on_resource_saved"):
29 | plugin.disconnect("resource_saved", self, "_on_resource_saved")
30 |
31 | func _on_filesystem_changed(has_changed: bool) -> void:
32 | if has_changed:
33 | _file_system.changed = true
34 |
35 | func _on_file_removed(file: String) -> void:
36 | _on_filesystem_changed(file.begins_with(Settings.test_directory()))
37 |
38 | func _on_files_moved(old: String, new: String) -> void:
39 | if old.begins_with(Settings.test_directory()) and new.begins_with(Settings.test_directory()):
40 | _file_system.tagged.swap(old, new)
41 | _on_filesystem_changed(
42 | old.begins_with(Settings.test_directory())
43 | or new.begins_with(Settings.test_directory()))
44 |
45 |
46 | func _on_folder_moved(old: String, new: String) -> void:
47 | _on_filesystem_changed(
48 | old.begins_with(Settings.test_directory())
49 | or new.begins_with(Settings.test_directory()))
50 |
51 | func _on_folder_removed(old: String) -> void:
52 | _on_filesystem_changed(old.begins_with(Settings.test_directory()))
53 |
54 | func _on_resource_saved(resource: Resource) -> void:
55 | _on_filesystem_changed(
56 | resource.resource_path.begins_with(Settings.test_directory()))
57 |
--------------------------------------------------------------------------------
/addons/WAT/filesystem/yield_calculator.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | const COMMENT: String = "#"
4 | const PRE_HOOK: String = "func pre()"
5 | const POST_HOOK: String = "func post()"
6 | const FUNCTION: String = "func"
7 | const OPENING_STRING_QUOTE: String = '"'
8 |
9 | static func calculate_yield_time(gdscript: Script, test_method_count: int) -> float:
10 | var time: float = 0.0
11 | var floats: PoolRealArray = PoolRealArray()
12 | var in_hook: bool = false
13 | for line in gdscript.source_code.split("\n"):
14 | if line.begins_with(PRE_HOOK) or line.begins_with(POST_HOOK):
15 | # Yielding pre or post requires counting for each test method
16 | in_hook = true
17 | elif line.begins_with(FUNCTION):
18 | in_hook = false
19 | if "YIELD" in line and not line.begins_with(COMMENT) and not line.begins_with(OPENING_STRING_QUOTE):
20 | var f: PoolRealArray = PoolRealArray()
21 | f += line.split_floats("(")
22 | f += line.split_floats(",")
23 | if in_hook:
24 | f = duplicate(f, test_method_count)
25 | floats += f
26 | for real in floats:
27 | time += real
28 | return time
29 |
30 | static func duplicate(source: PoolRealArray, count: int) -> PoolRealArray:
31 | var floats: PoolRealArray = PoolRealArray()
32 | for real in source:
33 | for i in count:
34 | floats.append(real)
35 | return floats
36 |
--------------------------------------------------------------------------------
/addons/WAT/io/junit_xml.gd:
--------------------------------------------------------------------------------
1 | extends Script
2 |
3 | static func write(results, settings: Reference, time: float = 0.0) -> void:
4 | var path: String
5 | if not settings.results_directory():
6 | push_warning("WAT: Cannot find results directory. Defaulting to root to write Junit XML")
7 | path = "res://"
8 | else:
9 | path = settings.results_directory()
10 | if not Directory.new().dir_exists(path):
11 | Directory.new().make_dir_recursive(path)
12 | var tests: int = results.size()
13 | var failures: int = 0
14 | for i in results:
15 | if not i.success:
16 | failures += 1
17 | var output: String = ""
18 | output += ''
19 | output += '\n' % [failures, tests, time]
20 | for result in results:
21 | output += '\n\t' % [result.context, result.total - result.passed, result.total, result.time_taken]
22 | if result.methods.empty():
23 | output += '\n\t\t'
24 | output += '' % result.path
25 | output += ""
26 | for case in result.methods:
27 | output += '\n\t\t' % [case.context, case.time]
28 | for assertion in case.assertions:
29 | if not assertion.success:
30 | output += '\n\t\t\t' % [assertion.expected, assertion.actual]
31 | # I think these are unnecessary. Will revisit on CLI creation.
32 | output += ''
33 | output += "\n\t\n"
34 | output += '\n'
35 | var XML = File.new()
36 | var xml_file: String = "%s/results.xml" % path
37 | var err = XML.open(xml_file, File.WRITE)
38 | if err:
39 | push_warning("Error saving result xml to %s : %s" % [xml_file, err as String])
40 | XML.store_string(output)
41 | XML.close()
42 |
--------------------------------------------------------------------------------
/addons/WAT/io/metadata.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | static func load_metadata(filesystem: Reference) -> void:
4 | var path: String
5 | if not filesystem.Settings.metadata_directory():
6 | path = filesystem.Settings.test_directory()
7 | else:
8 | path = filesystem.Settings.metadata_directory()
9 | path += "/metadata.json"
10 | if not Directory.new().file_exists(path):
11 | return
12 |
13 | var file = File.new()
14 | file.open(path, File.READ)
15 | var content: Dictionary = JSON.parse(file.get_as_text()).result
16 | file.close()
17 |
18 | for key in content:
19 | if key == "failed":
20 | filesystem.failed.paths = content[key]
21 | else:
22 | filesystem.tagged.tagged[key] = content[key]
23 |
24 | static func save_metadata(filesystem: Reference) -> void:
25 | var path: String
26 | if not filesystem.Settings.metadata_directory():
27 | push_warning("WAT: Cannot find metadata directory. Defaulting to test directory to save metadata")
28 | path = filesystem.Settings.test_directory()
29 | else:
30 | path = filesystem.Settings.metadata_directory()
31 | if not Directory.new().dir_exists(path):
32 | Directory.new().make_dir_recursive(path)
33 |
34 | path += "/metadata.json"
35 | var data = {"failed": filesystem.failed.paths}
36 | for tag in filesystem.tagged.tagged:
37 | var paths: Array = filesystem.tagged.tagged[tag]
38 | if not paths.empty():
39 | data[tag] = paths
40 |
41 | var file = File.new()
42 | file.open(path, File.WRITE)
43 | file.store_string(JSON.print(data, "\t", true))
44 | file.close()
45 |
--------------------------------------------------------------------------------
/addons/WAT/mono/Attributes.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Godot;
3 |
4 | namespace WAT
5 | {
6 | public partial class Test: Node
7 | {
8 | [AttributeUsage(AttributeTargets.Class)]
9 | protected class TitleAttribute : Attribute
10 | {
11 | public readonly string Title;
12 |
13 | public TitleAttribute(string title)
14 | {
15 | Title = title;
16 | }
17 | }
18 |
19 | [AttributeUsage(AttributeTargets.Class)]
20 | protected class HookAttribute : Attribute
21 | {
22 | public readonly string Method;
23 | protected HookAttribute(string method) => Method = method;
24 | }
25 |
26 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
27 | protected class TestAttribute : Attribute
28 | {
29 | public readonly object[] Arguments;
30 | public TestAttribute(params object[] args) { Arguments = args; }
31 | }
32 |
33 | protected class StartAttribute : HookAttribute { public StartAttribute(string method) : base(method) { } }
34 | protected class PreAttribute : HookAttribute { public PreAttribute(string method) : base(method) { } }
35 | protected class PostAttribute : HookAttribute { public PostAttribute(string method) : base(method) { } }
36 | protected class EndAttribute : HookAttribute { public EndAttribute(string method) : base(method) { } }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/addons/WAT/mono/BuildScene.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 | using System;
3 |
4 | public class BuildScene : Node
5 | {
6 | public override void _Ready()
7 | {
8 | GetTree().Quit();
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/addons/WAT/mono/BuildScene.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=2 format=2]
2 |
3 | [ext_resource path="res://addons/WAT/mono/BuildScene.cs" type="Script" id=1]
4 |
5 | [node name="BuildScene" type="Node"]
6 | script = ExtResource( 1 )
7 |
--------------------------------------------------------------------------------
/addons/WAT/mono/GDScriptWrapper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using Godot;
6 | using Array = Godot.Collections.Array;
7 | using Object = Godot.Object;
8 | // ReSharper disable InconsistentNaming
9 |
10 |
11 | namespace WAT
12 | {
13 |
14 | public partial class Test: Node
15 | {
16 | [Signal] public delegate void test_method_started();
17 | [Signal] public delegate void asserted();
18 | [Signal] public delegate void test_method_finished();
19 | [Signal] public delegate void test_script_finished();
20 |
21 | private const bool IS_WAT_TEST = true;
22 |
23 | private void OnAssertion(Godot.Collections.Dictionary assertion)
24 | {
25 | EmitSignal(nameof(asserted), assertion);
26 | }
27 |
28 | public String title() { return Title(); }
29 |
30 | public Array get_test_methods()
31 | {
32 | return new Array
33 | (GetType().GetMethods().
34 | Where(m => m.IsDefined(typeof(TestAttribute))).
35 | Select(m => (string) m.Name).ToList());
36 | }
37 |
38 | public Test setup(string directory, string filepath, IEnumerable methods)
39 | {
40 | _methods = GenerateTestMethods(methods);
41 | _case = (Object) GD.Load("res://addons/WAT/test/case.gd").New(directory, filepath, Title(), this);
42 | return this;
43 | }
44 |
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/addons/WAT/mono/assertions/Assertion.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Dynamic;
3 | using Godot;
4 | using Godot.Collections;
5 |
6 | namespace WAT
7 | {
8 | public class Assertion
9 | {
10 |
11 | protected static Dictionary Result(bool success, string expected, string actual, string context, string notes = "")
12 | {
13 | return new Dictionary
14 | {
15 | {"success", success},
16 | {"expected", expected},
17 | {"actual", actual},
18 | {"context", context}
19 | };
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/addons/WAT/mono/assertions/Boolean.cs:
--------------------------------------------------------------------------------
1 | using Godot.Collections;
2 |
3 | namespace WAT
4 | {
5 | public class Boolean: Assertion
6 | {
7 | public static Dictionary IsTrue(bool value, string context)
8 | {
9 | string passed = $"|boolean| {value.ToString()} == true";
10 | string failed = $"|boolean| {value.ToString()} == false";
11 | string result = value ? passed : failed;
12 | return Result(value, passed, result, context);
13 | }
14 |
15 | public static Dictionary IsFalse(bool value, string context)
16 | {
17 | string passed = $"|boolean| {value.ToString()} == false";
18 | string failed = $"|boolean| {value.ToString()} == true";
19 | bool success = !value;
20 | string result = success ? passed : failed;
21 | return Result(success, passed, result, context);
22 | }
23 | }
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/addons/WAT/mono/assertions/File.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Godot;
3 | using Godot.Collections;
4 |
5 | namespace WAT
6 | {
7 | public class File: Assertion
8 | {
9 | public static Dictionary Exists(string path, string context)
10 | {
11 | string passed = $"{path} exists";
12 | string failed = $"{path} does not exist";
13 | bool success = new Godot.File().FileExists(path);
14 | string result = success ? passed : failed;
15 | return Result(success, passed, result, context);
16 | }
17 |
18 | public static Dictionary DoesNotExist(string path, string context)
19 | {
20 | string passed = $"{path} does not exist";
21 | string failed = $"{path} exists";
22 | bool success = !new Godot.File().FileExists(path);
23 | string result = success ? passed : failed;
24 | return Result(success, passed, result, context);
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/addons/WAT/mono/assertions/Is.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 | using System;
3 | using Godot.Collections;
4 |
5 | namespace WAT {
6 |
7 | public class Is : Assertion
8 | {
9 | public static Dictionary IsType(object value, string context)
10 | {
11 | string passed = $"{value} is builtin {typeof(T)}";
12 | string failed = $"{value} is not builtin {typeof(T)}";
13 | bool success = value is T;
14 | string result = success ? passed : failed;
15 | return Result(success, passed, result, context);
16 | }
17 |
18 | public static Dictionary IsNotType(object value, string context)
19 | {
20 | string passed = $"{value} is builtin {typeof(T)}";
21 | string failed = $"{value} is not builtin {typeof(T)}";
22 | bool success = !(value is T);
23 | string result = success ? passed : failed;
24 | return Result(success, passed, result, context);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/addons/WAT/mono/assertions/Null.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 | using System;
3 | using Godot.Collections;
4 |
5 |
6 | namespace WAT
7 | {
8 | public class Null : Assertion
9 | {
10 | // Godot Objects that are freed don't become null immediatly
11 | // so they may still be valid instances
12 | public static Dictionary IsNull(object obj, string context)
13 | {
14 | const string passed = "object is null";
15 | const string failed = "object is not null";
16 | bool success = obj is null;
17 | if (!success)
18 | {
19 | //failed = $"{obj} is not null";
20 | }
21 |
22 | string result = success ? passed : failed;
23 | return Result(success, passed, result, context);
24 | }
25 |
26 | public static Dictionary IsNotNull(object obj, string context)
27 | {
28 | string passed = "object is not null";
29 | const string failed = "object is null";
30 | bool success = !(obj is null);
31 | if (success)
32 | {
33 | passed = $"{obj} is not null";
34 | }
35 |
36 | string result = success ? passed : failed;
37 | return Result(success, passed, result, context);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/addons/WAT/mono/assertions/Property.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using Godot.Collections;
3 |
4 | namespace WAT
5 | {
6 | public class Property: Assertion
7 | {
8 | public static Dictionary Contains(object value, T container, string context)
9 | {
10 | string passed = $"{container.GetType()} contains |{value.GetType()}|{value}";
11 | string failed = $"{container.GetType()} does not contain |{value.GetType()}|{value}";
12 | MethodInfo method = container.GetType().GetMethod("Contains");
13 | bool success = false;
14 | if (method != null)
15 | {
16 | success = (bool) method.Invoke(container, new object[] {value});
17 | }
18 |
19 | string result = success ? passed : failed;
20 | return Result(success, passed, result, context);
21 | }
22 |
23 | public static Dictionary DoesNotContain(object value, T container, string context)
24 | {
25 | string passed = $"{container.GetType()} does not contain |{value.GetType()}|{value}";
26 | string failed = $"{container.GetType()} contains |{value.GetType()}|{value}";
27 | MethodInfo method = container.GetType().GetMethod("Contains");
28 | bool success = false;
29 | if (method != null)
30 | {
31 | success = !(bool) method.Invoke(container, new object[] {value});
32 | }
33 |
34 | string result = success ? passed : failed;
35 | return Result(success, passed, result, context);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/addons/WAT/mono/assertions/Range.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Godot.Collections;
3 |
4 | namespace WAT
5 | {
6 | public class Range: Assertion
7 | {
8 | public static Dictionary IsInRange(double val, double low, double high, string context)
9 | {
10 | string passed = $"{val} is in range {low}-{high}";
11 | string failed = $"{val} is not in range {low}-{high}";
12 | bool success = val >= low && val < high;
13 | string result = success ? passed : failed;
14 | return Result(success, passed, result, context);
15 | }
16 |
17 | public static Dictionary IsNotInRange(double val, double low, double high, string context)
18 | {
19 | string passed = $"{val} is not in range {low}-{high}";
20 | string failed = $"{val} is in range {low}-{high}";
21 | bool success = val < low || val >= high;
22 | string result = success ? passed : failed;
23 | return Result(success, passed, result, context);
24 | }
25 |
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/addons/WAT/mono/assertions/StringX.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 | using Godot.Collections;
3 |
4 | namespace WAT
5 | {
6 | public class StringX: Assertion
7 | {
8 | public static Dictionary BeginsWith(string value, string str, string context)
9 | {
10 | string passed = $"{str} begins with {value}";
11 | string failed = $"{str} does not begin with {value}";
12 | bool success = str.BeginsWith(value);
13 | string result = success ? passed : failed;
14 | return Result(success, passed, result, context);
15 | }
16 |
17 | public static Dictionary DoesNotBeginWith(string value, string str, string context)
18 | {
19 | string passed = $"{str} does not begin with {value}";
20 | string failed = $"{str} begins with {value}";
21 | bool success = !str.BeginsWith(value);
22 | string result = success ? passed : failed;
23 | return Result(success, passed, result, context);
24 | }
25 |
26 | public static Dictionary Contains(string value, string str, string context)
27 | {
28 | string passed = $"{str} contains {value}";
29 | string failed = $"{str} does not contain {value}";
30 | bool success = str.Contains(value);
31 | string result = success ? passed : failed;
32 | return Result(success, passed, result, context);
33 | }
34 |
35 | public static Dictionary DoesNotContain(string value, string str, string context)
36 | {
37 | string passed = $"{str} does not contain {value}";
38 | string failed = $"{str} contains {value}";
39 | bool success = !str.Contains(value);
40 | string result = success ? passed : failed;
41 | return Result(success, passed, result, context);
42 | }
43 |
44 | public static Dictionary EndsWith(string value, string str, string context)
45 | {
46 | string passed = $"{str} ends with {value}";
47 | string failed = $"{str} does not end with {value}";
48 | bool success = str.EndsWith(value);
49 | string result = success ? passed : failed;
50 | return Result(success, passed, result, context);
51 | }
52 |
53 | public static Dictionary DoesNotEndWith(string value, string str, string context)
54 | {
55 | string passed = $"{str} does not end with {value}";
56 | string failed = $"{str} end with {value}";
57 | bool success = !str.EndsWith(value);
58 | string result = success ? passed : failed;
59 | return Result(success, passed, result, context);
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/addons/WAT/mono/assertions/Utility.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Godot;
4 | using Godot.Collections;
5 | using Object = Godot.Object;
6 |
7 | namespace WAT
8 | {
9 | public class Utility: Assertion
10 | {
11 | public static Dictionary Fail(string context)
12 | {
13 | return Result(false, "N/A", "N/A", context);
14 | }
15 |
16 | public static Dictionary AutoPass(string context)
17 | {
18 | return Result(true, "N/A", "N/A", context);
19 | }
20 |
21 | public static Dictionary Throws(Action function, string context)
22 | {
23 | try
24 | {
25 | function();
26 | const string fail = "No exception was thrown";
27 | return Result(false, "Exception was thrown", fail, context);
28 | }
29 | catch (Exception e)
30 | {
31 | string pass = $"Threw Exception {e} with Message: {e.Message}";
32 | return Result(true, "Exception was thrown", pass, context);
33 | }
34 | }
35 |
36 | public static Dictionary DoesNotThrow(Action function, string context)
37 | {
38 | try
39 | {
40 | function();
41 | string pass = $"No exception was thrown";
42 | return Result(true, "No Exception was thrown", pass, context);
43 | }
44 | catch (Exception e)
45 | {
46 | string fail = $"Threw {e} with Message: {e.Message}";
47 | return Result(true, "No Exception was thrown", fail, context);
48 | }
49 | }
50 |
51 | public static Dictionary Throws(Action function, string context)
52 | {
53 | string expected = $"{typeof(T)} was thrown";
54 | try
55 | {
56 | function();
57 | const string fail = "No Exception was thrown";
58 | return Result(false, expected, fail, context);
59 | }
60 | catch (Exception e)
61 | {
62 | if (e is T)
63 | {
64 | string pass = $"Threw {e} with Message: {e.Message}";
65 | return Result(true, expected, pass, context);
66 | }
67 |
68 | string fail = $"Threw {e} with Message: {e.Message}";
69 | return Result(false, expected, fail, context);
70 | }
71 | }
72 |
73 | public static Dictionary DoesNotThrow(Action function, string context)
74 | {
75 | string expected = $"{typeof(T)} was not thrown";
76 | try
77 | {
78 | function();
79 | string pass = $"Did not throw {typeof(T)}";
80 | return Result(true, expected, pass, context);
81 | }
82 | catch (Exception e)
83 | {
84 | string pass = "";
85 | if (e is T)
86 | {
87 | string fail = $"Threw {e} with Message: {e.Message}";
88 | return Result(false, expected, fail, context);
89 | }
90 |
91 | pass = $"Threw {e} with Message: {e.Message}";
92 | return Result(true, expected, pass, context);
93 | }
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/addons/WAT/namespace.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Reference
3 | class_name WAT
4 |
5 |
6 | const COMPLETED: String = "completed"
7 | const Test: Script = preload("res://addons/WAT/test/test.gd")
8 | const TestRunnerScene: PackedScene = preload("res://addons/WAT/runner/TestRunner.tscn")
9 |
--------------------------------------------------------------------------------
/addons/WAT/network/test_client.gd:
--------------------------------------------------------------------------------
1 | extends "res://addons/WAT/network/test_network.gd"
2 |
3 | func _ready() -> void:
4 | custom_multiplayer.connect("connection_failed", self, "_on_connection_failed")
5 | if _error(_peer.create_client(IPAddress, PORT)) == OK:
6 | custom_multiplayer.network_peer = _peer
7 |
8 | func _on_connection_failed() -> void:
9 | push_warning("TestClient could not connect to TestServer")
10 |
11 | puppet func _on_tests_received_from_server(tests: Array, repeat: int, thread_count: int) -> void:
12 | var results: Array = yield(get_parent().run(tests, repeat, thread_count, self), "completed")
13 | rpc_id(MASTER, "_on_results_received_from_client", results)
14 |
15 | # LiveWire Functions
16 | func on_test_script_started(data: Dictionary) -> void:
17 | rpc_id(MASTER, "_on_test_script_started", data)
18 |
19 | func on_test_script_finished(data: Dictionary) -> void:
20 | rpc_id(MASTER, "_on_test_script_finished", data)
21 |
22 | func on_test_method_started(data: Dictionary) -> void:
23 | rpc_id(MASTER, "_on_test_method_started", data)
24 |
25 | func on_test_method_finished(data: Dictionary) -> void:
26 | rpc_id(MASTER, "_on_test_method_finished", data)
27 |
28 | func on_asserted(data: Dictionary) -> void:
29 | rpc_id(MASTER, "_on_asserted", data)
30 |
31 | func on_test_method_described(data: Dictionary) -> void:
32 | rpc_id(MASTER, "_on_test_method_described", data)
33 |
--------------------------------------------------------------------------------
/addons/WAT/network/test_network.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Node
3 |
4 | const IPAddress: String = "127.0.0.1"
5 | const PORT: int = 6019
6 | const MAXCLIENTS: int = 1
7 | const MASTER: int = 1
8 | var _peer: NetworkedMultiplayerENet
9 | var _id: int
10 |
11 | func _init() -> void:
12 | _close()
13 | custom_multiplayer = MultiplayerAPI.new()
14 | custom_multiplayer.root_node = self
15 | custom_multiplayer.allow_object_decoding = true
16 | _peer = NetworkedMultiplayerENet.new()
17 |
18 | func _process(delta: float) -> void:
19 | if custom_multiplayer.has_network_peer():
20 | custom_multiplayer.poll()
21 |
22 | func _close() -> void:
23 | if is_instance_valid(_peer):
24 | if _is_connected():
25 | _peer.close_connection()
26 | _peer = null
27 |
28 | func _error(err: int) -> int:
29 | if err != OK:
30 | match err:
31 | ERR_ALREADY_IN_USE:
32 | push_warning("Network Peer is already in use")
33 | ERR_CANT_CREATE:
34 | push_warning("Network Peer cannot be created")
35 | _:
36 | push_warning(err as String)
37 | return err
38 |
39 | func _is_connected() -> bool:
40 | return _peer.get_connection_status() == NetworkedMultiplayerENet.CONNECTION_CONNECTED
41 |
42 | func _exit_tree() -> void:
43 | _close()
44 |
--------------------------------------------------------------------------------
/addons/WAT/network/test_server.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends "res://addons/WAT/network/test_network.gd"
3 |
4 | signal network_peer_connected
5 | signal results_received
6 |
7 | enum STATE { SENDING, RECEIVING, DISCONNECTED }
8 |
9 | var _peer_id: int
10 | # Store incoming cases from client in case of abrupt termination.
11 | var caselist: Array = []
12 | var results_view: TabContainer
13 | var status: int = STATE.DISCONNECTED
14 |
15 | func _ready() -> void:
16 | if not Engine.is_editor_hint():
17 | return
18 | custom_multiplayer.connect("network_peer_connected", self, "_on_network_peer_connected")
19 | custom_multiplayer.connect("network_peer_disconnected", self, "_on_network_peer_disconnected")
20 | if _error(_peer.create_server(PORT, MAXCLIENTS)) == OK:
21 | custom_multiplayer.network_peer = _peer
22 |
23 | func _on_network_peer_connected(id: int) -> void:
24 | _peer_id = id
25 | _peer.set_peer_timeout(id, 1000, 2000, 3000)
26 | emit_signal("network_peer_connected")
27 |
28 | func _on_network_peer_disconnected(_id: int) -> void:
29 | if status == STATE.SENDING:
30 | emit_signal("results_received", caselist)
31 | caselist.clear()
32 | status = STATE.DISCONNECTED
33 |
34 | func send_tests(testdir: Array, repeat: int, thread_count: int) -> void:
35 | status = STATE.SENDING
36 | rpc_id(_peer_id, "_on_tests_received_from_server", testdir, repeat, thread_count)
37 |
38 | master func _on_results_received_from_client(results: Array = []) -> void:
39 | status = STATE.RECEIVING
40 | emit_signal("results_received", results)
41 | _peer.disconnect_peer(_peer_id, true)
42 |
43 | master func _on_test_script_started(data: Dictionary) -> void:
44 | results_view.on_test_script_started(data)
45 |
46 | master func _on_test_script_finished(data: Dictionary) -> void:
47 | results_view.on_test_script_finished(data)
48 | caselist.append(data)
49 |
50 | master func _on_test_method_started(data: Dictionary) -> void:
51 | results_view.on_test_method_started(data)
52 |
53 | master func _on_test_method_finished(data: Dictionary) -> void:
54 | results_view.on_test_method_finished(data)
55 |
56 | master func _on_asserted(data: Dictionary) -> void:
57 | results_view.on_asserted(data)
58 |
59 | master func _on_test_method_described(data: Dictionary) -> void:
60 | results_view.on_test_method_described(data)
61 |
--------------------------------------------------------------------------------
/addons/WAT/plugin.cfg:
--------------------------------------------------------------------------------
1 | [plugin]
2 |
3 | name="WAT"
4 | description="Unit Testing Plugin"
5 | author="github/AlexDarigan"
6 | version="6"
7 | script="plugin.gd"
8 |
--------------------------------------------------------------------------------
/addons/WAT/plugin.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends EditorPlugin
3 |
4 | const Title: String = "Tests"
5 | const GUI: PackedScene = preload("res://addons/WAT/gui.tscn")
6 | const TestPanel: GDScript = preload("res://addons/WAT/ui/gui.gd")
7 | const TestPanelDocker: GDScript = preload("res://addons/WAT/ui/docker.gd")
8 | const FileSystem: GDScript = preload("res://addons/WAT/filesystem/filesystem.gd")
9 | const FileTracker: GDScript = preload("res://addons/WAT/filesystem/tracker.gd")
10 | const Settings: GDScript = preload("res://addons/WAT/settings.gd")
11 | const Metadata: GDScript = preload("res://addons/WAT/io/metadata.gd")
12 | const PluginAssetsRegistry: GDScript = preload("res://addons/WAT/ui/scaling/plugin_assets_registry.gd")
13 | var _test_panel: TestPanel
14 | var _file_system: FileSystem
15 | var _file_tracker: FileTracker
16 | var _assets_registiry: PluginAssetsRegistry
17 | var _panel_docker: TestPanelDocker
18 |
19 | func _enter_tree() -> void:
20 | Settings.initialize()
21 | var build: FuncRef = funcref(self, "_build_function")
22 | _file_system = FileSystem.new(build)
23 | _file_tracker = FileTracker.new(_file_system)
24 | Metadata.load_metadata(_file_system)
25 | _assets_registiry = PluginAssetsRegistry.new(self)
26 | _file_tracker.start_tracking_files(self)
27 | _test_panel = GUI.instance()
28 | _test_panel.setup_editor_context(self, build, funcref(self, "goto_function"), _file_system)
29 | _panel_docker = TestPanelDocker.new(self, _test_panel)
30 | add_child(_panel_docker)
31 |
32 | func _exit_tree() -> void:
33 | Metadata.save_metadata(_file_system)
34 | _panel_docker.queue_free()
35 | if(is_instance_valid(_test_panel)):
36 | _test_panel.queue_free()
37 |
38 | func _build_function() -> bool:
39 | _test_panel.Results.clear()
40 | var text: String = "FileSystem has been changed since last build."
41 | text += "\nTriggering a Build by launching an Empty Scene."
42 | text += "\nPlease select your option again after the scene quits."
43 | OS.alert(text, "Build Required")
44 | var editor: EditorInterface = get_editor_interface()
45 | editor.play_custom_scene("res://addons/WAT/mono/BuildScene.tscn")
46 | while editor.is_playing_scene():
47 | yield(get_tree(), "idle_frame")
48 | yield(get_tree(), "idle_frame")
49 | _file_system.update()
50 | _file_system.changed = false
51 | make_bottom_panel_item_visible(_test_panel)
52 | return true
53 |
54 | func goto_function(path: String, function: String) -> void:
55 | var script: Script = load(path)
56 | var script_editor: ScriptEditor = get_editor_interface().get_script_editor()
57 | get_editor_interface().edit_resource(script)
58 | var idx: int = 0
59 | for line in script.source_code.split("\n"):
60 | idx += 1
61 | if function in line and line.begins_with("func"):
62 | script_editor.goto_line(idx)
63 | return
64 |
--------------------------------------------------------------------------------
/addons/WAT/runner/TestRunner.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Node
3 |
4 | const Settings: GDScript = preload("res://addons/WAT/settings.gd")
5 | const Splitter: GDScript = preload("splitter.gd")
6 | const COMPLETED: String = "completed"
7 | signal completed
8 |
9 | func _ready() -> void:
10 | name = "TestRunner"
11 | if not Engine.is_editor_hint():
12 | OS.window_size = Settings.window_size()
13 | if Settings.minimize_window_when_running_tests():
14 | OS.window_minimized = true
15 |
16 | func run(tests: Array, repeat: int, threads: int, results_view: Node = null) -> Array:
17 | var results: Array = []
18 | tests = _repeat(tests, repeat)
19 | var testthreads = Splitter.split(tests, threads)
20 | for thread in testthreads:
21 | thread.controller.results = results_view
22 | add_child(thread.controller)
23 | thread.start(self, "_run", thread)
24 | thread.wait_to_finish()
25 | for count in testthreads:
26 | results += yield(self, COMPLETED)
27 | return results
28 |
29 | func _run(thread: Thread) -> void:
30 | var results: Array = []
31 | for test in thread.tests:
32 | results.append(yield(thread.controller.run(test), COMPLETED))
33 | thread.controller.queue_free()
34 | emit_signal(COMPLETED, results)
35 |
36 | func _repeat(tests: Array, repeat: int) -> Array:
37 | var duplicates: Array = []
38 | for idx in repeat:
39 | for test in tests:
40 | duplicates.append(test)
41 | duplicates += tests
42 | return duplicates
43 |
44 |
--------------------------------------------------------------------------------
/addons/WAT/runner/TestRunner.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=3 format=2]
2 |
3 | [ext_resource path="res://addons/WAT/runner/TestRunner.gd" type="Script" id=1]
4 | [ext_resource path="res://addons/WAT/network/test_client.gd" type="Script" id=2]
5 |
6 | [node name="TestRunner" type="Node"]
7 | script = ExtResource( 1 )
8 |
9 | [node name="TestClient" type="Node" parent="."]
10 | script = ExtResource( 2 )
11 |
--------------------------------------------------------------------------------
/addons/WAT/runner/splitter.gd:
--------------------------------------------------------------------------------
1 | extends Node
2 |
3 | static func split(tests: Array, threads: int = 1) -> Array:
4 | tests.sort_custom(YieldTimeSorter, "sort_ascending")
5 | threads = calibrate_threads(tests.size(), threads)
6 | return _testthreads(_distribute(_testpools(threads), tests, threads))
7 |
8 | static func calibrate_threads(tests: int, threads: int) -> int:
9 | if tests < threads:
10 | push_warning("Readjusting thread count to match low test size")
11 | threads = tests
12 | return threads
13 |
14 | static func _testpools(count: int) -> Array:
15 | var pools: Array = []
16 | for pool in count:
17 | pools.append([])
18 | return pools
19 |
20 | static func _distribute(pools: Array, tests: Array, count: int) -> Array:
21 | var idx: int = 0
22 | for test in tests:
23 | pools[idx].append(test)
24 | idx = 0 if idx == count - 1 else idx + 1
25 | return pools
26 |
27 | static func _testthreads(pools: Array) -> Array:
28 | # Our tests are sorted from slowest to quickest..
29 | # ..so we loop through each pool in order to disaparate time
30 | var threads: Array = []
31 | for pool in pools:
32 | threads.append(TestThread.new(pool))
33 | return threads
34 |
35 | class TestThread extends Thread:
36 | var tests: Array
37 | var controller: Node = load("res://addons/WAT/runner/test_controller.gd").new()
38 |
39 | func _init(_tests):
40 | tests = _tests
41 |
42 | class YieldTimeSorter:
43 |
44 | static func sort_ascending(a: Dictionary, b: Dictionary) -> bool:
45 | return a["time"] < b["time"]
46 |
47 |
48 |
--------------------------------------------------------------------------------
/addons/WAT/settings.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Reference
3 |
4 |
5 | static func initialize() -> void:
6 | if not ProjectSettings.has_setting("WAT/Test_Directory"):
7 | push_warning("Test Directory was set to project root.\nYou may change any setting for WAT in Project -> ProjectSettings -> General -> WAT")
8 | _add_setting("Test_Directory", TYPE_STRING, "res://")
9 | _add_setting("Results_Directory", TYPE_STRING, "res://")
10 | _add_setting("Test_Metadata_Directory", TYPE_STRING, "res://")
11 | _add_setting("Tags", TYPE_STRING_ARRAY, PoolStringArray())
12 | _add_setting("Cache_Tests", TYPE_BOOL, true)
13 | _add_setting("Window_Size", TYPE_VECTOR2, Vector2(1280, 720))
14 | _add_setting("Minimize_Window_When_Running_Tests", TYPE_BOOL, false)
15 | _add_setting("Port", TYPE_INT, 6008)
16 | _add_setting("Tags", TYPE_STRING_ARRAY, PoolStringArray())
17 |
18 | # Set this to true if using external editors
19 | ProjectSettings.save()
20 |
21 | static func _add_setting(title: String, type: int, value, hint_type: int = -1, hint_string = "") -> void:
22 | title = title.insert(0, "WAT/")
23 | if ProjectSettings.has_setting(title):
24 | return
25 | ProjectSettings.set(title, value)
26 | var prop: Dictionary = {}
27 | prop["name"] = title
28 | prop["type"] = type
29 | if hint_type > -1:
30 | prop["hint"] = hint_type
31 | prop["hint_string"] = hint_string
32 | ProjectSettings.add_property_info(prop)
33 |
34 | static func test_directory() -> String:
35 | return ProjectSettings.get_setting("WAT/Test_Directory")
36 |
37 | static func results_directory() -> String:
38 | return ProjectSettings.get_setting("WAT/Results_Directory")
39 |
40 | static func metadata_directory() -> String:
41 | return ProjectSettings.get_setting("WAT/Test_Metadata_Directory")
42 |
43 | static func window_size() -> Vector2:
44 | return ProjectSettings.get_setting("WAT/Window_Size")
45 |
46 | static func tags() -> PoolStringArray:
47 | return ProjectSettings.get_setting("WAT/Tags")
48 |
49 | static func cache_tests() -> bool:
50 | return ProjectSettings.get_setting("WAT/Cache_Tests")
51 |
52 | static func minimize_window_when_running_tests() -> bool:
53 | return ProjectSettings.get_setting("WAT/Minimize_Window_When_Running_Tests")
54 |
55 | static func port() -> int:
56 | return ProjectSettings.get_setting("WAT/Port")
57 |
58 | static func is_bottom_panel() -> int:
59 | return ProjectSettings.get_setting("WAT/Display") == 8
60 |
--------------------------------------------------------------------------------
/addons/WAT/test/any.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | # I hate this
4 | # Used for do not care values in stubs
5 | # Probably a better way to handle it
6 |
7 | func get_class() -> String:
8 | return "Any"
9 |
--------------------------------------------------------------------------------
/addons/WAT/test/case.gd:
--------------------------------------------------------------------------------
1 | extends Node
2 |
3 | var _total: int = 0
4 | var _passed: int = 0
5 | var _directory: String
6 | var _title: String
7 | var _path: String
8 | var _methods: Array = []
9 | var _success: bool = false
10 | var _time_taken: float = 0.0
11 | var _test: Node
12 | var _names: Array = []
13 |
14 | func _init(directory, filepath, title, test) -> void:
15 | _test = test
16 | _title = title
17 | _path = filepath
18 | _directory = directory
19 |
20 | func add_method(name: String) -> void:
21 | if name in _names:
22 | # We're running a test with multiple arguments
23 | return
24 | _names.append(name)
25 | var contxt = name.replace("_", " ").lstrip("test")
26 | _methods.append({fullname = name, context = contxt, assertions = [], total = 0, passed = 0, success = false, time = 0.0})
27 |
28 | func _on_test_method_described(description: String) -> void:
29 | _methods.back().context = description
30 |
31 | # We pass this to the controller who passes it to the runner who passes
32 | func _on_asserted(assertion: Dictionary) -> void:
33 | assertion["method"] = _methods.back()["fullname"]
34 | assertion["script"] = _path
35 | # Handle on demand so we can pass it on to live updaters
36 | _methods.back().assertions.append(assertion)
37 | _methods.back()["total"] += 1
38 | _methods.back()["passed"] += assertion["success"] as int # false = 0, true = 1
39 |
40 | func calculate() -> void:
41 | for method in _methods:
42 | method.success = method.total > 0 and method.total == method.passed
43 | _passed += method.success as int
44 | _total = _methods.size()
45 | _success = _total > 0 and _total == _passed
46 |
47 | func to_dictionary() -> Dictionary:
48 | return { total = _total,
49 | passed = _passed,
50 | context = _title,
51 | methods = _methods,
52 | success = _success,
53 | path = _path,
54 | time_taken = _time_taken,
55 | dir = _directory,
56 | }
57 |
--------------------------------------------------------------------------------
/addons/WAT/test/parameters.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | var _keys: Array = []
4 | var _values: Array = []
5 |
6 | var parameters: Dictionary = {}
7 | #parameters([["a", "b", "expected"], [2, 2, 4], [5, 5, 10], [7, 7, 14]])
8 | func parameters(list: Array) -> bool:
9 | if _keys.empty() or _values.empty():
10 | # Keys aren't empty, so we'll be updating this implicilty every time a call is made instead
11 | _keys = list.pop_front()
12 | _values = list
13 | return _update()
14 |
15 | func _update() -> bool:
16 | parameters.clear()
17 | var values = _values.pop_front()
18 | for i in _keys.size():
19 | parameters[_keys[i]] = values[i]
20 | return not _values.empty()
21 |
--------------------------------------------------------------------------------
/addons/WAT/test/recorder.gd:
--------------------------------------------------------------------------------
1 | extends Node
2 |
3 | var _recording: Object
4 | var _properties: Dictionary
5 | var _is_recording: bool = false
6 |
7 | func record(what: Object, properties: Array) -> void:
8 | _recording = what
9 | for property in properties:
10 | _properties[property] = []
11 |
12 | func start() -> void:
13 | _is_recording = true
14 |
15 | func stop() -> void:
16 | _is_recording = false
17 |
18 | func _process(delta: float) -> void:
19 | if _is_recording:
20 | _capture()
21 |
22 | func _capture() -> void:
23 | if not is_instance_valid(_recording):
24 | return
25 | for property in _properties:
26 | _properties[property].append(_recording.get(property))
27 |
28 | func get_property_timeline(property: String):
29 | return _properties[property]
30 |
31 | func get_property_map() -> Dictionary:
32 | return _properties
33 |
--------------------------------------------------------------------------------
/addons/WAT/test/watcher.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | var watching: Dictionary = {}
4 | var _objects: Array = []
5 |
6 | func watch(emitter, event: String) -> void:
7 | _objects.append(emitter)
8 | if emitter.is_connected(event, self, "_add_emit"):
9 | return
10 | emitter.set_meta("watcher", self)
11 | emitter.connect(event, self, "_add_emit", [emitter, event])
12 | watching[event] = {emit_count = 0, calls = []}
13 |
14 |
15 | func _add_emit(a = null, b = null, c = null, d = null, e = null, f = null, g = null, h = null, i = null, j = null, k = null):
16 | var arguments: Array = [a, b, c, d, e, f, g, h, i, j, k]
17 | var event
18 | while not event:
19 | event = arguments.pop_back()
20 | var obj = arguments.pop_back()
21 | watching[event].emit_count += 1
22 | watching[event].calls.append({emitter = obj, args = arguments})
23 |
24 | func unwatch(emitter, event: String) -> void:
25 | if emitter.is_connected(event, self, "_add_emit"):
26 | emitter.disconnect(event, self, "_add_emit")
27 | watching.erase(event)
28 | emitter.set_meta("watcher", null)
29 |
30 | func get_emit_count(event: String) -> int:
31 | return watching[event]["emit_count"]
32 |
33 | func get_data(event: String) -> Dictionary:
34 | return watching[event]
35 |
36 | func clear() -> void:
37 | for object in _objects:
38 | if is_instance_valid(object):
39 | object.set_meta("watcher", null)
40 |
41 | #func _notification(what):
42 | # if what == NOTIFICATION_PREDELETE:
43 | # clear()
44 |
--------------------------------------------------------------------------------
/addons/WAT/test/yielder.gd:
--------------------------------------------------------------------------------
1 | extends Timer
2 |
3 | signal finished
4 | var _emitter: Object
5 | var _event: String
6 |
7 | func _init() -> void:
8 | one_shot = true
9 | connect("timeout", self, "_on_resume", [], CONNECT_DEFERRED)
10 |
11 | func until_timeout(time: float) -> Timer:
12 | start(time)
13 | return self
14 |
15 | func until_signal(time: float, emitter: Object, event: String) -> Timer:
16 | _emitter = emitter
17 | _event = event
18 | _emitter.connect(event, self, "_on_resume", [], CONNECT_DEFERRED)
19 | start(time)
20 | return self
21 |
22 | func _on_resume(a = null, b = null, c = null, d = null, e = null, f = null) -> void:
23 | stop()
24 | if is_instance_valid(_emitter) and _emitter.is_connected(_event, self, "_on_resume"):
25 | _emitter.disconnect(_event, self, "_on_resume")
26 | # Our adapter is connected to this. When this is emitted our adapter
27 | # ..will call "_next" which call defers _change_state. Since it is a deferred
28 | # ..call the test will resume first. Therefore if a new yield gets constructed
29 | # ..in the interim we will be able to check if we have restarted the yield clock
30 | emit_signal("finished", [a, b, c, d, e, f])
31 |
32 | func is_active() -> bool:
33 | return not is_stopped() and time_left > 0
34 |
--------------------------------------------------------------------------------
/addons/WAT/ui/docker.gd:
--------------------------------------------------------------------------------
1 | extends Node
2 |
3 | const BOTTOM_PANEL: int = 8
4 | const displays: Dictionary = {
5 | 0: "Left.UL Dock", 1: "Left.BL Dock", 2: "Left.UR Dock",
6 | 3: "Left.BR Dock", 4: "Right.UL Dock", 5: "Right.BL Dock",
7 | 6: "Right.UR Dock", 7: "Right.BR Dock", 8: "Bottom Panel",
8 | }
9 |
10 | var _plugin: EditorPlugin
11 | var _scene: Control
12 | var _state: int
13 |
14 | func _init(plugin: EditorPlugin, scene: Control) -> void:
15 | _plugin = plugin
16 | _scene = scene
17 | add_setting()
18 | _state = ProjectSettings.get_setting("WAT/Display")
19 | construct()
20 |
21 | func _process(delta: float) -> void:
22 | var state = ProjectSettings.get_setting("WAT/Display")
23 | if state != _state:
24 | deconstruct()
25 | _state = state
26 | construct()
27 |
28 | func construct() -> void:
29 | if _state == BOTTOM_PANEL:
30 | _plugin.add_control_to_bottom_panel(_scene, "Tests")
31 | else:
32 | _plugin.add_control_to_dock(_state, _scene)
33 |
34 | func deconstruct() -> void:
35 | if _state == BOTTOM_PANEL and is_instance_valid(_scene):
36 | _plugin.remove_control_from_bottom_panel(_scene)
37 | elif is_instance_valid(_scene):
38 | _plugin.remove_control_from_docks(_scene)
39 |
40 | func _notification(what) -> void:
41 | if what == NOTIFICATION_PREDELETE:
42 | ProjectSettings.set_setting("WAT/Display", _state)
43 | ProjectSettings.save()
44 | deconstruct()
45 |
46 | func add_setting() -> void:
47 | if not ProjectSettings.has_setting("WAT/Display"):
48 | ProjectSettings.set_setting("WAT/Display", BOTTOM_PANEL)
49 | ProjectSettings.save()
50 | var property = {}
51 | property.name = "WAT/Display"
52 | property.type = TYPE_INT
53 | property.hint = PROPERTY_HINT_ENUM
54 | property.hint_string = PoolStringArray(displays.values()).join(",")
55 | ProjectSettings.add_property_info(property)
56 | ProjectSettings.save()
57 |
--------------------------------------------------------------------------------
/addons/WAT/ui/links.gd:
--------------------------------------------------------------------------------
1 | extends MenuButton
2 | tool
3 |
4 | func _ready() -> void:
5 | set_focus_mode(FOCUS_ALL)
6 | var p: PopupMenu = get_popup()
7 | p.set_item_metadata(0, "https://ko-fi.com/alexanddraw")
8 | p.set_item_metadata(1, "https://github.com/AlexDarigan/WAT/issues/new")
9 | p.connect("index_pressed", self, "_on_idx_pressed")
10 |
11 | func _on_idx_pressed(idx: int) -> void:
12 | OS.shell_open(get_popup().get_item_metadata(idx))
13 |
--------------------------------------------------------------------------------
/addons/WAT/ui/results/assertion.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | var component: TreeItem
4 | var context: String = ""
5 | var success: bool = false
6 |
7 | func _init(_component: TreeItem, data: Dictionary) -> void:
8 | component = _component
9 | context = data["context"]
10 | success = data["success"]
11 | if context != "":
12 | component.set_text(0, context)
13 |
--------------------------------------------------------------------------------
/addons/WAT/ui/results/counter.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 | # Counter TreeItem component for tests passed over total executed.
3 |
4 | signal counter_changed
5 |
6 | var component: TreeItem
7 | var path: String
8 | var title: String setget set_title
9 | var passed: int = 0 setget set_passed
10 | var total: int = 0 setget set_total
11 | var show: bool = true
12 |
13 | func _init(_component: TreeItem) -> void:
14 | component = _component
15 | connect("counter_changed", self, "display")
16 |
17 | func set_passed(_passed: int) -> void:
18 | passed = _passed
19 | emit_signal("counter_changed")
20 |
21 | func set_total(_total: int) -> void:
22 | total = _total
23 | emit_signal("counter_changed")
24 |
25 | func set_title(_title: String) -> void:
26 | title = _title
27 | component.set_text(0, _title)
28 |
29 | # Displays (total / passed) in the component text.
30 | func display() -> void:
31 | if show:
32 | component.set_text(0, "(%s/%s) %s" % [passed, total, title])
33 |
--------------------------------------------------------------------------------
/addons/WAT/ui/results/method.gd:
--------------------------------------------------------------------------------
1 | extends "res://addons/WAT/ui/results/counter.gd"
2 |
3 | const AssertionTreeItem: GDScript = preload("res://addons/WAT/ui/results/assertion.gd")
4 |
5 | var scriptpath: String
6 | var name: String
7 | var assertions: Array = []
8 |
9 | func _init(_component: TreeItem, _title: String, _script: String).(_component) -> void:
10 | scriptpath = _script
11 | path = _title
12 | name = _title # func name
13 | set_title(_title.replace("test_", "").replace("_", " "))
14 | show = false # Modify if test method results should display number of assertions passed.
15 |
16 | func add_assertion(tree: Tree, data: Dictionary):
17 | set_total(total + 1)
18 | if data["assertion"]["success"]:
19 | set_passed(passed + 1)
20 | if data["assertion"]["context"] == "":
21 | component.collapsed = true
22 | var expected: TreeItem = tree.create_item(component)
23 | var actual: TreeItem = tree.create_item(component)
24 | expected.set_text(0, "EXPECTED: %s" % data["assertion"]["expected"])
25 | actual.set_text(0, "RESULTED: %s" % data["assertion"]["actual"])
26 | else:
27 | var assertion: AssertionTreeItem = AssertionTreeItem.new(tree.create_item(component), data["assertion"])
28 | assertion.component.collapsed = true
29 | var expected: TreeItem = tree.create_item(assertion.component)
30 | var actual: TreeItem = tree.create_item(assertion.component)
31 | expected.set_text(0, "EXPECTED: %s" % data["assertion"]["expected"])
32 | actual.set_text(0, "RESULTED: %s" % data["assertion"]["actual"])
33 | assertion.component.set_custom_color(0, tree.PASSED if assertion.success else tree.FAILED)
34 | assertion.component.set_icon(0, tree.icons.passed if assertion.success else tree.icons.failed)
35 | tree.scroll_to_item(assertion.component)
36 | assertions.append(assertion)
37 | return assertion
38 |
--------------------------------------------------------------------------------
/addons/WAT/ui/results/script.gd:
--------------------------------------------------------------------------------
1 | extends "res://addons/WAT/ui/results/counter.gd"
2 |
3 | const MethodTreeItem: GDScript = preload("res://addons/WAT/ui/results/method.gd")
4 |
5 | var methods: Dictionary = {}
6 | var method_names: PoolStringArray
7 |
8 | func _init(_component: TreeItem, data: Dictionary).(_component) -> void:
9 | set_title(data["name"] if data["title"] == "" else data["title"])
10 | path = data["path"]
11 | method_names = data["methods"]
12 |
13 | func add_method(tree: Tree, data: Dictionary) -> void:
14 | var method = MethodTreeItem.new(tree.create_item(component), data["method"], path)
15 | methods[method.path] = method
16 | set_total(total + 1)
17 | tree.scroll_to_item(method.component)
18 |
19 | func on_method_finished(data: Dictionary) -> void:
20 | if data["success"]:
21 | set_passed(passed + 1)
22 |
--------------------------------------------------------------------------------
/addons/WAT/ui/results/tab.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | var tree: Tree
4 | var title: String
5 | var idx: int = 0
6 | var count: int = 0
7 | var passed: int = 0
8 | var _multiplier: int = 0
9 | var _expected_total: int = 0
10 | var success: bool = false
11 | var expected setget ,_get_expected
12 |
13 | func _init(_tree: Tree, _title: String, multiplier: int) -> void:
14 | tree = _tree
15 | title = _title
16 | _multiplier = multiplier + 1
17 |
18 | func increment_expected_total() -> void:
19 | # Multiplier tracks how many times we repeat tests
20 | # count should always be 1
21 | _expected_total += 1 * _multiplier
22 |
23 | func on_test_script_finished(successful: bool) -> void:
24 | if successful:
25 | passed += 1
26 | if count == _expected_total and passed == count:
27 | success = true
28 |
29 | func _get_expected() -> int:
30 | return _expected_total
31 |
--------------------------------------------------------------------------------
/addons/WAT/ui/scaling/dynamic_size_spinbox.gd:
--------------------------------------------------------------------------------
1 | extends SpinBox
2 | tool
3 |
4 | var oldText
5 |
6 | func _ready():
7 | get_line_edit().expand_to_text_length = true
8 | get_line_edit().connect("text_changed", self, "_on_text_edit_changed")
9 | get_line_edit().connect("focus_exited", self, "_on_focus_exited")
10 | connect("value_changed", self, "_on_value_changed")
11 | oldText = get_line_edit().text
12 |
13 | # Set's the text to itself in order to shoot an update to the line edit
14 | # This is needed or else the line edit starts off off-centered at startup
15 | get_line_edit().text = oldText
16 |
17 | func _on_focus_exited():
18 | # Disgusting frame waiting workaround because there is currently no way to
19 | # listen for when a spinbox is changed and the change is rejected.
20 | # (ie. inputting 20 in the spinbox when the spinbox already has a value of 20)
21 | yield(get_tree(),"idle_frame")
22 | yield(get_tree(),"idle_frame")
23 | set_size(get_minimum_size())
24 | pass
25 |
26 | func _on_value_changed(newValue):
27 | set_size(get_minimum_size())
28 |
29 | func _on_text_edit_changed(newText):
30 | # Using regex since you cannot reliably detect if a string is not an int
31 | # (ie. String(invalid text) = 0, when 0 might be a value we want)
32 | var regex = RegEx.new()
33 | regex.compile("^(0|[1-9][0-9]*)$")
34 |
35 | # Remove prefix and suffixes
36 | newText = newText.trim_prefix(prefix + " ").trim_suffix(" " + suffix)
37 |
38 | # Try and parse the inputted text in the middle
39 | var result = regex.search(newText)
40 | var invalidInput = false
41 |
42 | # If input is not an integer (excluding empty input), then revert the input back
43 | if not newText.empty() and not result:
44 | get_line_edit().text = oldText
45 | invalidInput = true
46 | # If input is out of bounds, bring it back to the nearest bound
47 | elif result:
48 | if int(result.get_string()) > max_value:
49 | get_line_edit().text = str(max_value)
50 | get_line_edit().caret_position = get_line_edit().text.length()
51 | invalidInput = true
52 | elif int(result.get_string()) < min_value:
53 | get_line_edit().text = str(min_value)
54 | get_line_edit().caret_position = get_line_edit().text.length()
55 | invalidInput = true
56 |
57 | if not invalidInput:
58 | oldText = prefix + " " + newText + " " + suffix
59 |
60 | set_size(get_minimum_size())
61 |
--------------------------------------------------------------------------------
/addons/WAT/ui/scaling/icons.gd:
--------------------------------------------------------------------------------
1 | extends Reference
2 |
3 | var debug_failed = preload("res://addons/WAT/assets/debug_failed.png")
4 | var docs = preload("res://addons/WAT/assets/docs.svg")
5 | var failed = preload("res://addons/WAT/assets/failed.png")
6 | var folder = preload("res://addons/WAT/assets/folder.png")
7 | var function = preload("res://addons/WAT/assets/function.png")
8 | var issue = preload("res://addons/WAT/assets/issue.svg")
9 | var kofi = preload("res://addons/WAT/assets/kofi.png")
10 | var label = preload("res://addons/WAT/assets/label.png")
11 | var passed = preload("res://addons/WAT/assets/passed.png")
12 | var play = preload("res://addons/WAT/assets/play.png")
13 | var play_debug = preload("res://addons/WAT/assets/play_debug.png")
14 | var play_failed = preload("res://addons/WAT/assets/play_failed.png")
15 | var request_docs = preload("res://addons/WAT/assets/request_docs.svg")
16 | var scriptx = preload("res://addons/WAT/assets/script.png")
17 | var timer = preload("res://addons/WAT/assets/timer.png")
18 |
--------------------------------------------------------------------------------
/addons/WAT/ui/scaling/scene_tree_adjuster.gd:
--------------------------------------------------------------------------------
1 | tool
2 | extends Reference
3 |
4 | const PluginAssetsRegistry: GDScript = preload("res://addons/WAT/ui/scaling/plugin_assets_registry.gd")
5 |
6 | static func adjust(runner: PanelContainer, icons: Reference, plugin = null) -> void:
7 | var registry: PluginAssetsRegistry = PluginAssetsRegistry.new(plugin)
8 |
9 | # Scale Icons
10 | icons.debug_failed = registry.load_asset("assets/debug_failed.png")
11 | icons.docs = registry.load_asset("assets/docs.svg")
12 | icons.failed = registry.load_asset("assets/failed.png")
13 | icons.folder = registry.load_asset("assets/folder.png")
14 | icons.function = registry.load_asset("assets/function.png")
15 | icons.issue = registry.load_asset("assets/issue.svg")
16 | icons.kofi = registry.load_asset("assets/kofi.png")
17 | icons.label = registry.load_asset("assets/label.png")
18 | icons.passed = registry.load_asset("assets/passed.png")
19 | icons.play = registry.load_asset("assets/play.png")
20 | icons.play_debug = registry.load_asset("assets/play_debug.png")
21 | icons.play_failed = registry.load_asset("assets/play_failed.png")
22 | icons.request_docs = registry.load_asset("assets/request_docs.svg")
23 | icons.scriptx = registry.load_asset("assets/script.png")
24 | icons.timer = registry.load_asset("assets/timer.png")
25 |
26 | # Scale Icons already in the editor
27 | runner.RunAll.icon = registry.load_asset(runner.RunAll.icon)
28 | runner.DebugAll.icon = registry.load_asset(runner.DebugAll.icon)
29 |
30 | # Scale summary icons
31 | runner.Summary.Time.icon = registry.load_asset(runner.Summary.Time.icon)
32 | runner.Summary.Tests.icon = registry.load_asset(runner.Summary.Tests.icon)
33 | runner.Summary.Passing.icon = registry.load_asset(runner.Summary.Passing.icon)
34 | runner.Summary.Failing.icon = registry.load_asset(runner.Summary.Failing.icon)
35 | runner.Summary.Runs.icon = registry.load_asset(runner.Summary.Runs.icon)
36 |
--------------------------------------------------------------------------------
/addons/WAT/ui/summary.gd:
--------------------------------------------------------------------------------
1 | extends HBoxContainer
2 | tool
3 |
4 | var time: float = 0
5 | var runcount: int = 0
6 | var running = false
7 | var time_taken: float = 0.0
8 |
9 | onready var Time: Button = $Time
10 | onready var Tests: Button = $Tests
11 | onready var Passing: Button = $Passing
12 | onready var Failing: Button = $Failing
13 | onready var Runs: Button = $Runs
14 |
15 | func _ready() -> void:
16 | for child in get_children():
17 | child.set_focus_mode(FOCUS_NONE)
18 |
19 | func time() -> void:
20 | time_taken = 0.0
21 | runcount += 1
22 | time = OS.get_ticks_msec()
23 | running = true
24 |
25 | func _process(delta):
26 | if running:
27 | Time.text = str((OS.get_ticks_msec() - time) / 1000)
28 |
29 | func summarize(caselist: Array) -> void:
30 | running = false
31 | time_taken = (OS.get_ticks_msec() - time) / 1000
32 | var passed = 0
33 | var failed = 0
34 | var total = 0
35 | for case in caselist:
36 | total += 1
37 | if case.success:
38 | passed += 1
39 | else:
40 | failed += 1
41 | Time.text = time_taken as String
42 | Tests.text = total as String
43 | Passing.text = passed as String
44 | Failing.text = failed as String
45 | Runs.text = runcount as String
46 |
47 | func _setup_editor_assets(assets_registry):
48 | Time.icon = assets_registry.load_asset(Time.icon)
49 | Tests.icon = assets_registry.load_asset(Tests.icon)
50 | Passing.icon = assets_registry.load_asset(Passing.icon)
51 | Failing.icon = assets_registry.load_asset(Failing.icon)
52 | Runs.icon = assets_registry.load_asset(Runs.icon)
53 |
--------------------------------------------------------------------------------
/bootsplash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/bootsplash.png
--------------------------------------------------------------------------------
/bootsplash.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/bootsplash.png-30e2c9990faa42442c2d12c3b0f7ed9a.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://bootsplash.png"
13 | dest_files=[ "res://.import/bootsplash.png-30e2c9990faa42442c2d12c3b0f7ed9a.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | stream=false
32 | size_limit=0
33 | detect_3d=true
34 | svg/scale=1.0
35 |
--------------------------------------------------------------------------------
/default_env.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Environment" load_steps=2 format=2]
2 |
3 | [sub_resource type="ProceduralSky" id=1]
4 |
5 | [resource]
6 | background_mode = 2
7 | background_sky = SubResource( 1 )
8 |
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fractural/GodotFixedVolatilePhysics/9a4daf5a28cb4893fa91e42734719f4504382598/icon.png
--------------------------------------------------------------------------------
/icon.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="StreamTexture"
5 | path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
6 | metadata={
7 | "vram_texture": false
8 | }
9 |
10 | [deps]
11 |
12 | source_file="res://icon.png"
13 | dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ]
14 |
15 | [params]
16 |
17 | compress/mode=0
18 | compress/lossy_quality=0.7
19 | compress/hdr_mode=0
20 | compress/bptc_ldr=0
21 | compress/normal_map=0
22 | flags/repeat=0
23 | flags/filter=true
24 | flags/mipmaps=false
25 | flags/anisotropic=false
26 | flags/srgb=2
27 | process/fix_alpha_border=true
28 | process/premult_alpha=false
29 | process/HDR_as_SRGB=false
30 | process/invert_color=false
31 | process/normal_map_invert_y=false
32 | stream=false
33 | size_limit=0
34 | detect_3d=true
35 | svg/scale=1.0
36 |
--------------------------------------------------------------------------------
/project.godot:
--------------------------------------------------------------------------------
1 | ; Engine configuration file.
2 | ; It's best edited using the editor UI and not directly,
3 | ; since the parameters that go here are not all obvious.
4 | ;
5 | ; Format:
6 | ; [section] ; section goes between []
7 | ; param=value ; assign values to parameters
8 |
9 | config_version=4
10 |
11 | _global_script_classes=[ {
12 | "base": "Control",
13 | "class": "VirtualJoystick",
14 | "language": "GDScript",
15 | "path": "res://addons/VirtualJoystick/virtual_joystick.gd"
16 | }, {
17 | "base": "Reference",
18 | "class": "WAT",
19 | "language": "GDScript",
20 | "path": "res://addons/WAT/namespace.gd"
21 | }, {
22 | "base": "Node",
23 | "class": "WATTest",
24 | "language": "GDScript",
25 | "path": "res://addons/WAT/test/test.gd"
26 | } ]
27 | _global_script_class_icons={
28 | "VirtualJoystick": "",
29 | "WAT": "",
30 | "WATTest": ""
31 | }
32 |
33 | [FracturalCommons]
34 |
35 | "Generate CSharp Scripts Table"=false
36 | "Generate Version Preprocessor Defines"=false
37 |
38 | [MonoCustomResourceRegistry]
39 |
40 | ClassPrefix=""
41 | SearchType=0
42 | ResourceScriptDirectories=[ "res://" ]
43 |
44 | [WAT]
45 |
46 | Test_Directory="res://tests"
47 | Results_Directory="res://tests"
48 | Test_Metadata_Directory="res://tests"
49 | Tags=PoolStringArray( )
50 | Window_Size=Vector2( 1280, 720 )
51 | Minimize_Window_When_Running_Tests=false
52 | Port=6008
53 | Display=8
54 | Cache_Tests=true
55 |
56 | [application]
57 |
58 | config/name="GodotFixedVolatilePhysics"
59 | run/main_scene="res://tests/Manual/Physics/CompleteTest.tscn"
60 | boot_splash/image="res://bootsplash.png"
61 | boot_splash/bg_color=Color( 0, 0, 0, 1 )
62 | config/icon="res://icon.png"
63 |
64 | [display]
65 |
66 | window/stretch/mode="viewport"
67 | window/stretch/aspect="expand"
68 |
69 | [editor_plugins]
70 |
71 | enabled=PoolStringArray( "res://addons/FracturalCommons/plugin.cfg", "res://addons/GodotFixedVolatilePhysics/plugin.cfg", "res://addons/WAT/plugin.cfg" )
72 |
73 | [input_devices]
74 |
75 | pointing/emulate_touch_from_mouse=true
76 |
77 | [logging]
78 |
79 | file_logging/enable_file_logging=true
80 | file_logging/max_log_files=10
81 |
82 | [mono]
83 |
84 | project/assembly_name="GodotFixedVolatilePhysics"
85 |
86 | [physics]
87 |
88 | common/physics_fps=20
89 | common/enable_pause_aware_picking=true
90 |
91 | [rendering]
92 |
93 | quality/driver/driver_name="GLES2"
94 | vram_compression/import_etc=true
95 | environment/default_environment="res://default_env.tres"
96 |
--------------------------------------------------------------------------------
/tests/Manual/Physics/FPSCounter.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 | using System;
3 |
4 | namespace Tests
5 | {
6 | public class FPSCounter : Label
7 | {
8 | public override void _Process(float delta)
9 | {
10 | Text = Engine.GetFramesPerSecond() + " FPS";
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/tests/Manual/Physics/GDKinematicMovement.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 | using System;
3 | using VirtualJoystickAddon;
4 | using Fractural.Utils;
5 |
6 | namespace Tests
7 | {
8 | public class GDKinematicMovement : KinematicBody2D
9 | {
10 | [Export]
11 | public float speed;
12 | [Export]
13 | private NodePath joystickPath;
14 | private VirtualJoystick joystick;
15 |
16 | public override void _Ready()
17 | {
18 | joystick = this.GetNodeAsWrapper(joystickPath);
19 | }
20 |
21 | public override void _PhysicsProcess(float delta)
22 | {
23 | if (joystick.Output != Vector2.Zero)
24 | MoveAndSlide(joystick.Output * speed);
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/tests/Manual/Physics/Prefabs/VolatileAreaTestPrefab.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=2]
2 |
3 | [ext_resource path="res://tests/Manual/VoltNode2D/VolatileAreaTest.cs" type="Script" id=1]
4 | [ext_resource path="res://addons/GodotFixedVolatilePhysics/Core/VolatileShapes/VolatileRect.cs" type="Script" id=2]
5 | [ext_resource path="res://icon.png" type="Texture" id=3]
6 |
7 | [node name="VolatileAreaTest" type="Node2D"]
8 | position = Vector2( -280.631, -220.769 )
9 | script = ExtResource( 1 )
10 | AutoQuery = true
11 | hasEntityInsideSpritePath = NodePath("Sprite")
12 | _fixedTransform = PoolByteArray( 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 112, 94, 231, 254, 255, 255, 0, 0, 11, 59, 35, 255, 255, 255 )
13 |
14 | [node name="VolatileRect" type="Node2D" parent="."]
15 | script = ExtResource( 2 )
16 | Editing = true
17 | DebugDraw = true
18 | _extents = PoolByteArray( 0, 0, 112, 252, 48, 0, 0, 0, 0, 0, 57, 89, 85, 0, 0, 0 )
19 | _fixedTransform = PoolByteArray( 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )
20 |
21 | [node name="Sprite" type="Sprite" parent="."]
22 | self_modulate = Color( 1, 1, 1, 0.223529 )
23 | scale = Vector2( 0.297486, 0.297486 )
24 | texture = ExtResource( 3 )
25 |
--------------------------------------------------------------------------------
/tests/Manual/Physics/Prefabs/VolatileKinematicMovementPrefab.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=2]
2 |
3 | [ext_resource path="res://tests/Manual/VoltNode2D/VolatileKinematicBodyMovement.cs" type="Script" id=1]
4 | [ext_resource path="res://addons/GodotFixedVolatilePhysics/Core/VolatileShapes/VolatileCircle.cs" type="Script" id=2]
5 | [ext_resource path="res://icon.png" type="Texture" id=3]
6 |
7 | [node name="VolatileKinematicBodyMovement" type="Node2D"]
8 | position = Vector2( 261.629, -50.7239 )
9 | script = ExtResource( 1 )
10 | _speed = PoolByteArray( 0, 0, 0, 0, 10, 0, 0, 0 )
11 | joystickPath = NodePath("")
12 | _fixedTransform = PoolByteArray( 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 234, 160, 5, 1, 0, 0, 0, 0, 172, 70, 205, 255, 255, 255 )
13 |
14 | [node name="VolatileCircle" type="Node2D" parent="."]
15 | script = ExtResource( 2 )
16 | Editing = true
17 | DebugDraw = true
18 | _radius = PoolByteArray( 0, 0, 168, 211, 23, 0, 0, 0 )
19 | _fixedTransform = PoolByteArray( 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )
20 |
21 | [node name="Sprite" type="Sprite" parent="."]
22 | scale = Vector2( 0.124448, 0.124448 )
23 | texture = ExtResource( 3 )
24 |
--------------------------------------------------------------------------------
/tests/Manual/VoltNode2D/FixedMovement.cs:
--------------------------------------------------------------------------------
1 | using FixMath.NET;
2 | using Godot;
3 | using Volatile;
4 | using Volatile.GodotEngine;
5 |
6 | namespace Tests
7 | {
8 | [Tool]
9 | public class FixedMovement : VoltNode2D
10 | {
11 | private Fix64 speed;
12 | public Fix64 Speed
13 | {
14 | get
15 | {
16 |
17 | #if TOOLS
18 | if (Engine.EditorHint)
19 | return VoltType.DeserializeOrDefault(_speed);
20 | else
21 | #endif
22 | return speed;
23 | }
24 | set
25 | {
26 | #if TOOLS
27 | if (Engine.EditorHint)
28 | _speed = VoltType.Serialize(value);
29 | else
30 | #endif
31 | speed = value;
32 | }
33 | }
34 | [Export(hintString: VoltPropertyHint.Fix64)]
35 | private byte[] _speed;
36 |
37 | public override void _Ready()
38 | {
39 | base._Ready();
40 | speed = VoltType.DeserializeOrDefault(_speed);
41 | }
42 |
43 | public static readonly Fix64 FIX_0_0001 = Fix64.From("0.0001");
44 |
45 | public override void _PhysicsProcess(float delta)
46 | {
47 | var movementInput = Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down").ToVoltVector2();
48 | if (movementInput != VoltVector2.Zero)
49 | FixedPosition += movementInput * speed;
50 | var rotation = Input.GetAxis("ui_left", "ui_right");
51 | if (rotation != 0)
52 | FixedRotation += (Fix64)rotation * speed * Fix64.Deg2Rad;
53 | var scale = Input.GetAxis("ui_up", "ui_down");
54 | if (scale != 0)
55 | FixedScale += VoltVector2.One * (Fix64)scale * speed * FIX_0_0001;
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/tests/Manual/VoltNode2D/VolatileAreaTest.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 | using Volatile.GodotEngine;
3 |
4 | namespace Tests
5 | {
6 | [Tool]
7 | public class VolatileAreaTest : VolatileArea
8 | {
9 | [Export]
10 | private NodePath hasEntityInsideSpritePath;
11 | private Sprite hasEntityInsideSprite;
12 |
13 | public override void _Ready()
14 | {
15 | base._Ready();
16 | if (Engine.EditorHint) return;
17 | hasEntityInsideSprite = GetNode(hasEntityInsideSpritePath);
18 | }
19 |
20 | protected override void OnBodyEntered(IVolatileBody body)
21 | {
22 | base.OnBodyEntered(body);
23 | OnBodyCollidingWithChanged();
24 | }
25 |
26 | protected override void OnBodyExited(IVolatileBody body)
27 | {
28 | base.OnBodyExited(body);
29 | OnBodyCollidingWithChanged();
30 | }
31 |
32 | private void OnBodyCollidingWithChanged()
33 | {
34 | hasEntityInsideSprite.Visible = CurrCollidingWith.Count > 0;
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/tests/Manual/VoltNode2D/VolatileKinematicBodyMovement.cs:
--------------------------------------------------------------------------------
1 | using FixMath.NET;
2 | using Fractural.Utils;
3 | using Godot;
4 | using VirtualJoystickAddon;
5 | using Volatile;
6 | using Volatile.GodotEngine;
7 |
8 | namespace Tests
9 | {
10 | [Tool]
11 | public class VolatileKinematicBodyMovement : VolatileKinematicBody
12 | {
13 | private Fix64 speed;
14 | public Fix64 Speed
15 | {
16 | get
17 | {
18 |
19 | #if TOOLS
20 | if (Engine.EditorHint)
21 | return VoltType.DeserializeOrDefault(_speed);
22 | else
23 | #endif
24 | return speed;
25 | }
26 | set
27 | {
28 | #if TOOLS
29 | if (Engine.EditorHint)
30 | _speed = VoltType.Serialize(value);
31 | else
32 | #endif
33 | speed = value;
34 | }
35 | }
36 | [Export(hintString: VoltPropertyHint.Fix64)]
37 | private byte[] _speed;
38 |
39 | [Export]
40 | private NodePath joystickPath;
41 | private VirtualJoystick joystick;
42 |
43 | public override void _Ready()
44 | {
45 | base._Ready();
46 | if (Engine.EditorHint) return;
47 | speed = VoltType.DeserializeOrDefault(_speed);
48 | joystick = this.GetNodeAsWrapper(joystickPath);
49 | }
50 |
51 | public override void _PhysicsProcess(float delta)
52 | {
53 | base._PhysicsProcess(delta);
54 | if (Engine.EditorHint) return;
55 | if (joystick.Output != Vector2.Zero)
56 | MoveAndSlide(joystick.Output.ToVoltVector2() * speed);
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/tests/Manual/VoltNode2D/VoltNode2DTest.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=2]
2 |
3 | [ext_resource path="res://icon.png" type="Texture" id=1]
4 | [ext_resource path="res://tests/Manual/VoltNode2D/FixedMovement.cs" type="Script" id=2]
5 | [ext_resource path="res://addons/GodotFixedVolatilePhysics/Core/Test.cs" type="Script" id=3]
6 |
7 | [node name="VoltNode2DTest" type="Node2D"]
8 |
9 | [node name="Test" type="Node2D" parent="."]
10 | position = Vector2( 46.6128, 100.26 )
11 | script = ExtResource( 3 )
12 | fixed64Array = PoolByteArray( 4, 0, 0, 0, 8, 0, 0, 0, 0, 10, 0, 0, 0, 8, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 0, 223, 187, 11, 2 )
13 | fixedVectorArray = PoolByteArray( 3, 0, 0, 0, 16, 50, 114, 22, 110, 47, 1, 0, 0, 239, 56, 69, 87, 230, 0, 0, 0, 16, 127, 159, 113, 89, 40, 0, 0, 0, 139, 108, 231, 59, 132, 36, 0, 0, 16, 9, 104, 34, 60, 9, 0, 0, 0, 200, 36, 35, 87, 24, 0, 0, 0 )
14 | voltRectArray = PoolByteArray( 2, 0, 0, 0, 32, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 61, 10, 215, 99, 92, 0, 0, 0, 0, 0, 0, 0, 45, 9, 0, 0, 0, 0, 0, 0, 243, 16, 0, 0, 0, 0, 0, 0, 195, 207, 255, 255 )
15 | voltRect = PoolByteArray( 160, 240, 35, 60, 29, 0, 0, 0, 204, 204, 204, 76, 214, 3, 0, 0, 0, 0, 0, 64, 166, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )
16 | tests = "asdfasdf"
17 |
18 | [node name="FixedMovement" type="Node2D" parent="."]
19 | position = Vector2( 154.101, -25.905 )
20 | rotation = 0.226891
21 | script = ExtResource( 2 )
22 | _speed = PoolByteArray( 0, 0, 0, 0, 1, 0, 0, 0 )
23 | _fixedTransform = PoolByteArray( 0, 90, 112, 249, 0, 0, 0, 0, 128, 63, 150, 57, 0, 0, 0, 0, 128, 192, 105, 198, 255, 255, 255, 255, 0, 90, 112, 249, 0, 0, 0, 0, 0, 0, 212, 25, 154, 0, 0, 0, 0, 128, 81, 24, 230, 255, 255, 255 )
24 |
25 | [node name="Sprite" type="Sprite" parent="FixedMovement"]
26 | texture = ExtResource( 1 )
27 |
28 | [node name="Camera2D" type="Camera2D" parent="FixedMovement"]
29 | current = true
30 | zoom = Vector2( 5, 5 )
31 |
32 | [node name="Sprite2" type="Sprite" parent="."]
33 | self_modulate = Color( 1, 1, 1, 0.329412 )
34 | position = Vector2( -103.881, 54.7806 )
35 | texture = ExtResource( 1 )
36 |
--------------------------------------------------------------------------------