Note Editor: Auto-offset nodes on insertion

Implements "Auto-offset" (called "insert offset" in code) feature for Node Editor, developed during and after LSOC :)
Idea and sponsoring by Sebastian König, blendFX, Mathias Eimann, Mikavaa, Knick Design

When you drop a node with at least one input and one output socket onto a an existing connection between two nodes, Auto-offset will, depending on the direction setting, automatically and animated move the left or right and all of its following nodes away to make room for the new node.
The direction for offsetting can be toggled while you are moving the node by pressing „T“.

The auto-offset is enabled by default but can be disabled in the header of the node-editor. The offset margin can be changed in the editing section of the User Preferences.

Thanks a lot to the sponsors, and especially to Sebastian who helped *a lot* with this. That's how users can help developing Blender!
This commit is contained in:
Julian Eisel 2015-08-01 17:39:48 +02:00
parent 31bf82c17d
commit 47bc66fc8d
21 changed files with 1356 additions and 21 deletions

View File

@ -30320,6 +30320,434 @@
stdDeviation="0.25149387"
id="feGaussianBlur17891" />
</filter>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath15455">
<rect
style="color:#000000;fill:#d8d8d8;fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
id="rect15457"
width="16"
height="16"
x="301.96045"
y="236.91833" />
</clipPath>
<mask
maskUnits="userSpaceOnUse"
id="mask15700">
<path
style="color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter15613);enable-background:new"
d="m 302.9292,245.91834 -2.4375,-1.125 -0.53125,-9.84375 19.95312,-0.0469 0.0156,9.95313 -2.9375,1.09375 0,5.96875 -14,0 z"
id="path15702"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
</mask>
<filter
color-interpolation-filters="sRGB"
inkscape:collect="always"
id="filter15613"
x="-0.092011765"
width="1.1840235"
y="-0.097762503"
height="1.1955251">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.65175"
id="feGaussianBlur15615" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient37542-55"
id="linearGradient15678"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.6025789,0,0,0.668336,262.51944,86.612922)"
x1="49.543404"
y1="230.81766"
x2="73.932747"
y2="247.27646" />
<linearGradient
id="linearGradient37542-55">
<stop
id="stop37544-61"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
<stop
id="stop37546-03"
offset="1"
style="stop-color:#ffffff;stop-opacity:1;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient319-74"
id="linearGradient15680"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9120445,0,0,1,24.780995,9.8636515)"
x1="305.12527"
y1="239.03134"
x2="308.97327"
y2="242" />
<linearGradient
id="linearGradient319-74">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop320-42" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop321-67" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient37542-55"
id="linearGradient15682"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.584271,0,0,0.661005,267.80323,78.438648)"
x1="51.682816"
y1="229.19724"
x2="73.932762"
y2="247.35141" />
<linearGradient
id="linearGradient14195">
<stop
id="stop14197"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
<stop
id="stop14199"
offset="1"
style="stop-color:#ffffff;stop-opacity:1;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient319-74"
id="linearGradient15684"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9103441,0,0,0.989031,29.299938,2.5312404)"
x1="305.12527"
y1="239.03134"
x2="307.25021"
y2="241.62509" />
<linearGradient
id="linearGradient14202">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop14204" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop14206" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient21609-6"
id="linearGradient15688"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.6025789,0,0,0.668336,273.45693,86.644181)"
x1="49.543404"
y1="230.81766"
x2="73.932747"
y2="247.27646" />
<linearGradient
id="linearGradient21609-6">
<stop
id="stop21611-3"
offset="0"
style="stop-color:black;stop-opacity:1" />
<stop
id="stop21613-0"
offset="1"
style="stop-color:white;stop-opacity:1;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient29312-0"
id="linearGradient15690"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9120445,0,0,1,35.718484,9.8949108)"
x1="305.12527"
y1="239.03134"
x2="308.97327"
y2="242" />
<linearGradient
inkscape:collect="always"
id="linearGradient29312-0">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop29314-8" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop29316-3" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient16019"
id="linearGradient15692"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0.59375,1.375)"
x1="308.85309"
y1="245.43437"
x2="314.06238"
y2="245.43437" />
<linearGradient
inkscape:collect="always"
id="linearGradient16019">
<stop
style="stop-color:#c6d7ef;stop-opacity:1"
offset="0"
id="stop16021" />
<stop
style="stop-color:#7fa4dc;stop-opacity:1"
offset="1"
id="stop16023" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient15996"
id="linearGradient15694"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0.59375,1.375)"
x1="304.86005"
y1="245.47992"
x2="310.04089"
y2="245.47992" />
<linearGradient
inkscape:collect="always"
id="linearGradient15996">
<stop
style="stop-color:#5f8dd3;stop-opacity:1"
offset="0"
id="stop15998" />
<stop
style="stop-color:#d7e3f4;stop-opacity:1"
offset="1"
id="stop16000" />
</linearGradient>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath15455-9">
<rect
style="color:#000000;fill:#d8d8d8;fill-opacity:1;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
id="rect15457-6"
width="16"
height="16"
x="301.96045"
y="236.91833" />
</clipPath>
<mask
maskUnits="userSpaceOnUse"
id="mask15700-4">
<path
style="color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.20000005000000010;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter15613-8);enable-background:new"
d="m 302.9292,245.91834 -2.4375,-1.125 -0.53125,-9.84375 19.95312,-0.0469 0.0156,9.95313 -2.9375,1.09375 0,5.96875 -14,0 z"
id="path15702-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
</mask>
<filter
color-interpolation-filters="sRGB"
inkscape:collect="always"
id="filter15613-8"
x="-0.092011765"
width="1.1840235"
y="-0.097762503"
height="1.1955251">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.65175"
id="feGaussianBlur15615-1" />
</filter>
<filter
color-interpolation-filters="sRGB"
inkscape:label="Greyscale"
id="filter15388">
<feColorMatrix
values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
id="feColorMatrix15390"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix15392" />
<feColorMatrix
id="feColorMatrix15394"
values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
in="fbSourceGraphic" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient37542-91"
id="linearGradient15371"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.6025789,0,0,0.668336,262.51944,86.612922)"
x1="49.543404"
y1="230.81766"
x2="73.932747"
y2="247.27646" />
<linearGradient
id="linearGradient37542-91">
<stop
id="stop37544-81"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
<stop
id="stop37546-75"
offset="1"
style="stop-color:#ffffff;stop-opacity:1;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient319-223"
id="linearGradient15373"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9120445,0,0,1,24.780995,9.8636515)"
x1="305.12527"
y1="239.03134"
x2="308.97327"
y2="242" />
<linearGradient
id="linearGradient319-223">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop320-84" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop321-34" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient37542-91"
id="linearGradient15375"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.584271,0,0,0.661005,267.80323,78.438648)"
x1="51.682816"
y1="229.19724"
x2="73.932762"
y2="247.35141" />
<linearGradient
id="linearGradient14275">
<stop
id="stop14277"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
<stop
id="stop14279"
offset="1"
style="stop-color:#ffffff;stop-opacity:1;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient319-223"
id="linearGradient15377"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9103441,0,0,0.989031,29.299938,2.5312404)"
x1="305.12527"
y1="239.03134"
x2="307.25021"
y2="241.62509" />
<linearGradient
id="linearGradient14282">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop14284" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop14286" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient21609-3"
id="linearGradient15379"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.6025789,0,0,0.668336,273.45693,86.644181)"
x1="49.543404"
y1="230.81766"
x2="73.932747"
y2="247.27646" />
<linearGradient
id="linearGradient21609-3">
<stop
id="stop21611-9"
offset="0"
style="stop-color:black;stop-opacity:1" />
<stop
id="stop21613-8"
offset="1"
style="stop-color:white;stop-opacity:1;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient29312-7"
id="linearGradient15381"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9120445,0,0,1,35.718484,9.8949108)"
x1="305.12527"
y1="239.03134"
x2="308.97327"
y2="242" />
<linearGradient
inkscape:collect="always"
id="linearGradient29312-7">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop29314-6" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop29316-8" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient16019-5"
id="linearGradient15384"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0.59375,1.375)"
x1="308.85309"
y1="245.43437"
x2="314.06238"
y2="245.43437" />
<linearGradient
inkscape:collect="always"
id="linearGradient16019-5">
<stop
style="stop-color:#c6d7ef;stop-opacity:1"
offset="0"
id="stop16021-1" />
<stop
style="stop-color:#7fa4dc;stop-opacity:1"
offset="1"
id="stop16023-8" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient15996-5"
id="linearGradient15386"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0.59375,1.375)"
x1="304.86005"
y1="245.47992"
x2="310.04089"
y2="245.47992" />
<linearGradient
inkscape:collect="always"
id="linearGradient15996-5">
<stop
style="stop-color:#5f8dd3;stop-opacity:1"
offset="0"
id="stop15998-9" />
<stop
style="stop-color:#d7e3f4;stop-opacity:1"
offset="1"
id="stop16000-1" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
@ -90739,6 +91167,464 @@
id="path30830"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
<g
mask="url(#mask15700)"
transform="translate(-149.97053,-18.918247)"
id="g15634"
style="display:inline;enable-background:new"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
clip-path="url(#clipPath15455)">
<rect
style="opacity:0.01000001;fill:none;stroke:#e8a930;stroke-width:2.99999928;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000248;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect15636"
width="1.9930685"
height="1.9947703"
x="309.50693"
y="239.5"
ry="0.99734437"
rx="0.98426884" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.99999946;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect15638"
width="7.9999909"
height="8.000001"
x="299.4917"
y="247.35583"
ry="1.5185405"
rx="1.7691951"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<rect
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
rx="0.0128693"
ry="0.010695697"
y="247.85583"
x="299.9917"
height="7.000001"
width="6.9999909"
id="rect15640"
style="fill:url(#linearGradient15678);fill-opacity:1;fill-rule:nonzero;stroke:none" />
<rect
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
rx="1.5194846"
ry="1.4892343"
y="237.42615"
x="305.49991"
height="6.9921885"
width="8.9605312"
id="rect15642"
style="fill:none;stroke:#000000;stroke-width:0.99999958;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="rect15644"
width="5.0000091"
height="0.99999899"
x="300.9917"
y="248.85583"
ry="0.0053478414"
rx="0.0086254831"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<rect
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
rx="0"
ry="0"
y="248.35583"
x="300.4917"
height="6.000001"
width="5.9999909"
id="rect15646"
style="opacity:0.8;fill:none;stroke:url(#linearGradient15680);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
style="fill:url(#linearGradient15682);fill-opacity:1;fill-rule:nonzero;stroke:none"
id="rect15648"
width="7.9604402"
height="5.9921885"
x="306"
y="237.92615"
ry="0"
rx="0"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<rect
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
rx="0.0071879062"
ry="0.0053478414"
y="238.92615"
x="306.98389"
height="0.99218851"
width="5.9765534"
id="rect15650"
style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<rect
style="opacity:0.8;fill:none;stroke:url(#linearGradient15684);stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect15652"
width="5.9604402"
height="4.0030832"
x="306.5"
y="238.41525"
ry="0"
rx="0"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<rect
rx="0"
style="fill:#ffb72a;fill-opacity:1;fill-rule:nonzero;stroke:#553800;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000248;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect15654"
width="2"
height="1.9882908"
x="313.45264"
y="240.50037"
ry="0" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.99999946;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
id="rect15656"
width="8.9614162"
height="7.9608927"
x="312.43652"
y="247.39494"
ry="1.5185405"
rx="1.7691951"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<rect
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
rx="0.0128693"
ry="0.010695697"
y="247.8949"
x="312.93652"
height="6.9609385"
width="7.9614167"
id="rect15658"
style="fill:url(#linearGradient15688);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new" />
<rect
style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
id="rect15660"
width="5.9614167"
height="0.96093851"
x="313.93652"
y="248.8949"
ry="0.0053478414"
rx="0.0086254831"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<rect
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
rx="0"
ry="0"
y="248.395"
x="313.43652"
height="5.9608316"
width="6.9614167"
id="rect15662"
style="opacity:0.8;fill:none;stroke:url(#linearGradient15690);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new" />
<rect
rx="0"
style="fill:#ffb72a;fill-opacity:1;fill-rule:nonzero;stroke:#553800;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000248;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect15664"
width="2"
height="1.9882908"
x="304.42139"
y="240.46912"
ry="0" />
<path
style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
d="m 304.05985,242.89398 5.95666,5.92541"
id="path15666"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
d="m 316.05011,242.91732 -6.03144,5.909"
id="path15668"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="cc"
id="path15670"
d="m 315.98761,242.94305 -5.93475,5.88889"
style="fill:none;stroke:url(#linearGradient15692);stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="cc"
id="path15672"
d="m 304.05985,242.89398 5.96875,5.95312"
style="fill:none;stroke:url(#linearGradient15694);stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
inkscape:connector-curvature="0" />
<ellipse
sodipodi:ry="0.61330098"
sodipodi:rx="0.59120387"
sodipodi:cy="242.89087"
sodipodi:cx="304.0946"
style="opacity:0.51799999;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="ellipse15674"
cx="304.0946"
cy="242.89087"
rx="0.59120387"
ry="0.61330098"
d="m 304.68581,242.89087 c 0,0.33872 -0.26469,0.6133 -0.59121,0.6133 -0.32651,0 -0.5912,-0.27458 -0.5912,-0.6133 0,-0.33872 0.26469,-0.6133 0.5912,-0.6133 0.32652,0 0.59121,0.27458 0.59121,0.6133 z" />
<ellipse
sodipodi:ry="0.61330098"
sodipodi:rx="0.59120387"
sodipodi:cy="242.95337"
sodipodi:cx="315.98523"
style="opacity:0.51799999;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="ellipse15676"
cx="315.98523"
cy="242.95337"
rx="0.59120387"
ry="0.61330098"
d="m 316.57643,242.95337 c 0,0.33872 -0.26469,0.6133 -0.5912,0.6133 -0.32651,0 -0.5912,-0.27458 -0.5912,-0.6133 0,-0.33872 0.26469,-0.6133 0.5912,-0.6133 0.32651,0 0.5912,0.27458 0.5912,0.6133 z" />
</g>
<g
clip-path="url(#clipPath15455-9)"
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\g42357.png"
style="opacity:0.65;display:inline;filter:url(#filter15388);enable-background:new"
id="g15325"
transform="translate(-170.98527,-18.905399)"
mask="url(#mask15700-4)">
<rect
rx="0.98426884"
ry="0.99734437"
y="239.5"
x="309.50693"
height="1.9947703"
width="1.9930685"
id="rect15327"
style="opacity:0.01000001;fill:none;stroke:#e8a930;stroke-width:2.99999928;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000248;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
rx="1.7691951"
ry="1.5185405"
y="247.35583"
x="299.4917"
height="8.000001"
width="7.9999909"
id="rect15329"
style="fill:none;stroke:#000000;stroke-width:0.99999946;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
style="fill:url(#linearGradient15371);fill-opacity:1;fill-rule:nonzero;stroke:none"
id="rect15331"
width="6.9999909"
height="7.000001"
x="299.9917"
y="247.85583"
ry="0.010695697"
rx="0.0128693"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<rect
style="fill:none;stroke:#000000;stroke-width:0.99999958;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect15333"
width="8.9605312"
height="6.9921885"
x="305.49991"
y="237.42615"
ry="1.4892343"
rx="1.5194846"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<rect
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
rx="0.0086254831"
ry="0.0053478414"
y="248.85583"
x="300.9917"
height="0.99999899"
width="5.0000091"
id="rect15335"
style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<rect
style="opacity:0.8;fill:none;stroke:url(#linearGradient15373);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect15337"
width="5.9999909"
height="6.000001"
x="300.4917"
y="248.35583"
ry="0"
rx="0"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<rect
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
rx="0"
ry="0"
y="237.92615"
x="306"
height="5.9921885"
width="7.9604402"
id="rect15339"
style="fill:url(#linearGradient15375);fill-opacity:1;fill-rule:nonzero;stroke:none" />
<rect
style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="rect15341"
width="5.9765534"
height="0.99218851"
x="306.98389"
y="238.92615"
ry="0.0053478414"
rx="0.0071879062"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<rect
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
rx="0"
ry="0"
y="238.41525"
x="306.5"
height="4.0030832"
width="5.9604402"
id="rect15343"
style="opacity:0.8;fill:none;stroke:url(#linearGradient15377);stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
ry="0"
y="240.50037"
x="313.45264"
height="1.9882908"
width="2"
id="rect15345"
style="fill:#ffb72a;fill-opacity:1;fill-rule:nonzero;stroke:#553800;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000248;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
rx="0" />
<rect
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
rx="1.7691951"
ry="1.5185405"
y="247.39494"
x="312.43652"
height="7.9608927"
width="8.9614162"
id="rect15347"
style="fill:none;stroke:#000000;stroke-width:0.99999946;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new" />
<rect
style="fill:url(#linearGradient15379);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
id="rect15349"
width="7.9614167"
height="6.9609385"
x="312.93652"
y="247.8949"
ry="0.010695697"
rx="0.0128693"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<rect
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
rx="0.0086254831"
ry="0.0053478414"
y="248.8949"
x="313.93652"
height="0.96093851"
width="5.9614167"
id="rect15351"
style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new" />
<rect
style="opacity:0.8;fill:none;stroke:url(#linearGradient15381);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
id="rect15354"
width="6.9614167"
height="5.9608316"
x="313.43652"
y="248.395"
ry="0"
rx="0"
inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\blender's iconset.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<rect
ry="0"
y="240.46912"
x="304.42139"
height="1.9882908"
width="2"
id="rect15356"
style="fill:#ffb72a;fill-opacity:1;fill-rule:nonzero;stroke:#553800;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000248;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
rx="0" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path15358"
d="m 304.05985,242.89398 5.95666,5.92541"
style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path15360"
d="m 316.05011,242.91732 -6.03144,5.909"
style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new" />
<path
inkscape:connector-curvature="0"
style="fill:none;stroke:url(#linearGradient15384);stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
d="m 315.98761,242.94305 -5.93475,5.88889"
id="path15362"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
style="fill:none;stroke:url(#linearGradient15386);stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
d="m 304.05985,242.89398 5.96875,5.95312"
id="path15364"
sodipodi:nodetypes="cc" />
<ellipse
sodipodi:ry="0.61330098"
sodipodi:rx="0.59120387"
sodipodi:cy="242.89087"
sodipodi:cx="304.0946"
ry="0.61330098"
rx="0.59120387"
cy="242.89087"
cx="304.0946"
id="ellipse15366"
style="opacity:0.51799999;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 304.68581,242.89087 c 0,0.33872 -0.26469,0.6133 -0.59121,0.6133 -0.32651,0 -0.5912,-0.27458 -0.5912,-0.6133 0,-0.33872 0.26469,-0.6133 0.5912,-0.6133 0.32652,0 0.59121,0.27458 0.59121,0.6133 z" />
<ellipse
sodipodi:ry="0.61330098"
sodipodi:rx="0.59120387"
sodipodi:cy="242.95337"
sodipodi:cx="315.98523"
ry="0.61330098"
rx="0.59120387"
cy="242.95337"
cx="315.98523"
id="ellipse15368"
style="opacity:0.51799999;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 316.57643,242.95337 c 0,0.33872 -0.26469,0.6133 -0.5912,0.6133 -0.32651,0 -0.5912,-0.27458 -0.5912,-0.6133 0,-0.33872 0.26469,-0.6133 0.5912,-0.6133 0.32651,0 0.5912,0.27458 0.5912,0.6133 z" />
</g>
</g>
</g>
</g>

Before

Width:  |  Height:  |  Size: 4.3 MiB

After

Width:  |  Height:  |  Size: 4.4 MiB

View File

@ -125,7 +125,7 @@ class NodeAddOperator:
if self.use_transform and ('FINISHED' in result):
# removes the node again if transform is canceled
bpy.ops.transform.translate('INVOKE_DEFAULT', remove_on_cancel=True)
bpy.ops.node.translate_attach_remove_on_cancel('INVOKE_DEFAULT')
return result

View File

@ -115,6 +115,9 @@ class NODE_HT_header(Header):
layout.separator()
# Auto-offset nodes (called "insert_offset" in code)
layout.prop(snode, "use_insert_offset", text="")
# Snap
row = layout.row(align=True)
row.prop(toolsettings, "use_snap", text="")

View File

@ -313,6 +313,8 @@ class USERPREF_PT_edit(Panel):
col.separator()
col.separator()
col.separator()
col.label(text="Node Editor:")
col.prop(edit, "node_margin")
col.label(text="Animation Editors:")
col.prop(edit, "fcurve_unselected_alpha", text="F-Curve Visibility")

View File

@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 275
#define BLENDER_SUBVERSION 3
#define BLENDER_SUBVERSION 4
/* Several breakages with 270, e.g. constraint deg vs rad */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 5

