Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Draft] Improve the engine and adapt for version 0.7 #1

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.vscode/
*.exe
*.exe
utils/test.go
12 changes: 8 additions & 4 deletions blackprint/blackprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@ import (
)

// The constructor must return pointer (ex: &Node{})
func RegisterNode(namespace string, constructor func(*engine.Instance) any) {
engine.QNodeList[namespace] = constructor
func RegisterNode(namespace string, meta *engine.NodeRegister) {
engine.QNodeList[namespace] = meta
}

// The constructor must return pointer (ex: &any)
func RegisterInterface(namespace string, constructor func(any) any) {
func RegisterInterface(namespace string, meta *engine.InterfaceRegister) {
if strings.HasPrefix(namespace, "BPIC/") == false {
panic(namespace + ": The first parameter of 'RegisterInterface' must be started with BPIC to avoid name conflict. Please name the interface similar with 'templatePrefix' for your module that you have set on 'blackprint.config.js'.")
}

engine.QInterfaceList[namespace] = constructor
engine.QInterfaceList[namespace] = meta
}

var Event = engine.Event
var Environment = engine.QEnvironment
var Port = engine.QPorts
40 changes: 40 additions & 0 deletions engine/bpVar.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package engine

import (
"reflect"
)

type bpVarValue struct {
*CustomEvent
val any
}

func (b *bpVarValue) Get() any {
return b.val
}

func (b *bpVarValue) Set(val any) {
b.val = val
b.Emit("value", nil)
}

// used for instance.CreateVariable
type BPVariable struct {
*CustomEvent
Id string
Title string
Type reflect.Kind
Used []*Interface
Value bpVarValue
Listener []*Interface
FuncInstance *bpFunction // for shared function variables
}

func (b *BPVariable) Destroy() {
for _, iface := range b.Used {
ins := iface.Node.Instance
ins.DeleteNode(iface)
}

b.Used = b.Used[:0]
}
144 changes: 124 additions & 20 deletions engine/cable.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@ package engine

import (
"reflect"

"github.com/blackprint/engine-go/utils"
)

type Cable struct {
Type reflect.Kind
Owner *Port
Target *Port
Type reflect.Kind
Owner *Port
Target *Port
Input *Port
Output *Port
Source int
Disabled int
IsRoute bool
Connected bool
_evDisconnected bool
_ghost bool
}

type CableEvent struct {
Expand All @@ -16,42 +26,136 @@ type CableEvent struct {
Target *Port
}

func NewCable(owner *Port, target *Port) Cable {
return Cable{
type PortValueEvent = CableEvent

func newCable(owner *Port, target *Port) *Cable {
var input *Port
var output *Port

if owner.Source == PortInput {
input = owner
output = target
} else {
output = owner
input = target
}

return &Cable{
Type: owner.Type,
Source: owner.Source,
Owner: owner,
Target: target,
Input: input,
Output: output,
}
}

func (c *Cable) QConnected() {
c.Owner.QTrigger("cable.connect", CableEvent{
func (c *Cable) _connected() {
c.Connected = true

ownerEv := &CableEvent{
Cable: c,
Port: c.Owner,
Target: c.Target,
})
}
c.Owner.Emit("cable.connect", ownerEv)
c.Owner.Iface.Emit("cable.connect", ownerEv)

c.Target.QTrigger("cable.connect", CableEvent{
targetEv := &CableEvent{
Cable: c,
Port: c.Target,
Target: c.Owner,
})
}
c.Target.Emit("cable.connect", targetEv)
c.Target.Iface.Emit("cable.connect", targetEv)

var inp, out *Port
if c.Owner.Source == PortInput {
inp = c.Owner
out = c.Target
} else {
inp = c.Target
out = c.Owner
if c.Output.Value == nil {
return
}

if out.Value != nil {
inp.QTrigger("value", out)
inputEv := &PortValueEvent{
Port: c.Output,
}
c.Input.Emit("value", inputEv)
c.Input.Iface.Emit("value", inputEv)

c.Input.Iface.Node.Update(c)
}

// For debugging
func (c *Cable) String() string {
return "\nCable: " + c.Owner.Iface.Title + "." + c.Owner.Name + " <=> " + c.Target.Name + "." + c.Target.Iface.Title
return "\nCable: " + c.Output.Iface.Title + "." + c.Output.Name + " <=> " + c.Input.Name + "." + c.Input.Iface.Title
}

func (c *Cable) GetValue() any {
return c.Output.Value
}

func (c *Cable) Disconnect(which_ ...*Port) { // which = port
if c.IsRoute { // ToDo: simplify, use 'which' instead of check all
if c.Output.Cables != nil {
c.Output.Cables = c.Output.Cables[:0]
} else if c.Output.RoutePort.Out == c {
c.Output.RoutePort.Out = nil
} else if c.Input.RoutePort.Out == c {
c.Input.RoutePort.Out = nil
}

c.Output.RoutePort.In = utils.RemoveItem(c.Output.RoutePort.In, c)
c.Input.RoutePort.In = utils.RemoveItem(c.Input.RoutePort.In, c)

c.Connected = false
return
}

hasWhich := len(which_) == 0
which := which_[0]
alreadyEmitToInstance := false

if c.Input != nil {
c.Input._cache = nil
}

if c.Owner != nil && (!hasWhich || which == c.Owner) {
c.Owner.Cables = utils.RemoveItem(c.Owner.Cables, c)

if c.Connected {
temp := &CableEvent{
Cable: c,
Port: c.Owner,
Target: c.Target,
}

c.Owner.Emit("disconnect", temp)
c.Owner.Iface.Emit("cable.disconnect", temp)
ins := c.Owner.Iface.Node.Instance
ins.Emit("cable.disconnect", temp)

alreadyEmitToInstance = true
} else {
c.Owner.Iface.Emit("cable.cancel", &CableEvent{
Cable: c,
Port: c.Owner,
Target: nil,
})
}
}

if c.Target != nil && c.Connected && (!hasWhich || which == c.Target) {
c.Target.Cables = utils.RemoveItem(c.Target.Cables, c)

temp := &CableEvent{
Cable: c,
Port: c.Target,
Target: c.Owner,
}

c.Target.Emit("disconnect", temp)
c.Target.Iface.Emit("cable.disconnect", temp)

if alreadyEmitToInstance == false {
ins := c.Target.Iface.Node.Instance
ins.Emit("cable.disconnect", temp)
}
}
}
32 changes: 19 additions & 13 deletions engine/customevent.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,25 @@ package engine

import (
"strings"

"github.com/blackprint/engine-go/utils"
)

type eventObj struct {
callback any
once bool
}

type customEvent struct {
type CustomEvent struct {
events map[string][]*eventObj
}

func (e *customEvent) listen(evName string, callback any, once bool) {
func (e *CustomEvent) listen(evName string, callback any, once bool) {
if e.events == nil {
e.events = map[string][]*eventObj{}
}

evs := strings.Split(evName, ",")
evs := strings.Split(evName, " ")

for _, name := range evs {
list := e.events[name]
Expand All @@ -33,7 +35,7 @@ func (e *customEvent) listen(evName string, callback any, once bool) {
}

if exist {
break
continue
}

e.events[name] = append(list, &eventObj{
Expand All @@ -43,43 +45,47 @@ func (e *customEvent) listen(evName string, callback any, once bool) {
}
}

func (e *customEvent) On(evName string, callback any) {
func (e *CustomEvent) On(evName string, callback any) {
e.listen(evName, callback, false)
}

func (e *customEvent) Once(evName string, callback any) {
func (e *CustomEvent) Once(evName string, callback any) {
e.listen(evName, callback, true)
}

func (e *customEvent) Off(evName string, callback any) {
func (e *CustomEvent) Off(evName string, callback any) {
if e.events == nil {
return
}

evs := strings.Split(evName, ",")
evs := strings.Split(evName, " ")
for _, name := range evs {
if callback == nil {
e.events[name] = []*eventObj{}
break
continue
}

list := e.events[name]
if list == nil {
continue
}

for i, cb := range list {
if cb.callback == callback {
e.events[name] = append(list[:i], list[i+1:]...)
break
e.events[name] = utils.RemoveItemAtIndex(list, i)
continue
}
}
}
}

func (e *customEvent) QTrigger(evName string, data any) {
func (e *CustomEvent) Emit(evName string, data any) {
list := e.events[evName]
for i, cb := range list {
cb.callback.(func(any))(data)

if cb.once {
e.events[evName] = append(list[:i], list[i+1:]...)
e.events[evName] = utils.RemoveItemAtIndex(list, i)
}
}
}
Loading