Skip to content

Commit

Permalink
File parameter node
Browse files Browse the repository at this point in the history
  • Loading branch information
EliCDavis committed Jun 21, 2024
1 parent 2098532 commit f46fc25
Show file tree
Hide file tree
Showing 13 changed files with 379 additions and 51 deletions.
51 changes: 18 additions & 33 deletions examples/edit-gaussian-splats/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ package main
import (
"bufio"
"bytes"
"errors"
"io"
"math"
"os"

"github.com/EliCDavis/polyform/drawing/coloring"
"github.com/EliCDavis/polyform/formats/ply"
Expand All @@ -23,26 +20,6 @@ import (
"github.com/EliCDavis/vector/vector4"
)

type FileNode = nodes.StructNode[[]byte, FileNodeData]

type FileNodeData struct {
Path nodes.NodeOutput[string]
}

func (fnd FileNodeData) Process() ([]byte, error) {
if fnd.Path == nil {
return nil, errors.New("no path specified")
}

f, err := os.Open(fnd.Path.Value())
if err != nil {
return nil, err
}
defer f.Close()

return io.ReadAll(f)
}

type PointcloudLoaderNode = nodes.StructNode[modeling.Mesh, PointcloudLoaderNodeData]

type PointcloudLoaderNodeData struct {
Expand Down Expand Up @@ -192,16 +169,24 @@ func main() {

pointcloud := &PointcloudLoaderNode{
Data: PointcloudLoaderNodeData{
Data: &FileNode{
Data: FileNodeData{
Path: &generator.ParameterNode[string]{
Name: "Pointcloud Path",
DefaultValue: "./point_cloud/iteration_30000/point_cloud.ply",
CLI: &generator.CliParameterNodeConfig[string]{
FlagName: "splat",
Usage: "Path to the guassian splat to load (PLY file)",
},
},
// Data: &FileNode{
// Data: FileNodeData{
// Path: &generator.ParameterNode[string]{
// Name: "Pointcloud Path",
// DefaultValue: "./point_cloud/iteration_30000/point_cloud.ply",
// CLI: &generator.CliParameterNodeConfig[string]{
// FlagName: "splat",
// Usage: "Path to the guassian splat to load (PLY file)",
// },
// },
// },
// },
Data: &generator.FileParameterNode{
Name: "Splat File",
CLI: &generator.CliParameterNodeConfig[string]{
FlagName: "splat",
Usage: "Path to the guassian splat to load (PLY file)",
// Default: "./point_cloud/iteration_30000/point_cloud.ply",
},
},
},
Expand Down
177 changes: 177 additions & 0 deletions generator/file_parameter.go
Original file line number Diff line number Diff line change
@@ -1 +1,178 @@
package generator

import (
"flag"
"io"
"os"

"github.com/EliCDavis/jbtf"
"github.com/EliCDavis/polyform/nodes"
)

type FileParameterNode struct {
Name string
DefaultValue []byte
CLI *CliParameterNodeConfig[string]

version int
appliedProfile []byte
}

func (in *FileParameterNode) Node() nodes.Node {
return in
}

func (in FileParameterNode) Port() string {
return "Out"
}

func (vn FileParameterNode) SetInput(input string, output nodes.Output) {
panic("input can not be set")
}

func (pn *FileParameterNode) DisplayName() string {
return pn.Name
}

func (pn *FileParameterNode) ApplyMessage(msg []byte) (bool, error) {
pn.version++
pn.appliedProfile = msg
return true, nil
}

func (pn *FileParameterNode) ToMessage() []byte {
return pn.Value()
}

func (pn *FileParameterNode) Value() []byte {
if pn.appliedProfile != nil {
return pn.appliedProfile
}

if pn.CLI != nil && pn.CLI.value != nil && *pn.CLI.value != "" {
f, err := os.Open(*pn.CLI.value)
if err != nil {
return nil
}
defer f.Close()

pn.appliedProfile, err = io.ReadAll(f)
if err != nil {
return nil
}

return pn.appliedProfile
}
return pn.DefaultValue
}

func (pn *FileParameterNode) Schema() ParameterSchema {
return ParameterSchemaBase{
Name: pn.Name,
Type: "[]uint8",
}
}

func (pn *FileParameterNode) Dependencies() []nodes.NodeDependency {
return nil
}

func (pn *FileParameterNode) State() nodes.NodeState {
return nodes.Processed
}

type FileNodeOutput struct {
Val *FileParameterNode
}

func (sno FileNodeOutput) Value() []byte {
return sno.Val.Value()
}

func (sno FileNodeOutput) Node() nodes.Node {
return sno.Val
}

func (sno FileNodeOutput) Port() string {
return "Out"
}

func (tn *FileParameterNode) Outputs() []nodes.Output {
return []nodes.Output{
{
Type: "[]uint8",
NodeOutput: FileNodeOutput{
Val: tn,
},
},
}
}

func (tn *FileParameterNode) Out() FileNodeOutput {
return FileNodeOutput{
Val: tn,
}
}

func (tn FileParameterNode) Inputs() []nodes.Input {
return []nodes.Input{}
}

func (pn FileParameterNode) Version() int {
return pn.version
}

func (pn FileParameterNode) initializeForCLI(set *flag.FlagSet) {
if pn.CLI == nil {
return
}
pn.CLI.value = set.String(pn.CLI.FlagName, "", pn.CLI.Usage)
}

// CUSTOM JTF Serialization ===================================================

type fileNodeGraphSchema struct {
Name string `json:"name"`
CurrentValue *jbtf.Bytes `json:"currentValue"`
DefaultValue *jbtf.Bytes `json:"defaultValue"`
CLI *CliParameterNodeConfig[string] `json:"cli"`
}

func (pn *FileParameterNode) ToJSON(encoder *jbtf.Encoder) ([]byte, error) {
schema := fileNodeGraphSchema{
Name: pn.Name,
CLI: pn.CLI,
}

if pn.Value() != nil {
schema.CurrentValue = &jbtf.Bytes{
Data: pn.Value(),
}
}

if schema.DefaultValue != nil {
schema.DefaultValue = &jbtf.Bytes{
Data: pn.DefaultValue,
}
}

return encoder.Marshal(schema)
}

func (pn *FileParameterNode) FromJSON(decoder jbtf.Decoder, body []byte) (err error) {
gn, err := jbtf.Decode[fileNodeGraphSchema](decoder, body)
if err != nil {
return
}

pn.Name = gn.Name
pn.CLI = gn.CLI

if gn.DefaultValue != nil {
pn.DefaultValue = gn.DefaultValue.Data
}
if gn.CurrentValue != nil {
pn.appliedProfile = gn.CurrentValue.Data
}
return
}
14 changes: 14 additions & 0 deletions generator/html/js/node_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,16 @@ export class NodeManager {
nm.onNodeCreateCallback(this, ParameterNodeType(nodeDataType));
}

function FileParameterNode() {
const nodeDataType = "[]uint8";
// const nodeDataType = "github.com/EliCDavis/polyform/generator.FileParameterNode";
this.addOutput(ParameterNodeOutputPortName, nodeDataType);
this.title = "File";
this.color = ParameterNodeColor;
this.bgcolor = ParameterNodeBackgroundColor;
nm.onNodeCreateCallback(this, ParameterNodeType(nodeDataType));
}

function Vector3ParameterNode() {
const nodeDataType = "github.com/EliCDavis/vector/vector3.Vector[float64]";
this.addOutput(ParameterNodeOutputPortName, nodeDataType);
Expand Down Expand Up @@ -233,6 +243,7 @@ export class NodeManager {
LiteGraph.registerNodeType(ParameterNamespace("vector3[]"), Vector3ArrayParameterNode);
LiteGraph.registerNodeType(ParameterNamespace("color"), ColorParameterNode);
LiteGraph.registerNodeType(ParameterNamespace("image"), ImageParameterNode);
LiteGraph.registerNodeType(ParameterNamespace("file"), FileParameterNode);
}

sortNodesByName(nodesToSort) {
Expand Down Expand Up @@ -348,6 +359,9 @@ export class NodeManager {
case "image.Image":
return LiteGraph.createNode(ParameterNamespace("image"));

case "[]uint8":
return LiteGraph.createNode(ParameterNamespace("file"));

default:
throw new Error("unimplemented parameter type: " + parameterType);

Expand Down
59 changes: 59 additions & 0 deletions generator/html/js/nodes/file_parameter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@

export class FileParameterNode {

constructor(lightNode, nodeManager, id, parameterData, app) {
this.lightNode = lightNode;
this.id = id;
this.app = app;
this.lightNode.title = parameterData.name;

this.lightNode.onDropFile = (file) => {
// console.log(file)
var reader = new FileReader();
reader.onload = (evt) => {
console.log(evt.target.result)
nodeManager.nodeParameterChanged({
id: id,
data: evt.target.result,
binary: true
});
}
reader.readAsArrayBuffer(file);

const url = URL.createObjectURL(file);
// this.loadImage(this._url, function (img) {
// that.size[1] = (img.height / img.width) * that.size[0];
// });
// this.loadImgFromURL(url);
}
}

loadImgFromURL(url) {
// const img = document.createElement("img");
// img.src = url;
// img.onload = () => {
// // if (callback) {
// // callback(this);
// // }
// // console.log("Image loaded, size: " + img.width + "x" + img.height);
// // this.dirty = true;
// // that.boxcolor = "#9F9";f
// // that.setDirtyCanvas(true);
// this.lightNode.widgets[0].image = img
// this.lightNode.setSize(this.lightNode.computeSize());
// };
// img.onerror = () => {
// console.log("error loading the image:" + url);
// }
}

update(parameterData) {
console.log("image parameter", parameterData)
const curVal = parameterData.currentValue;
// this.app.RequestManager.getParameterValue(this.id, (response) => {
// const url = URL.createObjectURL(response);
// this.loadImgFromURL(url)
// })
}

}
4 changes: 4 additions & 0 deletions generator/html/js/nodes/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ImageParameterNode } from './image_parameter.js';
import { NodeAABBParameter } from './aabb_parameter.js';
import { ColorParameter } from './color_parameter.js';
import { NodeManager } from '../node_manager.js';
import { FileParameterNode } from './file_parameter.js';


function BuildParameter(liteNode, nodeManager, id, parameterData, app) {
Expand All @@ -31,6 +32,9 @@ function BuildParameter(liteNode, nodeManager, id, parameterData, app) {
case "image.Image":
return new ImageParameterNode(liteNode, nodeManager, id, parameterData, app);

case "[]uint8":
return new FileParameterNode(liteNode, nodeManager, id, parameterData, app);

case "geometry.AABB":
return new NodeAABBParameter(liteNode, nodeManager, id, parameterData, app);

Expand Down
1 change: 1 addition & 0 deletions generator/html/server.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
<script type="module" src="js/nodes/color_parameter.js"></script>
<script type="module" src="js/nodes/vector3_array_parameter.js"></script>
<script type="module" src="js/nodes/image_parameter.js"></script>
<script type="module" src="js/nodes/file_parameter.js"></script>
<script type="module" src="js/nodes/aabb_parameter.js"></script>
<script type="module" src="js/nodes/node.js"></script>
<script type="module" src="js/node_manager.js"></script>
Expand Down
1 change: 1 addition & 0 deletions generator/image_parameter_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ func (pn *ImageParameterNode) Value() image.Image {
if err != nil {
return nil
}
defer f.Close()

pn.appliedProfile, _, err = image.Decode(f)
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion generator/parameter_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ type ParameterNodeSchema[T any] struct {
type CliParameterNodeConfig[T any] struct {
FlagName string `json:"flagName"`
Usage string `json:"usage"`
value *T
// Default T `json:"default"`
value *T
}

// ============================================================================
Expand Down
Loading

0 comments on commit f46fc25

Please sign in to comment.