Skip to content

Commit

Permalink
feat(cli): draw, undraw and update layer (#302)
Browse files Browse the repository at this point in the history
  • Loading branch information
FrancoLiberali authored Nov 24, 2023
1 parent dfb816a commit 3f4d17e
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 120 deletions.
31 changes: 7 additions & 24 deletions CLI/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ func (n *updateObjNode) execute() (interface{}, error) {
}
values = append(values, val)
}
paths, err := cmd.UnfoldPath(path)
paths, err := cmd.C.UnfoldPath(path)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -778,17 +778,8 @@ func (n *drawNode) execute() (interface{}, error) {
if err != nil {
return nil, err
}
paths, err := cmd.UnfoldPath(path)
if err != nil {
return nil, err
}
for _, subpath := range paths {
err = cmd.Draw(subpath, n.depth, n.force)
if err != nil {
return nil, err
}
}
return nil, nil

return nil, cmd.C.Draw(path, n.depth, n.force)
}

type undrawNode struct {
Expand All @@ -797,23 +788,15 @@ type undrawNode struct {

func (n *undrawNode) execute() (interface{}, error) {
if n.path == nil {
return nil, cmd.Undraw("")
return nil, cmd.C.Undraw("")
}

path, err := nodeToString(n.path, "path")
if err != nil {
return nil, err
}
paths, err := cmd.UnfoldPath(path)
if err != nil {
return nil, err
}
for _, subpath := range paths {
err = cmd.Undraw(subpath)
if err != nil {
return nil, err
}
}
return nil, nil

return nil, cmd.C.Undraw(path)
}

type lsogNode struct{}
Expand Down
89 changes: 5 additions & 84 deletions CLI/controllers/commandController.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@ func PWD() string {
return State.CurrPath
}

func UnfoldPath(path string) ([]string, error) {
if strings.Contains(path, "*") {
_, subpaths, err := C.GetObjectsWildcard(path)
func (controller Controller) UnfoldPath(path string) ([]string, error) {
if strings.Contains(path, "*") || models.PathHasLayer(path) {
_, subpaths, err := controller.GetObjectsWildcard(path)
return subpaths, err
}

if path == "_" {
return State.ClipBoard, nil
}

return []string{path}, nil
}

Expand Down Expand Up @@ -1234,87 +1236,6 @@ func UnlinkObject(path string) error {
return err
}

func objectCounter(parent map[string]interface{}) int {
count := 0
if parent != nil {
count += 1
if _, ok := parent["children"]; ok {
if arr, ok := parent["children"].([]interface{}); ok {
for _, childInf := range arr {
if child, ok := childInf.(map[string]interface{}); ok {
count += objectCounter(child)
}
}
}
if arr, ok := parent["children"].([]map[string]interface{}); ok {
for _, child := range arr {
count += objectCounter(child)
}
}
}
}
return count
}

// Unity UI will draw already existing objects
// by retrieving the hierarchy. 'force' bool is useful
// for scripting where the user can 'force' input if
// the num objects to draw surpasses threshold
func Draw(path string, depth int, force bool) error {
obj, err := C.GetObjectWithChildren(path, depth)
if err != nil {
return err
}

count := objectCounter(obj)
okToGo := true
if count > State.DrawThreshold && !force {
msg := "You are about to send " + strconv.Itoa(count) +
" objects to the Unity 3D client. " +
"Do you want to continue ? (y/n)\n"
(*State.Terminal).Write([]byte(msg))
(*State.Terminal).SetPrompt(">")
ans, _ := (*State.Terminal).Readline()
if ans != "y" && ans != "Y" {
okToGo = false
}
} else if force {
okToGo = true
} else if !force && count > State.DrawThreshold {
okToGo = false
}
if okToGo {
data := map[string]interface{}{"type": "create", "data": obj}
//0 to include the JSON filtration
unityErr := Ogree3D.Inform("Draw", 0, data)
if unityErr != nil {
return unityErr
}
}
return nil
}

func Undraw(x string) error {
var id string
if x == "" {
id = ""
} else {
obj, err := C.GetObject(x)
if err != nil {
return err
}
var ok bool
id, ok = obj["id"].(string)
if !ok {
return fmt.Errorf("this object has no id")
}
}

data := map[string]interface{}{"type": "delete", "data": id}

return Ogree3D.Inform("Undraw", 0, data)
}

func IsEntityDrawable(path string) (bool, error) {
obj, err := C.GetObject(path)
if err != nil {
Expand Down
107 changes: 107 additions & 0 deletions CLI/controllers/draw.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package controllers

import (
"fmt"
"strconv"
)

// Unity UI will draw already existing objects
// by retrieving the hierarchy. 'force' bool is useful
// for scripting where the user can 'force' input if
// the num objects to draw surpasses threshold
func (controller Controller) Draw(path string, depth int, force bool) error {
paths, err := controller.UnfoldPath(path)
if err != nil {
return err
}

for _, path := range paths {
obj, err := controller.GetObjectWithChildren(path, depth)
if err != nil {
return err
}

count := objectCounter(obj)
okToGo := true
if count > State.DrawThreshold && !force {
msg := "You are about to send " + strconv.Itoa(count) +
" objects to the Unity 3D client. " +
"Do you want to continue ? (y/n)\n"
(*State.Terminal).Write([]byte(msg))
(*State.Terminal).SetPrompt(">")
ans, _ := (*State.Terminal).Readline()
if ans != "y" && ans != "Y" {
okToGo = false
}
} else if force {
okToGo = true
} else if !force && count > State.DrawThreshold {
okToGo = false
}
if okToGo {
data := map[string]interface{}{"type": "create", "data": obj}
//0 to include the JSON filtration
unityErr := controller.Ogree3D.Inform("Draw", 0, data)
if unityErr != nil {
return unityErr
}
}
}

return nil
}

func objectCounter(parent map[string]interface{}) int {
count := 0
if parent != nil {
count += 1
if _, ok := parent["children"]; ok {
if arr, ok := parent["children"].([]interface{}); ok {
for _, childInf := range arr {
if child, ok := childInf.(map[string]interface{}); ok {
count += objectCounter(child)
}
}
}
if arr, ok := parent["children"].([]map[string]interface{}); ok {
for _, child := range arr {
count += objectCounter(child)
}
}
}
}
return count
}

func (controller Controller) Undraw(path string) error {
paths, err := controller.UnfoldPath(path)
if err != nil {
return err
}

for _, path := range paths {
var id string
if path == "" {
id = ""
} else {
obj, err := controller.GetObject(path)
if err != nil {
return err
}
var ok bool
id, ok = obj["id"].(string)
if !ok {
return fmt.Errorf("this object has no id")
}
}

data := map[string]interface{}{"type": "delete", "data": id}

err := controller.Ogree3D.Inform("Undraw", 0, data)
if err != nil {
return err
}
}

return nil
}
69 changes: 69 additions & 0 deletions CLI/controllers/layers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -593,3 +593,72 @@ func TestRemoveLayerRemovesAllObjectsOfTheLayer(t *testing.T) {
_, err := controller.DeleteObj("/Physical/BASIC/A/R1/#racks")
assert.Nil(t, err)
}

func TestDrawLayerDrawsAllObjectsOfTheLayer(t *testing.T) {
controller, mockAPI, mockOgree3D := layersSetup(t)

mockGetObjectHierarchy(mockAPI, roomWithChildren)
mockGetObjects(mockAPI, "category=rack&id=BASIC.A.R1.*&namespace=physical.hierarchy", []any{rack1, rack2})
mockGetObject(mockAPI, rack1)
mockGetObject(mockAPI, rack2)

controllers.State.ObjsForUnity = controllers.SetObjsForUnity([]string{"all"})

mockOgree3D.On(
"Inform", "Draw",
0, map[string]any{"data": removeChildren(rack1), "type": "create"},
).Return(nil)
mockOgree3D.On(
"Inform", "Draw",
0, map[string]any{"data": removeChildren(rack2), "type": "create"},
).Return(nil)

err := controller.Draw("/Physical/BASIC/A/R1/#racks", 0, true)
assert.Nil(t, err)
}

func TestDrawLayerWithDepthDrawsAllObjectsOfTheLayerAndChildren(t *testing.T) {
controller, mockAPI, mockOgree3D := layersSetup(t)

mockGetObjectHierarchy(mockAPI, roomWithChildren)
mockGetObjects(mockAPI, "category=rack&id=BASIC.A.R1.*&namespace=physical.hierarchy", []any{rack1, rack2})
mockGetObjectHierarchy(mockAPI, rack1)
mockGetObjectHierarchy(mockAPI, rack2)

controllers.State.ObjsForUnity = controllers.SetObjsForUnity([]string{"all"})

mockOgree3D.On(
"Inform", "Draw",
0, map[string]any{"data": keepOnlyDirectChildren(rack1), "type": "create"},
).Return(nil)
mockOgree3D.On(
"Inform", "Draw",
0, map[string]any{"data": keepOnlyDirectChildren(rack2), "type": "create"},
).Return(nil)

err := controller.Draw("/Physical/BASIC/A/R1/#racks", 1, true)
assert.Nil(t, err)
}

func TestUndrawLayerUndrawAllObjectsOfTheLayer(t *testing.T) {
controller, mockAPI, mockOgree3D := layersSetup(t)

mockGetObjectHierarchy(mockAPI, roomWithChildren)
mockGetObjects(mockAPI, "category=rack&id=BASIC.A.R1.*&namespace=physical.hierarchy", []any{rack1, rack2})
mockGetObject(mockAPI, rack1)
mockGetObject(mockAPI, rack2)

controllers.State.ObjsForUnity = controllers.SetObjsForUnity([]string{"all"})

mockOgree3D.On(
"Inform", "Undraw",
0, map[string]any{"data": "BASIC.A.R1.A01", "type": "delete"},
).Return(nil)
mockOgree3D.On(
"Inform", "Undraw",
0, map[string]any{"data": "BASIC.A.R1.B01", "type": "delete"},
).Return(nil)

err := controller.Undraw("/Physical/BASIC/A/R1/#racks")
assert.Nil(t, err)
}
21 changes: 9 additions & 12 deletions CLI/controllers/select.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
package controllers

import (
"cli/models"
"fmt"
"strings"
)

func (controller Controller) Select(path string) ([]string, error) {
var selection []string
var err error

if strings.Contains(path, "*") || models.PathHasLayer(path) {
_, selection, err = controller.GetObjectsWildcard(path)
} else if path != "" {
selection = []string{path}
err = controller.CD(path)
}

paths, err := controller.UnfoldPath(path)
if err != nil {
return nil, err
}

return controller.SetClipBoard(selection)
if len(paths) == 1 && paths[0] == path {
err = controller.CD(paths[0])
if err != nil {
return nil, err
}
}

return controller.SetClipBoard(paths)
}

func (controller Controller) SetClipBoard(x []string) ([]string, error) {
Expand Down

0 comments on commit 3f4d17e

Please sign in to comment.