Преглед на файлове

backup before connections

everything in shaderEditor now finished only thing left to add is the connections.
marauder2k7 преди 1 година
родител
ревизия
6e85b43088

+ 532 - 4
Engine/source/gui/shaderEditor/guiShaderEditor.cpp

@@ -40,37 +40,142 @@ ConsoleDocClass(GuiShaderEditor,
 );
 
 GuiShaderEditor::GuiShaderEditor()
+   : mDragBeginPoint(-1, -1),
+   mViewOffset(0,0),
+   mZoomScale(1.0f),
+   mFullBoxSelection(false),
+   mDragAddSelection(false),
+   mDragMoveUndo(false)
 {
+   VECTOR_SET_ASSOCIATION(mCurrNodes);
+   VECTOR_SET_ASSOCIATION(mSelectedNodes);
+   VECTOR_SET_ASSOCIATION(mDragBeginPoints);
+
+   mActive = true;
+   mMouseDownMode = GuiShaderEditor::Selecting;
+
+   mTrash = NULL;
+   mSelectedSet = NULL;
 }
 
 bool GuiShaderEditor::onWake()
 {
-   return false;
+   if (!Parent::onWake())
+      return false;
+
+   return true;
 }
 
 void GuiShaderEditor::onSleep()
 {
+   Parent::onSleep();
 }
 
 void GuiShaderEditor::initPersistFields()
 {
+   docsURL;
+   addGroup("Selection");
+   addField("fullBoxSelection", TypeBool, Offset(mFullBoxSelection, GuiShaderEditor),
+      "If true, rectangle selection will only select controls fully inside the drag rectangle.");
+   endGroup("Selection");
+   Parent::initPersistFields();
 }
 
 bool GuiShaderEditor::onAdd()
 {
-   return false;
+   if (!Parent::onAdd())
+      return false;
+
+   mTrash = new SimGroup();
+   mSelectedSet = new SimSet();
+
+   if (!mTrash->registerObject())
+      return false;
+   if (!mSelectedSet->registerObject())
+      return false;
+
+   return true;
 }
 
 void GuiShaderEditor::onRemove()
 {
+   mTrash->deleteObject();
+   mSelectedSet->deleteObject();
+
+   mTrash = NULL;
+   mSelectedSet = NULL;
 }
 
 void GuiShaderEditor::onPreRender()
 {
+   setUpdate();
+}
+
+void GuiShaderEditor::renderNodes(Point2I offset, const RectI& updateRect)
+{
+   // Save the current clip rect
+   // so we can restore it at the end of this method.
+   RectI savedClipRect = GFX->getClipRect();
+
+   // offset is the upper-left corner of this control in screen coordinates
+   // updateRect is the intersection rectangle in screen coords of the control
+   // hierarchy.  This can be set as the clip rectangle in most cases.
+   RectI clipRect = updateRect;
+
+   GFXDrawUtil* drawer = GFX->getDrawUtil();
+
+   for (ShaderNode* node : mCurrNodes)
+   {
+      // this is useful for sub node graphs.
+      if (node->isVisible())
+      {
+         Point2I childPos = offset + node->getPosition();
+         RectI childClip(childPos, node->getExtent() + Point2I(1, 1));
+
+         if (childClip.intersect(clipRect))
+         {
+            GFX->setClipRect(childClip);
+            GFX->setStateBlock(mDefaultGuiSB);
+            node->onRender(offset, childClip);
+         }
+
+         if (selectionContains(node))
+         {
+            GFX->setClipRect(clipRect);
+            childClip.inset(1, 1);
+            drawer->drawRect(childClip, ColorI(255, 255, 0, 128));
+         }
+      }
+   }
+
+   // Restore the clip rect to what it was at the start
+   // of this method.
+   GFX->setClipRect(savedClipRect);
 }
 
 void GuiShaderEditor::onRender(Point2I offset, const RectI& updateRect)
 {
+   offset += mViewOffset * mZoomScale;
+
+   GFXDrawUtil* drawer = GFX->getDrawUtil();
+
+   // render our nodes.
+   renderNodes(offset, updateRect);
+
+   // Draw selection rectangle last so it is rendered on top.
+   if (mActive && mMouseDownMode == DragSelecting)
+   {
+      RectI b;
+      getDragRect(b);
+      b.point += offset;
+
+      // Draw outline.
+      drawer->drawRect(b, ColorI(100, 100, 100, 128));
+
+      // Draw fill.
+      b.inset(1, 1);
+      drawer->drawRectFill(b, ColorI(150, 150, 150, 128));
+   }
 }
 
 bool GuiShaderEditor::onKeyDown(const GuiEvent& event)
