diff options
21 files changed, 2315 insertions, 43 deletions
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp index f4a6de0e96..9d920724e1 100644 --- a/core/os/input_event.cpp +++ b/core/os/input_event.cpp @@ -39,6 +39,8 @@ bool InputEvent::operator==(const InputEvent &p_event) const { } switch(type) { + case NONE: + return true; case KEY: return key.unicode == p_event.key.unicode && key.scancode == p_event.key.scancode @@ -77,6 +79,8 @@ bool InputEvent::operator==(const InputEvent &p_event) const { case ACTION: return action.action == p_event.action.action && action.pressed == p_event.action.pressed; + default: + ERR_PRINT("No logic to compare InputEvents of this type, this shouldn't happen."); } return false; diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 5337b6ba04..e7e71e8251 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -54,10 +54,10 @@ struct _VariantCall { int arg_count; Vector<Variant> default_args; Vector<Variant::Type> arg_types; - -#ifdef DEBUG_ENABLED Vector<StringName> arg_names; Variant::Type return_type; + +#ifdef DEBUG_ENABLED bool returns; #endif VariantFunc func; diff --git a/main/input_default.cpp b/main/input_default.cpp index ea08bfc2ef..d84b0b0f58 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -559,12 +559,18 @@ static const char *s_ControllerMappings [] = #ifdef WINDOWS_ENABLED "00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", "00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", + "02200090000000000000504944564944,8Bitdo NES30 PRO USB,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "0d0f4900000000000000504944564944,Hatsune Miku Sho Controller,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", + "0d0f6e00000000000000504944564944,HORIPAD 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", "10080100000000000000504944564944,PS1 USB,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,", "10080300000000000000504944564944,PS2 USB,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5,", + "10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,y:b3,x:b4,start:b11,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,", + "20380900000000000000504944564944,8Bitdo NES30 PRO Wireless,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,", "25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,", "2509e803000000000000504944564944,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", "28040140000000000000504944564944,GamePad Pro USB,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,", + "300f1001000000000000504944564944,Saitek P480 Rumble Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,", + "341a0108000000000000504944564944,EXEQ RF USB Gamepad 8206,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,leftstick:b8,rightstick:b7,back:b8,start:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", "36280100000000000000504944564944,OUYA Controller,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13,", "49190204000000000000504944564944,Ipega PG-9023,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9", @@ -574,6 +580,7 @@ static const char *s_ControllerMappings [] = "4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,", "4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "4f0423b3000000000000504944564944,Dual Trigger 3-in-1,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7", + "63252305000000000000504944564944,USB Vibration Joystick (BM),x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", "6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", @@ -589,8 +596,10 @@ static const char *s_ControllerMappings [] = "8f0e1200000000000000504944564944,Acme,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", "9000318000000000000504944564944,Mayflash Wiimote PC Adapter,a:b2,b:h0.4,x:b0,y:b1,back:b4,start:b5,guide:b11,leftshoulder:b6,rightshoulder:b3,leftx:a0,lefty:a1,", "a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,", + "c0111352000000000000504944564944,Battalife Joystick,x:b4,a:b6,b:b7,y:b5,back:b2,start:b3,leftshoulder:b0,rightshoulder:b1,leftx:a0,lefty:a1,", "c911f055000000000000504944564944,GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", "d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", + "ff113133000000000000504944564944,Gembird JPD-DualForce,a:b2,b:b3,x:b0,y:b1,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,leftstick:b10,rightstick:b11,", "ff113133000000000000504944564944,SVEN X-PAD,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9,", "ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", "__XINPUT_DEVICE__,XInput Gamepad,a:b12,b:b13,x:b14,y:b15,start:b4,back:b5,leftstick:b6,rightstick:b7,leftshoulder:b8,rightshoulder:b9,dpup:b0,dpdown:b1,dpleft:b2,dpright:b3,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,", @@ -599,21 +608,30 @@ static const char *s_ControllerMappings [] = #ifdef OSX_ENABLED "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", "050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,y:b9,x:b10,start:b6,guide:b8,back:b7,dpup:b2,dpleft:b0,dpdown:b3,dpright:b1,leftx:a0,lefty:a1,lefttrigger:b12,righttrigger:,leftshoulder:b11,", + "050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,x:b18,y:b17,back:b7,guide:b8,start:b6,leftstick:b23,rightstick:b24,leftshoulder:b19,rightshoulder:b20,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b21,righttrigger:b22,", "0d0f0000000000004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", + "0d0f0000000000006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:a4,", + "10280000000000000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", + "2509000000000000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", + "351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", "4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", "4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,", "4f0400000000000015b3000000000000,Thrustmaster Dual Analog 3.2,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,", + "5e04000000000000dd02000000000000,Xbox One Wired Controller,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */ "6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", "6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* This includes F710 in DInput mode and the "Logitech Cordless RumblePad 2", at the very least. */ "6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,", + "79000000000000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,x:b0,y:b12,back:b32,start:b36,leftstick:b40,rightstick:b44,leftshoulder:b16,rightshoulder:b20,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a4,rightx:a8,righty:a12,lefttrigger:b24,righttrigger:b28,", "79000000000000000600000000000000,G-Shark GP-702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b6,righttrigger:b7,", "83050000000000006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,", "891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,", "8f0e0000000000000300000000000000,Piranha xtreme,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", - "AD1B00000000000001F9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,", + "ad1b00000000000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,", + "b4040000000000000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,x:b3,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", + "d814000000000000cecf000000000000,MC Cthulhu,leftx:,lefty:,rightx:,righty:,lefttrigger:b6,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,righttrigger:b7,", #endif #if X11_ENABLED @@ -644,6 +662,7 @@ static const char *s_ControllerMappings [] = "030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", + "030000005e0400008e02000062230000,Microsoft X-Box 360 pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,", "030000005e040000d102000001010000,Microsoft X-Box One pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "030000005e040000dd02000003020000,Microsoft X-Box One pad v2,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", @@ -657,6 +676,7 @@ static const char *s_ControllerMappings [] = "030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,x:b0,a:b2,b:b3,y:b1,back:b10,guide:b12,start:b11,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,", + "030000006f0e00000103000000020000,Logic3 Controller,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "030000006f0e00001304000000010000,Generic X-Box pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,", "030000006f0e00001f01000000010000,Generic X-Box pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", @@ -671,19 +691,26 @@ static const char *s_ControllerMappings [] = "030000008916000001fd000024010000,Razer Onza Classic Edition,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", "030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,", + "03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,y:b1,x:b0,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b6,righttrigger:b7,", "03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,", "03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,", "03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,", + "03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,", "03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,", "03000000c9110000f055000011010000,HJC Game GAMEPAD,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b4,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", + "03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,", + "03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,leftx:a0,lefty:a1,", "03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "03000000fd0500002a26000000010000,3dfx InterAct HammerHead FX,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b5,rightshoulder:b7,rightx:a2,start:b11,righty:a3,dpleft:h0.8,lefttrigger:b8,x:b0,dpup:h0.1,back:b10,leftstick:b2,leftshoulder:b6,y:b1,a:b3,dpright:h0.2,righttrigger:b9,b:b4,", "03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", + "05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,y:b3,x:b2,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", + "05000000102800000900000000010000,8Bitdo SFC30 GamePad,x:b4,a:b1,b:b0,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,", "05000000362800000100000002010000,OUYA Game Controller,leftx:a0,lefty:a1,dpdown:b9,rightstick:b7,rightshoulder:b5,rightx:a3,start:b16,righty:a4,dpleft:b10,lefttrigger:b12,x:b1,dpup:b8,back:b14,leftstick:b6,leftshoulder:b4,y:b2,a:b0,dpright:b11,righttrigger:b13,b:b3,", "05000000362800000100000003010000,OUYA Game Controller,leftx:a0,lefty:a1,dpdown:b9,rightstick:b7,rightshoulder:b5,rightx:a3,start:b16,righty:a4,dpleft:b10,lefttrigger:b12,x:b1,dpup:b8,back:b14,leftstick:b6,leftshoulder:b4,y:b2,a:b0,dpright:b11,righttrigger:b13,b:b3,", "05000000362800000100000004010000,OUYA Game Controller,leftx:a0,lefty:a1,dpdown:b9,rightstick:b7,rightshoulder:b5,rightx:a3,start:b16,righty:a4,dpleft:b10,lefttrigger:b12,x:b1,dpup:b8,back:b14,leftstick:b6,leftshoulder:b4,y:b2,a:b0,dpright:b11,righttrigger:b13,b:b3,", + "05000000380700006652000025010000,Mad Catz C.T.R.L.R,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", "050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,", "050000004c050000c405000000010000,PS4 Controller (Bluetooth),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp index 0e97107660..ad54149b51 100644 --- a/modules/visual_script/register_types.cpp +++ b/modules/visual_script/register_types.cpp @@ -36,6 +36,7 @@ #include "visual_script_builtin_funcs.h" #include "visual_script_flow_control.h" #include "visual_script_yield_nodes.h" +#include "visual_script_expression.h" VisualScriptLanguage *visual_script_language=NULL; @@ -98,11 +99,14 @@ void register_visual_script_types() { ObjectTypeDB::register_type<VisualScriptBuiltinFunc>(); + ObjectTypeDB::register_type<VisualScriptExpression>(); + register_visual_script_nodes(); register_visual_script_func_nodes(); register_visual_script_builtin_func_node(); register_visual_script_flow_control_nodes(); register_visual_script_yield_nodes(); + register_visual_script_expression_node(); #ifdef TOOLS_ENABLED VisualScriptEditor::register_editor(); diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index aa09e7f005..4de593760d 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -3,7 +3,7 @@ #include "scene/main/node.h" #include "os/os.h" #include "globals.h" -#define SCRIPT_VARIABLES_PREFIX "script_variables/" + //used by editor, this is not really saved @@ -574,6 +574,23 @@ bool VisualScript::is_input_value_port_connected(const StringName& p_func,int p_ return false; } +bool VisualScript::get_input_value_port_connection_source(const StringName& p_func,int p_node,int p_port,int *r_node,int *r_port) const { + + ERR_FAIL_COND_V(!functions.has(p_func),false); + const Function &func = functions[p_func]; + + for (const Set<DataConnection>::Element *E=func.data_connections.front();E;E=E->next()) { + if (E->get().to_node==p_node && E->get().to_port==p_port) { + *r_node=E->get().from_node; + *r_port=E->get().from_port; + return true; + } + } + + return false; + +} + void VisualScript::get_data_connection_list(const StringName& p_func,List<DataConnection> *r_connection) const { ERR_FAIL_COND(!functions.has(p_func)); @@ -598,8 +615,6 @@ void VisualScript::add_variable(const StringName& p_name,const Variant& p_defaul v._export=p_export; variables[p_name]=v; - script_variable_remap[SCRIPT_VARIABLES_PREFIX+String(p_name)]=p_name; - #ifdef TOOLS_ENABLED _update_placeholders(); @@ -616,7 +631,6 @@ void VisualScript::remove_variable(const StringName& p_name) { ERR_FAIL_COND(!variables.has(p_name)); variables.erase(p_name); - script_variable_remap.erase(SCRIPT_VARIABLES_PREFIX+String(p_name)); #ifdef TOOLS_ENABLED _update_placeholders(); @@ -911,7 +925,7 @@ void VisualScript::_update_placeholders() { continue; PropertyInfo p = E->get().info; - p.name=SCRIPT_VARIABLES_PREFIX+String(E->key()); + p.name=String(E->key()); pinfo.push_back(p); values[p.name]=E->get().default_value; } @@ -947,7 +961,7 @@ ScriptInstance* VisualScript::instance_create(Object *p_this) { continue; PropertyInfo p = E->get().info; - p.name=SCRIPT_VARIABLES_PREFIX+String(E->key()); + p.name=String(E->key()); pinfo.push_back(p); values[p.name]=E->get().default_value; } @@ -1045,10 +1059,10 @@ void VisualScript::get_script_signal_list(List<MethodInfo> *r_signals) const { bool VisualScript::get_property_default_value(const StringName& p_property,Variant& r_value) const { - if (!script_variable_remap.has(p_property)) + if (!variables.has(p_property)) return false; - r_value=variables[ script_variable_remap[p_property] ].default_value; + r_value=variables[ p_property ].default_value; return true; } void VisualScript::get_script_method_list(List<MethodInfo> *p_list) const { @@ -1385,12 +1399,10 @@ VisualScript::~VisualScript() { bool VisualScriptInstance::set(const StringName& p_name, const Variant& p_value) { - const Map<StringName,StringName>::Element *remap = script->script_variable_remap.find(p_name); - if (!remap) - return false; - Map<StringName,Variant>::Element *E=variables.find(remap->get()); - ERR_FAIL_COND_V(!E,false); + Map<StringName,Variant>::Element *E=variables.find(p_name); + if (!E) + return false; E->get()=p_value; @@ -1400,13 +1412,10 @@ bool VisualScriptInstance::set(const StringName& p_name, const Variant& p_value) bool VisualScriptInstance::get(const StringName& p_name, Variant &r_ret) const { - const Map<StringName,StringName>::Element *remap = script->script_variable_remap.find(p_name); - if (!remap) + const Map<StringName,Variant>::Element *E=variables.find(p_name); + if (!E) return false; - const Map<StringName,Variant>::Element *E=variables.find(remap->get()); - ERR_FAIL_COND_V(!E,false); - return E->get(); } void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const{ @@ -1416,21 +1425,15 @@ void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) c if (!E->get()._export) continue; PropertyInfo p = E->get().info; - p.name=SCRIPT_VARIABLES_PREFIX+String(E->key()); + p.name=String(E->key()); p_properties->push_back(p); } } Variant::Type VisualScriptInstance::get_property_type(const StringName& p_name,bool *r_is_valid) const{ - const Map<StringName,StringName>::Element *remap = script->script_variable_remap.find(p_name); - if (!remap) { - if (r_is_valid) - *r_is_valid=false; - return Variant::NIL; - } - const Map<StringName,VisualScript::Variable>::Element *E=script->variables.find(remap->get()); + const Map<StringName,VisualScript::Variable>::Element *E=script->variables.find(p_name); if (!E) { if (r_is_valid) *r_is_valid=false; @@ -1892,17 +1895,21 @@ Variant VisualScriptInstance::_call_internal(const StringName& p_method, void* p if (node && (r_error.error!=Variant::CallError::CALL_ERROR_INVALID_METHOD || error_str==String())) { + if (error_str!=String()) { + error_str+=" "; + } + if (r_error.error==Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) { int errorarg=r_error.argument; - error_str="Cannot convert argument "+itos(errorarg+1)+" to "+Variant::get_type_name(r_error.expected)+"."; + error_str+="Cannot convert argument "+itos(errorarg+1)+" to "+Variant::get_type_name(r_error.expected)+"."; } else if (r_error.error==Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) { - error_str="Expected "+itos(r_error.argument)+" arguments."; + error_str+="Expected "+itos(r_error.argument)+" arguments."; } else if (r_error.error==Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) { - error_str="Expected "+itos(r_error.argument)+" arguments."; + error_str+="Expected "+itos(r_error.argument)+" arguments."; } else if (r_error.error==Variant::CallError::CALL_ERROR_INVALID_METHOD) { - error_str="Invalid Call."; + error_str+="Invalid Call."; } else if (r_error.error==Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL) { - error_str="Instance is null"; + error_str+="Base Instance is null"; } } diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index fe09e7af43..794230d694 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -65,7 +65,7 @@ public: Variant::Type type; InputEvent::Type ev_type; StringName obj_type; - String script_type; + Ref<Script> script; TypeGuess() { type=Variant::NIL; ev_type=InputEvent::NONE; } }; @@ -227,7 +227,6 @@ friend class VisualScriptInstance; Map<StringName,Function> functions; Map<StringName,Variable> variables; - Map<StringName,StringName> script_variable_remap; Map<StringName,Vector<Argument> > custom_signals; Map<Object*,VisualScriptInstance*> instances; @@ -281,6 +280,7 @@ public: bool has_data_connection(const StringName& p_func,int p_from_node,int p_from_port,int p_to_node,int p_to_port) const; void get_data_connection_list(const StringName& p_func,List<DataConnection> *r_connection) const; bool is_input_value_port_connected(const StringName& p_name,int p_node,int p_port) const; + bool get_input_value_port_connection_source(const StringName& p_name,int p_node,int p_port,int *r_node,int *r_port) const; void add_variable(const StringName& p_name,const Variant& p_default_value=Variant(),bool p_export=false); bool has_variable(const StringName& p_name) const; diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 9f8dfcabc4..14708799af 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -3,6 +3,7 @@ #include "visual_script_nodes.h" #include "visual_script_flow_control.h" #include "visual_script_func_nodes.h" +#include "visual_script_expression.h" #include "os/input.h" #include "tools/editor/editor_resource_preview.h" #include "os/keyboard.h" @@ -505,6 +506,9 @@ void VisualScriptEditor::_update_graph(int p_only_id) { Label *text = memnew( Label ); text->set_text(node->get_text()); gnode->add_child(text); + if (node->cast_to<VisualScriptExpression>()) { + text->add_font_override("font",get_font("source","EditorFonts")); + } if (node->cast_to<VisualScriptComment>()) { Ref<VisualScriptComment> vsc=node; @@ -2578,11 +2582,320 @@ void VisualScriptEditor::_graph_disconnected(const String& p_from,int p_from_slo } + void VisualScriptEditor::_graph_connect_to_empty(const String& p_from,int p_from_slot,const Vector2& p_release_pos) { + Node* node = graph->get_node(p_from); + if (!node) + return; + + GraphNode *gn = node->cast_to<GraphNode>(); + if (!gn) + return; + + Ref<VisualScriptNode> vsn = script->get_node(edited_func,p_from.to_int()); + if (!vsn.is_valid()) + return; + + if (p_from_slot<vsn->get_output_sequence_port_count()) { + + port_action_popup->clear(); + port_action_popup->add_item(TTR("Condition"),CREATE_COND); + port_action_popup->add_item(TTR("Sequence"),CREATE_SEQUENCE); + port_action_popup->add_item(TTR("Switch"),CREATE_SWITCH); + port_action_popup->add_item(TTR("Iterator"),CREATE_ITERATOR); + port_action_popup->add_item(TTR("While"),CREATE_WHILE); + port_action_popup->add_item(TTR("Return"),CREATE_RETURN); + + port_action_node=p_from.to_int(); + port_action_output=p_from_slot; + + } else { + port_action_popup->clear(); + port_action_popup->add_item(TTR("Call"),CREATE_CALL); + port_action_popup->add_item(TTR("Get"),CREATE_GET); + port_action_popup->add_item(TTR("Set"),CREATE_SET); + + + port_action_output=p_from_slot-vsn->get_output_sequence_port_count(); + port_action_node=p_from.to_int(); + + + } + + port_action_pos=p_release_pos; + port_action_popup->set_size(Size2(1,1)); + port_action_popup->set_pos(graph->get_global_pos()+p_release_pos); + port_action_popup->popup(); +} + +VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_node,int p_output,Set<int> &visited_nodes) { + + + VisualScriptNode::TypeGuess tg; + tg.type=Variant::NIL; + + if (visited_nodes.has(p_node)) + return tg; //no loop + + visited_nodes.insert(p_node); + + Ref<VisualScriptNode> node = script->get_node(edited_func,p_node); + + if (!node.is_valid()) { + + return tg; + } + + Vector<VisualScriptNode::TypeGuess> in_guesses; + + for(int i=0;i<node->get_input_value_port_count();i++) { + PropertyInfo pi = node->get_input_value_port_info(i); + VisualScriptNode::TypeGuess g; + g.type=pi.type; + + if (g.type==Variant::NIL || g.type==Variant::OBJECT) { + //any or object input, must further guess what this is + int from_node; + int from_port; + + if (script->get_input_value_port_connection_source(edited_func,p_node,i,&from_node,&from_port)) { + + g = _guess_output_type(from_node,from_port,visited_nodes); + } else { + Variant defval = node->get_default_input_value(i); + if (defval.get_type()==Variant::OBJECT) { + + Object *obj = defval; + + if (obj) { + + g.type=Variant::OBJECT; + g.obj_type=obj->get_type(); + g.script=obj->get_script(); + } + } + } + + } + + in_guesses.push_back(g); + } + + return node->guess_output_type(in_guesses.ptr(),p_output); +} + +void VisualScriptEditor::_port_action_menu(int p_option) { + + Vector2 ofs = graph->get_scroll_ofs() + port_action_pos; + if (graph->is_using_snap()) { + int snap = graph->get_snap(); + ofs = ofs.snapped(Vector2(snap,snap)); + } + ofs/=EDSCALE; + + bool seq_connect=false; + + Ref<VisualScriptNode> vnode; + Set<int> vn; + + switch(p_option) { + + case CREATE_CALL: { + + Ref<VisualScriptFunctionCall> n; + n.instance(); + vnode=n; + + VisualScriptNode::TypeGuess tg = _guess_output_type(port_action_node,port_action_output,vn); + + if (tg.type==Variant::OBJECT) { + n->set_call_mode(VisualScriptFunctionCall::CALL_MODE_INSTANCE); + + if (tg.obj_type!=StringName()) { + n->set_base_type(tg.obj_type); + } else { + n->set_base_type("Object"); + } + + if (tg.script.is_valid()) { + n->set_base_script(tg.script->get_path()); + new_connect_node_select->select_method_from_script(tg.script); + } else { + new_connect_node_select->select_method_from_base_type(n->get_base_type()); + } + + + } else { + n->set_call_mode(VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE); + n->set_basic_type(tg.type); + new_connect_node_select->select_method_from_basic_type(tg.type); + } + + + + } break; + case CREATE_SET: { + + Ref<VisualScriptPropertySet> n; + n.instance(); + vnode=n; + + + VisualScriptNode::TypeGuess tg = _guess_output_type(port_action_node,port_action_output,vn); + + if (tg.type==Variant::OBJECT) { + n->set_call_mode(VisualScriptPropertySet::CALL_MODE_INSTANCE); + + if (tg.obj_type!=StringName()) { + n->set_base_type(tg.obj_type); + } else { + n->set_base_type("Object"); + } + + if (tg.script.is_valid()) { + n->set_base_script(tg.script->get_path()); + new_connect_node_select->select_property_from_script(tg.script); + } else { + new_connect_node_select->select_property_from_base_type(n->get_base_type()); + } + + + } else { + n->set_call_mode(VisualScriptPropertySet::CALL_MODE_BASIC_TYPE); + n->set_basic_type(tg.type); + new_connect_node_select->select_property_from_basic_type(tg.type,tg.ev_type); + } + } break; + case CREATE_GET: { + + Ref<VisualScriptPropertyGet> n; + n.instance(); + vnode=n; + + VisualScriptNode::TypeGuess tg = _guess_output_type(port_action_node,port_action_output,vn); + + if (tg.type==Variant::OBJECT) { + n->set_call_mode(VisualScriptPropertyGet::CALL_MODE_INSTANCE); + + if (tg.obj_type!=StringName()) { + n->set_base_type(tg.obj_type); + } else { + n->set_base_type("Object"); + } + + if (tg.script.is_valid()) { + n->set_base_script(tg.script->get_path()); + new_connect_node_select->select_property_from_script(tg.script); + } else { + new_connect_node_select->select_property_from_base_type(n->get_base_type()); + } + + + } else { + n->set_call_mode(VisualScriptPropertyGet::CALL_MODE_BASIC_TYPE); + n->set_basic_type(tg.type); + new_connect_node_select->select_property_from_basic_type(tg.type,tg.ev_type); + } + + } break; + case CREATE_COND: { + + Ref<VisualScriptCondition> n; + n.instance(); + vnode=n; + seq_connect=true; + + } break; + case CREATE_SEQUENCE: { + + Ref<VisualScriptSequence> n; + n.instance(); + vnode=n; + seq_connect=true; + + } break; + case CREATE_SWITCH: { + + Ref<VisualScriptSwitch> n; + n.instance(); + vnode=n; + seq_connect=true; + + } break; + case CREATE_ITERATOR: { + + Ref<VisualScriptIterator> n; + n.instance(); + vnode=n; + seq_connect=true; + + } break; + case CREATE_WHILE: { + + Ref<VisualScriptWhile> n; + n.instance(); + vnode=n; + seq_connect=true; + + } break; + case CREATE_RETURN: { + + Ref<VisualScriptReturn> n; + n.instance(); + vnode=n; + seq_connect=true; + + } break; + + } + + int new_id = script->get_available_id(); + undo_redo->create_action(TTR("Add Node")); + undo_redo->add_do_method(script.ptr(),"add_node",edited_func,new_id,vnode,ofs); + if (seq_connect) { + undo_redo->add_do_method(script.ptr(),"sequence_connect",edited_func,port_action_node,port_action_output,new_id); + } + undo_redo->add_undo_method(script.ptr(),"remove_node",edited_func,new_id); + undo_redo->add_do_method(this,"_update_graph",new_id); + undo_redo->add_undo_method(this,"_update_graph",new_id); + undo_redo->commit_action(); + + port_action_new_node=new_id; } +void VisualScriptEditor::_selected_connect_node_method_or_setget(const String& p_text) { + + Ref<VisualScriptNode> vsn = script->get_node(edited_func,port_action_new_node); + + if (vsn->cast_to<VisualScriptFunctionCall>()) { + + Ref<VisualScriptFunctionCall> vsfc = vsn; + vsfc->set_function(p_text); + script->data_connect(edited_func,port_action_node,port_action_output,port_action_new_node,0); + } + + if (vsn->cast_to<VisualScriptPropertySet>()) { + + Ref<VisualScriptPropertySet> vsp = vsn; + vsp->set_property(p_text); + script->data_connect(edited_func,port_action_node,port_action_output,port_action_new_node,0); + } + + if (vsn->cast_to<VisualScriptPropertyGet>()) { + + Ref<VisualScriptPropertyGet> vsp = vsn; + vsp->set_property(p_text); + script->data_connect(edited_func,port_action_node,port_action_output,port_action_new_node,0); + } + + _update_graph(port_action_new_node); + _update_graph_connections(); + +} + + void VisualScriptEditor::_default_value_changed() { @@ -2909,6 +3222,8 @@ void VisualScriptEditor::_bind_methods() { ObjectTypeDB::bind_method("_center_on_node",&VisualScriptEditor::_center_on_node); ObjectTypeDB::bind_method("_comment_node_resized",&VisualScriptEditor::_comment_node_resized); ObjectTypeDB::bind_method("_button_resource_previewed",&VisualScriptEditor::_button_resource_previewed); + ObjectTypeDB::bind_method("_port_action_menu",&VisualScriptEditor::_port_action_menu); + ObjectTypeDB::bind_method("_selected_connect_node_method_or_setget",&VisualScriptEditor::_selected_connect_node_method_or_setget); @@ -2969,7 +3284,7 @@ VisualScriptEditor::VisualScriptEditor() { VBoxContainer *left_vb = memnew( VBoxContainer ); left_vsplit->add_child(left_vb); left_vb->set_v_size_flags(SIZE_EXPAND_FILL); - left_vb->set_custom_minimum_size(Size2(180,1)*EDSCALE); + left_vb->set_custom_minimum_size(Size2(230,1)*EDSCALE); base_type_select = memnew( Button ); left_vb->add_margin_child(TTR("Base Type:"),base_type_select); @@ -3113,6 +3428,15 @@ VisualScriptEditor::VisualScriptEditor() { method_select->connect("selected",this,"_selected_method"); error_line=-1; + new_connect_node_select = memnew( PropertySelector ); + add_child(new_connect_node_select); + new_connect_node_select->connect("selected",this,"_selected_connect_node_method_or_setget"); + + port_action_popup = memnew( PopupMenu ); + add_child(port_action_popup); + port_action_popup->connect("item_pressed",this,"_port_action_menu"); + + } VisualScriptEditor::~VisualScriptEditor() { diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index 5a40822bfe..5191ed540a 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -33,6 +33,19 @@ class VisualScriptEditor : public ScriptEditorBase { EDIT_PASTE_NODES, }; + enum PortAction { + + CREATE_CALL, + CREATE_SET, + CREATE_GET, + CREATE_COND, + CREATE_SEQUENCE, + CREATE_SWITCH, + CREATE_ITERATOR, + CREATE_WHILE, + CREATE_RETURN, + }; + MenuButton *edit_menu; Ref<VisualScript> script; @@ -53,6 +66,7 @@ class VisualScriptEditor : public ScriptEditorBase { PropertyEditor *edit_signal_edit; PropertySelector *method_select; + PropertySelector *new_connect_node_select; VisualScriptEditorVariableEdit *variable_editor; @@ -114,6 +128,16 @@ class VisualScriptEditor : public ScriptEditorBase { static Clipboard *clipboard; + PopupMenu *port_action_popup; + + PortAction port_action; + int port_action_node; + int port_action_output; + Vector2 port_action_pos; + int port_action_new_node; + void _port_action_menu(int p_option); + void _selected_connect_node_method_or_setget(const String& p_text); + int error_line; @@ -145,6 +169,7 @@ class VisualScriptEditor : public ScriptEditorBase { void _member_button(Object *p_item, int p_column, int p_button); + String revert_on_drag; void _input(const InputEvent& p_event); @@ -173,6 +198,8 @@ class VisualScriptEditor : public ScriptEditorBase { void _draw_color_over_button(Object* obj,Color p_color); void _button_resource_previewed(const String& p_path,const Ref<Texture>& p_preview,Variant p_ud); + VisualScriptNode::TypeGuess _guess_output_type(int p_port_action_node,int p_port_action_output,Set<int> &visited_nodes); + protected: diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp new file mode 100644 index 0000000000..3cfb1c154e --- /dev/null +++ b/modules/visual_script/visual_script_expression.cpp @@ -0,0 +1,1440 @@ +#include "visual_script_expression.h" + + +bool VisualScriptExpression::_set(const StringName& p_name, const Variant& p_value) { + + if (String(p_name)=="expression") { + expression=p_value; + expression_dirty=true; + ports_changed_notify(); + return true; + } + + if (String(p_name)=="out_type") { + output_type=Variant::Type(int(p_value)); + expression_dirty=true; + ports_changed_notify(); + return true; + } + if (String(p_name)=="sequenced") { + sequenced=p_value; + ports_changed_notify(); + return true; + } + + if (String(p_name)=="input_count") { + + int from=inputs.size(); + inputs.resize(int(p_value)); + for(int i=from;i<inputs.size();i++) { + inputs[i].name=String::chr('a'+i); + if (from==0) { + inputs[i].type=output_type; + } else { + inputs[i].type=inputs[from-1].type; + } + } + expression_dirty=true; + ports_changed_notify(); + _change_notify(); + return true; + } + + if (String(p_name).begins_with("input/")) { + + int idx=String(p_name).get_slice("/",1).to_int(); + ERR_FAIL_INDEX_V(idx,inputs.size(),false); + + String what=String(p_name).get_slice("/",2); + + if (what=="type") { + + inputs[idx].type=Variant::Type(int(p_value)); + } else if (what=="name") { + + inputs[idx].name=p_value; + } else { + return false; + } + + expression_dirty=true; + ports_changed_notify(); + return true; + } + + + return false; + +} + +bool VisualScriptExpression::_get(const StringName& p_name,Variant &r_ret) const { + + if (String(p_name)=="expression") { + r_ret=expression; + return true; + } + + if (String(p_name)=="out_type") { + r_ret=output_type; + return true; + } + + if (String(p_name)=="sequenced") { + r_ret=sequenced; + return true; + } + + if (String(p_name)=="input_count") { + r_ret=inputs.size(); + return true; + } + + if (String(p_name).begins_with("input/")) { + + int idx=String(p_name).get_slice("/",1).to_int(); + ERR_FAIL_INDEX_V(idx,inputs.size(),false); + + String what=String(p_name).get_slice("/",2); + + if (what=="type") { + + r_ret=inputs[idx].type; + } else if (what=="name") { + + r_ret=inputs[idx].name; + } else { + return false; + } + + return true; + } + + + return false; +} +void VisualScriptExpression::_get_property_list( List<PropertyInfo> *p_list) const { + + + String argt="Any"; + for(int i=1;i<Variant::VARIANT_MAX;i++) { + argt+=","+Variant::get_type_name(Variant::Type(i)); + } + + p_list->push_back(PropertyInfo(Variant::STRING,"expression")); + p_list->push_back(PropertyInfo(Variant::INT,"out_type",PROPERTY_HINT_ENUM,argt)); + p_list->push_back(PropertyInfo(Variant::INT,"input_count",PROPERTY_HINT_RANGE,"0,64,1")); + p_list->push_back(PropertyInfo(Variant::BOOL,"sequenced")); + + for(int i=0;i<inputs.size();i++) { + + p_list->push_back(PropertyInfo(Variant::INT,"input/"+itos(i)+"/type",PROPERTY_HINT_ENUM,argt)); + p_list->push_back(PropertyInfo(Variant::STRING,"input/"+itos(i)+"/name")); + } +} + +int VisualScriptExpression::get_output_sequence_port_count() const { + + return sequenced?1:0; +} +bool VisualScriptExpression::has_input_sequence_port() const{ + + return sequenced; +} + + +String VisualScriptExpression::get_output_sequence_port_text(int p_port) const{ + + return String(); +} + + +int VisualScriptExpression::get_input_value_port_count() const{ + + return inputs.size(); + +} +int VisualScriptExpression::get_output_value_port_count() const{ + + return 1; +} + + +PropertyInfo VisualScriptExpression::get_input_value_port_info(int p_idx) const{ + + return PropertyInfo(inputs[p_idx].type,inputs[p_idx].name); +} +PropertyInfo VisualScriptExpression::get_output_value_port_info(int p_idx) const{ + + return PropertyInfo(output_type,"result"); +} + +String VisualScriptExpression::get_caption() const{ + + return "Expression"; +} +String VisualScriptExpression::get_text() const{ + + return expression; +} + + +Error VisualScriptExpression::_get_token(Token& r_token) { + + while (true) { +#define GET_CHAR() (str_ofs>=expression.length()?0:expression[str_ofs++]) + + CharType cchar = GET_CHAR(); + if (cchar==0) { + r_token.type=TK_EOF; + return OK; + } + + + switch(cchar) { + + case 0: { + r_token.type=TK_EOF; + return OK; + } break; + case '{': { + + r_token.type=TK_CURLY_BRACKET_OPEN; + return OK; + }; + case '}': { + + r_token.type=TK_CURLY_BRACKET_CLOSE; + return OK; + }; + case '[': { + + r_token.type=TK_BRACKET_OPEN; + return OK; + }; + case ']': { + + r_token.type=TK_BRACKET_CLOSE; + return OK; + }; + case '(': { + + r_token.type=TK_PARENTHESIS_OPEN; + return OK; + }; + case ')': { + + r_token.type=TK_PARENTHESIS_CLOSE; + return OK; + }; + case ',': { + + r_token.type=TK_COMMA; + return OK; + }; + case ':': { + + r_token.type=TK_COLON; + return OK; + }; + case '.': { + + r_token.type=TK_PERIOD; + return OK; + }; + case '=': { + + cchar=GET_CHAR(); + if (cchar=='=') { + r_token.type=TK_OP_EQUAL; + } else { + _set_error("Expected '='"); + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } + return OK; + }; + case '!': { + + if (expression[str_ofs]=='=') { + r_token.type=TK_OP_NOT_EQUAL; + str_ofs++; + } else { + r_token.type=TK_OP_NOT; + } + return OK; + }; + case '>': { + + if (expression[str_ofs]=='=') { + r_token.type=TK_OP_GREATER_EQUAL; + str_ofs++; + } else if (expression[str_ofs]=='>') { + r_token.type=TK_OP_SHIFT_RIGHT; + str_ofs++; + } else { + r_token.type=TK_OP_GREATER; + } + return OK; + }; + case '<': { + + if (expression[str_ofs]=='=') { + r_token.type=TK_OP_LESS_EQUAL; + str_ofs++; + } else if (expression[str_ofs]=='<') { + r_token.type=TK_OP_SHIFT_LEFT; + str_ofs++; + } else { + r_token.type=TK_OP_LESS; + } + return OK; + }; + case '+': { + r_token.type=TK_OP_ADD; + return OK; + }; + case '-': { + r_token.type=TK_OP_SUB; + return OK; + }; + case '/': { + r_token.type=TK_OP_DIV; + return OK; + }; + case '*': { + r_token.type=TK_OP_MUL; + return OK; + }; + case '%': { + r_token.type=TK_OP_MOD; + return OK; + }; + case '&': { + + if (expression[str_ofs]=='&') { + r_token.type=TK_OP_AND; + str_ofs++; + } else { + r_token.type=TK_OP_BIT_AND; + } + return OK; + }; + case '|': { + + if (expression[str_ofs]=='|') { + r_token.type=TK_OP_OR; + str_ofs++; + } else { + r_token.type=TK_OP_BIT_OR; + } + return OK; + }; + case '^': { + + r_token.type=TK_OP_BIT_XOR; + + return OK; + }; + case '~': { + + r_token.type=TK_OP_BIT_INVERT; + + return OK; + }; + case '"': { + + + String str; + while(true) { + + CharType ch=GET_CHAR(); + + if (ch==0) { + _set_error("Unterminated String"); + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } else if (ch=='"') { + break; + } else if (ch=='\\') { + //escaped characters... + + CharType next = GET_CHAR(); + if (next==0) { + _set_error("Unterminated String"); + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } + CharType res=0; + + switch(next) { + + case 'b': res=8; break; + case 't': res=9; break; + case 'n': res=10; break; + case 'f': res=12; break; + case 'r': res=13; break; + case 'u': { + //hexnumbarh - oct is deprecated + + + for(int j=0;j<4;j++) { + CharType c = GET_CHAR(); + + if (c==0) { + _set_error("Unterminated String"); + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } + if (!((c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F'))) { + + _set_error("Malformed hex constant in string"); + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } + CharType v; + if (c>='0' && c<='9') { + v=c-'0'; + } else if (c>='a' && c<='f') { + v=c-'a'; + v+=10; + } else if (c>='A' && c<='F') { + v=c-'A'; + v+=10; + } else { + ERR_PRINT("BUG"); + v=0; + } + + res<<=4; + res|=v; + + + } + + + + } break; + //case '\"': res='\"'; break; + //case '\\': res='\\'; break; + //case '/': res='/'; break; + default: { + res = next; + //r_err_str="Invalid escape sequence"; + //return ERR_PARSE_ERROR; + } break; + } + + str+=res; + + } else { + str+=ch; + } + } + + r_token.type=TK_CONSTANT; + r_token.value=str; + return OK; + + } break; + default: { + + if (cchar<=32) { + break; + } + + if (cchar=='-' || (cchar>='0' && cchar<='9')) { + //a number + + + String num; +#define READING_SIGN 0 +#define READING_INT 1 +#define READING_DEC 2 +#define READING_EXP 3 +#define READING_DONE 4 + int reading=READING_INT; + + if (cchar=='-') { + num+='-'; + cchar=GET_CHAR(); + + } + + + + CharType c = cchar; + bool exp_sign=false; + bool exp_beg=false; + bool is_float=false; + + while(true) { + + switch(reading) { + case READING_INT: { + + if (c>='0' && c<='9') { + //pass + } else if (c=='.') { + reading=READING_DEC; + is_float=true; + } else if (c=='e') { + reading=READING_EXP; + } else { + reading=READING_DONE; + } + + } break; + case READING_DEC: { + + if (c>='0' && c<='9') { + + } else if (c=='e') { + reading=READING_EXP; + + } else { + reading=READING_DONE; + } + + } break; + case READING_EXP: { + + if (c>='0' && c<='9') { + exp_beg=true; + + } else if ((c=='-' || c=='+') && !exp_sign && !exp_beg) { + if (c=='-') + is_float=true; + exp_sign=true; + + } else { + reading=READING_DONE; + } + } break; + } + + if (reading==READING_DONE) + break; + num+=String::chr(c); + c = GET_CHAR(); + + + } + + str_ofs--; + + r_token.type=TK_CONSTANT; + + if (is_float) + r_token.value=num.to_double(); + else + r_token.value=num.to_int(); + return OK; + + } else if ((cchar>='A' && cchar<='Z') || (cchar>='a' && cchar<='z') || cchar=='_') { + + String id; + bool first=true; + + while((cchar>='A' && cchar<='Z') || (cchar>='a' && cchar<='z') || cchar=='_' || (!first && cchar>='0' && cchar<='9')) { + + id+=String::chr(cchar); + cchar=GET_CHAR(); + first=false; + } + + str_ofs--; //go back one + + if (id=="in") { + r_token.type=TK_OP_IN; + } else if (id=="null") { + r_token.type=TK_CONSTANT; + r_token.value=Variant(); + } else if (id=="true") { + r_token.type=TK_CONSTANT; + r_token.value=true; + } else if (id=="false") { + r_token.type=TK_CONSTANT; + r_token.value=false; + } else if (id=="PI") { + r_token.type=TK_CONSTANT; + r_token.value=Math_PI; + } else if (id=="not") { + r_token.type=TK_OP_NOT; + } else if (id=="or") { + r_token.type=TK_OP_OR; + } else if (id=="and") { + r_token.type=TK_OP_AND; + } else if (id=="self") { + r_token.type=TK_SELF; + } else { + + for(int i=0;i<Variant::VARIANT_MAX;i++) { + if (id==Variant::get_type_name(Variant::Type(i))) { + r_token.type=TK_BASIC_TYPE; + r_token.value=i; + return OK; + break; + } + } + + r_token.type=TK_IDENTIFIER; + r_token.value=id; + } + + return OK; + } else { + _set_error("Unexpected character."); + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; + } + } + } + } + + r_token.type=TK_ERROR; + return ERR_PARSE_ERROR; +} + +const char* VisualScriptExpression::token_name[TK_MAX]={ +"CURLY BRACKET OPEN", +"CURLY BRACKET CLOSE", +"BRACKET OPEN", +"BRACKET CLOSE", +"PARENTHESIS OPEN", +"PARENTHESIS CLOSE", +"IDENTIFIER", +"SELF", +"CONSTANT", +"BASIC TYPE", +"COLON", +"COMMA", +"PERIOD", +"OP IN", +"OP EQUAL", +"OP NOT EQUAL", +"OP LESS", +"OP LESS EQUAL", +"OP GREATER", +"OP GREATER EQUAL", +"OP AND", +"OP OR", +"OP NOT", +"OP ADD", +"OP SUB", +"OP MUL", +"OP DIV", +"OP MOD", +"OP SHIFT LEFT", +"OP SHIFT RIGHT", +"OP BIT AND", +"OP BIT OR", +"OP BIT XOR", +"OP BIT INVERT", +"EOF", +"ERROR" +}; + +VisualScriptExpression::ENode* VisualScriptExpression::_parse_expression() { + + + Vector<Expression> expression; + + while(true) { + //keep appending stuff to expression + ENode*expr=NULL; + + Token tk; + _get_token(tk); + if (error_set) + return NULL; + + + + switch(tk.type) { + case TK_CURLY_BRACKET_OPEN: { + //a dictionary + DictionaryNode *dn = alloc_node<DictionaryNode>(); + + + while(true) { + + int cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_CURLY_BRACKET_CLOSE) { + break; + } + str_ofs=cofs; //revert + //parse an expression + ENode* expr=_parse_expression(); + if (!expr) + return NULL; + dn->dict.push_back(expr); + + _get_token(tk); + if (tk.type!=TK_COLON) { + _set_error("Expected ':'"); + return NULL; + } + + expr=_parse_expression(); + if (!expr) + return NULL; + + dn->dict.push_back(expr); + + cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_COMMA) { + //all good + } else if (tk.type==TK_CURLY_BRACKET_CLOSE) { + str_ofs=cofs; + } else { + _set_error("Expected ',' or '}'"); + } + } + + expr=dn; + } break; + case TK_BRACKET_OPEN: { + //an array + + ArrayNode *an = alloc_node<ArrayNode>(); + + + while(true) { + + int cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_BRACKET_CLOSE) { + break; + } + str_ofs=cofs; //revert + //parse an expression + ENode* expr=_parse_expression(); + if (!expr) + return NULL; + an->array.push_back(expr); + + cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_COMMA) { + //all good + } else if (tk.type==TK_BRACKET_CLOSE) { + str_ofs=cofs; + } else { + _set_error("Expected ',' or ']'"); + } + } + + expr=an; + } break; + case TK_PARENTHESIS_OPEN: { + //a suexpression + ENode* e=_parse_expression(); + if (error_set) + return NULL; + _get_token(tk); + if (tk.type!=TK_PARENTHESIS_CLOSE) { + _set_error("Expected ')'"); + return NULL; + } + + expr=e; + + } break; + case TK_IDENTIFIER: { + + String what = tk.value; + int index=-1; + for(int i=0;i<inputs.size();i++) { + if (what==inputs[i].name) { + index=i; + break; + } + } + + if (index!=-1) { + InputNode *input = alloc_node<InputNode>(); + input->index=index; + expr=input; + } else { + _set_error("Invalid input identifier '"+what+"'. For script variables, use self (locals are for inputs)."+what); + return NULL; + } + } break; + case TK_SELF: { + + SelfNode *self = alloc_node<SelfNode>(); + expr=self; + } break; + case TK_CONSTANT: { + ConstantNode *constant = alloc_node<ConstantNode>(); + constant->value=tk.value; + expr=constant; + } break; + case TK_BASIC_TYPE: { + //constructor.. + + Variant::Type bt = Variant::Type(int(tk.value)); + _get_token(tk); + if (tk.type!=TK_PARENTHESIS_OPEN) { + _set_error("Expected '('"); + return NULL; + } + + ConstructorNode *constructor = alloc_node<ConstructorNode>(); + constructor->data_type=bt; + + while(true) { + + int cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_PARENTHESIS_CLOSE) { + break; + } + str_ofs=cofs; //revert + //parse an expression + ENode* expr=_parse_expression(); + if (!expr) + return NULL; + + constructor->arguments.push_back(expr); + + cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_COMMA) { + //all good + } else if (tk.type==TK_PARENTHESIS_CLOSE) { + str_ofs=cofs; + } else { + _set_error("Expected ',' or ')'"); + } + } + + expr=constructor; + + } break; + case TK_OP_SUB: { + + Expression e; + e.is_op=true; + e.op=Variant::OP_NEGATE; + expression.push_back(e); + continue; + } break; + case TK_OP_NOT: { + + Expression e; + e.is_op=true; + e.op=Variant::OP_NOT; + expression.push_back(e); + continue; + } break; + + default: { + _set_error("Expected expression."); + return NULL; + } break; + + } + + //before going to operators, must check indexing! + + while(true) { + int cofs2=str_ofs; + _get_token(tk); + if (error_set) + return NULL; + + bool done=false; + + switch(tk.type) { + case TK_BRACKET_OPEN: { + //value indexing + + IndexNode *index = alloc_node<IndexNode>(); + index->base=expr; + + ENode* what=_parse_expression(); + if (!what) + return NULL; + + index->index=what; + + _get_token(tk); + if (tk.type!=TK_BRACKET_CLOSE) { + _set_error("Expected ']' at end of index."); + return NULL; + } + expr=index; + + } break; + case TK_PERIOD: { + //named indexing or function call + _get_token(tk); + if (tk.type!=TK_IDENTIFIER) { + _set_error("Expected identifier after '.'"); + return NULL; + } + + StringName identifier=tk.value; + + int cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_PARENTHESIS_OPEN) { + //function call + CallNode *func_call = alloc_node<CallNode>(); + func_call->method=identifier; + func_call->base=expr; + + while(true) { + + int cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_PARENTHESIS_CLOSE) { + break; + } + str_ofs=cofs; //revert + //parse an expression + ENode* expr=_parse_expression(); + if (!expr) + return NULL; + + func_call->arguments.push_back(expr); + + cofs=str_ofs; + _get_token(tk); + if (tk.type==TK_COMMA) { + //all good + } else if (tk.type==TK_PARENTHESIS_CLOSE) { + str_ofs=cofs; + } else { + _set_error("Expected ',' or ')'"); + } + } + + expr=func_call; + } else { + //named indexing + str_ofs=cofs; + + NamedIndexNode *index = alloc_node<NamedIndexNode>(); + index->base=expr; + index->name=identifier; + expr=index; + + } + + } break; + default: { + str_ofs=cofs2; + done=true; + } break; + } + + if (done) + break; + } + + //push expression + { + Expression e; + e.is_op=false; + e.node=expr; + expression.push_back(e); + } + + //ok finally look for an operator + + + int cofs=str_ofs; + _get_token(tk); + if (error_set) + return NULL; + + + Variant::Operator op = Variant::OP_MAX; + + switch(tk.type) { + case TK_OP_IN: op=Variant::OP_IN; break; + case TK_OP_EQUAL: op=Variant::OP_EQUAL; break; + case TK_OP_NOT_EQUAL: op=Variant::OP_NOT_EQUAL; break; + case TK_OP_LESS: op=Variant::OP_LESS; break; + case TK_OP_LESS_EQUAL: op=Variant::OP_LESS_EQUAL; break; + case TK_OP_GREATER: op=Variant::OP_GREATER; break; + case TK_OP_GREATER_EQUAL: op=Variant::OP_GREATER_EQUAL; break; + case TK_OP_AND: op=Variant::OP_AND; break; + case TK_OP_OR: op=Variant::OP_OR; break; + case TK_OP_NOT: op=Variant::OP_NOT; break; + case TK_OP_ADD: op=Variant::OP_ADD; break; + case TK_OP_SUB: op=Variant::OP_SUBSTRACT; break; + case TK_OP_MUL: op=Variant::OP_MULTIPLY; break; + case TK_OP_DIV: op=Variant::OP_DIVIDE; break; + case TK_OP_MOD: op=Variant::OP_MODULE; break; + case TK_OP_SHIFT_LEFT: op=Variant::OP_SHIFT_LEFT; break; + case TK_OP_SHIFT_RIGHT: op=Variant::OP_SHIFT_RIGHT; break; + case TK_OP_BIT_AND: op=Variant::OP_BIT_AND; break; + case TK_OP_BIT_OR: op=Variant::OP_BIT_OR; break; + case TK_OP_BIT_XOR: op=Variant::OP_BIT_XOR; break; + case TK_OP_BIT_INVERT: op=Variant::OP_BIT_NEGATE; break; + default: {}; + } + + if (op==Variant::OP_MAX) { //stop appending stuff + str_ofs=cofs; + break; + } + + //push operator and go on + { + Expression e; + e.is_op=true; + e.op=op; + expression.push_back(e); + } + } + + + /* Reduce the set set of expressions and place them in an operator tree, respecting precedence */ + + + while(expression.size()>1) { + + int next_op=-1; + int min_priority=0xFFFFF; + bool is_unary=false; + + for(int i=0;i<expression.size();i++) { + + + + if (!expression[i].is_op) { + + continue; + } + + int priority; + + bool unary=false; + + switch(expression[i].op) { + + + case Variant::OP_BIT_NEGATE: priority=0; unary=true; break; + case Variant::OP_NEGATE: priority=1; unary=true; break; + + case Variant::OP_MULTIPLY: priority=2; break; + case Variant::OP_DIVIDE: priority=2; break; + case Variant::OP_MODULE: priority=2; break; + + case Variant::OP_ADD: priority=3; break; + case Variant::OP_SUBSTRACT: priority=3; break; + + case Variant::OP_SHIFT_LEFT: priority=4; break; + case Variant::OP_SHIFT_RIGHT: priority=4; break; + + case Variant::OP_BIT_AND: priority=5; break; + case Variant::OP_BIT_XOR: priority=6; break; + case Variant::OP_BIT_OR: priority=7; break; + + case Variant::OP_LESS: priority=8; break; + case Variant::OP_LESS_EQUAL: priority=8; break; + case Variant::OP_GREATER: priority=8; break; + case Variant::OP_GREATER_EQUAL: priority=8; break; + + case Variant::OP_EQUAL: priority=8; break; + case Variant::OP_NOT_EQUAL: priority=8; break; + + case Variant::OP_IN: priority=10; break; + + case Variant::OP_NOT: priority=11; unary=true; break; + case Variant::OP_AND: priority=12; break; + case Variant::OP_OR: priority=13; break; + + + default: { + _set_error("Parser bug, invalid operator in expression: "+itos(expression[i].op)); + return NULL; + } + + } + + if (priority<min_priority) { + // < is used for left to right (default) + // <= is used for right to left + + next_op=i; + min_priority=priority; + is_unary=unary; + } + + } + + if (next_op==-1) { + + + _set_error("Yet another parser bug...."); + ERR_FAIL_COND_V(next_op==-1,NULL); + } + + + // OK! create operator.. + if (is_unary) { + + int expr_pos=next_op; + while(expression[expr_pos].is_op) { + + expr_pos++; + if (expr_pos==expression.size()) { + //can happen.. + _set_error("Unexpected end of expression.."); + return NULL; + } + } + + //consecutively do unary opeators + for(int i=expr_pos-1;i>=next_op;i--) { + + OperatorNode *op = alloc_node<OperatorNode>(); + op->op=expression[i].op; + op->nodes[0]=expression[i+1].node; + op->nodes[1]=NULL; + expression[i].is_op=false; + expression[i].node=op; + expression.remove(i+1); + } + + + } else { + + if (next_op <1 || next_op>=(expression.size()-1)) { + _set_error("Parser bug.."); + ERR_FAIL_V(NULL); + } + + OperatorNode *op = alloc_node<OperatorNode>(); + op->op=expression[next_op].op; + + if (expression[next_op-1].is_op) { + + _set_error("Parser bug.."); + ERR_FAIL_V(NULL); + } + + if (expression[next_op+1].is_op) { + // this is not invalid and can really appear + // but it becomes invalid anyway because no binary op + // can be followed by an unary op in a valid combination, + // due to how precedence works, unaries will always dissapear first + + _set_error("Unexpected two consecutive operators."); + return NULL; + } + + + op->nodes[0]=expression[next_op-1].node; //expression goes as left + op->nodes[1]=expression[next_op+1].node; //next expression goes as right + + //replace all 3 nodes by this operator and make it an expression + expression[next_op-1].node=op; + expression.remove(next_op); + expression.remove(next_op); + } + } + + return expression[0].node; +} + +bool VisualScriptExpression::_compile_expression() { + + if (!expression_dirty) + return error_set; + + if (nodes) { + memdelete(nodes); + nodes=NULL; + root=NULL; + + } + + error_str=String(); + error_set=false; + str_ofs=0; + + root=_parse_expression(); + + if (error_set) { + root=NULL; + if (nodes) { + memdelete(nodes); + } + nodes=NULL; + return true; + } + + expression_dirty=false; + return false; +} + + +class VisualScriptNodeInstanceExpression : public VisualScriptNodeInstance { +public: + + VisualScriptInstance* instance; + VisualScriptExpression *expression; + + //virtual int get_working_memory_size() const { return 0; } + //execute by parsing the tree directly + virtual bool _execute(const Variant** p_inputs,VisualScriptExpression::ENode *p_node,Variant& r_ret,String& r_error_str,Variant::CallError &ce) { + + switch(p_node->type) { + case VisualScriptExpression::ENode::TYPE_INPUT: { + + const VisualScriptExpression::InputNode *in = static_cast<const VisualScriptExpression::InputNode*>(p_node); + r_ret=*p_inputs[in->index]; + } break; + case VisualScriptExpression::ENode::TYPE_CONSTANT: { + + const VisualScriptExpression::ConstantNode *c = static_cast<const VisualScriptExpression::ConstantNode*>(p_node); + r_ret=c->value; + + } break; + case VisualScriptExpression::ENode::TYPE_SELF: { + + r_ret=instance->get_owner_ptr(); + } break; + case VisualScriptExpression::ENode::TYPE_OPERATOR: { + + + const VisualScriptExpression::OperatorNode *op = static_cast<const VisualScriptExpression::OperatorNode*>(p_node); + + Variant a; + bool ret = _execute(p_inputs,op->nodes[0],a,r_error_str,ce); + if (ret) + return true; + + Variant b; + + if (op->nodes[1]) { + ret = _execute(p_inputs,op->nodes[1],b,r_error_str,ce); + if (ret) + return true; + } + + bool valid=true; + Variant::evaluate(op->op,a,b,r_ret,valid); + if (!valid) { + r_error_str="Invalid operands to operator "+Variant::get_operator_name(op->op)+": "+Variant::get_type_name(a.get_type())+" and "+Variant::get_type_name(b.get_type())+"."; + return true; + } + + } break; + case VisualScriptExpression::ENode::TYPE_INDEX: { + + const VisualScriptExpression::IndexNode *index = static_cast<const VisualScriptExpression::IndexNode*>(p_node); + + Variant base; + bool ret = _execute(p_inputs,index->base,base,r_error_str,ce); + if (ret) + return true; + + Variant idx; + + ret = _execute(p_inputs,index->index,idx,r_error_str,ce); + if (ret) + return true; + + bool valid; + r_ret=base.get(idx,&valid); + if (!valid) { + r_error_str="Invalid index of type "+Variant::get_type_name(idx.get_type())+" for base of type "+Variant::get_type_name(base.get_type())+"."; + return true; + } + + + + } break; + case VisualScriptExpression::ENode::TYPE_NAMED_INDEX: { + + const VisualScriptExpression::NamedIndexNode *index = static_cast<const VisualScriptExpression::NamedIndexNode*>(p_node); + + Variant base; + bool ret = _execute(p_inputs,index->base,base,r_error_str,ce); + if (ret) + return true; + + bool valid; + r_ret=base.get_named(index->name,&valid); + if (!valid) { + r_error_str="Invalid index '"+String(index->name)+"' for base of type "+Variant::get_type_name(base.get_type())+"."; + return true; + } + + } break; + case VisualScriptExpression::ENode::TYPE_ARRAY: { + const VisualScriptExpression::ArrayNode *array = static_cast<const VisualScriptExpression::ArrayNode*>(p_node); + + Array arr; + arr.resize(array->array.size()); + for (int i=0;i<array->array.size();i++) { + + Variant value; + bool ret = _execute(p_inputs,array->array[i],value,r_error_str,ce); + if (ret) + return true; + arr[i]=value; + } + + r_ret=arr; + + } break; + case VisualScriptExpression::ENode::TYPE_DICTIONARY: { + const VisualScriptExpression::DictionaryNode *dictionary = static_cast<const VisualScriptExpression::DictionaryNode*>(p_node); + + Dictionary d; + for (int i=0;i<dictionary->dict.size();i+=2) { + + Variant key; + bool ret = _execute(p_inputs,dictionary->dict[i+0],key,r_error_str,ce); + if (ret) + return true; + + Variant value; + ret = _execute(p_inputs,dictionary->dict[i+1],value,r_error_str,ce); + if (ret) + return true; + + d[key]=value; + } + + r_ret=d; + } break; + case VisualScriptExpression::ENode::TYPE_CONSTRUCTOR: { + + const VisualScriptExpression::ConstructorNode *constructor = static_cast<const VisualScriptExpression::ConstructorNode*>(p_node); + + Vector<Variant> arr; + Vector<const Variant*> argp; + arr.resize(constructor->arguments.size()); + argp.resize(constructor->arguments.size()); + + for (int i=0;i<constructor->arguments.size();i++) { + + Variant value; + bool ret = _execute(p_inputs,constructor->arguments[i],value,r_error_str,ce); + if (ret) + return true; + arr[i]=value; + argp[i]=&arr[i]; + } + + + r_ret=Variant::construct(constructor->data_type,argp.ptr(),argp.size(),ce); + + if (ce.error!=Variant::CallError::CALL_OK) { + r_error_str="Invalid arguments to construct '"+Variant::get_type_name(constructor->data_type)+"'."; + return true; + } + + + } break; + case VisualScriptExpression::ENode::TYPE_CALL: { + + const VisualScriptExpression::CallNode *call = static_cast<const VisualScriptExpression::CallNode*>(p_node); + + + Variant base; + bool ret = _execute(p_inputs,call->base,base,r_error_str,ce); + if (ret) + return true; + + Vector<Variant> arr; + Vector<const Variant*> argp; + arr.resize(call->arguments.size()); + argp.resize(call->arguments.size()); + + for (int i=0;i<call->arguments.size();i++) { + + Variant value; + bool ret = _execute(p_inputs,call->arguments[i],value,r_error_str,ce); + if (ret) + return true; + arr[i]=value; + argp[i]=&arr[i]; + } + + + r_ret=base.call(call->method,argp.ptr(),argp.size(),ce); + + if (ce.error!=Variant::CallError::CALL_OK) { + r_error_str="On call to '"+String(call->method)+"':"; + return true; + } + + } break; + } + return false; + } + + virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) { + + if (!expression->root || expression->error_set) { + r_error_str=expression->error_str; + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + return 0; + } + + + bool error = _execute(p_inputs,expression->root,*p_outputs[0],r_error_str,r_error); + if (error && r_error.error==Variant::CallError::CALL_OK) { + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + } + +#ifdef DEBUG_ENABLED + if (!error && expression->output_type!=Variant::NIL && !Variant::can_convert_strict(p_outputs[0]->get_type(),expression->output_type)) { + + r_error_str+="Can't convert expression result from "+Variant::get_type_name(p_outputs[0]->get_type())+" to "+Variant::get_type_name(expression->output_type)+"."; + r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD; + +#endif + } + + return 0; + } + + +}; + +VisualScriptNodeInstance* VisualScriptExpression::instance(VisualScriptInstance* p_instance){ + + _compile_expression(); + VisualScriptNodeInstanceExpression *instance = memnew( VisualScriptNodeInstanceExpression ); + instance->instance=p_instance; + instance->expression=this; + return instance; +} + + +VisualScriptExpression::VisualScriptExpression() +{ + output_type=Variant::NIL; + expression_dirty=true; + error_set=true; + root=NULL; + nodes=NULL; + sequenced=false; +} + +VisualScriptExpression::~VisualScriptExpression() { + + if (nodes) { + memdelete(nodes); + } +} + + +void register_visual_script_expression_node() { + + VisualScriptLanguage::singleton->add_register_func("operators/expression",create_node_generic<VisualScriptExpression>); + +} diff --git a/modules/visual_script/visual_script_expression.h b/modules/visual_script/visual_script_expression.h new file mode 100644 index 0000000000..90b955b5da --- /dev/null +++ b/modules/visual_script/visual_script_expression.h @@ -0,0 +1,269 @@ +#ifndef VISUALSCRIPTEXPRESSION_H +#define VISUALSCRIPTEXPRESSION_H + +#include "visual_script.h" + +class VisualScriptExpression : public VisualScriptNode { + + OBJ_TYPE(VisualScriptExpression,VisualScriptNode) +friend class VisualScriptNodeInstanceExpression; + + struct Input { + + Variant::Type type; + String name; + + Input() { type=Variant::NIL; } + }; + + Vector<Input> inputs; + Variant::Type output_type; + + String expression; + + bool sequenced; + int str_ofs; + bool expression_dirty; + + bool _compile_expression(); + + enum TokenType { + TK_CURLY_BRACKET_OPEN, + TK_CURLY_BRACKET_CLOSE, + TK_BRACKET_OPEN, + TK_BRACKET_CLOSE, + TK_PARENTHESIS_OPEN, + TK_PARENTHESIS_CLOSE, + TK_IDENTIFIER, + TK_SELF, + TK_CONSTANT, + TK_BASIC_TYPE, + TK_COLON, + TK_COMMA, + TK_PERIOD, + TK_OP_IN, + TK_OP_EQUAL, + TK_OP_NOT_EQUAL, + TK_OP_LESS, + TK_OP_LESS_EQUAL, + TK_OP_GREATER, + TK_OP_GREATER_EQUAL, + TK_OP_AND, + TK_OP_OR, + TK_OP_NOT, + TK_OP_ADD, + TK_OP_SUB, + TK_OP_MUL, + TK_OP_DIV, + TK_OP_MOD, + TK_OP_SHIFT_LEFT, + TK_OP_SHIFT_RIGHT, + TK_OP_BIT_AND, + TK_OP_BIT_OR, + TK_OP_BIT_XOR, + TK_OP_BIT_INVERT, + TK_EOF, + TK_ERROR, + TK_MAX + }; + + static const char* token_name[TK_MAX]; + struct Token { + + TokenType type; + Variant value; + }; + + + void _set_error(const String& p_err) { + if (error_set) + return; + error_str=p_err; + error_set=true; + } + + Error _get_token(Token& r_token); + + String error_str; + bool error_set; + + + + struct ENode { + + enum Type { + TYPE_INPUT, + TYPE_CONSTANT, + TYPE_SELF, + TYPE_OPERATOR, + TYPE_INDEX, + TYPE_NAMED_INDEX, + TYPE_ARRAY, + TYPE_DICTIONARY, + TYPE_CONSTRUCTOR, + TYPE_CALL + }; + + ENode *next; + + Type type; + + ENode() { next=NULL; } + virtual ~ENode() { if (next) { memdelete(next); } } + }; + + struct Expression { + + bool is_op; + union { + Variant::Operator op; + ENode *node; + }; + }; + + ENode* _parse_expression(); + + struct InputNode : public ENode { + + int index; + InputNode() { + type=TYPE_INPUT; + } + }; + + + struct ConstantNode : public ENode { + + Variant value; + ConstantNode() { + type=TYPE_CONSTANT; + } + }; + + struct OperatorNode : public ENode { + + Variant::Operator op; + + ENode* nodes[2]; + + OperatorNode() { + type=TYPE_OPERATOR; + } + }; + + struct SelfNode : public ENode { + + + SelfNode() { + type=TYPE_SELF; + } + }; + + struct IndexNode : public ENode { + ENode*base; + ENode*index; + + IndexNode() { + type=TYPE_INDEX; + } + }; + + struct NamedIndexNode : public ENode { + ENode*base; + StringName name; + + NamedIndexNode() { + type=TYPE_NAMED_INDEX; + } + + }; + + struct ConstructorNode : public ENode { + Variant::Type data_type; + Vector<ENode*> arguments; + + ConstructorNode() { + type=TYPE_CONSTRUCTOR; + } + }; + + struct CallNode : public ENode { + ENode*base; + StringName method; + Vector<ENode*> arguments; + + CallNode() { + type=TYPE_CALL; + } + + }; + + struct ArrayNode : public ENode { + Vector<ENode*> array; + ArrayNode() { + type=TYPE_ARRAY; + } + + }; + + struct DictionaryNode : public ENode { + Vector<ENode*> dict; + DictionaryNode() { + type=TYPE_DICTIONARY; + } + + }; + + template<class T> + T* alloc_node() { + T* node = memnew(T); + node->next=nodes; + nodes=node; + return node; + } + + ENode *root; + ENode *nodes; + + + + + +protected: + + bool _set(const StringName& p_name, const Variant& p_value); + bool _get(const StringName& p_name,Variant &r_ret) const; + void _get_property_list( List<PropertyInfo> *p_list) const; + +public: + + + virtual int get_output_sequence_port_count() const; + virtual bool has_input_sequence_port() const; + + + virtual String get_output_sequence_port_text(int p_port) const; + + + virtual int get_input_value_port_count() const; + virtual int get_output_value_port_count() const; + + + virtual PropertyInfo get_input_value_port_info(int p_idx) const; + virtual PropertyInfo get_output_value_port_info(int p_idx) const; + + virtual String get_caption() const; + virtual String get_text() const; + virtual String get_category() const { return "operators"; } + + virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); + + VisualScriptExpression(); + ~VisualScriptExpression(); +}; + + +void register_visual_script_expression_node(); + + +#endif // VISUALSCRIPTEXPRESSION_H diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index 79910aa2bd..de99beacaf 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -12,7 +12,7 @@ int VisualScriptFunctionCall::get_output_sequence_port_count() const { - if (method_cache.flags&METHOD_FLAG_CONST) + if (method_cache.flags&METHOD_FLAG_CONST || call_mode==CALL_MODE_BASIC_TYPE) return 0; else return 1; @@ -20,7 +20,7 @@ int VisualScriptFunctionCall::get_output_sequence_port_count() const { bool VisualScriptFunctionCall::has_input_sequence_port() const{ - if (method_cache.flags&METHOD_FLAG_CONST) + if (method_cache.flags&METHOD_FLAG_CONST || call_mode==CALL_MODE_BASIC_TYPE) return false; else return true; @@ -920,6 +920,18 @@ VisualScriptNodeInstance* VisualScriptFunctionCall::instance(VisualScriptInstanc instance->validate=validate; return instance; } + + +VisualScriptFunctionCall::TypeGuess VisualScriptFunctionCall::guess_output_type(TypeGuess* p_inputs, int p_output) const { + + if (p_output==0 && call_mode==CALL_MODE_INSTANCE) { + return p_inputs[0]; + } + + return VisualScriptNode::guess_output_type(p_inputs,p_output); + +} + VisualScriptFunctionCall::VisualScriptFunctionCall() { validate=true; @@ -1600,6 +1612,17 @@ VisualScriptNodeInstance* VisualScriptPropertySet::instance(VisualScriptInstance return instance; } + + +VisualScriptPropertySet::TypeGuess VisualScriptPropertySet::guess_output_type(TypeGuess* p_inputs, int p_output) const { + + if (p_output==0 && call_mode==CALL_MODE_INSTANCE) { + return p_inputs[0]; + } + + return VisualScriptNode::guess_output_type(p_inputs,p_output); + +} VisualScriptPropertySet::VisualScriptPropertySet() { call_mode=CALL_MODE_SELF; diff --git a/modules/visual_script/visual_script_func_nodes.h b/modules/visual_script/visual_script_func_nodes.h index 5367deed7f..43ef276cf4 100644 --- a/modules/visual_script/visual_script_func_nodes.h +++ b/modules/visual_script/visual_script_func_nodes.h @@ -105,6 +105,9 @@ public: virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); + virtual TypeGuess guess_output_type(TypeGuess* p_inputs, int p_output) const; + + VisualScriptFunctionCall(); }; @@ -195,6 +198,7 @@ public: virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); + virtual TypeGuess guess_output_type(TypeGuess* p_inputs, int p_output) const; VisualScriptPropertySet(); }; diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index e5436cc26c..7ada292b13 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -553,7 +553,7 @@ void VisualScriptOperator::_bind_methods() { argt+=","+Variant::get_type_name(Variant::Type(i)); } - ADD_PROPERTY(PropertyInfo(Variant::INT,"operator_value/type",PROPERTY_HINT_ENUM,types,PROPERTY_USAGE_NOEDITOR),_SCS("set_operator"),_SCS("get_operator")); + ADD_PROPERTY(PropertyInfo(Variant::INT,"operator_value/type",PROPERTY_HINT_ENUM,types),_SCS("set_operator"),_SCS("get_operator")); ADD_PROPERTY(PropertyInfo(Variant::INT,"typed_value/typed",PROPERTY_HINT_ENUM,argt),_SCS("set_typed"),_SCS("get_typed")); } @@ -1071,7 +1071,13 @@ PropertyInfo VisualScriptPreload::get_input_value_port_info(int p_idx) const{ PropertyInfo VisualScriptPreload::get_output_value_port_info(int p_idx) const{ - return PropertyInfo(Variant::OBJECT,"res"); + PropertyInfo pinfo=PropertyInfo(Variant::OBJECT,"res"); + if (preload.is_valid()) { + pinfo.hint=PROPERTY_HINT_RESOURCE_TYPE; + pinfo.hint_string=preload->get_type(); + } + + return pinfo; } @@ -1927,6 +1933,19 @@ VisualScriptNodeInstance* VisualScriptEngineSingleton::instance(VisualScriptInst return instance; } +VisualScriptEngineSingleton::TypeGuess VisualScriptEngineSingleton::guess_output_type(TypeGuess* p_inputs, int p_output) const { + + Object *obj=Globals::get_singleton()->get_singleton_object(singleton); + TypeGuess tg; + tg.type=Variant::OBJECT; + if (obj) { + tg.obj_type=obj->get_type(); + tg.script=obj->get_script(); + } + + return tg; +} + void VisualScriptEngineSingleton::_bind_methods() { @@ -2064,6 +2083,8 @@ VisualScriptNodeInstance* VisualScriptSceneNode::instance(VisualScriptInstance* } + + #ifdef TOOLS_ENABLED static Node* _find_script_node(Node* p_edited_scene,Node* p_current_node,const Ref<Script> &script) { @@ -2087,6 +2108,49 @@ static Node* _find_script_node(Node* p_edited_scene,Node* p_current_node,const R #endif +VisualScriptSceneNode::TypeGuess VisualScriptSceneNode::guess_output_type(TypeGuess* p_inputs, int p_output) const { + + + VisualScriptSceneNode::TypeGuess tg; + tg.type=Variant::OBJECT; + tg.obj_type="Node"; + +#ifdef TOOLS_ENABLED + Ref<Script> script = get_visual_script(); + if (!script.is_valid()) + return tg; + + MainLoop * main_loop = OS::get_singleton()->get_main_loop(); + if (!main_loop) + return tg; + + SceneTree *scene_tree = main_loop->cast_to<SceneTree>(); + + if (!scene_tree) + return tg; + + Node *edited_scene = scene_tree->get_edited_scene_root(); + + if (!edited_scene) + return tg; + + Node* script_node = _find_script_node(edited_scene,edited_scene,script); + + if (!script_node) + return tg; + + Node* another = script_node->get_node(path); + + if (another) { + tg.obj_type=another->get_type(); + tg.script=another->get_script(); + } +#endif + return tg; + +} + + void VisualScriptSceneNode::_validate_property(PropertyInfo& property) const { #ifdef TOOLS_ENABLED @@ -2224,6 +2288,13 @@ VisualScriptNodeInstance* VisualScriptSceneTree::instance(VisualScriptInstance* return instance; } +VisualScriptSceneTree::TypeGuess VisualScriptSceneTree::guess_output_type(TypeGuess* p_inputs, int p_output) const { + + TypeGuess tg; + tg.type=Variant::OBJECT; + tg.obj_type="SceneTree"; + return tg; +} void VisualScriptSceneTree::_validate_property(PropertyInfo& property) const { @@ -2415,6 +2486,23 @@ VisualScriptNodeInstance* VisualScriptSelf::instance(VisualScriptInstance* p_ins return instance; } +VisualScriptSelf::TypeGuess VisualScriptSelf::guess_output_type(TypeGuess* p_inputs, int p_output) const { + + VisualScriptSceneNode::TypeGuess tg; + tg.type=Variant::OBJECT; + tg.obj_type="Object"; + + Ref<Script> script = get_visual_script(); + if (!script.is_valid()) + return tg; + + tg.obj_type=script->get_instance_base_type(); + tg.script=script; + + return tg; + + +} void VisualScriptSelf::_bind_methods() { diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h index 885c73ca3d..94eeadca57 100644 --- a/modules/visual_script/visual_script_nodes.h +++ b/modules/visual_script/visual_script_nodes.h @@ -538,6 +538,9 @@ public: virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); + virtual TypeGuess guess_output_type(TypeGuess* p_inputs, int p_output) const; + + VisualScriptEngineSingleton(); }; @@ -577,6 +580,8 @@ public: virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); + virtual TypeGuess guess_output_type(TypeGuess* p_inputs, int p_output) const; + VisualScriptSceneNode(); }; @@ -613,6 +618,8 @@ public: virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); + virtual TypeGuess guess_output_type(TypeGuess* p_inputs, int p_output) const; + VisualScriptSceneTree(); }; @@ -686,6 +693,8 @@ public: virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance); + virtual TypeGuess guess_output_type(TypeGuess* p_inputs, int p_output) const; + VisualScriptSelf(); }; diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 2307b33345..8b03dbbc2d 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -425,6 +425,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { connecting_color=to->cast_to<GraphNode>()->get_connection_input_color(E->get().to_port); connecting_target=false; connecting_to=pos; + just_disconected=true; emit_signal("disconnection_request",E->get().from,E->get().from_port,E->get().to,E->get().to_port); to = get_node(String(connecting_from)); //maybe it was erased @@ -446,6 +447,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { connecting_color=gn->get_connection_output_color(j); connecting_target=false; connecting_to=pos; + just_disconected=false; return; } @@ -474,6 +476,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { connecting_color=fr->cast_to<GraphNode>()->get_connection_output_color(E->get().from_port); connecting_target=false; connecting_to=pos; + just_disconected=true; emit_signal("disconnection_request",E->get().from,E->get().from_port,E->get().to,E->get().to_port); fr = get_node(String(connecting_from)); //maybe it was erased @@ -496,6 +499,8 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { connecting_color=gn->get_connection_input_color(j); connecting_target=false; connecting_to=pos; + just_disconected=true; + return; } @@ -568,7 +573,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { } emit_signal("connection_request",from,from_slot,to,to_slot); - } else { + } else if (!just_disconected) { String from = connecting_from; int from_slot = connecting_index; Vector2 ofs = Vector2(p_ev.mouse_button.x,p_ev.mouse_button.y); @@ -1323,6 +1328,7 @@ GraphEdit::GraphEdit() { zoom_hb->add_child(snap_amount); setting_scroll_ofs=false; + just_disconected=false; diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index ed6e4ef6ac..c5174f6699 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -92,6 +92,7 @@ private: Vector2 connecting_to; String connecting_target_to; int connecting_target_index; + bool just_disconected; bool dragging; bool just_selected; diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 5ece970936..da298a795a 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -183,12 +183,39 @@ void GraphNode::_resort() { } +bool GraphNode::has_point(const Point2& p_point) const { + + if (comment) { + Ref<StyleBox> comment = get_stylebox("comment"); + Ref<Texture> resizer =get_icon("resizer"); + + if (Rect2(get_size()-resizer->get_size(), resizer->get_size()).has_point(p_point)) { + return true; + } + if (Rect2(0,0,get_size().width,comment->get_margin(MARGIN_TOP)).has_point(p_point)) { + return true; + } + + return false; + + } else { + return Control::has_point(p_point); + } +} void GraphNode::_notification(int p_what) { if (p_what==NOTIFICATION_DRAW) { - Ref<StyleBox> sb=get_stylebox(comment? "comment": (selected ? "selectedframe" : "frame")); + Ref<StyleBox> sb; + + if (comment) { + sb = get_stylebox( selected? "commentfocus" : "comment"); + + } else { + + sb = get_stylebox( selected ? "selectedframe" : "frame"); + } sb=sb->duplicate(); sb->call("set_modulate",modulate); @@ -601,6 +628,8 @@ void GraphNode::_input_event(const InputEvent& p_ev) { ERR_EXPLAIN("GraphNode must be the child of a GraphEdit node."); ERR_FAIL_COND(get_parent_control() == NULL); + print_line("INPUT EVENT BUTTON"); + if(p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) { Vector2 mpos = Vector2(p_ev.mouse_button.x,p_ev.mouse_button.y); diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h index 7357ab5a45..cbfd34f556 100644 --- a/scene/gui/graph_node.h +++ b/scene/gui/graph_node.h @@ -93,6 +93,9 @@ private: Overlay overlay; Color modulate; + + bool has_point(const Point2& p_point) const; + protected: diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 8c1233b634..03f28bef08 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -628,6 +628,7 @@ void fill_default_theme(Ref<Theme>& t,const Ref<Font> & default_font,const Ref<F Ref<StyleBoxTexture> graphsb = make_stylebox(graph_node_png,6,24,6,5,16,24,16,5); Ref<StyleBoxTexture> graphsbcomment = make_stylebox(graph_node_comment_png,6,24,6,5,16,24,16,5); + Ref<StyleBoxTexture> graphsbcommentselected = make_stylebox(graph_node_comment_focus_png,6,24,6,5,16,24,16,5); Ref<StyleBoxTexture> graphsbselected = make_stylebox(graph_node_selected_png,6,24,6,5,16,24,16,5); Ref<StyleBoxTexture> graphsbdefault = make_stylebox(graph_node_default_png,4,4,4,4,6,4,4,4); Ref<StyleBoxTexture> graphsbdeffocus = make_stylebox(graph_node_default_focus_png,4,4,4,4,6,4,4,4); @@ -641,6 +642,7 @@ void fill_default_theme(Ref<Theme>& t,const Ref<Font> & default_font,const Ref<F t->set_stylebox("defaultframe", "GraphNode", graphsbdefault ); t->set_stylebox("defaultfocus", "GraphNode", graphsbdeffocus ); t->set_stylebox("comment", "GraphNode", graphsbcomment ); + t->set_stylebox("commentfocus", "GraphNode", graphsbcommentselected ); t->set_stylebox("breakpoint", "GraphNode", graph_bpoint ); t->set_stylebox("position", "GraphNode", graph_position ); t->set_constant("separation","GraphNode", 1 *scale); diff --git a/scene/resources/default_theme/graph_node_comment_focus.png b/scene/resources/default_theme/graph_node_comment_focus.png Binary files differnew file mode 100644 index 0000000000..a4b7b5a618 --- /dev/null +++ b/scene/resources/default_theme/graph_node_comment_focus.png diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index ea68901196..73c801483f 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -119,6 +119,11 @@ static const unsigned char graph_node_comment_png[]={ }; +static const unsigned char graph_node_comment_focus_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x0,0x0,0x0,0x0,0x0,0xf9,0x43,0xbb,0x7f,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x9,0x2,0xe,0x16,0x22,0xbe,0xef,0xc2,0xe1,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x4a,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0xd7,0xbf,0x4b,0xdb,0x41,0x1c,0xc6,0xf1,0xd7,0x37,0x51,0x4,0x3,0xa,0xa2,0x20,0xd2,0xe2,0xe2,0x64,0x41,0xdc,0xdc,0xac,0xe0,0x54,0xdc,0xb2,0xe6,0x2f,0x10,0x1a,0xf0,0x4f,0x11,0x22,0xf8,0x17,0x64,0xcd,0x26,0x9d,0x1c,0x74,0x73,0x13,0x21,0x4e,0x2e,0xa5,0xa5,0x14,0xac,0x82,0x82,0x62,0xd0,0x7c,0xd3,0xa1,0x77,0x18,0x35,0xfe,0x48,0xa4,0xdb,0x3d,0x70,0xdc,0xf2,0x79,0xde,0x77,0xf7,0x39,0x38,0xee,0xc9,0xdc,0x2b,0x43,0x1,0xc5,0x30,0x67,0x1e,0xaa,0x83,0x1c,0xed,0x30,0x77,0x74,0x15,0x15,0x30,0x8a,0x9,0x4c,0x61,0xc,0xc3,0x8f,0x0,0xb7,0xb8,0xc4,0x29,0xce,0x71,0x8d,0x3c,0xae,0x5a,0xc2,0x5c,0xa3,0x5a,0x59,0xc7,0x17,0x7c,0xd0,0x5b,0x3f,0xf1,0xad,0x5c,0xab,0x6f,0xe3,0x4,0x57,0x59,0x58,0x69,0xb6,0x51,0xad,0x6c,0x62,0xed,0x77,0xf3,0xf0,0x87,0x17,0x34,0xfd,0x69,0xf1,0x23,0x76,0xca,0xb5,0xfa,0x6,0xbe,0xc7,0x33,0x4f,0x61,0xe5,0x35,0x33,0x84,0x9a,0x95,0xe0,0x29,0xc6,0x66,0x95,0xc2,0x78,0xab,0x62,0x7d,0x16,0x1,0x45,0xfd,0xab,0x18,0x1,0x9d,0x78,0x25,0x83,0xa8,0xe0,0x9d,0x4a,0x80,0x4,0x48,0x80,0x7f,0x1a,0xea,0xf1,0xda,0xc,0xe,0x38,0xd8,0xdf,0x5b,0x7d,0x8b,0x69,0x69,0xf9,0xf3,0x6e,0xba,0x85,0x4,0x48,0x80,0x4,0x48,0x80,0x4,0x48,0x80,0x4,0xf8,0xaf,0x80,0xac,0x47,0x46,0xec,0x7b,0x7,0xf9,0x0,0xde,0x3c,0x2,0x72,0xdc,0xa0,0xd5,0x87,0xb9,0x15,0x3c,0x79,0x21,0x44,0xd9,0x33,0x34,0xbb,0x3f,0x4f,0xaf,0x7c,0xb0,0x9a,0xc1,0xd3,0x8e,0xc9,0x75,0x1c,0xb,0x8d,0x6a,0x65,0xb,0xf3,0x2f,0x34,0x37,0xc7,0x71,0xb9,0x56,0xff,0x8a,0x23,0x5c,0x64,0x5d,0x11,0x6e,0xc,0x33,0x98,0xc4,0xc8,0x33,0xe1,0xbb,0x85,0x3f,0xf8,0x15,0x72,0x74,0x3b,0x7b,0xd4,0xd0,0xa1,0x98,0x7,0x9f,0xd9,0x41,0x27,0x1c,0xf9,0x6e,0xc0,0xc6,0x3f,0xd5,0x5f,0x9d,0x54,0x4e,0x15,0xfd,0xeb,0xb4,0x4f,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + static const unsigned char graph_node_default_png[]={ 0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x39,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x16,0x12,0x19,0xe,0xb,0x10,0xe,0xb,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x16,0x12,0x19,0x0,0x0,0x0,0x19,0x15,0x1c,0x24,0x1e,0x27,0x16,0x12,0x19,0xff,0xff,0xff,0x2b,0x4d,0xfd,0x66,0x0,0x0,0x0,0xf,0x74,0x52,0x4e,0x53,0x0,0x46,0x47,0x3f,0x2b,0x11,0x3,0xfd,0xd3,0xcd,0x2a,0x73,0x45,0xf8,0x3d,0x3f,0x57,0xda,0x84,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x12,0x7b,0xbc,0x6c,0x0,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xe0,0x6,0x16,0x12,0x2b,0x4,0x4e,0x1d,0x2,0xaf,0x0,0x0,0x0,0x38,0x49,0x44,0x41,0x54,0x18,0xd3,0x63,0x60,0x64,0x2,0x2,0x46,0x8,0xc9,0xcc,0xc2,0xca,0xc6,0xc0,0x8f,0x4,0xd8,0x39,0x98,0x59,0x19,0x50,0x80,0x0,0x27,0x17,0xaa,0x0,0x83,0x20,0x37,0x9a,0x0,0x3f,0xd3,0xc0,0x8,0xf0,0xa0,0x9,0xf0,0xf2,0x61,0x3a,0x1d,0xc3,0x73,0xe8,0xde,0x7,0x0,0x89,0x4d,0x2,0xf2,0x16,0xd3,0x74,0x45,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; |