Files
LifeProject/LifeMaterialEditor/GUIShaderNode.cpp
T
2025-05-13 02:46:21 +03:00

318 lines
7.6 KiB
C++

#include "GUIShaderNode.h"
GUIShaderNode::GUIShaderNode(IShaderGraphNode* src)
:resizing(false), moving(false), GraphicsNode(src)
{
skip_mouse = true;
size_min = Vec2i(100, 50);
size_max = Vec2i(250, 250);
header = new GUIPlane();
header->SetPosition(Vec2i(0, 0));
header->SetWidth(120);
header->SetHeight(25);
header->SetBackColor(Vec4f(0.16f,0.16f,0.16f,1));
header->SetBorderColor(Vec4f(0.016f,0.016f,0.016f,1));
body = new GUIPlane();
body->SetPosition(Vec2i(0, 25));
body->SetWidth(120);
body->SetHeight(120);
body->SetBackColor(Vec4f(0.25f,0.0f,0.0f,1));
body->SetBorderColor(Vec4f(0.016f,0.016f,0.016f,1));
display = new GUIPicture();
body->AddChild(display);
display->SetPosition(Vec2i(2,2));
back = new GUIPlane();
back->SetPosition(Vec2i(0, 0));
back->SetWidth(width);
back->SetHeight(height);
back->SetBackColor(Vec4f(0.9f,0.25f,0.25f,1));
back->SetBorderColor(Vec4f(0.9f,0.016f,0.016f,1));
mover = new GUIPlane();
mover->SetPosition(Vec2i(115, 140));
mover->SetWidth(10);
mover->SetHeight(10);
mover->SetBackColor(Vec4f(0.75f,0.75f,0.75f,0.5f));
mover->SetBorderColor(Vec4f(0.016f,0.016f,0.016f,1));
mover->cursor = STR("Size_d1");
header_text = new GUIText();
header->AddChild(header_text);
header_text->SetDock(Video::DOCK_FILL);
header_text->SetHAlign(HA_CENTER);
header_text->SetVAlign(VA_CENTER);
header_text->SetText("Invert (1-x)");
header_text->SetBackColor(Vec4f(0.0f,0.0f,0.0f,0.0f));
header_text->SetForeColor(Vec4f(0.8f,0.8f,0.8f,1.0f));
header_text->mouseEnabled = false;
mover->Event_MouseDown += NewDelegate(this, &GUIShaderNode::OnBeginResize);
mover->Event_MouseUp += NewDelegate(this, &GUIShaderNode::OnEndResize);
mover->Event_MouseMove += NewDelegate(this, &GUIShaderNode::OnDoResize);
header->Event_MouseDown += NewDelegate(this, &GUIShaderNode::OnHeaderMouseDown);
header->Event_MouseUp += NewDelegate(this, &GUIShaderNode::OnHeaderMouseUp);
header->Event_MouseMove += NewDelegate(this, &GUIShaderNode::OnHeaderMouseMove);
header->Event_MouseClick += NewDelegate(this, &GUIShaderNode::OnHeaderMouseClick);
menu = new GUIMenu(true);
menu->AddItem("Delete node", false);
//AddChild(back);
AddChild(body);
AddChild(mover);
AddChild(header);
}
void GUIShaderNode::OnHeaderRightClick(GUIWindow* wnd, int param)
{
printf("Right click on header!\n");
}
void GUIShaderNode::OnHeaderMouseClick(GUIWindow* wnd, int param)
{
Event_HeaderClick.Invoke(this, param);
}
void GUIShaderNode::SetDisplayImage(texture_ptr tex)
{
displayImage = tex;
display->SetPicture(CImage::FromTexture(displayImage.ptr()));
}
void GUIShaderNode::SetCaption(const String& text)
{
header_text->SetText(text);
}
const String& GUIShaderNode::GetCaption()
{
return header_text->GetText();
}
GUIShaderNode::~GUIShaderNode()
{
}
void GUIShaderNode::OnBeginResize(GUIWindow* wnd, int param)
{
resizing = true;
FindOverlay()->GrabMouse(wnd);
size_pos = body->GetRectangleAbs().GetMax() - FindOverlay()->cursorPos;
}
void GUIShaderNode::OnDoResize(GUIWindow* wnd, int param)
{
if(resizing)
{
Vec2i newPos = FindOverlay()->cursorPos + size_pos;
Vec2i diff = newPos - body->GetRectangleAbs().GetMin();
if(diff.X < size_min.X)
diff.X = size_min.X;
if(diff.Y < size_min.Y)
diff.Y = size_min.Y;
if(diff.X > size_max.X)
diff.X = size_max.X;
if(diff.Y > size_max.Y)
diff.Y = size_max.Y;
body->SetWidth(diff.X);
body->SetHeight(diff.Y);
header->SetWidth(diff.X);
display->SetWidth(body->GetClientRectangle().width - 4);
display->SetHeight(body->GetClientRectangle().height - 4);
Invalidate();
}
}
void GUIShaderNode::OnEndResize(GUIWindow* wnd, int param)
{
resizing = false;
FindOverlay()->ReleaseMouse();
}
void GUIShaderNode::OnHeaderMouseDown(GUIWindow* wnd, int param)
{
if(param == KEY_MOUSE_LEFT)
{
OnSelect();
moving = true;
FindOverlay()->GrabMouse(wnd);
size_pos = this->GetRectangleAbs().GetMin() - FindOverlay()->cursorPos;
}
}
void GUIShaderNode::OnHeaderMouseMove(GUIWindow* wnd, int param)
{
if(moving)
{
Vec2i new_pos = parent->CursorToLocal(FindOverlay()->cursorPos + size_pos);
this->SetPosition(new_pos);
Invalidate();
}
}
void GUIShaderNode::OnHeaderMouseUp(GUIWindow* wnd, int param)
{
if(param == KEY_MOUSE_LEFT)
{
FindOverlay()->ReleaseMouse();
moving = false;
}
}
void GUIShaderNode::ProcessLink(GUIShaderNodeIO* my, GUIShaderNodeIO* other)
{
if(my->Owner != other->Owner)
{
Event_Attach.Invoke(my, other);
}
}
void GUIShaderNode::FormatInputs()
{
int cnt = inputs.size();
int spacing = 5;
if(!cnt) return;
int totalSize = spacing * (cnt - 1) + inputs[0]->GetHeight() * cnt;
int step = totalSize / cnt;
int h = body->GetHeight();
int start = (h - totalSize) / 2 + body->GetPosition().Y;
for(int i = 0; i < cnt; i++)
{
Vec2i pos = inputs[i]->GetPosition();
int newX = body->GetRectangle().GetMaxX();
if(pos.X != newX)
Invalidate();
pos.X = newX;
pos.Y = start + (step * i);
inputs[i]->SetPosition(pos);
}
}
void GUIShaderNode::FormatOutputs()
{
int cnt = outputs.size();
int spacing = 5;
if(!cnt) return;
int totalSize = spacing * (cnt - 1) + outputs[0]->GetHeight() * cnt;
int step = totalSize / cnt;
int h = body->GetHeight();
int start = (h - totalSize) / 2 + body->GetPosition().Y;
for(int i = 0; i < cnt; i++)
{
Vec2i pos = outputs[i]->GetPosition();
int newX = body->GetPosition().X - outputs[i]->GetWidth();
if(pos.X != newX)
Invalidate();
pos.X = newX;
pos.Y = start + (step * i);
outputs[i]->SetPosition(pos);
}
}
void GUIShaderNode::AddInput(GUIShaderNodeIO* node)
{
node->SetMode(true);
node->Event_Link += NewDelegate(this, &GUIShaderNode::ProcessLink);
node->Event_Resize += NewDelegate(this, &GUIShaderNode::OnIOResize);
node->id = inputs.size();
inputs.push_back(node);
node->Owner = this;
AddChild(node);
FormatInputs();
}
void GUIShaderNode::OnIOResize(GUIWindow* wnd)
{
this->Invalidate();
}
void GUIShaderNode::AddOutput(GUIShaderNodeIO* node)
{
node->SetMode(false);
node->Event_Link += NewDelegate(this, &GUIShaderNode::ProcessLink);
node->Event_Resize += NewDelegate(this, &GUIShaderNode::OnIOResize);
AddChild(node);
node->Owner = this;
node->id = outputs.size();
outputs.push_back(node);
FormatOutputs();
}
size_t GUIShaderNode::GetInputCount()
{
return inputs.size();
}
size_t GUIShaderNode::GetOutputCount()
{
return outputs.size();
}
GUIShaderNodeIO* GUIShaderNode::GetInput(int id)
{
return inputs[id];
}
GUIShaderNodeIO* GUIShaderNode::GetOutput(int id)
{
return outputs[id];
}
void GUIShaderNode::OnSelect()
{
Event_Select.Invoke(this);
}
void GUIShaderNode::RenderSelf()
{
if(invalid)
{
LifeMath::Rect2i tr = childs[0]->GetRectangle();
//find all childs bounding rectangle
for(WindowList::iterator it = childs.begin(); it!= childs.end(); ++it)
{
GUIWindow* w = (*it);
tr.Merge(w->GetRectangle());
}
int new_width = tr.width;
int new_height = tr.height;
if(this->width != new_width)
this->SetWidth(new_width);
if(this->height != new_height)
this->SetHeight(new_height);
mover->SetPosition(body->GetRectangle().GetMax() - Vec2i(5,5));
//need to move all childs
if(tr.x !=0 || tr.y !=0)
{
for(WindowList::iterator it = childs.begin(); it!= childs.end(); ++it)
{
GUIWindow* w = (*it);
Vec2i pp = w->GetPosition();
w->SetPosition(Vec2i(pp.X - tr.x, pp.Y - tr.y));
}
}
FormatInputs();
FormatOutputs();
invalid = false;
if(parent)
parent->Invalidate();
}
}
void GUIShaderNode::Update(float dt)
{
}
void GUIShaderNode::SetBackColor(const Vec4f& color)
{
}
bool GUIShaderNode::ProcessMessage(GUIMessageType mt, GUIMessageParam mp, IMessageArgs* args)
{
return false;
}