trying to find a consistent and C++1x styled graph representation
This commit is contained in:
parent
f6c7f1adbb
commit
2e151b87c6
13 changed files with 528 additions and 31 deletions
|
@ -5,6 +5,6 @@ cmake_minimum_required(VERSION 3.8)
|
|||
|
||||
project(pixwerx)
|
||||
|
||||
set (CMAKE_CXX_STANDARD 14)
|
||||
set (CMAKE_CXX_STANDARD 17)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
|
164
src/core/include/pw/core/log.hpp
Normal file
164
src/core/include/pw/core/log.hpp
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Copyright (C) 1999-2017 Hartmut Seichter
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PW_CORE_LOG_HPP_
|
||||
#define PW_CORE_LOG_HPP_
|
||||
|
||||
#include <pw/core/globals.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
namespace pw {
|
||||
|
||||
class Log;
|
||||
|
||||
/**
|
||||
* @brief the streaming interface for the logger
|
||||
*/
|
||||
class LogStream {
|
||||
public:
|
||||
|
||||
|
||||
LogStream(Log* log = nullptr);
|
||||
~LogStream();
|
||||
LogStream(const LogStream& other);
|
||||
|
||||
|
||||
LogStream &operator << (const bool &value);
|
||||
LogStream &operator << (const char *value);
|
||||
LogStream& operator << (const std::string& value); ///! log a string
|
||||
|
||||
LogStream& operator << (const float &value); ///! log a float value
|
||||
LogStream& operator << (const double &value); ///! log a double value
|
||||
|
||||
LogStream& operator << (const int &value); ///! log a int value
|
||||
LogStream& operator << (const unsigned int &value); ///! log a int value
|
||||
|
||||
LogStream& operator << (const long &value); ///! log a long value
|
||||
LogStream& operator << (const unsigned long &value); ///! log a int value
|
||||
|
||||
LogStream& operator << (const void *value); ///! pointer
|
||||
|
||||
protected:
|
||||
|
||||
Log* _log;
|
||||
std::string _line;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief multipurpose logger used internally
|
||||
*/
|
||||
class Log {
|
||||
public:
|
||||
|
||||
enum LogLevel {
|
||||
kNone, //!< nothing will be logged, even no errors
|
||||
kError, //!< only errors will be logged
|
||||
kWarning, //!< log warnings (non-critical errors)
|
||||
kMessage, //!< log messages (something to note but not an error)
|
||||
kNotify, //!< log some more information
|
||||
kInfo, //!< log verbose information
|
||||
kAll = 0xFF //!< log absolutely everything
|
||||
};
|
||||
|
||||
|
||||
/** sets the logging level */
|
||||
void setLevel(LogLevel level) {_level = level;}
|
||||
|
||||
/** gets the logging level */
|
||||
LogLevel level() const { return _level; }
|
||||
|
||||
/**
|
||||
* @brief get the stream interface of the logger
|
||||
* @return return a temporary object that will write and flush the logger
|
||||
*/
|
||||
static LogStream s(LogLevel level = kInfo);
|
||||
|
||||
inline static LogStream d() { return s(Log::kInfo); }
|
||||
inline static LogStream e() { return s(Log::kError); }
|
||||
inline static LogStream w() { return s(Log::kWarning); }
|
||||
|
||||
/**
|
||||
* @brief returns the instance of the logger
|
||||
* @return
|
||||
*/
|
||||
static Log& get();
|
||||
|
||||
/**
|
||||
* @brief write a message to the log
|
||||
* @param message string
|
||||
*/
|
||||
void write(const std::string &message);
|
||||
|
||||
typedef std::function<void(const char*)> Callback;
|
||||
typedef std::vector<Callback> CallbackList;
|
||||
|
||||
protected:
|
||||
|
||||
Log();
|
||||
~Log();
|
||||
|
||||
CallbackList _callbacks;
|
||||
LogLevel _level;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief helper for changing the log level in a scope
|
||||
*/
|
||||
struct ScopeLogLevel
|
||||
{
|
||||
Log::LogLevel levelOutside;
|
||||
explicit ScopeLogLevel(Log::LogLevel level)
|
||||
{
|
||||
levelOutside = Log::get().level();
|
||||
Log::get().setLevel(level);
|
||||
}
|
||||
~ScopeLogLevel()
|
||||
{
|
||||
Log::get().setLevel(levelOutside);
|
||||
}
|
||||
};
|
||||
|
||||
template <Log::LogLevel level>
|
||||
struct tpScopeLog {
|
||||
const char* info;
|
||||
explicit tpScopeLog(const char* i) : info(i) {
|
||||
Log::s(level) << info;
|
||||
}
|
||||
|
||||
~tpScopeLog() {
|
||||
Log::s(level) << info;
|
||||
}
|
||||
};
|
||||
|
||||
// some macros
|
||||
|
||||
#define LOG_INFO() Log::s()
|
||||
#define LOG_FUNC() LOG_INFO() << __FUNCTION__ << " " << __LINE__ << " "
|
||||
}
|
||||
|
||||
|
||||
#endif
|
57
src/core/include/pw/core/timer.hpp
Normal file
57
src/core/include/pw/core/timer.hpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
/* vim: set tabstop=4:softtabstop=4:shiftwidth=4:noexpandtab */
|
||||
/*
|
||||
* SSTT - Simplified Spatial Target Tracker
|
||||
*
|
||||
* (c) Copyrights 2007-2018 Hartmut Seichter
|
||||
*/
|
||||
|
||||
#ifndef PW_CORE_TIMER_HPP_
|
||||
#define PW_CORE_TIMER_HPP_
|
||||
|
||||
|
||||
#include <pw/core/globals.hpp>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace pw {
|
||||
|
||||
/**
|
||||
* @brief A simple timer
|
||||
*/
|
||||
class timer {
|
||||
public:
|
||||
|
||||
const static unsigned int UnitMicroSeconds = 1000000;
|
||||
const static unsigned int UnitMilliSeconds = 1000;
|
||||
const static unsigned int UnitSeconds = 1;
|
||||
|
||||
typedef std::chrono::time_point<std::chrono::high_resolution_clock> tick_t;
|
||||
|
||||
timer(); /// c'tor
|
||||
~timer(); /// d'tor
|
||||
|
||||
void reset(); /// reset the timer
|
||||
|
||||
/**
|
||||
* @brief elapsed time based on the scale
|
||||
* @param scale units the time will be reported
|
||||
* @return value of the time since last @see reset
|
||||
*/
|
||||
double elapsed(unsigned int scale = UnitMilliSeconds) const;
|
||||
|
||||
/**
|
||||
* @brief Now
|
||||
* @param scale
|
||||
* @return
|
||||
*/
|
||||
static double now(unsigned int scale = UnitMicroSeconds);
|
||||
|
||||
protected:
|
||||
|
||||
tick_t _start;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
204
src/core/src/log.cpp
Normal file
204
src/core/src/log.cpp
Normal file
|
@ -0,0 +1,204 @@
|
|||
/* vim: set tabstop=4:softtabstop=4:shiftwidth=4:noexpandtab */
|
||||
/*
|
||||
* SSTT - Simplified Spatial Target Tracker
|
||||
*
|
||||
* (c) Copyrights 2007-2018 Hartmut Seichter
|
||||
*/
|
||||
#include "pw/core/log.hpp"
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
|
||||
namespace pw {
|
||||
|
||||
#if defined(ANDROID)
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
|
||||
struct tpConsoleLog : tpLogCallback
|
||||
{
|
||||
void operator()(const char* cstr)
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_INFO, "libsstt", "%s", cstr);
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
struct tpConsoleLog
|
||||
{
|
||||
void operator()(const char* cstr) const
|
||||
{
|
||||
::fputs(cstr,stdout);
|
||||
::fflush(stdout);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
struct tpFileLog {
|
||||
FILE* m_file;
|
||||
|
||||
tpFileLog() : m_file(fopen("libsstt.txt","a+"))
|
||||
{
|
||||
}
|
||||
|
||||
~tpFileLog()
|
||||
{
|
||||
if (m_file != nullptr) fclose(m_file);
|
||||
}
|
||||
|
||||
void operator()(const char* stuff) {
|
||||
if (m_file) ::fputs(stuff,m_file);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
Log::Log() :
|
||||
_level(Log::kNotify)
|
||||
{
|
||||
#if defined(_WINCE)
|
||||
_callbacks.add(new tpFileLog());
|
||||
#else
|
||||
_callbacks.push_back(tpConsoleLog());
|
||||
#endif
|
||||
// drop some info
|
||||
LogStream stream(this);
|
||||
|
||||
// stream << "SSTT " << versionString(kVersionFull) << " " << std::thread::hardware_concurrency() << " threads";
|
||||
|
||||
}
|
||||
|
||||
Log::~Log()
|
||||
{
|
||||
}
|
||||
|
||||
void Log::write(const std::string& message)
|
||||
{
|
||||
for (CallbackList::iterator i = _callbacks.begin();
|
||||
i != _callbacks.end();
|
||||
++i)
|
||||
{
|
||||
if (message.length()) (*i)(message.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* static */
|
||||
LogStream Log::s(Log::LogLevel level) {
|
||||
return LogStream(&Log::get());
|
||||
}
|
||||
|
||||
Log &Log::get() {
|
||||
static Log the_log;
|
||||
return the_log;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// tpLogStream
|
||||
//
|
||||
|
||||
LogStream::LogStream(Log *log)
|
||||
: _log(log)
|
||||
{
|
||||
// _line.append(std::to_string(Timer::now(Timer::UnitSeconds)) + " ");
|
||||
}
|
||||
|
||||
LogStream::~LogStream()
|
||||
{
|
||||
_log->write(_line + "\n");
|
||||
}
|
||||
|
||||
LogStream::LogStream(const LogStream &other)
|
||||
: _log(other._log)
|
||||
, _line(other._line)
|
||||
{
|
||||
}
|
||||
|
||||
LogStream &LogStream::operator <<(const bool &value)
|
||||
{
|
||||
_line.append(value ? "true" : "false");
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogStream &LogStream::operator <<(const char* value)
|
||||
{
|
||||
_line.append(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogStream &LogStream::operator <<(const std::string &value)
|
||||
{
|
||||
_line.append(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogStream &LogStream::operator <<(const float &value)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << value;
|
||||
(*this) << ss.str();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogStream &LogStream::operator <<(const double &value)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << value;
|
||||
(*this) << ss.str();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogStream &LogStream::operator <<(const int &value)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << value;
|
||||
(*this) << ss.str();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogStream &LogStream::operator <<(const unsigned int &value)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << value;
|
||||
(*this) << ss.str();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogStream &LogStream::operator <<(const long &value)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << value;
|
||||
(*this) << ss.str();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogStream &LogStream::operator <<(const unsigned long &value)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << value;
|
||||
(*this) << ss.str();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogStream &LogStream::operator <<(const void *value)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << value;
|
||||
(*this) << ss.str();
|
||||
|
||||
return *this;
|
||||
}
|
||||
}
|
41
src/core/src/timer.cpp
Normal file
41
src/core/src/timer.cpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
/* vim: set tabstop=4:softtabstop=4:shiftwidth=4:noexpandtab */
|
||||
/*
|
||||
* SSTT - Simplified Spatial Target Tracker
|
||||
*
|
||||
* (c) Copyrights 2007-2018 Hartmut Seichter
|
||||
*/
|
||||
|
||||
#include "pw/core/timer.hpp"
|
||||
|
||||
|
||||
namespace pw {
|
||||
|
||||
static timer global_timer;
|
||||
|
||||
timer::timer()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
timer::~timer()
|
||||
{
|
||||
}
|
||||
|
||||
void timer::reset()
|
||||
{
|
||||
_start = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
double timer::elapsed( unsigned int scale ) const
|
||||
{
|
||||
std::chrono::duration<double> elapsed_seconds = std::chrono::high_resolution_clock::now() - _start;
|
||||
return elapsed_seconds.count() * scale;
|
||||
}
|
||||
|
||||
double timer::now( unsigned int scale )
|
||||
{
|
||||
return global_timer.elapsed(scale);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
namespace pw {
|
||||
|
||||
class transform;
|
||||
|
||||
/**
|
||||
* @brief nodes represent the structure for the scene graph
|
||||
*
|
||||
|
@ -50,16 +52,16 @@ public:
|
|||
friend class component;
|
||||
|
||||
//! standard c'tor
|
||||
node(const std::string& name = "");
|
||||
node();
|
||||
|
||||
//! copy c'tor
|
||||
node(const node& node);
|
||||
|
||||
//! d'tor
|
||||
virtual ~node();
|
||||
~node();
|
||||
|
||||
//! cloning interface
|
||||
virtual ref clone(const unsigned short& copymode) const;
|
||||
ref clone(const unsigned short& copymode) const;
|
||||
|
||||
std::string name() const; //!< get name
|
||||
void set_name(const std::string &name); //!< set name
|
||||
|
@ -68,7 +70,7 @@ public:
|
|||
inline ptr parent() const { return _path.back(); }
|
||||
|
||||
//! add a child node
|
||||
ref add_child(ref anode);
|
||||
ref add_child();
|
||||
|
||||
//! remove a child
|
||||
void remove_child(ref child_node);
|
||||
|
@ -89,7 +91,7 @@ public:
|
|||
const component::array& components() const;
|
||||
|
||||
//! add a node component
|
||||
void add_component(component::ref c);
|
||||
void add_component(component::ref new_component);
|
||||
|
||||
//! remove a node component
|
||||
void remove_component(component::ref c);
|
||||
|
@ -111,6 +113,10 @@ public:
|
|||
}
|
||||
|
||||
|
||||
const transform* transform() const { return _transform; }
|
||||
class transform* transform() { return _transform; }
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
ref_array _children; //!< list of children
|
||||
|
@ -118,6 +124,8 @@ protected:
|
|||
|
||||
component::array _components; //<! components
|
||||
|
||||
class transform* _transform;
|
||||
|
||||
std::string _name;
|
||||
|
||||
// change mask
|
||||
|
|
|
@ -9,6 +9,8 @@ namespace pw {
|
|||
class transform : public component {
|
||||
public:
|
||||
|
||||
transform() = default;
|
||||
|
||||
using component::component;
|
||||
using component::ref;
|
||||
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
#include "pw/scene/node.hpp"
|
||||
#include "pw/scene/transform.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace pw {
|
||||
|
||||
node::node(const std::string &name)
|
||||
: _name(name)
|
||||
node::node()
|
||||
{
|
||||
// generate node-name from cache generate
|
||||
// add_component(std::make_shared<transform>());
|
||||
}
|
||||
|
||||
node::node(const node &node)
|
||||
: _children(node.children())
|
||||
, _components(node.components())
|
||||
, _name(node._name)
|
||||
{
|
||||
}
|
||||
|
@ -28,21 +33,22 @@ void node::set_name(const std::string &name)
|
|||
_name = name;
|
||||
}
|
||||
|
||||
node::ref node::add_child(ref anode)
|
||||
node::ref node::add_child()
|
||||
{
|
||||
// remove old nodepath
|
||||
anode->_path.clear();
|
||||
// create new node
|
||||
node::ref new_node = std::make_shared<node>();
|
||||
|
||||
// take parent nodepath ...
|
||||
if (!this->is_root()) anode->_path = this->_path;
|
||||
if (!this->is_root()) new_node->_path = this->_path;
|
||||
|
||||
// add itself
|
||||
anode->_path.push_back(this);
|
||||
new_node->_path.push_back(this);
|
||||
|
||||
// add as child
|
||||
_children.push_back(anode);
|
||||
_children.push_back(new_node);
|
||||
|
||||
// return
|
||||
return anode;
|
||||
return new_node;
|
||||
}
|
||||
|
||||
void node::remove_child(ref child_node)
|
||||
|
@ -62,9 +68,19 @@ node::~node()
|
|||
//
|
||||
// components
|
||||
//
|
||||
void node::add_component(component::ref c)
|
||||
void node::add_component(component::ref new_component)
|
||||
{
|
||||
_components.push_back(c);
|
||||
if (new_component->singular()) {
|
||||
for (auto c : _components) {
|
||||
if (typeid(c.get()) == typeid (new_component.get())) {
|
||||
// warn and/or override?
|
||||
c = new_component;
|
||||
std::cout << "Meh!" << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
_components.push_back(new_component);
|
||||
}
|
||||
|
||||
void node::remove_component(component::ref c)
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
#include "pw/scene/transform.hpp"
|
||||
#include "pw/scene/node.hpp"
|
||||
|
||||
namespace pw {
|
||||
|
||||
|
||||
void transform::set_local(const matrix44 &local)
|
||||
{
|
||||
// TODO need to rebuild the transforms: both -> global down and global up
|
||||
_local = local;
|
||||
|
||||
// update the global transform
|
||||
if (_node && _node->parent() && _node->parent()->find<transform>()) {
|
||||
// this->_global = _node->find<transform>()->_global * _local;
|
||||
}
|
||||
}
|
||||
|
||||
void transform::set_global(const matrix44 &global)
|
||||
|
|
|
@ -22,11 +22,12 @@ int main(int argc,char **argv) {
|
|||
|
||||
using namespace pw;
|
||||
|
||||
node::ref n(new node("test"));
|
||||
node::ref n = std::make_shared<node>();
|
||||
n->set_name("root");
|
||||
|
||||
// check
|
||||
{
|
||||
n->add_child(std::make_shared<node>("sub"));
|
||||
n->add_child()->set_name("node");
|
||||
}
|
||||
|
||||
std::cout << "n name: " << n->name() << std::endl;
|
||||
|
@ -49,7 +50,7 @@ int main(int argc,char **argv) {
|
|||
print_node_path((n));
|
||||
|
||||
|
||||
auto t = n->find<transform>();
|
||||
auto t = n->transform();
|
||||
|
||||
if (t) std::cout << t->local().at(0,0) << std::endl;
|
||||
|
||||
|
|
|
@ -40,13 +40,14 @@ int main(int argc,char **argv) {
|
|||
|
||||
using namespace pw;
|
||||
|
||||
node::ref root(std::make_shared<node>("root"));
|
||||
root->add_child(std::make_shared<node>("sub-1"));
|
||||
node::ref root(std::make_shared<node>());
|
||||
root->set_name("root");
|
||||
root->add_child()->set_name("sub-1");
|
||||
|
||||
node::ref sub_2_1 = std::make_shared<node>("sub-2-1");
|
||||
// node::ref sub_2_1 = std::make_shared<node>("sub-2-1");
|
||||
|
||||
root->add_child(std::make_shared<node>("sub-3"))->add_child(sub_2_1);
|
||||
root->add_child(std::make_shared<node>("sub-2"))->add_child(std::make_shared<node>("sub-2-2"));
|
||||
// root->add_child(std::make_shared<node>("sub-3"))->add_child(sub_2_1);
|
||||
// root->add_child(std::make_shared<node>("sub-2"))->add_child(std::make_shared<node>("sub-2-2"));
|
||||
|
||||
// std::cout << "sub-2-1 parent count: " << sub_2_1->parents().size() << std::endl;
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ void script_scene::load(sol::table &ns)
|
|||
{
|
||||
|
||||
ns.new_usertype<node>("node",
|
||||
sol::constructors<node(), node(std::string)>(),
|
||||
sol::constructors<node()>(),
|
||||
"add_child",&node::add_child,
|
||||
"children",sol::readonly_property(&node::children),
|
||||
"child_count",sol::readonly_property(&node::child_count),
|
||||
|
|
|
@ -39,12 +39,10 @@ local aa = pw.axisangle.new(v1,0.707)
|
|||
print("aa.axis",aa.axis.x,aa.axis.y,aa.axis.z)
|
||||
print("aa.angle",aa.angle)
|
||||
|
||||
|
||||
local n_1 = pw.node.new("node-1")
|
||||
local n_2 = pw.node.new("node-2")
|
||||
local n_1 = pw.node.create()
|
||||
n_1.name = "root"
|
||||
|
||||
print("node 1: ", n_1.name)
|
||||
print("node 2: ", n_2.name)
|
||||
|
||||
--print(pw.node.create())
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue