Copy disabled (too large)
Download .txt
Showing preview only (11,727K chars total). Download the full file to get everything.
Repository: SimulaVR/godot-haskell
Branch: master
Commit: cabc06451292
Files: 788
Total size: 11.0 MB
Directory structure:
gitextract_kt3cl1ny/
├── .gitignore
├── .gitmodules
├── .hlint.yaml
├── .travis.yml
├── .vscode/
│ └── tasks.json
├── LICENSE
├── README.md
├── Setup.hs
├── cbits/
│ └── util.h
├── classgen/
│ ├── README.md
│ ├── app-classgen/
│ │ └── Main.hs
│ ├── default.nix
│ ├── godot-haskell-classgen.cabal
│ ├── package.yaml
│ ├── release.nix
│ ├── src-classgen/
│ │ └── Classgen/
│ │ ├── Docs.hs
│ │ ├── Module.hs
│ │ ├── Spec.hs
│ │ └── Utils.hs
│ └── stack.yaml
├── default.nix
├── examples/
│ ├── dodge-the-creeps/
│ │ ├── .gitignore
│ │ ├── ChangeLog.md
│ │ ├── LICENSE
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── Support.hs
│ │ ├── ffi/
│ │ │ ├── cbits/
│ │ │ │ └── flib.c
│ │ │ └── flib/
│ │ │ └── FLib.hs
│ │ ├── game/
│ │ │ ├── HUD.gdns
│ │ │ ├── HUD.tres
│ │ │ ├── HUD.tscn
│ │ │ ├── Main.gdns
│ │ │ ├── Main.tscn
│ │ │ ├── Mob.gdns
│ │ │ ├── Mob.tscn
│ │ │ ├── Player.gdns
│ │ │ ├── Player.tscn
│ │ │ ├── dodge_assets/
│ │ │ │ ├── art/
│ │ │ │ │ └── House In a Forest Loop.ogg
│ │ │ │ └── fonts/
│ │ │ │ ├── FONTLOG.txt
│ │ │ │ └── LICENSE.txt
│ │ │ ├── lib/
│ │ │ │ └── libmyproject.gdnlib
│ │ │ └── project.godot
│ │ ├── godot-haskell.nix
│ │ ├── hie.yaml
│ │ ├── myproject.cabal
│ │ ├── package.yaml
│ │ ├── pinned-nixpkgs.nix
│ │ ├── shell.nix
│ │ ├── src/
│ │ │ ├── Game/
│ │ │ │ ├── HUD.hs
│ │ │ │ ├── Main.hs
│ │ │ │ ├── Mob.hs
│ │ │ │ └── Player.hs
│ │ │ ├── Lib.hs
│ │ │ └── Project/
│ │ │ ├── Requirements.hs
│ │ │ ├── Scenes/
│ │ │ │ ├── HUD.hs
│ │ │ │ ├── Main.hs
│ │ │ │ ├── Mob.hs
│ │ │ │ └── Player.hs
│ │ │ ├── Scenes.hs
│ │ │ └── Support.hs
│ │ ├── stack-shell.nix
│ │ └── stack.yaml
│ ├── rss-reader/
│ │ ├── .gitignore
│ │ ├── ChangeLog.md
│ │ ├── LICENSE
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── Support.hs
│ │ ├── ffi/
│ │ │ ├── cbits/
│ │ │ │ └── flib.c
│ │ │ └── flib/
│ │ │ └── FLib.hs
│ │ ├── game/
│ │ │ ├── Rss_reader.gdns
│ │ │ ├── Rss_reader.tscn
│ │ │ ├── export_presets.cfg
│ │ │ ├── lib/
│ │ │ │ └── libmyproject.gdnlib
│ │ │ └── project.godot
│ │ ├── godot-haskell.nix
│ │ ├── hie.yaml
│ │ ├── myproject.cabal
│ │ ├── package.yaml
│ │ ├── pinned-nixpkgs.nix
│ │ ├── shell.nix
│ │ ├── src/
│ │ │ ├── Game/
│ │ │ │ ├── RSSReader.hs
│ │ │ │ └── q
│ │ │ ├── Lib.hs
│ │ │ └── Project/
│ │ │ ├── Requirements.hs
│ │ │ ├── Scenes/
│ │ │ │ └── Rss_reader.hs
│ │ │ ├── Scenes.hs
│ │ │ └── Support.hs
│ │ ├── stack-shell.nix
│ │ └── stack.yaml
│ └── top-down-ten-minutes/
│ ├── .gitignore
│ ├── ChangeLog.md
│ ├── LICENSE
│ ├── Makefile
│ ├── README.md
│ ├── ffi/
│ │ ├── cbits/
│ │ │ └── flib.c
│ │ └── flib/
│ │ └── FLib.hs
│ ├── game/
│ │ ├── Bullet.gdns
│ │ ├── Bullet.tscn
│ │ ├── Enemy.gdns
│ │ ├── Enemy.tscn
│ │ ├── Explosion.tscn
│ │ ├── Player.gdns
│ │ ├── lib/
│ │ │ └── libtop-down-ten-minutes.gdnlib
│ │ ├── project.godot
│ │ ├── wall.tres
│ │ └── world.tscn
│ ├── godot-haskell.nix
│ ├── hie.yaml
│ ├── package.yaml
│ ├── pinned-nixpkgs.nix
│ ├── shell.nix
│ ├── src/
│ │ ├── Game/
│ │ │ └── World.hs
│ │ ├── Lib.hs
│ │ └── Project/
│ │ ├── Requirements.hs
│ │ ├── Scenes/
│ │ │ ├── Bullet.hs
│ │ │ ├── Enemy.hs
│ │ │ ├── Explosion.hs
│ │ │ └── World.hs
│ │ ├── Scenes.hs
│ │ └── Support.hs
│ ├── stack-shell.nix
│ ├── stack.yaml
│ └── top-down-ten-minutes.cabal
├── godot-haskell.cabal
├── hie.yaml
├── nix/
│ ├── pinned/
│ │ ├── all-hies.json
│ │ ├── default.nix
│ │ ├── hie.nix
│ │ └── nixpkgs.json
│ └── spacemacs-hie.nix
├── nixpkgs-version.json
├── package.yaml
├── pinned-nixpkgs.nix
├── project-generator/
│ └── Main.hs
├── release.nix
├── shell-spacemacs-hie.nix
├── shell.nix
├── src/
│ ├── Godot/
│ │ ├── Api/
│ │ │ └── Types.hs
│ │ ├── Api.hs
│ │ ├── Core/
│ │ │ ├── ARVRAnchor.hs
│ │ │ ├── ARVRCamera.hs
│ │ │ ├── ARVRController.hs
│ │ │ ├── ARVRInterface.hs
│ │ │ ├── ARVRInterfaceGDNative.hs
│ │ │ ├── ARVROrigin.hs
│ │ │ ├── ARVRPositionalTracker.hs
│ │ │ ├── ARVRServer.hs
│ │ │ ├── AStar.hs
│ │ │ ├── AStar2D.hs
│ │ │ ├── AcceptDialog.hs
│ │ │ ├── AnimatedSprite.hs
│ │ │ ├── AnimatedSprite3D.hs
│ │ │ ├── AnimatedTexture.hs
│ │ │ ├── Animation.hs
│ │ │ ├── AnimationNode.hs
│ │ │ ├── AnimationNodeAdd2.hs
│ │ │ ├── AnimationNodeAdd3.hs
│ │ │ ├── AnimationNodeAnimation.hs
│ │ │ ├── AnimationNodeBlend2.hs
│ │ │ ├── AnimationNodeBlend3.hs
│ │ │ ├── AnimationNodeBlendSpace1D.hs
│ │ │ ├── AnimationNodeBlendSpace2D.hs
│ │ │ ├── AnimationNodeBlendTree.hs
│ │ │ ├── AnimationNodeOneShot.hs
│ │ │ ├── AnimationNodeOutput.hs
│ │ │ ├── AnimationNodeStateMachine.hs
│ │ │ ├── AnimationNodeStateMachinePlayback.hs
│ │ │ ├── AnimationNodeStateMachineTransition.hs
│ │ │ ├── AnimationNodeTimeScale.hs
│ │ │ ├── AnimationNodeTimeSeek.hs
│ │ │ ├── AnimationNodeTransition.hs
│ │ │ ├── AnimationPlayer.hs
│ │ │ ├── AnimationRootNode.hs
│ │ │ ├── AnimationTree.hs
│ │ │ ├── AnimationTreePlayer.hs
│ │ │ ├── Area.hs
│ │ │ ├── Area2D.hs
│ │ │ ├── ArrayMesh.hs
│ │ │ ├── AtlasTexture.hs
│ │ │ ├── AudioBusLayout.hs
│ │ │ ├── AudioEffect.hs
│ │ │ ├── AudioEffectAmplify.hs
│ │ │ ├── AudioEffectBandLimitFilter.hs
│ │ │ ├── AudioEffectBandPassFilter.hs
│ │ │ ├── AudioEffectChorus.hs
│ │ │ ├── AudioEffectCompressor.hs
│ │ │ ├── AudioEffectDelay.hs
│ │ │ ├── AudioEffectDistortion.hs
│ │ │ ├── AudioEffectEQ.hs
│ │ │ ├── AudioEffectEQ10.hs
│ │ │ ├── AudioEffectEQ21.hs
│ │ │ ├── AudioEffectEQ6.hs
│ │ │ ├── AudioEffectFilter.hs
│ │ │ ├── AudioEffectHighPassFilter.hs
│ │ │ ├── AudioEffectHighShelfFilter.hs
│ │ │ ├── AudioEffectInstance.hs
│ │ │ ├── AudioEffectLimiter.hs
│ │ │ ├── AudioEffectLowPassFilter.hs
│ │ │ ├── AudioEffectLowShelfFilter.hs
│ │ │ ├── AudioEffectNotchFilter.hs
│ │ │ ├── AudioEffectPanner.hs
│ │ │ ├── AudioEffectPhaser.hs
│ │ │ ├── AudioEffectPitchShift.hs
│ │ │ ├── AudioEffectRecord.hs
│ │ │ ├── AudioEffectReverb.hs
│ │ │ ├── AudioEffectSpectrumAnalyzer.hs
│ │ │ ├── AudioEffectSpectrumAnalyzerInstance.hs
│ │ │ ├── AudioEffectStereoEnhance.hs
│ │ │ ├── AudioServer.hs
│ │ │ ├── AudioStream.hs
│ │ │ ├── AudioStreamGenerator.hs
│ │ │ ├── AudioStreamGeneratorPlayback.hs
│ │ │ ├── AudioStreamMicrophone.hs
│ │ │ ├── AudioStreamOGGVorbis.hs
│ │ │ ├── AudioStreamPlayback.hs
│ │ │ ├── AudioStreamPlaybackResampled.hs
│ │ │ ├── AudioStreamPlayer.hs
│ │ │ ├── AudioStreamPlayer2D.hs
│ │ │ ├── AudioStreamPlayer3D.hs
│ │ │ ├── AudioStreamRandomPitch.hs
│ │ │ ├── AudioStreamSample.hs
│ │ │ ├── BackBufferCopy.hs
│ │ │ ├── BakedLightmap.hs
│ │ │ ├── BakedLightmapData.hs
│ │ │ ├── BaseButton.hs
│ │ │ ├── BitMap.hs
│ │ │ ├── BitmapFont.hs
│ │ │ ├── Bone2D.hs
│ │ │ ├── BoneAttachment.hs
│ │ │ ├── BoxContainer.hs
│ │ │ ├── BoxShape.hs
│ │ │ ├── BulletPhysicsDirectBodyState.hs
│ │ │ ├── BulletPhysicsServer.hs
│ │ │ ├── Button.hs
│ │ │ ├── ButtonGroup.hs
│ │ │ ├── CPUParticles.hs
│ │ │ ├── CPUParticles2D.hs
│ │ │ ├── CSGBox.hs
│ │ │ ├── CSGCombiner.hs
│ │ │ ├── CSGCylinder.hs
│ │ │ ├── CSGMesh.hs
│ │ │ ├── CSGPolygon.hs
│ │ │ ├── CSGPrimitive.hs
│ │ │ ├── CSGShape.hs
│ │ │ ├── CSGSphere.hs
│ │ │ ├── CSGTorus.hs
│ │ │ ├── Camera.hs
│ │ │ ├── Camera2D.hs
│ │ │ ├── CameraFeed.hs
│ │ │ ├── CameraServer.hs
│ │ │ ├── CameraTexture.hs
│ │ │ ├── CanvasItem.hs
│ │ │ ├── CanvasItemMaterial.hs
│ │ │ ├── CanvasLayer.hs
│ │ │ ├── CanvasModulate.hs
│ │ │ ├── CapsuleMesh.hs
│ │ │ ├── CapsuleShape.hs
│ │ │ ├── CapsuleShape2D.hs
│ │ │ ├── CenterContainer.hs
│ │ │ ├── CharFXTransform.hs
│ │ │ ├── CheckBox.hs
│ │ │ ├── CheckButton.hs
│ │ │ ├── CircleShape2D.hs
│ │ │ ├── ClassDB.hs
│ │ │ ├── ClippedCamera.hs
│ │ │ ├── CollisionObject.hs
│ │ │ ├── CollisionObject2D.hs
│ │ │ ├── CollisionPolygon.hs
│ │ │ ├── CollisionPolygon2D.hs
│ │ │ ├── CollisionShape.hs
│ │ │ ├── CollisionShape2D.hs
│ │ │ ├── ColorPicker.hs
│ │ │ ├── ColorPickerButton.hs
│ │ │ ├── ColorRect.hs
│ │ │ ├── ConcavePolygonShape.hs
│ │ │ ├── ConcavePolygonShape2D.hs
│ │ │ ├── ConeTwistJoint.hs
│ │ │ ├── ConfigFile.hs
│ │ │ ├── ConfirmationDialog.hs
│ │ │ ├── Container.hs
│ │ │ ├── Control.hs
│ │ │ ├── ConvexPolygonShape.hs
│ │ │ ├── ConvexPolygonShape2D.hs
│ │ │ ├── Crypto.hs
│ │ │ ├── CryptoKey.hs
│ │ │ ├── CubeMap.hs
│ │ │ ├── CubeMesh.hs
│ │ │ ├── Curve.hs
│ │ │ ├── Curve2D.hs
│ │ │ ├── Curve3D.hs
│ │ │ ├── CurveTexture.hs
│ │ │ ├── CylinderMesh.hs
│ │ │ ├── CylinderShape.hs
│ │ │ ├── DampedSpringJoint2D.hs
│ │ │ ├── DirectionalLight.hs
│ │ │ ├── Directory.hs
│ │ │ ├── DynamicFont.hs
│ │ │ ├── DynamicFontData.hs
│ │ │ ├── EncodedObjectAsID.hs
│ │ │ ├── Engine.hs
│ │ │ ├── Environment.hs
│ │ │ ├── Expression.hs
│ │ │ ├── File.hs
│ │ │ ├── FileDialog.hs
│ │ │ ├── Font.hs
│ │ │ ├── FuncRef.hs
│ │ │ ├── GDNative.hs
│ │ │ ├── GDNativeLibrary.hs
│ │ │ ├── GDScript.hs
│ │ │ ├── GDScriptFunctionState.hs
│ │ │ ├── GIProbe.hs
│ │ │ ├── GIProbeData.hs
│ │ │ ├── Generic6DOFJoint.hs
│ │ │ ├── Geometry.hs
│ │ │ ├── GeometryInstance.hs
│ │ │ ├── GlobalConstants.hs
│ │ │ ├── Gradient.hs
│ │ │ ├── GradientTexture.hs
│ │ │ ├── GraphEdit.hs
│ │ │ ├── GraphNode.hs
│ │ │ ├── GridContainer.hs
│ │ │ ├── GridMap.hs
│ │ │ ├── GrooveJoint2D.hs
│ │ │ ├── HBoxContainer.hs
│ │ │ ├── HScrollBar.hs
│ │ │ ├── HSeparator.hs
│ │ │ ├── HSlider.hs
│ │ │ ├── HSplitContainer.hs
│ │ │ ├── HTTPClient.hs
│ │ │ ├── HTTPRequest.hs
│ │ │ ├── HashingContext.hs
│ │ │ ├── HeightMapShape.hs
│ │ │ ├── HingeJoint.hs
│ │ │ ├── IP.hs
│ │ │ ├── IP_Unix.hs
│ │ │ ├── Image.hs
│ │ │ ├── ImageTexture.hs
│ │ │ ├── ImmediateGeometry.hs
│ │ │ ├── Input.hs
│ │ │ ├── InputDefault.hs
│ │ │ ├── InputEvent.hs
│ │ │ ├── InputEventAction.hs
│ │ │ ├── InputEventGesture.hs
│ │ │ ├── InputEventJoypadButton.hs
│ │ │ ├── InputEventJoypadMotion.hs
│ │ │ ├── InputEventKey.hs
│ │ │ ├── InputEventMIDI.hs
│ │ │ ├── InputEventMagnifyGesture.hs
│ │ │ ├── InputEventMouse.hs
│ │ │ ├── InputEventMouseButton.hs
│ │ │ ├── InputEventMouseMotion.hs
│ │ │ ├── InputEventPanGesture.hs
│ │ │ ├── InputEventScreenDrag.hs
│ │ │ ├── InputEventScreenTouch.hs
│ │ │ ├── InputEventWithModifiers.hs
│ │ │ ├── InputMap.hs
│ │ │ ├── InstancePlaceholder.hs
│ │ │ ├── InterpolatedCamera.hs
│ │ │ ├── ItemList.hs
│ │ │ ├── JSON.hs
│ │ │ ├── JSONParseResult.hs
│ │ │ ├── JSONRPC.hs
│ │ │ ├── JavaClass.hs
│ │ │ ├── JavaClassWrapper.hs
│ │ │ ├── JavaScript.hs
│ │ │ ├── Joint.hs
│ │ │ ├── Joint2D.hs
│ │ │ ├── KinematicBody.hs
│ │ │ ├── KinematicBody2D.hs
│ │ │ ├── KinematicCollision.hs
│ │ │ ├── KinematicCollision2D.hs
│ │ │ ├── Label.hs
│ │ │ ├── LargeTexture.hs
│ │ │ ├── Light.hs
│ │ │ ├── Light2D.hs
│ │ │ ├── LightOccluder2D.hs
│ │ │ ├── Line2D.hs
│ │ │ ├── LineEdit.hs
│ │ │ ├── LineShape2D.hs
│ │ │ ├── LinkButton.hs
│ │ │ ├── Listener.hs
│ │ │ ├── MainLoop.hs
│ │ │ ├── MarginContainer.hs
│ │ │ ├── Marshalls.hs
│ │ │ ├── Material.hs
│ │ │ ├── MenuButton.hs
│ │ │ ├── Mesh.hs
│ │ │ ├── MeshDataTool.hs
│ │ │ ├── MeshInstance.hs
│ │ │ ├── MeshInstance2D.hs
│ │ │ ├── MeshLibrary.hs
│ │ │ ├── MeshTexture.hs
│ │ │ ├── MobileVRInterface.hs
│ │ │ ├── MultiMesh.hs
│ │ │ ├── MultiMeshInstance.hs
│ │ │ ├── MultiMeshInstance2D.hs
│ │ │ ├── MultiplayerAPI.hs
│ │ │ ├── MultiplayerPeerGDNative.hs
│ │ │ ├── Mutex.hs
│ │ │ ├── NativeScript.hs
│ │ │ ├── Navigation.hs
│ │ │ ├── Navigation2D.hs
│ │ │ ├── NavigationMesh.hs
│ │ │ ├── NavigationMeshInstance.hs
│ │ │ ├── NavigationPolygon.hs
│ │ │ ├── NavigationPolygonInstance.hs
│ │ │ ├── NetworkedMultiplayerENet.hs
│ │ │ ├── NetworkedMultiplayerPeer.hs
│ │ │ ├── NinePatchRect.hs
│ │ │ ├── Node.hs
│ │ │ ├── Node2D.hs
│ │ │ ├── NoiseTexture.hs
│ │ │ ├── OS.hs
│ │ │ ├── Object.hs
│ │ │ ├── OccluderPolygon2D.hs
│ │ │ ├── OmniLight.hs
│ │ │ ├── OpenSimplexNoise.hs
│ │ │ ├── OptionButton.hs
│ │ │ ├── PCKPacker.hs
│ │ │ ├── PHashTranslation.hs
│ │ │ ├── PackedDataContainer.hs
│ │ │ ├── PackedDataContainerRef.hs
│ │ │ ├── PackedScene.hs
│ │ │ ├── PacketPeer.hs
│ │ │ ├── PacketPeerGDNative.hs
│ │ │ ├── PacketPeerStream.hs
│ │ │ ├── PacketPeerUDP.hs
│ │ │ ├── Panel.hs
│ │ │ ├── PanelContainer.hs
│ │ │ ├── PanoramaSky.hs
│ │ │ ├── ParallaxBackground.hs
│ │ │ ├── ParallaxLayer.hs
│ │ │ ├── Particles.hs
│ │ │ ├── Particles2D.hs
│ │ │ ├── ParticlesMaterial.hs
│ │ │ ├── Path.hs
│ │ │ ├── Path2D.hs
│ │ │ ├── PathFollow.hs
│ │ │ ├── PathFollow2D.hs
│ │ │ ├── Performance.hs
│ │ │ ├── PhysicalBone.hs
│ │ │ ├── Physics2DDirectBodyState.hs
│ │ │ ├── Physics2DDirectBodyStateSW.hs
│ │ │ ├── Physics2DDirectSpaceState.hs
│ │ │ ├── Physics2DServer.hs
│ │ │ ├── Physics2DServerSW.hs
│ │ │ ├── Physics2DShapeQueryParameters.hs
│ │ │ ├── Physics2DShapeQueryResult.hs
│ │ │ ├── Physics2DTestMotionResult.hs
│ │ │ ├── PhysicsBody.hs
│ │ │ ├── PhysicsBody2D.hs
│ │ │ ├── PhysicsDirectBodyState.hs
│ │ │ ├── PhysicsDirectSpaceState.hs
│ │ │ ├── PhysicsMaterial.hs
│ │ │ ├── PhysicsServer.hs
│ │ │ ├── PhysicsShapeQueryParameters.hs
│ │ │ ├── PhysicsShapeQueryResult.hs
│ │ │ ├── PinJoint.hs
│ │ │ ├── PinJoint2D.hs
│ │ │ ├── PlaneMesh.hs
│ │ │ ├── PlaneShape.hs
│ │ │ ├── PluginScript.hs
│ │ │ ├── PointMesh.hs
│ │ │ ├── Polygon2D.hs
│ │ │ ├── PolygonPathFinder.hs
│ │ │ ├── Popup.hs
│ │ │ ├── PopupDialog.hs
│ │ │ ├── PopupMenu.hs
│ │ │ ├── PopupPanel.hs
│ │ │ ├── Position2D.hs
│ │ │ ├── Position3D.hs
│ │ │ ├── PrimitiveMesh.hs
│ │ │ ├── PrismMesh.hs
│ │ │ ├── ProceduralSky.hs
│ │ │ ├── ProgressBar.hs
│ │ │ ├── ProjectSettings.hs
│ │ │ ├── ProximityGroup.hs
│ │ │ ├── ProxyTexture.hs
│ │ │ ├── QuadMesh.hs
│ │ │ ├── RandomNumberGenerator.hs
│ │ │ ├── Range.hs
│ │ │ ├── RayCast.hs
│ │ │ ├── RayCast2D.hs
│ │ │ ├── RayShape.hs
│ │ │ ├── RayShape2D.hs
│ │ │ ├── RectangleShape2D.hs
│ │ │ ├── Reference.hs
│ │ │ ├── ReferenceRect.hs
│ │ │ ├── ReflectionProbe.hs
│ │ │ ├── RegEx.hs
│ │ │ ├── RegExMatch.hs
│ │ │ ├── RemoteTransform.hs
│ │ │ ├── RemoteTransform2D.hs
│ │ │ ├── Resource.hs
│ │ │ ├── ResourceFormatLoader.hs
│ │ │ ├── ResourceFormatLoaderCrypto.hs
│ │ │ ├── ResourceFormatSaver.hs
│ │ │ ├── ResourceFormatSaverCrypto.hs
│ │ │ ├── ResourceImporter.hs
│ │ │ ├── ResourceInteractiveLoader.hs
│ │ │ ├── ResourceLoader.hs
│ │ │ ├── ResourcePreloader.hs
│ │ │ ├── ResourceSaver.hs
│ │ │ ├── RichTextEffect.hs
│ │ │ ├── RichTextLabel.hs
│ │ │ ├── RigidBody.hs
│ │ │ ├── RigidBody2D.hs
│ │ │ ├── RootMotionView.hs
│ │ │ ├── SceneState.hs
│ │ │ ├── SceneTree.hs
│ │ │ ├── SceneTreeTimer.hs
│ │ │ ├── Script.hs
│ │ │ ├── ScrollBar.hs
│ │ │ ├── ScrollContainer.hs
│ │ │ ├── SegmentShape2D.hs
│ │ │ ├── Semaphore.hs
│ │ │ ├── Separator.hs
│ │ │ ├── Shader.hs
│ │ │ ├── ShaderMaterial.hs
│ │ │ ├── Shape.hs
│ │ │ ├── Shape2D.hs
│ │ │ ├── ShortCut.hs
│ │ │ ├── Skeleton.hs
│ │ │ ├── Skeleton2D.hs
│ │ │ ├── SkeletonIK.hs
│ │ │ ├── Skin.hs
│ │ │ ├── SkinReference.hs
│ │ │ ├── Sky.hs
│ │ │ ├── Slider.hs
│ │ │ ├── SliderJoint.hs
│ │ │ ├── SoftBody.hs
│ │ │ ├── Spatial.hs
│ │ │ ├── SpatialGizmo.hs
│ │ │ ├── SpatialMaterial.hs
│ │ │ ├── SpatialVelocityTracker.hs
│ │ │ ├── SphereMesh.hs
│ │ │ ├── SphereShape.hs
│ │ │ ├── SpinBox.hs
│ │ │ ├── SplitContainer.hs
│ │ │ ├── SpotLight.hs
│ │ │ ├── SpringArm.hs
│ │ │ ├── Sprite.hs
│ │ │ ├── Sprite3D.hs
│ │ │ ├── SpriteBase3D.hs
│ │ │ ├── SpriteFrames.hs
│ │ │ ├── StaticBody.hs
│ │ │ ├── StaticBody2D.hs
│ │ │ ├── StreamPeer.hs
│ │ │ ├── StreamPeerBuffer.hs
│ │ │ ├── StreamPeerGDNative.hs
│ │ │ ├── StreamPeerSSL.hs
│ │ │ ├── StreamPeerTCP.hs
│ │ │ ├── StreamTexture.hs
│ │ │ ├── StyleBox.hs
│ │ │ ├── StyleBoxEmpty.hs
│ │ │ ├── StyleBoxFlat.hs
│ │ │ ├── StyleBoxLine.hs
│ │ │ ├── StyleBoxTexture.hs
│ │ │ ├── SurfaceTool.hs
│ │ │ ├── TCP_Server.hs
│ │ │ ├── TabContainer.hs
│ │ │ ├── Tabs.hs
│ │ │ ├── TextEdit.hs
│ │ │ ├── TextFile.hs
│ │ │ ├── Texture.hs
│ │ │ ├── Texture3D.hs
│ │ │ ├── TextureArray.hs
│ │ │ ├── TextureButton.hs
│ │ │ ├── TextureLayered.hs
│ │ │ ├── TextureProgress.hs
│ │ │ ├── TextureRect.hs
│ │ │ ├── Theme.hs
│ │ │ ├── Thread.hs
│ │ │ ├── TileMap.hs
│ │ │ ├── TileSet.hs
│ │ │ ├── Timer.hs
│ │ │ ├── ToolButton.hs
│ │ │ ├── TouchScreenButton.hs
│ │ │ ├── Translation.hs
│ │ │ ├── TranslationServer.hs
│ │ │ ├── Tree.hs
│ │ │ ├── TreeItem.hs
│ │ │ ├── TriangleMesh.hs
│ │ │ ├── Tween.hs
│ │ │ ├── UPNP.hs
│ │ │ ├── UPNPDevice.hs
│ │ │ ├── UndoRedo.hs
│ │ │ ├── VBoxContainer.hs
│ │ │ ├── VScrollBar.hs
│ │ │ ├── VSeparator.hs
│ │ │ ├── VSlider.hs
│ │ │ ├── VSplitContainer.hs
│ │ │ ├── VehicleBody.hs
│ │ │ ├── VehicleWheel.hs
│ │ │ ├── VideoPlayer.hs
│ │ │ ├── VideoStream.hs
│ │ │ ├── VideoStreamGDNative.hs
│ │ │ ├── VideoStreamTheora.hs
│ │ │ ├── VideoStreamWebm.hs
│ │ │ ├── Viewport.hs
│ │ │ ├── ViewportContainer.hs
│ │ │ ├── ViewportTexture.hs
│ │ │ ├── VisibilityEnabler.hs
│ │ │ ├── VisibilityEnabler2D.hs
│ │ │ ├── VisibilityNotifier.hs
│ │ │ ├── VisibilityNotifier2D.hs
│ │ │ ├── VisualInstance.hs
│ │ │ ├── VisualScript.hs
│ │ │ ├── VisualScriptBasicTypeConstant.hs
│ │ │ ├── VisualScriptBuiltinFunc.hs
│ │ │ ├── VisualScriptClassConstant.hs
│ │ │ ├── VisualScriptComment.hs
│ │ │ ├── VisualScriptComposeArray.hs
│ │ │ ├── VisualScriptCondition.hs
│ │ │ ├── VisualScriptConstant.hs
│ │ │ ├── VisualScriptConstructor.hs
│ │ │ ├── VisualScriptCustomNode.hs
│ │ │ ├── VisualScriptDeconstruct.hs
│ │ │ ├── VisualScriptEmitSignal.hs
│ │ │ ├── VisualScriptEngineSingleton.hs
│ │ │ ├── VisualScriptExpression.hs
│ │ │ ├── VisualScriptFunction.hs
│ │ │ ├── VisualScriptFunctionCall.hs
│ │ │ ├── VisualScriptFunctionState.hs
│ │ │ ├── VisualScriptGlobalConstant.hs
│ │ │ ├── VisualScriptIndexGet.hs
│ │ │ ├── VisualScriptIndexSet.hs
│ │ │ ├── VisualScriptInputAction.hs
│ │ │ ├── VisualScriptIterator.hs
│ │ │ ├── VisualScriptLists.hs
│ │ │ ├── VisualScriptLocalVar.hs
│ │ │ ├── VisualScriptLocalVarSet.hs
│ │ │ ├── VisualScriptMathConstant.hs
│ │ │ ├── VisualScriptNode.hs
│ │ │ ├── VisualScriptOperator.hs
│ │ │ ├── VisualScriptPreload.hs
│ │ │ ├── VisualScriptPropertyGet.hs
│ │ │ ├── VisualScriptPropertySet.hs
│ │ │ ├── VisualScriptResourcePath.hs
│ │ │ ├── VisualScriptReturn.hs
│ │ │ ├── VisualScriptSceneNode.hs
│ │ │ ├── VisualScriptSceneTree.hs
│ │ │ ├── VisualScriptSelect.hs
│ │ │ ├── VisualScriptSelf.hs
│ │ │ ├── VisualScriptSequence.hs
│ │ │ ├── VisualScriptSubCall.hs
│ │ │ ├── VisualScriptSwitch.hs
│ │ │ ├── VisualScriptTypeCast.hs
│ │ │ ├── VisualScriptVariableGet.hs
│ │ │ ├── VisualScriptVariableSet.hs
│ │ │ ├── VisualScriptWhile.hs
│ │ │ ├── VisualScriptYield.hs
│ │ │ ├── VisualScriptYieldSignal.hs
│ │ │ ├── VisualServer.hs
│ │ │ ├── VisualShader.hs
│ │ │ ├── VisualShaderNode.hs
│ │ │ ├── VisualShaderNodeBooleanConstant.hs
│ │ │ ├── VisualShaderNodeBooleanUniform.hs
│ │ │ ├── VisualShaderNodeColorConstant.hs
│ │ │ ├── VisualShaderNodeColorFunc.hs
│ │ │ ├── VisualShaderNodeColorOp.hs
│ │ │ ├── VisualShaderNodeColorUniform.hs
│ │ │ ├── VisualShaderNodeCompare.hs
│ │ │ ├── VisualShaderNodeCubeMap.hs
│ │ │ ├── VisualShaderNodeCubeMapUniform.hs
│ │ │ ├── VisualShaderNodeCustom.hs
│ │ │ ├── VisualShaderNodeDeterminant.hs
│ │ │ ├── VisualShaderNodeDotProduct.hs
│ │ │ ├── VisualShaderNodeExpression.hs
│ │ │ ├── VisualShaderNodeFaceForward.hs
│ │ │ ├── VisualShaderNodeFresnel.hs
│ │ │ ├── VisualShaderNodeGlobalExpression.hs
│ │ │ ├── VisualShaderNodeGroupBase.hs
│ │ │ ├── VisualShaderNodeIf.hs
│ │ │ ├── VisualShaderNodeInput.hs
│ │ │ ├── VisualShaderNodeIs.hs
│ │ │ ├── VisualShaderNodeOuterProduct.hs
│ │ │ ├── VisualShaderNodeOutput.hs
│ │ │ ├── VisualShaderNodeScalarClamp.hs
│ │ │ ├── VisualShaderNodeScalarConstant.hs
│ │ │ ├── VisualShaderNodeScalarDerivativeFunc.hs
│ │ │ ├── VisualShaderNodeScalarFunc.hs
│ │ │ ├── VisualShaderNodeScalarInterp.hs
│ │ │ ├── VisualShaderNodeScalarOp.hs
│ │ │ ├── VisualShaderNodeScalarSmoothStep.hs
│ │ │ ├── VisualShaderNodeScalarSwitch.hs
│ │ │ ├── VisualShaderNodeScalarUniform.hs
│ │ │ ├── VisualShaderNodeSwitch.hs
│ │ │ ├── VisualShaderNodeTexture.hs
│ │ │ ├── VisualShaderNodeTextureUniform.hs
│ │ │ ├── VisualShaderNodeTextureUniformTriplanar.hs
│ │ │ ├── VisualShaderNodeTransformCompose.hs
│ │ │ ├── VisualShaderNodeTransformConstant.hs
│ │ │ ├── VisualShaderNodeTransformDecompose.hs
│ │ │ ├── VisualShaderNodeTransformFunc.hs
│ │ │ ├── VisualShaderNodeTransformMult.hs
│ │ │ ├── VisualShaderNodeTransformUniform.hs
│ │ │ ├── VisualShaderNodeTransformVecMult.hs
│ │ │ ├── VisualShaderNodeUniform.hs
│ │ │ ├── VisualShaderNodeVec3Constant.hs
│ │ │ ├── VisualShaderNodeVec3Uniform.hs
│ │ │ ├── VisualShaderNodeVectorClamp.hs
│ │ │ ├── VisualShaderNodeVectorCompose.hs
│ │ │ ├── VisualShaderNodeVectorDecompose.hs
│ │ │ ├── VisualShaderNodeVectorDerivativeFunc.hs
│ │ │ ├── VisualShaderNodeVectorDistance.hs
│ │ │ ├── VisualShaderNodeVectorFunc.hs
│ │ │ ├── VisualShaderNodeVectorInterp.hs
│ │ │ ├── VisualShaderNodeVectorLen.hs
│ │ │ ├── VisualShaderNodeVectorOp.hs
│ │ │ ├── VisualShaderNodeVectorRefract.hs
│ │ │ ├── VisualShaderNodeVectorScalarMix.hs
│ │ │ ├── VisualShaderNodeVectorScalarSmoothStep.hs
│ │ │ ├── VisualShaderNodeVectorScalarStep.hs
│ │ │ ├── VisualShaderNodeVectorSmoothStep.hs
│ │ │ ├── WeakRef.hs
│ │ │ ├── WebRTCDataChannel.hs
│ │ │ ├── WebRTCDataChannelGDNative.hs
│ │ │ ├── WebRTCMultiplayer.hs
│ │ │ ├── WebRTCPeerConnection.hs
│ │ │ ├── WebRTCPeerConnectionGDNative.hs
│ │ │ ├── WebSocketClient.hs
│ │ │ ├── WebSocketMultiplayerPeer.hs
│ │ │ ├── WebSocketPeer.hs
│ │ │ ├── WebSocketServer.hs
│ │ │ ├── WindowDialog.hs
│ │ │ ├── World.hs
│ │ │ ├── World2D.hs
│ │ │ ├── WorldEnvironment.hs
│ │ │ ├── X509Certificate.hs
│ │ │ ├── XMLParser.hs
│ │ │ └── YSort.hs
│ │ ├── Gdnative/
│ │ │ ├── Internal/
│ │ │ │ ├── Api.hs
│ │ │ │ ├── Gdnative.chs
│ │ │ │ ├── TH.hs
│ │ │ │ └── Types.hs
│ │ │ └── Internal.hs
│ │ ├── Gdnative.hs
│ │ ├── Internal/
│ │ │ └── Dispatch.hs
│ │ ├── Nativescript.hs
│ │ └── Tools/
│ │ ├── AnimationTrackEditPlugin.hs
│ │ ├── EditorExportPlugin.hs
│ │ ├── EditorFeatureProfile.hs
│ │ ├── EditorFileDialog.hs
│ │ ├── EditorFileSystem.hs
│ │ ├── EditorFileSystemDirectory.hs
│ │ ├── EditorImportPlugin.hs
│ │ ├── EditorInspector.hs
│ │ ├── EditorInspectorPlugin.hs
│ │ ├── EditorInterface.hs
│ │ ├── EditorNavigationMeshGenerator.hs
│ │ ├── EditorPlugin.hs
│ │ ├── EditorProperty.hs
│ │ ├── EditorResourceConversionPlugin.hs
│ │ ├── EditorResourcePreview.hs
│ │ ├── EditorResourcePreviewGenerator.hs
│ │ ├── EditorSceneImporter.hs
│ │ ├── EditorSceneImporterAssimp.hs
│ │ ├── EditorScenePostImport.hs
│ │ ├── EditorScript.hs
│ │ ├── EditorSelection.hs
│ │ ├── EditorSettings.hs
│ │ ├── EditorSpatialGizmo.hs
│ │ ├── EditorSpatialGizmoPlugin.hs
│ │ ├── EditorSpinSlider.hs
│ │ ├── EditorVCSInterface.hs
│ │ ├── ScriptCreateDialog.hs
│ │ ├── ScriptEditor.hs
│ │ └── VisualScriptEditor.hs
│ └── Godot.hs
├── src-generate/
│ ├── Generate.hs
│ ├── Spec.hs
│ ├── Types/
│ │ └── Internal.hs
│ └── Types.hs
├── stack-shell.nix
├── stack.yaml
├── template/
│ ├── README.md
│ ├── demo/
│ │ ├── Makefile
│ │ ├── ffi/
│ │ │ └── cbits/
│ │ │ └── flib.c
│ │ └── game/
│ │ ├── Main.gdns
│ │ ├── lib/
│ │ │ └── libdemo.gdnlib
│ │ └── project.godot
│ ├── godot-haskell.hsfiles
│ ├── mkdemo.sh
│ └── update-template.sh
└── update-nixpkgs.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
dist*
*.hi
*.o
.hsenv*
cabal-dev/
.stack-work/
.cabal-sandbox
cabal.sandbox.config
.DS_Store
*.dyn_o
*.dyn_hi
app/*.cpp
src/**/*.cpp
src/**/*.c
*.so
.ghc*
#*
.#*
doc/build/
# osvr_server
lighthousedb.json
lhr-*/
# emacs TAG file
TAGS
================================================
FILE: .gitmodules
================================================
[submodule "godot_headers"]
path = godot_headers
url = https://github.com/GodotNativeTools/godot_headers/
[submodule "haskell-src-exts-qq"]
path = haskell-src-exts-qq
url = https://github.com/KaneTW/haskell-src-exts-qq
[submodule "haskell-src-exts-sc"]
path = haskell-src-exts-sc
url = https://github.com/achirkin/haskell-src-exts-sc
================================================
FILE: .hlint.yaml
================================================
- ignore: { name: "Use camelCase" }
- ignore: { name: "Use newtype instead of data" }
================================================
FILE: .travis.yml
================================================
# https://docs.haskellstack.org/en/stable/travis_ci/
sudo: false
dist: bionic
language: generic
addons:
apt:
update: true
cache:
directories:
- $HOME/.stack
- $TRAVIS_BUILD_DIR/.stack-work
before_install:
- mkdir -p ~/.local/bin
- export PATH=$HOME/.local/bin:$PATH
- travis_retry curl -L https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
install:
- git submodule update --init --recursive
- stack build
- stack test
================================================
FILE: .vscode/tasks.json
================================================
{
// Automatically created by phoityne-vscode extension.
"version": "2.0.0",
"presentation": {
"reveal": "always",
"panel": "new"
},
"tasks": [
{
// F7
"group": {
"kind": "build",
"isDefault": true
},
"label": "haskell build",
"type": "shell",
//"command": "cabal configure && cabal build"
"command": "stack build"
},
{
// F6
"group": "build",
"type": "shell",
"label": "haskell clean & build",
//"command": "cabal clean && cabal configure && cabal build"
"command": "stack clean && stack build"
//"command": "stack clean ; stack build" // for powershell
},
{
// F8
"group": {
"kind": "test",
"isDefault": true
},
"type": "shell",
"label": "haskell test",
//"command": "cabal test"
"command": "stack test"
},
{
// F6
"isBackground": true,
"type": "shell",
"label": "haskell watch",
"command": "stack build --test --no-run-tests --file-watch"
}
]
}
================================================
FILE: LICENSE
================================================
Copyright David Kraeutmann (c) 2018
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of David Kraeutmann nor the names of other
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: README.md
================================================
# godot-haskell
[](https://travis-ci.org/SimulaVR/godot-haskell)
Haskell bindings for the Godot game engine.
* Low-level (GDNative) in Godot.Gdnative
* Nativescript (binding classes/methods/etc) in Godot.Nativescript
* High-level (classes generated from the API ) in Godot.Api
* Access methods through Godot.Core
## Getting started with the examples
The easiest way to get started is to have a look at the demos included in the
[examples](https://github.com/SimulaVR/godot-haskell/tree/master/examples)
directory. First check out ["Dodge the
Creeps!"](https://github.com/SimulaVR/godot-haskell/tree/master/examples/dodge-the-creeps),
your first game from the [Godot
documentation](https://docs.godotengine.org/en/3.1/getting_started/step_by_step/your_first_game.html). Following
along with the documentation and the code should make everything understandable.
To build:
```bash
git clone --recursive https://github.com/SimulaVR/godot-haskell
stack install godot-haskell:exe:godot-haskell-project-generator
cd godot-haskell/examples/dodge-the-creeps
make
```
To make changes to the game, in two different terminals:
```bash
make stack-watch
make project-watch
```
The first command will constantly build Haskell code and copy the shared library
into the Godot project, demo. The second command will constantly scan the Godot
project and build Haskell code out of it.
Load up the game by importing `game/project.godot` into the editor, which you
can do from the commandline with `godot game/project.godot`. To run the game in
the editor press F5, stop it with F8.
### Understanding the examples
There are two parts to every project. `examples/dodge-the-creeps/game` which is
the Godot project and `examples/dodge-the-creeps/src` which are the Haskell
sources. When you run `cd examples/dodge-the-creeps && make stack` to build the
demo, it builds the project locally with `stack build` and then does a `cp` to
copy the resulting shared library into the right place in
`examples/dodge-the-creeps/game`. This way Godot will pick it up. If you just do
a `stack build` without copying, your shared library will never update and Godot
will run the old code.
You must regenerate `examples/dodge-the-creeps/src/Project` any time you modify
the Godot project. This directory contains the Godot project mirrored into
Haskell, just like @Servant@ provides you with API safety by declaring APIs in
Haskell. When you change the name of a node in Godot, this will update a Haskell
class instance, which will lead to a type error in your project. You can do this
with `stack exec godot-haskell-parse-game game src` which will watch your
project for changes.
## Known issues & inconveniences
* Script variables only appear in the editor when you reload it.
* No type safety for call and call_deferred.
* Every time you add a new node which needs a native script you need to manually
select the library. It's tedious right now. This is the procedure for adding a
new node backed by Haskell code: create the node, right click it, attach a
script, select nativescript, the script will open in the editor, in the
inspector find the Library subheading under NativeScript, click [empty], pick
Load, the file picker will open, open lib, and select libmyproject.dnlib or
whatever you've renamed the library to. That's it. Don't edit the empty file
that's been opened. Now in Haskell, you can create a class with the same name
as the Godot one and that inherits from the same type. See the demo. There is
a ticket in Godot to automate this process :(
## Setting up your own project.
It's best to start with one of the existing examples, make a copy, and rename
the project. If you want to start another project use the stack template
`template/godot-haskell.hsroots` Alternatively, fetch it directly from git:
```bash
stack new myproject https://raw.githubusercontent.com/SimulaVR/godot-haskell/master/template/godot-haskell.hsfiles
```
## Changing Godot versions
You will need to regenerate the bindings if you switch Godot versions. At
present, these are generated for the version that corresponds to the
godot_headers submodule included here. This was 3.1 at the time of writing.
To regenerate bindings:
* Replace godot_headers with a version that corresponds to your
install. Instructions are included there, but that generally means either
checking out the corresponding files or rebuilding Godot.
* Check out a copy of the godot repo and make sure you're on the commit
corresponding to your version of godot. You don't need to build this, but you
probably will anyway. We need it because documentation files are not included
in the api.json file found in godot_headers.
* Summarize the documentation xml files into a json file:
```bash
# Prerequisite
sudo apt-get install jq libcurl4-gnutls-dev # Or equivalent on you OS/Distro
cabal install xml-to-json
# Generate the JSON
xml-to-json godot-install-directory/doc/classes/*.xml | jq -n '[inputs]' &> godot_doc_classes.json
```
* Build the bindings themselves:
```bash
cd classgen
stack build
rm ../src/Godot/Core/* ../src/Godot/Tools/*
stack exec godot-haskell-classgen -- ../godot_headers/api.json ../godot_doc_classes.json ../
```
That's it! The rest of the bindings are fairly lightweight with few
dependencies, so you shouldn't see much breakage in the rest of the package.
If you want to get an idea of what the Haskell libraries are doing, set the
environment variable `HS_GODOT_DEBUG`.
## Questions
The primary method of contact is the SimulaVR [Discord server](https://discord.gg/V2NgzZt).
Mirrors are available at [](https://gitter.im/SimulaVR/Simula?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) and in the SimulaVR channel at Matrix.
## Docs
Most of the API is documented but the lowest-level bindings, like GDNative
functions don't have documentation. They are quite intuitive to use though.
================================================
FILE: Setup.hs
================================================
import Distribution.Simple
main = defaultMain
================================================
FILE: cbits/util.h
================================================
#ifndef GODOT_HASKELL_UTIL_H__
#define GODOT_HASKELL_UTIL_H__
#include <gdnative/gdnative.h>
#endif /* GODOT_HASKELL_UTIL_H__ */
================================================
FILE: classgen/README.md
================================================
Generate bindings to the Godot API.
See the godot-haskell README.md for instructions on use
================================================
FILE: classgen/app-classgen/Main.hs
================================================
import Classgen.Module
import Classgen.Spec
import Control.Lens
import Control.Monad.State
import Data.Maybe (mapMaybe)
import Data.Aeson
import qualified Data.ByteString.Lazy as BL
import qualified Data.HashMap.Strict as HM
import Language.Haskell.Exts
import Language.Haskell.Exts.SimpleComments
import System.Directory
import System.Environment
import System.Exit
import System.FilePath
import Control.Applicative
import qualified Classgen.Docs as D
import qualified Data.HashMap.Strict as H
import qualified Data.Text as T
main :: IO ()
main = do
args <- getArgs
when (length args /= 3) $ do
putStrLn "See the godot-haskell README.md for instructions"
putStrLn "godot-haskell-classgen <api.json> <godot_doc_classes.json> <godot-haskell-root>"
exitFailure
api <- BL.readFile (args !! 0)
let decodeErr x = either error id (eitherDecode x)
let (Just classes) = decodeErr api :: Maybe GodotClasses
doc <- BL.readFile (args !! 1)
let (Just docs) = decodeErr doc :: Maybe D.GodotDocs
let godotHaskellRootDir = args !! 2
let docTable = D.toTable docs
let state = execState (mapM_ (\cls -> addClass cls (H.lookup (cls ^. Classgen.Spec.name) docTable
<|> (T.stripPrefix "Godot_" (cls ^. Classgen.Spec.name)
>>= \r -> H.lookup r docTable)
<|> (T.stripPrefix "Godot" (cls ^. Classgen.Spec.name)
>>= \r -> H.lookup r docTable)
<|> (T.stripPrefix "_" (cls ^. Classgen.Spec.name)
>>= \r -> H.lookup r docTable)
<|> (H.lookup ("_" <> (cls ^. Classgen.Spec.name)) docTable)
) classes) classes)
(ClassgenState mempty mempty mempty)
writeModule godotHaskellRootDir $ godotApiTypes (state ^. tyDecls)
mapM_ (writeModule godotHaskellRootDir) (HM.elems (state ^. modules))
where
godotApiTypes decls = Module Nothing (Just
$ ModuleHead Nothing (ModuleName Nothing "Godot.Api.Types") Nothing
$ Just (classExports decls))
[LanguagePragma Nothing [Ident Nothing "DerivingStrategies"
,Ident Nothing "GeneralizedNewtypeDeriving"
,Ident Nothing "TypeFamilies"
,Ident Nothing "TemplateHaskell"]]
classImports
(decls ++ mapMaybe fromNewtypeDerivingBase decls)
classExports decls = ExportSpecList Nothing $ tcHasBaseClass : mapMaybe fromNewtypeOnly decls
tcHasBaseClass = fmap (\_ -> Nothing) $ EThingWith () (EWildcard () 0) (UnQual () (Ident () "HasBaseClass")) []
fromNewtypeOnly decl = case decl of
DataDecl _ (NewType _) _ (DHead _ (Ident Nothing ntName)) _ _ ->
Just $ EThingWith Nothing (EWildcard Nothing 0) (UnQual Nothing (Ident Nothing ntName)) []
_ ->
Nothing
fromNewtypeDerivingBase decl = case decl of
DataDecl _ (NewType _) _ (DHead _ (Ident Nothing ntName)) _ _ ->
Just $ SpliceDecl Nothing (App Nothing (Var Nothing (UnQual Nothing (Ident Nothing "deriveBase")))
(TypQuote Nothing (UnQual Nothing (Ident Nothing ntName))))
_ ->
Nothing
classImports = map (\n -> ImportDecl Nothing (ModuleName Nothing n) False False False Nothing Nothing Nothing)
[ "Data.Coerce", "Foreign.C", "Godot.Internal.Dispatch", "Godot.Gdnative.Internal"]
writeModule :: FilePath -> Module (Maybe CodeComment) -> IO ()
writeModule godotHaskellRootDir mdl@(Module _ (Just (ModuleHead _ (ModuleName Nothing name) _ _)) _ _ _) = do
let filepath = godotHaskellRootDir </> "src/" ++ map replaceDot name ++ ".hs"
-- let out = prettyPrint mdl
let out = uncurry exactPrint (ppWithComments mdl)
createDirectoryIfMissing True (takeDirectory filepath)
writeFile filepath out
where
replaceDot '.' = '/'
replaceDot c = c
================================================
FILE: classgen/default.nix
================================================
{ mkDerivation, aeson, base, bytestring, c2hs, casing, containers
, directory, filepath, hpack
, lens, mtl, template-haskell, text, unordered-containers
, vector , stdenv, syb, callPackage, haskell, haskellPackages, fetchFromGitHub
}:
let haskell-src-exts-custom = haskell.lib.dontCheck (haskellPackages.callPackage
({ mkDerivation, array, base, containers, directory, filepath
, ghc-prim, happy, mtl, pretty, pretty-show, smallcheck, stdenv
, tasty, tasty-golden, tasty-smallcheck
}:
mkDerivation {
pname = "haskell-src-exts";
version = "1.23.0";
sha256 = "09048bhv7ajfsnjlzaz445yb65n2pc4l3yn7nmmrnkdy1f0gn2cm";
libraryHaskellDepends = [ array base ghc-prim pretty ];
libraryToolDepends = [ happy ];
testHaskellDepends = [
base containers directory filepath mtl pretty-show smallcheck tasty
tasty-golden tasty-smallcheck
];
doCheck = false;
description = "Manipulating Haskell source: abstract syntax, lexer, parser, and pretty-printer";
license = stdenv.lib.licenses.bsd3;
hydraPlatforms = stdenv.lib.platforms.none;
}) {});
haskell-src-exts-qq = haskellPackages.callPackage (
{ mkDerivation, base, hspec, stdenv, syb, template-haskell
}:
mkDerivation {
pname = "haskell-src-exts-qq";
version = "0.8";
src = fetchFromGitHub {
owner = "KaneTW";
repo = "haskell-src-exts-qq";
rev = "a2d9071c9d6a627a253edfaaa64b6b67c9da3534";
sha256 = "1cvk90zi16m3nnz52gxim9b8sm17356jrp756y95is6ky13l2h60";
};
libraryHaskellDepends = [
base haskell-src-exts-custom haskell-src-meta-custom syb template-haskell
];
testHaskellDepends = [ base haskell-src-exts-custom hspec ];
description = "A quasiquoter for haskell-src-exts";
license = stdenv.lib.licenses.bsd3;
}) { };
haskell-src-meta-custom = haskell.lib.dontCheck (haskellPackages.callPackage
({ mkDerivation, base, HUnit, pretty, stdenv, syb
, template-haskell, test-framework, test-framework-hunit
, th-orphans
}:
mkDerivation {
pname = "haskell-src-meta";
version = "0.8.5";
sha256 = "1csqp3n7330rhia9msyw34z7qwwj64gdy5qlv8w4jbm49dap24ik";
revision = "1";
editedCabalFile = "00znr8mrlbyn0n1bw4c82rv82pq5ngkk7kw9cgk13pghf93hwwv7";
libraryHaskellDepends = [
base haskell-src-exts-custom pretty syb template-haskell th-orphans
];
description = "Parse source to template-haskell abstract syntax";
license = stdenv.lib.licenses.bsd3;
}) {});
in
mkDerivation {
pname = "godot-haskell-classgen";
version = "0.1.0.0";
src = ./.;
isLibrary = true;
isExecutable = true;
libraryHaskellDepends = [
aeson base bytestring casing containers
haskell-src-exts-qq lens mtl template-haskell text
unordered-containers vector
];
libraryToolDepends = [ c2hs hpack ];
executableHaskellDepends = [
aeson base bytestring casing containers directory filepath
lens mtl template-haskell text
unordered-containers vector
];
executableToolDepends = [ c2hs ];
prePatch = "hpack";
homepage = "https://github.com/KaneTW/godot-haskell#readme";
license = stdenv.lib.licenses.bsd3;
}
================================================
FILE: classgen/godot-haskell-classgen.cabal
================================================
cabal-version: 1.12
-- This file has been generated from package.yaml by hpack version 0.31.1.
--
-- see: https://github.com/sol/hpack
--
-- hash: 35a149339951f4c097aab1ae9ef0e3952109a1273b725ce775c4483b80c67fb6
name: godot-haskell-classgen
version: 0.1.0.0
category: Web
homepage: https://github.com/KaneTW/godot-haskell#readme
bug-reports: https://github.com/KaneTW/godot-haskell/issues
author: David Kraeutmann
maintainer: kane@kane.cx
copyright: 2018 David Kraeutmann
license: BSD3
build-type: Simple
extra-source-files:
README.md
source-repository head
type: git
location: https://github.com/KaneTW/godot-haskell
library
exposed-modules:
Classgen.Docs
Classgen.Module
Classgen.Spec
Classgen.Utils
other-modules:
Paths_godot_haskell_classgen
hs-source-dirs:
src-classgen
default-extensions: FlexibleContexts FlexibleInstances ScopedTypeVariables TypeApplications StandaloneDeriving DerivingStrategies DefaultSignatures MultiParamTypeClasses FunctionalDependencies TypeFamilies TemplateHaskell TypeOperators TypeInType QuasiQuotes OverloadedStrings PatternSynonyms GeneralizedNewtypeDeriving
include-dirs:
godot_headers
cbits
build-tools:
c2hs
build-depends:
aeson
, base
, bytestring
, casing
, containers
, haskell-src-exts
, haskell-src-exts-qq
, haskell-src-exts-sc
, lens
, mtl
, template-haskell
, text
, unordered-containers
, vector
default-language: Haskell2010
executable godot-haskell-classgen
main-is: Main.hs
other-modules:
Paths_godot_haskell_classgen
hs-source-dirs:
app-classgen
default-extensions: FlexibleContexts FlexibleInstances ScopedTypeVariables TypeApplications StandaloneDeriving DerivingStrategies DefaultSignatures MultiParamTypeClasses FunctionalDependencies TypeFamilies TemplateHaskell TypeOperators TypeInType QuasiQuotes OverloadedStrings PatternSynonyms GeneralizedNewtypeDeriving
include-dirs:
godot_headers
cbits
build-tools:
c2hs
build-depends:
aeson
, base
, bytestring
, casing
, containers
, directory
, filepath
, godot-haskell-classgen
, haskell-src-exts
, haskell-src-exts-sc
, lens
, mtl
, template-haskell
, text
, unordered-containers
, vector
default-language: Haskell2010
================================================
FILE: classgen/package.yaml
================================================
name: godot-haskell-classgen
version: '0.1.0.0'
category: Web
author: David Kraeutmann
maintainer: kane@kane.cx
copyright: 2018 David Kraeutmann
license: BSD3
github: KaneTW/godot-haskell
extra-source-files:
- README.md
dependencies:
- base
- aeson
- bytestring
- template-haskell
- lens
- text
- casing
- vector
- containers
- unordered-containers
- mtl
build-tools:
- c2hs
include-dirs:
- godot_headers
- cbits
default-extensions:
- FlexibleContexts
- FlexibleInstances
- ScopedTypeVariables
- TypeApplications
- StandaloneDeriving
- DerivingStrategies
- DefaultSignatures
- MultiParamTypeClasses
- FunctionalDependencies
- TypeFamilies
- TemplateHaskell
- TypeOperators
- TypeInType
- QuasiQuotes
- OverloadedStrings
- PatternSynonyms
- GeneralizedNewtypeDeriving
library:
source-dirs: src-classgen
dependencies:
- haskell-src-exts
- haskell-src-exts-qq
- haskell-src-exts-sc
executables:
godot-haskell-classgen:
main: Main.hs
source-dirs: app-classgen
dependencies:
- godot-haskell-classgen
- haskell-src-exts
- haskell-src-exts-sc
- directory
- filepath
================================================
FILE: classgen/release.nix
================================================
let
pkgs = import <nixpkgs> { };
in
pkgs.haskellPackages.callPackage ./default.nix { }
================================================
FILE: classgen/src-classgen/Classgen/Docs.hs
================================================
{-# LANGUAGE TemplateHaskell, GeneralizedNewtypeDeriving, OverloadedStrings #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Classgen.Docs where
import Control.Applicative
import Control.Lens
import Data.Aeson
import Data.Aeson.TH
import Data.Monoid
import Data.Text (Text)
import qualified Data.Text as T
import Data.Vector (Vector)
import qualified Data.Vector as V
import Data.HashMap.Strict (HashMap)
import qualified Data.Set as S
import qualified Data.ByteString.Lazy as BL
import qualified Data.HashMap.Strict as H
import Text.Casing
import Classgen.Utils
-- | One of the two values that has been parsed from JSON
data AlternativeJSON a b
= FirstJSON a
| SecondJSON b
deriving (Eq, Ord, Show)
instance (FromJSON a, FromJSON b) => FromJSON (AlternativeJSON a b) where
parseJSON v = FirstJSON <$> parseJSON v <|> SecondJSON <$> parseJSON v
alternative1 :: AlternativeJSON a b -> a -> a
alternative1 (FirstJSON a) _ = a
alternative1 _ a = a
alt1 :: AlternativeJSON a b -> Maybe a
alt1 (FirstJSON a) = Just a
alt1 _ = Nothing
type GodotDocTable = HashMap Text GodotDocClass
type GodotDocs = Vector GodotDoc
newtype Ref a = Ref Text
deriving (Show, Eq, FromJSON, ToJSON)
data GPrimType = VoidType | BoolType | IntType | FloatType
deriving (Show, Eq)
instance FromJSON GPrimType where
parseJSON = withText "primitive type" $ \t ->
case t of
"void" -> pure VoidType
"bool" -> pure BoolType
"int" -> pure IntType
"float" -> pure FloatType
_ -> fail $ "Unknown type" <> T.unpack t
data GType
= PrimitiveType !GPrimType
| CoreType !Text
| CustomType !Text
| EnumType !Text
deriving (Show, Eq)
isCoreType t = t `S.member` S.fromList
[ "AABB",
"Array",
"Basis",
"Color",
"Dictionary",
"GodotError",
"NodePath",
"Plane",
"PoolByteArray",
"PoolIntArray",
"PoolRealArray",
"PoolStringArray",
"PoolVector2Array",
"PoolVector3Array",
"PoolColorArray",
"Object",
"Quat",
"Rect2",
"RID",
"String",
"Transform",
"Transform2D",
"Variant",
"Vector2",
"Vector3" ]
instance FromJSON GType where
parseJSON v = PrimitiveType <$> parseJSON v
<|> withText "type" (\t ->
if isCoreType t
then pure $ CoreType t
else if "enum." `T.isPrefixOf` t
then pure $ EnumType t
else pure $ CustomType t) v
data GodotDoc = GodotDoc {
_gdClass :: !GodotDocClass
} deriving (Show, Eq)
instance FromJSON GodotDoc where
parseJSON (Object x) = GodotDoc <$> x .: "class"
parseJSON _ = fail "Expected an Object"
data OptionalArray a = OptionalArray { unOption :: Vector a }
deriving (Show, Eq)
instance FromJSON a => FromJSON (OptionalArray a) where
parseJSON x@(Array _) = OptionalArray <$> parseJSON x
parseJSON x = OptionalArray . V.singleton <$> parseJSON x
data GodotDocClass = GodotDocClass
{ _gdName :: !Text
, _gdVersion :: !Text
, _gdBrief_description :: !(AlternativeJSON Text Object)
, _gdDescription :: !(AlternativeJSON Text Object)
, _gdCategory :: !(Maybe Text)
, _gdInherits :: !(Maybe Text)
, _gdMembers :: !(Maybe (HashMap Text (OptionalArray GodotProperty)))
, _gdConstants :: !(HashMap Text (OptionalArray GodotConstant))
, _gdSignals :: !(Maybe (HashMap Text (OptionalArray GodotSignal)))
, _gdMethods :: !(HashMap Text (OptionalArray GodotMethod))
} deriving (Show, Eq)
data GodotProperty = GodotProperty
{ _gpName :: !Text
, _gcType :: !GType
, _gcGetter :: !Text
, _gcSetter :: !Text
, _gcValue :: !(Maybe Text)
} deriving (Show, Eq)
data GodotConstant = GodotConstant
{ _goName :: !Text
, _goValue :: !Text
, _goEnum :: !(Maybe Text)
} deriving (Show, Eq)
data GodotSignal = GodotSignal
{ _gsName :: !Text
, _gsDescription :: !(AlternativeJSON Text Object)
, _gsArgument :: !(Maybe (OptionalArray GodotArgument))
} deriving (Show, Eq)
data GodotArgument = GodotArgument
{ _gaName :: !Text
, _gaType :: !GType
, _gaIndex :: !Text
, _gaDefault_ :: !(Maybe Text)
} deriving (Show, Eq)
instance FromJSON GodotArgument where
parseJSON (Object x) = GodotArgument <$> x .: "name" <*> x .: "type" <*> x .: "index" <*> x .:? "default"
parseJSON _ = fail "Expected an Object"
data GodotMethod = GodotMethod
{ _gmName :: !Text
, _gmDescription :: !(AlternativeJSON Text Object)
, _gmReturn :: !(Maybe (HashMap Text GType))
, _gmArgument :: !(Maybe (OptionalArray GodotArgument))
} deriving (Show, Eq)
makeLensesWith fixedTypeFields ''GodotDoc
makeLensesWith fixedTypeFields ''GodotDocClass
makeLensesWith fixedTypeFields ''GodotProperty
makeLensesWith fixedTypeFields ''GodotSignal
makeLensesWith fixedTypeFields ''GodotArgument
makeLensesWith fixedTypeFields ''GodotMethod
toTable :: GodotDocs -> GodotDocTable
toTable = V.foldl' (\hm d -> H.insert (d ^. class' . name) (d ^. class') hm) H.empty
makePrisms ''GType
makePrisms ''GPrimType
concat <$> mapM (deriveFromJSON defaultOptions { fieldLabelModifier = quietSnake . drop 3, omitNothingFields = True })
[ ''GodotDocClass
, ''GodotProperty
, ''GodotConstant
, ''GodotSignal
, ''GodotMethod ]
convertDoc = T.replace "]" "@" . T.replace "[" "@"
. T.replace "[/code]" "@" . T.replace "[code]" "@"
. T.replace "[/codeblock]" "\n@\n" . T.replace "[codeblock]" "\n@\n"
. T.replace "[b]" "__" . T.replace "[/b]" "__"
. T.replace "[constant " "@"
. T.replace "[member " "@"
================================================
FILE: classgen/src-classgen/Classgen/Module.hs
================================================
{-# LANGUAGE NoMonoLocalBinds, NoMonomorphismRestriction #-}
module Classgen.Module where
import Control.Lens hiding (index)
import Control.Applicative
import Control.Monad.State
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HM
import qualified Data.Vector as V
import Data.Text (Text)
import qualified Data.Text as T
import Data.Set (Set)
import qualified Data.Set as S
import qualified Language.Haskell.Exts as HS
import Language.Haskell.Exts.QQ
import Language.Haskell.Exts.SimpleComments
import Text.Casing
import Classgen.Spec
import qualified Classgen.Docs as D
import Data.Maybe
import Data.List
--TODO add singleton functions
data ClassgenState = ClassgenState
{ _csModules :: !(HashMap Text (HS.Module (Maybe CodeComment)))
, _csMethods :: !(HashMap Text (Set Text))
, _csTyDecls :: !([HS.Decl (Maybe CodeComment)])
} deriving (Show, Eq)
makeLensesWith abbreviatedFields ''ClassgenState
noComments l = fmap (\_ -> Nothing) l
addClass :: MonadState ClassgenState m => GodotClass -> Maybe D.GodotDocClass -> GodotClasses -> m ()
addClass cls mdoc allClasses = do
methods <- mkMethods cls mdoc
properties <- mkProperties cls mdoc
signals <- mkSignals cls mdoc
let dataType = if isCoreType (cls ^. name) then [] else mkDataType cls mdoc
tyDecls <>= dataType
let classDecls = nub $ (noComments <$> (mkConstants cls ++ mkEnums cls))
++ signals ++ properties ++ methods
modules %= HM.insert (mangleClass $ cls ^. name) (HS.Module Nothing
(Just $ classModuleHead classDecls)
[HS.LanguagePragma Nothing [HS.Ident Nothing "DerivingStrategies"
,HS.Ident Nothing "GeneralizedNewtypeDeriving"
,HS.Ident Nothing "TypeFamilies"
,HS.Ident Nothing "TypeOperators"
,HS.Ident Nothing "FlexibleContexts"
,HS.Ident Nothing "DataKinds"
,HS.Ident Nothing "MultiParamTypeClasses"]]
(noComments <$> classImports)
classDecls)
where
classImports = map (\n -> HS.ImportDecl () (HS.ModuleName () n) False False False Nothing Nothing Nothing)
([ "Data.Coerce", "Foreign.C", "Godot.Internal.Dispatch"
, "qualified Data.Vector as V"
, "Linear(V2(..),V3(..),M22)", "Data.Colour(withOpacity)", "Data.Colour.SRGB(sRGB)"
, "System.IO.Unsafe", "Godot.Gdnative.Internal", "Godot.Api.Types"
] <> maybe [] (:[]) parentModuleImport)
classModuleHead decls = HS.ModuleHead Nothing classModuleName Nothing $ Just (classExports decls)
classModuleName = noComments $ HS.ModuleName () $ "Godot." ++ (pascal $ T.unpack (cls ^. apiType))
++ "." ++ (T.unpack $ mangleClass $ cls ^. name)
parentModuleImport = case (cls ^. baseClass, V.find (\x -> cls ^. baseClass == x ^. name) allClasses) of
("", Nothing) -> Nothing
(_, Nothing) -> error "Can't find base class"
(_, Just baseCls) -> Just $ "Godot." ++ (pascal $ T.unpack (baseCls ^. apiType))
++ "." ++ (T.unpack $ mangleClass $ baseCls ^. name)
++ "()"
classExports decls = HS.ExportSpecList Nothing $
mapMaybe (\decl -> case decl of
HS.TypeSig _ [name] (HS.TyCon _ (HS.Qual _ _ (HS.Ident _ "MethodBind"))) ->
Nothing
HS.TypeSig _ [name] (HS.TyCon _ (HS.UnQual _ (HS.Ident _ "MethodBind"))) ->
Nothing
HS.TypeSig _ [name] _ ->
Just $ HS.EVar Nothing (HS.Qual Nothing classModuleName name)
_ -> Nothing)
decls
mkProperties :: MonadState ClassgenState m => GodotClass -> Maybe D.GodotDocClass -> m [HS.Decl (Maybe CodeComment)]
mkProperties cls mdoc = concat <$> mapM mkProperty (V.toList $ cls ^. properties)
where
mkProperty prop = do
get <- mkGetter prop
set <- mkSetter prop
inst <- mkProp prop
return (get ++ set ++ [inst])
indexArg prop = if prop ^. index == -1 then
V.empty else
V.singleton (GodotArgument "param" (PrimitiveType IntType) Nothing)
mkGetter prop = mkMethod cls (GodotMethod (prop ^. getter)
(gty prop) False False True False False False False
(indexArg prop))
(methodDoc (prop ^. getter) mdoc)
mkSetter prop | T.null (prop ^. setter) = return []
| otherwise = mkMethod cls (GodotMethod (prop ^. setter)
(PrimitiveType VoidType) False False False False False False False
(indexArg prop <> V.singleton (GodotArgument (prop ^. name) (gty prop) Nothing)))
(methodDoc (prop ^. setter) mdoc)
gty prop = case (cls ^. name,prop ^. name) of
-- NB These are bugs in api.json
("VisualScriptPropertySet","type_cache") -> CoreType "Dictionary" -- has int
("PhysicsDirectBodyState","transform") -> CoreType "Transform" -- has transform2d
("JSONParseResult","error") -> PrimitiveType IntType -- has Object
("InputEventKey", "echo") -> PrimitiveType BoolType -- has int
("GeometryInstance", "lod_max_distance") -> PrimitiveType FloatType -- has int
("GeometryInstance", "lod_max_hysteresis") -> PrimitiveType FloatType -- has int
("GeometryInstance", "lod_min_distance") -> PrimitiveType FloatType -- has int
("GeometryInstance", "lod_min_hysteresis") -> PrimitiveType FloatType -- has int
("Control", "margin_bottom") -> PrimitiveType FloatType -- has int
("Control", "margin_top") -> PrimitiveType FloatType -- has int
("Control", "margin_left") -> PrimitiveType FloatType -- has int
("Control", "margin_right") -> PrimitiveType FloatType -- has int
("Curve3D", "_data") -> CoreType "Dictionary" -- has int
("Curve2D", "_data") -> CoreType "Dictionary" -- has int
("Curve", "_data") -> CoreType "Array" -- has int
("Polygon2D", "bones") -> CoreType "Array" -- has Bool
("RichTextLabel", "custom_effects") -> CoreType "Array" -- has 17/17:RichTextEffect
("AudioEffectPitchShift", "oversampling") -> PrimitiveType IntType -- has float
("Area2D", "priority") -> PrimitiveType FloatType -- has int
("Area", "priority") -> PrimitiveType FloatType -- has int
-- NB These seem to be too specific or generic in api.json
("ARVRServer", "primary_interface") -> CustomType "ARVRInterface" -- has Object
("AnimationTree", "tree_root") -> CustomType "AnimationNode" -- has AnimationRootNode
("Camera2D", "custom_viewport") -> CustomType "Node" -- has Viewport
("CanvasLayer", "custom_viewport") -> CustomType "Node" -- has Viewport
("ConvexPolygonShape", "points") -> CustomType "PoolVector3Array" -- has Array
("ParticlesMaterial","angle_curve") -> CoreType "Texture" -- has CurveTexture
("ParticlesMaterial","angular_velocity_curve") -> CoreType "Texture" -- has CurveTexture
("ParticlesMaterial","anim_offset_curve") -> CoreType "Texture" -- has CurveTexture
("ParticlesMaterial","anim_speed_curve") -> CoreType "Texture" -- has CurveTexture
("ParticlesMaterial","damping_curve") -> CoreType "Texture" -- has CurveTexture
("ParticlesMaterial","hue_variation_curve") -> CoreType "Texture" -- has CurveTexture
("ParticlesMaterial","linear_accel_curve") -> CoreType "Texture" -- has CurveTexture
("ParticlesMaterial","orbit_velocity_curve") -> CoreType "Texture" -- has CurveTexture
("ParticlesMaterial","radial_accel_curve") -> CoreType "Texture" -- has CurveTexture
("ParticlesMaterial","scale_curve") -> CoreType "Texture" -- has CurveTexture
("ParticlesMaterial","tangential_accel_curve") -> CoreType "Texture" -- has CurveTexture
("ParticlesMaterial","color_ramp") -> CoreType "Texture" -- has GradientTexture
("SceneTree","root") -> CoreType "Viewport" -- has Node
_ -> prop ^. type'
mkProp prop = do
pure $ noComments [dec|instance NodeProperty ((cty)) ((n)) ((ty)) ((ro)) where nodeProperty = ( $get , $set , Nothing) |]
where cty = clsTy cls
n = promotedString $ T.unpack $ prop ^. name
ty = toHsType $ gty prop
ro = if T.null (prop ^. setter) then
HS.TyPromoted () $ HS.PromotedCon () True $ HS.UnQual () $ HS.Ident () "True" else
HS.TyPromoted () $ HS.PromotedCon () True $ HS.UnQual () $ HS.Ident () "False"
setname = toMethodName (prop ^. setter)
getname = toMethodName (prop ^. getter)
i :: String = show $ ((prop ^. index)::Int)
get = if prop ^. index == -1 then
[hs|__getname__|] else
[hs|wrapIndexedGetter __i__ __getname__|]
set = if prop ^. index == -1 || T.null (prop ^. setter) then
if T.null (prop ^. setter) then
[hs|()|] else
[hs|wrapDroppingSetter __setname__|]
else
[hs|wrapIndexedSetter __i__ __setname__|]
godotObjectTy :: HS.Type ()
godotObjectTy = HS.TyCon () $ HS.UnQual () $ HS.Ident () "Object"
sigCon :: HS.Exp ()
sigCon = HS.Con () $ HS.Qual () (HS.ModuleName () $ "Godot.Internal.Dispatch") $ HS.Ident () "Signal"
sigTy :: HS.Type ()
sigTy = HS.TyCon () $ HS.Qual () (HS.ModuleName () $ "Godot.Internal.Dispatch") $ HS.Ident () "Signal"
clsAsName :: GodotClass -> HS.Name ()
clsAsName cls = HS.Ident () (T.unpack $ mangleClass $ cls ^. name)
clsTy :: GodotClass -> HS.Type ()
clsTy = HS.TyCon () . HS.UnQual () . clsAsName
nameToTyCon = HS.TyCon () . HS.UnQual () . HS.Ident () . T.unpack
baseClsTy :: GodotClass -> HS.Type ()
baseClsTy cls = nameToTyCon (cls ^. baseClass)
intTy = HS.TyCon () . HS.UnQual () $ HS.name "Int"
promotedString s = HS.TyPromoted () (HS.PromotedString () s s)
promotedList l = HS.TyPromoted () (HS.PromotedList () True l)
mkDataType cls mdoc =
[ HS.DataDecl (case mdoc of
Nothing -> Nothing
Just d -> case d ^. D.brief_description of
D.FirstJSON x -> preComment (T.unpack $
D.convertDoc $
x <> "\n" <> let desc = D.alternative1 (d ^. D.description) ""
in case T.stripPrefix x desc of
Nothing -> T.strip desc
Just r -> r)
_ -> Nothing) (HS.NewType Nothing) Nothing
(noComments $ HS.DHead () $ clsAsName cls)
[noComments $ HS.QualConDecl () Nothing Nothing $ HS.ConDecl () (clsAsName cls) [godotObjectTy]]
[noComments $ HS.Deriving () (Just $ HS.DerivNewtype ()) [asVariantRule]]
] ++ if T.null (cls ^. baseClass) then [] else
[ noComments
$ [dec| instance HasBaseClass ((cty)) where
type BaseClass ((cty)) = ((bty))
super = coerce |] ]
where
asVariantRule = HS.IRule () Nothing Nothing $ HS.IHCon () (HS.UnQual () $ HS.Ident () "AsVariant")
cty = clsTy cls
bty = baseClsTy cls
mkSignals :: MonadState ClassgenState m => GodotClass -> Maybe D.GodotDocClass -> m [HS.Decl (Maybe CodeComment)]
mkSignals cls mdoc = return $ concatMap mkSignal (V.toList $ cls ^. signals)
where
signalDoc :: Text -> Maybe D.GodotDocClass -> Maybe CodeComment
signalDoc name mdoc = do
doc <- mdoc
sigs <- D._gdSignals doc
ss <- D.unOption <$> HM.lookup (T.pack "signal") sigs
sdoc <- V.find (\e -> e ^. D.name == name) ss
d <- D.alt1 $ sdoc ^. D.description
preComment (T.unpack $ D.convertDoc d)
argToHsType (GodotArgument _ ty _) = toHsType ty
mkSignal sig
= let sigStr = T.unpack (sig ^. name)
sigName = HS.Ident () ("sig_" ++ sigStr)
in [ HS.TypeSig (signalDoc (sig ^. name) mdoc) [noComments $ sigName] (noComments $ HS.TyApp () sigTy (clsTy cls))
, noComments $ HS.PatBind () (HS.PVar () sigName) (
HS.UnGuardedRhs () $ HS.App () sigCon $ HS.Lit () $ HS.String () sigStr sigStr
) Nothing
, let cty = clsTy cls
args = promotedList $ map argToHsType $ V.toList $ sig ^. arguments
st = promotedString sigStr
in noComments [dec|instance NodeSignal ((cty)) ((st)) ((args))|]
]
mkConstants :: GodotClass -> [HS.Decl ()]
mkConstants cls = concatMap mkConstant (HM.toList $ cls ^. constants)
where
mkConstant (cname, cval)
= let constName = HS.Ident () $ T.unpack ("_" <> cname)
in [ HS.TypeSig () [constName] intTy
, HS.FunBind () [HS.Match ()
constName
[]
(HS.UnGuardedRhs () (HS.Lit () (HS.Int () (fromIntegral cval) (show cval))))
Nothing]
]
mkEnums cls = [] -- TODO Not sure what to do about these
methodDoc :: Text -> Maybe D.GodotDocClass -> Maybe CodeComment
methodDoc name mdoc = do
doc <- mdoc
(do
ms <- D.unOption <$> HM.lookup (T.pack "method") (D._gdMethods doc)
docm <- V.find (\e -> e ^. D.name == name) ms
d <- D.alt1 $ docm ^. D.description
preComment (T.unpack $ D.convertDoc d))
<|> (do
mems <- D.unOption <$> (HM.lookup (T.pack "member") =<< D._gdMembers doc)
doc <- V.find (\e -> e ^. D.getter == name || e ^. D.setter == name) mems
d <- doc ^. D.value
preComment (T.unpack $ D.convertDoc d))
mkMethods :: MonadState ClassgenState m => GodotClass -> Maybe D.GodotDocClass -> m [HS.Decl (Maybe CodeComment)]
mkMethods cls mdoc =
concat <$> mapM (\m -> mkMethod cls m (methodDoc (m ^. name) mdoc))
(V.toList $ cls ^. methods)
mkMethod :: MonadState ClassgenState m => GodotClass -> GodotMethod -> Maybe CodeComment -> m [HS.Decl (Maybe CodeComment)]
mkMethod cls method doc = do
mtds <- use methods
if (method ^. name) `S.member` (HM.lookupDefault mempty (cls ^. name) mtds)
then return []
else do
methods %= HM.insertWith S.union (mangleClass $ cls ^. name) (S.singleton $ method ^. name)
when (T.null $ method ^. name) $ error (show cls ++ "\n" ++ show method)
return $
[ noComments $ HS.InlineSig () False Nothing (HS.UnQual () clsMethodBindName)
, HS.TypeSig doc [noComments $ clsMethodBindName]
(noComments $ HS.TyCon () (HS.UnQual () (HS.Ident () "MethodBind")))
, noComments $ HS.PatBind () (HS.PVar () clsMethodBindName) clsMethodBindRhs Nothing
, HS.TypeSig doc [HS.Ident Nothing $ methodName]
(noComments [ty|(((clsName)) :< cls, Object :< cls) => cls -> ((methodSig))|])
, noComments $ HS.FunBind () [HS.Match () (HS.Ident () $ methodName)
((HS.PVar () (HS.Ident () "cls") : map (HS.PVar ()) argNames)
++ if method ^. hasVarargs then
[HS.PVar () (HS.Ident () "varargs")] else
[])
runMethodRhs Nothing]
, let cty = clsTy cls
name = promotedString rawMethodName
args = promotedList $ V.toList methodArgs
ret = toHsType $ method ^. returnType
mname = classModuleName <> "." <> methodName
in noComments $
[dec|instance NodeMethod ((cty)) ((name)) ((args)) (IO ((ret)) ) where nodeMethod = __mname__ |]
]
where
clsName = HS.TyCon () (HS.UnQual () (clsAsName cls))
clsMethodBindName = HS.Ident () $ "bind" ++ (T.unpack $ mangleClass (cls ^. name)) ++ "_" ++ methodName
clsMethodBindVar = HS.Var () $ HS.UnQual () clsMethodBindName
clsMethodBindRhs = HS.UnGuardedRhs ()
[hs| unsafePerformIO $ withCString $(HS.strE (T.unpack $ cls ^. name)) $
\clsNamePtr -> withCString $(HS.strE rawMethodName) $
\methodNamePtr -> godot_method_bind_get_method clsNamePtr methodNamePtr |]
classModuleName = "Godot." ++ (pascal $ T.unpack (cls ^. apiType)) ++ "." ++ (T.unpack $ mangleClass $ cls ^. name)
runMethodRhs = HS.UnGuardedRhs () $ HS.App () (
HS.App ()
(HS.Var () (HS.UnQual () (HS.Ident () "withVariantArray")))
(let a = HS.List () $ zipWith (\a an -> wrapDefault a an) (V.toList $ method ^. arguments) argNames
in if method ^. hasVarargs then
[hs|$a ++ varargs|] else
a))
[hs|
\(arrPtr, len) -> godot_method_bind_call $(clsMethodBindVar) (upcast cls) arrPtr len >>=
\(err, res) -> throwIfErr err >> fromGodotVariant res |]
wrapDefault (GodotArgument _ ty Nothing) v = mkToVariant v
wrapDefault (GodotArgument _ ty (Just d)) v = mkDefault ty d (HS.Var () $ HS.UnQual () v)
mkDefault :: GType -> Text -> HS.Exp () -> HS.Exp ()
mkDefault (PrimitiveType IntType) d v = [hs|maybe (VariantInt (__dt__)) toVariant $v |]
where dt = T.unpack d
mkDefault (PrimitiveType FloatType) d v = [hs|maybe (VariantReal (__dt__)) toVariant $v |]
where dt = T.unpack d
mkDefault (PrimitiveType BoolType) d v = [hs|maybe (VariantBool __dt__) toVariant $v |]
where dt = T.unpack d
mkDefault (CoreType "Color") "1,1,1,1" v = [hs|defaultedVariant VariantColor (withOpacity (sRGB 1 1 1) 1) $v |]
mkDefault (CoreType "Rect2") "(0, 0, 0, 0)" v = [hs|defaultedVariant VariantRect2 (V2 (V2 0 0) (V2 0 0)) $v |]
mkDefault (CoreType "PoolStringArray") "[]" v = [hs|defaultedVariant VariantPoolStringArray V.empty $v |]
mkDefault (CoreType "Dictionary") "{}" v = [hs|defaultedVariant VariantDictionary V.empty $v |]
mkDefault (CoreType "PoolVector2Array") "[]" v = [hs|defaultedVariant VariantPoolVector2Array V.empty $v |]
mkDefault (CoreType "PoolVector3Array") "[]" v = [hs|defaultedVariant VariantPoolVector3Array V.empty $v |]
mkDefault (CoreType "PoolIntArray") "[]" v = [hs|defaultedVariant VariantPoolIntArray V.empty $v |]
mkDefault (CoreType "PoolRealArray") "[]" v = [hs|defaultedVariant VariantPoolRealArray V.empty $v |]
mkDefault (CoreType "PoolColorArray") "[PoolColorArray]" v = [hs|defaultedVariant VariantPoolColorArray V.empty $v |]
mkDefault (CoreType "Array") "[]" v = [hs|defaultedVariant VariantArray V.empty $v |]
mkDefault (CoreType "Vector2") "(-1, -1)" v = [hs|defaultedVariant VariantVector2 (V2 (-1) (-1)) $v |]
mkDefault (CoreType "Vector2") "(0, 0)" v = [hs|defaultedVariant VariantVector2 (V2 0 0) $v |]
mkDefault (CoreType "Vector3") "(0, 0, 0)" v = [hs|defaultedVariant VariantVector3 (V3 0 0 0) $v |]
mkDefault (CoreType "Transform2D") "((1, 0), (0, 1), (0, 0))" v = [hs|defaultedVariant VariantTransform2d (TF2d (V2 1 0) (V2 0 1) (V2 0 0)) $v |]
mkDefault (CoreType "Transform") "1, 0, 0, 0, 1, 0, 0, 0, 1 - 0, 0, 0" v = [hs|defaultedVariant VariantTransform (TF (V3 (V3 1 0 0) (V3 0 1 0) (V3 0 0 1)) (V3 0 0 0)) $v |]
-- TODO Is this right?
mkDefault (CoreType "RID") "[RID]" v = [hs|maybe VariantNil toVariant $v |]
mkDefault (CoreType "String") d v = [hs|defaultedVariant VariantString __dt__ $v |]
where dt = "\"" <> T.unpack d <> "\""
mkDefault _ "Null" v = [hs|maybe VariantNil toVariant $v |]
mkDefault _ "0" v = [hs|maybe (VariantInt 0) toVariant $v |]
mkDefault _ "1" v = [hs|maybe (VariantInt 1) toVariant $v |]
mkDefault _ "[Object:null]" v = [hs|maybe VariantNil toVariant $v |]
mkDefault t d _ = error $ "Don't know how to make defaults for this type (" ++ show t ++ ") for value (" ++ show d ++ ")"
mkToVariant = HS.App () (HS.Var () (HS.UnQual () (HS.Ident () "toVariant"))) . HS.Var () . HS.UnQual ()
argNames = map (HS.Ident () . ("arg" ++) . show) [1..length (method ^. arguments)]
methodSig = foldr (HS.TyFun ()) (HS.TyApp () [ty|IO|] (toHsType $ method ^. returnType)) methodArgs
methodArgs = let args = fmap argToHsType (method ^. arguments)
in if method ^. hasVarargs then
args `V.snoc` [ty|[Variant 'GodotTy]|] else
args
argToHsType (GodotArgument _ ty (Just _)) =
HS.TyApp () (HS.TyCon () $ HS.UnQual () $ HS.Ident () "Maybe") $ toHsType ty
argToHsType (GodotArgument _ ty _) = toHsType ty
rawMethodName = T.unpack $ method ^. name
methodName = toMethodName (method ^. name)
toMethodName name = T.unpack (case name of
"case" -> "case'"
"class" -> "class'"
"data" -> "data'"
"default" -> "default'"
"deriving" -> "deriving'"
"do" -> "do'"
"else" -> "else'"
"forall" -> "forall'"
"if" -> "if'"
"import" -> "import'"
"in" -> "in'"
"infix" -> "infix'"
"infixl" -> "infixl'"
"infixr" -> "infixr'"
"instance" -> "instance'"
"let" -> "let'"
"module" -> "module'"
"newtype" -> "newtype'"
"of" -> "of'"
"qualified" -> "qualified'"
"then" -> "then'"
"type" -> "type'"
"where" -> "where'"
"foreign" -> "foreign'"
"ccall" -> "ccall'"
"as" -> "as'"
"safe" -> "safe'"
"unsafe" -> "unsafe'"
x -> x)
mangleClass "String" = "GodotString"
mangleClass "Variant" = "GodotVariant"
mangleClass c = case T.stripPrefix "_" c of
Nothing -> c
Just x -> x
toHsType :: GType -> HS.Type ()
toHsType (PrimitiveType VoidType) = [ty| () |]
toHsType (PrimitiveType BoolType) = [ty| Bool |]
toHsType (PrimitiveType IntType) = [ty| Int |]
toHsType (PrimitiveType FloatType) = [ty| Float |]
toHsType (CoreType ty) = nameToTyCon $ renameType ty
where
renameType "RID" = "Rid"
renameType "Transform2D" = "Transform2d"
renameType "AABB" = "Aabb"
renameType "String" = "GodotString"
renameType "Variant" = "GodotVariant"
renameType x = mangleClass x
-- NB: Are these bugs in api.json? Why is the type different from anywhere else?
toHsType (CustomType "SpatialMaterial,ShaderMaterial") = nameToTyCon "Material"
toHsType (CustomType "ShaderMaterial,CanvasItemMaterial") = nameToTyCon "Material"
toHsType (CustomType "ShaderMaterial,SpatialMaterial") = nameToTyCon "Material"
toHsType (CustomType "ShaderMaterial,ParticlesMaterial") = nameToTyCon "Material"
toHsType (CustomType ty) = nameToTyCon ty
toHsType (EnumType _) = [ty| Int |]
================================================
FILE: classgen/src-classgen/Classgen/Spec.hs
================================================
{-# LANGUAGE TemplateHaskell, GeneralizedNewtypeDeriving, OverloadedStrings #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Classgen.Spec where
import Control.Applicative
import Control.Lens
import Data.Aeson
import Data.Aeson.TH
import Data.Monoid
import Data.Text (Text)
import qualified Data.Text as T
import Data.Vector (Vector)
import Data.HashMap.Strict (HashMap)
import qualified Data.Set as S
import Text.Casing
import Classgen.Utils
type GodotClasses = Vector GodotClass
newtype Ref a = Ref Text
deriving (Show, Eq, FromJSON, ToJSON)
data GPrimType = VoidType | BoolType | IntType | FloatType
deriving (Show, Eq)
instance FromJSON GPrimType where
parseJSON = withText "primitive type" $ \t ->
case t of
"void" -> pure VoidType
"bool" -> pure BoolType
"int" -> pure IntType
"float" -> pure FloatType
_ -> fail $ "Unknown type" <> T.unpack t
data GType
= PrimitiveType !GPrimType
| CoreType !Text
| CustomType !Text
| EnumType !Text
deriving (Show, Eq)
isCoreType t = t `S.member` S.fromList
[ "AABB",
"Array",
"Basis",
"Color",
"Dictionary",
"GodotError",
"NodePath",
"Plane",
"PoolByteArray",
"PoolIntArray",
"PoolRealArray",
"PoolStringArray",
"PoolVector2Array",
"PoolVector3Array",
"PoolColorArray",
"Object",
"Quat",
"Rect2",
"RID",
"String",
"Transform",
"Transform2D",
"Variant",
"Vector2",
"Vector3" ]
instance FromJSON GType where
parseJSON v = PrimitiveType <$> parseJSON v
<|> withText "type" (\t ->
if isCoreType t
then pure $ CoreType t
else if "enum." `T.isPrefixOf` t
then pure $ EnumType t
else pure $ CustomType t) v
data GodotClass = GodotClass
{ _gcName :: !Text
, _gcBaseClass :: !Text
, _gcApiType :: !Text
, _gcSingleton :: !Bool
, _gcInstanciable :: !Bool
, _gcIsReference :: !Bool
, _gcConstants :: !(HashMap Text Int)
, _gcProperties:: !(Vector GodotProperty)
, _gcSignals :: !(Vector GodotSignal)
, _gcMethods :: !(Vector GodotMethod)
, _gcEnums :: !(Vector GodotEnum)
} deriving (Show, Eq)
data GodotProperty = GodotProperty
{ _gpName :: !Text
, _gcType :: !GType
, _gcGetter :: !Text
, _gcSetter :: !Text
, _gcIndex :: !Int
} deriving (Show, Eq)
data GodotSignal = GodotSignal
{ _gsName :: !Text
, _gsArguments :: !(Vector GodotArgument)
} deriving (Show, Eq)
data GodotArgument = GodotArgument
{ _gaName :: !Text
, _gaType :: !GType
, _gaDefaultValue :: !(Maybe Text)
} deriving (Show, Eq)
instance FromJSON GodotArgument where
parseJSON = withObject "argument" $ \v ->
do
hasDefault <- v .:? "has_default_value"
maybeDefault <- case hasDefault of
Just False -> pure Nothing
_ -> Just <$> v .: "default_value"
GodotArgument
<$> v .: "name"
<*> v .: "type"
<*> pure maybeDefault
data GodotMethod = GodotMethod
{ _gmName :: !Text
, _gmReturnType :: !GType
, _gmIsEditor :: !Bool
, _gmIsNoscript :: !Bool
, _gmIsConst :: !Bool
, _gmIsReverse :: !Bool
, _gmIsVirtual :: !Bool
, _gmHasVarargs :: !Bool
, _gmIsFromScript :: !Bool
, _gmArguments :: !(Vector GodotArgument)
} deriving (Show, Eq)
data GodotEnum = GodotEnum
{ _geName :: !GType
, _geValues :: !(HashMap Text Int)
} deriving (Show, Eq)
makeLensesWith fixedTypeFields ''GodotClass
makeLensesWith fixedTypeFields ''GodotProperty
makeLensesWith fixedTypeFields ''GodotSignal
makeLensesWith fixedTypeFields ''GodotArgument
makeLensesWith fixedTypeFields ''GodotMethod
makeLensesWith fixedTypeFields ''GodotEnum
makePrisms ''GType
makePrisms ''GPrimType
concat <$> mapM (deriveFromJSON defaultOptions { fieldLabelModifier = quietSnake . drop 3 })
[ ''GodotClass
, ''GodotProperty
, ''GodotSignal
, ''GodotMethod
, ''GodotEnum ]
================================================
FILE: classgen/src-classgen/Classgen/Utils.hs
================================================
module Classgen.Utils where
import Control.Lens
import Language.Haskell.TH
fixedTypeFields :: LensRules
fixedTypeFields = defaultFieldRules & lensField .~ (\tyn fs f -> map fixDefName $ abbreviatedNamer tyn fs f)
where
fixDefName (TopName n) = TopName (fixName n)
fixDefName (MethodName c n) = MethodName c (fixName n)
fixName n = mkName $ case nameBase n of
"type" -> "type'"
"id" -> "id'"
"class" -> "class'"
s -> s
================================================
FILE: classgen/stack.yaml
================================================
# This file was automatically generated by 'stack init'
#
# Some commonly used options have been documented as comments in this file.
# For advanced use and comprehensive documentation of the format, please see:
# https://docs.haskellstack.org/en/stable/yaml_configuration/
# Resolver to choose a 'specific' stackage snapshot or a compiler version.
# A snapshot resolver dictates the compiler version and the set of packages
# to be used for project dependencies. For example:
#
# resolver: lts-3.5
# resolver: nightly-2015-09-21
# resolver: ghc-7.10.2
# resolver: ghcjs-0.1.0_ghc-7.10.2
# resolver:
# name: custom-snapshot
# location: "./custom-snapshot.yaml"
# resolver: lts-11.2
resolver: lts-15.4
# User packages to be built.
# Various formats can be used as shown in the example below.
#
# packages:
# - some-directory
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
# - location:
# git: https://github.com/commercialhaskell/stack.git
# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a
# extra-dep: true
# subdirs:
# - auto-update
# - wai
#
# A package marked 'extra-dep: true' will only be built if demanded by a
# non-dependency (i.e. a user package), and its test suites and benchmarks
# will not be run. This is useful for tweaking upstream packages.
packages:
- .
- ../haskell-src-exts-qq
- ../haskell-src-exts-sc
# Dependency packages to be pulled from upstream that are not in the resolver
# (e.g., acme-missiles-0.3)
extra-deps: []
# Override default flag values for local packages and extra-deps
# flags: {}
# Extra package databases containing global packages
# extra-package-dbs: []
# Control whether we use the GHC we find on the path
# system-ghc: true
#
# Require a specific version of stack, using version ranges
# require-stack-version: -any # Default
require-stack-version: ">=1.7"
#
# Override the architecture used by stack, especially useful on Windows
# arch: i386
# arch: x86_64
#
# Extra directories used by stack for building
# extra-include-dirs: [/path/to/dir]
# extra-lib-dirs: [/path/to/dir]
#
# Allow a newer minor version of GHC than the snapshot specifies
# compiler-check: newer-minor
================================================
FILE: default.nix
================================================
{ mkDerivation, aeson, ansi-wl-pprint, base, bytestring, c2hs
, casing, colour, containers, hpack, lens, linear, mtl, parsec
, parsers, stdenv, stm, template-haskell, text
, unordered-containers, vector, rsync, api-json ? null, lib, haskellPackages
}:
let godot-haskell-classgen = haskellPackages.callPackage ./classgen/default.nix { };
modifyGodotApi = lib.optionalString (api-json != null) ''
cd classgen
echo "Running godot-haskell-classgen on path " ${api-json}
godot-haskell-classgen ${api-json}
cd ..
cp -r src src.bak
rsync -a classgen/src/ src/
''; in
mkDerivation {
pname = "godot-haskell";
version = "3.1.0.0";
src = ./.;
libraryHaskellDepends = [
aeson ansi-wl-pprint base bytestring casing colour containers lens
linear mtl parsec parsers stm template-haskell text
unordered-containers vector
];
libraryToolDepends = [ c2hs hpack rsync godot-haskell-classgen];
doHaddock = false;
preConfigure = ''
hpack
${modifyGodotApi}
'';
homepage = "https://github.com/KaneTW/godot-haskell#readme";
description = "Haskell bindings for the Godot game engine API";
license = stdenv.lib.licenses.bsd3;
}
================================================
FILE: examples/dodge-the-creeps/.gitignore
================================================
dist*
*.hi
*.o
.stack-work/
.stack-work-devel/
*~
\#*
*.import
result
================================================
FILE: examples/dodge-the-creeps/ChangeLog.md
================================================
# Empty
================================================
FILE: examples/dodge-the-creeps/LICENSE
================================================
BSD 3-Clause License
Copyright (c) Andrei Barbu 2019
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: examples/dodge-the-creeps/Makefile
================================================
NAME = myproject
STACKLIBFILE = $(shell stack path --local-install-root)/lib/lib$(NAME).so
GODOTPROJECT = $(shell stack path --project-root)/game
all: stack
nix:
nix-build shell.nix
cp result/lib/ghc-*/lib$(NAME).so $(GODOTPROJECT)/lib
stack:
stack build --fast --force-dirty
cp $(STACKLIBFILE) $(GODOTPROJECT)/lib
stack-nix:
stack --nix clean $(NAME)
stack --nix build
cp $(shell stack --nix path --local-install-root)/lib/lib$(NAME).so $(GODOTPROJECT)/lib
stack-run:
stack build
cp $(STACKLIBFILE) $(GODOTPROJECT)/lib
godot -e --path ./game
stack-watch:
stack build --file-watch --fast --exec "cp $(STACKLIBFILE) $(GODOTPROJECT)/lib"
project-watch:
stack exec godot-haskell-project-generator game src
updatelib:
cp $(STACKLIBFILE) $(GODOTPROJECT)/lib
================================================
FILE: examples/dodge-the-creeps/README.md
================================================
The official Godot demo from the manual: Dodge the Creeps.
Run with `make stack` then `godot game/project.godot` and press F5 to start, F8 to end.
Requires Godot 3.1
================================================
FILE: examples/dodge-the-creeps/Support.hs
================================================
{-# LANGUAGE FlexibleContexts, FunctionalDependencies, MultiParamTypeClasses, OverloadedLabels, UndecidableInstances,
OverloadedStrings, TemplateHaskell, TypeApplications, TypeFamilies, DataKinds, TypeOperators, FlexibleInstances #-}
module Generated.Support where
import Godot
import GHC.TypeLits
class SceneNode (scene :: Symbol) (s :: Symbol) where
type SceneNodeType scene s :: *
type SceneNodeName scene s :: Symbol
class NodeInScheme (scene :: Symbol) (s :: Symbol) n | scene s -> n, n -> scene s
================================================
FILE: examples/dodge-the-creeps/ffi/cbits/flib.c
================================================
#include "HsFFI.h"
static void flib_init() __attribute__((constructor));
static void flib_init() {
static char *argv[] = { "libGodotHaskellPlugin.so", 0 }, **argv_ = argv;
static int argc = 1;
hs_init(&argc, &argv_);
}
static void flib_fini() __attribute__((destructor));
static void flib_fini() {
hs_exit();
}
================================================
FILE: examples/dodge-the-creeps/ffi/flib/FLib.hs
================================================
{-# LANGUAGE ForeignFunctionInterface #-}
module FLib where
import qualified Foreign
import Foreign(nullPtr, Ptr,newForeignPtr_,castPtr)
import qualified Godot.Gdnative.Internal as FFI
import Godot.Gdnative
import Godot.Nativescript
import Lib
import qualified Data.Text as T
import qualified Data.Text.IO as T
godot_nativescript_init :: GdnativeHandle -> IO ()
godot_nativescript_init desc = do
defaultExports desc
exports desc
putStrLn "Haskell NativeScript lib initialized"
foreign export ccall godot_nativescript_init :: GdnativeHandle -> IO ()
godot_gdnative_init :: FFI.GdnativeInitOptionsPtr -> IO ()
godot_gdnative_init opts = do
Foreign.peek opts >>= FFI.initApiStructs
foreign export ccall godot_gdnative_init :: FFI.GdnativeInitOptionsPtr -> IO ()
godot_gdnative_terminate :: FFI.GdnativeTerminateOptionsPtr -> IO ()
godot_gdnative_terminate handle = pure ()
foreign export ccall godot_gdnative_terminate :: FFI.GdnativeTerminateOptionsPtr -> IO ()
================================================
FILE: examples/dodge-the-creeps/game/HUD.gdns
================================================
[gd_resource type="NativeScript" load_steps=2 format=2]
[ext_resource path="res://lib/libmyproject.gdnlib" type="GDNativeLibrary" id=1]
[resource]
resource_name = "HUD"
class_name = "HUD"
library = ExtResource( 1 )
================================================
FILE: examples/dodge-the-creeps/game/HUD.tres
================================================
[gd_resource type="DynamicFont" load_steps=2 format=2]
[ext_resource path="res://dodge_assets/fonts/Xolonium-Regular.ttf" type="DynamicFontData" id=1]
[resource]
size = 64
font_data = ExtResource( 1 )
================================================
FILE: examples/dodge-the-creeps/game/HUD.tscn
================================================
[gd_scene load_steps=5 format=2]
[ext_resource path="res://HUD.gdns" type="Script" id=1]
[ext_resource path="res://HUD.tres" type="DynamicFont" id=2]
[sub_resource type="InputEventAction" id=1]
action = "ui_select"
[sub_resource type="ShortCut" id=2]
shortcut = SubResource( 1 )
[node name="HUD" type="CanvasLayer"]
script = ExtResource( 1 )
[node name="ScoreLabel" type="Label" parent="."]
anchor_right = 1.0
margin_bottom = 78.0
custom_fonts/font = ExtResource( 2 )
text = "0"
align = 1
__meta__ = {
"_edit_use_anchors_": false
}
[node name="MessageLabel" type="Label" parent="."]
anchor_top = 0.5
anchor_right = 1.0
anchor_bottom = 0.5
margin_top = -79.5
margin_bottom = 79.5
custom_fonts/font = ExtResource( 2 )
text = "Dodge
the Creeps!"
align = 1
[node name="StartButton" type="Button" parent="."]
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
margin_left = -90.0
margin_top = -200.0
margin_right = 90.0
margin_bottom = -100.0
custom_fonts/font = ExtResource( 2 )
shortcut = SubResource( 2 )
text = "Start"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="MessageTimer" type="Timer" parent="."]
wait_time = 2.0
one_shot = true
[connection signal="pressed" from="StartButton" to="." method="_on_StartButton_pressed"]
[connection signal="timeout" from="MessageTimer" to="." method="_on_MessageTimer_timeout"]
================================================
FILE: examples/dodge-the-creeps/game/Main.gdns
================================================
[gd_resource type="NativeScript" load_steps=2 format=2]
[ext_resource path="res://lib/libmyproject.gdnlib" type="GDNativeLibrary" id=1]
[resource]
class_name = "Main"
library = ExtResource( 1 )
================================================
FILE: examples/dodge-the-creeps/game/Main.tscn
================================================
[gd_scene load_steps=6 format=2]
[ext_resource path="res://Main.gdns" type="Script" id=1]
[ext_resource path="res://Mob.tscn" type="PackedScene" id=2]
[ext_resource path="res://Player.tscn" type="PackedScene" id=3]
[ext_resource path="res://HUD.tscn" type="PackedScene" id=4]
[sub_resource type="Curve2D" id=1]
_data = {
"points": PoolVector2Array( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 480, 0, 0, 0, 0, 0, 480, 720, 0, 0, 0, 0, 0, 720, 0, 0, 0, 0, 0, 0 )
}
[node name="Main" type="Node"]
script = ExtResource( 1 )
PackedScene = ExtResource( 2 )
[node name="ColorRect" type="ColorRect" parent="."]
margin_right = 480.0
margin_bottom = 720.0
color = Color( 0.229564, 0.339542, 0.394531, 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Player" parent="." instance=ExtResource( 3 )]
[node name="MobTimer" type="Timer" parent="."]
wait_time = 0.5
[node name="ScoreTimer" type="Timer" parent="."]
[node name="StartTimer" type="Timer" parent="."]
wait_time = 2.0
one_shot = true
[node name="StartPosition" type="Position2D" parent="."]
position = Vector2( 240, 450 )
[node name="MobPath" type="Path2D" parent="."]
curve = SubResource( 1 )
[node name="MobSpawnLocation" type="PathFollow2D" parent="MobPath"]
[node name="HUD" parent="." instance=ExtResource( 4 )]
[connection signal="hit" from="Player" to="." method="game_over"]
[connection signal="timeout" from="MobTimer" to="." method="_on_MobTimer_timeout"]
[connection signal="timeout" from="ScoreTimer" to="." method="_on_ScoreTimer_timeout"]
[connection signal="timeout" from="StartTimer" to="." method="_on_StartTimer_timeout"]
[connection signal="start_game" from="HUD" to="." method="new_game"]
================================================
FILE: examples/dodge-the-creeps/game/Mob.gdns
================================================
[gd_resource type="NativeScript" load_steps=2 format=2]
[ext_resource path="res://lib/libmyproject.gdnlib" type="GDNativeLibrary" id=1]
[resource]
resource_name = "Mob"
class_name = "Mob"
library = ExtResource( 1 )
================================================
FILE: examples/dodge-the-creeps/game/Mob.tscn
================================================
[gd_scene load_steps=10 format=2]
[ext_resource path="res://Mob.gdns" type="Script" id=1]
[ext_resource path="res://dodge_assets/art/enemyFlyingAlt_1.png" type="Texture" id=2]
[ext_resource path="res://dodge_assets/art/enemyFlyingAlt_2.png" type="Texture" id=3]
[ext_resource path="res://dodge_assets/art/enemyWalking_1.png" type="Texture" id=4]
[ext_resource path="res://dodge_assets/art/enemyWalking_2.png" type="Texture" id=5]
[ext_resource path="res://dodge_assets/art/enemySwimming_1.png" type="Texture" id=6]
[ext_resource path="res://dodge_assets/art/enemySwimming_2.png" type="Texture" id=7]
[sub_resource type="SpriteFrames" id=1]
animations = [ {
"frames": [ ExtResource( 2 ), ExtResource( 3 ) ],
"loop": true,
"name": "fly",
"speed": 3.0
}, {
"frames": [ ExtResource( 4 ), ExtResource( 5 ) ],
"loop": true,
"name": "walk",
"speed": 4.0
}, {
"frames": [ ExtResource( 6 ), ExtResource( 7 ) ],
"loop": true,
"name": "swim",
"speed": 4.0
} ]
[sub_resource type="CapsuleShape2D" id=2]
radius = 36.0297
height = 27.5338
[node name="Mob" type="RigidBody2D"]
collision_mask = 0
gravity_scale = 0.0
script = ExtResource( 1 )
__meta__ = {
"_edit_group_": true
}
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
scale = Vector2( 0.75, 0.75 )
frames = SubResource( 1 )
animation = "swim"
frame = 1
playing = true
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
rotation = 1.5708
shape = SubResource( 2 )
[node name="VisibilityNotifier2D" type="VisibilityNotifier2D" parent="."]
[connection signal="screen_exited" from="VisibilityNotifier2D" to="." method="_on_VisibilityNotifier2D_screen_exited"]
================================================
FILE: examples/dodge-the-creeps/game/Player.gdns
================================================
[gd_resource type="NativeScript" load_steps=2 format=2]
[ext_resource path="res://lib/libmyproject.gdnlib" type="GDNativeLibrary" id=1]
[resource]
resource_name = "Player"
class_name = "Player"
library = ExtResource( 1 )
================================================
FILE: examples/dodge-the-creeps/game/Player.tscn
================================================
[gd_scene load_steps=8 format=2]
[ext_resource path="res://Player.gdns" type="Script" id=1]
[ext_resource path="res://dodge_assets/art/playerGrey_walk1.png" type="Texture" id=2]
[ext_resource path="res://dodge_assets/art/playerGrey_walk2.png" type="Texture" id=3]
[ext_resource path="res://dodge_assets/art/playerGrey_up1.png" type="Texture" id=4]
[ext_resource path="res://dodge_assets/art/playerGrey_up2.png" type="Texture" id=5]
[sub_resource type="SpriteFrames" id=1]
animations = [ {
"frames": [ ExtResource( 2 ), ExtResource( 3 ) ],
"loop": true,
"name": "right",
"speed": 5.0
}, {
"frames": [ ExtResource( 4 ), ExtResource( 5 ) ],
"loop": true,
"name": "up",
"speed": 5.0
} ]
[sub_resource type="CapsuleShape2D" id=2]
radius = 26.892
height = 15.9045
[node name="Player" type="Area2D"]
script = ExtResource( 1 )
__meta__ = {
"_edit_group_": true
}
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
position = Vector2( 0, -1 )
scale = Vector2( 0.5, 0.5 )
frames = SubResource( 1 )
animation = "up"
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource( 2 )
[connection signal="body_entered" from="." to="." method="_on_Player_body_entered"]
================================================
FILE: examples/dodge-the-creeps/game/dodge_assets/fonts/FONTLOG.txt
================================================
Please distribute this file along with the Xolonium fonts when possible.
Source
Find the sourcefiles of Xolonium at
<gitlab.com/sev/xolonium>
Credits
Xolonium is created with FontForge <fontforge.org>,
Inkscape <inkscape.org>, Python <python.org>, and
FontTools <github.com/fonttools>.
It originated as a custom font for the open-source
game Xonotic <xonotic.org>. With many thanks to the
Xonotic community for your support.
Supported OpenType features
case Provides case sensitive placement of punctuation,
brackets, and math symbols for uppercase text.
frac Replaces number/number sequences with diagonal fractions.
Numbers that touch a slash should not exceed 10 digits.
kern Provides kerning for Latin, Greek, and Cyrillic scripts.
locl Dutch: Replaces j with a stressed version if it follows í.
Sami: Replaces n-form Eng with the preferred N-form version.
Romanian and Moldovan: Replaces ŞşŢţ with the preferred ȘșȚț.
pnum Replaces monospaced digits with proportional versions.
sinf Replaces digits with scientific inferiors below the baseline.
subs Replaces digits with subscript versions on the baseline.
sups Replaces digits with superscript versions.
zero Replaces zero with a slashed version.
Supported glyph sets
Adobe Latin 3
OpenType W1G
ISO 8859-1 Western European
ISO 8859-2 Central European
ISO 8859-3 South European
ISO 8859-4 North European
ISO 8859-5 Cyrillic
ISO 8859-7 Greek
ISO 8859-9 Turkish
ISO 8859-10 Nordic
ISO 8859-13 Baltic Rim
ISO 8859-14 Celtic
ISO 8859-15 Western European
ISO 8859-16 South-Eastern European
Available glyphs
!"#$%&'()*+,-./0123456789:;<=>?
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
`abcdefghijklmnopqrstuvwxyz{|}~
¡¢£¤¥¦§¨©ª«¬ ®¯°±²³´µ¶·¸¹º»¼½¾¿
ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞß
àáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
ĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğ
ĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľ
ĿŀŁłŃńŅņŇňŊŋŌōŎŏŐőŒœŔŕŖŗŘřŚśŜŝŞş
ŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽž
ƒǺǻǼǽǾǿȘșȚțȷ
ˆˇˉ˘˙˚˛˜˝
ͺ;΄΅Ά·ΈΉΊΌΎΏΐ
ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫάέήίΰ
αβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ
ЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБВГДЕЖЗИЙКЛМНОП
РСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп
рстуфхцчшщъыьэюяѐёђѓєѕіїјљњћќѝўџ
ѢѣѲѳѴѵҐґҒғҔҕҖҗҘҙҚқҜҝҞҟҠҡҢңҤҥҦҧҨҩ
ҪҫҬҭҮүҰұҲҳҴҵҶҷҸҹҺһҼҽӀӁӂӇӈӋӌӏӐӑӒӓ
ӔӕӖӗӘәӜӝӞӟӠӡӢӣӤӥӦӧӨөӮӯӰӱӲӳӴӵӶӷӸӹ
Ԥԥ
ḂḃḊḋḞḟṀṁṖṗṠṡṪṫẀẁẂẃẄẅẞỲỳ
‒–—―‘’‚‛“”„‟†‡•…‰′″‹›‽‾⁄
⁰⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾ⁿ₀₁₂₃₄₅₆₇₈₉₊₋₌₍₎
₤₦₩₫€₯₱₹₺₽₿
℅ℓ№℗™Ω℮
⅛⅜⅝⅞
←↑→↓
∂∆∏∑−∕∙√∞∟∫≈≠≤≥
⌖
■▬▮▰▲▶▼◀◆◊●◢◣◤◥
☄★☠☢☣⚙⚛⚠⚡⛔
❇❈❌❤❰❱❲❳
fffiflffiffl
🌌🌍🌎🌏👽💣🔥🔫
😁😃😄😆😇😈😉😊😎😐😒😕😘
😛😝😞😟😠😣😭😮😲😴😵
🚀
Debugging glyphs
U+EFFD Font version
U+F000 Font hinting indicator
Changelog
Xolonium 4.1 2016-11-22 Severin Meyer <sev.ch@web.de>
Reverted frac OpenType feature to a more stable implementation
Xolonium 4.0 2016-10-08 Severin Meyer <sev.ch@web.de>
Decreased width of most glyphs
Thinner vertical stems in Xolonium-Regular
Thicker horizontal stems in Xolonium-Bold
Revised diagonal stems
Lowered middle bars
Revised diacritical bars
Added glyphs:
ӏẞ₿
U+2007 U+2008 U+2009 U+200A U+202F
U+EFFD U+F000
Revised glyphs:
$&,JKQRXkwxy~¢¤ßǻ˜ζκλμξφЖУжћѴѵ∕₱₺₦₩€ℓ№≈ffffiffl
❤🌍🌎🌏😁😄😇😈😉😊😘😭😮😴🚀
Removed uncommon glyphs:
ʼnſʼҌҍҎҏҾҿӃӄӇӈӚӛӪӫӬӭ
U+0312 U+0313 U+0326
Simplified OpenType features pnum, zero, and case
Removed OpenType feature dlig
Revised vertical metrics
Merged outlines of composite glyphs in otf version
Added ttf version with custom outlines and instructions
Added woff and woff2 version
Xolonium 3.1 2015-06-10 Severin Meyer <sev.ch@web.de>
Added currency glyphs:
₦₩₫₱₹₺₽
Revised glyph:
₯
Relicensed public release under the SIL Open Font License 1.1
Xolonium 3.0 2015-05-04 Severin Meyer <sev.ch@web.de>
Decreased width of glyphs
Decreased descender height
Increased height of super/subscript glyphs
Revised width of dashes, underscore, and overscore
Sharper bends with more circular proportions
Decreased stroke thickness of mathematical glyphs
Revised diacritical marks
Revised diacritical bars
Revised Cyrillic hooks
Revised glyphs:
GQRYjmuwßŊŒſƒǻfffiffiffl
ΞΨΩδζιξπςστυφω
ЉЄДЛУЭЯбдлэяєљђєћѢѣҨҩҼҽӃӄӘә
#$&'()*,/69?@[]{}~¡£¤¥§©®¿
‹›₤€₯ℓ№℗℮←↑→↓∂∏∑∞≈▰☄❈❰❱❲❳😝
Raised vertical position of mathematical glyphs
Unified advance width of numeral and monetary glyphs
Unified advance width of mathematical glyphs
Revised bearings
Rewrote kern feature
Bolder Xolonium-Bold with improved proportions
Updated glyph names to conform to the AGLFN 1.7
Revised hints and PS Private Dictionary
Added glyphs:
ӶӷԤԥ
Added OpenType features:
case frac liga locl pnum sinf subs sups zero
Xolonium 2.4 2014-12-23 Severin Meyer <sev.ch@web.de>
Added dingbats:
⛔💣🔥
Revised size and design of emoticons
Revised dingbats:
⌖☄☠☣⚙⚛⚠⚡❇❈🌌🌍🌎🌏🔫
Removed dingbat:
💥
Xolonium 2.3 2014-08-14 Severin Meyer <sev.ch@web.de>
Bugfixed ε and έ, thanks to bowzee for the feedback
Xolonium 2.2 2014-03-01 Severin Meyer <sev.ch@web.de>
Added dingbats:
⌖◆●❌💥
Revised dingbats:
•←↑→↓◊☄★☠☣⚙⚛⚠⚡❇❈❤🌌🌍🌎🌏👽🔫🚀
Removed dingbats:
♻✪💡📡🔋🔧🔭
Xolonium 2.1 2013-10-20 Severin Meyer <sev.ch@web.de>
Added dingbats:
←↑→↓❰❱❲❳■▬▮▰▲▶▼◀◢◣◤◥
☄★☠☢☣♻⚙⚛⚠⚡✪❇❈❤
🌌🌍🌎🌏👽💡📡🔋🔧🔫🔭🚀
😁😃😄😆😇😈😉😊😎😐😒😕
😘😛😝😞😟😠😣😭😮😲😴😵
Xolonium 2.0.1 2013-07-12 Severin Meyer <sev.ch@web.de>
Reorganised and simplified files
Xolonium 2.0 2012-08-11 Severin Meyer <sev.ch@web.de>
Revised bends
Revised thickness of uppercase diagonal stems
Revised diacritical marks
Revised hints and PS Private Dictionary
Revised glyphs:
*1469@DPRly{}§©®¶ÐÞƒΘΞαεζνξνυЄЉЊ
ЏБЗЛУЧЪЫЬЭЯбзлчъыьэяєљњџ•€∂∙√∞∫≠
Completed glyph sets:
Adobe Latin 3
OpenType World Glyph Set 1 (W1G)
Ghostscript Standard (ghostscript-fonts-std-8.11)
Added OpenType kern feature
Added Xolonium-Bold
Xolonium 1.2 2011-02-12 Severin Meyer <sev.ch@web.de>
Revised glyphs:
D·Ðı
Completed glyph sets:
ISO 8859-7 (Greek)
Unicode Latin Extended-A block
Added glyphs:
†‡•…‰⁄™∂∑−√∞≠≤≥
Xolonium 1.1 2011-01-17 Severin Meyer <sev.ch@web.de>
Revised placement of cedilla and ogonek in accented glyphs
Revised glyphs:
,;DKTjkvwxy¥§Ð˛€
Completed glyph sets:
ISO 8859-2 (Central European)
ISO 8859-3 (South European, Esperanto)
ISO 8859-4 (North European)
ISO 8859-5 (Cyrillic)
ISO 8859-9 (Turkish)
ISO 8859-10 (Nordic)
ISO 8859-13 (Baltic Rim)
ISO 8859-14 (Celtic)
ISO 8859-16 (South-Eastern European)
Added glyphs:
ȷʼ̒ ЀЍѐѝ‒–—‘’‚‛“”„‟‹›
Xolonium 1.0 2011-01-04 Severin Meyer <sev.ch@web.de>
Completed glyph sets:
ISO 8859-1 (Western European)
ISO 8859-15 (Western European)
Added glyphs:
ĄĆĘŁŃŚŹŻąćęłńśźżıˆˇ˙˚˛˜
================================================
FILE: examples/dodge-the-creeps/game/dodge_assets/fonts/LICENSE.txt
================================================
Copyright 2011-2016 Severin Meyer <sev.ch@web.de>,
with Reserved Font Name Xolonium.
This Font Software is licensed under the SIL Open Font License,
Version 1.1. This license is copied below, and is also available
with a FAQ at <http://scripts.sil.org/OFL>
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
================================================
FILE: examples/dodge-the-creeps/game/lib/libmyproject.gdnlib
================================================
[general]
singleton=false
load_once=true
symbol_prefix="godot_"
reloadable=false
[entry]
X11.64="res://lib/libmyproject.so"
================================================
FILE: examples/dodge-the-creeps/game/project.godot
================================================
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=4
_global_script_classes=[ ]
_global_script_class_icons={
}
[application]
config/name="myproject"
run/main_scene="res://Main.tscn"
[audio]
default_bus_layout=""
[display]
window/size/width=480
window/size/height=720
[gdnative]
singletons=[ ]
================================================
FILE: examples/dodge-the-creeps/godot-haskell.nix
================================================
{ fetchFromGitHub, mkDerivation, aeson, ansi-wl-pprint, base, bytestring, c2hs
, casing, colour, containers, hpack, lens, linear, mtl, parsec
, parsers, stdenv, stm, template-haskell, text
, unordered-containers, vector
}:
mkDerivation {
pname = "godot-haskell";
version = "3.1.0.0";
src = fetchFromGitHub {
owner = "SimulaVR";
repo = "godot-haskell";
rev = "b423d4f2fa5a6a3dcfffb82bb36be571adb29d34"; # godot-haskell rev
# Use nix-prefetch-git to get the hash
sha256 = "0jh2j5rr90dqdxvcipygwnhhj7j2dj4zvm6gbdpg106ll60pyqrp";
fetchSubmodules = true;
};
libraryHaskellDepends = [
aeson ansi-wl-pprint base bytestring casing colour containers lens
linear mtl parsec parsers stm template-haskell text
unordered-containers vector
];
libraryToolDepends = [ c2hs hpack ];
doHaddock = false;
preConfigure = "hpack";
homepage = "https://github.com/KaneTW/godot-haskell#readme";
description = "Haskell bindings for the Godot game engine API";
license = stdenv.lib.licenses.bsd3;
}
================================================
FILE: examples/dodge-the-creeps/hie.yaml
================================================
cradle:
stack:
- path: "./src"
component: "myproject:lib"
- path: "./game"
component: "myproject:lib"
================================================
FILE: examples/dodge-the-creeps/myproject.cabal
================================================
cabal-version: 1.12
-- This file has been generated from package.yaml by hpack version 0.33.0.
--
-- see: https://github.com/sol/hpack
--
-- hash: 98269f1144e3857ceb0d2b7a1ec2c981a99768d91b04e6febe2406912eda49b8
name: myproject
version: 0.0.0.0
description: Please see the README on Github at <https://github.com/SimulaVR/godot-haskell/tree/master/demo#readme>
homepage: https://github.com/SimulaVR/godot-haskell#readme
bug-reports: https://github.com/SimulaVR/godot-haskell/issues
author: Andrei Barbu
maintainer: andrei@0xab.com
copyright: Andrei Barbu 2019, 2021
license: BSD3
license-file: LICENSE
build-type: Simple
extra-source-files:
ChangeLog.md
README.md
foreign-library myproject
type: native-shared
other-modules: FLib
hs-source-dirs: ffi/flib
c-sources: ffi/cbits/flib.c
build-depends:
base >= 4.12 && <5
, godot-haskell
, myproject
, text
default-language: Haskell2010
source-repository head
type: git
location: https://github.com/SimulaVR/godot-haskell
library
exposed-modules:
Lib
other-modules:
Game.HUD
Game.Main
Game.Mob
Game.Player
Project.Requirements
Project.Scenes
Project.Scenes.HUD
Project.Scenes.Main
Project.Scenes.Mob
Project.Scenes.Player
Project.Support
Paths_myproject
hs-source-dirs:
src
game
default-extensions: FlexibleContexts MultiParamTypeClasses OverloadedStrings TemplateHaskell TypeApplications TypeFamilies DataKinds FlexibleInstances ScopedTypeVariables AllowAmbiguousTypes TupleSections FunctionalDependencies
ghc-options: -Wall -Wno-orphans -O0
build-depends:
base >=4.12 && <5
, containers
, extra
, godot-haskell
, lens
, linear
, random
, strict-concurrency
, template-haskell
, text
, th-abstraction
, vector
default-language: Haskell2010
================================================
FILE: examples/dodge-the-creeps/package.yaml
================================================
name: myproject
version: '0.0.0.0'
description: Please see the README on Github at <https://github.com/SimulaVR/godot-haskell/tree/master/demo#readme>
author: Andrei Barbu
maintainer: andrei@0xab.com
copyright: Andrei Barbu 2019, 2021
license: BSD3
github: SimulaVR/godot-haskell
extra-source-files:
- ChangeLog.md
- README.md
dependencies:
- base >=4.12 && <5
- godot-haskell
- linear
- random
- text
- vector
- strict-concurrency
- lens
- template-haskell
- th-abstraction
- containers
- extra
library:
source-dirs:
- src
- game
default-extensions:
- FlexibleContexts
- MultiParamTypeClasses
- OverloadedStrings
- TemplateHaskell
- TypeApplications
- TypeFamilies
- DataKinds
- FlexibleInstances
- ScopedTypeVariables
- AllowAmbiguousTypes
- TupleSections
- FunctionalDependencies
exposed-modules:
- Lib
ghc-options: -Wall -Wno-orphans -O0
verbatim: |
foreign-library myproject
type: native-shared
other-modules: FLib
hs-source-dirs: ffi/flib
c-sources: ffi/cbits/flib.c
build-depends:
base >= 4.12 && <5
, godot-haskell
, myproject
, text
default-language: Haskell2010
================================================
FILE: examples/dodge-the-creeps/pinned-nixpkgs.nix
================================================
{}:
let
# 19.03-beta (25 feb)
rev = "0c0954781e257b8b0dc49341795a2fe7d96945a3"; # pinned-nixpkgs rev
pkgs = import (builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
}) {};
in
pkgs
================================================
FILE: examples/dodge-the-creeps/shell.nix
================================================
{ nixpkgs ? import ./pinned-nixpkgs.nix {}
, compiler ? "default"
, doBenchmark ? false }:
let
inherit (nixpkgs) pkgs;
haskellPackages = if compiler == "default"
then pkgs.haskellPackages
else pkgs.haskell.packages.${compiler};
f = { mkDerivation, stdenv, base, godot-haskell, linear, text , vector, stm }:
mkDerivation {
pname = "myproject";
version = "3.1.0.0";
src = ./.;
libraryHaskellDepends = [
base godot-haskell linear text vector stm
];
libraryToolDepends = [];
homepage = "https://github.com/abarbu/myproject#readme";
license = stdenv.lib.licenses.bsd3;
};
variant = if doBenchmark then pkgs.haskell.lib.doBenchmark else pkgs.lib.id;
drv = variant (haskellPackages.callPackage f {
godot-haskell = haskellPackages.callPackage ./godot-haskell.nix {fetchFromGitHub = pkgs.fetchFromGitHub;};
});
in
if pkgs.lib.inNixShell then drv.env else drv
================================================
FILE: examples/dodge-the-creeps/src/Game/HUD.hs
================================================
module Game.HUD where
import Control.Lens
import Control.Monad
import qualified Data.Text as T
import Godot
import Godot.Core.CanvasItem as CanvasItem
import Godot.Core.Label as Label
import Godot.Core.Timer as Timer
import Project.Support
import Project.Scenes.HUD()
data HUD = HUD { _hBase :: CanvasLayer }
instance NodeInit HUD where
init = pure . HUD
instance NodeMethod HUD "_on_MessageTimer_timeout" '[] (IO ()) where
nodeMethod self = getNode' @"MessageLabel" self >>= CanvasItem.hide
instance NodeMethod HUD "_on_StartButton_pressed" '[] (IO ()) where
nodeMethod self = do
getNode' @"StartButton" self >>= CanvasItem.hide
emit_signal' @"start_game" self []
instance NodeMethod HUD "show_message" '[GodotString] (IO ()) where
nodeMethod = show_message
instance NodeMethod HUD "show_game_over" '[] (IO ()) where
nodeMethod = show_game_over
instance NodeMethod HUD "update_score" '[Int] (IO ()) where
nodeMethod = update_score
instance NodeSignal HUD "start_game" '[]
show_message :: HUD -> GodotString -> IO ()
show_message self text = do
messageLabel <- getNode' @"MessageLabel" self
set_text messageLabel text
CanvasItem.show messageLabel
getNode' @"MessageTimer" self >>= (`Timer.start` Nothing)
show_game_over :: HUD -> IO ()
show_game_over self = do
show_message self =<< toLowLevel "Game Over"
await' @"MessageTimer" @"timeout" self $ \self' -> do
messageLabel <- getNode' @"MessageLabel" self'
set_text messageLabel =<< toLowLevel "Dodge the\nCreeps!"
CanvasItem.show messageLabel
getNode' @"StartButton" self' >>= CanvasItem.show
pure ()
update_score :: HUD -> Int -> IO ()
update_score self score = do
set_text
<$> getNode' @"ScoreLabel" self
<*> toLowLevel (T.pack $ Prelude.show score)
& join
setupNode ''HUD "HUD" "HUD"
deriveBase ''HUD
================================================
FILE: examples/dodge-the-creeps/src/Game/Main.hs
================================================
module Game.Main where
import Control.Lens
import Control.Monad
import Foreign.C.Types
import Godot
import Godot.Core.Node as Node
import Godot.Core.Node2D as Node2D
import Godot.Core.Object as Object
import Godot.Core.PackedScene as PackedScene
import Godot.Core.PathFollow2D as PathFollow2D
import Godot.Core.RigidBody2D as RigidBody2D
import Godot.Core.Timer as Timer
import Godot.Gdnative
import Linear.V2
import System.Random
import Project.Support
import Project.Scenes.Main()
import Game.HUD
import Game.Mob
import Game.Player()
data Main = Main
{ _base :: Node
, _score :: MVar Int
, _mobScene :: MVar PackedScene
}
makeFieldsNoPrefix ''Main
instance NodeInit Main where
init b = Main b <$> newMVar 0 <*> newEmptyMVar
instance NodeMethod Main "_on_MobTimer_timeout" '[] (IO ()) where
nodeMethod = on_MobTimer_timeout
instance NodeMethod Main "_on_StartTimer_timeout" '[] (IO ()) where
nodeMethod = on_StartTimer_timeout
instance NodeMethod Main "_on_ScoreTimer_timeout" '[] (IO ()) where
nodeMethod = on_ScoreTimer_timeout
instance NodeMethod Main "game_over" '[] (IO ()) where
nodeMethod = game_over
instance NodeMethod Main "new_game" '[] (IO ()) where
nodeMethod = new_game
instance NodeProperty Main "PackedScene" PackedScene 'False where
nodeProperty = createMVarProperty' "PackedScene" _mobScene (Left VariantTypeObject)
game_over :: Main -> IO ()
game_over self = do
getNode' @"ScoreTimer" self >>= Timer.stop
getNode' @"MobTimer" self >>= Timer.stop
getNodeNativeScript' @"HUD" self >>= show_game_over & void
new_game :: Main -> IO ()
new_game self = do
void $ swapMVar (self ^. score) 0
position <- getNode' @"StartPosition" self >>= get_position
void $ call
<$> getNodeNativeScript' @"Player" self
<*> toLowLevel "_start"
<*> pure [toVariant position]
& join
getNode' @"StartTimer" self >>= start `flip` Nothing
hud <- getNodeNativeScript' @"HUD" self
update_score hud 0
show_message hud =<< toLowLevel "Get Ready!"
on_StartTimer_timeout :: Main -> IO ()
on_StartTimer_timeout self = do
getNode' @"MobTimer" self >>= start `flip` Nothing
getNode' @"ScoreTimer" self >>= start `flip` Nothing
on_ScoreTimer_timeout :: Main -> IO ()
on_ScoreTimer_timeout self = do
modifyMVar_ (self ^. score) (pure . (+) 1)
update_score
<$> getNodeNativeScript' @"HUD" self
<*> readMVar (self ^. score)
& join
on_MobTimer_timeout :: Main -> IO ()
on_MobTimer_timeout self@(Main _ _ mobScene_) = do
-- Choose a random location on Path2D.
mobSpawnLoc <- getNode' @"MobPath/MobSpawnLocation" self
PathFollow2D.set_offset mobSpawnLoc . fromInteger =<< randomIO
-- Create a Mob instance and add it to the scene.
mob :: Mob <- readMVar mobScene_
>>= (`PackedScene.instance'` Just 0)
>>= (asNativeScript . upcast)
>>= maybe (error "Couldn't cast mob to NativeScript") pure
add_child self (upcast mob) (Just False)
-- Set the mob's direction perpendicular to the path direction.
direction <- get_rotation mobSpawnLoc <&> (+ pi / 2)
-- Set the mob's position to a random location.
Node2D.set_position mob =<< get_position mobSpawnLoc
-- Add some randomness to the direction.
direction' <- (direction +) <$> randomRIO ((-pi) / 4, pi / 4)
set_rotation mob direction'
-- Set the velocity' (speed & direction).
liftM2 (,) (readMVar $ _mMinSpeed mob) (readMVar $ _mMaxSpeed mob)
>>= randomRIO
>>= (\x -> toLowLevel (V2 x 0))
>>= (`godot_vector2_rotated` CFloat direction')
>>= set_linear_velocity mob
setupNode ''Main "Main" "Main"
deriveBase ''Main
================================================
FILE: examples/dodge-the-creeps/src/Game/Mob.hs
================================================
module Game.Mob where
import Godot
import Godot.Core.AnimatedSprite as AnimatedSprite
import Godot.Core.Node as Node
import System.Random
import Project.Support
import Project.Scenes.Mob()
data Mob = Mob
{ _mBase :: RigidBody2D
, _mMinSpeed :: MVar Float
, _mMaxSpeed :: MVar Float
, _mMobTypes :: MVar [Text]
}
instance NodeInit Mob where
init base = Mob base <$> newMVar 150 <*> newMVar 250 <*> newMVar ["walk", "swim", "fly"]
instance NodeMethod Mob "_ready" '[] (IO ()) where
nodeMethod self = do
let randElem xs = (xs !!) <$> randomRIO (0, length xs - 1)
randAnim <- readMVar (_mMobTypes self) >>= randElem >>= toLowLevel
getNode' @"AnimatedSprite" self >>= (`set_animation` randAnim)
instance NodeMethod Mob "_on_VisibilityNotifier2D_screen_exited" '[] (IO ()) where
nodeMethod = queue_free
setupNode ''Mob "Mob" "Mob"
deriveBase ''Mob
================================================
FILE: examples/dodge-the-creeps/src/Game/Player.hs
================================================
module Game.Player where
import Control.Lens
import Control.Monad
import Godot
import Godot.Core.AnimatedSprite as AnimatedSprite
import Godot.Core.CanvasItem as CanvasItem
import Godot.Core.CollisionShape2D as CollisionShape2D
import Godot.Core.Input as Input
import Godot.Core.Node2D as Node2D
import Godot.Core.Object as Object
import Godot.Gdnative
import Linear.Metric (normalize)
import Linear.V2
import Linear.Vector
import Project.Support
import Project.Scenes.Player()
data Player = Player
{ _pBase :: Area2D
, _pSpeed :: MVar Float
, _pScreenSize :: MVar (V2 Float)
}
instance NodeInit Player where
init base = Player base <$> newMVar 400 <*> newMVar zero
instance NodeMethod Player "_ready" '[] (IO ()) where
nodeMethod = player_ready
instance NodeMethod Player "_process" '[Float] (IO ()) where
nodeMethod = player_process
instance NodeMethod Player "_start" '[Vector2] (IO ()) where
nodeMethod = player_start
instance NodeMethod Player "_on_Player_body_entered" '[Node] (IO ()) where
nodeMethod self _body = do
hide self -- Player disappears after being hit.
emit_signal' @"hit" self []
getNode' @"CollisionShape2D" self >>= \cSh -> do
disable <- toLowLevel "set_disabled"
call_deferred cSh disable [VariantBool True]
instance NodeProperty Player "Player" Float 'False where
nodeProperty = createMVarProperty' "Player" _pSpeed (Right 400)
instance NodeSignal Player "hit" '[]
player_ready :: Player -> IO ()
player_ready self = do
screenRect <- get_viewport_rect self >>= fromLowLevel
void $ swapMVar (_pScreenSize self) (screenRect ^. _y)
hide self
player_start :: Player -> Vector2 -> IO ()
player_start self pos = do
set_position self pos
CanvasItem.show self
getNode' @"CollisionShape2D" self >>= (`set_disabled` False)
player_process :: Player -> Float -> IO ()
player_process self delta = do
animSprite <- getNode' @"AnimatedSprite" self
screenSize <- get_viewport_rect self >>= fromLowLevel <&> (^. _y)
[left, right, up, down] <- do
Just inp <- getSingleton @Input
let isActionPressed = is_action_pressed inp <=< toLowLevel
mapM isActionPressed ["ui_left", "ui_right", "ui_up", "ui_down"]
let velocity =
let bVal b v = if b then v else 0
in V2 (bVal left (-1) + bVal right 1) (bVal up (-1) + bVal down 1)
if velocity /= zero
then do
speed <- readMVar (_pSpeed self)
pos <- get_position self >>= fromLowLevel
let velocity' = normalize velocity ^* speed
pos' = pos + velocity' ^* delta
clamp v a b = max a (min b v)
newPos =
let posX = clamp (pos' ^. _x) 0 (screenSize ^. _x)
posY = clamp (pos' ^. _y) 0 (screenSize ^. _y)
in V2 posX posY
set_position self =<< toLowLevel newPos
animationName <- toLowLevel ""
play animSprite (Just animationName) Nothing
if velocity' ^. _x /= 0
then do
set_animation animSprite =<< toLowLevel "right"
-- official demo sets flip_v to false but this is better
set_flip_v animSprite (velocity' ^. _y > 0)
set_flip_h animSprite (velocity' ^. _x < 0)
else when (velocity' ^. _y /= 0) $ do
set_animation animSprite =<< toLowLevel "up"
set_flip_v animSprite (velocity' ^. _y > 0)
else stop animSprite
setupNode ''Player "Player" "Player"
deriveBase ''Player
================================================
FILE: examples/dodge-the-creeps/src/Lib.hs
================================================
module Lib (exports) where
import Godot
import Game.Mob
import Game.Main
import Game.Player
import Game.HUD
import Project.Support
import Project.Requirements
exports :: GdnativeHandle -> IO ()
exports = registerAll' @Nodes @'[HUD, Main, Mob, Player]
================================================
FILE: examples/dodge-the-creeps/src/Project/Requirements.hs
================================================
-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT
module Project.Requirements where
import Project.Support
type Nodes = '[OneResourceNode "HUD" "HUD", OneResourceNode "Main" "Main", OneResourceNode "Mob" "Mob", OneResourceNode "Player" "Player"]
================================================
FILE: examples/dodge-the-creeps/src/Project/Scenes/HUD.hs
================================================
-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT
{-# LANGUAGE FlexibleContexts, FunctionalDependencies, MultiParamTypeClasses,
UndecidableInstances, OverloadedStrings, TemplateHaskell, TypeApplications,
TypeFamilies, DataKinds, TypeOperators, FlexibleInstances, RankNTypes,
AllowAmbiguousTypes, ScopedTypeVariables, DerivingStrategies,
GeneralizedNewtypeDeriving, LambdaCase #-}
module Project.Scenes.HUD where
import Project.Support
import Godot
import GHC.TypeLits
import Godot.Core.CanvasLayer()
import Godot.Core.Label()
import Godot.Core.Timer()
import Godot.Core.Button()
instance SceneResourcePath "HUD" where
sceneResourcePath = "res://HUD.tscn"
instance SceneRoot "HUD" where
type SceneRootNode "HUD" = "HUD"
instance SceneNode "HUD" "HUD" where
type SceneNodeType "HUD" "HUD" = CanvasLayer
type SceneNodeName "HUD" "HUD" = "HUD"
type SceneNodeIsHaskell "HUD" "HUD" = 'Just '("HUD", "HUD")
instance SceneNode "HUD" "MessageLabel" where
type SceneNodeType "HUD" "MessageLabel" = Label
type SceneNodeName "HUD" "MessageLabel" = "MessageLabel"
type SceneNodeIsHaskell "HUD" "MessageLabel" = 'Nothing
instance SceneNode "HUD" "MessageTimer" where
type SceneNodeType "HUD" "MessageTimer" = Timer
type SceneNodeName "HUD" "MessageTimer" = "MessageTimer"
type SceneNodeIsHaskell "HUD" "MessageTimer" = 'Nothing
instance SceneNode "HUD" "ScoreLabel" where
type SceneNodeType "HUD" "ScoreLabel" = Label
type SceneNodeName "HUD" "ScoreLabel" = "ScoreLabel"
type SceneNodeIsHaskell "HUD" "ScoreLabel" = 'Nothing
instance SceneNode "HUD" "StartButton" where
type SceneNodeType "HUD" "StartButton" = Button
type SceneNodeName "HUD" "StartButton" = "StartButton"
type SceneNodeIsHaskell "HUD" "StartButton" = 'Nothing
instance SceneConnection "HUD" "MessageTimer" "timeout" "HUD" "_on_MessageTimer_timeout"
instance SceneConnection "HUD" "StartButton" "pressed" "HUD" "_on_StartButton_pressed"
================================================
FILE: examples/dodge-the-creeps/src/Project/Scenes/Main.hs
================================================
-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT
{-# LANGUAGE FlexibleContexts, FunctionalDependencies, MultiParamTypeClasses,
UndecidableInstances, OverloadedStrings, TemplateHaskell, TypeApplications,
TypeFamilies, DataKinds, TypeOperators, FlexibleInstances, RankNTypes,
AllowAmbiguousTypes, ScopedTypeVariables, DerivingStrategies,
GeneralizedNewtypeDeriving, LambdaCase #-}
module Project.Scenes.Main where
import Project.Support
import Godot
import GHC.TypeLits
import Godot.Core.ColorRect()
import Godot.Core.PackedScene()
import Godot.Core.Node()
import Godot.Core.Path2D()
import Godot.Core.PathFollow2D()
import Godot.Core.Timer()
import Godot.Core.Position2D()
instance SceneResourcePath "Main" where
sceneResourcePath = "res://Main.tscn"
instance SceneRoot "Main" where
type SceneRootNode "Main" = "Main"
instance SceneNode "Main" "ColorRect" where
type SceneNodeType "Main" "ColorRect" = ColorRect
type SceneNodeName "Main" "ColorRect" = "ColorRect"
type SceneNodeIsHaskell "Main" "ColorRect" = 'Nothing
instance SceneNode "Main" "HUD" where
type SceneNodeType "Main" "HUD" = PackedScene' "HUD"
type SceneNodeName "Main" "HUD" = "HUD"
type SceneNodeIsHaskell "Main" "HUD" = 'Just '("HUD", "HUD")
instance SceneNode "Main" "Main" where
type SceneNodeType "Main" "Main" = Node
type SceneNodeName "Main" "Main" = "Main"
type SceneNodeIsHaskell "Main" "Main" = 'Just '("Main", "Main")
instance SceneNode "Main" "MobPath" where
type SceneNodeType "Main" "MobPath" = Path2D
type SceneNodeName "Main" "MobPath" = "MobPath"
type SceneNodeIsHaskell "Main" "MobPath" = 'Nothing
instance SceneNode "Main" "MobPath/MobSpawnLocation" where
type SceneNodeType "Main" "MobPath/MobSpawnLocation" = PathFollow2D
type SceneNodeName "Main" "MobPath/MobSpawnLocation" = "MobSpawnLocation"
type SceneNodeIsHaskell "Main" "MobPath/MobSpawnLocation" = 'Nothing
instance SceneNode "Main" "MobTimer" where
type SceneNodeType "Main" "MobTimer" = Timer
type SceneNodeName "Main" "MobTimer" = "MobTimer"
type SceneNodeIsHaskell "Main" "MobTimer" = 'Nothing
instance SceneNode "Main" "Player" where
type SceneNodeType "Main" "Player" = PackedScene' "Player"
type SceneNodeName "Main" "Player" = "Player"
type SceneNodeIsHaskell "Main" "Player" = 'Just '("Player", "Player")
instance SceneNode "Main" "ScoreTimer" where
type SceneNodeType "Main" "ScoreTimer" = Timer
type SceneNodeName "Main" "ScoreTimer" = "ScoreTimer"
type SceneNodeIsHaskell "Main" "ScoreTimer" = 'Nothing
instance SceneNode "Main" "StartPosition" where
type SceneNodeType "Main" "StartPosition" = Position2D
type SceneNodeName "Main" "StartPosition" = "StartPosition"
type SceneNodeIsHaskell "Main" "StartPosition" = 'Nothing
instance SceneNode "Main" "StartTimer" where
type SceneNodeType "Main" "StartTimer" = Timer
type SceneNodeName "Main" "StartTimer" = "StartTimer"
type SceneNodeIsHaskell "Main" "StartTimer" = 'Nothing
instance SceneConnection "Main" "HUD" "start_game" "Main" "new_game"
instance SceneConnection "Main" "StartTimer" "timeout" "Main" "_on_StartTimer_timeout"
instance SceneConnection "Main" "ScoreTimer" "timeout" "Main" "_on_ScoreTimer_timeout"
instance SceneConnection "Main" "MobTimer" "timeout" "Main" "_on_MobTimer_timeout"
instance SceneConnection "Main" "Player" "hit" "Main" "game_over"
================================================
FILE: examples/dodge-the-creeps/src/Project/Scenes/Mob.hs
================================================
-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT
{-# LANGUAGE FlexibleContexts, FunctionalDependencies, MultiParamTypeClasses,
UndecidableInstances, OverloadedStrings, TemplateHaskell, TypeApplications,
TypeFamilies, DataKinds, TypeOperators, FlexibleInstances, RankNTypes,
AllowAmbiguousTypes, ScopedTypeVariables, DerivingStrategies,
GeneralizedNewtypeDeriving, LambdaCase #-}
module Project.Scenes.Mob where
import Project.Support
import Godot
import GHC.TypeLits
import Godot.Core.AnimatedSprite()
import Godot.Core.CollisionShape2D()
import Godot.Core.RigidBody2D()
import Godot.Core.VisibilityNotifier2D()
instance SceneResourcePath "Mob" where
sceneResourcePath = "res://Mob.tscn"
instance SceneRoot "Mob" where
type SceneRootNode "Mob" = "Mob"
instance SceneNode "Mob" "AnimatedSprite" where
type SceneNodeType "Mob" "AnimatedSprite" = AnimatedSprite
type SceneNodeName "Mob" "AnimatedSprite" = "AnimatedSprite"
type SceneNodeIsHaskell "Mob" "AnimatedSprite" = 'Nothing
instance SceneNode "Mob" "CollisionShape2D" where
type SceneNodeType "Mob" "CollisionShape2D" = CollisionShape2D
type SceneNodeName "Mob" "CollisionShape2D" = "CollisionShape2D"
type SceneNodeIsHaskell "Mob" "CollisionShape2D" = 'Nothing
instance SceneNode "Mob" "Mob" where
type SceneNodeType "Mob" "Mob" = RigidBody2D
type SceneNodeName "Mob" "Mob" = "Mob"
type SceneNodeIsHaskell "Mob" "Mob" = 'Just '("Mob", "Mob")
instance SceneNode "Mob" "VisibilityNotifier2D" where
type SceneNodeType "Mob" "VisibilityNotifier2D" = VisibilityNotifier2D
type SceneNodeName "Mob" "VisibilityNotifier2D" = "VisibilityNotifier2D"
type SceneNodeIsHaskell "Mob" "VisibilityNotifier2D" = 'Nothing
instance SceneConnection "Mob" "VisibilityNotifier2D" "screen_exited" "Mob" "_on_VisibilityNotifier2D_screen_exited"
================================================
FILE: examples/dodge-the-creeps/src/Project/Scenes/Player.hs
================================================
-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT
{-# LANGUAGE FlexibleContexts, FunctionalDependencies, MultiParamTypeClasses,
UndecidableInstances, OverloadedStrings, TemplateHaskell, TypeApplications,
TypeFamilies, DataKinds, TypeOperators, FlexibleInstances, RankNTypes,
AllowAmbiguousTypes, ScopedTypeVariables, DerivingStrategies,
GeneralizedNewtypeDeriving, LambdaCase #-}
module Project.Scenes.Player where
import Project.Support
import Godot
import GHC.TypeLits
import Godot.Core.AnimatedSprite()
import Godot.Core.CollisionShape2D()
import Godot.Core.Area2D()
instance SceneResourcePath "Player" where
sceneResourcePath = "res://Player.tscn"
instance SceneRoot "Player" where
type SceneRootNode "Player" = "Player"
instance SceneNode "Player" "AnimatedSprite" where
type SceneNodeType "Player" "AnimatedSprite" = AnimatedSprite
type SceneNodeName "Player" "AnimatedSprite" = "AnimatedSprite"
type SceneNodeIsHaskell "Player" "AnimatedSprite" = 'Nothing
instance SceneNode "Player" "CollisionShape2D" where
type SceneNodeType "Player" "CollisionShape2D" = CollisionShape2D
type SceneNodeName "Player" "CollisionShape2D" = "CollisionShape2D"
type SceneNodeIsHaskell "Player" "CollisionShape2D" = 'Nothing
instance SceneNode "Player" "Player" where
type SceneNodeType "Player" "Player" = Area2D
type SceneNodeName "Player" "Player" = "Player"
type SceneNodeIsHaskell "Player" "Player" = 'Just '("Player", "Player")
instance SceneConnection "Player" "Player" "body_entered" "Player" "_on_Player_body_entered"
================================================
FILE: examples/dodge-the-creeps/src/Project/Scenes.hs
================================================
-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT
module Project.Scenes (module M) where
import qualified Project.Scenes.HUD as M
import qualified Project.Scenes.Main as M
import qualified Project.Scenes.Mob as M
import qualified Project.Scenes.Player as M
================================================
FILE: examples/dodge-the-creeps/src/Project/Support.hs
================================================
-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT
{-# LANGUAGE FlexibleContexts, FunctionalDependencies, MultiParamTypeClasses,
UndecidableInstances, OverloadedStrings, TemplateHaskell, TypeApplications,
TypeFamilies, DataKinds, TypeOperators, FlexibleInstances, RankNTypes,
AllowAmbiguousTypes, ScopedTypeVariables, DerivingStrategies,
GeneralizedNewtypeDeriving, LambdaCase #-}
{-# OPTIONS_GHC -Wno-name-shadowing #-}
module Project.Support where
import Godot.Core.Object
import Godot.Internal.Dispatch
import Godot.Gdnative.Internal.Types
import Data.Typeable
import qualified Data.Text as T
import qualified Data.Map as M
import Language.Haskell.TH
import Language.Haskell.TH.Datatype
import Control.Lens
import Control.Monad
import Godot
import Godot.Gdnative
import GHC.TypeLits
import Data.List
import Data.Maybe
import Data.Coerce
import Godot.Core.ResourceLoader
import Godot.Core.PackedScene
-- * Helper to keep Haskell types in sync with the Godot project.
newtype PackedScene' (scene :: Symbol) = PackedScene' PackedScene
deriving newtype AsVariant
instance HasBaseClass (PackedScene' scene) where
type BaseClass (PackedScene' scene) = PackedScene
super = coerce
deriveBase ''PackedScene'
-- | Use this to register all of your classes, it makes sure that you don't
-- forget a class that Godot needs.
--
-- exports :: GdnativeHandle -> IO ()
-- exports desc = registerAll' @Nodes @'[HUD, Main, Mob, Player] desc
registerAll' :: forall (res :: [*]) (ns :: [*]). ImplementedInHaskell res ns => GdnativeHandle -> IO ()
registerAll' = fill @res @ns
-- | A safe version of getNode; gives you back the Godot object
-- getNode' @"MobPath/MobSpawnLocation" self
getNode' :: forall label b cls scene name. (Object :< cls, Node :< cls,
Node :< b,
NodeInScene scene name cls,
SceneNode scene label,
SceneNodeType scene label ~ b,
KnownSymbol label)
=> cls -> IO b
getNode' o = getNode @(SceneNodeType scene label) o (T.pack $ symbolVal (Proxy @label))
-- | A safe version of getNodeNativeScript; gives you back the Haskell object
-- getNodeNativeScript' @"HUD" self
getNodeNativeScript' :: forall label b cls scene name scene' label'.
(NativeScript b, Node :< cls, Object :< cls, NodeInScene scene name cls,
SceneNodeIsHaskell scene label ~ 'Just '(scene', label'),
NodeInScene scene' label' b,
KnownSymbol label)
=> cls -> IO b
getNodeNativeScript' cls = getNodeNativeScript @b cls (T.pack $ symbolVal (Proxy @label))
-- | A safe version of emit_signal; will error at compile time if the signal doesn't exist
-- emit_signal' @"hit" self []
-- TODO We don't check arguments yet!
emit_signal' :: forall label args cls.
(Object :< cls, Object :< cls, NodeSignal cls label args, KnownSymbol label)
=> cls -> [Variant 'GodotTy] -> IO ()
emit_signal' cls args = do
name <- toLowLevel (T.pack $ symbolVal (Proxy @label))
emit_signal cls name args
-- | A safe version of await; will error at compile time if the signal and nodes don't exist
-- await' @"MessageTimer" @"timeout" self $ \self' -> pure ()
await' :: forall (label :: Symbol) (signal :: Symbol) a b cls scene name.
(NodeInScene scene name cls, NativeScript cls, KnownSymbol label, KnownSymbol signal,
SceneNode scene label, Node :< cls, AsVariant a, Node :< SceneNodeType scene label,
NodeSignal b signal '[], SceneNodeType scene label ~ b)
=> cls -> (cls -> IO a) -> IO ()
await' o f = do
n <- getNode' @label o
await o n (T.pack $ symbolVal (Proxy @signal)) f
-- | Preload a scene so you can instantiate it later.
-- Use this when the scene is known ahead of time. Store scenes in as @PackedScene' "SceneName"@
preloadScene :: forall scene. (KnownSymbol scene, SceneResourcePath scene) => IO (PackedScene' scene)
preloadScene = do
Just r <- getSingleton @ResourceLoader
path <- toLowLevel $ sceneResourcePath @scene
PackedScene' <$> (tryCast' =<< load r path Nothing Nothing)
-- | Create an instance of a scene from a @PackedScene' "SceneName"@
-- Makes sure that you are getting the type of the scene root.
sceneInstance :: forall scene o. (Node :< o, Typeable o, AsVariant o, SceneNodeType scene (SceneRootNode scene) ~ o) => PackedScene' scene -> IO o
sceneInstance e = tryCast' =<< instance' e Nothing
-- | Combines nodeMethod with getNode' to call functions in a type-safe way
-- Provides no additional safety compared to using the two separately, but does clean up code a bit.
-- For example: fn @"MyNode" @"hide" self
fn :: forall (node :: Symbol) (func :: Symbol) scene name cls args ret b.
(Object :< cls, Node :< cls,
Node :< SceneNodeType scene node,
NodeInScene scene name cls, SceneNode scene node,
NodeMethodSuper (SceneNodeType scene node) func args ret,
ListToFun args ret ~ IO b, KnownSymbol node) => cls -> IO b
fn self = nodeMethod' @_ @func =<< getNode' @node self
-- | Get the file path to the scene
class SceneResourcePath (scene :: Symbol) where
sceneResourcePath :: forall scene. T.Text
-- * Internal helpers: You won't use these
-- | The root node of a scene
class SceneRoot (scene :: Symbol) where
type SceneRootNode scene :: Symbol
-- | A node in the scene, we know its type and its name, @s@ is the path relate
-- to the scene
class (Typeable (SceneNodeType scene s),
AsVariant (SceneNodeType scene s),
Object :< SceneNodeType scene s) => SceneNode (scene :: Symbol) (s :: Symbol) where
type SceneNodeType scene s :: *
type SceneNodeName scene s :: Symbol
type SceneNodeIsHaskell scene s :: Maybe (Symbol, Symbol)
-- | You declare this for your types. You offer up a haskell type, @n@, for the
-- node. This class verifies that your base class is correct.
class (HasBaseClass n, BaseClass n ~ SceneNodeType scene s) =>
NodeInScene (scene :: Symbol) (s :: Symbol) n | scene s -> n, n -> scene s
-- | A connection between nodes in a scene. @from@ and @to@ are paths.
-- It connects @signal@ in @from@ to @method@ in @to@.
class SceneConnection (scene :: Symbol) (from :: Symbol) (signal :: Symbol) (to :: Symbol) (method :: Symbol)
-- | Internal, just for convenience
data OneResourceNode (resource :: Symbol) (name :: Symbol)
-- | Internal. Don't touch this and don't make instances of it. It's the
-- workhorse for making sure that you are implementing all of the classes that
-- Godot needs, nothing more and nothing less.
class ImplementedInHaskell (a :: [*]) (b :: [*]) where
fill :: GdnativeHandle -> IO ()
instance ImplementedInHaskell '[] '[] where
fill _ = pure ()
registerOne :: forall ty. (NativeScript ty, AsVariant (BaseClass ty)) => GdnativeHandle -> IO ()
registerOne desc = registerClass $ RegClass desc $ classInit @ty
instance (NodeInScene scene name n,
NativeScript n, AsVariant (BaseClass n),
ImplementedInHaskell t t',
SceneNodeIsHaskell scene name ~ 'Just '(resource, name))
=> ImplementedInHaskell (OneResourceNode resource name ': t) (n ': t') where
fill handle = do
registerOne @n handle
fill @t @t' handle
-- | Create a signal
-- TODO args ~ '[] is temproary, we need signeltons to reflect this into a runtime value
signal' :: forall cls label args.
(NodeSignal cls label args, KnownSymbol label, args ~ '[])
=> (Text, [SignalArgument])
signal' = signal (T.pack $ symbolVal (Proxy @label)) []
createMVarProperty' :: (Typeable ty, AsVariant ty) => Text
-> (node -> MVar ty)
-- ^ We typically can't do IO (for initialisation) when calling this, in
-- which case we need to annotate the type without providing a value.
-> Either VariantType ty
-> (node -> IO ty
,node -> ty -> IO ()
,Maybe (Object -> node -> IO GodotVariant
,Object -> node -> GodotVariant -> IO ()
,PropertyAttributes))
createMVarProperty' name fieldName tyOrVal =
(readMVar . fieldName,
\c t -> propertySetter p undefined c =<< toGodotVariant t,
Just (propertyGetter p, propertySetter p, propertyAttrs p))
where p = createMVarProperty name fieldName tyOrVal
appsT :: Type -> [Type] -> Type
appsT t [] = t
appsT t (x:xs) = appsT (AppT t x) xs
-- | Verify that the signal connects to an endpoint that exists and has the right type.
witnessConnection :: forall (scene :: Symbol) (from :: Symbol) (signal :: Symbol) (to :: Symbol) (method :: Symbol) parent sigTy hTy.
(SceneNode scene to,
NodeSignal parent signal sigTy,
-- TODO This the check unsound, but SceneNodeType isn't right for this constraint. What is?
-- The warning produced because 'from' is not used is a reminder of this issue.
-- parent :< SceneNodeType scene from,
NodeMethod hTy method sigTy (IO ()),
NodeInScene scene to hTy) => ()
witnessConnection = ()
-- | Sets up a class
class NodeInit n where
init :: BaseClass n -> IO n
-- | You never implement this. It's a helper so that we can have a more
-- polymorphic call to nodeMethod which will work when the method is implemneted
-- for any parent of the current node.
class NodeMethodSuper node (name :: Symbol) (args :: [*]) (ret :: *) | node name -> args, node name -> ret where
nodeMethod' :: node -> ListToFun args ret
-- | An instance that supports calling nodeMethod' on your parents This can lead
-- to infinite loops in the type checker on error, so we isolate it in
-- NodeMethodSuper instead of NodeMethod.
instance {-# OVERLAPPABLE #-} (NodeMethod (BaseClass node) name arg ret, HasBaseClass node)
=> NodeMethodSuper node name arg ret where
nodeMethod' = nodeMethod' @node @name @arg @ret
mkProperty' :: forall node (name :: Symbol) ty. (NodeProperty node name ty 'False, KnownSymbol name) => ClassProperty node
mkProperty' = ClassProperty (T.pack $ symbolVal (Proxy @name)) a s g
where (_,_,Just (g,s,a)) = nodeProperty @node @name @ty @'False
-- | You should use this as:
-- setupNode ''Ty
-- deriveBase ''Ty
-- This will instantiate everything that your Object needs
setupNode :: Name -> String -> String -> Q [Dec]
setupNode ty scene sceneNode = do
-- Collect information about all scenes
tree <- map unTree . classInstances <$> reify ''(:<)
sceneRoots <- M.fromList . map unSceneRootNode . familyInstances <$> reify ''SceneRootNode
sceneNodes <- map unSceneNodeType . familyInstances <$> reify ''SceneNodeType
haskellNodes <- map unNodeInScene . classInstances <$> reify ''NodeInScene
allSignals <- map unNodeSignal . classInstances <$> reify ''NodeSignal
-- Collect information about our node
rdt <- reifyDatatype ty
let base = case datatypeCons rdt of
(c:_) -> case (constructorFields c, constructorVariant c) of
(ConT baseTy:_, RecordConstructor (baseFn:_)) -> Just (baseTy, baseFn)
_ -> Nothing
_ -> Nothing
--
methods <- filter (\i -> i^._1 == ty) . mapMaybe unNodeMethod . classInstances <$> reify ''NodeMethod
properties <- filter (\i -> i^._1 == ty) . mapMaybe unNodeProperty . classInstances <$> reify ''NodeProperty
let signals = filter (\i -> i^._1 == ty) allSignals
connections <- filter (\i -> i^._1 == scene && i^._4 == sceneNode) . map unConnect . classInstances <$> reify ''SceneConnection
-- Helpers
let parentsOf cls = map snd $ filter (\(c,_) -> cls == c) tree
let nodeToType :: String -> String -> Name
nodeToType scene node = case (hty, ty ^. _4) of
(Just t, _) -> t
(_, Nothing) -> ty ^. _3
(_, Just scene') -> case M.lookup scene' sceneRoots of
Nothing -> error $ "Looking up the root of a scene that is lacking one. This is a bug. " ++ show (scene', scene, node)
Just node' -> nodeToType scene' node'
where ty = fromJust $ find (\n -> n^._1 == scene && n^._2 == node) sceneNodes
hty = (^._3) <$> find (\n -> n^._1 == scene && n^._2 == node) haskellNodes
let resolveSignalActualClass scene from signal =
case mapMaybe (\p -> (p,) <$> find (\s -> s^._2 == signal && s^._1 == p) allSignals) $ parentsOf (nodeToType scene from) of
-- The root issue is that the signal might not yet exist.
-- If witnessConnection was not unsound, this would not be needed as the error would happen later.
[] -> error $ "Class " ++ show from ++ " used in scene " ++ show scene ++ " is lacking a signal named " ++ show signal ++ "\n" ++ show (nodeToType scene from) ++ "\n" ++ show (parentsOf (nodeToType scene from))
(h:_) -> h ^. _1
-- Debug
when False $ runIO $ do
putStrLn "Regenerating .."
print rdt
putStrLn "\nScene roots:"
print sceneRoots
putStrLn "\nScene nodes types:"
mapM_ print sceneNodes
putStrLn "\nMethods:"
mapM_ print methods
putStrLn "\nProperties:"
mapM_ print properties
putStrLn "\nSignals:"
mapM_ print allSignals
mapM_ print signals
putStrLn "\nConnections:"
mapM_ print connections
putStrLn "\nHaskell nodes:"
mapM_ print haskellNodes
-- Generate code
bi <- case base of
Just (baseTy, baseFn) ->
[d|instance HasBaseClass $(pure $ PromotedT ty) where
type BaseClass $(pure $ PromotedT ty) = $(pure $ PromotedT baseTy)
super = $(pure $ VarE baseFn)|]
_ -> error "setupNode can only handle records whose first field is the Godot base class. You can still interface with Godot, but you will need to set things up manually."
nis <- [d|instance NodeInScene $(pure $ LitT $ StrTyLit scene) $(pure $ LitT $ StrTyLit sceneNode) $(pure $ PromotedT ty)|]
ns <- [d|instance NativeScript $(pure $ PromotedT ty) where
classInit = Project.Support.init
classMethods = $(ListE <$> mapM (\(t,n,argTy,_) ->
let m = case nrArguments argTy of
0 -> [e|method0|]
1 -> [e|method1|]
2 -> [e|method2|]
3 -> [e|method3|]
4 -> [e|method4|]
5 -> [e|method5|]
n -> error $ "More arguments than we currently impelement, look for 'method5' for more info " ++ show n
in [e|$m $(pure $ LitE $ StringL n) (nodeMethod @ $(pure $ PromotedT t) @ $(pure $ LitT $ StrTyLit n))|]) methods)
classProperties = $(ListE <$> mapM (\(name,prop,_,_) -> [e|mkProperty' @ $(pure $ PromotedT name) @ $(pure $ LitT $ StrTyLit prop) |]) properties)
classSignals = $(ListE <$> mapM (\(ty,name,_) -> [e|signal' @ $(pure $ PromotedT ty) @ $(pure $ LitT $ StrTyLit name)|]) signals)|]
let cn = mkName $ "witness_connections_" ++ nameBase ty
ws <- (:) <$> (cn `sigD` [t| [()] |]) <*>
[d|$(varP cn) =
$(ListE <$> mapM (\(scene,from,signal,to,method) ->
[e|witnessConnection
@ $(pure $ LitT $ StrTyLit scene) @ $(pure $ LitT $ StrTyLit from)
@ $(pure $ LitT $ StrTyLit signal) @ $(pure $ LitT $ StrTyLit to)
@ $(pure $ LitT $ StrTyLit method)
@ $(pure $ PromotedT $ resolveSignalActualClass scene from signal)
|]) connections)|]
pure $ bi <> nis <> ns <> ws
where
unTree (InstanceD Nothing [] (AppT (AppT _ parent) child) []) = (unName child, unName parent)
unTree p = error $ "I don't understand this parent " ++ show p
unName (ConT x) = x
unName (AppT (ConT x) _) = x
unName x = error $ "I don't know how to extract the name of this type: " ++ show x
unSceneRootNode (TySynInstD (TySynEqn Nothing (AppT _ (LitT (StrTyLit scene))) (LitT (StrTyLit node)))) = (scene,node)
unSceneRootNode x = error $ "Don't know how unpack this SceneRootNode: " ++ show x
unSceneNodeType (TySynInstD (TySynEqn Nothing (AppT (AppT _ (LitT (StrTyLit scene))) (LitT (StrTyLit node))) ty))
= (scene,node,unName ty, unpackScene ty)
unSceneNodeType x = error $ "Don't know how unpack this SceneNodeType: " ++ show x
unpackScene (ConT _) = Nothing
unpackScene (AppT (ConT _) (LitT (StrTyLit scene))) = Just scene
unpackScene x = error $ "Don't know how unpack this Scene: " ++ show x
unNodeMethod (InstanceD Nothing [] (AppT (AppT (AppT (AppT (ConT _) (ConT cls)) (LitT (StrTyLit name))) arg) ret) [])
= Just (cls, name, arg, ret)
unNodeMethod _ = Nothing
unNodeProperty (InstanceD Nothing [] (AppT (AppT (AppT (AppT (ConT _) (ConT cls)) (LitT (StrTyLit name))) arg) ret) [])
= Just (cls, name, arg, ret)
unNodeProperty x = error $ show x
unNodeInScene (InstanceD Nothing [] (AppT (AppT (AppT (ConT _) (LitT (StrTyLit scene))) (LitT (StrTyLit node))) (ConT hty)) [])
= (scene, node, hty)
unNodeInScene x = error $ show x
unNodeSignal (InstanceD Nothing [] (AppT (AppT (AppT (ConT _) (ConT cls)) (LitT (StrTyLit name))) arg) []) = (cls, name, arg)
unNodeSignal _ = error "Bad signal"
unConnect (InstanceD Nothing [] (AppT (AppT (AppT (AppT (AppT _ (LitT (StrTyLit scene))) (LitT (StrTyLit from))) (LitT (StrTyLit signal))) (LitT (StrTyLit to))) (LitT (StrTyLit method))) []) = (scene, from, signal, to, method)
unConnect x = error $ "Bad signal" ++ show x
nrArguments :: Type -> Int
nrArguments (AppT _ r) = 1 + nrArguments r
nrArguments (SigT PromotedNilT (AppT ListT StarT)) = 0
nrArguments _ = error "Can't compute # of arguments"
classInstances :: Info -> [InstanceDec]
classInstances (ClassI _ is) = is
classInstances _ = error "Bad class"
familyInstances :: Info -> [InstanceDec]
familyInstances (FamilyI _ is) = is
familyInstances _ = error "Bad class"
================================================
FILE: examples/dodge-the-creeps/stack-shell.nix
================================================
{ nixpkgs ? import ./pinned-nixpkgs.nix {}
, ghc
}:
with nixpkgs;
haskell.lib.buildStackProject {
inherit ghc;
name = "myproject";
buildInputs = [];
}
================================================
FILE: examples/dodge-the-creeps/stack.yaml
================================================
resolver: nightly-2021-02-06
packages:
- .
extra-deps:
- ../../
require-stack-version: ">=1.8"
nix:
enable: false
pure: true
packages: []
shell-file: stack-shell.nix
nix-shell-options: []
path: []
add-gc-roots: false
================================================
FILE: examples/rss-reader/.gitignore
================================================
dist*
*.hi
*.o
.stack-work/
.stack-work-devel/
*~
\#*
*.import
result
================================================
FILE: examples/rss-reader/ChangeLog.md
================================================
# Empty
================================================
FILE: examples/rss-reader/LICENSE
================================================
BSD 3-Clause License
Copyright (c) Andrei Barbu 2019
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: examples/rss-reader/Makefile
================================================
NAME = myproject
STACKLIBFILE = $(shell stack path --local-install-root)/lib/lib$(NAME).so
GODOTPROJECT = $(shell stack path --project-root)/game
all: stack
nix:
nix-build shell.nix
cp result/lib/ghc-*/lib$(NAME).so $(GODOTPROJECT)/lib
stack:
stack build --fast --force-dirty
cp $(STACKLIBFILE) $(GODOTPROJECT)/lib
stack-nix:
stack --nix clean $(NAME)
stack --nix build
cp $(shell stack --nix path --local-install-root)/lib/lib$(NAME).so $(GODOTPROJECT)/lib
stack-run:
stack build
cp $(STACKLIBFILE) $(GODOTPROJECT)/lib
godot -e --path ./game
stack-watch:
stack build --file-watch --fast --exec "cp $(STACKLIBFILE) $(GODOTPROJECT)/lib"
project-watch:
stack exec godot-haskell-project-generator game src
updatelib:
cp $(STACKLIBFILE) $(GODOTPROJECT)/lib
================================================
FILE: examples/rss-reader/README.md
================================================
The official Godot demo from the manual: Dodge the Creeps.
Run with `make stack` then `godot game/project.godot` and press F5 to start, F8 to end.
Requires Godot 3.1
================================================
FILE: examples/rss-reader/Support.hs
================================================
{-# LANGUAGE FlexibleContexts, FunctionalDependencies, MultiParamTypeClasses, OverloadedLabels, UndecidableInstances,
OverloadedStrings, TemplateHaskell, TypeApplications, TypeFamilies, DataKinds, TypeOperators, FlexibleInstances #-}
module Generated.Support where
import Godot
import GHC.TypeLits
class SceneNode (scene :: Symbol) (s :: Symbol) where
type SceneNodeType scene s :: *
type SceneNodeName scene s :: Symbol
class NodeInScheme (scene :: Symbol) (s :: Symbol) n | scene s -> n, n -> scene s
================================================
FILE: examples/rss-reader/ffi/cbits/flib.c
================================================
#include "HsFFI.h"
static void flib_init() __attribute__((constructor));
static void flib_init() {
static char *argv[] = { "libGodotHaskellPlugin.so", 0 }, **argv_ = argv;
static int argc = 1;
hs_init(&argc, &argv_);
}
static void flib_fini() __attribute__((destructor));
static void flib_fini() {
hs_exit();
}
================================================
FILE: examples/rss-reader/ffi/flib/FLib.hs
================================================
{-# LANGUAGE ForeignFunctionInterface #-}
module FLib where
import qualified Foreign
import Foreign(nullPtr, Ptr,newForeignPtr_,castPtr)
import qualified Godot.Gdnative.Internal as FFI
import Godot.Gdnative
import Godot.Nativescript
import Lib
import qualified Data.Text as T
import qualified Data.Text.IO as T
godot_nativescript_init :: GdnativeHandle -> IO ()
godot_nativescript_init desc = do
defaultExports desc
exports desc
putStrLn "Haskell NativeScript lib initialized"
foreign export ccall godot_nativescript_init :: GdnativeHandle -> IO ()
godot_gdnative_init :: FFI.GdnativeInitOptionsPtr -> IO ()
godot_gdnative_init opts = do
Foreign.peek opts >>= FFI.initApiStructs
foreign export ccall godot_gdnative_init :: FFI.GdnativeInitOptionsPtr -> IO ()
godot_gdnative_terminate :: FFI.GdnativeTerminateOptionsPtr -> IO ()
godot_gdnative_terminate handle = pure ()
foreign export ccall godot_gdnative_terminate :: FFI.GdnativeTerminateOptionsPtr -> IO ()
================================================
FILE: examples/rss-reader/game/Rss_reader.gdns
================================================
[gd_resource type="NativeScript" load_steps=2 format=2]
[ext_resource path="res://lib/libmyproject.gdnlib" type="GDNativeLibrary" id=1]
[resource]
resource_name = "RSSReader"
class_name = "RSSReader"
library = ExtResource( 1 )
================================================
FILE: examples/rss-reader/game/Rss_reader.tscn
================================================
[gd_scene load_steps=2 format=2]
[ext_resource path="res://Rss_reader.gdns" type="Script" id=1]
[node name="RSSReader" type="Control"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_right = 1102.0
margin_bottom = 168.0
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="OpenButton" type="Button" parent="."]
margin_left = 34.48
margin_top = 65.522
margin_right = 179.48
margin_bottom = 106.522
text = "Open"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="TextEdit" type="TextEdit" parent="."]
visible = false
margin_left = 20.9119
margin_top = 575.146
margin_right = 585.912
margin_bottom = 868.146
__meta__ = {
"_edit_use_anchors_": false
}
[node name="HTTPRequest" type="HTTPRequest" parent="."]
[node name="ItemList" type="ItemList" parent="."]
margin_left = 25.0
margin_top = 137.0
margin_right = 850.0
margin_bottom = 490.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="DescriptionField" type="TextEdit" parent="."]
margin_left = 882.0
margin_top = 137.0
margin_right = 1555.0
margin_bottom = 489.0
readonly = true
wrap_enabled = true
[node name="LinkButton" type="LinkButton" parent="."]
margin_left = 29.8409
margin_top = 496.385
margin_right = 1289.84
margin_bottom = 554.385
__meta__ = {
"_edit_use_anchors_": false
}
[node name="SettingsButton" type="Button" parent="."]
margin_left = 1416.23
margin_top = 67.6134
margin_right = 1549.23
margin_bottom = 108.613
text = "Settings"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="SettingsDialog" type="WindowDialog" parent="."]
margin_left = 352.0
margin_top = 256.0
margin_right = 1340.0
margin_bottom = 538.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="RSSURLText" type="LineEdit" parent="SettingsDialog"]
margin_left = 136.409
margin_top = 89.8409
margin_right = 847.409
margin_bottom = 131.841
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="SettingsDialog"]
margin_left = 135.431
margin_top = 42.4543
margin_right = 436.431
margin_bottom = 80.4543
text = "The RSS feed URL "
[node name="Button" type="Button" parent="SettingsDialog"]
margin_left = 134.283
margin_top = 161.682
margin_right = 200.283
margin_bottom = 196.682
text = "Clear"
[node name="SaveButton" type="Button" parent="SettingsDialog"]
margin_left = 784.273
margin_top = 159.841
margin_right = 845.273
margin_bottom = 197.841
text = "Save"
__meta__ = {
"_edit_use_anchors_": false
}
[connection signal="ready" from="." to="." method="_on_RSSReader_ready"]
[connection signal="pressed" from="OpenButton" to="." method="_on_OpenButton_pressed"]
[connection signal="request_completed" from="HTTPRequest" to="." method="_on_HTTPRequest_request_completed"]
[connection signal="item_selected" from="ItemList" to="." method="_on_ItemList_item_selected"]
[connection signal="pressed" from="LinkButton" to="." method="_on_LinkButton_pressed"]
[connection signal="pressed" from="SettingsButton" to="." method="_on_SettingsButton_pressed"]
[connection signal="pressed" from="SettingsDialog/Button" to="." method="_on_Settings_Clear_Button_pressed"]
[connection signal="pressed" from="SettingsDialog/SaveButton" to="." method="_on_SaveButton_pressed"]
================================================
FILE: examples/rss-reader/game/export_presets.cfg
================================================
[preset.0]
name="Linux/X11"
platform="Linux/X11"
runnable=true
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="../../../../../../../tmp/rssreader.x86_64"
patch_list=PoolStringArray( )
script_export_mode=1
script_encryption_key=""
[preset.0.options]
texture_format/bptc=false
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
texture_format/no_bptc_fallbacks=true
binary_format/64_bits=true
binary_format/embed_pck=false
custom_template/release=""
custom_template/debug=""
================================================
FILE: examples/rss-reader/game/lib/libmyproject.gdnlib
================================================
[general]
singleton=false
load_once=true
symbol_prefix="godot_"
reloadable=false
[entry]
X11.64="res://lib/libmyproject.so"
================================================
FILE: examples/rss-reader/game/project.godot
================================================
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=4
_global_script_classes=[ ]
_global_script_class_icons={
}
[application]
config/name="rss-reader"
run/main_scene="res://Rss_reader.tscn"
[audio]
default_bus_layout=""
[display]
window/size/width=480
window/size/height=720
window/dpi/allow_hidpi=true
[gdnative]
singletons=[ ]
[gui]
theme/use_hidpi=true
================================================
FILE: examples/rss-reader/godot-haskell.nix
================================================
{ fetchFromGitHub, mkDerivation, aeson, ansi-wl-pprint, base, bytestring, c2hs
, casing, colour, containers, hpack, lens, linear, mtl, parsec
, parsers, stdenv, stm, template-haskell, text
, unordered-containers, vector
}:
mkDerivation {
pname = "godot-haskell";
version = "3.1.0.0";
src = fetchFromGitHub {
owner = "SimulaVR";
repo = "godot-haskell";
rev = "b423d4f2fa5a6a3dcfffb82bb36be571adb29d34"; # godot-haskell rev
# Use nix-prefetch-git to get the hash
sha256 = "0jh2j5rr90dqdxvcipygwnhhj7j2dj4zvm6gbdpg106ll60pyqrp";
fetchSubmodules = true;
};
libraryHaskellDepends = [
aeson ansi-wl-pprint base bytestring casing colour containers lens
linear mtl parsec parsers stm template-haskell text
unordered-containers vector
];
libraryToolDepends = [ c2hs hpack ];
doHaddock = false;
preConfigure = "hpack";
homepage = "https://github.com/KaneTW/godot-haskell#readme";
description = "Haskell bindings for the Godot game engine API";
license = stdenv.lib.licenses.bsd3;
}
================================================
FILE: examples/rss-reader/hie.yaml
================================================
cradle:
stack:
- path: "./src"
component: "myproject:lib"
- path: "./game"
component: "myproject:lib"
================================================
FILE: examples/rss-reader/myproject.cabal
================================================
cabal-version: 1.12
-- This file has been generated from package.yaml by hpack version 0.33.0.
--
-- see: https://github.com/sol/hpack
--
-- hash: b6a0d2a1fc09513a3765e90723389dc19ec4879f3963404979d2a68731de6d6e
name: myproject
version: 0.0.0.0
description: Please see the README on Github at <https://github.com/SimulaVR/godot-haskell/tree/master/demo#readme>
homepage: https://github.com/SimulaVR/godot-haskell#readme
bug-reports: https://github.com/SimulaVR/godot-haskell/issues
author: Andrei Barbu
maintainer: andrei@0xab.com
copyright: Andrei Barbu 2019, 2021
license: BSD3
license-file: LICENSE
build-type: Simple
extra-source-files:
ChangeLog.md
README.md
foreign-library myproject
type: native-shared
other-modules: FLib
hs-source-dirs: ffi/flib
c-sources: ffi/cbits/flib.c
build-depends:
base >= 4.12 && <5
, godot-haskell
, myproject
, text
default-language: Haskell2010
source-repository head
type: git
location: https://github.com/SimulaVR/godot-haskell
library
exposed-modules:
Lib
other-modules:
Game.RSSReader
Project.Requirements
Project.Scenes
Project.Scenes.Rss_reader
Project.Support
Paths_myproject
hs-source-dirs:
src
game
default-extensions: FlexibleContexts MultiParamTypeClasses OverloadedStrings TemplateHaskell TypeApplications TypeFamilies DataKinds FlexibleInstances ScopedTypeVariables AllowAmbiguousTypes TypeOperators TupleSections
ghc-options: -Wall -Wno-orphans -O0
build-depends:
aeson
, base >=4.12 && <5
, containers
, directory
, extra
, godot-haskell
, lens
, linear
, monad-loops
, random
, strict-concurrency
, template-haskell
, text
, th-abstraction
, vector
, xeno
default-language: Haskell2010
================================================
FILE: examples/rss-reader/package.yaml
================================================
name: myproject
version: '0.0.0.0'
description: Please see the README on Github at <https://github.com/SimulaVR/godot-haskell/tree/master/demo#readme>
author: Andrei Barbu
maintainer: andrei@0xab.com
copyright: Andrei Barbu 2019, 2021
license: BSD3
github: SimulaVR/godot-haskell
extra-source-files:
- ChangeLog.md
- README.md
dependencies:
- base >=4.12 && <5
- godot-haskell
- linear
- random
- text
- vector
- strict-concurrency
- lens
- template-haskell
- th-abstraction
- containers
- extra
- monad-loops
- xeno
- aeson
- directory
library:
source-dirs:
- src
- game
default-extensions:
- FlexibleContexts
- MultiParamTypeClasses
- OverloadedStrings
- TemplateHaskell
- TypeApplications
- TypeFamilies
- DataKinds
- FlexibleInstances
- ScopedTypeVariables
- AllowAmbiguousTypes
- TypeOperators
- TupleSections
exposed-modules:
- Lib
ghc-options: -Wall -Wno-orphans -O0
verbatim: |
foreign-library myproject
type: native-shared
other-modules: FLib
hs-source-dirs: ffi/flib
c-sources: ffi/cbits/flib.c
build-depends:
base >= 4.12 && <5
, godot-haskell
, myproject
, text
default-language: Haskell2010
================================================
FILE: examples/rss-reader/pinned-nixpkgs.nix
================================================
{}:
let
# 19.03-beta (25 feb)
rev = "0c0954781e257b8b0dc49341795a2fe7d96945a3"; # pinned-nixpkgs rev
pkgs = import (builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
}) {};
in
pkgs
================================================
FILE: examples/rss-reader/shell.nix
================================================
{ nixpkgs ? import ./pinned-nixpkgs.nix {}
, compiler ? "default"
, doBenchmark ? false }:
let
inherit (nixpkgs) pkgs;
haskellPackages = if compiler == "default"
then pkgs.haskellPackages
else pkgs.haskell.packages.${compiler};
f = { mkDerivation, stdenv, base, godot-haskell, linear, text , vector, stm }:
mkDerivation {
pname = "myproject";
version = "3.1.0.0";
src = ./.;
libraryHaskellDepends = [
base godot-haskell linear text vector stm
];
libraryToolDepends = [];
homepage = "https://github.com/abarbu/myproject#readme";
license = stdenv.lib.licenses.bsd3;
};
variant = if doBenchmark then pkgs.haskell.lib.doBenchmark else pkgs.lib.id;
drv = variant (haskellPackages.callPackage f {
godot-haskell = haskellPackages.callPackage ./godot-haskell.nix {fetchFromGitHub = pkgs.fetchFromGitHub;};
});
in
if pkgs.lib.inNixShell then drv.env else drv
================================================
FILE: examples/rss-reader/src/Game/RSSReader.hs
================================================
{-# LANGUAGE LambdaCase, FunctionalDependencies, DeriveGeneric, UndecidableInstances, ConstraintKinds #-}
module Game.RSSReader where
import Control.Lens
import Control.Monad
import Foreign.Ptr
import Godot
import Godot.Core.HTTPClient as HTTPClient
import Godot.Core.OS as OS
import Godot.Core.ItemList as ItemList
import Godot.Core.HTTPRequest as HTTPRequest
import Godot.Core.TextEdit as TextEdit
import Godot.Core.LineEdit as LineEdit
import Godot.Core.LinkButton as LinkButton
import Godot.Core.Popup as Popup
import Godot.Gdnative
import Project.Scenes.Rss_reader()
import Project.Support
import qualified Xeno.DOM.Robust as X
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Data.List
import Data.Maybe
import Data.Typeable
import GHC.Generics
import qualified Data.Aeson as A
import System.Directory
import qualified Godot.Core.CanvasItem as CanvasItem
data Settings = Settings { _url :: Text }
deriving (Generic, Show)
instance A.FromJSON Settings
instance A.ToJSON Settings
makeFieldsNoPrefix ''Settings
data Story = Story { _storyTitle :: T.Text
, _storyDescription :: Maybe T.Text
, _storyLink :: T.Text }
deriving Show
makeFields ''Story
data RSSReader = RSSReader
{ _base :: Control
, _feed :: MVar [Story]
}
makeFieldsNoPrefix ''RSSReader
instance NodeInit RSSReader where
init base = RSSReader base <$> newMVar []
instance NodeMethod RSSReader "_on_OpenButton_pressed" '[] (IO ()) where
nodeMethod = populateEdit
instance NodeMethod RSSReader "populateEdit" '[] (IO ()) where
nodeMethod = populateEdit
instance NodeMethod RSSReader "_on_HTTPRequest_request_completed" [Int, Int, PoolStringArray, PoolByteArray] (IO ()) where
nodeMethod self _ _ _ body = do
t <- getNode' @"TextEdit" self
sz <- godot_pool_byte_array_size body
s <- (\x -> godot_string_chars_to_utf8_with_len (castPtr x) sz) =<< godot_pool_byte_array_read_access_ptr =<< godot_pool_byte_array_read body
TextEdit.set_text t s
contents <- T.encodeUtf8 <$> fromLowLevel s
let stories = parseXML contents
lst <- getNode' @"ItemList" self
void $ swapMVar (self ^. feed) stories
mapM_ (\s -> ItemList.add_item lst <$> toLowLevel (s ^. title) <*> pure Nothing <*> pure (Just True) & join) stories
instance NodeMethod RSSReader "_on_ItemList_item_selected" '[Int] (IO ()) where
nodeMethod self n = do
f <- readMVar (self ^. feed)
TextEdit.set_text <$> getNode' @"DescriptionField" self
<*> toLowLevel (fromMaybe "" $ (f !! n) ^. description)
& join
LinkButton.set_text <$> getNode' @"LinkButton" self
<*> toLowLevel ((f !! n) ^. link)
& join
pure ()
instance NodeMethod RSSReader "_on_LinkButton_pressed" '[] (IO ()) where
nodeMethod self = do
(Just os) <- getSingleton @OS
void $ OS.shell_open os =<< LinkButton.get_text =<< getNode' @"LinkButton" self
instance NodeMethod RSSReader "_on_SettingsButton_pressed" '[] (IO ()) where
nodeMethod self = do
d <- getNode' @"SettingsDialog" self
Popup.popup d Nothing
instance NodeMethod RSSReader "_on_Settings_Clear_Button_pressed" '[] (IO ()) where
nodeMethod self = LineEdit.set_text <$> getNode' @"SettingsDialog/RSSURLText" self
<*> toLowLevel ""
& join
instance NodeMethod RSSReader "_on_RSSReader_ready" '[] (IO ()) where
nodeMethod self = loadData self
instance NodeMethod RSSReader "_on_SaveButton_pressed" '[] (IO ()) where
nodeMethod self = do
saveData self
CanvasItem.hide =<< getNode' @"SettingsDialog" self
pure ()
clearFields (self :: RSSReader) = do
void $ swapMVar (self ^. feed) []
ItemList.clear =<< getNode' @"ItemList" self
TextEdit.set_text <$> getNode' @"DescriptionField" self <*> toLowLevel "" & join
LinkButton.set_text <$> getNode' @"LinkButton" self <*> toLowLevel "" & join
pure ()
saveData self = do
putStrLn "Saving data"
(Just os) <- getSingleton @OS
d <- fromLowLevel =<< OS.get_user_data_dir os
t <- fromLowLevel =<< LineEdit.get_text =<< getNode' @"SettingsDialog/RSSURLText" self
A.encodeFile (T.unpack d <> "/save_config.json") (Settings t)
loadData self = do
putStrLn "Loading data"
(Just os) <- getSingleton @OS
d <- fromLowLevel =<< OS.get_user_data_dir os
e <- doesFileExist (T.unpack d <> "/save_config.json")
when e $ do
r <- A.decodeFileStrict' (T.unpack d <> "/save_config.json")
case r of
Nothing -> pure ()
Just (s :: Settings) -> do
LineEdit.set_text <$> getNode' @"SettingsDialog/RSSURLText" self
<*> toLowLevel (s ^. url)
& join
parseXML x = case X.parse x of
Right xml -> do
case X.children xml of
[chan] -> do
mapMaybe unItem $ X.children chan
_ -> error "Unknown RSS"
Left a -> []
where head' (h:_) = Just h
head' _ = Nothing
byName name nodes = head' . nodeData =<< find (\e -> X.name e == name) nodes
nodeData = mapMaybe (\case
X.Text t -> Just t
X.CData t -> Just t
_ -> Nothing) . X.contents
unItem item = let nodes = X.children item
in do
t <- byName "title" nodes
l <- byName "link" nodes
pure $ Story (T.decodeUtf8 t) (T.decodeUtf8 <$> byName "description" nodes) (T.decodeUtf8 l)
nothing :: (Object :< a, Typeable a, AsVariant a) => IO a
nothing = fromJust <$> tryCast (Object nullPtr)
populateEdit :: RSSReader -> IO ()
populateEdit self = do
url <- LineEdit.get_text =<< getNode' @"SettingsDialog/RSSURLText" self
void $ HTTPRequest.request <$> getNode' @"HTTPRequest" self
<*> pure url
<*> (Just <$> godot_pool_string_array_new)
<*> pure (Just True)
<*> pure (Just HTTPClient._METHOD_GET)
<*> pure Nothing
& join
setupNode ''RSSReader "Rss_reader" "RSSReader"
deriveBase ''RSSReader
================================================
FILE: examples/rss-reader/src/Game/q
================================================
{-# LANGUAGE LambdaCase, FunctionalDependencies, DeriveGeneric, UndecidableInstances, ConstraintKinds #-}
module Game.RSSReader where
import Control.Lens
import Control.Monad
import Foreign.Ptr
import Godot
import Godot.Core.HTTPClient as HTTPClient
import Godot.Core.OS as OS
import Godot.Core.ItemList as ItemList
import Godot.Core.HTTPRequest as HTTPRequest
import Godot.Core.TextEdit as TextEdit
import Godot.Core.LineEdit as LineEdit
import Godot.Core.LinkButton as LinkButton
import Godot.Core.Popup as Popup
import Godot.Gdnative
import Project.Scenes.Rss_reader()
import Project.Support
import qualified Xeno.DOM.Robust as X
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Data.List
import Data.Maybe
import Data.Typeable
import GHC.Generics
import qualified Data.Aeson as A
import System.Directory
import qualified Godot.Core.CanvasItem as CanvasItem
data Settings = Settings { _url :: Text }
deriving (Generic, Show)
instance A.FromJSON Settings
instance A.ToJSON Settings
makeFieldsNoPrefix ''Settings
data Story = Story { _storyTitle :: T.Text
, _storyDescription :: Maybe T.Text
, _storyLink :: T.Text }
deriving Show
makeFields ''Story
data RSSReader = RSSReader
{ _base :: Control
, _feed :: MVar [Story]
}
makeFieldsNoPrefix ''RSSReader
instance NodeInit RSSReader where
init base = RSSReader base <$> newMVar []
instance NodeMethod RSSReader "_on_OpenButton_pressed" '[] (IO ()) where
nodeMethod = populateEdit
instance NodeMethod RSSReader "populateEdit" '[] (IO ()) where
nodeMethod = populateEdit
instance NodeMethod RSSReader "_on_HTTPRequest_request_completed" [Int, Int, PoolStringArray, PoolByteArray] (IO ()) where
nodeMethod self _ _ _ body = do
t <- getNode' @"TextEdit" self
sz <- godot_pool_byte_array_size body
s <- (\x -> godot_string_chars_to_utf8_with_len (castPtr x) sz) =<< godot_pool_byte_array_read_access_ptr =<< godot_pool_byte_array_read body
TextEdit.set_text t s
contents <- T.encodeUtf8 <$> fromLowLevel s
let stories = parseXML contents
lst <- getNode' @"ItemList" self
void $ swapMVar (self ^. feed) stories
mapM_ (\s -> ItemList.add_item lst <$> toLowLevel (s ^. title) <*> pure Nothing <*> pure (Just True) & join) stories
instance NodeMethod RSSReader "_on_ItemList_item_selected" '[Int] (IO ()) where
nodeMethod = on_ItemList_item_selected
instance NodeMethod RSSReader "_on_LinkButton_pressed" '[] (IO ()) where
nodeMethod = on_LinkButton_pressed
instance NodeMethod RSSReader "_on_SettingsButton_pressed" '[] (IO ()) where
nodeMethod = on_SettingsButton_pressed
instance NodeMethod RSSReader "_on_Settings_Clear_Button_pressed" '[] (IO ()) where
nodeMethod = on_Settings_Clear_Button_pressed
instance NodeMethod RSSReader "_on_RSSReader_ready" '[] (IO ()) where
nodeMethod = on_RSSReader_ready
instance NodeMethod RSSReader "_on_SaveButton_pressed" '[] (IO ()) where
nodeMethod = on_SaveButton_pressed
on_RSSReader_ready self = do
loadData self
on_SaveButton_pressed (self :: RSSReader) = do
saveData self
CanvasItem.hide =<< getNode' @"SettingsDialog" self
pure ()
clearFields (self :: RSSReader) = do
void $ swapMVar (self ^. feed) []
ItemList.clear =<< getNode' @"ItemList" self
TextEdit.set_text <$> getNode' @"DescriptionField" self <*> toLowLevel "" & join
LinkButton.set_text <$> getNode' @"LinkButton" self <*> toLowLevel "" & join
pure ()
saveData self = do
putStrLn "Saving data"
(Just os) <- getSingleton @OS
d <- fromLowLevel =<< OS.get_user_data_dir os
t <- fromLowLevel =<< LineEdit.get_text =<< getNode' @"SettingsDialog/RSSURLText" self
A.encodeFile (T.unpack d <> "/save_config.json") (Settings t)
loadData self = do
putStrLn "Loading data"
(Just os) <- getSingleton @OS
d <- fromLowLevel =<< OS.get_user_data_dir os
e <- doesFileExist (T.unpack d <> "/save_config.json")
when e $ do
r <- A.decodeFileStrict' (T.unpack d <> "/save_config.json")
case r of
Nothing -> pure ()
Just (s :: Settings) -> do
LineEdit.set_text <$> getNode' @"SettingsDialog/RSSURLText" self
<*> toLowLevel (s ^. url)
& join
on_Settings_Clear_Button_pressed :: RSSReader -> IO ()
on_Settings_Clear_Button_pressed self = do
LineEdit.set_text <$> getNode' @"SettingsDialog/RSSURLText" self
<*> toLowLevel ""
& join
on_SettingsButton_pressed :: RSSReader -> IO ()
on_SettingsButton_pressed self = do
d <- getNode' @"SettingsDialog" self
Popup.popup d Nothing
on_LinkButton_pressed :: RSSReader -> IO ()
on_LinkButton_pressed self = do
(Just os) <- getSingleton @OS
void $ OS.shell_open os =<< LinkButton.get_text =<< getNode' @"LinkButton" self
on_ItemList_item_selected :: RSSReader -> Int -> IO ()
on_ItemList_item_selected self n = do
f <- readMVar (self ^. feed)
TextEdit.set_text <$> getNode' @"DescriptionField" self
<*> toLowLevel (fromMaybe "" $ (f !! n) ^. description)
& join
LinkButton.set_text <$> getNode' @"LinkButton" self
<*> toLowLevel ((f !! n) ^. link)
& join
pure ()
parseXML x = case X.parse x of
Right xml -> do
case X.children xml of
[chan] -> do
mapMaybe unItem $ X.children chan
_ -> error "Unknown RSS"
Left a -> []
where head' (h:_) = Just h
head' _ = Nothing
byName name nodes = head' . nodeData =<< find (\e -> X.name e == name) nodes
nodeData = mapMaybe (\case
X.Text t -> Just t
X.CData t -> Just t
_ -> Nothing) . X.contents
unItem item = let nodes = X.children item
in do
t <- byName "title" nodes
l <- byName "link" nodes
pure $ Story (T.decodeUtf8 t) (T.decodeUtf8 <$> byName "description" nodes) (T.decodeUtf8 l)
nothing :: (Object :< a, Typeable a, AsVariant a) => IO a
nothing = fromJust <$> tryCast (Object nullPtr)
on_HTTPRequest_request_completed :: RSSReader -> Int -> Int -> PoolStringArray -> PoolByteArray -> IO ()
on_HTTPRequest_request_completed self _ _ _ body = do
t <- getNode' @"TextEdit" self
sz <- godot_pool_byte_array_size body
s <- (\x -> godot_string_chars_to_utf8_with_len (castPtr x) sz) =<< godot_pool_byte_array_read_access_ptr =<< godot_pool_byte_array_read body
TextEdit.set_text t s
contents <- T.encodeUtf8 <$> fromLowLevel s
let stories = parseXML contents
lst <- getNode' @"ItemList" self
void $ swapMVar (self ^. feed) stories
mapM_ (\s -> ItemList.add_item lst <$> toLowLevel (s ^. title) <*> pure Nothing <*> pure (Just True) & join) stories
populateEdit :: RSSReader -> IO ()
populateEdit self = do
url <- LineEdit.get_text =<< getNode' @"SettingsDialog/RSSURLText" self
void $ HTTPRequest.request <$> getNode' @"HTTPRequest" self
<*> pure url
<*> (Just <$> godot_pool_string_array_new)
<*> pure (Just True)
<*> pure (Just HTTPClient._METHOD_GET)
<*> pure Nothing
& join
setupNode ''RSSReader "Rss_reader" "RSSReader"
deriveBase ''RSSReader
================================================
FILE: examples/rss-reader/src/Lib.hs
================================================
module Lib (exports) where
import Godot
import Project.Support
import Project.Requirements
import Game.RSSReader
exports :: GdnativeHandle -> IO ()
exports = registerAll' @Nodes @'[RSSReader]
================================================
FILE: examples/rss-reader/src/Project/Requirements.hs
================================================
-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT
module Project.Requirements where
import Project.Support
type Nodes = '[OneResourceNode "Rss_reader" "RSSReader"]
================================================
FILE: examples/rss-reader/src/Project/Scenes/Rss_reader.hs
================================================
-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT
{-# LANGUAGE FlexibleContexts, FunctionalDependencies, MultiParamTypeClasses,
UndecidableInstances, OverloadedStrings, TemplateHaskell, TypeApplications,
TypeFamilies, DataKinds, TypeOperators, FlexibleInstances, RankNTypes,
AllowAmbiguousTypes, ScopedTypeVariables, DerivingStrategies,
GeneralizedNewtypeDeriving, LambdaCase #-}
module Project.Scenes.Rss_reader where
import Project.Support
import Godot
import GHC.TypeLits
import Godot.Core.Button()
import Godot.Core.TextEdit()
import Godot.Core.HTTPRequest()
import Godot.Core.ItemList()
import Godot.Core.Label()
import Godot.Core.LinkButton()
import Godot.Core.Control()
import Godot.Core.LineEdit()
import Godot.Core.WindowDialog()
instance SceneResourcePath "Rss_reader" where
sceneResourcePath = "res://Rss_reader.tscn"
instance SceneRoot "Rss_reader" where
type SceneRootNode "Rss_reader" = "RSSReader"
instance SceneNode "Rss_reader" "SettingsDialog/Button" where
type SceneNodeType "Rss_reader" "SettingsDialog/Button" = Button
type SceneNodeName "Rss_reader" "SettingsDialog/Button" = "Button"
type SceneNodeIsHaskell "Rss_reader" "SettingsDialog/Button" = 'Nothing
instance SceneNode "Rss_reader" "DescriptionField" where
type SceneNodeType "Rss_reader" "DescriptionField" = TextEdit
type SceneNodeName "Rss_reader" "DescriptionField" = "DescriptionField"
type SceneNodeIsHaskell "Rss_reader" "DescriptionField" = 'Nothing
instance SceneNode "Rss_reader" "HTTPRequest" where
type SceneNodeType "Rss_reader" "HTTPRequest" = HTTPRequest
type SceneNodeName "Rss_reader" "HTTPRequest" = "HTTPRequest"
type SceneNodeIsHaskell "Rss_reader" "HTTPRequest" = 'Nothing
instance SceneNode "Rss_reader" "ItemList" where
type SceneNodeType "Rss_reader" "ItemList" = ItemList
type SceneNodeName "Rss_reader" "ItemList" = "ItemList"
type SceneNodeIsHaskell "Rss_reader" "ItemList" = 'Nothing
instance SceneNode "Rss_reader" "SettingsDialog/Label" where
type SceneNodeType "Rss_reader" "SettingsDialog/Label" = Label
type SceneNodeName "Rss_reader" "SettingsDialog/Label" = "Label"
type SceneNodeIsHaskell "Rss_reader" "SettingsDialog/Label" = 'Nothing
instance SceneNode "Rss_reader" "LinkButton" where
type SceneNodeType "Rss_reader" "LinkButton" = LinkButton
type SceneNodeName "Rss_reader" "LinkButton" = "LinkButton"
type SceneNodeIsHaskell "Rss_reader" "LinkButton" = 'Nothing
instance SceneNode "Rss_reader" "OpenButton" where
type SceneNodeType "Rss_reader" "OpenButton" = Button
type SceneNodeName "Rss_reader" "OpenButton" = "OpenButton"
type SceneNodeIsHaskell "Rss_reader" "OpenButton" = 'Nothing
instance SceneNode "Rss_reader" "RSSReader" where
type SceneNodeType "Rss_reader" "RSSReader" = Control
type SceneNodeName "Rss_reader" "RSSReader" = "RSSReader"
type SceneNodeIsHaskell "Rss_reader" "RSSReader" = 'Just '("Rss_reader", "RSSReader")
instance SceneNode "Rss_reader" "SettingsDialog/RSSURLText" where
type SceneNodeType "Rss_reader" "SettingsDialog/RSSURLText" = LineEdit
type SceneNodeName "Rss_reader" "SettingsDialog/RSSURLText" = "RSSURLText"
type SceneNodeIsHaskell "Rss_reader" "SettingsDialog/RSSURLText" = 'Nothing
instance SceneNode "Rss_reader" "SettingsDialog/SaveButton" where
type SceneNodeType "Rss_reader" "SettingsDialog/SaveButton" = Button
type SceneNodeName "Rss_reader" "SettingsDialog/SaveButton" = "SaveButton"
type SceneNodeIsHaskell "Rss_reader" "SettingsDialog/SaveButton" = 'Nothing
instance SceneNode "Rss_reader" "SettingsButton" where
type SceneNodeType "Rss_reader" "SettingsButton" = Button
type SceneNodeName "Rss_reader" "SettingsButton" = "SettingsButton"
type SceneNodeIsHaskell "Rss_reader" "SettingsButton" = 'Nothing
instance SceneNode "Rss_reader" "SettingsDialog" where
type SceneNodeType "Rss_reader" "SettingsDialog" = WindowDialog
type SceneNodeName "Rss_reader" "SettingsDialog" = "SettingsDialog"
type SceneNodeIsHaskell "Rss_reader" "SettingsDialog" = 'Nothing
instance SceneNode "Rss_reader" "TextEdit" where
type SceneNodeType "Rss_reader" "TextEdit" = TextEdit
type SceneNodeName "Rss_reader" "TextEdit" = "TextEdit"
type SceneNodeIsHaskell "Rss_reader" "TextEdit" = 'Nothing
instance SceneConnection "Rss_reader" "SettingsDialog/SaveButton" "pressed" "RSSReader" "_on_SaveButton_pressed"
instance SceneConnection "Rss_reader" "SettingsDialog/Button" "pressed" "RSSReader" "_on_Settings_Clear_Button_pressed"
instance SceneConnection "Rss_reader" "SettingsButton" "pressed" "RSSReader" "_on_SettingsButton_pressed"
instance SceneConnection "Rss_reader" "LinkButton" "pressed" "RSSReader" "_on_LinkButton_pressed"
instance SceneConnection "Rss_reader" "ItemList" "item_selected" "RSSReader" "_on_ItemList_item_selected"
instance SceneConnection "Rss_reader" "HTTPRequest" "request_completed" "RSSReader" "_on_HTTPRequest_request_completed"
instance SceneConnection "Rss_reader" "OpenButton" "pressed" "RSSReader" "_on_OpenButton_pressed"
instance SceneConnection "Rss_reader" "RSSReader" "ready" "RSSReader" "_on_RSSReader_ready"
================================================
FILE: examples/rss-reader/src/Project/Scenes.hs
================================================
-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT
module Project.Scenes (module M) where
import qualified Project.Scenes.Rss_reader as M
================================================
FILE: examples/rss-reader/src/Project/Support.hs
================================================
-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT
{-# LANGUAGE FlexibleContexts, FunctionalDependencies, MultiParamTypeClasses,
UndecidableInstances, OverloadedStrings, TemplateHaskell, TypeApplications,
TypeFamilies, DataKinds, TypeOperators, FlexibleInstances, RankNTypes,
AllowAmbiguousTypes, ScopedTypeVariables, DerivingStrategies,
GeneralizedNewtypeDeriving, LambdaCase #-}
{-# OPTIONS_GHC -Wno-name-shadowing #-}
module Project.Support where
import Godot.Core.Object
import Godot.Internal.Dispatch
import Godot.Gdnative.Internal.Types
import Data.Typeable
import qualified Data.Text as T
import qualified Data.Map as M
import Language.Haskell.TH
import Language.Haskell.TH.Datatype
import Control.Lens
import Control.Monad
import Godot
import Godot.Gdnative
import GHC.TypeLits
import Data.List
import Data.Maybe
import Data.Coerce
import Godot.Core.ResourceLoader
import Godot.Core.PackedScene
-- * Helper to keep Haskell types in sync with the Godot project.
newtype PackedScene' (scene :: Symbol) = PackedScene' PackedScene
deriving newtype AsVariant
instance HasBaseClass (PackedScene' scene) where
type BaseClass (PackedScene' scene) = PackedScene
super = coerce
deriveBase ''PackedScene'
-- | Use this to register all of your classes, it makes sure that you don't
-- forget a class that Godot needs.
--
-- exports :: GdnativeHandle -> IO ()
-- exports desc = registerAll' @Nodes @'[HUD, Main, Mob, Player] desc
registerAll' :: forall (res :: [*]) (ns :: [*]). ImplementedInHaskell res ns => GdnativeHandle -> IO ()
registerAll' = fill @res @ns
-- | A safe version of getNode; gives you back the Godot object
-- getNode' @"MobPath/MobSpawnLocation" self
getNode' :: forall label b cls scene name. (Object :< cls, Node :< cls,
Node :< b,
NodeInScene scene name cls,
SceneNode scene label,
SceneNodeType scene label ~ b,
KnownSymbol label)
=> cls -> IO b
getNode' o = getNode @(SceneNodeType scene label) o (T.pack $ symbolVal (Proxy @label))
-- | A safe version of getNodeNativeScript; gives you back the Haskell object
-- getNodeNativeScript' @"HUD" self
getNodeNativeScript' :: forall label b cls scene name scene' label'.
(NativeScript b, Node :< cls, Object :< cls, NodeInScene scene name cls,
SceneNodeIsHaskell scene label ~ 'Just '(scene', label'),
NodeInScene scene' label' b,
KnownSymbol label)
=> cls -> IO b
getNodeNativeScript' cls = getNodeNativeScript @b cls (T.pack $ symbolVal (Proxy @label))
-- | A safe version of emit_signal; will error at compile time if the signal doesn't exist
-- emit_signal' @"hit" self []
-- TODO We don't check arguments yet!
emit_signal' :: forall label args cls.
(Object :< cls, Object :< cls, NodeSignal cls label args, KnownSymbol label)
=> cls -> [Variant 'GodotTy] -> IO ()
emit_signal' cls args = do
name <- toLowLevel (T.pack $ symbolVal (Proxy @label))
emit_signal cls name args
-- | A safe version of await; will error at compile time if the signal and nodes don't exist
-- await' @"MessageTimer" @"timeout" self $ \self' -> pure ()
await' :: forall (label :: Symbol) (signal :: Symbol) a b cls scene name.
(NodeInScene scene name cls, NativeScript cls, KnownSymbol label, KnownSymbol signal,
SceneNode scene label, Node :< cls, AsVariant a, Node :< SceneNodeType scene label,
NodeSignal b signal '[], SceneNodeType scene label ~ b)
=> cls -> (cls -> IO a) -> IO ()
await' o f = do
n <- getNode' @label o
await o n (T.pack $ symbolVal (Proxy @signal)) f
-- | Preload a scene so you can instantiate it later.
-- Use this when the scene is known ahead of time. Store scenes in as @PackedScene' "SceneName"@
preloadScene :: forall scene. (KnownSymbol scene, SceneResourcePath scene) => IO (PackedScene' scene)
preloadScene = do
Just r <- getSingleton @ResourceLoader
path <- toLowLevel $ sceneResourcePath @scene
PackedScene' <$> (tryCast' =<< load r path Nothing Nothing)
-- | Create an instance of a scene from a @PackedScene' "SceneName"@
-- Makes sure that you are getting the type of the scene root.
sceneInstance :: forall scene o. (Node :< o, Typeable o, AsVariant o, SceneNodeType scene (SceneRootNode scene) ~ o) => PackedScene' scene -> IO o
sceneInstance e = tryCast' =<< instance' e Nothing
-- | Combines nodeMethod with getNode' to call functions in a type-safe way
-- Provides no additional safety compared to using the two separately, but does clean up code a bit.
-- For example: fn @"MyNode" @"hide" self
fn :: forall (node :: Symbol) (func :: Symbol) scene name cls args ret b.
(Object :< cls, Node :< cls,
Node :< SceneNodeType scene node,
NodeInScene scene name cls, SceneNode scene node,
NodeMethodSuper (SceneNodeType scene node) func args ret,
ListToFun args ret ~ IO b, KnownSymbol node) => cls -> IO b
fn self = nodeMethod' @_ @func =<< getNode' @node self
-- | Get the file path to the scene
class SceneResourcePath (scene :: Symbol) where
sceneResourcePath :: forall scene. T.Text
-- * Internal helpers: You won't use these
-- | The root node of a scene
class SceneRoot (scene :: Symbol) where
type SceneRootNode scene :: Symbol
-- | A node in the scene, we know its type and its name, @s@ is the path relate
-- to the scene
class (Typeable (SceneNodeType scene s),
AsVariant (SceneNodeType scene s),
Object :< SceneNodeType scene s) => SceneNode (scene :: Symbol) (s :: Symbol) where
type SceneNodeType scene s :: *
type SceneNodeName scene s :: Symbol
type SceneNodeIsHaskell scene s :: Maybe (Symbol, Symbol)
-- | You declare this for your types. You offer up a haskell type, @n@, for the
-- node. This class verifies that your base class is correct.
class (HasBaseClass n, BaseClass n ~ SceneNodeType scene s) =>
NodeInScene (scene :: Symbol) (s :: Symbol) n | scene s -> n, n -> scene s
-- | A connection between nodes in a scene. @from@ and @to@ are paths.
-- It connects @signal@ in @from@ to @method@ in @to@.
class SceneConnection (scene :: Symbol) (from :: Symbol) (signal :: Symbol) (to :: Symbol) (method :: Symbol)
-- | Internal, just for convenience
data OneResourceNode (resource :: Symbol) (name :: Symbol)
-- | Internal. Don't touch this and don't make instances of it. It's the
-- workhorse for making sure that you are implementing all of the classes that
-- Godot needs, nothing more and nothing less.
class ImplementedInHaskell (a :: [*]) (b :: [*]) where
fill :: GdnativeHandle -> IO ()
instance ImplementedInHaskell '[] '[] where
fill _ = pure ()
registerOne :: forall ty. (NativeScript ty, AsVariant (BaseClass ty)) => GdnativeHandle -> IO ()
registerOne desc = registerClass $ RegClass desc $ classInit @ty
instance (NodeInScene scene name n,
NativeScript n, AsVariant (BaseClass n),
ImplementedInHaskell t t',
SceneNodeIsHaskell scene name ~ 'Just '(resource, name))
=> ImplementedInHaskell (OneResourceNode resource name ': t) (n ': t') where
fill handle = do
registerOne @n handle
fill @t @t' handle
-- | Create a signal
-- TODO args ~ '[] is temproary, we need signeltons to reflect this into a runtime value
signal' :: forall cls label args.
(NodeSignal cls label args, KnownSymbol label, args ~ '[])
=> (Text, [SignalArgument])
signal' = signal (T.pack $ symbolVal (Proxy @label)) []
createMVarProperty' :: (Typeable ty, AsVariant ty) => Text
-> (node -> MVar ty)
-- ^ We typically can't do IO (for initialisation) when calling this, in
-- which case we need to annotate the type without providing a value.
-> Either VariantType ty
-> (node -> IO ty
,node -> ty -> IO ()
,Maybe (Object -> node -> IO GodotVariant
,Object -> node -> GodotVariant -> IO ()
,PropertyAttributes))
createMVarProperty' name fieldName tyOrVal =
(readMVar . fieldName,
\c t -> propertySetter p undefined c =<< toGodotVariant t,
Just (propertyGetter p, propertySetter p, propertyAttrs p))
where p = createMVarProperty name fieldName tyOrVal
appsT :: Type -> [Type] -> Type
appsT t [] = t
appsT t (x:xs) = appsT (AppT t x) xs
-- | Verify that the signal connects to an endpoint that exists and has the right type.
witnessConnection :: forall (scene :: Symbol) (from :: Symbol) (signal :: Symbol) (to :: Symbol) (method :: Symbol) parent sigTy hTy.
(SceneNode scene to,
NodeSignal parent signal sigTy,
-- TODO This the check unsound, but SceneNodeType isn't right for this constraint. What is?
-- The warning produced because 'from' is not used is a reminder of this issue.
-- parent :< SceneNodeType scene from,
NodeMethod hTy method sigTy (IO ()),
NodeInScene scene to hTy) => ()
witnessConnection = ()
-- | Sets up a class
class NodeInit n where
init :: BaseClass n -> IO n
-- | You never implement this. It's a helper so that we can have a more
-- polymorphic call to nodeMethod which will work when the method is implemneted
-- for any parent of the current node.
class NodeMethodSuper node (name :: Symbol) (args :: [*]) (ret :: *) | node name -> args, node name -> ret where
nodeMethod' :: node -> ListToFun args ret
-- | An instance that supports calling nodeMethod' on your parents This can lead
-- to infinite loops in the type checker on error, so we isolate it in
-- NodeMethodSuper instead of NodeMethod.
instance {-# OVERLAPPABLE #-} (NodeMethod (BaseClass node) name arg ret, HasBaseClass node)
=> NodeMethodSuper node name arg ret where
nodeMethod' = nodeMethod' @node @name @arg @ret
mkProperty' :: forall node (name :: Symbol) ty. (NodeProperty node name ty 'False, KnownSymbol name) => ClassProperty node
mkProperty' = ClassProperty (T.pack $ symbolVal (Proxy @name)) a s g
where (_,_,Just (g,s,a)) = nodeProperty @node @name @ty @'False
-- | You should use this as:
-- setupNode ''Ty
-- deriveBase ''Ty
-- This will instantiate everything that your Object needs
setupNode :: Name -> String -> String -> Q [Dec]
setupNode ty scene sceneNode = do
-- Collect information about all scenes
tree <- map unTree . classInstances <$> reify ''(:<)
sceneRoots <- M.fromList . map unSceneRootNode . familyInstances <$> reify ''SceneRootNode
sceneNodes <- map unSceneNodeType . familyInstances <$> reify ''SceneNodeType
haskellNodes <- map unNodeInScene . classInstances <$> reify ''NodeInScene
allSignals <- map unNodeSignal . classInstances <$> reify ''NodeSignal
-- Collect information about our node
rdt <- reifyDatatype ty
let base = case datatypeCons rdt of
(c:_) -> case (constructorFields c, constructorVariant c) of
(ConT baseTy:_, RecordConstructor (baseFn:_)) -> Just (baseTy, baseFn)
_ -> Nothing
_ -> Nothing
--
methods <- filter (\i -> i^._1 == ty) . mapMaybe unNodeMethod . classInstances <$> reify ''NodeMethod
properties <- filter (\i -> i^._1 == ty) . mapMaybe unNodeProperty . classInstances <$> reify ''NodeProperty
let signals = filter (\i -> i^._1 == ty) allSignals
connections <- filter (\i -> i^._1 == scene && i^._4 == sceneNode) . map unConnect . classInstances <$> reify ''SceneConnection
-- Helpers
let parentsOf cls = map snd $ filter (\(c,_) -> cls == c) tree
let nodeToType :: String -> String -> Name
nodeToType scene node = case (hty, ty ^. _4) of
(Just t, _) -> t
(_, Nothing) -> ty ^. _3
(_, Just scene') -> case M.lookup scene' sceneRoots of
Nothing -> error $ "Looking up the root of a scene that is lacking one. This is a bug. " ++ show (scene', scene, node)
Just node' -> nodeToType scene' node'
where ty = fromJust $ find (\n -> n^._1 == scene && n^._2 == node) sceneNodes
hty = (^._3) <$> find (\n -> n^._1 == scene && n^._2 == node) haskellNodes
let resolveSignalActualClass scene from signal =
case mapMaybe (\p -> (p,) <$> find (\s -> s^._2 == signal && s^._1 == p) allSignals) $ parentsOf (nodeToType scene from) of
-- The root issue is that the signal might not yet exist.
-- If witnessConnection was not unsound, this would not be needed as the error would happen later.
[] -> error $ "Class " ++ show from ++ " used in scene " ++ show scene ++ " is lacking a signal named " ++ show signal ++ "\n" ++ show (nodeToType scene from) ++ "\n" ++ show (parentsOf (nodeToType scene from))
(h:_) -> h ^. _1
-- Debug
when False $ runIO $ do
putStrLn "Regenerating .."
print rdt
putStrLn "\nScene roots:"
print sceneRoots
putStrLn "\nScene nodes types:"
mapM_ print sceneNodes
putStrLn "\nMethods:"
mapM_ print methods
putStrLn "\nProperties:"
mapM_ print properties
putStrLn "\nSignals:"
mapM_ print allSignals
mapM_ print signals
putStrLn "\nConnections:"
mapM_ print connections
putStrLn "\nHaskell nodes:"
mapM_ print haskellNodes
-- Generate code
bi <- case base of
Just (baseTy, baseFn) ->
[d|instance HasBaseClass $(pure $ PromotedT ty) where
type BaseClass $(pure $ PromotedT ty) = $(pure $ PromotedT baseTy)
super = $(pure $ VarE baseFn)|]
_ -> error "setupNode can only handle records whose first field is the Godot base class. You can still interface with Godot, but you will need to set things up manually."
nis <- [d|instance NodeInScene $(pure $ LitT $ StrTyLit scene) $(pure $ LitT $ StrTyLit sceneNode) $(pure $ PromotedT ty)|]
ns <- [d|instance NativeScript $(pure $ PromotedT ty) where
classInit = Project.Support.init
classMethods = $(ListE <$> mapM (\(t,n,argTy,_) ->
let m = case nrArguments argTy of
0 -> [e|method0|]
1 -> [e|method1|]
2 -> [e|method2|]
3 -> [e|method3|]
4 -> [e|method4|]
5 -> [e|method5|]
n -> error $ "More arguments than we currently impelement, look for 'method5' for more info " ++ show n
in [e|$m $(pure $ LitE $ StringL n) (nodeMethod @ $(pure $ PromotedT t) @ $(pure $ LitT $ StrTyLit n))|]) methods)
classProperties = $(ListE <$> mapM (\(name,prop,_,_) -> [e|mkProperty' @ $(pure $ PromotedT name) @ $(pure $ LitT $ StrTyLit prop) |]) properties)
classSignals = $(ListE <$> mapM (\(ty,name,_) -> [e|signal' @ $(pure $ PromotedT ty) @ $(pure $ LitT $ StrTyLit name)|]) signals)|]
let cn = mkName $ "witness_connections_" ++ nameBase ty
ws <- (:) <$> (cn `sigD` [t| [()] |]) <*>
[d|$(varP cn) =
$(ListE <$> mapM (\(scene,from,signal,to,method) ->
[e|witnessConnection
@ $(pure $ LitT $ StrTyLit scene) @ $(pure $ LitT $ StrTyLit from)
@ $(pure $ LitT $ StrTyLit signal) @ $(pure $ LitT $ StrTyLit to)
@ $(pure $ LitT $ StrTyLit method)
@ $(pure $ PromotedT $ resolveSignalActualClass scene from signal)
|]) connections)|]
pure $ bi <> nis <> ns <> ws
where
unTree (InstanceD Nothing [] (AppT (AppT _ parent) child) []) = (unName child, unName parent)
unTree p = error $ "I don't understand this parent " ++ show p
unName (ConT x) = x
unName (AppT (ConT x) _) = x
unName x = error $ "I don't know how to extract the name of this type: " ++ show x
unSceneRootNode (TySynInstD (TySynEqn Nothing (AppT _ (LitT (StrTyLit scene))) (LitT (StrTyLit node)))) = (scene,node)
unSceneRootNode x = error $ "Don't know how unpack this SceneRootNode: " ++ show x
unSceneNodeType (TySynInstD (TySynEqn Nothing (AppT (AppT _ (LitT (StrTyLit scene))) (LitT (StrTyLit node))) ty))
= (scene,node,unName ty, unpackScene ty)
unSceneNodeType x = error $ "Don't know how unpack this SceneNodeType: " ++ show x
unpackScene (ConT _) = Nothing
unpackScene (AppT (ConT _) (LitT (StrTyLit scene))) = Just scene
unpackScene x = error $ "Don't know how unpack this Scene: " ++ show x
unNodeMethod (InstanceD Nothing [] (AppT (AppT (AppT (AppT (ConT _) (ConT cls)) (LitT (StrTyLit name))) arg) ret) [])
= Just (cls, name, arg, ret)
unNodeMethod _ = Nothing
unNodeProperty (InstanceD Nothing [] (AppT (AppT (AppT (AppT (ConT _) (ConT cls)) (LitT (StrTyLit name))) arg) ret) [])
= Just (cls, name, arg, ret)
unNodeProperty x = error $ show x
unNodeInScene (InstanceD Nothing [] (AppT (AppT (AppT (ConT _) (LitT (StrTyLit scene))) (LitT (StrTyLit node))) (ConT hty)) [])
= (scene, node, hty)
unNodeInScene x = error $ show x
unNodeSignal (InstanceD Nothing [] (AppT (AppT (AppT (ConT _) (ConT cls)) (LitT (StrTyLit name))) arg) []) = (cls, name, arg)
unNodeSignal _ = error "Bad signal"
unConnect (InstanceD Nothing [] (AppT (AppT (AppT (AppT (AppT _ (LitT (StrTyLit scene))) (LitT (StrTyLit from))) (LitT (StrTyLit signal))) (LitT (StrTyLit to))) (LitT (StrTyLit method))) []) = (scene, from, signal, to, method)
unConnect x = error $ "Bad signal" ++ show x
nrArguments :: Type -> Int
nrArguments (AppT _ r) = 1 + nrArguments r
nrArguments (SigT PromotedNilT (AppT ListT StarT)) = 0
nrArguments _ = error "Can't compute # of arguments"
classInstances :: Info -> [InstanceDec]
classInstances (ClassI _ is) = is
classInstances _ = error "Bad class"
familyInstances :: Info -> [InstanceDec]
familyInstances (FamilyI _ is) = is
familyInstances _ = error "Bad class"
================================================
FILE: examples/rss-reader/stack-shell.nix
================================================
{ nixpkgs ? import ./pinned-nixpkgs.nix {}
, ghc
}:
with nixpkgs;
haskell.lib.buildStackProject {
inherit ghc;
name = "myproject";
buildInputs = [];
}
================================================
FILE: examples/rss-reader/stack.yaml
================================================
resolver: nightly-2021-02-06
packages:
- .
extra-deps:
- ../../
require-stack-version: ">=1.8"
nix:
enable: false
pure: true
packages: []
shell-file: stack-shell.nix
nix-shell-options: []
path: []
add-gc-roots: false
================================================
FILE: examples/top-down-ten-minutes/.gitignore
================================================
dist*
*.hi
*.o
.stack-work/
.stack-work-devel/
*~
\#*
*.import
result
================================================
FILE: examples/top-down-ten-minutes/ChangeLog.md
================================================
# Empty
================================================
FILE: examples/top-down-ten-minutes/LICENSE
================================================
BSD 3-Clause License
Copyright (c) Andrei Barbu 2019
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: examples/top-down-ten-minutes/Makefile
================================================
NAME = top-down-ten-minutes
STACKLIBFILE = $(shell stack path --local-install-root)/lib/lib$(NAME).so
GODOTPROJECT = $(shell stack path --project-root)/game
all: stack
nix:
nix-build shell.nix
cp result/lib/ghc-*/lib$(NAME).so $(GODOTPROJECT)/lib
stack:
stack build --fast --force-dirty
cp $(STACKLIBFILE) $(GODOTPROJECT)/lib
stack-nix:
stack --nix clean $(NAME)
stack --nix build
cp $(shell stack --nix path --local-install-root)/lib/lib$(NAME).so $(GODOTPROJECT)/lib
stack-run:
stack build
cp $(STACKLIBFILE) $(GODOTPROJECT)/lib
godot -e --path ./game
stack-watch:
stack build --file-watch --fast --exec "cp $(STACKLIBFILE) $(GODOTPROJECT)/lib"
project-watch:
stack exec godot-haskell-project-generator game src
updatelib:
cp $(STACKLIBFILE) $(GODOTPROJECT)/lib
================================================
FILE: examples/top-down-ten-minutes/README.md
================================================
The official Godot demo from the manual: Dodge the Creeps.
Run with `make stack` then `godot game/project.godot` and press F5 to start, F8 to end.
Requires Godot 3.1
================================================
FILE: examples/top-down-ten-minutes/ffi/cbits/flib.c
================================================
#include "HsFFI.h"
static void flib_init() __attribute__((constructor));
static void flib_init() {
static char *argv[] = { "libGodotHaskellPlugin.so", 0 }, **argv_ = argv;
static int argc = 1;
hs_init(&argc, &argv_);
}
static void flib_fini() __attribute__((destructor));
static void flib_fini() {
hs_exit();
}
================================================
FILE: examples/top-down-ten-minutes/ffi/flib/FLib.hs
================================================
{-# LANGUAGE ForeignFunctionInterface #-}
module FLib where
import qualified Foreign
import Foreign(nullPtr, Ptr,newForeignPtr_,castPtr)
import qualified Godot.Gdnative.Internal as FFI
import Godot.Gdnative
import Godot.Nativescript
import Lib
import qualified Data.Text as T
import qualified Data.Text.IO as T
godot_nativescript_init :: GdnativeHandle -> IO ()
godot_nativescript_init desc = do
defaultExports desc
exports desc
putStrLn "Haskell NativeScript lib initialized"
foreign export ccall godot_nativescript_init :: GdnativeHandle -> IO ()
godot_gdnative_init :: FFI.GdnativeInitOptionsPtr -> IO ()
godot_gdnative_init opts = do
Foreign.peek opts >>= FFI.initApiStructs
foreign export ccall godot_gdnative_init :: FFI.GdnativeInitOptionsPtr -> IO ()
godot_gdnative_terminate :: FFI.GdnativeTerminateOptionsPtr -> IO ()
godot_gdnative_terminate handle = pure ()
foreign export ccall godot_gdnative_terminate :: FFI.GdnativeTerminateOptionsPtr -> IO ()
================================================
FILE: examples/top-down-ten-minutes/game/Bullet.gdns
================================================
[gd_resource type="NativeScript" load_steps=2 format=2]
[ext_resource path="res://lib/libtop-down-ten-minutes.gdnlib" type="GDNativeLibrary" id=1]
[resource]
resource_name = "Bullet"
class_name = "Bullet"
library = ExtResource( 1 )
================================================
FILE: examples/top-down-ten-minutes/game/Bullet.tscn
================================================
[gd_scene load_steps=5 format=2]
[ext_resource path="res://Player.png" type="Texture" id=1]
[ext_resource path="res://Bullet.gdns" type="Script" id=2]
[sub_resource type="RectangleShape2D" id=1]
extents = Vector2( 4, 1.6 )
[sub_resource type="Animation" id=2]
resource_name = "fadeout"
length = 0.4
tracks/0/type = "value"
tracks/0/path = NodePath("Sprite:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.3 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Color( 1, 1, 1, 1 ), Color( 0.45098, 0.447059, 0.447059, 0 ) ]
}
[node name="Bullet" type="RigidBody2D"]
collision_layer = 8
continuous_cd = 1
contacts_reported = 1
contact_monitor = true
script = ExtResource( 2 )
[
gitextract_kt3cl1ny/ ├── .gitignore ├── .gitmodules ├── .hlint.yaml ├── .travis.yml ├── .vscode/ │ └── tasks.json ├── LICENSE ├── README.md ├── Setup.hs ├── cbits/ │ └── util.h ├── classgen/ │ ├── README.md │ ├── app-classgen/ │ │ └── Main.hs │ ├── default.nix │ ├── godot-haskell-classgen.cabal │ ├── package.yaml │ ├── release.nix │ ├── src-classgen/ │ │ └── Classgen/ │ │ ├── Docs.hs │ │ ├── Module.hs │ │ ├── Spec.hs │ │ └── Utils.hs │ └── stack.yaml ├── default.nix ├── examples/ │ ├── dodge-the-creeps/ │ │ ├── .gitignore │ │ ├── ChangeLog.md │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── README.md │ │ ├── Support.hs │ │ ├── ffi/ │ │ │ ├── cbits/ │ │ │ │ └── flib.c │ │ │ └── flib/ │ │ │ └── FLib.hs │ │ ├── game/ │ │ │ ├── HUD.gdns │ │ │ ├── HUD.tres │ │ │ ├── HUD.tscn │ │ │ ├── Main.gdns │ │ │ ├── Main.tscn │ │ │ ├── Mob.gdns │ │ │ ├── Mob.tscn │ │ │ ├── Player.gdns │ │ │ ├── Player.tscn │ │ │ ├── dodge_assets/ │ │ │ │ ├── art/ │ │ │ │ │ └── House In a Forest Loop.ogg │ │ │ │ └── fonts/ │ │ │ │ ├── FONTLOG.txt │ │ │ │ └── LICENSE.txt │ │ │ ├── lib/ │ │ │ │ └── libmyproject.gdnlib │ │ │ └── project.godot │ │ ├── godot-haskell.nix │ │ ├── hie.yaml │ │ ├── myproject.cabal │ │ ├── package.yaml │ │ ├── pinned-nixpkgs.nix │ │ ├── shell.nix │ │ ├── src/ │ │ │ ├── Game/ │ │ │ │ ├── HUD.hs │ │ │ │ ├── Main.hs │ │ │ │ ├── Mob.hs │ │ │ │ └── Player.hs │ │ │ ├── Lib.hs │ │ │ └── Project/ │ │ │ ├── Requirements.hs │ │ │ ├── Scenes/ │ │ │ │ ├── HUD.hs │ │ │ │ ├── Main.hs │ │ │ │ ├── Mob.hs │ │ │ │ └── Player.hs │ │ │ ├── Scenes.hs │ │ │ └── Support.hs │ │ ├── stack-shell.nix │ │ └── stack.yaml │ ├── rss-reader/ │ │ ├── .gitignore │ │ ├── ChangeLog.md │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── README.md │ │ ├── Support.hs │ │ ├── ffi/ │ │ │ ├── cbits/ │ │ │ │ └── flib.c │ │ │ └── flib/ │ │ │ └── FLib.hs │ │ ├── game/ │ │ │ ├── Rss_reader.gdns │ │ │ ├── Rss_reader.tscn │ │ │ ├── export_presets.cfg │ │ │ ├── lib/ │ │ │ │ └── libmyproject.gdnlib │ │ │ └── project.godot │ │ ├── godot-haskell.nix │ │ ├── hie.yaml │ │ ├── myproject.cabal │ │ ├── package.yaml │ │ ├── pinned-nixpkgs.nix │ │ ├── shell.nix │ │ ├── src/ │ │ │ ├── Game/ │ │ │ │ ├── RSSReader.hs │ │ │ │ └── q │ │ │ ├── Lib.hs │ │ │ └── Project/ │ │ │ ├── Requirements.hs │ │ │ ├── Scenes/ │ │ │ │ └── Rss_reader.hs │ │ │ ├── Scenes.hs │ │ │ └── Support.hs │ │ ├── stack-shell.nix │ │ └── stack.yaml │ └── top-down-ten-minutes/ │ ├── .gitignore │ ├── ChangeLog.md │ ├── LICENSE │ ├── Makefile │ ├── README.md │ ├── ffi/ │ │ ├── cbits/ │ │ │ └── flib.c │ │ └── flib/ │ │ └── FLib.hs │ ├── game/ │ │ ├── Bullet.gdns │ │ ├── Bullet.tscn │ │ ├── Enemy.gdns │ │ ├── Enemy.tscn │ │ ├── Explosion.tscn │ │ ├── Player.gdns │ │ ├── lib/ │ │ │ └── libtop-down-ten-minutes.gdnlib │ │ ├── project.godot │ │ ├── wall.tres │ │ └── world.tscn │ ├── godot-haskell.nix │ ├── hie.yaml │ ├── package.yaml │ ├── pinned-nixpkgs.nix │ ├── shell.nix │ ├── src/ │ │ ├── Game/ │ │ │ └── World.hs │ │ ├── Lib.hs │ │ └── Project/ │ │ ├── Requirements.hs │ │ ├── Scenes/ │ │ │ ├── Bullet.hs │ │ │ ├── Enemy.hs │ │ │ ├── Explosion.hs │ │ │ └── World.hs │ │ ├── Scenes.hs │ │ └── Support.hs │ ├── stack-shell.nix │ ├── stack.yaml │ └── top-down-ten-minutes.cabal ├── godot-haskell.cabal ├── hie.yaml ├── nix/ │ ├── pinned/ │ │ ├── all-hies.json │ │ ├── default.nix │ │ ├── hie.nix │ │ └── nixpkgs.json │ └── spacemacs-hie.nix ├── nixpkgs-version.json ├── package.yaml ├── pinned-nixpkgs.nix ├── project-generator/ │ └── Main.hs ├── release.nix ├── shell-spacemacs-hie.nix ├── shell.nix ├── src/ │ ├── Godot/ │ │ ├── Api/ │ │ │ └── Types.hs │ │ ├── Api.hs │ │ ├── Core/ │ │ │ ├── ARVRAnchor.hs │ │ │ ├── ARVRCamera.hs │ │ │ ├── ARVRController.hs │ │ │ ├── ARVRInterface.hs │ │ │ ├── ARVRInterfaceGDNative.hs │ │ │ ├── ARVROrigin.hs │ │ │ ├── ARVRPositionalTracker.hs │ │ │ ├── ARVRServer.hs │ │ │ ├── AStar.hs │ │ │ ├── AStar2D.hs │ │ │ ├── AcceptDialog.hs │ │ │ ├── AnimatedSprite.hs │ │ │ ├── AnimatedSprite3D.hs │ │ │ ├── AnimatedTexture.hs │ │ │ ├── Animation.hs │ │ │ ├── AnimationNode.hs │ │ │ ├── AnimationNodeAdd2.hs │ │ │ ├── AnimationNodeAdd3.hs │ │ │ ├── AnimationNodeAnimation.hs │ │ │ ├── AnimationNodeBlend2.hs │ │ │ ├── AnimationNodeBlend3.hs │ │ │ ├── AnimationNodeBlendSpace1D.hs │ │ │ ├── AnimationNodeBlendSpace2D.hs │ │ │ ├── AnimationNodeBlendTree.hs │ │ │ ├── AnimationNodeOneShot.hs │ │ │ ├── AnimationNodeOutput.hs │ │ │ ├── AnimationNodeStateMachine.hs │ │ │ ├── AnimationNodeStateMachinePlayback.hs │ │ │ ├── AnimationNodeStateMachineTransition.hs │ │ │ ├── AnimationNodeTimeScale.hs │ │ │ ├── AnimationNodeTimeSeek.hs │ │ │ ├── AnimationNodeTransition.hs │ │ │ ├── AnimationPlayer.hs │ │ │ ├── AnimationRootNode.hs │ │ │ ├── AnimationTree.hs │ │ │ ├── AnimationTreePlayer.hs │ │ │ ├── Area.hs │ │ │ ├── Area2D.hs │ │ │ ├── ArrayMesh.hs │ │ │ ├── AtlasTexture.hs │ │ │ ├── AudioBusLayout.hs │ │ │ ├── AudioEffect.hs │ │ │ ├── AudioEffectAmplify.hs │ │ │ ├── AudioEffectBandLimitFilter.hs │ │ │ ├── AudioEffectBandPassFilter.hs │ │ │ ├── AudioEffectChorus.hs │ │ │ ├── AudioEffectCompressor.hs │ │ │ ├── AudioEffectDelay.hs │ │ │ ├── AudioEffectDistortion.hs │ │ │ ├── AudioEffectEQ.hs │ │ │ ├── AudioEffectEQ10.hs │ │ │ ├── AudioEffectEQ21.hs │ │ │ ├── AudioEffectEQ6.hs │ │ │ ├── AudioEffectFilter.hs │ │ │ ├── AudioEffectHighPassFilter.hs │ │ │ ├── AudioEffectHighShelfFilter.hs │ │ │ ├── AudioEffectInstance.hs │ │ │ ├── AudioEffectLimiter.hs │ │ │ ├── AudioEffectLowPassFilter.hs │ │ │ ├── AudioEffectLowShelfFilter.hs │ │ │ ├── AudioEffectNotchFilter.hs │ │ │ ├── AudioEffectPanner.hs │ │ │ ├── AudioEffectPhaser.hs │ │ │ ├── AudioEffectPitchShift.hs │ │ │ ├── AudioEffectRecord.hs │ │ │ ├── AudioEffectReverb.hs │ │ │ ├── AudioEffectSpectrumAnalyzer.hs │ │ │ ├── AudioEffectSpectrumAnalyzerInstance.hs │ │ │ ├── AudioEffectStereoEnhance.hs │ │ │ ├── AudioServer.hs │ │ │ ├── AudioStream.hs │ │ │ ├── AudioStreamGenerator.hs │ │ │ ├── AudioStreamGeneratorPlayback.hs │ │ │ ├── AudioStreamMicrophone.hs │ │ │ ├── AudioStreamOGGVorbis.hs │ │ │ ├── AudioStreamPlayback.hs │ │ │ ├── AudioStreamPlaybackResampled.hs │ │ │ ├── AudioStreamPlayer.hs │ │ │ ├── AudioStreamPlayer2D.hs │ │ │ ├── AudioStreamPlayer3D.hs │ │ │ ├── AudioStreamRandomPitch.hs │ │ │ ├── AudioStreamSample.hs │ │ │ ├── BackBufferCopy.hs │ │ │ ├── BakedLightmap.hs │ │ │ ├── BakedLightmapData.hs │ │ │ ├── BaseButton.hs │ │ │ ├── BitMap.hs │ │ │ ├── BitmapFont.hs │ │ │ ├── Bone2D.hs │ │ │ ├── BoneAttachment.hs │ │ │ ├── BoxContainer.hs │ │ │ ├── BoxShape.hs │ │ │ ├── BulletPhysicsDirectBodyState.hs │ │ │ ├── BulletPhysicsServer.hs │ │ │ ├── Button.hs │ │ │ ├── ButtonGroup.hs │ │ │ ├── CPUParticles.hs │ │ │ ├── CPUParticles2D.hs │ │ │ ├── CSGBox.hs │ │ │ ├── CSGCombiner.hs │ │ │ ├── CSGCylinder.hs │ │ │ ├── CSGMesh.hs │ │ │ ├── CSGPolygon.hs │ │ │ ├── CSGPrimitive.hs │ │ │ ├── CSGShape.hs │ │ │ ├── CSGSphere.hs │ │ │ ├── CSGTorus.hs │ │ │ ├── Camera.hs │ │ │ ├── Camera2D.hs │ │ │ ├── CameraFeed.hs │ │ │ ├── CameraServer.hs │ │ │ ├── CameraTexture.hs │ │ │ ├── CanvasItem.hs │ │ │ ├── CanvasItemMaterial.hs │ │ │ ├── CanvasLayer.hs │ │ │ ├── CanvasModulate.hs │ │ │ ├── CapsuleMesh.hs │ │ │ ├── CapsuleShape.hs │ │ │ ├── CapsuleShape2D.hs │ │ │ ├── CenterContainer.hs │ │ │ ├── CharFXTransform.hs │ │ │ ├── CheckBox.hs │ │ │ ├── CheckButton.hs │ │ │ ├── CircleShape2D.hs │ │ │ ├── ClassDB.hs │ │ │ ├── ClippedCamera.hs │ │ │ ├── CollisionObject.hs │ │ │ ├── CollisionObject2D.hs │ │ │ ├── CollisionPolygon.hs │ │ │ ├── CollisionPolygon2D.hs │ │ │ ├── CollisionShape.hs │ │ │ ├── CollisionShape2D.hs │ │ │ ├── ColorPicker.hs │ │ │ ├── ColorPickerButton.hs │ │ │ ├── ColorRect.hs │ │ │ ├── ConcavePolygonShape.hs │ │ │ ├── ConcavePolygonShape2D.hs │ │ │ ├── ConeTwistJoint.hs │ │ │ ├── ConfigFile.hs │ │ │ ├── ConfirmationDialog.hs │ │ │ ├── Container.hs │ │ │ ├── Control.hs │ │ │ ├── ConvexPolygonShape.hs │ │ │ ├── ConvexPolygonShape2D.hs │ │ │ ├── Crypto.hs │ │ │ ├── CryptoKey.hs │ │ │ ├── CubeMap.hs │ │ │ ├── CubeMesh.hs │ │ │ ├── Curve.hs │ │ │ ├── Curve2D.hs │ │ │ ├── Curve3D.hs │ │ │ ├── CurveTexture.hs │ │ │ ├── CylinderMesh.hs │ │ │ ├── CylinderShape.hs │ │ │ ├── DampedSpringJoint2D.hs │ │ │ ├── DirectionalLight.hs │ │ │ ├── Directory.hs │ │ │ ├── DynamicFont.hs │ │ │ ├── DynamicFontData.hs │ │ │ ├── EncodedObjectAsID.hs │ │ │ ├── Engine.hs │ │ │ ├── Environment.hs │ │ │ ├── Expression.hs │ │ │ ├── File.hs │ │ │ ├── FileDialog.hs │ │ │ ├── Font.hs │ │ │ ├── FuncRef.hs │ │ │ ├── GDNative.hs │ │ │ ├── GDNativeLibrary.hs │ │ │ ├── GDScript.hs │ │ │ ├── GDScriptFunctionState.hs │ │ │ ├── GIProbe.hs │ │ │ ├── GIProbeData.hs │ │ │ ├── Generic6DOFJoint.hs │ │ │ ├── Geometry.hs │ │ │ ├── GeometryInstance.hs │ │ │ ├── GlobalConstants.hs │ │ │ ├── Gradient.hs │ │ │ ├── GradientTexture.hs │ │ │ ├── GraphEdit.hs │ │ │ ├── GraphNode.hs │ │ │ ├── GridContainer.hs │ │ │ ├── GridMap.hs │ │ │ ├── GrooveJoint2D.hs │ │ │ ├── HBoxContainer.hs │ │ │ ├── HScrollBar.hs │ │ │ ├── HSeparator.hs │ │ │ ├── HSlider.hs │ │ │ ├── HSplitContainer.hs │ │ │ ├── HTTPClient.hs │ │ │ ├── HTTPRequest.hs │ │ │ ├── HashingContext.hs │ │ │ ├── HeightMapShape.hs │ │ │ ├── HingeJoint.hs │ │ │ ├── IP.hs │ │ │ ├── IP_Unix.hs │ │ │ ├── Image.hs │ │ │ ├── ImageTexture.hs │ │ │ ├── ImmediateGeometry.hs │ │ │ ├── Input.hs │ │ │ ├── InputDefault.hs │ │ │ ├── InputEvent.hs │ │ │ ├── InputEventAction.hs │ │ │ ├── InputEventGesture.hs │ │ │ ├── InputEventJoypadButton.hs │ │ │ ├── InputEventJoypadMotion.hs │ │ │ ├── InputEventKey.hs │ │ │ ├── InputEventMIDI.hs │ │ │ ├── InputEventMagnifyGesture.hs │ │ │ ├── InputEventMouse.hs │ │ │ ├── InputEventMouseButton.hs │ │ │ ├── InputEventMouseMotion.hs │ │ │ ├── InputEventPanGesture.hs │ │ │ ├── InputEventScreenDrag.hs │ │ │ ├── InputEventScreenTouch.hs │ │ │ ├── InputEventWithModifiers.hs │ │ │ ├── InputMap.hs │ │ │ ├── InstancePlaceholder.hs │ │ │ ├── InterpolatedCamera.hs │ │ │ ├── ItemList.hs │ │ │ ├── JSON.hs │ │ │ ├── JSONParseResult.hs │ │ │ ├── JSONRPC.hs │ │ │ ├── JavaClass.hs │ │ │ ├── JavaClassWrapper.hs │ │ │ ├── JavaScript.hs │ │ │ ├── Joint.hs │ │ │ ├── Joint2D.hs │ │ │ ├── KinematicBody.hs │ │ │ ├── KinematicBody2D.hs │ │ │ ├── KinematicCollision.hs │ │ │ ├── KinematicCollision2D.hs │ │ │ ├── Label.hs │ │ │ ├── LargeTexture.hs │ │ │ ├── Light.hs │ │ │ ├── Light2D.hs │ │ │ ├── LightOccluder2D.hs │ │ │ ├── Line2D.hs │ │ │ ├── LineEdit.hs │ │ │ ├── LineShape2D.hs │ │ │ ├── LinkButton.hs │ │ │ ├── Listener.hs │ │ │ ├── MainLoop.hs │ │ │ ├── MarginContainer.hs │ │ │ ├── Marshalls.hs │ │ │ ├── Material.hs │ │ │ ├── MenuButton.hs │ │ │ ├── Mesh.hs │ │ │ ├── MeshDataTool.hs │ │ │ ├── MeshInstance.hs │ │ │ ├── MeshInstance2D.hs │ │ │ ├── MeshLibrary.hs │ │ │ ├── MeshTexture.hs │ │ │ ├── MobileVRInterface.hs │ │ │ ├── MultiMesh.hs │ │ │ ├── MultiMeshInstance.hs │ │ │ ├── MultiMeshInstance2D.hs │ │ │ ├── MultiplayerAPI.hs │ │ │ ├── MultiplayerPeerGDNative.hs │ │ │ ├── Mutex.hs │ │ │ ├── NativeScript.hs │ │ │ ├── Navigation.hs │ │ │ ├── Navigation2D.hs │ │ │ ├── NavigationMesh.hs │ │ │ ├── NavigationMeshInstance.hs │ │ │ ├── NavigationPolygon.hs │ │ │ ├── NavigationPolygonInstance.hs │ │ │ ├── NetworkedMultiplayerENet.hs │ │ │ ├── NetworkedMultiplayerPeer.hs │ │ │ ├── NinePatchRect.hs │ │ │ ├── Node.hs │ │ │ ├── Node2D.hs │ │ │ ├── NoiseTexture.hs │ │ │ ├── OS.hs │ │ │ ├── Object.hs │ │ │ ├── OccluderPolygon2D.hs │ │ │ ├── OmniLight.hs │ │ │ ├── OpenSimplexNoise.hs │ │ │ ├── OptionButton.hs │ │ │ ├── PCKPacker.hs │ │ │ ├── PHashTranslation.hs │ │ │ ├── PackedDataContainer.hs │ │ │ ├── PackedDataContainerRef.hs │ │ │ ├── PackedScene.hs │ │ │ ├── PacketPeer.hs │ │ │ ├── PacketPeerGDNative.hs │ │ │ ├── PacketPeerStream.hs │ │ │ ├── PacketPeerUDP.hs │ │ │ ├── Panel.hs │ │ │ ├── PanelContainer.hs │ │ │ ├── PanoramaSky.hs │ │ │ ├── ParallaxBackground.hs │ │ │ ├── ParallaxLayer.hs │ │ │ ├── Particles.hs │ │ │ ├── Particles2D.hs │ │ │ ├── ParticlesMaterial.hs │ │ │ ├── Path.hs │ │ │ ├── Path2D.hs │ │ │ ├── PathFollow.hs │ │ │ ├── PathFollow2D.hs │ │ │ ├── Performance.hs │ │ │ ├── PhysicalBone.hs │ │ │ ├── Physics2DDirectBodyState.hs │ │ │ ├── Physics2DDirectBodyStateSW.hs │ │ │ ├── Physics2DDirectSpaceState.hs │ │ │ ├── Physics2DServer.hs │ │ │ ├── Physics2DServerSW.hs │ │ │ ├── Physics2DShapeQueryParameters.hs │ │ │ ├── Physics2DShapeQueryResult.hs │ │ │ ├── Physics2DTestMotionResult.hs │ │ │ ├── PhysicsBody.hs │ │ │ ├── PhysicsBody2D.hs │ │ │ ├── PhysicsDirectBodyState.hs │ │ │ ├── PhysicsDirectSpaceState.hs │ │ │ ├── PhysicsMaterial.hs │ │ │ ├── PhysicsServer.hs │ │ │ ├── PhysicsShapeQueryParameters.hs │ │ │ ├── PhysicsShapeQueryResult.hs │ │ │ ├── PinJoint.hs │ │ │ ├── PinJoint2D.hs │ │ │ ├── PlaneMesh.hs │ │ │ ├── PlaneShape.hs │ │ │ ├── PluginScript.hs │ │ │ ├── PointMesh.hs │ │ │ ├── Polygon2D.hs │ │ │ ├── PolygonPathFinder.hs │ │ │ ├── Popup.hs │ │ │ ├── PopupDialog.hs │ │ │ ├── PopupMenu.hs │ │ │ ├── PopupPanel.hs │ │ │ ├── Position2D.hs │ │ │ ├── Position3D.hs │ │ │ ├── PrimitiveMesh.hs │ │ │ ├── PrismMesh.hs │ │ │ ├── ProceduralSky.hs │ │ │ ├── ProgressBar.hs │ │ │ ├── ProjectSettings.hs │ │ │ ├── ProximityGroup.hs │ │ │ ├── ProxyTexture.hs │ │ │ ├── QuadMesh.hs │ │ │ ├── RandomNumberGenerator.hs │ │ │ ├── Range.hs │ │ │ ├── RayCast.hs │ │ │ ├── RayCast2D.hs │ │ │ ├── RayShape.hs │ │ │ ├── RayShape2D.hs │ │ │ ├── RectangleShape2D.hs │ │ │ ├── Reference.hs │ │ │ ├── ReferenceRect.hs │ │ │ ├── ReflectionProbe.hs │ │ │ ├── RegEx.hs │ │ │ ├── RegExMatch.hs │ │ │ ├── RemoteTransform.hs │ │ │ ├── RemoteTransform2D.hs │ │ │ ├── Resource.hs │ │ │ ├── ResourceFormatLoader.hs │ │ │ ├── ResourceFormatLoaderCrypto.hs │ │ │ ├── ResourceFormatSaver.hs │ │ │ ├── ResourceFormatSaverCrypto.hs │ │ │ ├── ResourceImporter.hs │ │ │ ├── ResourceInteractiveLoader.hs │ │ │ ├── ResourceLoader.hs │ │ │ ├── ResourcePreloader.hs │ │ │ ├── ResourceSaver.hs │ │ │ ├── RichTextEffect.hs │ │ │ ├── RichTextLabel.hs │ │ │ ├── RigidBody.hs │ │ │ ├── RigidBody2D.hs │ │ │ ├── RootMotionView.hs │ │ │ ├── SceneState.hs │ │ │ ├── SceneTree.hs │ │ │ ├── SceneTreeTimer.hs │ │ │ ├── Script.hs │ │ │ ├── ScrollBar.hs │ │ │ ├── ScrollContainer.hs │ │ │ ├── SegmentShape2D.hs │ │ │ ├── Semaphore.hs │ │ │ ├── Separator.hs │ │ │ ├── Shader.hs │ │ │ ├── ShaderMaterial.hs │ │ │ ├── Shape.hs │ │ │ ├── Shape2D.hs │ │ │ ├── ShortCut.hs │ │ │ ├── Skeleton.hs │ │ │ ├── Skeleton2D.hs │ │ │ ├── SkeletonIK.hs │ │ │ ├── Skin.hs │ │ │ ├── SkinReference.hs │ │ │ ├── Sky.hs │ │ │ ├── Slider.hs │ │ │ ├── SliderJoint.hs │ │ │ ├── SoftBody.hs │ │ │ ├── Spatial.hs │ │ │ ├── SpatialGizmo.hs │ │ │ ├── SpatialMaterial.hs │ │ │ ├── SpatialVelocityTracker.hs │ │ │ ├── SphereMesh.hs │ │ │ ├── SphereShape.hs │ │ │ ├── SpinBox.hs │ │ │ ├── SplitContainer.hs │ │ │ ├── SpotLight.hs │ │ │ ├── SpringArm.hs │ │ │ ├── Sprite.hs │ │ │ ├── Sprite3D.hs │ │ │ ├── SpriteBase3D.hs │ │ │ ├── SpriteFrames.hs │ │ │ ├── StaticBody.hs │ │ │ ├── StaticBody2D.hs │ │ │ ├── StreamPeer.hs │ │ │ ├── StreamPeerBuffer.hs │ │ │ ├── StreamPeerGDNative.hs │ │ │ ├── StreamPeerSSL.hs │ │ │ ├── StreamPeerTCP.hs │ │ │ ├── StreamTexture.hs │ │ │ ├── StyleBox.hs │ │ │ ├── StyleBoxEmpty.hs │ │ │ ├── StyleBoxFlat.hs │ │ │ ├── StyleBoxLine.hs │ │ │ ├── StyleBoxTexture.hs │ │ │ ├── SurfaceTool.hs │ │ │ ├── TCP_Server.hs │ │ │ ├── TabContainer.hs │ │ │ ├── Tabs.hs │ │ │ ├── TextEdit.hs │ │ │ ├── TextFile.hs │ │ │ ├── Texture.hs │ │ │ ├── Texture3D.hs │ │ │ ├── TextureArray.hs │ │ │ ├── TextureButton.hs │ │ │ ├── TextureLayered.hs │ │ │ ├── TextureProgress.hs │ │ │ ├── TextureRect.hs │ │ │ ├── Theme.hs │ │ │ ├── Thread.hs │ │ │ ├── TileMap.hs │ │ │ ├── TileSet.hs │ │ │ ├── Timer.hs │ │ │ ├── ToolButton.hs │ │ │ ├── TouchScreenButton.hs │ │ │ ├── Translation.hs │ │ │ ├── TranslationServer.hs │ │ │ ├── Tree.hs │ │ │ ├── TreeItem.hs │ │ │ ├── TriangleMesh.hs │ │ │ ├── Tween.hs │ │ │ ├── UPNP.hs │ │ │ ├── UPNPDevice.hs │ │ │ ├── UndoRedo.hs │ │ │ ├── VBoxContainer.hs │ │ │ ├── VScrollBar.hs │ │ │ ├── VSeparator.hs │ │ │ ├── VSlider.hs │ │ │ ├── VSplitContainer.hs │ │ │ ├── VehicleBody.hs │ │ │ ├── VehicleWheel.hs │ │ │ ├── VideoPlayer.hs │ │ │ ├── VideoStream.hs │ │ │ ├── VideoStreamGDNative.hs │ │ │ ├── VideoStreamTheora.hs │ │ │ ├── VideoStreamWebm.hs │ │ │ ├── Viewport.hs │ │ │ ├── ViewportContainer.hs │ │ │ ├── ViewportTexture.hs │ │ │ ├── VisibilityEnabler.hs │ │ │ ├── VisibilityEnabler2D.hs │ │ │ ├── VisibilityNotifier.hs │ │ │ ├── VisibilityNotifier2D.hs │ │ │ ├── VisualInstance.hs │ │ │ ├── VisualScript.hs │ │ │ ├── VisualScriptBasicTypeConstant.hs │ │ │ ├── VisualScriptBuiltinFunc.hs │ │ │ ├── VisualScriptClassConstant.hs │ │ │ ├── VisualScriptComment.hs │ │ │ ├── VisualScriptComposeArray.hs │ │ │ ├── VisualScriptCondition.hs │ │ │ ├── VisualScriptConstant.hs │ │ │ ├── VisualScriptConstructor.hs │ │ │ ├── VisualScriptCustomNode.hs │ │ │ ├── VisualScriptDeconstruct.hs │ │ │ ├── VisualScriptEmitSignal.hs │ │ │ ├── VisualScriptEngineSingleton.hs │ │ │ ├── VisualScriptExpression.hs │ │ │ ├── VisualScriptFunction.hs │ │ │ ├── VisualScriptFunctionCall.hs │ │ │ ├── VisualScriptFunctionState.hs │ │ │ ├── VisualScriptGlobalConstant.hs │ │ │ ├── VisualScriptIndexGet.hs │ │ │ ├── VisualScriptIndexSet.hs │ │ │ ├── VisualScriptInputAction.hs │ │ │ ├── VisualScriptIterator.hs │ │ │ ├── VisualScriptLists.hs │ │ │ ├── VisualScriptLocalVar.hs │ │ │ ├── VisualScriptLocalVarSet.hs │ │ │ ├── VisualScriptMathConstant.hs │ │ │ ├── VisualScriptNode.hs │ │ │ ├── VisualScriptOperator.hs │ │ │ ├── VisualScriptPreload.hs │ │ │ ├── VisualScriptPropertyGet.hs │ │ │ ├── VisualScriptPropertySet.hs │ │ │ ├── VisualScriptResourcePath.hs │ │ │ ├── VisualScriptReturn.hs │ │ │ ├── VisualScriptSceneNode.hs │ │ │ ├── VisualScriptSceneTree.hs │ │ │ ├── VisualScriptSelect.hs │ │ │ ├── VisualScriptSelf.hs │ │ │ ├── VisualScriptSequence.hs │ │ │ ├── VisualScriptSubCall.hs │ │ │ ├── VisualScriptSwitch.hs │ │ │ ├── VisualScriptTypeCast.hs │ │ │ ├── VisualScriptVariableGet.hs │ │ │ ├── VisualScriptVariableSet.hs │ │ │ ├── VisualScriptWhile.hs │ │ │ ├── VisualScriptYield.hs │ │ │ ├── VisualScriptYieldSignal.hs │ │ │ ├── VisualServer.hs │ │ │ ├── VisualShader.hs │ │ │ ├── VisualShaderNode.hs │ │ │ ├── VisualShaderNodeBooleanConstant.hs │ │ │ ├── VisualShaderNodeBooleanUniform.hs │ │ │ ├── VisualShaderNodeColorConstant.hs │ │ │ ├── VisualShaderNodeColorFunc.hs │ │ │ ├── VisualShaderNodeColorOp.hs │ │ │ ├── VisualShaderNodeColorUniform.hs │ │ │ ├── VisualShaderNodeCompare.hs │ │ │ ├── VisualShaderNodeCubeMap.hs │ │ │ ├── VisualShaderNodeCubeMapUniform.hs │ │ │ ├── VisualShaderNodeCustom.hs │ │ │ ├── VisualShaderNodeDeterminant.hs │ │ │ ├── VisualShaderNodeDotProduct.hs │ │ │ ├── VisualShaderNodeExpression.hs │ │ │ ├── VisualShaderNodeFaceForward.hs │ │ │ ├── VisualShaderNodeFresnel.hs │ │ │ ├── VisualShaderNodeGlobalExpression.hs │ │ │ ├── VisualShaderNodeGroupBase.hs │ │ │ ├── VisualShaderNodeIf.hs │ │ │ ├── VisualShaderNodeInput.hs │ │ │ ├── VisualShaderNodeIs.hs │ │ │ ├── VisualShaderNodeOuterProduct.hs │ │ │ ├── VisualShaderNodeOutput.hs │ │ │ ├── VisualShaderNodeScalarClamp.hs │ │ │ ├── VisualShaderNodeScalarConstant.hs │ │ │ ├── VisualShaderNodeScalarDerivativeFunc.hs │ │ │ ├── VisualShaderNodeScalarFunc.hs │ │ │ ├── VisualShaderNodeScalarInterp.hs │ │ │ ├── VisualShaderNodeScalarOp.hs │ │ │ ├── VisualShaderNodeScalarSmoothStep.hs │ │ │ ├── VisualShaderNodeScalarSwitch.hs │ │ │ ├── VisualShaderNodeScalarUniform.hs │ │ │ ├── VisualShaderNodeSwitch.hs │ │ │ ├── VisualShaderNodeTexture.hs │ │ │ ├── VisualShaderNodeTextureUniform.hs │ │ │ ├── VisualShaderNodeTextureUniformTriplanar.hs │ │ │ ├── VisualShaderNodeTransformCompose.hs │ │ │ ├── VisualShaderNodeTransformConstant.hs │ │ │ ├── VisualShaderNodeTransformDecompose.hs │ │ │ ├── VisualShaderNodeTransformFunc.hs │ │ │ ├── VisualShaderNodeTransformMult.hs │ │ │ ├── VisualShaderNodeTransformUniform.hs │ │ │ ├── VisualShaderNodeTransformVecMult.hs │ │ │ ├── VisualShaderNodeUniform.hs │ │ │ ├── VisualShaderNodeVec3Constant.hs │ │ │ ├── VisualShaderNodeVec3Uniform.hs │ │ │ ├── VisualShaderNodeVectorClamp.hs │ │ │ ├── VisualShaderNodeVectorCompose.hs │ │ │ ├── VisualShaderNodeVectorDecompose.hs │ │ │ ├── VisualShaderNodeVectorDerivativeFunc.hs │ │ │ ├── VisualShaderNodeVectorDistance.hs │ │ │ ├── VisualShaderNodeVectorFunc.hs │ │ │ ├── VisualShaderNodeVectorInterp.hs │ │ │ ├── VisualShaderNodeVectorLen.hs │ │ │ ├── VisualShaderNodeVectorOp.hs │ │ │ ├── VisualShaderNodeVectorRefract.hs │ │ │ ├── VisualShaderNodeVectorScalarMix.hs │ │ │ ├── VisualShaderNodeVectorScalarSmoothStep.hs │ │ │ ├── VisualShaderNodeVectorScalarStep.hs │ │ │ ├── VisualShaderNodeVectorSmoothStep.hs │ │ │ ├── WeakRef.hs │ │ │ ├── WebRTCDataChannel.hs │ │ │ ├── WebRTCDataChannelGDNative.hs │ │ │ ├── WebRTCMultiplayer.hs │ │ │ ├── WebRTCPeerConnection.hs │ │ │ ├── WebRTCPeerConnectionGDNative.hs │ │ │ ├── WebSocketClient.hs │ │ │ ├── WebSocketMultiplayerPeer.hs │ │ │ ├── WebSocketPeer.hs │ │ │ ├── WebSocketServer.hs │ │ │ ├── WindowDialog.hs │ │ │ ├── World.hs │ │ │ ├── World2D.hs │ │ │ ├── WorldEnvironment.hs │ │ │ ├── X509Certificate.hs │ │ │ ├── XMLParser.hs │ │ │ └── YSort.hs │ │ ├── Gdnative/ │ │ │ ├── Internal/ │ │ │ │ ├── Api.hs │ │ │ │ ├── Gdnative.chs │ │ │ │ ├── TH.hs │ │ │ │ └── Types.hs │ │ │ └── Internal.hs │ │ ├── Gdnative.hs │ │ ├── Internal/ │ │ │ └── Dispatch.hs │ │ ├── Nativescript.hs │ │ └── Tools/ │ │ ├── AnimationTrackEditPlugin.hs │ │ ├── EditorExportPlugin.hs │ │ ├── EditorFeatureProfile.hs │ │ ├── EditorFileDialog.hs │ │ ├── EditorFileSystem.hs │ │ ├── EditorFileSystemDirectory.hs │ │ ├── EditorImportPlugin.hs │ │ ├── EditorInspector.hs │ │ ├── EditorInspectorPlugin.hs │ │ ├── EditorInterface.hs │ │ ├── EditorNavigationMeshGenerator.hs │ │ ├── EditorPlugin.hs │ │ ├── EditorProperty.hs │ │ ├── EditorResourceConversionPlugin.hs │ │ ├── EditorResourcePreview.hs │ │ ├── EditorResourcePreviewGenerator.hs │ │ ├── EditorSceneImporter.hs │ │ ├── EditorSceneImporterAssimp.hs │ │ ├── EditorScenePostImport.hs │ │ ├── EditorScript.hs │ │ ├── EditorSelection.hs │ │ ├── EditorSettings.hs │ │ ├── EditorSpatialGizmo.hs │ │ ├── EditorSpatialGizmoPlugin.hs │ │ ├── EditorSpinSlider.hs │ │ ├── EditorVCSInterface.hs │ │ ├── ScriptCreateDialog.hs │ │ ├── ScriptEditor.hs │ │ └── VisualScriptEditor.hs │ └── Godot.hs ├── src-generate/ │ ├── Generate.hs │ ├── Spec.hs │ ├── Types/ │ │ └── Internal.hs │ └── Types.hs ├── stack-shell.nix ├── stack.yaml ├── template/ │ ├── README.md │ ├── demo/ │ │ ├── Makefile │ │ ├── ffi/ │ │ │ └── cbits/ │ │ │ └── flib.c │ │ └── game/ │ │ ├── Main.gdns │ │ ├── lib/ │ │ │ └── libdemo.gdnlib │ │ └── project.godot │ ├── godot-haskell.hsfiles │ ├── mkdemo.sh │ └── update-template.sh └── update-nixpkgs.sh
SYMBOL INDEX (8 symbols across 4 files)
FILE: examples/dodge-the-creeps/ffi/cbits/flib.c
function flib_init (line 4) | static void flib_init() {
function flib_fini (line 11) | static void flib_fini() {
FILE: examples/rss-reader/ffi/cbits/flib.c
function flib_init (line 4) | static void flib_init() {
function flib_fini (line 11) | static void flib_fini() {
FILE: examples/top-down-ten-minutes/ffi/cbits/flib.c
function flib_init (line 4) | static void flib_init() {
function flib_fini (line 11) | static void flib_fini() {
FILE: template/demo/ffi/cbits/flib.c
function flib_init (line 4) | static void flib_init() {
function flib_fini (line 11) | static void flib_fini() {
Copy disabled (too large)
Download .json
Condensed preview — 788 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (12,040K chars).
[
{
"path": ".gitignore",
"chars": 237,
"preview": "dist*\n*.hi\n*.o\n.hsenv*\ncabal-dev/\n.stack-work/\n.cabal-sandbox\ncabal.sandbox.config\n.DS_Store\n*.dyn_o\n*.dyn_hi\napp/*.cpp\n"
},
{
"path": ".gitmodules",
"chars": 340,
"preview": "[submodule \"godot_headers\"]\n\tpath = godot_headers\n\turl = https://github.com/GodotNativeTools/godot_headers/\n[submodule \""
},
{
"path": ".hlint.yaml",
"chars": 86,
"preview": "- ignore: { name: \"Use camelCase\" }\n- ignore: { name: \"Use newtype instead of data\" }\n"
},
{
"path": ".travis.yml",
"chars": 519,
"preview": "# https://docs.haskellstack.org/en/stable/travis_ci/\n\nsudo: false\ndist: bionic\nlanguage: generic\naddons:\n apt:\n upda"
},
{
"path": ".vscode/tasks.json",
"chars": 1091,
"preview": "\n{\n // Automatically created by phoityne-vscode extension.\n\n \"version\": \"2.0.0\",\n \"presentation\": {\n \"reveal\": \"al"
},
{
"path": "LICENSE",
"chars": 1528,
"preview": "Copyright David Kraeutmann (c) 2018\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or wi"
},
{
"path": "README.md",
"chars": 6038,
"preview": "# godot-haskell\n\n[](https://travis-ci.org"
},
{
"path": "Setup.hs",
"chars": 46,
"preview": "import Distribution.Simple\nmain = defaultMain\n"
},
{
"path": "cbits/util.h",
"chars": 131,
"preview": "#ifndef GODOT_HASKELL_UTIL_H__\n#define GODOT_HASKELL_UTIL_H__\n\n#include <gdnative/gdnative.h>\n\n#endif /* GODOT_HASKELL_U"
},
{
"path": "classgen/README.md",
"chars": 93,
"preview": "Generate bindings to the Godot API.\n\nSee the godot-haskell README.md for instructions on use\n"
},
{
"path": "classgen/app-classgen/Main.hs",
"chars": 4378,
"preview": "import Classgen.Module\nimport Classgen.Spec\nimport Control.Lens\nimport Control.Monad.State\nimport Data.Maybe (mapMaybe)\n"
},
{
"path": "classgen/default.nix",
"chars": 3469,
"preview": "{ mkDerivation, aeson, base, bytestring, c2hs, casing, containers\n, directory, filepath, hpack\n, lens, mtl, template-has"
},
{
"path": "classgen/godot-haskell-classgen.cabal",
"chars": 2436,
"preview": "cabal-version: 1.12\n\n-- This file has been generated from package.yaml by hpack version 0.31.1.\n--\n-- see: https://githu"
},
{
"path": "classgen/package.yaml",
"chars": 1120,
"preview": "name: godot-haskell-classgen\nversion: '0.1.0.0'\ncategory: Web\nauthor: David Kraeutmann\nmaintainer: kane@kane.cx\ncopyrigh"
},
{
"path": "classgen/release.nix",
"chars": 91,
"preview": "let\n pkgs = import <nixpkgs> { };\nin\n pkgs.haskellPackages.callPackage ./default.nix { }\n"
},
{
"path": "classgen/src-classgen/Classgen/Docs.hs",
"chars": 5668,
"preview": "{-# LANGUAGE TemplateHaskell, GeneralizedNewtypeDeriving, OverloadedStrings #-}\n{-# OPTIONS_GHC -Wno-orphans #-}\nmodule "
},
{
"path": "classgen/src-classgen/Classgen/Module.hs",
"chars": 24891,
"preview": "{-# LANGUAGE NoMonoLocalBinds, NoMonomorphismRestriction #-}\nmodule Classgen.Module where\n\nimport Control.Lens hiding (i"
},
{
"path": "classgen/src-classgen/Classgen/Spec.hs",
"chars": 4061,
"preview": "{-# LANGUAGE TemplateHaskell, GeneralizedNewtypeDeriving, OverloadedStrings #-}\n{-# OPTIONS_GHC -Wno-orphans #-}\nmodule "
},
{
"path": "classgen/src-classgen/Classgen/Utils.hs",
"chars": 477,
"preview": "module Classgen.Utils where\n\nimport Control.Lens\nimport Language.Haskell.TH\n\nfixedTypeFields :: LensRules\nfixedTypeField"
},
{
"path": "classgen/stack.yaml",
"chars": 2247,
"preview": "# This file was automatically generated by 'stack init'\n#\n# Some commonly used options have been documented as comments "
},
{
"path": "default.nix",
"chars": 1146,
"preview": "{ mkDerivation, aeson, ansi-wl-pprint, base, bytestring, c2hs\n, casing, colour, containers, hpack, lens, linear, mtl, pa"
},
{
"path": "examples/dodge-the-creeps/.gitignore",
"chars": 72,
"preview": "dist*\n*.hi\n*.o\n.stack-work/\n.stack-work-devel/\n*~\n\\#*\n*.import\nresult\n\n\n"
},
{
"path": "examples/dodge-the-creeps/ChangeLog.md",
"chars": 10,
"preview": "# Empty\n\n\n"
},
{
"path": "examples/dodge-the-creeps/LICENSE",
"chars": 1512,
"preview": "BSD 3-Clause License\n\nCopyright (c) Andrei Barbu 2019\nAll rights reserved.\n\nRedistribution and use in source and binary "
},
{
"path": "examples/dodge-the-creeps/Makefile",
"chars": 767,
"preview": "NAME = myproject\nSTACKLIBFILE = $(shell stack path --local-install-root)/lib/lib$(NAME).so\nGODOTPROJECT = $(shell stack "
},
{
"path": "examples/dodge-the-creeps/README.md",
"chars": 168,
"preview": "The official Godot demo from the manual: Dodge the Creeps.\n\nRun with `make stack` then `godot game/project.godot` and pr"
},
{
"path": "examples/dodge-the-creeps/Support.hs",
"chars": 512,
"preview": "{-# LANGUAGE FlexibleContexts, FunctionalDependencies, MultiParamTypeClasses, OverloadedLabels, UndecidableInstances,\n "
},
{
"path": "examples/dodge-the-creeps/ffi/cbits/flib.c",
"chars": 321,
"preview": "#include \"HsFFI.h\"\n\nstatic void flib_init() __attribute__((constructor));\nstatic void flib_init() {\n static char *argv["
},
{
"path": "examples/dodge-the-creeps/ffi/flib/FLib.hs",
"chars": 1023,
"preview": "{-# LANGUAGE ForeignFunctionInterface #-}\nmodule FLib where\n\nimport qualified Foreign\nimport Foreign(nullPtr, "
},
{
"path": "examples/dodge-the-creeps/game/HUD.gdns",
"chars": 217,
"preview": "[gd_resource type=\"NativeScript\" load_steps=2 format=2]\n\n[ext_resource path=\"res://lib/libmyproject.gdnlib\" type=\"GDNati"
},
{
"path": "examples/dodge-the-creeps/game/HUD.tres",
"chars": 203,
"preview": "[gd_resource type=\"DynamicFont\" load_steps=2 format=2]\n\n[ext_resource path=\"res://dodge_assets/fonts/Xolonium-Regular.tt"
},
{
"path": "examples/dodge-the-creeps/game/HUD.tscn",
"chars": 1355,
"preview": "[gd_scene load_steps=5 format=2]\n\n[ext_resource path=\"res://HUD.gdns\" type=\"Script\" id=1]\n[ext_resource path=\"res://HUD."
},
{
"path": "examples/dodge-the-creeps/game/Main.gdns",
"chars": 196,
"preview": "[gd_resource type=\"NativeScript\" load_steps=2 format=2]\n\n[ext_resource path=\"res://lib/libmyproject.gdnlib\" type=\"GDNati"
},
{
"path": "examples/dodge-the-creeps/game/Main.tscn",
"chars": 1663,
"preview": "[gd_scene load_steps=6 format=2]\n\n[ext_resource path=\"res://Main.gdns\" type=\"Script\" id=1]\n[ext_resource path=\"res://Mob"
},
{
"path": "examples/dodge-the-creeps/game/Mob.gdns",
"chars": 217,
"preview": "[gd_resource type=\"NativeScript\" load_steps=2 format=2]\n\n[ext_resource path=\"res://lib/libmyproject.gdnlib\" type=\"GDNati"
},
{
"path": "examples/dodge-the-creeps/game/Mob.tscn",
"chars": 1634,
"preview": "[gd_scene load_steps=10 format=2]\n\n[ext_resource path=\"res://Mob.gdns\" type=\"Script\" id=1]\n[ext_resource path=\"res://dod"
},
{
"path": "examples/dodge-the-creeps/game/Player.gdns",
"chars": 223,
"preview": "[gd_resource type=\"NativeScript\" load_steps=2 format=2]\n\n[ext_resource path=\"res://lib/libmyproject.gdnlib\" type=\"GDNati"
},
{
"path": "examples/dodge-the-creeps/game/Player.tscn",
"chars": 1197,
"preview": "[gd_scene load_steps=8 format=2]\n\n[ext_resource path=\"res://Player.gdns\" type=\"Script\" id=1]\n[ext_resource path=\"res://d"
},
{
"path": "examples/dodge-the-creeps/game/dodge_assets/fonts/FONTLOG.txt",
"chars": 6744,
"preview": "Please distribute this file along with the Xolonium fonts when possible.\n\n\nSource\n\n\tFind the sourcefiles of Xolonium at\n"
},
{
"path": "examples/dodge-the-creeps/game/dodge_assets/fonts/LICENSE.txt",
"chars": 4482,
"preview": "Copyright 2011-2016 Severin Meyer <sev.ch@web.de>,\r\nwith Reserved Font Name Xolonium.\r\n\r\nThis Font Software is licensed "
},
{
"path": "examples/dodge-the-creeps/game/lib/libmyproject.gdnlib",
"chars": 127,
"preview": "[general]\n\nsingleton=false\nload_once=true\nsymbol_prefix=\"godot_\"\nreloadable=false\n\n[entry]\n\nX11.64=\"res://lib/libmyproje"
},
{
"path": "examples/dodge-the-creeps/game/project.godot",
"chars": 511,
"preview": "; Engine configuration file.\n; It's best edited using the editor UI and not directly,\n; since the parameters that go her"
},
{
"path": "examples/dodge-the-creeps/godot-haskell.nix",
"chars": 1034,
"preview": "{ fetchFromGitHub, mkDerivation, aeson, ansi-wl-pprint, base, bytestring, c2hs\n, casing, colour, containers, hpack, lens"
},
{
"path": "examples/dodge-the-creeps/hie.yaml",
"chars": 125,
"preview": "cradle:\n stack:\n - path: \"./src\"\n component: \"myproject:lib\"\n\n - path: \"./game\"\n component: \"myproject:"
},
{
"path": "examples/dodge-the-creeps/myproject.cabal",
"chars": 1945,
"preview": "cabal-version: 1.12\n\n-- This file has been generated from package.yaml by hpack version 0.33.0.\n--\n-- see: https://githu"
},
{
"path": "examples/dodge-the-creeps/package.yaml",
"chars": 1221,
"preview": "name: myproject\nversion: '0.0.0.0'\ndescription: Please see the README on Github at <https://github.com/SimulaVR/godot-ha"
},
{
"path": "examples/dodge-the-creeps/pinned-nixpkgs.nix",
"chars": 240,
"preview": "{}:\n\nlet\n # 19.03-beta (25 feb)\n rev = \"0c0954781e257b8b0dc49341795a2fe7d96945a3\"; # pinned-nixpkgs rev\n pkgs = impor"
},
{
"path": "examples/dodge-the-creeps/shell.nix",
"chars": 993,
"preview": "{ nixpkgs ? import ./pinned-nixpkgs.nix {}\n, compiler ? \"default\"\n, doBenchmark ? false }:\n\n\nlet\n\n inherit (nixpkgs) pk"
},
{
"path": "examples/dodge-the-creeps/src/Game/HUD.hs",
"chars": 1829,
"preview": "module Game.HUD where\nimport Control.Lens\nimport Control.Monad\nimport qualified Data.Text as T\nimport Godot\nimport Godot"
},
{
"path": "examples/dodge-the-creeps/src/Game/Main.hs",
"chars": 3626,
"preview": "module Game.Main where\nimport Control.Lens\nimport Control.Monad\nimport Foreign.C.Types\nimport Godot\nimport Godot.Core.No"
},
{
"path": "examples/dodge-the-creeps/src/Game/Mob.hs",
"chars": 885,
"preview": "module Game.Mob where\nimport Godot\nimport Godot.Core.AnimatedSprite as AnimatedSprite\nimport Godot.Core.Node as Node\nimp"
},
{
"path": "examples/dodge-the-creeps/src/Game/Player.hs",
"chars": 3439,
"preview": "module Game.Player where\nimport Control.Lens\nimport Control.Monad\nimport Godot\nimport Godot.Core.AnimatedSprite as Anima"
},
{
"path": "examples/dodge-the-creeps/src/Lib.hs",
"chars": 252,
"preview": "module Lib (exports) where\nimport Godot\nimport Game.Mob\nimport Game.Main\nimport Game.Player\nimport Game.HUD\nimport Proje"
},
{
"path": "examples/dodge-the-creeps/src/Project/Requirements.hs",
"chars": 278,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\nmodule Project.Requirements where\nimpor"
},
{
"path": "examples/dodge-the-creeps/src/Project/Scenes/HUD.hs",
"chars": 2068,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\n{-# LANGUAGE FlexibleContexts, Function"
},
{
"path": "examples/dodge-the-creeps/src/Project/Scenes/Main.hs",
"chars": 3583,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\n{-# LANGUAGE FlexibleContexts, Function"
},
{
"path": "examples/dodge-the-creeps/src/Project/Scenes/Mob.hs",
"chars": 1928,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\n{-# LANGUAGE FlexibleContexts, Function"
},
{
"path": "examples/dodge-the-creeps/src/Project/Scenes/Player.hs",
"chars": 1641,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\n{-# LANGUAGE FlexibleContexts, Function"
},
{
"path": "examples/dodge-the-creeps/src/Project/Scenes.hs",
"chars": 289,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\nmodule Project.Scenes (module M) where\n"
},
{
"path": "examples/dodge-the-creeps/src/Project/Support.hs",
"chars": 18614,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\n{-# LANGUAGE FlexibleContexts, Function"
},
{
"path": "examples/dodge-the-creeps/stack-shell.nix",
"chars": 161,
"preview": "{ nixpkgs ? import ./pinned-nixpkgs.nix {}\n, ghc\n}:\n\nwith nixpkgs;\n\nhaskell.lib.buildStackProject {\n inherit ghc;\n nam"
},
{
"path": "examples/dodge-the-creeps/stack.yaml",
"chars": 237,
"preview": "resolver: nightly-2021-02-06\n\npackages:\n- .\n\nextra-deps:\n- ../../\n\nrequire-stack-version: \">=1.8\"\n\nnix:\n enable: false\n"
},
{
"path": "examples/rss-reader/.gitignore",
"chars": 72,
"preview": "dist*\n*.hi\n*.o\n.stack-work/\n.stack-work-devel/\n*~\n\\#*\n*.import\nresult\n\n\n"
},
{
"path": "examples/rss-reader/ChangeLog.md",
"chars": 10,
"preview": "# Empty\n\n\n"
},
{
"path": "examples/rss-reader/LICENSE",
"chars": 1512,
"preview": "BSD 3-Clause License\n\nCopyright (c) Andrei Barbu 2019\nAll rights reserved.\n\nRedistribution and use in source and binary "
},
{
"path": "examples/rss-reader/Makefile",
"chars": 766,
"preview": "NAME = myproject\nSTACKLIBFILE = $(shell stack path --local-install-root)/lib/lib$(NAME).so\nGODOTPROJECT = $(shell stack "
},
{
"path": "examples/rss-reader/README.md",
"chars": 168,
"preview": "The official Godot demo from the manual: Dodge the Creeps.\n\nRun with `make stack` then `godot game/project.godot` and pr"
},
{
"path": "examples/rss-reader/Support.hs",
"chars": 512,
"preview": "{-# LANGUAGE FlexibleContexts, FunctionalDependencies, MultiParamTypeClasses, OverloadedLabels, UndecidableInstances,\n "
},
{
"path": "examples/rss-reader/ffi/cbits/flib.c",
"chars": 321,
"preview": "#include \"HsFFI.h\"\n\nstatic void flib_init() __attribute__((constructor));\nstatic void flib_init() {\n static char *argv["
},
{
"path": "examples/rss-reader/ffi/flib/FLib.hs",
"chars": 1023,
"preview": "{-# LANGUAGE ForeignFunctionInterface #-}\nmodule FLib where\n\nimport qualified Foreign\nimport Foreign(nullPtr, "
},
{
"path": "examples/rss-reader/game/Rss_reader.gdns",
"chars": 229,
"preview": "[gd_resource type=\"NativeScript\" load_steps=2 format=2]\n\n[ext_resource path=\"res://lib/libmyproject.gdnlib\" type=\"GDNati"
},
{
"path": "examples/rss-reader/game/Rss_reader.tscn",
"chars": 3181,
"preview": "[gd_scene load_steps=2 format=2]\n\n[ext_resource path=\"res://Rss_reader.gdns\" type=\"Script\" id=1]\n\n[node name=\"RSSReader\""
},
{
"path": "examples/rss-reader/game/export_presets.cfg",
"chars": 552,
"preview": "[preset.0]\n\nname=\"Linux/X11\"\nplatform=\"Linux/X11\"\nrunnable=true\ncustom_features=\"\"\nexport_filter=\"all_resources\"\ninclude"
},
{
"path": "examples/rss-reader/game/lib/libmyproject.gdnlib",
"chars": 127,
"preview": "[general]\n\nsingleton=false\nload_once=true\nsymbol_prefix=\"godot_\"\nreloadable=false\n\n[entry]\n\nX11.64=\"res://lib/libmyproje"
},
{
"path": "examples/rss-reader/game/project.godot",
"chars": 575,
"preview": "; Engine configuration file.\n; It's best edited using the editor UI and not directly,\n; since the parameters that go her"
},
{
"path": "examples/rss-reader/godot-haskell.nix",
"chars": 1034,
"preview": "{ fetchFromGitHub, mkDerivation, aeson, ansi-wl-pprint, base, bytestring, c2hs\n, casing, colour, containers, hpack, lens"
},
{
"path": "examples/rss-reader/hie.yaml",
"chars": 125,
"preview": "cradle:\n stack:\n - path: \"./src\"\n component: \"myproject:lib\"\n\n - path: \"./game\"\n component: \"myproject:"
},
{
"path": "examples/rss-reader/myproject.cabal",
"chars": 1878,
"preview": "cabal-version: 1.12\n\n-- This file has been generated from package.yaml by hpack version 0.33.0.\n--\n-- see: https://githu"
},
{
"path": "examples/rss-reader/package.yaml",
"chars": 1261,
"preview": "name: myproject\nversion: '0.0.0.0'\ndescription: Please see the README on Github at <https://github.com/SimulaVR/godot-ha"
},
{
"path": "examples/rss-reader/pinned-nixpkgs.nix",
"chars": 240,
"preview": "{}:\n\nlet\n # 19.03-beta (25 feb)\n rev = \"0c0954781e257b8b0dc49341795a2fe7d96945a3\"; # pinned-nixpkgs rev\n pkgs = impor"
},
{
"path": "examples/rss-reader/shell.nix",
"chars": 993,
"preview": "{ nixpkgs ? import ./pinned-nixpkgs.nix {}\n, compiler ? \"default\"\n, doBenchmark ? false }:\n\n\nlet\n\n inherit (nixpkgs) pk"
},
{
"path": "examples/rss-reader/src/Game/RSSReader.hs",
"chars": 6310,
"preview": "{-# LANGUAGE LambdaCase, FunctionalDependencies, DeriveGeneric, UndecidableInstances, ConstraintKinds #-}\nmodule Game.RS"
},
{
"path": "examples/rss-reader/src/Game/q",
"chars": 7454,
"preview": "{-# LANGUAGE LambdaCase, FunctionalDependencies, DeriveGeneric, UndecidableInstances, ConstraintKinds #-}\nmodule Game.RS"
},
{
"path": "examples/rss-reader/src/Lib.hs",
"chars": 193,
"preview": "module Lib (exports) where\nimport Godot\nimport Project.Support\nimport Project.Requirements\nimport Game.RSSReader\n\nexport"
},
{
"path": "examples/rss-reader/src/Project/Requirements.hs",
"chars": 196,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\nmodule Project.Requirements where\nimpor"
},
{
"path": "examples/rss-reader/src/Project/Scenes/Rss_reader.hs",
"chars": 5388,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\n{-# LANGUAGE FlexibleContexts, Function"
},
{
"path": "examples/rss-reader/src/Project/Scenes.hs",
"chars": 169,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\nmodule Project.Scenes (module M) where\n"
},
{
"path": "examples/rss-reader/src/Project/Support.hs",
"chars": 18614,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\n{-# LANGUAGE FlexibleContexts, Function"
},
{
"path": "examples/rss-reader/stack-shell.nix",
"chars": 161,
"preview": "{ nixpkgs ? import ./pinned-nixpkgs.nix {}\n, ghc\n}:\n\nwith nixpkgs;\n\nhaskell.lib.buildStackProject {\n inherit ghc;\n nam"
},
{
"path": "examples/rss-reader/stack.yaml",
"chars": 237,
"preview": "resolver: nightly-2021-02-06\n\npackages:\n- .\n\nextra-deps:\n- ../../\n\nrequire-stack-version: \">=1.8\"\n\nnix:\n enable: false\n"
},
{
"path": "examples/top-down-ten-minutes/.gitignore",
"chars": 72,
"preview": "dist*\n*.hi\n*.o\n.stack-work/\n.stack-work-devel/\n*~\n\\#*\n*.import\nresult\n\n\n"
},
{
"path": "examples/top-down-ten-minutes/ChangeLog.md",
"chars": 10,
"preview": "# Empty\n\n\n"
},
{
"path": "examples/top-down-ten-minutes/LICENSE",
"chars": 1512,
"preview": "BSD 3-Clause License\n\nCopyright (c) Andrei Barbu 2019\nAll rights reserved.\n\nRedistribution and use in source and binary "
},
{
"path": "examples/top-down-ten-minutes/Makefile",
"chars": 777,
"preview": "NAME = top-down-ten-minutes\nSTACKLIBFILE = $(shell stack path --local-install-root)/lib/lib$(NAME).so\nGODOTPROJECT = $(s"
},
{
"path": "examples/top-down-ten-minutes/README.md",
"chars": 168,
"preview": "The official Godot demo from the manual: Dodge the Creeps.\n\nRun with `make stack` then `godot game/project.godot` and pr"
},
{
"path": "examples/top-down-ten-minutes/ffi/cbits/flib.c",
"chars": 321,
"preview": "#include \"HsFFI.h\"\n\nstatic void flib_init() __attribute__((constructor));\nstatic void flib_init() {\n static char *argv["
},
{
"path": "examples/top-down-ten-minutes/ffi/flib/FLib.hs",
"chars": 1023,
"preview": "{-# LANGUAGE ForeignFunctionInterface #-}\nmodule FLib where\n\nimport qualified Foreign\nimport Foreign(nullPtr, "
},
{
"path": "examples/top-down-ten-minutes/game/Bullet.gdns",
"chars": 234,
"preview": "[gd_resource type=\"NativeScript\" load_steps=2 format=2]\n\n[ext_resource path=\"res://lib/libtop-down-ten-minutes.gdnlib\" t"
},
{
"path": "examples/top-down-ten-minutes/game/Bullet.tscn",
"chars": 1291,
"preview": "[gd_scene load_steps=5 format=2]\n\n[ext_resource path=\"res://Player.png\" type=\"Texture\" id=1]\n[ext_resource path=\"res://B"
},
{
"path": "examples/top-down-ten-minutes/game/Enemy.gdns",
"chars": 232,
"preview": "[gd_resource type=\"NativeScript\" load_steps=2 format=2]\n\n[ext_resource path=\"res://lib/libtop-down-ten-minutes.gdnlib\" t"
},
{
"path": "examples/top-down-ten-minutes/game/Enemy.tscn",
"chars": 944,
"preview": "[gd_scene load_steps=5 format=2]\n\n[ext_resource path=\"res://Player.png\" type=\"Texture\" id=1]\n[ext_resource path=\"res://E"
},
{
"path": "examples/top-down-ten-minutes/game/Explosion.tscn",
"chars": 842,
"preview": "[gd_scene load_steps=4 format=2]\n\n[sub_resource type=\"Curve\" id=1]\n_data = [ Vector2( 0, 1 ), 0.0, 0.0, 0, 0, Vector2( 1"
},
{
"path": "examples/top-down-ten-minutes/game/Player.gdns",
"chars": 234,
"preview": "[gd_resource type=\"NativeScript\" load_steps=2 format=2]\n\n[ext_resource path=\"res://lib/libtop-down-ten-minutes.gdnlib\" t"
},
{
"path": "examples/top-down-ten-minutes/game/lib/libtop-down-ten-minutes.gdnlib",
"chars": 167,
"preview": "[general]\n\nsingleton=false\nload_once=false\nsymbol_prefix=\"godot_\"\nreloadable=true\n\n[entry]\n\nX11.64=\"res://lib/libtop-dow"
},
{
"path": "examples/top-down-ten-minutes/game/project.godot",
"chars": 2064,
"preview": "; Engine configuration file.\n; It's best edited using the editor UI and not directly,\n; since the parameters that go her"
},
{
"path": "examples/top-down-ten-minutes/game/wall.tres",
"chars": 979,
"preview": "[gd_resource type=\"TileSet\" load_steps=4 format=2]\n\n[ext_resource path=\"res://Player.png\" type=\"Texture\" id=1]\n\n[sub_res"
},
{
"path": "examples/top-down-ten-minutes/game/world.tscn",
"chars": 17219,
"preview": "[gd_scene load_steps=8 format=2]\n\n[ext_resource path=\"res://Player.png\" type=\"Texture\" id=1]\n[ext_resource path=\"res://P"
},
{
"path": "examples/top-down-ten-minutes/godot-haskell.nix",
"chars": 1034,
"preview": "{ fetchFromGitHub, mkDerivation, aeson, ansi-wl-pprint, base, bytestring, c2hs\n, casing, colour, containers, hpack, lens"
},
{
"path": "examples/top-down-ten-minutes/hie.yaml",
"chars": 147,
"preview": "cradle:\n stack:\n - path: \"./src\"\n component: \"top-down-ten-minutes:lib\"\n\n - path: \"./game\"\n component: "
},
{
"path": "examples/top-down-ten-minutes/package.yaml",
"chars": 1332,
"preview": "name: top-down-ten-minutes\nversion: '0.0.0.0'\ndescription: Please see the README on Github at <https://github.com/Simula"
},
{
"path": "examples/top-down-ten-minutes/pinned-nixpkgs.nix",
"chars": 240,
"preview": "{}:\n\nlet\n # 19.03-beta (25 feb)\n rev = \"0c0954781e257b8b0dc49341795a2fe7d96945a3\"; # pinned-nixpkgs rev\n pkgs = impor"
},
{
"path": "examples/top-down-ten-minutes/shell.nix",
"chars": 1015,
"preview": "{ nixpkgs ? import ./pinned-nixpkgs.nix {}\n, compiler ? \"default\"\n, doBenchmark ? false }:\n\n\nlet\n\n inherit (nixpkgs) pk"
},
{
"path": "examples/top-down-ten-minutes/src/Game/World.hs",
"chars": 5176,
"preview": "{-# LANGUAGE LambdaCase, TypeOperators #-}\n{-# OPTIONS_GHC -Wno-name-shadowing #-}\nmodule Game.World where\nimport Contro"
},
{
"path": "examples/top-down-ten-minutes/src/Lib.hs",
"chars": 199,
"preview": "module Lib (exports) where\nimport Godot\nimport Project.Support\nimport Project.Requirements\nimport Game.World\n\nexports ::"
},
{
"path": "examples/top-down-ten-minutes/src/Project/Requirements.hs",
"chars": 257,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\nmodule Project.Requirements where\nimpor"
},
{
"path": "examples/top-down-ten-minutes/src/Project/Scenes/Bullet.hs",
"chars": 2025,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\n{-# LANGUAGE FlexibleContexts, Function"
},
{
"path": "examples/top-down-ten-minutes/src/Project/Scenes/Enemy.hs",
"chars": 1842,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\n{-# LANGUAGE FlexibleContexts, Function"
},
{
"path": "examples/top-down-ten-minutes/src/Project/Scenes/Explosion.hs",
"chars": 984,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\n{-# LANGUAGE FlexibleContexts, Function"
},
{
"path": "examples/top-down-ten-minutes/src/Project/Scenes/World.hs",
"chars": 5401,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\n{-# LANGUAGE FlexibleContexts, Function"
},
{
"path": "examples/top-down-ten-minutes/src/Project/Scenes.hs",
"chars": 298,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\nmodule Project.Scenes (module M) where\n"
},
{
"path": "examples/top-down-ten-minutes/src/Project/Support.hs",
"chars": 18614,
"preview": "-- | This file is AUTOGENERATED by godot-haskell-project-generator. DO NOT EDIT\n\n{-# LANGUAGE FlexibleContexts, Function"
},
{
"path": "examples/top-down-ten-minutes/stack-shell.nix",
"chars": 172,
"preview": "{ nixpkgs ? import ./pinned-nixpkgs.nix {}\n, ghc\n}:\n\nwith nixpkgs;\n\nhaskell.lib.buildStackProject {\n inherit ghc;\n nam"
},
{
"path": "examples/top-down-ten-minutes/stack.yaml",
"chars": 237,
"preview": "resolver: nightly-2021-02-06\n\npackages:\n- .\n\nextra-deps:\n- ../../\n\nrequire-stack-version: \">=1.8\"\n\nnix:\n enable: false\n"
},
{
"path": "examples/top-down-ten-minutes/top-down-ten-minutes.cabal",
"chars": 2019,
"preview": "cabal-version: 1.12\n\n-- This file has been generated from package.yaml by hpack version 0.33.0.\n--\n-- see: https://githu"
},
{
"path": "godot-haskell.cabal",
"chars": 25681,
"preview": "cabal-version: 2.0\n\n-- This file has been generated from package.yaml by hpack version 0.33.0.\n--\n-- see: https://github"
},
{
"path": "hie.yaml",
"chars": 262,
"preview": "cradle:\n stack:\n - path: \"./src\"\n component: \"godot-haskell:lib\"\n\n - path: \"./src-generate\"\n component:"
},
{
"path": "nix/pinned/all-hies.json",
"chars": 290,
"preview": "{\n \"url\": \"https://github.com/Infinisil/all-hies.git\",\n \"rev\": \"d98bdbff3ebdab408a12a9b7890d4cf400180839\",\n \"date\": \""
},
{
"path": "nix/pinned/default.nix",
"chars": 405,
"preview": "{ fetchFromGitHub, lib }:\n\nlet\n fetch = owner: repo: jsonFile: fetchFromGitHub {\n inherit owner repo;\n inherit (l"
},
{
"path": "nix/pinned/hie.nix",
"chars": 776,
"preview": "{ fetchFromGitHub, lib, ghc, useSystem ? true, useLatest ? false, versions ? [] }:\n\nlet\n fetch = owner: repo: jsonFile:"
},
{
"path": "nix/pinned/nixpkgs.json",
"chars": 295,
"preview": "{\n \"url\": \"https://github.com/nixos/nixpkgs-channels.git\",\n \"rev\": \"ce9f1aaa39ee2a5b76a9c9580c859a74de65ead5\",\n \"date"
},
{
"path": "nix/spacemacs-hie.nix",
"chars": 461,
"preview": "{ pkgs, hsPkgs }:\nlet\n pinned = import ./pinned { inherit (pkgs) fetchFromGitHub lib; };\n hie = pinned.hie { inherit ("
},
{
"path": "nixpkgs-version.json",
"chars": 249,
"preview": "{\n \"url\": \"https://github.com/nixos/nixpkgs-channels.git\",\n \"rev\": \"c8db7a8a16ee9d54103cade6e766509e1d1c8d7b\",\n \"date"
},
{
"path": "package.yaml",
"chars": 1487,
"preview": "name: godot-haskell\nsynopsis: Haskell bindings for the Godot game engine API\ndescription: This package contains Haskell "
},
{
"path": "pinned-nixpkgs.nix",
"chars": 288,
"preview": "{}:\nlet hostPkgs = import <nixpkgs> {};\n pinnedVersion = hostPkgs.lib.importJSON ./nixpkgs-version.json;\n pinnedPk"
},
{
"path": "project-generator/Main.hs",
"chars": 35012,
"preview": "{-# LANGUAGE DerivingStrategies #-}\n{-# LANGUAGE FlexibleContexts #-}\n{-# LANGUAGE FlexibleInstances #-}\n{-# LANGUAGE Fu"
},
{
"path": "release.nix",
"chars": 108,
"preview": "let\n pkgs = import <nixpkgs> { };\nin\n pkgs.haskellPackages.callPackage ./default.nix { api-json = null; }\n"
},
{
"path": "shell-spacemacs-hie.nix",
"chars": 385,
"preview": "let\n pinned = import ./nix/pinned {\n inherit (import <nixpkgs> {})\n fetchFromGitHub\n lib;\n };\n\n hsPkgs = "
},
{
"path": "shell.nix",
"chars": 467,
"preview": "{ nixpkgs ? import ./pinned-nixpkgs.nix {}\n, compiler ? \"default\"\n, doBenchmark ? false }:\n\nlet\n inherit (nixpkgs) pkgs"
},
{
"path": "src/Godot/Api/Types.hs",
"chars": 368538,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TemplateHaskell #-}\nmodule Godot.Api.Types\n"
},
{
"path": "src/Godot/Api.hs",
"chars": 64,
"preview": "module Godot.Api (module M) where\n\nimport Godot.Api.Types as M\n\n"
},
{
"path": "src/Godot/Core/ARVRAnchor.hs",
"chars": 9811,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/ARVRCamera.hs",
"chars": 487,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/ARVRController.hs",
"chars": 17492,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/ARVRInterface.hs",
"chars": 19859,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/ARVRInterfaceGDNative.hs",
"chars": 505,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/ARVROrigin.hs",
"chars": 3278,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/ARVRPositionalTracker.hs",
"chars": 20418,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/ARVRServer.hs",
"chars": 24585,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AStar.hs",
"chars": 33282,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AStar2D.hs",
"chars": 30775,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AcceptDialog.hs",
"chars": 18148,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimatedSprite.hs",
"chars": 24918,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimatedSprite3D.hs",
"chars": 13987,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimatedTexture.hs",
"chars": 134455,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/Animation.hs",
"chars": 81381,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNode.hs",
"chars": 29006,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNodeAdd2.hs",
"chars": 3153,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNodeAdd3.hs",
"chars": 3153,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNodeAnimation.hs",
"chars": 3198,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNodeBlend2.hs",
"chars": 3204,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNodeBlend3.hs",
"chars": 3204,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNodeBlendSpace1D.hs",
"chars": 58817,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNodeBlendSpace2D.hs",
"chars": 76819,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNodeBlendTree.hs",
"chars": 16719,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNodeOneShot.hs",
"chars": 17687,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNodeOutput.hs",
"chars": 503,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNodeStateMachine.hs",
"chars": 28570,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNodeStateMachinePlayback.hs",
"chars": 7859,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNodeStateMachineTransition.hs",
"chars": 21694,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNodeTimeScale.hs",
"chars": 506,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNodeTimeSeek.hs",
"chars": 505,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationNodeTransition.hs",
"chars": 27994,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationPlayer.hs",
"chars": 60638,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationRootNode.hs",
"chars": 501,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationTree.hs",
"chars": 21644,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AnimationTreePlayer.hs",
"chars": 93214,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/Area.hs",
"chars": 62881,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/Area2D.hs",
"chars": 55574,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/ArrayMesh.hs",
"chars": 27885,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AtlasTexture.hs",
"chars": 9428,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioBusLayout.hs",
"chars": 493,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffect.hs",
"chars": 490,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectAmplify.hs",
"chars": 3181,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectBandLimitFilter.hs",
"chars": 514,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectBandPassFilter.hs",
"chars": 513,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectChorus.hs",
"chars": 25527,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectCompressor.hs",
"chars": 18538,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectDelay.hs",
"chars": 31128,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectDistortion.hs",
"chars": 13093,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectEQ.hs",
"chars": 3700,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectEQ10.hs",
"chars": 499,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectEQ21.hs",
"chars": 499,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectEQ6.hs",
"chars": 498,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectFilter.hs",
"chars": 9286,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectHighPassFilter.hs",
"chars": 513,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectHighShelfFilter.hs",
"chars": 514,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectInstance.hs",
"chars": 499,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectLimiter.hs",
"chars": 10366,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectLowPassFilter.hs",
"chars": 512,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
},
{
"path": "src/Godot/Core/AudioEffectLowShelfFilter.hs",
"chars": 513,
"preview": "{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving,\n TypeFamilies, TypeOperators, FlexibleContexts, DataKinds,"
}
]
// ... and 588 more files (download for full content)
About this extraction
This page contains the full source code of the SimulaVR/godot-haskell GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 788 files (11.0 MB), approximately 2.9M tokens, and a symbol index with 8 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.