@@ -80,26 +185,449 @@ bool GuiShaderEditor::onKeyDown(const GuiEvent& event)
 
 void GuiShaderEditor::onMouseDown(const GuiEvent& event)
 {
+   if (!mActive)
+   {
+      Parent::onMouseDown(event);
+      return;
+   }
+
+   setFirstResponder();
+
+   // lock mouse
+   mouseLock();
+
+   // get mouse pos with our view offset and scale.
+   mLastMousePos = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale;
+
+   ShaderNode* node = findHitNode(mLastMousePos);
+
+   if (event.modifier & SI_SHIFT)
+   {
+      startDragRectangle(mLastMousePos);
+      mDragAddSelection = true;
+   }
+   else if (selectionContains(node))
+   {
+      if (event.modifier & SI_MULTISELECT)
+      {
+         removeSelection(node);
+         setMouseMode(Selecting);
+      }
+      else if (event.modifier & SI_PRIMARY_ALT)
+      {
+         startDragClone(mLastMousePos);
+      }
+      else
+      {
+         startDragMove(mLastMousePos);
+      }
+   }
+   else
+   {
+      if (node == NULL)
+      {
+         startDragRectangle(mLastMousePos);
+         mDragAddSelection = false;
+      }
+      else if (event.modifier & SI_PRIMARY_ALT && node != NULL)
+      {
+         // Alt is down.  Start a drag clone.
+         clearSelection();
+         addSelection(node);
+         startDragClone(mLastMousePos);
+      }
+      else if (event.modifier & SI_MULTISELECT)
+      {
+         addSelection(node);
+      }
+      else
+      {
+         // Clicked on node.  Start move.
+         clearSelection();
+         addSelection(node);
+         startDragMove(mLastMousePos);
+      }
+   }
+
 }
 
 void GuiShaderEditor::onMouseUp(const GuiEvent& event)
 {
+   if (!mActive)
+   {
+      Parent::onMouseUp(event);
+      return;
+   }
+
+   ShaderNode* node = findHitNode(mLastMousePos);
+
+   //unlock the mouse
+   mouseUnlock();
+
+   // Reset Drag Axis Alignment Information
+   mDragBeginPoint.set(-1, -1);
+   mDragBeginPoints.clear();
+
+   // get mouse pos with our view offset and scale.
+   mLastMousePos = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale;
+
+   if (mMouseDownMode == DragSelecting)
+   {
+      if (!(event.modifier & SI_MULTISELECT) && !mDragAddSelection)
+         clearSelection();
+
+      RectI rect;
+      getDragRect(rect);
+
+      if (rect.extent.x <= 2 && rect.extent.y <= 2)
+      {
+         addSelectionAtPoint(rect.point);
+      }
+      else
+      {
+         Vector< ShaderNode* > hits;
+         findNodesInRect(rect, hits);
+
+         for (ShaderNode* node : hits)
+         {
+            addSelection(node);
+         }
+      }
+   }
+
+   if (mMouseDownMode == MovingSelection && mDragMoveUndo)
+   {
+
+   }
+
+   //reset the mouse mode
+   setFirstResponder();
+   setMouseMode(Selecting);
 }
 
-void GuiShaderEditor::onMouseMove(const GuiEvent& event)
+void GuiShaderEditor::onMouseDragged(const GuiEvent& event)
 {
+   if (!mActive)
+   {
+      Parent::onMouseDragged(event);
+      return;
+   }
+
+   // get mouse pos with our view offset and scale.
+   Point2I mousePoint = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale;
+
+   if (mMouseDownMode == DragClone)
+   {
+      // If we haven't yet crossed the mouse delta to actually start the
+      // clone, check if we have now.
+
+      S32 delta = mAbs((mousePoint - mDragBeginPoint).len());
+      if (delta >= 4)
+      {
+         cloneSelection();
+         mLastMousePos = mDragBeginPoint;
+         mDragMoveUndo = false;
+
+         setMouseMode(MovingSelection);
+      }
+   }
+
+   if (mMouseDownMode == MovingSelection && mSelectedNodes.size())
+   {
+      Point2I delta = mousePoint - mLastMousePos;
+      RectI selBounds = getSelectionBounds();
+
+      if (delta.x || delta.y)
+         moveSelection(delta, mDragMoveUndo);
+
+      mLastMousePos += delta;
+   }
+   else
+      mLastMousePos = mousePoint;
 }
 
 void GuiShaderEditor::onMiddleMouseDown(const GuiEvent& event)
 {
+   if (!mActive)
+   {
+      Parent::onMiddleMouseDown(event);
+      return;
+   }
+
+   setFirstResponder();
+
+   // lock mouse
+   mouseLock();
+
+   // get mouse pos with our view offset and scale.
+   mLastMousePos = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale;
+
+   setMouseMode(DragPanning);
+
+}
+
+void GuiShaderEditor::onMiddleMouseUp(const GuiEvent& event)
+{
+   if (!mActive)
+   {
+      Parent::onMiddleMouseUp(event);
+      return;
+   }
+
+   //unlock the mouse
+   mouseUnlock();
+
+   // Reset Drag Axis Alignment Information
+   mDragBeginPoint.set(-1, -1);
+   mDragBeginPoints.clear();
+
+   // get mouse pos with our view offset and scale.
+   mLastMousePos = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale;
+
+   setFirstResponder();
+   setMouseMode(Selecting);
+}
+
+void GuiShaderEditor::onMiddleMouseDragged(const GuiEvent& event)
+{
+   if (!mActive)
+   {
+      Parent::onMiddleMouseDragged(event);
+      return;
+   }
+
+   // get mouse pos with our view offset and scale.
+   Point2I mousePoint = globalToLocalCoord(event.mousePoint) + mViewOffset * mZoomScale;
+
+   if (mMouseDownMode == DragPanning)
+   {
+      Point2I delta = mousePoint - mLastMousePos;
+      RectI selBounds = getSelectionBounds();
+
+      // invert it
+      if (delta.x || delta.y)
+         mViewOffset += -delta;
+
+      mLastMousePos += delta;
+   }
+   else
+      mLastMousePos = mousePoint;
 }
 
 bool GuiShaderEditor::onMouseWheelUp(const GuiEvent& event)
 {
-   return false;
+   if (!mActive || !mAwake || !mVisible)
+      return Parent::onMouseWheelUp(event);
+
+   mZoomScale *= 1.1;
+
+   return true;
 }
 
 bool GuiShaderEditor::onMouseWheelDown(const GuiEvent& event)
 {
+   if (!mActive || !mAwake || !mVisible)
+      return Parent::onMouseWheelDown(event);
+
+   mZoomScale *= 0.9;
+
+   return true;
+}
+
+RectI GuiShaderEditor::getSelectionBounds()
+{
+
+   Vector<ShaderNode*>::const_iterator i = mSelectedNodes.begin();
+
+   Point2I minPos = (*i)->localToGlobalCoord(Point2I(0, 0)) + mViewOffset * mZoomScale;
+   Point2I maxPos = minPos;
+
+   for (; i != mSelectedNodes.end(); i++)
+   {
+      Point2I iPos = (**i).localToGlobalCoord(Point2I(0, 0)) + mViewOffset * mZoomScale;
+
+      minPos.x = getMin(iPos.x, minPos.x);
+      minPos.y = getMin(iPos.y, minPos.y);
+
+      Point2I iExt = (**i).getExtent();
+
+      iPos.x += iExt.x;
+      iPos.y += iExt.y;
+
+      maxPos.x = getMax(iPos.x, maxPos.x);
+      maxPos.y = getMax(iPos.y, maxPos.y);
+   }
+
+   minPos = globalToLocalCoord(minPos) + mViewOffset * mZoomScale;
+   maxPos = globalToLocalCoord(maxPos) + mViewOffset * mZoomScale;
+
+   return RectI(minPos.x, minPos.y, (maxPos.x - minPos.x), (maxPos.y - minPos.y));
+}
+
+void GuiShaderEditor::deleteSelection()
+{
+   for (ShaderNode* node : mSelectedNodes)
+   {
+      mTrash->addObject(node);
+   }
+
+   clearSelection();
+}
+
+void GuiShaderEditor::moveSelection(const Point2I& delta, bool callback)
+{
+   for (ShaderNode* node : mSelectedNodes)
+   {
+      node->setPosition(node->getPosition() + delta);
+   }
+}
+
+void GuiShaderEditor::clearSelection()
+{
+   mSelectedNodes.clear();
+}
+
+void GuiShaderEditor::cloneSelection()
+{
+   Vector<ShaderNode*> newSelection;
+
+   for (ShaderNode* node : mSelectedNodes)
+   {
+      ShaderNode* clone = dynamic_cast<ShaderNode*>(node->deepClone());
+      if (clone)
+         newSelection.push_back(clone);
+   }
+
+   clearSelection();
+
+   for (ShaderNode* cloneNode : newSelection)
+   {
+      addSelection(cloneNode);
+   }
+}
+
+void GuiShaderEditor::addSelectionAtPoint(const Point2I& pos)
+{
+   // turn hit off on already selected nodes.
+   canHitSelectedNodes(false);
+
+   ShaderNode* node = findHitNode(pos);
+
+   // reset hit status.
+   canHitSelectedNodes();
+
+   if (node)
+      addSelection(node);
+}
+
+void GuiShaderEditor::addSelection(ShaderNode* inNode)
+{
+   if (inNode != NULL && !selectionContains(inNode))
+   {
+      mSelectedNodes.push_back(inNode);
+   }
+}
+
+bool GuiShaderEditor::selectionContains(ShaderNode* inNode)
+{
+   for (ShaderNode* node : mSelectedNodes)
+   {
+      if (node == inNode)
+         return true;
+   }
+
    return false;
 }
+
+void GuiShaderEditor::removeSelection(ShaderNode* inNode)
+{
+   if (selectionContains(inNode))
+   {
+      Vector< ShaderNode* >::iterator i = T3D::find(mSelectedNodes.begin(), mSelectedNodes.end(), inNode);
+      if (i != mSelectedNodes.end())
+         mSelectedNodes.erase(i);
+   }
+}
+
+void GuiShaderEditor::canHitSelectedNodes(bool state)
+{
+   for (ShaderNode* node : mSelectedNodes)
+      node->setCanHit(state);
+}
+
+//-----------------------------------------------------------------------------
+// Input handling
+//-----------------------------------------------------------------------------
+
+ShaderNode* GuiShaderEditor::findHitNode(const Point2I& pt)
+{
+   for (ShaderNode* node : mCurrNodes)
+   {
+      if (node->pointInControl(pt))
+      {
+         return node;
+      }
+   }
+
+   return nullptr;
+}
+
+void GuiShaderEditor::findNodesInRect(const RectI& rect, Vector<ShaderNode*>& outResult)
+{
+   canHitSelectedNodes(false);
+   for (ShaderNode* node : mCurrNodes)
+   {
+      if (node->getBounds().overlaps(rect))
+      {
+         outResult.push_back(node);
+      }
+   }
+
+   canHitSelectedNodes();
+}
+
+void GuiShaderEditor::getDragRect(RectI& box)
+{
+   box.point.x = getMin(mLastMousePos.x, mSelectionAnchor.x);
+   box.extent.x = getMax(mLastMousePos.x, mSelectionAnchor.x) - box.point.x + 1;
+   box.point.y = getMin(mLastMousePos.y, mSelectionAnchor.y);
+   box.extent.y = getMax(mLastMousePos.y, mSelectionAnchor.y) - box.point.y + 1;
+}
+
+void GuiShaderEditor::startDragMove(const Point2I& startPoint)
+{
+   mDragMoveUndo = true;
+
+   mDragBeginPoint = startPoint;
+
+   mDragBeginPoints.reserve(mSelectedNodes.size());
+
+   for (ShaderNode* node : mSelectedNodes)
+   {
+      mDragBeginPoints.push_back(node->getPosition());
+   }
+
+   setMouseMode(MovingSelection);
+
+}
+
+void GuiShaderEditor::startDragRectangle(const Point2I& startPoint)
+{
+   mSelectionAnchor = startPoint;
+   setMouseMode(DragSelecting);
+}
+
+void GuiShaderEditor::startDragClone(const Point2I& startPoint)
+{
+   mDragBeginPoint = startPoint;
+   setMouseMode(DragClone);
+}
+
+void GuiShaderEditor::setMouseMode(mouseModes mode)
+{
+   if (mMouseDownMode != mode)
+   {
+      mMouseDownMode = mode;
+   }
+}
+

