Commit d78c5cdc authored by Oscar Campos's avatar Oscar Campos
Browse files

Merge branch '0.1.0' into 'master'

0.1.0-relase-candidate

See merge request !2
parents de4a478a d70a4bdf
Pipeline #204175545 passed with stages
in 3 minutes and 5 seconds
......@@ -8,4 +8,8 @@ doc/
*.dynlib
*.dll
*_registrable.gen.go
gdnative/*.gen.*
.vscode/
plan/
image: golang:1.14.4-buster
# GDNative-Go Gitlab CI Pipelines
image: golang:1.15-buster
variables:
TAG: $CI_BUILD_REF_NAME
VERSION: "NONE"
TAG: $CI_BUILD_REF_NAME
# define non taggable references
.non_taggable_refs: &non_taggable_refs
- "/^master$"
- "tags"
# release references
.release_refs: &release_refs
- "/^master$"
- "tags"
# Go Mod caching
.go-cache:
variables:
GOPATH: $CI_PROJECT_DIR/.go
before_script:
- mkdir -p .go
cache:
paths:
- .go/pkg/mod
stages:
- code_health
- test
- version
- commits_check
- linting
- version
cache:
paths:
- $GOPATH/pkg/mod
# ---------------- commits check ----------------
commit_messages_check:
stage: commits_check
image: registry.gitlab.com/juhani/go-semrel-gitlab:v0.21.1
script:
- release test-git
allow_failure: false
except:
*release_refs
# ---------------- code checks ----------------
code_linting:
extends: .go-cache
image:
name: golangci/golangci-lint:latest
entrypoint: [""]
stage: linting
script:
# get goreturns and add it to the $PATH
- go get -u github.com/sqs/goreturns
- export PATH="$PATH:$GOPATH/bin"
# ----------------- code health -----------------
validate_commit_message:
stage: code_health
image: registry.gitlab.com/juhani/go-semrel-gitlab:v0.20.4
script:
- release test-git
allow_failure: false
except:
*non_taggable_refs
# checkout godot_headers submodule
- git submodule update --init
code_format_analysys:
stage: code_health
script:
- go get -u github.com/sqs/goreturns
- if [[ $(goreturns -d ./gdnative && goreturns -d ./cmd) -eq "" ]]; then echo "goreturns check successful"; exit 0; fi
- echo "ERROR - goreturns check failed - please run goreturns on your code and commit again"
- goreturns -d ./gdnative
- goreturns -d ./cmd
- exit 1
allow_failure: false
except:
- tags
# generate bindings and build library
- go run build/mage.go generate
# here will be golangci-lint call when I fix all inherited godot-go errors
# run linters
- golangci-lint run -v --timeout 5m
# ----------------- test -----------------
compile_gdnativego:
stage: test
script:
- git submodule update --init --recursive
- go get -u github.com/sqs/goreturns
- go run ./build/mage.go generate
- go run ./build/mage.go build
- go run ./build/mage.go gdnativego
except:
- tags
# run goretuns formating
- if [[ $(goreturns -d ./gdnative ./cmd) -eq "" ]]; then echo "goreturns check success"; exit 0; fi
- echo "ERROR - goreturn check failed"
- goreturns -d ./gdnative ./cmd
- exit 1
allow_failure: false
except:
- tags
# ----------------- version -----------------
update_version:
stage: version
image: registry.gitlab.com/juhani/go-semrel-gitlab:v0.20.4
script:
- release changelog
- release commit-and-tag --create-tag-pipeline CHANGELOG.md
allow_failure: true
when: manual
only:
- master
\ No newline at end of file
# ---------------- update version ----------------
version_update:
stage: version
image: registry.gitlab.com/juhani/go-semrel-gitlab:v0.21.1
script:
- release changelog
- release commit-and-tag --create-tag-pipeline CHANGELOG.md
allow_failure: true
when: on_success
only:
- master
# Summary
(Provide a concise description of the encountered bug)
## Godot Version
(Provide the exact Godot version you were using when the bug appeared)
## GDnative-Go Version
(Provide the exact GDnative-Go version you were using when the bug appeared)
## Operating System and Architecture
(Provide your operating system name, version and architecture, example: Artix Linux, kernel-5.7.6-artix1-1 x86_64)
## Steps to reproduce
(How one can reproduce the issue - this is very important)
## Example Project
(If possible, please create an example project here on gitlab.com or github.com that exhibits the problematic behavior and link it here in the bug report)
(If you already have a public repository with the contents of your project just link it here in the bug report)
## What is the current behavior?
(What actually happens)
## What is the expected behavior?
(What do you expected to happens)
## Relevant logs and/or screenshots and videos
(Paste any relevant logs - please use code block (```) to format console output, logs, and code)
(If the logs output is very long, use https://hastebin.com/ and post a link here in the bug report)
## Possible fixes
(If you happen to know why the bug happens, please share a link to the line of code that might be responsible of the problem and speak your mind about it)
/label ~bug ~reproduced ~needs-investigation
/cc @core-team
# Feature Request Form
(Present youself to the Community in a few lines)
## Feature Description
(Describe to the best of your abilities what your feature request is about)
## Motivation
(Give a concise explanation about why this feature should be implemented into GDnative-Go)
## Technical Aspects
(Provide technical details about how this feature could be implemented)
## Are you coding this feature yourself?
(In case that you are contributing this feature yourself make sure you check our [Contribute Guide](CONTRIBUTING.md))
[ ] Yes I am
[ ] No I am not
**important**: note that we ask feature contributors to become feature maintainers, make sure you are ready for such a commitment, if you are not, is better that you fork gdnative-go and implement that feature in your own fork yourself
/label ~feature-request
/cc @core-team
\ No newline at end of file
# Feedback
(Thank you for becoming part of GDnative-Go Community, please provide your feedback using this template, your feedback is very important for us)
/label ~feedback
/cc @all-team
# This file contains configuration options for golangci linter
# Any options can be override creating a .golangci-.yml file
# in deeper levels of the hierarchy path
# linter settings
linter-settings:
go-vet:
# report about shadowed variables
check-shadowing: true
maligned:
# print struct with more effective memory layout or not, false by default
suggest-new: true
# enable or disable specific linters
linters:
enable:
- interfacer
- maligned
- gosec
- nakedret
- stylecheck
- goconst
- gocyclo
# List of regexps of issue texts to exclude
issues:
# Excluding configuration per path
exclude-rules:
- path: _test\.go
linters:
- gocyclo
- errcheck
- dupl
- gosec
run:
# skip the following files
skip-files:
- ".gen\\.go$"
- "_gen\\.go$"
# skip the following directories
skip-dirs:
- "(^|/)example($|/)"
![alt text][logo]
# GDNative bindings for Go
Golang bindings to the [Godot GDNative](https://github.com/GodotNativeTools/godot_headers) API.
## Intention
This project is a maintained as a smaller fork of [godot-go](https://github.com/ShadowApex/godot-go)
This project is a maintained and a smaller fork of [godot-go](https://github.com/ShadowApex/godot-go)
project, its aim is to make simpler the task of invoke Golang code from [godot](https://github.com/godotengine/godot)'s
GDScript not to write Godot video games using the Golang language. If your are looking for a way to
write Godot games using Golang as development language you can take a look at
......@@ -22,7 +24,7 @@ This project exists for three main reasons
1. Bind Golang ecosystem applications to GDScript (like making BBolt or CockroachDB available natively to your GDScript code)
2. Delegate CPU bound calculations to the Golang runtime
3. Use Golang concurrency on GDNative golang modules from GDScript
3. Use Golang concurrency on NativeScript golang modules from GDScript
If what you are looking for is to write your Godot game in a more performant than GDScript language I
recommend you to use the **godot-mono** version, if C# is not performant enough for you or you want to use a
......@@ -30,4 +32,91 @@ concurrent native language to write your game code then take a look to [gdnative
project, it is actively maintained and in good health, you can also take a look to
[godot-cpp](https://github.com/GodotNativeTools/godot-cpp) Godot's C++ bindings.
At least while we rewrite the full Godot classes wrapper into a new Godot Goland API wrapper library
### Does that means I will never provide full set of bindings in this project?
Yes, that is exactly what it means, this project will only provide bindings for NativeScript
### It is all lost?
No, I am currently working into generate full bindings to Godot full API in a separate project that
uses this one as a base interface between Go and Godot NativeScript. I believe both concepts are
divisible, some times one will want to bring that cool Go library into Godot while some others one
would like to code their whole project using Go, tie this two clearly different needs into the same
library just does not feels right to me
### So is that new library available?
Not yet, will update this repository when its done
## Special Thanks
I would like to give special thanks to the individuals and organizations that had made this project's
existence to be possible
* Juan Linietsky, Ariel Manzur and the amazing Godot team and Community for their fantastic work
* William Edwards (ShadowApex) for writing the original [https://github.com/ShadowApex/godot-go](godot-go) library this is based on
* Rob Pike, Ken Thompson, Robert Griesemer and the whole Go Language team for creating this language
## Attributions
This project is based on a previous work by [William Edwards](https://github.com/ShadowApex) and big parts of its
code remains under its license (shown below)
The gdnative-go logo and godopher (godot + gopher) logos are based on the Godot image by
[Andrea Calabró](https://commons.wikimedia.org/wiki/File:Godot_logo.svg) Licensed under the
[CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/legalcode) license
The logos are also inspired in a vectorial gopher design by [Takuya Ueda](https://github.com/golang-samples/gopher-vector)
Licensed under the [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/legalcode) license
# Licenses
This project diverges from a previous work by William Edwards licensed under the MIT License, both
projects licenses are applicable and thus both of them are shown in this section
#### GDnative-Go License
```
Copyright © 2019 - 2020 Oscar Campos <oscar.campos@thepimpam.com>
Copyright © 2017 - William Edwards
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License
```
#### godot-go License (by ShadowApex)
```
MIT License
Copyright (c) 2017 William Edwards
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
[logo]: img/gdnative-go-logo-with-text.png "GDnative-Go"
......@@ -4,6 +4,7 @@ package gdnative
import (
"encoding/json"
"errors"
"io/ioutil"
"log"
"os"
......@@ -21,36 +22,27 @@ type View struct {
// not the given element is the last in the slice or not. This is so we can
// correctly insert commas for argument lists.
func (v View) NotLastElement(n int, slice [][]string) bool {
if n != (len(slice) - 1) {
return true
}
return false
return n != (len(slice) - 1)
}
// NotVoid checks to see if the return string is void or not. This is used inside
// our template so we can determine if we need to use the `return` keyword in
// the function body.
func (v View) NotVoid(ret string) bool {
if ret != "void" {
return true
}
return false
return ret != "void"
}
// HasArgs is a function we use inside the template to test whether or not the
// function has arguments. This is so we can determine if we need to place a
// comma.
func (v View) HasArgs(args [][]string) bool {
if len(args) != 0 {
return true
}
return false
return len(args) != 0
}
// Generate generates the bindings from the JSON definition
func Generate() {
// Get the API Path so we can localte the godot api JSON.
// Get the API Path so we can locate the godot api JSON.
apiPath := os.Getenv("API_PATH")
if apiPath == "" {
panic("$API_PATH is not defined.")
......@@ -114,7 +106,9 @@ func Parse(packagePath string) APIs {
// Unmarshal the JSON into our struct.
var apis APIs
json.Unmarshal(body, &apis)
if err := json.Unmarshal(body, &apis); err != nil {
panic(errors.New("could not unmarshal Godot JSON API"))
}
return apis
}
......@@ -129,10 +123,10 @@ func WriteTemplate(templatePath, outputPath string, view View) {
// Open the output file for writing
f, err := os.Create(outputPath)
defer f.Close()
if err != nil {
panic(err)
}
defer f.Close()
// Write the template with the given view.
err = t.Execute(f, view)
......
......@@ -24,11 +24,13 @@ package {{ $data.Package }}
import (
"fmt"
"reflect"
"gitlab.com/pimpam-games-studio/gdnative-go/gdnative"
)
// used for FreeFunc
var emptyFreeFunc = func(_ string) {}
{{ range $className, $class := $data.Classes -}}
// {{ $className }}Wrapper is a wrapper over {{ $className }} that will register it with in godot
type {{ $className }}Wrapper struct {
......@@ -131,55 +133,44 @@ func nativeScriptInit{{ $className }}() {
// define properties attached to the instance
properties := []gdnative.Property{
{{ range $i, $property := $class.Properties -}}
{{ if $class.Alias -}}
gdnative.NewGodotProperty("{{ $class.Alias }}", "{{ if $property.Alias }}{{ $property.Alias }}{{ else }}{{ $property.Name }}{{ end }}", "{{ $property.Hint }}", "{{ $property.HintString }}", "{{ $property.Usage }}", "{{ $property.RsetType }}", nil, nil),
{{ else -}}
setter.MethodData = fmt.Sprintf("{{ $className }}::%s", propertyString)
getter.MethodData = fmt.Sprintf("{{ $className }}::%s", propertyString)
gdnative.NewGodotProperty("{{ $className }}", "{{ if $property.Alias }}{{ $property.Alias }}{{ else }}{{ $property.Name }}{{ end }}", "{{ $property.Hint }}", "{{ $property.HintString }}", "{{ $property.Usage }}", "{{ $property.RsetType }}", nil, nil),
{{ end -}}
gdnative.NewGodotProperty(
"{{ if $class.Alias }}{{ $class.Alias }}{{ else }}{{ $className }}{{ end }}",
"{{ if $property.Alias }}{{ $property.Alias }}{{ else }}{{ $property.Name }}{{ end }}",
"{{ $property.Hint }}", "{{ $property.HintString }}",
"{{ $property.Usage }}", "{{ $property.RsetType }}",
&gdnative.InstancePropertySet{
SetFunc: func(object gdnative.Object, classProperty, instanceString string, property gdnative.Variant) {
class, ok := SimpleClassInstances[instanceString]
if !ok {
panic(fmt.Sprintf("Set property %s does not exists on instance %s registry", classProperty, instanceString))
}
class.class.{{ $property.Name }} = {{ $property.SetConvert }}
},
MethodData: "{{ if $class.Alias }}{{ $class.Alias }}{{ else }}{{ $className }}{{ end }}::{{ if $property.Alias }}{{ $property.Alias }}{{ else }}{{ $property.Name }}{{ end }}",
FreeFunc: emptyFreeFunc,
},
&gdnative.InstancePropertyGet{
GetFunc: func(object gdnative.Object, classProperty, instanceString string) gdnative.Variant {
class, ok := SimpleClassInstances[instanceString]
if !ok {
panic(fmt.Sprintf("Get property %q does not exists on instance %q registry", classProperty, instanceString))
}
return {{ $property.GetConvert }}
},
MethodData: "{{ if $class.Alias }}{{ $class.Alias }}{{ else }}{{ $className }}{{ end }}::{{ if $property.Alias }}{{ $property.Alias }}{{ else }}{{ $property.Name }}{{ end }}",
FreeFunc: emptyFreeFunc,
},
),
{{ end -}}
}
{{/* second pass to add the setter/getters */}}
for i := range properties {
var setter gdnative.InstancePropertySet
setter.SetFunc = func(object gdnative.Object, classProperty, instanceString string, property gdnative.Variant) {
class, ok := {{ $className }}Instances[instanceString]
if !ok {
panic(fmt.Sprintf("Set property %s does not exists on instance %s registry", classProperty, instanceString))
}
propertyField := reflect.ValueOf(reflect.ValueOf(class)).Elem().FieldByName(properties[i].GetName())
propertyField.Set(reflect.ValueOf(property))
}
setter.FreeFunc = func(methodData string) {}
var getter gdnative.InstancePropertyGet
getter.GetFunc = func(object gdnative.Object, classProperty, instanceString string) gdnative.Variant {
class, ok := {{ $className }}Instances[instanceString]
if !ok {
panic(fmt.Sprintf("Set property %s does not exists on instance %s registry", classProperty, instanceString))
}
propertyField := reflect.ValueOf(reflect.ValueOf(class)).Elem().FieldByName(properties[i].GetName())
return gdnative.GoTypeToVariant(propertyField)
}
getter.FreeFunc = func(methodData string) {}
{{ if $class.Alias -}}
setter.MethodData = fmt.Sprintf("{{ $class.Alias }}::%s", properties[i].GetName())
getter.MethodData = fmt.Sprintf("{{ $class.Alias }}::%s", properties[i].GetName())
{{ else -}}
setter.MethodData = fmt.Sprintf("{{ $className }}::%s", properties[i].GetName())
getter.MethodData = fmt.Sprintf("{{ $className }}::%s", properties[i].GetName())
{{ end -}}
properties[i].SetSetter(&setter)
properties[i].SetGetter(&getter)
}
// signals attached to the instance
signals := []gdnative.GDSignal{
......
......@@ -50,10 +50,10 @@ package gdnative
*/
import "C"
{{/* Loop through and define all of the type definitions as Go structs */}}
{{/* Loop through and define all of the type definitions as Go structs -*/}}
{{ range $i, $typedef := $view.TypeDefinitions -}}
{{/* Handle struct definitions */}}
{{ if or (eq $typedef.Base "struct") (eq $typedef.Base "void") }}
{{ if or (eq $typedef.Base "struct") (eq $typedef.Base "void") -}}
// NewEmpty{{ $typedef.GoName }} will return a pointer to an empty
// initialized {{ $typedef.GoName }}. This is primarily used in
// conjunction with MethodBindPtrCall.
......@@ -91,7 +91,7 @@ import "C"
}
{{/* The String struct is a special case to be compatible with Go strings -*/}}
{{ if (eq $typedef.GoName "String") }}
{{ if (eq $typedef.GoName "String") -}}
type {{ $typedef.GoName }} string
func (s String) getBase() *C.godot_string {
......@@ -99,6 +99,7 @@ import "C"
}
{{/* Handle all other kinds of Godot structs -*/}}
{{ else }}
// {{ $typedef.GoName }} data structure wrapper
type {{ $typedef.GoName }} struct {
base *C.{{ $typedef.Name }}
{{/* Handle struct properties */}}
......@@ -115,13 +116,14 @@ import "C"
{{ end -}}
}
// returns the wrapped C base data type for this type