View File

@ -6772,6 +6772,7 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
link_list(fd, &snode->treepath);
snode->edittree = NULL;
snode->iofsd = NULL;
BLI_listbase_clear(&snode->linkdrag);
}
else if (sl->spacetype == SPACE_TEXT) {

View File

@ -462,8 +462,10 @@ DEF_ICON(FORCE_SMOKEFLOW)
DEF_ICON(BLANK690) /* XXX 'Temperature' icon! */
DEF_ICON(BLANK691) /* XXX 'Temperature' icon! */
DEF_ICON(BLANK692) /* XXX 'Gear' icon! */
DEF_ICON(BLANK693)
DEF_ICON(BLANK694)
#endif
DEF_ICON(NODE_INSERT_ON)
DEF_ICON(NODE_INSERT_OFF)
#ifndef DEF_ICON_BLANK_SKIP
DEF_ICON(BLANK695)
DEF_ICON(BLANK696)
DEF_ICON(BLANK697)

View File

@ -2635,6 +2635,10 @@ void init_userdef_do_versions(void)
U.ndof_deadzone = 0.1;
}
if (!USER_VERSION_ATLEAST(275, 4)) {
U.node_margin = 80;
}
if (U.pixelsize == 0.0f)
U.pixelsize = 1.0f;

View File

