Skip to content

Commit

Permalink
Merge pull request #226 from KaijuEngine/brent
Browse files Browse the repository at this point in the history
Adding start of hierarchy
BrentFarris authored Feb 24, 2024
2 parents 4c4fcbd + 2ab3ce4 commit e619c66
Showing 22 changed files with 170 additions and 102 deletions.
3 changes: 3 additions & 0 deletions content/editor/ui/editor_style.css
Original file line number Diff line number Diff line change
@@ -19,6 +19,9 @@ body {
.clip {
overflow: hidden;
}
.noClip {
overflow: scroll;
}
.fillWidth {
width: 100%;
}
10 changes: 10 additions & 0 deletions content/editor/ui/hierarchy_window.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.entry {
width: 100%;
height: 24px;
color: white;
background-color: #1f1f1f;
line-height: 24px;
}
.entry:hover {
background-color: #313232;
}
20 changes: 20 additions & 0 deletions content/editor/ui/hierarchy_window.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="editor/ui/editor_style.css">
<link rel="stylesheet" type="text/css" href="editor/ui/hierarchy_window.css">
</head>
<body>
<div class="fill darkBG noClip">
{{range .}}
<div id="{{.Entity.Id}}" class="entry" onclick="selectedEntity">
{{if .Entity.Name}}
<span>{{.Entity.Name}}</span>
{{else}}
<span>&lt;Unnamed&gt;</span>
{{end}}
</div>
{{end}}
</div>
</body>
</html>
1 change: 1 addition & 0 deletions content/editor/ui/menu.html
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
<div id="WindowList" class="menuItemList">
<div class="menuItemListItem" onclick="openLogWindow">Log Window</div>
<div class="menuItemListItem" onclick="openContentWindow">Content Window</div>
<div class="menuItemListItem" onclick="openHierarchyWindow">Hierarchy Window</div>
</div>
<div id="HelpList" class="menuItemList">
<div class="menuItemListItem" onclick="openAbout">About</div>
49 changes: 0 additions & 49 deletions content/ui/hierarchy/hierarchy.html

This file was deleted.

7 changes: 6 additions & 1 deletion src/assets/asset_importer/obj_importer.go
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@
package asset_importer

import (
"errors"
"kaiju/assets"
"kaiju/assets/asset_info"
"kaiju/editor/cache/project_cache"
@@ -78,6 +79,10 @@ func importMeshToCache(adi *asset_info.AssetDatabaseInfo) error {
return err
}
res := loaders.OBJ(src)
if len(res.Meshes) == 0 {
return errors.New("no meshes found in OBJ file")
}
adi.Metadata["name"] = res.Meshes[0].Name
for _, o := range res.Meshes {
info := adi.SpawnChild(uuid.New().String())
info.Type = editor_config.AssetTypeMesh
@@ -88,7 +93,7 @@ func importMeshToCache(adi *asset_info.AssetDatabaseInfo) error {
// TODO: Write the correct material to the adi
info.Metadata["shader"] = assets.ShaderDefinitionBasic
info.Metadata["texture"] = assets.TextureSquare
info.Metadata["name"] = o.Name
info.Metadata["name"] = o.MeshName
adi.Children = append(adi.Children, info)
}
return nil
9 changes: 5 additions & 4 deletions src/editor/cache/editor_cache/editor_cache_config.go
Original file line number Diff line number Diff line change
@@ -38,8 +38,9 @@
package editor_cache

const (
CacheFolder = "Kaiju"
MainWindow = "main"
LogWindow = "log"
ContentWindow = "content"
CacheFolder = "Kaiju"
MainWindow = "main"
LogWindow = "log"
ContentWindow = "content"
HierarchyWindow = "hierarchy"
)
4 changes: 3 additions & 1 deletion src/editor/content/content_opener/obj_opener.go
Original file line number Diff line number Diff line change
@@ -108,7 +108,9 @@ func load(host *engine.Host, adi asset_info.AssetDatabaseInfo, e *engine.Entity)

func (o ObjOpener) Open(adi asset_info.AssetDatabaseInfo, ed interfaces.Editor) error {
host := ed.Host()
e := host.NewEntity()
e := engine.NewEntity()
e.GenerateId()
host.AddEntity(e)
e.SetName(adi.MetaValue("name"))
for i := range adi.Children {
if err := load(host, adi.Children[i], e); err != nil {
2 changes: 1 addition & 1 deletion src/editor/editor.go
Original file line number Diff line number Diff line change
@@ -121,7 +121,7 @@ func New() *Editor {
}
ed.container = host_container.New("Kaiju Editor", logStream)
host := ed.container.Host
editor_window.OpenWindow(ed, editor_cache.MainWindow,
editor_window.OpenWindow(ed,
engine.DefaultWindowWidth, engine.DefaultWindowHeight, -1, -1)
ed.container.RunFunction(func() {
addConsole(ed.container.Host)
3 changes: 2 additions & 1 deletion src/editor/stages/manager.go
Original file line number Diff line number Diff line change
@@ -126,9 +126,10 @@ func (m *Manager) Load(adi asset_info.AssetDatabaseInfo, host *engine.Host) erro
klib.BinaryRead(stream, &eCount)
entities := make([]*engine.Entity, 0, eCount)
for i := int32(0); i < eCount && err == nil; i++ {
e := m.host.NewEntity()
e := engine.NewEntity()
entities = append(entities, e)
err = e.EditorDeserialize(stream, host)
m.host.AddEntity(e)
}
if err != nil {
for i := 0; i < len(entities); i++ {
3 changes: 1 addition & 2 deletions src/editor/ui/content_window/content_window.go
Original file line number Diff line number Diff line change
@@ -97,8 +97,7 @@ func New(opener *content_opener.Opener, editor interfaces.Editor) {
s.funcMap["contentClick"] = s.contentClick
s.container = host_container.New("Content Browser", nil)
x, y := editor.Host().Window.Center()
editor_window.OpenWindow(s, editor_cache.MainWindow,
500, 300, x-250, y-150)
editor_window.OpenWindow(s, 500, 300, x-250, y-150)
s.container.RunFunction(func() {
s.reloadUI()
})
2 changes: 1 addition & 1 deletion src/editor/ui/editor_window/editor_window.go
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ type EditorWindow interface {
Closed()
}

func OpenWindow(win EditorWindow, winTag string,
func OpenWindow(win EditorWindow,
defaultWidth, defaultHeight, defaultX, defaultY int) {
w, h := defaultWidth, defaultHeight
x, y := defaultX, defaultY
78 changes: 48 additions & 30 deletions src/editor/ui/hierarchy/hierarchy.go
Original file line number Diff line number Diff line change
@@ -38,16 +38,23 @@
package hierarchy

import (
"kaiju/editor/cache/editor_cache"
"kaiju/editor/interfaces"
"kaiju/editor/ui/editor_window"
"kaiju/engine"
"kaiju/host_container"
"kaiju/klib"
"kaiju/markup"
"kaiju/markup/document"
"kaiju/matrix"
"kaiju/systems/events"
"kaiju/ui"
"strings"
"log/slog"
)

type Hierarchy struct {
editor interfaces.Editor
container *host_container.Container
doc *document.Document
input *ui.Input
onChangeId events.Id
@@ -57,42 +64,53 @@ type entityEntry struct {
Entity *engine.Entity
}

func New() *Hierarchy {
return &Hierarchy{}
}
func (h *Hierarchy) Tag() string { return editor_cache.HierarchyWindow }
func (h *Hierarchy) Container() *host_container.Container { return h.container }
func (h *Hierarchy) Closed() {}

func (h *Hierarchy) Destroy() {
if h.doc != nil {
for _, elm := range h.doc.Elements {
elm.UI.Entity().Destroy()
}
func New(editor interfaces.Editor) {
h := &Hierarchy{
editor: editor,
container: host_container.New("Hierarchy", nil),
}
}

func (h *Hierarchy) Create(host *engine.Host) {
allEntities := host.Entities()
editor_window.OpenWindow(h, 300, 600, -1, -1)
allEntities := editor.Host().Entities()
entries := make([]entityEntry, 0, len(allEntities))
for _, entity := range allEntities {
entries = append(entries, entityEntry{Entity: entity})
}
html := klib.MustReturn(host.AssetDatabase().ReadText("ui/hierarchy/hierarchy.html"))
h.doc = markup.DocumentFromHTMLString(host, html, "", entries, nil)
searchInputElement, _ := h.doc.GetElementById("hierarchyInput")
entityList, _ := h.doc.GetElementById("entityList")
h.input = searchInputElement.UI.(*ui.Input)

h.input.Data().OnChange.Remove(h.onChangeId)
h.onChangeId = h.input.Data().OnChange.Add(func() {
activeText := strings.ToLower(h.input.Text())

for idx := range entityList.HTML.Children {
label := entityList.HTML.Children[idx].Children[0].DocumentElement.UI.(*ui.Label)
h.doc = klib.MustReturn(markup.DocumentFromHTMLAsset(
h.container.Host, "editor/ui/hierarchy_window.html", entries,
map[string]func(*document.DocElement){
"selectedEntity": h.onSelectedEntity,
}))
}

if strings.Contains(strings.ToLower(label.Text()), activeText) {
entityList.HTML.Children[idx].DocumentElement.UI.Entity().Activate()
} else {
entityList.HTML.Children[idx].DocumentElement.UI.Entity().Deactivate()
func (h *Hierarchy) onSelectedEntity(elm *document.DocElement) {
id := elm.HTML.Attribute("id")
if e, ok := h.editor.Host().FindEntity(id); !ok {
slog.Error("Could not find entity", slog.String("id", id))
} else {
kb := &h.container.Host.Window.Keyboard
if kb.HasCtrl() {
h.editor.Selection().Toggle(e)
} else if kb.HasShift() {
h.editor.Selection().Add(e)
} else {
h.editor.Selection().Set(e)
}
for i := range elm.HTML.Parent.Children {
elm.HTML.Parent.Children[i].DocumentElement.UIPanel.UnEnforceColor()
}
for i := range elm.HTML.Parent.Children {
child := &elm.HTML.Parent.Children[i]
id := child.Parent.Children[i].Attribute("id")
for _, se := range h.editor.Selection().Entities() {
if se.Id() == id {
child.DocumentElement.UIPanel.EnforceColor(matrix.ColorDarkBlue())
break
}
}
}
})
}
}
3 changes: 1 addition & 2 deletions src/editor/ui/log_window/log_window.go
Original file line number Diff line number Diff line change
@@ -158,8 +158,7 @@ func (l *LogWindow) Show(listing *editor_window.Listing) {
return
}
l.container = host_container.New("Log Window", nil)
editor_window.OpenWindow(l, editor_cache.MainWindow,
engine.DefaultWindowWidth,
editor_window.OpenWindow(l, engine.DefaultWindowWidth,
engine.DefaultWindowWidth/3, -1, -1)
l.reloadUI()
listing.Add(l)
20 changes: 13 additions & 7 deletions src/editor/ui/menu/editor_menu.go
Original file line number Diff line number Diff line change
@@ -42,6 +42,7 @@ import (
"kaiju/editor/interfaces"
"kaiju/editor/ui/about_window"
"kaiju/editor/ui/content_window"
"kaiju/editor/ui/hierarchy"
"kaiju/editor/ui/log_window"
"kaiju/engine"
"kaiju/host_container"
@@ -78,13 +79,14 @@ func New(container *host_container.Container,
editor: editor,
}
funcMap := map[string]func(*document.DocElement){
"openLogWindow": m.openLogWindow,
"openRepository": openRepository,
"openAbout": openAbout,
"newStage": m.newStage,
"saveStage": m.saveStage,
"openProject": m.openProject,
"openContentWindow": m.openContentWindow,
"openLogWindow": m.openLogWindow,
"openRepository": openRepository,
"openAbout": openAbout,
"newStage": m.newStage,
"saveStage": m.saveStage,
"openProject": m.openProject,
"openContentWindow": m.openContentWindow,
"openHierarchyWindow": m.openHierarchyWindow,
}
m.doc = markup.DocumentFromHTMLString(host, html, "", nil, funcMap)
allItems := m.doc.GetElementsByClass("menuItem")
@@ -165,6 +167,10 @@ func (m *Menu) openContentWindow(*document.DocElement) {
content_window.New(m.contentOpener, m.editor)
}

func (m *Menu) openHierarchyWindow(*document.DocElement) {
hierarchy.New(m.editor)
}

func (m *Menu) newStage(*document.DocElement) {
m.editor.StageManager().New()
}
20 changes: 18 additions & 2 deletions src/engine/entity.ed.go
Original file line number Diff line number Diff line change
@@ -47,6 +47,9 @@ import (
"kaiju/editor/cache/project_cache"
"kaiju/matrix"
"kaiju/rendering"
"log/slog"

"github.com/KaijuEngine/uuid"
)

const (
@@ -121,6 +124,15 @@ func (e *entityEditorBindings) Remove(key string) {
delete(e.data, key)
}

func (e *Entity) GenerateId() string {
if e.id == "" {
e.id = uuid.New().String()
} else {
slog.Error("Generating entity ID when one already exists")
}
return e.id
}

func (e *Entity) EditorSerialize(stream io.Writer) error {
if e.IsDestroyed() {
return errors.New("destroyed entities cannot be serialized")
@@ -129,7 +141,9 @@ func (e *Entity) EditorSerialize(stream io.Writer) error {
var p, r, s = e.Transform.Position(), e.Transform.Rotation(), e.Transform.Scale()
cpyDrawings := e.EditorBindings.Drawings()
e.EditorBindings.Remove(editorDrawingBinding)
if err := enc.Encode(p); err != nil {
if err := enc.Encode(e.id); err != nil {
return err
} else if err := enc.Encode(p); err != nil {
return err
} else if err = enc.Encode(r); err != nil {
return err
@@ -154,7 +168,9 @@ func (e *Entity) EditorSerialize(stream io.Writer) error {
func (e *Entity) EditorDeserialize(stream io.Reader, host *Host) error {
dec := gob.NewDecoder(stream)
var p, r, s matrix.Vec3
if err := dec.Decode(&p); err != nil {
if err := dec.Decode(&e.id); err != nil {
return err
} else if err := dec.Decode(&p); err != nil {
return err
} else if err = dec.Decode(&r); err != nil {
return err
7 changes: 7 additions & 0 deletions src/engine/entity.go
Original file line number Diff line number Diff line change
@@ -54,6 +54,7 @@ import (
// #Entity.SetChildrenOrdered to make them ordered. It is recommended to leave
// children unordered unless you have a specific reason to order them.
type Entity struct {
id string
Transform matrix.Transform
Parent *Entity
Children []*Entity
@@ -88,6 +89,12 @@ func NewEntity() *Entity {
return e
}

// ID returns the unique identifier of the entity. The Id is only valid for
// entities that are not generated through template instantiation. The Id may
// also be stripped during game runtime if the entity is never externally
// referenced by any other part of the system.
func (e *Entity) Id() string { return e.id }

// IsRoot returns true if the entity is the root entity in the hierarchy
func (e *Entity) IsRoot() bool { return e.Parent == nil }

8 changes: 8 additions & 0 deletions src/engine/host.ed.go
Original file line number Diff line number Diff line change
@@ -87,6 +87,9 @@ func (host *Host) addEntity(entity *Entity) {
host.editorEntities = append(host.editorEntities, entity)
} else {
host.entities = append(host.entities, entity)
if entity.id != "" {
host.entityLookup[entity.id] = entity
}
}
}

@@ -95,5 +98,10 @@ func (host *Host) addEntities(entities ...*Entity) {
host.editorEntities = append(host.editorEntities, entities...)
} else {
host.entities = append(host.entities, entities...)
for _, e := range entities {
if e.id != "" {
host.entityLookup[e.id] = e
}
}
}
}
10 changes: 10 additions & 0 deletions src/engine/host.go
Original file line number Diff line number Diff line change
@@ -75,6 +75,7 @@ type Host struct {
name string
editorEntities editorEntities
entities []*Entity
entityLookup map[string]*Entity
frameRunner []frameRun
Window *windowing.Window
LogStream *logging.LogStream
@@ -121,6 +122,7 @@ func NewHost(name string, logStream *logging.LogStream) *Host {
UICamera: cameras.NewStandardCameraOrthographic(w, h, matrix.Vec3{0, 0, 250}),
LogStream: logStream,
frameRunner: make([]frameRun, 0),
entityLookup: make(map[string]*Entity),
}
return host
}
@@ -238,6 +240,14 @@ func (host *Host) AddEntities(entities ...*Entity) {
host.addEntities(entities...)
}

// FindEntity will search for an entity contained in this host by its id. If the
// entity is found, then it will return the entity and true, otherwise it will
// return nil and false.
func (host *Host) FindEntity(id string) (*Entity, bool) {
e, ok := host.entityLookup[id]
return e, ok
}

// Entities returns all the entities that are currently in the host. This will
// return all entities in the standard entity pool only.
func (host *Host) Entities() []*Entity { return host.entities }
8 changes: 8 additions & 0 deletions src/engine/host.rt.go
Original file line number Diff line number Diff line change
@@ -53,8 +53,16 @@ func (e EditorEntities) contains(entity *Entity) bool { return false }

func (host *Host) addEntity(entity *Entity) {
host.entities = append(host.entities, entity)
if entity.id != "" {
host.entityLookup[entity.id] = entity
}
}

func (host *Host) addEntities(entities ...*Entity) {
host.entities = append(host.entities, entities...)
for _, e := range entities {
if e.id != "" {
host.entityLookup[e.id] = e
}
}
}
3 changes: 3 additions & 0 deletions src/host_container/host_container.go
Original file line number Diff line number Diff line change
@@ -63,6 +63,9 @@ func (c *Container) Run(width, height, x, y int) error {
c.Host.Window.Renderer.Initialize(c.Host, int32(c.Host.Window.Width()), int32(c.Host.Window.Height()))
c.Host.FontCache().Init(c.Host.Window.Renderer, c.Host.AssetDatabase(), c.Host)
lastTime := time.Now()
// Do one clean update and render before opening the prep lock
c.Host.Update(0)
c.Host.Render()
c.PrepLock <- struct{}{}
for !c.Host.Closing {
c.Host.WaitForFrameRate()
2 changes: 1 addition & 1 deletion src/rendering/loaders/obj_loader.go
Original file line number Diff line number Diff line change
@@ -207,7 +207,7 @@ func OBJ(objData string) load_result.Result {
Color: builder.colors[builder.vIndexes[vi]],
}
}
res.Add("", builder.name, verts, builder.vIndexes, nil)
res.Add(builder.name, builder.name, verts, builder.vIndexes, nil)
}
return res
}

0 comments on commit e619c66

Please sign in to comment.