+ 31 - 2
Engine/source/gui/shaderEditor/guiShaderEditor.h

@@ -43,7 +43,7 @@ public:
 
    typedef GuiControl Parent;
 
-   enum mouseModes { Selecting, MovingSelection, DragConnection, DragSelecting, DragClone };
+   enum mouseModes { Selecting, MovingSelection, DragPanning, DragConnection, DragSelecting, DragClone };
 
 protected:
 
@@ -56,6 +56,9 @@ protected:
    SimGroup* mTrash;
    SimSet* mSelectedSet;
 
+   // view controls
+   Point2I mViewOffset;
+   F32 mZoomScale;
    // mouse interaction
    mouseModes mMouseDownMode;
    Point2I mLastMousePos;
@@ -65,8 +68,21 @@ protected:
    Vector<Point2I> mDragBeginPoints;
    bool mDragAddSelection;
    bool mDragMoveUndo;
+   bool mFullBoxSelection;
    ShaderNodeVector mSelectedNodes;
 
+   void renderNodes(Point2I offset, const RectI& updateRect);
+
+   // functions for handling mouse events.
+   ShaderNode* findHitNode(const Point2I& pt);
+   void findNodesInRect(const RectI& rect, Vector<ShaderNode*>& outResult);
+
+   void getDragRect(RectI& box);
+   void startDragMove(const Point2I& startPoint);
+   void startDragRectangle(const Point2I& startPoint);
+   void startDragClone(const Point2I& startPoint);
+   void setMouseMode(mouseModes mode);
+
 public:
    GuiShaderEditor();
 
@@ -87,10 +103,23 @@ public:
    virtual bool onKeyDown(const GuiEvent& event) override;
    virtual void onMouseDown(const GuiEvent& event) override;
    virtual void onMouseUp(const GuiEvent& event) override;
-   virtual void onMouseMove(const GuiEvent& event) override;
+   virtual void onMouseDragged(const GuiEvent& event) override;
    virtual void onMiddleMouseDown(const GuiEvent& event) override;
+   virtual void onMiddleMouseUp(const GuiEvent& event) override;
+   virtual void onMiddleMouseDragged(const GuiEvent& event) override;
    virtual bool onMouseWheelUp(const GuiEvent& event) override;
    virtual bool onMouseWheelDown(const GuiEvent& event) override;
+
+   RectI getSelectionBounds();
+   void deleteSelection();
+   void moveSelection(const Point2I& delta, bool callback = true);
+   void clearSelection();
+   void cloneSelection();
+   void addSelectionAtPoint(const Point2I& pos);
+   void addSelection(ShaderNode* inNode);
+   bool selectionContains(ShaderNode* inNode);
+   void removeSelection(ShaderNode* inNode);
+   void canHitSelectedNodes(bool state = true);
 };
 
 #endif _GUISHADEREDITOR_H_

+ 11 - 2
Engine/source/gui/shaderEditor/nodes/shaderNode.cpp

@@ -39,20 +39,29 @@ ShaderNode::ShaderNode()
 
 bool ShaderNode::onWake()
 {
-   return false;
+   if (!Parent::onWake())
+      return false;
+
+   return true;
 }
 
 void ShaderNode::onSleep()
 {
+   Parent::onSleep();
 }
 
 void ShaderNode::initPersistFields()
 {
+   docsURL;
+   Parent::initPersistFields();
 }
 
 bool ShaderNode::onAdd()
 {
-   return false;
+   if (!Parent::onAdd())
+      return false;
+
+   return true;
 }
 
 void ShaderNode::onRemove()

+ 3 - 1
Engine/source/gui/shaderEditor/nodes/shaderNode.h

@@ -38,11 +38,13 @@ enum class NodeTypes
    Output,
    TextureSampler,
    MathOperation,
-   Procedural
+   Procedural,
+   Generator
 };
 
 enum class DataDimensions
 {
+   Dynamic, // can be any dimension, usually defined by what was connected to it.
    Scalar,
    Vector2,
    Vector3,