@ -167,6 +167,8 @@ void NODE_OT_detach(struct wmOperatorType *ot);
void NODE_OT_link_viewer(struct wmOperatorType *ot);
void NODE_OT_insert_offset(wmOperatorType *ot);
/* node_edit.c */
void snode_notify(struct bContext *C, struct SpaceNode *snode);
void snode_dag_update(struct bContext *C, struct SpaceNode *snode);

View File

@ -92,6 +92,8 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_link_viewer);
WM_operatortype_append(NODE_OT_insert_offset);
WM_operatortype_append(NODE_OT_read_renderlayers);
WM_operatortype_append(NODE_OT_read_fullsamplelayers);
WM_operatortype_append(NODE_OT_render_changed);
@ -147,6 +149,17 @@ void ED_operatormacros_node(void)
mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_boolean_set(mot->ptr, "release_confirm", true);
WM_operatortype_macro_define(ot, "NODE_OT_attach");
WM_operatortype_macro_define(ot, "NODE_OT_insert_offset");
/* NODE_OT_translate_attach with remove_on_canel set to true */
ot = WM_operatortype_append_macro("NODE_OT_translate_attach_remove_on_cancel", "Move and Attach",
"Move nodes and attach to frame",
OPTYPE_UNDO | OPTYPE_REGISTER);
mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_boolean_set(mot->ptr, "release_confirm", true);
RNA_boolean_set(mot->ptr, "remove_on_cancel", true);
WM_operatortype_macro_define(ot, "NODE_OT_attach");
WM_operatortype_macro_define(ot, "NODE_OT_insert_offset");
/* Note: Currently not in a default keymap or menu due to messy keymaps
* and tricky invoke functionality.

View File

@ -37,6 +37,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_easing.h"
#include "BKE_context.h"
#include "BKE_global.h"
@ -45,6 +46,7 @@
#include "ED_node.h" /* own include */
#include "ED_screen.h"
#include "ED_render.h"
#include "ED_util.h"
#include "RNA_access.h"
#include "RNA_define.h"
@ -53,6 +55,7 @@
#include "WM_types.h"
#include "UI_view2d.h"
#include "UI_resources.h"
#include "BLF_translation.h"
@ -66,6 +69,17 @@ typedef struct bNodeListItem {
struct bNode *node;
} bNodeListItem;
typedef struct NodeInsertOfsData {
bNodeTree *ntree;
bNode *insert; /* inserted node */
bNode *prev, *next; /* prev/next node in the chain */
bNode *insert_parent;
wmTimer *anim_timer;
float offset_x; /* offset to apply to node chain */
} NodeInsertOfsData;
static int sort_nodes_locx(const void *a, const void *b)
{
const bNodeListItem *nli1 = a;
@ -1099,25 +1113,33 @@ void NODE_OT_join(wmOperatorType *ot)
/* ****************** Attach ******************* */
static int node_attach_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
static bNode *node_find_frame_to_attach(ARegion *ar, const bNodeTree *ntree, const int mouse_xy[2])
{
ARegion *ar = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
bNode *frame;
float cursor[2];
/* convert mouse coordinates to v2d space */
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]);
UI_view2d_region_to_view(&ar->v2d, UNPACK2(mouse_xy), &cursor[0], &cursor[1]);
/* check nodes front to back */
for (frame = ntree->nodes.last; frame; frame = frame->prev) {
/* skip selected, those are the nodes we want to attach */
if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT))
continue;
if (BLI_rctf_isect_pt(&frame->totr, cursor[0], cursor[1]))
break;
if (BLI_rctf_isect_pt_v(&frame->totr, cursor))
return frame;
}
return NULL;
}
static int node_attach_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
bNode *frame = node_find_frame_to_attach(ar, ntree, event->mval);
if (frame) {
bNode *node, *parent;
for (node = ntree->nodes.last; node; node = node->prev) {
@ -1371,6 +1393,312 @@ static bNodeSocket *socket_best_match(ListBase *sockets)
return NULL;
}
static bool node_parents_offset_flag_enable_cb(bNode *parent, void *UNUSED(userdata))
{
/* NODE_TEST is used to flag nodes that shouldn't be offset (again) */
parent->flag |= NODE_TEST;
return true;
}
static void node_offset_apply(bNode *node, const float offset_x)
{
/* NODE_TEST is used to flag nodes that shouldn't be offset (again) */
if ((node->flag & NODE_TEST) == 0) {
node->anim_init_locx = node->locx;
node->anim_ofsx = (offset_x / UI_DPI_FAC);
node->flag |= NODE_TEST;
}
}
static void node_parent_offset_apply(NodeInsertOfsData *data, bNode *parent, const float offset_x)
{
bNode *node;
node_offset_apply(parent, offset_x);
/* flag all childs as offset to prevent them from being offset
* separately (they've already moved with the parent) */
for (node = data->ntree->nodes.first; node; node = node->next) {
if (nodeIsChildOf(parent, node)) {
/* NODE_TEST is used to flag nodes that shouldn't be offset (again) */
node->flag |= NODE_TEST;
}
}
}
#define NODE_INSOFS_ANIM_DURATION 0.25f
/**
* Callback that applies NodeInsertOfsData.offset_x to a node or its parent, similiar
* to node_link_insert_offset_output_chain_cb below, but with slightly different logic
*/
static bool node_link_insert_offset_frame_chain_cb(
bNode *fromnode, bNode *tonode,
void *userdata,
const bool reversed)
{
NodeInsertOfsData *data = userdata;
bNode *ofs_node = reversed ? fromnode : tonode;
if (ofs_node->parent && ofs_node->parent != data->insert_parent) {
node_offset_apply(ofs_node->parent, data->offset_x);
}
else {
node_offset_apply(ofs_node, data->offset_x);
}
return true;
}
/**
* Applies NodeInsertOfsData.offset_x to all childs of \a parent
*/
static void node_link_insert_offset_frame_chains(
const bNodeTree *ntree, const bNode *parent,
NodeInsertOfsData *data,
const bool reversed)
{
bNode *node;
for (node = ntree->nodes.first; node; node = node->next) {
if (nodeIsChildOf(parent, node)) {
nodeChainIter(ntree, node, node_link_insert_offset_frame_chain_cb, data, reversed);
}
}
}
/**
* Callback that applies NodeInsertOfsData.offset_x to a node or its parent,
* considering the logic needed for offseting nodes after link insert
*/
static bool node_link_insert_offset_chain_cb(
bNode *fromnode, bNode *tonode,
void *userdata,
const bool reversed)
{
NodeInsertOfsData *data = userdata;
bNode *ofs_node = reversed ? fromnode : tonode;
if (data->insert_parent) {
if (ofs_node->parent && (ofs_node->parent->flag & NODE_TEST) == 0) {
node_parent_offset_apply(data, ofs_node->parent, data->offset_x);
node_link_insert_offset_frame_chains(data->ntree, ofs_node->parent, data, reversed);
}
else {
node_offset_apply(ofs_node, data->offset_x);
}
if (nodeIsChildOf(data->insert_parent, ofs_node) == false) {
data->insert_parent = NULL;
}
}
else if (ofs_node->parent) {
bNode *node = nodeFindRootParent(ofs_node);
node_offset_apply(node, data->offset_x);
}
else {
node_offset_apply(ofs_node, data->offset_x);
}
return true;
}
static void node_link_insert_offset_ntree(
NodeInsertOfsData *iofsd, ARegion *ar,
const int mouse_xy[2], const bool right_alignment)
{
bNodeTree *ntree = iofsd->ntree;
bNode *insert = iofsd->insert;
bNode *prev = iofsd->prev, *next = iofsd->next;
bNode *init_parent = insert->parent; /* store old insert->parent for restoring later */
rctf totr_insert;
const float min_margin = U.node_margin * UI_DPI_FAC;
const float width = NODE_WIDTH(insert);
const bool needs_alignment = (next->totr.xmin - prev->totr.xmax) < (width + (min_margin * 2.0f));
float margin = width;
float dist, addval;
/* NODE_TEST will be used later, so disable for all nodes */
ntreeNodeFlagSet(ntree, NODE_TEST, false);
/* insert->totr isn't updated yet, so totr_insert is used to get the correct worldspace coords */
node_to_updated_rect(insert, &totr_insert);
/* frame attachement was't handled yet so we search the frame that the node will be attached to later */
insert->parent = node_find_frame_to_attach(ar, ntree, mouse_xy);
/* this makes sure nodes are also correctly offset when inserting a node on top of a frame
* without actually making it a part of the frame (because mouse isn't intersecting it)
* - logic here is similar to node_find_frame_to_attach */
if (!insert->parent ||
(prev->parent && (prev->parent == next->parent) && (prev->parent != insert->parent)))
{
bNode *frame;
rctf totr_frame;
/* check nodes front to back */
for (frame = ntree->nodes.last; frame; frame = frame->prev) {
/* skip selected, those are the nodes we want to attach */
if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT))
continue;
/* for some reason frame y coords aren't correct yet */
node_to_updated_rect(frame, &totr_frame);
if (BLI_rctf_isect_x(&totr_frame, totr_insert.xmin) &&
BLI_rctf_isect_x(&totr_frame, totr_insert.xmax))
{
if (BLI_rctf_isect_y(&totr_frame, totr_insert.ymin) ||
BLI_rctf_isect_y(&totr_frame, totr_insert.ymax))
{
/* frame isn't insert->parent actually, but this is needed to make offsetting
* nodes work correctly for above checked cases (it is restored later) */
insert->parent = frame;
break;
}
}
}
}
/* *** ensure offset at the left (or right for right_alignment case) of insert_node *** */
dist = right_alignment ? totr_insert.xmin - prev->totr.xmax : next->totr.xmin - totr_insert.xmax;
/* distance between insert_node and prev is smaller than min margin */
if (dist < min_margin) {
addval = (min_margin - dist) * (right_alignment ? 1.0f : -1.0f);
node_offset_apply(insert, addval);
totr_insert.xmin += addval;
totr_insert.xmax += addval;
margin += min_margin;
}
/* *** ensure offset at the right (or left for right_alignment case) of insert_node *** */
dist = right_alignment ? next->totr.xmin - totr_insert.xmax : totr_insert.xmin - prev->totr.xmax;
/* distance between insert_node and next is smaller than min margin */
if (dist < min_margin) {
addval = (min_margin - dist) * (right_alignment ? 1.0f : -1.0f);
if (needs_alignment) {
bNode *offs_node = right_alignment ? next : prev;
if (!offs_node->parent ||
offs_node->parent == insert->parent ||
nodeIsChildOf(offs_node->parent, insert))
{
node_offset_apply(offs_node, addval);
}
else if (!insert->parent && offs_node->parent) {
node_offset_apply(offs_node->parent, addval);
}
margin = addval;
}
/* enough room is available, but we want to ensure the min margin at the right */
else {
/* offset inserted node so that min margin is kept at the right */
node_offset_apply(insert, -addval);
}
}
if (needs_alignment) {
iofsd->insert_parent = insert->parent;
iofsd->offset_x = margin;
/* flag all parents of insert as offset to prevent them from being offset */
nodeParentsIter(insert, node_parents_offset_flag_enable_cb, NULL);
/* iterate over entire chain and apply offsets */
nodeChainIter(ntree, right_alignment ? next : prev, node_link_insert_offset_chain_cb, iofsd, !right_alignment);
}
insert->parent = init_parent;
}
/**
* Modal handler for insert offset animation
*/
static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
NodeInsertOfsData *iofsd = snode->iofsd;
bNode *node;
const float duration = (float)iofsd->anim_timer->duration;
if (!snode || event->type != TIMER || iofsd->anim_timer != event->customdata)
return OPERATOR_PASS_THROUGH;
/* end timer + free insert offset data */
if (duration > NODE_INSOFS_ANIM_DURATION) {
WM_event_remove_timer(CTX_wm_manager(C), NULL, iofsd->anim_timer);
for (node = snode->edittree->nodes.first; node; node = node->next) {
node->anim_init_locx = node->anim_ofsx = 0.0f;
}
snode->iofsd = NULL;
MEM_freeN(iofsd);
return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
}
/* handle animation */
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (node->anim_ofsx) {
node->locx = BLI_easing_cubic_ease_in_out(duration, node->anim_init_locx, node->anim_ofsx,
NODE_INSOFS_ANIM_DURATION);
}
}
ED_region_tag_redraw(CTX_wm_region(C));
return OPERATOR_RUNNING_MODAL;
}
#undef NODE_INSOFS_ANIM_DURATION
static int node_insert_offset_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
const SpaceNode *snode = CTX_wm_space_node(C);
NodeInsertOfsData *iofsd = snode->iofsd;
if (!iofsd || !iofsd->insert)
return OPERATOR_CANCELLED;
BLI_assert((snode->flag & SNODE_SKIP_INSOFFSET) == 0);
iofsd->ntree = snode->edittree;
iofsd->anim_timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.02);
node_link_insert_offset_ntree(
iofsd, CTX_wm_region(C),
event->mval, (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT));
/* add temp handler */
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
}
void NODE_OT_insert_offset(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Insert Offset";
ot->description = "Automatically offset nodes on insertion";
ot->idname = "NODE_OT_insert_offset";
/* callbacks */
ot->invoke = node_insert_offset_invoke;
ot->modal = node_insert_offset_modal;
ot->poll = ED_operator_node_editable;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
}
/* assumes link with NODE_LINKFLAG_HILITE set */
void ED_node_link_insert(ScrArea *sa)
{
@ -1401,6 +1729,17 @@ void ED_node_link_insert(ScrArea *sa)
nodeAddLink(snode->edittree, select, best_output, node, sockto);
/* set up insert offset data, it needs stuff from here */
if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) {
NodeInsertOfsData *iofsd = MEM_callocN(sizeof(NodeInsertOfsData), __func__);
iofsd->insert = select;
iofsd->prev = link->fromnode;
iofsd->next = node;
snode->iofsd = iofsd;
}
ntreeUpdateTree(G.main, snode->edittree); /* needed for pointers */
snode_update(snode, select);
ED_node_tag_update_id(snode->id);

