Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    infinite GeUserArea Rectangle inside GeDialogue

    SDK Help
    0
    10
    776
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      On 10/01/2015 at 11:30, xxxxxxxx wrote:

      User Information:
      Cinema 4D Version:   13+ 
      Platform:   Windows  ;   
      Language(s) :     C++  ;

      ---------
      I have a GeDialogue, it contains a GeUserArea , what I want is to create a typically infinite area similar to xpresso.

      I thought about drawing the background with DrawRectangle() using quite large numbers, but is this the correct approach? or I'm doing it wrong!!

      another question: can I draw a user area inside another user area?? "like nodes, a node can be a group which contains another nodes"

      and what about ScrollArea()? I tried using it, but it gives me errors in debug console "DrawBegin/End ist faul B" and hangs Cinema 4D

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 10/01/2015 at 12:23, xxxxxxxx wrote:

        The GeUserArea must be a finite size.  The 'infinite' part is in using a virtual window into your display space that is represented by the GeUserArea to draw into.  Store your virtual space window offsets (x, y) and draw accordingly with GeUserArea::Draw().

        You can't add a GeUserArea to a GeUserArea.  I draw nodes into it as separate entities.  So, I have a routine that knows how to draw a node and another that knows how to draw connections between nodes and so on.  With the bounding coordinates known, you can clip out nodes that aren't in the view and use SetClippingRegion() for anything partially drawn.

        For an infinite virtual space window set up, I would not use ScrollArea().  Handle mouse grabs (like in Google Maps or something), update your window x,y (typically upper left) by the mouseX, mouseY deltas, redraw.

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 10/01/2015 at 20:14, xxxxxxxx wrote:

          I see !Tongue[URL-REMOVED] , thanks a lot Robert.

          but here rises another 2 questions that are related:
          1- if I use quite large GeUserArea Rectangle "for example (-10000000,-10000000. 10000000. 10000000) " is this possible?  (this will be the world, and the window will be a tiny drawing region of 1000 x 1000 size)

          2- I want to do the behavior of re scaling , when you have an xpresso node, and mouse hovers the borders, it changes cursor and you can drag it to scale the node, how to do something similar? "in other words which functions to check, so if there is something automatic like a border function for them, or I will have to store all drawings """ nodes """ borders and check for mouse position against them "" will be a bad approach "" "


          [URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 11/01/2015 at 04:15, xxxxxxxx wrote:

            1. The GeUserArea rectangle is your window.  Your world is virtual and the GUA rectangle shows the portion given by your window offsets and GUA dimensions.  Typically, you would initialize this so that your world (0,0) are at the top, left of the GUA rectangle.

            2. When did you think you wouldn't have to store the position and dimensions of every existing node in the virtual world (in the node, of course)?  And then search them.  This is exactly what I did in the development phase.  There are many ways to increase search speed such as using sorting, hash tables, or binary space partitioning (divide and conquer).

            // iSUserArea.IsOverNode
            //*---------------------------------------------------------------------------*
            ShaderNode* iSUserArea::IsOverNode(LONG* pX, LONG* pY, const LONG& mx, const LONG& my)
            //*---------------------------------------------------------------------------*
            {
            	LONG h;
            	// Is mouse over ShaderNode? (Z-order search)
            	for (ShaderNode* snode = controller->GetLastSNode(); snode; snode = (ShaderNode* )snode->GetPrev())
            	{
            		h =			GetSNodeHeight(snode->GetType(), snode->GetExpanded(), snode->GetShowPreview());
            		snode->GetPos(pX, pY);
            		(*pX) -=	windowX;
            		(*pY) -=	windowY;
            		if ((mx >= *pX) && (mx < (*pX+cellWidth)) && (my >= *pY) && (my < (*pY+h))) return snode;
            	}
            	return NULL;
            }
            

            After you determine if you are over a node and which one, then you can refine where in the node to define locational functionality.

            *Note: my nodes here are all a fixed width with varying height by node type.

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 11/01/2015 at 05:05, xxxxxxxx wrote:

              thanks Robert 🙂, I know that I have to store all node data in the node class "like node size, position, inputs and outputs connections, etc.." , one last question that I didn't find an answer in the documentation:

              DrawMsg(Int32 x1, Int32 y1, Int32 x2, Int32 y2, const BaseContainer& msg);

              what are the values of x1,y1, x2,y2? is the the "window" of the world?

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                On 11/01/2015 at 05:34, xxxxxxxx wrote:

                I wouldn't worry about them.  I use them to set clipping and clear before drawing and that is it:

                // GeUserArea.Draw
                //*---------------------------------------------------------------------------*
                void iSUserArea::DrawMsg(LONG x1, LONG y1, LONG x2, LONG y2, const BaseContainer& msg)
                //*---------------------------------------------------------------------------*
                {
                	// No flicker
                	OffScreenOn();
                	SetClippingRegion(x1,y1,x2,y2);
                	// Clear area
                	DrawSetPen(isUAColor[ISCOLOR_BG]);
                	DrawRectangle(x1,y1,x2,y2);
                        ...
                

                What is more important is that you maintain your window offset in your GUA-derived class.  As noted, I initialize my windowX and windowY to (0,0) and then update them with LMB-down scrolls (I'm doing rectangular selection at the end, but it is easily modified for scrolling behavior) :

                // iSUserArea.GetWindowOffset
                //*---------------------------------------------------------------------------*
                void iSUserArea::GetWindowOffset(LONG* wx, LONG* wy)
                //*---------------------------------------------------------------------------*
                {
                	*wx = windowX;
                	*wy = windowY;
                }
                // iSUserArea.OffsetWindow
                //*---------------------------------------------------------------------------*
                void iSUserArea::OffsetWindow(const LONG& dx, const LONG& dy)
                //*---------------------------------------------------------------------------*
                {
                	windowX += dx;
                	windowY += dy;
                	Redraw();
                }
                // GeUserArea.InputEvent()
                //*---------------------------------------------------------------------------*
                Bool iSUserArea::InputEvent(const BaseContainer &msg)
                //*---------------------------------------------------------------------------*
                {
                	// Mouse Events
                	if (msg.GetLong(BFM_INPUT_DEVICE) == BFM_INPUT_MOUSE) return HandleMouseEvents(msg);
                	return FALSE;
                }
                // iSUserArea.HandleMouse
                //*---------------------------------------------------------------------------*
                Bool iSUserArea::HandleMouseEvents(const BaseContainer& msg)
                //*---------------------------------------------------------------------------*
                {
                	// Get Mouse Click location and other information
                	LONG	chn =						msg.GetLong(BFM_INPUT_CHANNEL);
                	// Left Button
                	if (chn == BFM_INPUT_MOUSELEFT)		return HandleMouse_LeftButton(msg);
                	// Right Button: Context PopupMenu
                	if (chn == BFM_INPUT_MOUSERIGHT)	return HandleMouse_RightButton(msg.GetLong(BFM_INPUT_X), msg.GetLong(BFM_INPUT_Y));
                	return TRUE;
                }
                //*---------------------------------------------------------------------------*
                Bool iSUserArea::HandleMouse_LeftButton(const BaseContainer& msg)
                //*---------------------------------------------------------------------------*
                {
                	// Get Mouse Click location and other information
                	LONG			mx =		msg.GetLong(BFM_INPUT_X);
                	LONG			my =		msg.GetLong(BFM_INPUT_Y);
                	Global2Local(&mx,&my);
                	LONG			pX, pY;
                	ShaderNode*		snode =		IsOverNode(&pX, &pY, mx, my);
                	// Do Something with ShaderNode
                	if (snode)					return HandleMouse_LBNode(snode, msg, pX, pY, mx, my);
                	// Over Background Area
                	// - Click - Remove all current selections
                	// - Drag - Create/Add to/Remove from Selection
                	return HandleMouse_LBBackground(msg, mx, my);
                }
                //*---------------------------------------------------------------------------*
                Bool iSUserArea::HandleMouse_LBBackground(const BaseContainer& msg, LONG mx, LONG my)
                //*---------------------------------------------------------------------------*
                {
                	// Do nothing on DoubleClick
                	if (msg.GetBool(BFM_INPUT_DOUBLECLICK))
                	{
                		PUM_Edit(NULL);
                		return TRUE;
                	}
                  
                	// Check for Keyboard Qualifiers
                	Bool			selmode;
                	LONG			qua =		msg.GetLong(BFM_INPUT_QUALIFIER);
                	if (qua == QSHIFT)			selmode = TRUE;
                	else if (qua == QCTRL)		selmode = FALSE;
                	else
                	{
                		controller->SelectAll(FALSE);
                		dialog->SelectedSNodes(FALSE);
                		selmode = TRUE;
                	}
                  
                	// Setup for dragging
                	BaseContainer	action(BFM_ACTION);
                	BaseContainer	state;
                	action.SetLong(BFM_ACTION_ID,GetId());
                	action.SetLong(BFM_ACTION_VALUE,0L);
                  
                	// General variables
                	LONG			width =		GetWidth();
                	LONG			height =	GetHeight();
                	LONG			hw =		width>>1;
                	LONG			hh =		height>>1;
                	LONG			rectX1 =	mx;
                	LONG			rectY1 =	my;
                	LONG			rectX2, rectY2;
                	// Drag Selecting
                	startX = rectX1;
                	startY = rectY1;
                	drawMode = ISUA_DRAWMODE_SELECTING;
                	while (GetInputState(BFM_INPUT_MOUSE,BFM_INPUT_MOUSELEFT,state))
                	{
                		if (state.GetLong(BFM_INPUT_VALUE) == 0) break;
                  
                		endX = state.GetLong(BFM_INPUT_X);
                		endY = state.GetLong(BFM_INPUT_Y);
                		Global2Local(&endX,&endY);
                		mx = endX/2L;
                		my = endY/2L;
                  
                		// Check for UserArea boundary, scroll if necessary
                		if (endX <= 0L)
                		{
                			windowX += mx;
                			startX -= mx;
                		}
                		else if (endX >= width)
                		{
                			windowX += (mx-hw);
                			startX -= (mx-hw);
                		}
                		if (endY <= 0L)
                		{
                			windowY += my;
                			startY -= my;
                		}
                		else if (endY >= height)
                		{
                			windowY += (my-hh);
                			startY -= (my-hh);
                		}
                  
                		Redraw();
                		action.SetLong(BFM_ACTION_INDRAG,TRUE);
                		SendParentMessage(action);
                	}
                	drawMode = ISUA_DRAWMODE_NORMAL;
                	rectX2 = endX;
                	rectY2 = endY;
                  
                	// Swap so that 1 is always UL, 2 LR
                	if (rectX1 > rectX2)
                	{
                		mx = rectX1;
                		rectX1 = rectX2;
                		rectX2 = mx;
                	}
                	if (rectY1 > rectY2)
                	{
                		my = rectY1;
                		rectY1 = rectY2;
                		rectY2 = my;
                	}
                  
                	// Find and Select/Deselect all ShaderNodes overlapped by Rectangle
                	LONG			pX, pY;
                	for (ShaderNode* snode = controller->GetFirstSNode(); snode; snode = (ShaderNode* )snode->GetNext())
                	{
                		snode->GetPos(&pX, &pY);
                		pX -= windowX;
                		mx = pX+cellWidth;
                		pY -= windowY;
                		my = pY+GetSNodeHeight(snode->GetType(), snode->GetExpanded(), snode->GetShowPreview());
                  
                		if ((my < rectY1) || (pY > rectY2) || (mx < rectX1) || (pX > rectX2)) continue;
                		controller->SelectNode(snode, selmode);
                		if (!selmode) dialog->SelectedSNodes(controller->AreSelectedSNodes());
                		else dialog->SelectedSNodes(TRUE);
                	}
                  
                	// Update and Notify
                	Redraw();
                	action.SetLong(BFM_ACTION_INDRAG,FALSE);
                	SendParentMessage(action);
                	return TRUE;
                }
                
                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  On 11/01/2015 at 06:48, xxxxxxxx wrote:

                  thanks a lot Robert 🙂

                  1 Reply Last reply Reply Quote 0
                  • H
                    Helper
                    last edited by

                    On 11/01/2015 at 07:36, xxxxxxxx wrote:

                    Can I ask you guys a stupid question?
                    What are these "Nodes" in your code. And where do the come from?

                    I've used the UA to draw shapes and move them around.
                    But how to you create these "nodes" that you can connect together in the UA?

                    I'm not having any luck with trying to put an xpresso window in a GeDialog. I can only launch a new one.
                    So I'm thinking that maybe I need to do what you guys are doing to creating my own "nodes" in my own UA. Instead of trying to use the existing xpresso window?
                    But I don't know how to create these "Nodes".

                    Sorry for the newbish question.
                    -ScottA

                    1 Reply Last reply Reply Quote 0
                    • H
                      Helper
                      last edited by

                      On 11/01/2015 at 09:13, xxxxxxxx wrote:

                      Scott, indeed, these nodes are classes I wrote.  The base class establishes a doubly-linked list set up (for easy insertion/deletion of nodes), position and size of the node graphically, inputs and outputs as NodeInput classes for connectivity, node ids, flags, methods, and other information.  The code is rather old and I would probably do it differently today having learned much over time.

                      ////////////////////////////////////////////////////////////////
                      // NodeInput.h
                      ////////////////////////////////////////////////////////////////
                      // Node Input Class include
                      ////////////////////////////////////////////////////////////////
                        
                      #ifndef _NODEINPUT_H_
                      #define _NODEINPUT_H_
                        
                      #include "ShaderNodeDefs.h"
                        
                      // Predefine for cross-referencing
                      class ShaderNode;
                        
                      // Input within Node
                      class NodeInput
                      {
                      	private:
                      		// NodeInput name
                      		String			name;
                      		// Vector(x,y,z), Color(R,G,B), Value(current,min,max), List(current,listtype,numitems)
                      		Vector			value;
                      		// Value Type - see NodeInput Type Defintions in ShaderNodeDefs
                      		LONG			type;
                      		// Whether Node accepts input connections
                      		Bool			acceptConnection;
                      		// ShaderNodes connected to this NodeInput
                      		LONG			numNodes;
                      		ShaderNode*		node;
                      		// - id of ShaderNode (for Read/Write/CopyTo)
                      		LONG			id;
                      		// ID of corresponding Edit Gadget in Dialog
                      		LONG			editID;
                      		// Name of bitmap file
                      		String			file;
                      	public:
                      		NodeInput();
                      		~NodeInput();
                      		// Initialize NodeInput
                      		void			Init(const String& t_name, const Vector& t_value, const LONG& t_type, const Bool& t_acceptConnection, ShaderNode* t_node, const String& t_file);
                      		// String name
                      		void			SetName(const String& t_name);
                      		String			GetName();
                      		// Vector value
                      		void			SetValue(const Vector& t_value);
                      		void			SetValueBool(const Bool& t_value);
                      		void			SetValueList(const LONG& t_value);
                      		void			SetValueReal(const Real& t_value);
                      		Vector			GetValue();
                      		Bool			GetValueBool();
                      		LONG			GetValueList();
                      		Real			GetValueReal();
                      		// LONG type
                      		Bool			IsInstanceOf(const LONG& t_type);
                      		void			SetType(const LONG& t_type);
                      		LONG			GetType();
                      		// Bool acceptConnection
                      		void			SetAcceptConnection(const Bool& t_acceptConnection);
                      		Bool			GetAcceptConnection();
                      		// ShaderNode *node
                      		void			SetNode(ShaderNode* t_node);
                      		ShaderNode*		GetNode();
                      		void			SetNodeID(const LONG& t_id);
                      		LONG			GetNodeID();
                      		// String file
                      		void			SetFile(String t_file);
                      		String			GetFile();
                      		// LONG editID
                      		void			SetEditID(const LONG& t_editID);
                      		LONG			GetEditID();
                      		// Read/Write/CopyTo
                      		Bool			Read(HyperFile* hf, LONG level);
                      		Bool			Write(HyperFile* hf);
                      		Bool			CopyTo(NodeInput* dni, Bool dataOnly);
                      };
                        
                      #endif //_NODEINPUT_H_
                      
                      ////////////////////////////////////////////////////////////////
                      // NodeInput.cpp
                      ////////////////////////////////////////////////////////////////
                      // Node Input Class
                      ////////////////////////////////////////////////////////////////
                        
                      // Includes
                        
                      #include "../glload.h"
                      #include "../general.h"
                      #include "NodeInput.h"
                      #include "ShaderNode.h"
                        
                      // ****************************************************************************
                      // METHODS: NodeInput
                      // Constructor #1
                      //*---------------------------------------------------------------------------*
                      NodeInput::NodeInput()
                      //*---------------------------------------------------------------------------*
                      {
                      	name =				String("");
                      	value =				Vector(0.0);
                      	type =				NODEINPUTTYPE_NONE;
                      	acceptConnection =	FALSE;
                      	numNodes =			0L;
                      	node =				NULL;
                      	id =				-1L;
                      	file =				String("");
                      	editID =			-1L;
                      }
                      // Destructor
                      //*---------------------------------------------------------------------------*
                      NodeInput::~NodeInput()
                      //*---------------------------------------------------------------------------*
                      {
                      }
                      // Initialize NodeInput
                      //*---------------------------------------------------------------------------*
                      void NodeInput::Init(const String& t_name, const Vector& t_value, const LONG& t_type, const Bool& t_acceptConnection, ShaderNode* t_node, const String& t_file)
                      //*---------------------------------------------------------------------------*
                      {
                      	name =				t_name;
                      	value =				Vector(t_value.x, t_value.y, t_value.z);
                      	type =				t_type;
                      	acceptConnection =	t_acceptConnection;
                      	node =				t_node;
                      	if (node)			id = node->GetID();
                      	else				id = -1L;
                      	file =				t_file;
                      }
                      // String name
                      //*---------------------------------------------------------------------------*
                      void NodeInput::SetName(const String& t_name)
                      //*---------------------------------------------------------------------------*
                      {
                      	name = t_name;
                      }
                      //*---------------------------------------------------------------------------*
                      String NodeInput::GetName()
                      //*---------------------------------------------------------------------------*
                      {
                      	return name;
                      }
                      // Vector value
                      //*---------------------------------------------------------------------------*
                      void NodeInput::SetValue(const Vector& t_value)
                      //*---------------------------------------------------------------------------*
                      {
                      	value = Vector(t_value.x, t_value.y, t_value.z);
                      }
                      //*---------------------------------------------------------------------------*
                      void NodeInput::SetValueBool(const Bool& t_value)
                      //*---------------------------------------------------------------------------*
                      {
                      	value.x = (Real)t_value;
                      }
                      //*---------------------------------------------------------------------------*
                      void NodeInput::SetValueList(const LONG& t_value)
                      //*---------------------------------------------------------------------------*
                      {
                      	value.x = (Real)t_value;
                      }
                      //*---------------------------------------------------------------------------*
                      void NodeInput::SetValueReal(const Real& t_value)
                      //*---------------------------------------------------------------------------*
                      {
                      	value.x = t_value;
                      }
                      //*---------------------------------------------------------------------------*
                      Vector NodeInput::GetValue()
                      //*---------------------------------------------------------------------------*
                      {
                      	return value;
                      }
                      //*---------------------------------------------------------------------------*
                      Bool NodeInput::GetValueBool()
                      //*---------------------------------------------------------------------------*
                      {
                      	return (Bool)(value.x);
                      }
                      //*---------------------------------------------------------------------------*
                      LONG NodeInput::GetValueList()
                      //*---------------------------------------------------------------------------*
                      {
                      	return (LONG)(value.x);
                      }
                      //*---------------------------------------------------------------------------*
                      Real NodeInput::GetValueReal()
                      //*---------------------------------------------------------------------------*
                      {
                      	return value.x;
                      }
                      // Bool acceptConnection
                      //*---------------------------------------------------------------------------*
                      void NodeInput::SetAcceptConnection(const Bool& t_acceptConnection)
                      //*---------------------------------------------------------------------------*
                      {
                      	acceptConnection = t_acceptConnection;
                      }
                      //*---------------------------------------------------------------------------*
                      Bool NodeInput::GetAcceptConnection()
                      //*---------------------------------------------------------------------------*
                      {
                      	return acceptConnection;
                      }
                      // LONG type
                      //*---------------------------------------------------------------------------*
                      Bool NodeInput::IsInstanceOf(const LONG& t_type)
                      //*---------------------------------------------------------------------------*
                      {
                      	return (type == t_type);
                      }
                      //*---------------------------------------------------------------------------*
                      void NodeInput::SetType(const LONG& t_type)
                      //*---------------------------------------------------------------------------*
                      {
                      	type = t_type;
                      }
                      //*---------------------------------------------------------------------------*
                      LONG NodeInput::GetType()
                      //*---------------------------------------------------------------------------*
                      {
                      	return type;
                      }
                      // ShaderNode* node
                      //*---------------------------------------------------------------------------*
                      void NodeInput::SetNode(ShaderNode* t_node)
                      //*---------------------------------------------------------------------------*
                      {
                      	node =		t_node;
                      	if (node)	id = node->GetID();
                      	else		id = -1L;
                      }
                      //*---------------------------------------------------------------------------*
                      ShaderNode* NodeInput::GetNode()
                      //*---------------------------------------------------------------------------*
                      {
                      	return node;
                      }
                      //*---------------------------------------------------------------------------*
                      void NodeInput::SetNodeID(const LONG& t_id)
                      //*---------------------------------------------------------------------------*
                      {
                      	id = t_id;
                      }
                      //*---------------------------------------------------------------------------*
                      LONG NodeInput::GetNodeID()
                      //*---------------------------------------------------------------------------*
                      {
                      	return id;
                      }
                      // String file
                      //*---------------------------------------------------------------------------*
                      void NodeInput::SetFile(String t_file)
                      //*---------------------------------------------------------------------------*
                      {
                      	file = t_file;
                      }
                      //*---------------------------------------------------------------------------*
                      String NodeInput::GetFile()
                      //*---------------------------------------------------------------------------*
                      {
                      	return file;
                      }
                      // LONG editID
                      //*---------------------------------------------------------------------------*
                      void NodeInput::SetEditID(const LONG& t_editID)
                      //*---------------------------------------------------------------------------*
                      {
                      	editID = t_editID;
                      }
                      //*---------------------------------------------------------------------------*
                      LONG NodeInput::GetEditID()
                      //*---------------------------------------------------------------------------*
                      {
                      	return editID;
                      }
                      // Read/Write/CopyTo
                      // - Read NodeInput info
                      //*---------------------------------------------------------------------------*
                      Bool NodeInput::Read(HyperFile* hf, LONG level)
                      //*---------------------------------------------------------------------------*
                      {
                      	if (!hf->ReadString(&name))				return FALSE;
                      	if (!hf->ReadVector(&value))			return FALSE;
                      	if (!hf->ReadLong(&type))				return FALSE;
                      	if (!hf->ReadBool(&acceptConnection))	return FALSE;
                      	// ShaderNode* node - Unique Index!
                      	if (!hf->ReadLong(&id))					return FALSE;
                      	if (!hf->ReadString(&file))				return FALSE;
                      	return TRUE;
                      }
                      // - Write NodeInput info
                      //*---------------------------------------------------------------------------*
                      Bool NodeInput::Write(HyperFile* hf)
                      //*---------------------------------------------------------------------------*
                      {
                      	if (!hf->WriteString(name))				return FALSE;
                      	if (!hf->WriteVector(value))			return FALSE;
                      	if (!hf->WriteLong(type))				return FALSE;
                      	if (!hf->WriteBool(acceptConnection))	return FALSE;
                      	// ShaderNode* node - Unique Index!
                      	if (!hf->WriteLong(id))					return FALSE;
                      	if (!hf->WriteString(file))				return FALSE;
                      	return TRUE;
                      }
                      // - Copy Source NodeInput info to Destination NodeInput
                      //*---------------------------------------------------------------------------*
                      Bool NodeInput::CopyTo(NodeInput* dni, Bool dataOnly)
                      //*---------------------------------------------------------------------------*
                      {
                      	dni->name = name;
                      	dni->value = Vector(value.x, value.y, value.z);
                      	dni->type = type;
                      	dni->acceptConnection = acceptConnection;
                      	dni->file = file;
                      	if (!dataOnly) dni->id = id;
                      	return TRUE;
                      }
                      
                      ////////////////////////////////////////////////////////////////
                      // ShaderNode.h
                      ////////////////////////////////////////////////////////////////
                      // Shader Node Base Class include
                      ////////////////////////////////////////////////////////////////
                        
                      #ifndef _SHADERNODE_H_
                      #define _SHADERNODE_H_
                        
                      #include "ShaderNodeDefs.h"
                        
                      // ShaderNode flags
                      #define SHADERNODE_FLAGS_NONE			0L
                      #define SHADERNODE_FLAGS_SHOWPREVIEW	(1<<0)
                      #define SHADERNODE_FLAGS_SELECTED		(1<<1)
                      #define SHADERNODE_FLAGS_CONNECTING		(1<<2)
                      #define SHADERNODE_FLAGS_EXPANDED		(1<<3)
                        
                      //class glload;
                      class NodeInput;
                      struct NodeInputDef;
                        
                      // Node within Tree
                      class ShaderNode
                      {
                      	public:
                      		ShaderNode*		prev;
                      		ShaderNode*		next;
                      		// - ShaderNode name
                      		String			name;
                      		// - UL Position within interface
                      		LONG			xPos;
                      		LONG			yPos;
                      		// - Unique ID
                      		LONG			id;
                      		// - Flags (see above)
                      		LONG			flags;
                      		// - Node Type - see ShaderNode Type Definitions in ShaderNodeDefs
                      		LONG			type;
                      		// NodeInputs: count
                      		LONG			numNodeInputs;
                      		LONG			acceptCount;
                      		// Number of outgoing connections
                      		LONG			connections;
                      		NodeInput*		nodeInputs;
                              // OpenGL Support
                      		//glload*			previewGL;
                      		// Bitmaps
                      		BaseBitmap*		previewBitmap;
                      		// For Output()
                      		ShaderNode*		sn;
                      		NodeInput*		ni;
                        
                      		// Methods
                      		ShaderNode();
                      		ShaderNode(const LONG& t_type, const LONG& t_numNodeInputs, const LONG& t_xPos, const LONG& t_yPos, const LONG& t_flags);
                      		virtual ~ShaderNode();
                      		Bool			Append(ShaderNode* previous);
                      		void			Remove();
                      		ShaderNode*		GetPrev();
                      		ShaderNode*		GetNext();
                      		// Initial ShaderNode
                      		Bool			Init(const LONG& t_xPos, const LONG& t_yPos, const LONG& t_pDim, const LONG& t_flags);
                      		Bool			InitInputs(NodeInputDef* nid);
                      		// String name
                      		void			SetName(const String& t_name);
                      		String			GetName();
                      		// Vector pos
                      		void			SetPos(const LONG& t_xPos, const LONG& t_yPos);
                      		void			GetPos(LONG* t_xPos, LONG* t_yPos);
                      		void			Move(const LONG& xDelta, const LONG& yDelta);
                      		// LONG id
                      		void			SetID(const LONG& t_id);
                      		LONG			GetID();
                      		// Bool showPreview
                      		void			SetShowPreview(const Bool& t_showPreview);
                      		Bool			GetShowPreview();
                      		void			InvertShowPreview();
                      		// Bool selected
                      		void			SetSelected(const Bool& t_selected);
                      		Bool			GetSelected();
                      		// Bool expanded
                      		void			SetExpanded(const Bool& t_expanded);
                      		Bool			GetExpanded();
                      		void			InvertExpanded();
                      		// LONG type
                      		Bool			IsInstanceOf(const LONG& t_type);
                      		void			SetType(const LONG& t_type);
                      		LONG			GetType();
                      		// NodeInputs
                      		LONG			GetNodeCount();
                      		LONG			GetAcceptCount();
                      		void			ClearInputs();
                      		// LONG connections
                      		void			SetConnections(const LONG& count);
                      		void			IncConnect();
                      		void			DecConnect();
                      		LONG			Connected();
                      		// Bool connecting
                      		void			SetConnecting(const Bool& t_connecting);
                      		Bool			IsConnecting();
                      		// NodeInput *nodeInputs - retrieve by index
                      		NodeInput*		GetNodeInput(LONG index=0L);
                      		// Read/Write/CopyTo
                      		Bool			Read(HyperFile* hf, LONG level);
                      		Bool			Write(HyperFile* hf);
                      		Bool			CopyTo(ShaderNode* dsn, Bool uniqueID);
                      		void			ReestablishNodeLinks(ShaderNode* firstSNode);
                      		// Preview Bitmap
                      		BaseBitmap*		GetPreview();
                      		// Pure Virtuals (no more)
                      		void			SetPreview(BaseMaterial* chn, Bool fromFile);
                      		Vector			Output(BaseMaterial* chn, ChannelData* cd);
                      };
                        
                      #endif //_SHADERNODE_H_
                      
                      ////////////////////////////////////////////////////////////////
                      // ShaderNode.cpp
                      ////////////////////////////////////////////////////////////////
                      // Shader Node and Node Input Class
                      ////////////////////////////////////////////////////////////////
                        
                      // Includes
                      //#include "../glload.h"
                      #include "../general.h"
                      #include "NodeInputDefs.h"
                      #include "NodeInput.h"
                      #include "ShaderNode.h"
                      #include "ShaderNodeStr.h"
                        
                        
                      // ****************************************************************************
                      // METHODS: ShaderNode
                      // Constructor #1
                      //*---------------------------------------------------------------------------*
                      ShaderNode::ShaderNode()
                      //*---------------------------------------------------------------------------*
                      {
                      	nodeInputs =	NULL;
                      	previewBitmap =	NULL;
                      	//previewGL	=   NULL;
                      	prev =			NULL;
                      	next =			NULL;
                      	xPos =			0L;
                      	yPos =			0L;
                      	flags =			SHADERNODE_FLAGS_NONE;
                      	type =			SHADERNODETYPE_NONE;
                      	numNodeInputs = 0L;
                      	acceptCount =	0L;
                      	connections =	0L;
                      }
                      // Constructor #2
                      //*---------------------------------------------------------------------------*
                      ShaderNode::ShaderNode(const LONG& t_type, const LONG& t_numNodeInputs, const LONG& t_xPos, const LONG& t_yPos, const LONG& t_flags)
                      //*---------------------------------------------------------------------------*
                      {
                      	nodeInputs =	NULL;
                      	previewBitmap =	NULL;
                      	//previewGL	=   NULL;
                      	prev =			NULL;
                      	next =			NULL;
                      	xPos =			t_xPos;
                      	yPos =			t_yPos;
                      	flags =			t_flags;
                      	type =			t_type;
                      	numNodeInputs =	t_numNodeInputs;
                      	acceptCount =	0L;
                      	connections =	0L;
                      }
                      // Destructor
                      //*---------------------------------------------------------------------------*
                      ShaderNode::~ShaderNode()
                      //*---------------------------------------------------------------------------*
                      {
                      	//gDelete(previewGL);
                      	BaseBitmap::Free(previewBitmap);
                      	bDelete(nodeInputs);
                      }
                      // Append node to list
                      //*---------------------------------------------------------------------------*
                      Bool ShaderNode::Append(ShaderNode* previous)
                      //*---------------------------------------------------------------------------*
                      {
                      	if (!previous)		return ErrorException::Throw(GeLoadString(CANERR_MEMORY), "ShaderNode.Append.previous");
                      	prev =				previous;
                      	previous->next =	this;
                      	return TRUE;
                      }
                      // Remove node from list
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::Remove()
                      //*---------------------------------------------------------------------------*
                      {
                      	ShaderNode*	p =	prev;
                      	ShaderNode*	n =	next;
                      	prev =			NULL;
                      	next =			NULL;
                      	if (p)			p->next = n;
                      	if (n)			n->prev = p;
                      }
                      // Get Previous node
                      //*---------------------------------------------------------------------------*
                      ShaderNode* ShaderNode::GetPrev()
                      //*---------------------------------------------------------------------------*
                      {
                      	return prev;
                      }
                      // Get Next node
                      //*---------------------------------------------------------------------------*
                      ShaderNode* ShaderNode::GetNext()
                      //*---------------------------------------------------------------------------*
                      {
                      	return next;
                      }
                      // Initialize ShaderNode
                      //*---------------------------------------------------------------------------*
                      Bool ShaderNode::Init(const LONG& t_xPos, const LONG& t_yPos, const LONG& t_pDim, const LONG& t_flags)
                      //*---------------------------------------------------------------------------*
                      {
                      	if (!previewBitmap)
                      	{
                      		previewBitmap =			BaseBitmap::Alloc();
                      		if (!previewBitmap)		return ErrorException::Throw(GeLoadString(CANERR_MEMORY), "ShaderNode.Init.previewBitmap");
                      		if (previewBitmap->Init(t_pDim, t_pDim, 32L) != IMAGERESULT_OK)
                      			return ErrorException::Throw(GeLoadString(CANERR_MEMORY), "ShaderNode.Init.previewBitmap.Init");
                      		previewBitmap->Clear(255L,255L,255L);
                      	}
                      	/*
                      	if (!previewGL)
                      	{
                      		previewGL =				gNew glload;
                      		if (!previewGL)			return ErrorException::Throw(GeLoadString(CANERR_MEMORY), "ShaderNode.Init.previewGL");
                      		if (!previewGL->Init())	return ErrorException::Throw(GeLoadString(CANERR_GENERAL), "ShaderNode.Init.previewGL.Init");
                      	}
                      	*/
                      	name =						ShaderNodeStrings[type];
                      	xPos =						t_xPos;
                      	yPos =						t_yPos;
                      	flags =						t_flags;
                      	return TRUE;
                      }
                      // Initialize ShaderNode Inputs
                      //*---------------------------------------------------------------------------*
                      Bool ShaderNode::InitInputs(NodeInputDef* nid)
                      //*---------------------------------------------------------------------------*
                      {
                      	// Initialize NodeInputs by ShaderNode type
                      	// - Delete default NodeInput array
                      	bDelete(nodeInputs);
                      	nodeInputs =		NULL;
                      	if (!numNodeInputs)	return ErrorException::Throw(GeLoadString(CANERR_GENERAL), "ShaderNode.InitInputs.numNodeInputs");
                      	// - Allocate NodeInput array
                      	nodeInputs =		bNew NodeInput[numNodeInputs];
                      	if (!nodeInputs)	return ErrorException::Throw(GeLoadString(CANERR_MEMORY), "ShaderNode.InitInputs.nodeInputs");
                      	// - Configure NodeInput array
                      	for (LONG i = 0L; i != numNodeInputs; ++i)
                      	{
                      		nodeInputs[i].Init(nid[i].name, Vector(nid[i].a, nid[i].b, nid[i].c), nid[i].type, nid[i].accept, NULL, String(""));
                      		if (nid[i].accept) ++acceptCount;
                      	}
                      	return TRUE;
                      }
                      // String name
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::SetName(const String& t_name)
                      //*---------------------------------------------------------------------------*
                      {
                      	name = t_name;
                      }
                      //*---------------------------------------------------------------------------*
                      String ShaderNode::GetName()
                      //*---------------------------------------------------------------------------*
                      {
                      	return name;
                      }
                      // LONG xPos, yPos
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::SetPos(const LONG& t_xPos, const LONG& t_yPos)
                      //*---------------------------------------------------------------------------*
                      {
                      	xPos = t_xPos;
                      	yPos = t_yPos;
                      }
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::GetPos(LONG* t_xPos, LONG* t_yPos)
                      //*---------------------------------------------------------------------------*
                      {
                      	*t_xPos = xPos;
                      	*t_yPos = yPos;
                      }
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::Move(const LONG& xDelta, const LONG& yDelta)
                      //*---------------------------------------------------------------------------*
                      {
                      	// Move position by amount
                      	xPos += xDelta;
                      	yPos += yDelta;
                      }
                      // LONG id
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::SetID(const LONG& t_id)
                      //*---------------------------------------------------------------------------*
                      {
                      	id = t_id;
                      }
                      //*---------------------------------------------------------------------------*
                      LONG ShaderNode::GetID()
                      //*---------------------------------------------------------------------------*
                      {
                      	return id;
                      }
                      // Bool showPreview
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::SetShowPreview(const Bool& t_showPreview)
                      //*---------------------------------------------------------------------------*
                      {
                      	if (t_showPreview)	flags |= SHADERNODE_FLAGS_SHOWPREVIEW;
                      	else				flags &= ~SHADERNODE_FLAGS_SHOWPREVIEW;
                      }
                      //*---------------------------------------------------------------------------*
                      Bool ShaderNode::GetShowPreview()
                      //*---------------------------------------------------------------------------*
                      {
                      	return (flags & SHADERNODE_FLAGS_SHOWPREVIEW);
                      }
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::InvertShowPreview()
                      //*---------------------------------------------------------------------------*
                      {
                      	if (flags & SHADERNODE_FLAGS_SHOWPREVIEW)	flags &= ~SHADERNODE_FLAGS_SHOWPREVIEW;
                      	else										flags |= SHADERNODE_FLAGS_SHOWPREVIEW;
                      }
                      // Bool selected
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::SetSelected(const Bool& t_selected)
                      //*---------------------------------------------------------------------------*
                      {
                      	if (t_selected)		flags |= SHADERNODE_FLAGS_SELECTED;
                      	else				flags &= ~SHADERNODE_FLAGS_SELECTED;
                      }
                      //*---------------------------------------------------------------------------*
                      Bool ShaderNode::GetSelected()
                      //*---------------------------------------------------------------------------*
                      {
                      	return (flags & SHADERNODE_FLAGS_SELECTED);
                      }
                      // Bool expanded
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::SetExpanded(const Bool& t_expanded)
                      //*---------------------------------------------------------------------------*
                      {
                      	if (t_expanded)		flags |= SHADERNODE_FLAGS_EXPANDED;
                      	else				flags &= ~SHADERNODE_FLAGS_EXPANDED;
                      }
                      //*---------------------------------------------------------------------------*
                      Bool ShaderNode::GetExpanded()
                      //*---------------------------------------------------------------------------*
                      {
                      	return (flags & SHADERNODE_FLAGS_EXPANDED);
                      }
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::InvertExpanded()
                      //*---------------------------------------------------------------------------*
                      {
                      	if (flags & SHADERNODE_FLAGS_EXPANDED)	flags &= ~SHADERNODE_FLAGS_EXPANDED;
                      	else									flags |= SHADERNODE_FLAGS_EXPANDED;
                      }
                      // LONG type
                      //*---------------------------------------------------------------------------*
                      Bool ShaderNode::IsInstanceOf(const LONG& t_type)
                      //*---------------------------------------------------------------------------*
                      {
                      	return (type == t_type);
                      }
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::SetType(const LONG& t_type)
                      //*---------------------------------------------------------------------------*
                      {
                      	type = t_type;
                      }
                      //*---------------------------------------------------------------------------*
                      LONG ShaderNode::GetType()
                      //*---------------------------------------------------------------------------*
                      {
                      	return type;
                      }
                      // LONG numNodeInputs
                      //*---------------------------------------------------------------------------*
                      LONG ShaderNode::GetNodeCount()
                      //*---------------------------------------------------------------------------*
                      {
                      	return numNodeInputs;
                      }
                      // LONG acceptCount
                      //*---------------------------------------------------------------------------*
                      LONG ShaderNode::GetAcceptCount()
                      //*---------------------------------------------------------------------------*
                      {
                      	return acceptCount;
                      }
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::ClearInputs()
                      //*---------------------------------------------------------------------------*
                      {
                      	if (!nodeInputs)	return;
                      	for (LONG i = 0L; i != numNodeInputs; ++i)
                      	{
                      		nodeInputs[i].SetNode(NULL);
                      	}
                      }
                      // LONG connections
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::SetConnections(const LONG& count)
                      //*---------------------------------------------------------------------------*
                      {
                      	connections = count;
                      }
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::IncConnect()
                      //*---------------------------------------------------------------------------*
                      {
                      	++connections;
                      }
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::DecConnect()
                      //*---------------------------------------------------------------------------*
                      {
                      	if (connections > 0L) --connections;
                      }
                      //*---------------------------------------------------------------------------*
                      LONG ShaderNode::Connected()
                      //*---------------------------------------------------------------------------*
                      {
                      	return connections;
                      }
                      // Bool connecting
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::SetConnecting(const Bool& t_connecting)
                      //*---------------------------------------------------------------------------*
                      {
                      	if (t_connecting)	flags |= SHADERNODE_FLAGS_CONNECTING;
                      	else				flags &= ~SHADERNODE_FLAGS_CONNECTING;
                      }
                      //*---------------------------------------------------------------------------*
                      Bool ShaderNode::IsConnecting()
                      //*---------------------------------------------------------------------------*
                      {
                      	return (flags & SHADERNODE_FLAGS_CONNECTING);
                      }
                      // NodeInput* nodeInputs - retrieve by index
                      //*---------------------------------------------------------------------------*
                      NodeInput* ShaderNode::GetNodeInput(LONG index)
                      //*---------------------------------------------------------------------------*
                      {
                      	if (!nodeInputs)				return NULL;
                      	if (!numNodeInputs)				return NULL;
                      	if (index >= numNodeInputs)	return NULL;
                      	return &nodeInputs[index];
                      }
                      // Read/Write/CopyTo
                      // - Read NodeInput info
                      //*---------------------------------------------------------------------------*
                      Bool ShaderNode::Read(HyperFile* hf, LONG level)
                      //*---------------------------------------------------------------------------*
                      {
                      	if (!hf->ReadString(&name))			return FALSE;
                      	if (!hf->ReadLong(&xPos))			return FALSE;
                      	if (!hf->ReadLong(&yPos))			return FALSE;
                      	if (!hf->ReadLong(&id))				return FALSE;
                      	if (!hf->ReadLong(&flags))			return FALSE;
                      	if (!hf->ReadLong(&type))			return FALSE;
                      	if (!hf->ReadLong(&numNodeInputs))	return FALSE;
                      	if (!hf->ReadLong(&acceptCount))	return FALSE;
                      	if (!hf->ReadLong(&connections))	return FALSE;
                      	if (!nodeInputs)					return TRUE;
                      	for (LONG i = 0L; i != numNodeInputs; ++i)
                      	{
                      		if (!nodeInputs[i].Read(hf, level)) return FALSE;
                      	}
                      	return TRUE;
                      }
                      // - Write NodeInput info
                      //*---------------------------------------------------------------------------*
                      Bool ShaderNode::Write(HyperFile* hf)
                      //*---------------------------------------------------------------------------*
                      {
                      	if (!hf->WriteString(name))			return FALSE;
                      	if (!hf->WriteLong(xPos))			return FALSE;
                      	if (!hf->WriteLong(yPos))			return FALSE;
                      	if (!hf->WriteLong(id))				return FALSE;
                      	if (!hf->WriteLong(flags))			return FALSE;
                      	if (!hf->WriteLong(type))			return FALSE;
                      	if (!hf->WriteLong(numNodeInputs))	return FALSE;
                      	if (!hf->WriteLong(acceptCount))	return FALSE;
                      	if (!hf->WriteLong(connections))	return FALSE;
                      	if (!nodeInputs)					return TRUE;
                      	for (LONG i = 0L; i != numNodeInputs; ++i)
                      	{
                      		if (!nodeInputs[i].Write(hf)) return FALSE;
                      	}
                      	return TRUE;
                      }
                      // - Copy Source NodeInput info to Destination NodeInput
                      //*---------------------------------------------------------------------------*
                      Bool ShaderNode::CopyTo(ShaderNode* dsn, Bool uniqueID)
                      //*---------------------------------------------------------------------------*
                      {
                      	dsn->name =				name;
                      	dsn->xPos =				xPos;
                      	dsn->yPos =				yPos;
                      	if (!uniqueID)			dsn->id = id;
                      	dsn->flags =			flags;
                      	dsn->type =				type;
                      	dsn->numNodeInputs =	numNodeInputs;
                      	dsn->acceptCount =		acceptCount;
                      	dsn->connections =		connections;
                      	if (!nodeInputs)		return TRUE;
                      	for (LONG i = 0L; i != numNodeInputs; ++i)
                      	{
                      		nodeInputs[i].CopyTo(&(dsn->nodeInputs[i]), FALSE);
                      	}
                      	return TRUE;
                      }
                      // - Reestablish NodeInput* node links from id's
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::ReestablishNodeLinks(ShaderNode* firstSNode)
                      //*---------------------------------------------------------------------------*
                      {
                      	if (!nodeInputs)	return;
                      	ShaderNode*	sn =	NULL;
                      	for (LONG i = 0L; i != numNodeInputs; ++i)
                      	{
                      		ni = &nodeInputs[i];
                      		for (sn = firstSNode; sn; sn = (ShaderNode* )sn->GetNext())
                      		{
                      			if (sn->id == ni->GetNodeID())
                      			{
                      				ni->SetNode(sn);
                      				break;
                      			}
                      		}
                      	}
                      }
                      //*---------------------------------------------------------------------------*
                      void ShaderNode::SetPreview(BaseMaterial* chn, Bool fromFile)
                      //*---------------------------------------------------------------------------*
                      {
                      }
                      //*---------------------------------------------------------------------------*
                      Vector ShaderNode::Output(BaseMaterial* chn, ChannelData* cd)
                      //*---------------------------------------------------------------------------*
                      {
                      	return Vector(1.0);
                      }
                      // BaseBitmap *previewBitmap
                      //*---------------------------------------------------------------------------*
                      BaseBitmap* ShaderNode::GetPreview()
                      //*---------------------------------------------------------------------------*
                      {
                      	/*
                      	if (!previewGL)		return NULL;
                      	if (!previewBitmap)	return NULL;
                      	// Create the shader node preview using OpenGL and store in 'previewBitmap'
                      	previewGL->Draw();
                      	// pointers for processing
                      	UCHAR*	redbuff =	previewGL->GetRender();
                      	UCHAR*	greenbuff =	redbuff+65536L;
                      	UCHAR*	bluebuff =	greenbuff+65536L;
                        
                      	// 256x256 pixels
                      	LONG	x;
                      	LONG	r, g, b;
                      	for (LONG y = 255L; y != -1L; --y)
                      	{
                      		for (x = 0L; x != 256L; ++x)
                      		{
                      			r =	*redbuff++;
                      			g =	*greenbuff++;
                      			b =	*bluebuff++;
                      			previewBitmap->SetPixel(x, y, r, g, b);
                      		}
                      	}
                      	*/
                        
                      	return previewBitmap;
                      }
                      
                      1 Reply Last reply Reply Quote 0
                      • H
                        Helper
                        last edited by

                        On 11/01/2015 at 09:38, xxxxxxxx wrote:

                        Thanks a lot Robert.
                        I'll try to make sense of that. But it's lot of code to sift through. Confused

                        That's not your fault though. I know that link lists always requires a ton of code. Which is one reason why I was hoping I could use the existing xpresso node system and just add my own custom nodes to it. Instead of writing the entire thing by hand.
                        But I'm running into a lot of things I can't figure out.

                        -ScottA

                        1 Reply Last reply Reply Quote 0
                        • First post
                          Last post