View File

@ -799,6 +799,8 @@ enum {
/* for analog input, like trackpad */
TFM_MODAL_PROPSIZE = 26,
/* node editor insert offset (aka auto-offset) direction toggle */
TFM_MODAL_INSERTOFS_TOGGLE_DIR = 27,
};
/* called in transform_ops.c, on each regeneration of keymaps */
@ -831,6 +833,7 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
{TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select next Edge Slide Edge", ""},
{TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select previous Edge Slide Edge", ""},
{TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportional Influence", ""},
{TFM_MODAL_INSERTOFS_TOGGLE_DIR, "INSERTOFS_TOGGLE_DIR", 0, "Toggle Direction for Node Auto-offset", ""},
{0, NULL, 0, NULL, NULL}
};
@ -879,7 +882,10 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_DEC);
WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_INC);
WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_DEC);
/* node editor only */
WM_modalkeymap_add_item(keymap, TKEY, KM_PRESS, 0, 0, TFM_MODAL_INSERTOFS_TOGGLE_DIR);
return keymap;
}
@ -1240,6 +1246,25 @@ int transformEvent(TransInfo *t, const wmEvent *event)
handled = true;
}
break;
case TFM_MODAL_INSERTOFS_TOGGLE_DIR:
if (t->spacetype == SPACE_NODE) {
SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
BLI_assert(t->sa->spacetype == t->spacetype);
if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) {
snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_LEFT;
}
else if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_LEFT) {
snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_RIGHT;
}
else {
BLI_assert(0);
}
t->redraw |= TREDRAW_SOFT;
}
break;
/* Those two are only handled in transform's own handler, see T44634! */
case TFM_MODAL_EDGESLIDE_UP:
case TFM_MODAL_EDGESLIDE_DOWN:
@ -4246,6 +4271,23 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[MAX_INF
if (t->flag & T_PROP_EDIT_ALL) {
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
}
if (t->spacetype == SPACE_NODE) {
SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) {
const char *str_old = BLI_strdup(str);
const char *str_dir = (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) ? "right" : "left";
char str_km[MAX_INFO_LEN];
WM_modalkeymap_items_to_string(t->keymap, TFM_MODAL_INSERTOFS_TOGGLE_DIR, true, sizeof(str_km), str_km);
ofs += BLI_snprintf(str, MAX_INFO_LEN, "Auto-offset set to %s - press %s to toggle direction | %s",
str_dir, str_km, str_old);
MEM_freeN((void *)str_old);
}
}
}
static void applyTranslationValue(TransInfo *t, const float vec[3])

View File

@ -191,6 +191,8 @@ typedef struct bNode {
float width, height; /* node custom width and height */
float miniwidth; /* node width if hidden */
float offsetx, offsety; /* additional offset from loc */
float anim_init_locx; /* initial locx for insert offset animation */
float anim_ofsx; /* offset that will be added to locx for insert offset animation */
int update; /* update flags */

View File

@ -985,12 +985,17 @@ typedef struct SpaceNode {
int treetype DNA_DEPRECATED; /* treetype: as same nodetree->type */
int pad3;
short texfrom; /* texfrom object, world or brush */
short shaderfrom; /* shader from object or world */
short recalc; /* currently on 0/1, for auto compo */
short pad4;
ListBase linkdrag; /* temporary data for modal linking operator */
short texfrom; /* texfrom object, world or brush */
short shaderfrom; /* shader from object or world */
short recalc; /* currently on 0/1, for auto compo */
char insert_ofs_dir; /* direction for offsetting nodes on insertion */
char pad4;
ListBase linkdrag; /* temporary data for modal linking operator */
/* XXX hack for translate_attach op-macros to pass data from transform op to insert_offset op */
struct NodeInsertOfsData *iofsd; /* temporary data for node insert offset (in UI called Auto-offset) */
struct bGPdata *gpd; /* grease-pencil data */
} SpaceNode;
@ -1006,8 +1011,9 @@ typedef enum eSpaceNode_Flag {
SNODE_AUTO_RENDER = (1 << 5),
SNODE_SHOW_HIGHLIGHT = (1 << 6),
// SNODE_USE_HIDDEN_PREVIEW = (1 << 10), DNA_DEPRECATED December2013
SNODE_NEW_SHADERS = (1 << 11),
SNODE_NEW_SHADERS = (1 << 11),
SNODE_PIN = (1 << 12),
SNODE_SKIP_INSOFFSET = (1 << 13), /* automatically offset following nodes in a chain on insertion */
} eSpaceNode_Flag;
/* snode->texfrom */
@ -1025,6 +1031,12 @@ typedef enum eSpaceNode_ShaderFrom {
SNODE_SHADER_LINESTYLE = 2,
} eSpaceNode_ShaderFrom;
/* snode->insert_ofs_dir */
enum {
SNODE_INSERTOFS_DIR_RIGHT = 0,
SNODE_INSERTOFS_DIR_LEFT = 1,
};
/* Game Logic Editor ===================================== */
/* Logic Editor */

View File

@ -465,7 +465,8 @@ typedef struct UserDef {
int scrollback; /* console scrollback limit */
int dpi; /* range 48-128? */
char pad2[2];
char node_margin; /* node insert offset (aka auto-offset) margin, but might be useful for later stuff as well */
char pad2;
short transopts;
short menuthreshold1, menuthreshold2;

View File

@ -4095,6 +4095,12 @@ static void rna_def_space_node(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem insert_ofs_dir_items[] = {
{SNODE_INSERTOFS_DIR_RIGHT, "RIGHT", 0, "Right"},
{SNODE_INSERTOFS_DIR_LEFT, "LEFT", 0, "Left"},
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem dummy_items[] = {
{0, "DUMMY", 0, "", ""},
{0, NULL, 0, NULL, NULL}};
@ -4208,6 +4214,20 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Cursor Location", "Location for adding new nodes");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
/* insert offset (called "Auto-offset" in UI) */
prop = RNA_def_property(srna, "use_insert_offset", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNODE_SKIP_INSOFFSET);
RNA_def_property_ui_text(prop, "Auto-offset", "Automatically offset the following or previous nodes in a "
"chain when inserting a new node");
RNA_def_property_ui_icon(prop, ICON_NODE_INSERT_ON, 1);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
prop = RNA_def_property(srna, "insert_offset_direction", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "insert_ofs_dir");
RNA_def_property_enum_items(prop, insert_ofs_dir_items);
RNA_def_property_ui_text(prop, "Auto-offset Direction", "Direction to offset nodes on insertion");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
RNA_api_space_node(srna);
}

View File

@ -3848,6 +3848,12 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_duplicate_particle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_PSYS);
RNA_def_property_ui_text(prop, "Duplicate Particle", "Causes particle systems to be duplicated with the object");
/* currently only used for insert offset (aka auto-offset), maybe also be useful for later stuff though */
prop = RNA_def_property(srna, "node_margin", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "node_margin");
RNA_def_property_ui_text(prop, "Auto-offset Margin", "Minimum distance between nodes for Auto-offsetting nodes");
RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_system(BlenderRNA *brna)