Integrated as a button in toolbar, and added a simple mesh painting tool
@ -1,6 +1,6 @@
|
||||
tool
|
||||
extends Tree
|
||||
|
||||
|
||||
func get_drag_data(position):
|
||||
var selected_item = get_selected()
|
||||
if selected_item != null:
|
||||
|
@ -1,3 +1,4 @@
|
||||
tool
|
||||
extends Panel
|
||||
|
||||
var current_tab = -1
|
||||
@ -28,6 +29,7 @@ func _ready():
|
||||
new_material()
|
||||
|
||||
func create_menu(menu, menu_name):
|
||||
menu.clear()
|
||||
menu.connect("id_pressed", self, "_on_PopupMenu_id_pressed")
|
||||
for i in MENU.size():
|
||||
if MENU[i].menu != menu_name:
|
||||
@ -110,8 +112,11 @@ func export_material():
|
||||
graph_edit.export_textures(2048)
|
||||
|
||||
func quit():
|
||||
get_tree().quit()
|
||||
|
||||
if Engine.editor_hint:
|
||||
get_parent().hide()
|
||||
get_parent().queue_free()
|
||||
else:
|
||||
get_tree().quit()
|
||||
|
||||
func add_to_user_library():
|
||||
var graph_edit = $VBoxContainer/HBoxContainer/Projects.get_current_tab_control()
|
||||
|
@ -72,7 +72,7 @@ group = null
|
||||
text = "File"
|
||||
flat = true
|
||||
align = 1
|
||||
items = [ ]
|
||||
items = [ "New material", null, 0, false, false, 0, 0, null, "", false, "Load material", null, 0, false, false, 1, 268435535, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "Save material", null, 0, false, false, 3, 268435539, null, "", false, "Save material as...", null, 0, false, false, 4, 301989971, null, "", false, "Save all materials...", null, 0, false, false, 5, 0, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "Export material", null, 0, false, false, 7, 268435525, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "Close material", null, 0, false, false, 9, 0, null, "", false, "Quit", null, 0, false, false, 10, 268435537, null, "", false ]
|
||||
|
||||
[node name="Edit" type="MenuButton" parent="VBoxContainer/Menu" index="1"]
|
||||
|
||||
@ -122,7 +122,7 @@ group = null
|
||||
text = "Tools"
|
||||
flat = true
|
||||
align = 1
|
||||
items = [ ]
|
||||
items = [ "Add selected node to user library", null, 0, false, false, 11, 0, null, "", false, "Save user library", null, 0, false, false, 12, 0, null, "", false ]
|
||||
|
||||
[node name="Help" type="MenuButton" parent="VBoxContainer/Menu" index="3"]
|
||||
|
||||
@ -147,7 +147,7 @@ group = null
|
||||
text = "Help"
|
||||
flat = true
|
||||
align = 1
|
||||
items = [ ]
|
||||
items = [ "Report a bug", null, 0, false, false, 13, 0, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "About", null, 0, false, false, 15, 0, null, "", false ]
|
||||
|
||||
[node name="HBoxContainer" type="HSplitContainer" parent="VBoxContainer" index="1"]
|
||||
|
||||
@ -246,4 +246,8 @@ _sections_unfolded = [ "Size Flags" ]
|
||||
|
||||
[connection signal="tab_selected" from="VBoxContainer/HBoxContainer/Projects" to="." method="_on_Projects_tab_changed"]
|
||||
|
||||
[connection signal="connection_request" from="VBoxContainer/HBoxContainer/Projects/GraphEdit" to="VBoxContainer/HBoxContainer/Projects/GraphEdit" method="connect_node"]
|
||||
|
||||
[connection signal="disconnection_request" from="VBoxContainer/HBoxContainer/Projects/GraphEdit" to="VBoxContainer/HBoxContainer/Projects/GraphEdit" method="disconnect_node"]
|
||||
|
||||
|
||||
|
270
addons/procedural_material/paint_tool/icons/icons.svg
Normal file
@ -0,0 +1,270 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="210mm"
|
||||
height="297mm"
|
||||
viewBox="0 0 744.09448819 1052.3622047"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="icons.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.35"
|
||||
inkscape:cx="-1174.504"
|
||||
inkscape:cy="21.101772"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Calque 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g4171"
|
||||
inkscape:export-filename="paint.png"
|
||||
inkscape:export-xdpi="10.23"
|
||||
inkscape:export-ydpi="10.23">
|
||||
<rect
|
||||
ry="80"
|
||||
y="-107.63779"
|
||||
x="-1148.5714"
|
||||
height="542.85712"
|
||||
width="542.85712"
|
||||
id="rect4136"
|
||||
style="opacity:0.98999999;fill:#787878;fill-opacity:1;stroke:none;stroke-width:3.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.78025477" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4149"
|
||||
d="m -870.75149,203.83407 270.72088,-219.203106 -15.15229,-57.578695 -42.42641,-30.304579 -41.41625,-2.0203 -214.15234,265.67012 z"
|
||||
style="fill:#0500ad;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cssszc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4138"
|
||||
d="m -1091.9749,410.91533 c 14.3152,-81.6581 -13.0914,-120.15625 49.4975,-208.09142 32.8188,-46.10933 122.86561,-57.50049 155.31642,-27.01118 29.43616,27.6569 9.19363,101.31963 -11.87479,123.98582 -42.31904,45.5284 -83.39182,14.78704 -128.28943,43.43656 -44.8975,28.64951 -64.6497,67.68022 -64.6497,67.68022 z"
|
||||
style="fill:#3b3b3b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="zcscsz"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4140"
|
||||
d="m -1054.3328,210.71275 c -40.6516,35.10051 -23.8771,121.67969 -37.6426,200.20195 0,0 19.7529,-39.03017 64.6504,-67.67968 38.06432,-24.28914 77.41961,0.16299 113.07577,-21.4176 19.08717,-18.91014 1.61734,-64.34589 -17.11103,-89.6995 -27.69006,-37.48554 -82.32094,-56.50568 -122.97254,-21.40517 z"
|
||||
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4145"
|
||||
d="m -918.22867,162.41781 c 5.05077,-3.03046 65.65991,-79.802048 65.65991,-79.802048 39.85558,7.631084 47.84972,17.851418 63.63962,57.578688 l -83.84266,67.68022 c -3.3998,-22.12992 -28.89589,-33.85589 -45.45687,-45.45686 z"
|
||||
style="fill:#bcbcbc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<rect
|
||||
style="opacity:0.98999999;fill:none;fill-opacity:1;stroke:#000000;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4147"
|
||||
width="542.85712"
|
||||
height="542.85712"
|
||||
x="-1148.5714"
|
||||
y="-107.63779"
|
||||
ry="80" />
|
||||
</g>
|
||||
<g
|
||||
id="g4179"
|
||||
inkscape:export-filename="line.png"
|
||||
inkscape:export-xdpi="10.23"
|
||||
inkscape:export-ydpi="10.23">
|
||||
<rect
|
||||
style="opacity:0.98999999;fill:#787878;fill-opacity:1;stroke:none;stroke-width:3.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.78025477"
|
||||
id="rect4151"
|
||||
width="542.85712"
|
||||
height="542.85712"
|
||||
x="-1151.9188"
|
||||
y="536.92365"
|
||||
ry="80" />
|
||||
<rect
|
||||
ry="80"
|
||||
y="536.92365"
|
||||
x="-1151.9188"
|
||||
height="542.85712"
|
||||
width="542.85712"
|
||||
id="rect4161"
|
||||
style="opacity:0.98999999;fill:none;fill-opacity:1;stroke:#000000;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4163"
|
||||
d="M -1065.0895,1003.8545 -697.29497,653.54057"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:40;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="g4184"
|
||||
inkscape:export-filename="line_strip.png"
|
||||
inkscape:export-xdpi="10.23"
|
||||
inkscape:export-ydpi="10.23">
|
||||
<g
|
||||
id="g4189">
|
||||
<rect
|
||||
style="opacity:0.98999999;fill:#787878;fill-opacity:1;stroke:none;stroke-width:3.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.78025477"
|
||||
id="rect4165"
|
||||
width="542.85712"
|
||||
height="542.85712"
|
||||
x="-1156.2046"
|
||||
y="1201.2094"
|
||||
ry="80" />
|
||||
<rect
|
||||
ry="80"
|
||||
y="1201.2094"
|
||||
x="-1156.2046"
|
||||
height="542.85712"
|
||||
width="542.85712"
|
||||
id="rect4167"
|
||||
style="opacity:0.98999999;fill:none;fill-opacity:1;stroke:#000000;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4169"
|
||||
d="m -1069.3752,1668.1402 36.3686,-351.7205 270.17762,336.4487 77.46155,-344.0815 -290.49896,284.7537"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:40;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g4282"
|
||||
inkscape:export-filename="paint_s.png"
|
||||
inkscape:export-xdpi="10"
|
||||
inkscape:export-ydpi="10">
|
||||
<rect
|
||||
style="opacity:0.98999999;fill:#d8d8d8;fill-opacity:1;stroke:#b3b3b3;stroke-width:3.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4196"
|
||||
width="542.85712"
|
||||
height="542.85712"
|
||||
x="-362.85712"
|
||||
y="-139.06636"
|
||||
ry="80" />
|
||||
<path
|
||||
style="fill:#0500ad;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -85.0372,172.4055 270.72088,-219.203107 -15.15229,-57.578693 -42.42641,-30.30458 -41.41625,-2.0203 -214.15234,265.67012 z"
|
||||
id="path4198"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#3b3b3b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -306.26061,379.48676 c 14.3152,-81.6581 -13.0914,-120.15625 49.4975,-208.09142 32.8188,-46.10933 122.86561,-57.50049 155.31642,-27.01118 29.43616,27.6569 9.19363,101.31963 -11.87479,123.98582 -42.31904,45.5284 -83.39182,14.78704 -128.28943,43.43656 -44.8975,28.64951 -64.6497,67.68022 -64.6497,67.68022 z"
|
||||
id="path4200"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cssszc" />
|
||||
<path
|
||||
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -268.61851,179.28418 c -40.6516,35.10051 -23.8771,121.67969 -37.6426,200.20195 0,0 19.7529,-39.03017 64.6504,-67.67968 38.06432,-24.28914 77.41961,0.16299 113.07577,-21.4176 19.08717,-18.91014 1.61734,-64.34589 -17.11103,-89.6995 -27.69006,-37.48554 -82.32094,-56.50568 -122.97254,-21.40517 z"
|
||||
id="path4202"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="zcscsz" />
|
||||
<path
|
||||
style="fill:#bcbcbc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -132.51438,130.98924 c 5.05077,-3.03046 65.65991,-79.802049 65.65991,-79.802049 39.85558,7.631084 47.84972,17.851418 63.63962,57.578689 l -83.84266,67.68022 c -3.3998,-22.12992 -28.89589,-33.85589 -45.45687,-45.45686 z"
|
||||
id="path4204"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<rect
|
||||
ry="80"
|
||||
y="-139.06636"
|
||||
x="-362.85712"
|
||||
height="542.85712"
|
||||
width="542.85712"
|
||||
id="rect4206"
|
||||
style="opacity:0.98999999;fill:none;fill-opacity:1;stroke:#000000;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="g4277"
|
||||
inkscape:export-filename="line_s.png"
|
||||
inkscape:export-xdpi="10"
|
||||
inkscape:export-ydpi="10">
|
||||
<rect
|
||||
ry="80"
|
||||
y="505.49509"
|
||||
x="-366.20453"
|
||||
height="542.85712"
|
||||
width="542.85712"
|
||||
id="rect4210"
|
||||
style="opacity:0.98999999;fill:#d8d8d8;fill-opacity:1;stroke:#b3b3b3;stroke-width:3.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
inkscape:export-filename="line_s.png"
|
||||
inkscape:export-xdpi="10"
|
||||
inkscape:export-ydpi="10" />
|
||||
<rect
|
||||
style="opacity:0.98999999;fill:none;fill-opacity:1;stroke:#000000;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4212"
|
||||
width="542.85712"
|
||||
height="542.85712"
|
||||
x="-366.20453"
|
||||
y="505.49509"
|
||||
ry="80" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:40;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M -279.37521,972.42593 88.41932,622.112"
|
||||
id="path4214"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</g>
|
||||
<g
|
||||
id="g4271"
|
||||
inkscape:export-filename="line_strip_s.png"
|
||||
inkscape:export-xdpi="10"
|
||||
inkscape:export-ydpi="10">
|
||||
<g
|
||||
transform="translate(785.71429,-31.428571)"
|
||||
id="g4218">
|
||||
<rect
|
||||
ry="80"
|
||||
y="1201.2094"
|
||||
x="-1156.2046"
|
||||
height="542.85712"
|
||||
width="542.85712"
|
||||
id="rect4220"
|
||||
style="opacity:0.98999999;fill:#d8d8d8;fill-opacity:1;stroke:#b3b3b3;stroke-width:3.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
style="opacity:0.98999999;fill:none;fill-opacity:1;stroke:#000000;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4222"
|
||||
width="542.85712"
|
||||
height="542.85712"
|
||||
x="-1156.2046"
|
||||
y="1201.2094"
|
||||
ry="80" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:40;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m -1069.3752,1668.1402 36.3686,-351.7205 270.17762,336.4487 77.46155,-344.0815 -290.49896,284.7537"
|
||||
id="path4224"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 12 KiB |
BIN
addons/procedural_material/paint_tool/icons/line.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
addons/procedural_material/paint_tool/icons/line_s.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
addons/procedural_material/paint_tool/icons/line_strip.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
addons/procedural_material/paint_tool/icons/line_strip_s.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
addons/procedural_material/paint_tool/icons/paint.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
addons/procedural_material/paint_tool/icons/paint_s.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 762 KiB |
BIN
addons/procedural_material/paint_tool/materials/bricks_mr.png
Normal file
After Width: | Height: | Size: 110 KiB |
After Width: | Height: | Size: 1.4 MiB |
After Width: | Height: | Size: 1008 KiB |
After Width: | Height: | Size: 463 KiB |
After Width: | Height: | Size: 219 KiB |
After Width: | Height: | Size: 754 KiB |
After Width: | Height: | Size: 352 KiB |
After Width: | Height: | Size: 805 KiB |
After Width: | Height: | Size: 450 KiB |
After Width: | Height: | Size: 1.8 MiB |
287
addons/procedural_material/paint_tool/paint.gd
Normal file
@ -0,0 +1,287 @@
|
||||
tool
|
||||
extends ViewportContainer
|
||||
|
||||
const MODE_FREE = 0
|
||||
const MODE_LINE = 1
|
||||
const MODE_LINE_STRIP = 2
|
||||
|
||||
var mode = MODE_FREE
|
||||
|
||||
var brush_size = 50.0
|
||||
var brush_strength = 0.5
|
||||
var texture_albedo = null
|
||||
var texture_mr = null
|
||||
var texture_normal = null
|
||||
var texture_scale = 2.0
|
||||
|
||||
var previous_position = null
|
||||
var painting = false
|
||||
var next_paint_to = null
|
||||
|
||||
var object_name = null
|
||||
|
||||
onready var albedo_viewport = $AlbedoPaint/Viewport
|
||||
onready var mr_viewport = $MRPaint/Viewport
|
||||
onready var normal_viewport = $NormalPaint/Viewport
|
||||
onready var albedo_material = $AlbedoPaint/Viewport/ColorRect.get_material()
|
||||
onready var mr_material = $MRPaint/Viewport/ColorRect.get_material()
|
||||
onready var normal_material = $NormalPaint/Viewport/ColorRect.get_material()
|
||||
|
||||
onready var brush_material = $Brush.get_material()
|
||||
|
||||
const MATERIAL_OPTIONS = [ "none", "bricks", "metal_pattern", "rusted_metal", "wooden_floor" ]
|
||||
|
||||
signal update_material
|
||||
|
||||
func _ready():
|
||||
# add View2Texture as input of Texture2View (to ignore non-visible parts of the mesh)
|
||||
$Texture2View/Viewport/PaintedMesh.get_surface_material(0).set_shader_param("view2texture", $View2Texture/Viewport.get_texture())
|
||||
# Add Texture2View as input to all painted textures
|
||||
$FixSeams/Viewport.get_texture().flags |= Texture.FLAG_FILTER
|
||||
albedo_material.set_shader_param("tex2view_tex", $FixSeams/Viewport.get_texture())
|
||||
mr_material.set_shader_param("tex2view_tex", $FixSeams/Viewport.get_texture())
|
||||
normal_material.set_shader_param("tex2view_tex", $FixSeams/Viewport.get_texture())
|
||||
# Add all painted textures as input to themselves
|
||||
albedo_material.set_shader_param("self_tex", albedo_viewport.get_texture())
|
||||
mr_material.set_shader_param("self_tex", mr_viewport.get_texture())
|
||||
normal_material.set_shader_param("self_tex", normal_viewport.get_texture())
|
||||
# Assign all textures to painted mesh
|
||||
albedo_viewport.get_texture().flags |= Texture.FLAG_FILTER
|
||||
$Viewport/PaintedMesh.get_surface_material(0).albedo_texture = albedo_viewport.get_texture()
|
||||
mr_viewport.get_texture().flags |= Texture.FLAG_FILTER
|
||||
$Viewport/PaintedMesh.get_surface_material(0).metallic_texture = mr_viewport.get_texture()
|
||||
$Viewport/PaintedMesh.get_surface_material(0).roughness_texture = mr_viewport.get_texture()
|
||||
normal_viewport.get_texture().flags |= Texture.FLAG_FILTER
|
||||
$Viewport/PaintedMesh.get_surface_material(0).normal_texture = normal_viewport.get_texture()
|
||||
# Updated Texture2View wrt current camera position
|
||||
update_tex2view()
|
||||
# Set size of painted textures
|
||||
set_texture_size(2048)
|
||||
# update the material list
|
||||
$Material/OptionButton.clear()
|
||||
for m in MATERIAL_OPTIONS:
|
||||
$Material/OptionButton.add_item(m)
|
||||
select_material(0)
|
||||
# Initialize brush related parameters in paint shaders
|
||||
update_brush_parameters()
|
||||
|
||||
func set_mesh(n, m):
|
||||
object_name = n
|
||||
var mat
|
||||
mat = $Viewport/PaintedMesh.get_surface_material(0)
|
||||
$Viewport/PaintedMesh.mesh = m
|
||||
$Viewport/PaintedMesh.set_surface_material(0, mat)
|
||||
mat = $Texture2View/Viewport/PaintedMesh.get_surface_material(0)
|
||||
$Texture2View/Viewport/PaintedMesh.mesh = m
|
||||
$Texture2View/Viewport/PaintedMesh.set_surface_material(0, mat)
|
||||
mat = $View2Texture/Viewport/PaintedMesh.get_surface_material(0)
|
||||
$View2Texture/Viewport/PaintedMesh.mesh = m
|
||||
$View2Texture/Viewport/PaintedMesh.set_surface_material(0, mat)
|
||||
update_tex2view()
|
||||
save()
|
||||
|
||||
func set_mode(m):
|
||||
mode = m
|
||||
for i in $Tools.get_child_count():
|
||||
$Tools.get_child(i).pressed = (i == m)
|
||||
|
||||
func set_texture_size(s):
|
||||
$Texture2View/Viewport.size = Vector2(s, s)
|
||||
$FixSeams/Viewport.size = Vector2(s, s)
|
||||
$FixSeams/Viewport/TextureRect1.rect_size = Vector2(s, s)
|
||||
$FixSeams/Viewport/TextureRect2.rect_size = Vector2(s, s)
|
||||
$FixSeams/Viewport/TextureRect3.rect_size = Vector2(s, s)
|
||||
$FixSeams/Viewport/TextureRect4.rect_size = Vector2(s, s)
|
||||
$FixSeams/Viewport/TextureRect5.rect_size = Vector2(s, s)
|
||||
$AlbedoPaint/Viewport.size = Vector2(s, s)
|
||||
$AlbedoPaint/Viewport/ColorRect.rect_size = Vector2(s, s)
|
||||
$MRPaint/Viewport.size = Vector2(s, s)
|
||||
$MRPaint/Viewport/ColorRect.rect_size = Vector2(s, s)
|
||||
|
||||
func _on_Test_gui_input(ev):
|
||||
if ev is InputEventWithModifiers:
|
||||
if ev.control:
|
||||
$Texture.show()
|
||||
else:
|
||||
$Texture.hide()
|
||||
if ev is InputEventMouseMotion:
|
||||
show_brush(ev.position, previous_position)
|
||||
if ev.button_mask & BUTTON_MASK_RIGHT != 0:
|
||||
$Viewport/CameraStand.rotate_y(-0.01*ev.relative.x)
|
||||
$Viewport/CameraStand.rotate_x(-0.01*ev.relative.y)
|
||||
if ev.button_mask & BUTTON_MASK_LEFT != 0:
|
||||
if ev.control:
|
||||
previous_position = null
|
||||
texture_scale += ev.relative.x*0.1
|
||||
texture_scale = clamp(texture_scale, 0.01, 20.0)
|
||||
elif ev.shift:
|
||||
previous_position = null
|
||||
brush_size += ev.relative.x*0.1
|
||||
brush_size = clamp(brush_size, 0.0, 250.0)
|
||||
brush_strength += ev.relative.y*0.01
|
||||
brush_strength = clamp(brush_strength, 0.0, 0.999)
|
||||
update_brush_parameters()
|
||||
elif mode == MODE_FREE:
|
||||
paint(ev.position)
|
||||
elif mode != MODE_LINE_STRIP:
|
||||
previous_position = null
|
||||
elif ev is InputEventMouseButton and !ev.shift:
|
||||
var pos = ev.position
|
||||
if ev.pressed:
|
||||
var zoom = 0.0
|
||||
if ev.button_index == BUTTON_WHEEL_UP:
|
||||
zoom += 0.1
|
||||
$Viewport/CameraStand/Camera.translate(Vector3(0.0, 0.0, zoom))
|
||||
update_tex2view()
|
||||
elif ev.button_index == BUTTON_WHEEL_DOWN:
|
||||
zoom -= 0.1
|
||||
$Viewport/CameraStand/Camera.translate(Vector3(0.0, 0.0, zoom))
|
||||
update_tex2view()
|
||||
elif ev.button_index == BUTTON_LEFT:
|
||||
if mode == MODE_LINE_STRIP && previous_position != null:
|
||||
paint(pos)
|
||||
if ev.doubleclick:
|
||||
pos = null
|
||||
previous_position = pos
|
||||
else:
|
||||
if ev.button_index == BUTTON_RIGHT:
|
||||
update_tex2view()
|
||||
elif ev.button_index == BUTTON_LEFT:
|
||||
if mode != MODE_LINE_STRIP:
|
||||
paint(pos)
|
||||
previous_position = null
|
||||
|
||||
func show_brush(p, op = null):
|
||||
if op == null:
|
||||
op = p
|
||||
var position = p/rect_size
|
||||
var old_position = op/rect_size
|
||||
brush_material.set_shader_param("brush_pos", position)
|
||||
brush_material.set_shader_param("brush_ppos", old_position)
|
||||
|
||||
func update_brush_parameters():
|
||||
var brush_size_vector = Vector2(brush_size, brush_size)/rect_size
|
||||
if brush_material != null:
|
||||
brush_material.set_shader_param("brush_size", Vector2(brush_size, brush_size)/rect_size)
|
||||
brush_material.set_shader_param("brush_strength", brush_strength)
|
||||
if albedo_material != null:
|
||||
albedo_material.set_shader_param("brush_size", brush_size_vector)
|
||||
albedo_material.set_shader_param("brush_strength", brush_strength)
|
||||
if mr_material != null:
|
||||
mr_material.set_shader_param("brush_size", brush_size_vector)
|
||||
mr_material.set_shader_param("brush_strength", brush_strength)
|
||||
if normal_material != null:
|
||||
normal_material.set_shader_param("brush_size", brush_size_vector)
|
||||
normal_material.set_shader_param("brush_strength", brush_strength)
|
||||
|
||||
func paint(p):
|
||||
if painting:
|
||||
# if not available for painting, record a paint order
|
||||
next_paint_to = p
|
||||
return
|
||||
painting = true
|
||||
if previous_position == null:
|
||||
previous_position = p
|
||||
var position = p/rect_size
|
||||
var prev_position = previous_position/rect_size
|
||||
albedo_material.set_shader_param("brush_pos", position)
|
||||
albedo_material.set_shader_param("brush_ppos", prev_position)
|
||||
albedo_material.set_shader_param("brush_color", $Material/AlbedoColor.color)
|
||||
albedo_viewport.render_target_update_mode = Viewport.UPDATE_ONCE
|
||||
albedo_viewport.update_worlds()
|
||||
mr_material.set_shader_param("brush_pos", position)
|
||||
mr_material.set_shader_param("brush_ppos", prev_position)
|
||||
mr_material.set_shader_param("brush_color", $Material/MRColor.color)
|
||||
mr_viewport.render_target_update_mode = Viewport.UPDATE_ONCE
|
||||
mr_viewport.update_worlds()
|
||||
normal_material.set_shader_param("brush_pos", position)
|
||||
normal_material.set_shader_param("brush_ppos", prev_position)
|
||||
normal_viewport.render_target_update_mode = Viewport.UPDATE_ONCE
|
||||
normal_viewport.update_worlds()
|
||||
previous_position = p
|
||||
yield(get_tree(), "idle_frame")
|
||||
yield(get_tree(), "idle_frame")
|
||||
painting = false
|
||||
# execute recorded paint order if any
|
||||
if next_paint_to != null:
|
||||
p = next_paint_to
|
||||
next_paint_to = null
|
||||
paint(p)
|
||||
|
||||
func update_tex2view():
|
||||
var camera = $Viewport/CameraStand/Camera
|
||||
var transform = camera.global_transform.affine_inverse()*$Viewport/PaintedMesh.global_transform
|
||||
# View to texture
|
||||
$View2Texture/Viewport.size = $Viewport.size
|
||||
$View2Texture/Viewport/Camera.transform = camera.global_transform
|
||||
$View2Texture/Viewport.render_target_update_mode = Viewport.UPDATE_ALWAYS
|
||||
$View2Texture/Viewport.update_worlds()
|
||||
yield(get_tree(), "idle_frame")
|
||||
yield(get_tree(), "idle_frame")
|
||||
yield(get_tree(), "idle_frame")
|
||||
var t2v_shader_material = $Texture2View/Viewport/PaintedMesh.get_surface_material(0)
|
||||
t2v_shader_material.set_shader_param("model_transform", transform)
|
||||
t2v_shader_material.set_shader_param("fovy_degrees", camera.fov)
|
||||
t2v_shader_material.set_shader_param("z_near", camera.near)
|
||||
t2v_shader_material.set_shader_param("z_far", camera.far)
|
||||
t2v_shader_material.set_shader_param("aspect", rect_size.x/rect_size.y)
|
||||
$Texture2View/Viewport.render_target_update_mode = Viewport.UPDATE_ALWAYS
|
||||
$Texture2View/Viewport.update_worlds()
|
||||
yield(get_tree(), "idle_frame")
|
||||
yield(get_tree(), "idle_frame")
|
||||
yield(get_tree(), "idle_frame")
|
||||
$Texture2View/Viewport.render_target_update_mode = Viewport.UPDATE_DISABLED
|
||||
$FixSeams/Viewport.render_target_update_mode = Viewport.UPDATE_ALWAYS
|
||||
$FixSeams/Viewport.update_worlds()
|
||||
yield(get_tree(), "idle_frame")
|
||||
yield(get_tree(), "idle_frame")
|
||||
yield(get_tree(), "idle_frame")
|
||||
$FixSeams/Viewport.render_target_update_mode = Viewport.UPDATE_DISABLED
|
||||
|
||||
func load_material():
|
||||
var dialog = FileDialog.new()
|
||||
add_child(dialog)
|
||||
dialog.rect_min_size = Vector2(500, 500)
|
||||
dialog.access = FileDialog.ACCESS_FILESYSTEM
|
||||
dialog.mode = FileDialog.MODE_OPEN_FILE
|
||||
dialog.add_filter("*.paintmat;Paint material")
|
||||
dialog.connect("file_selected", self, "do_load_material")
|
||||
dialog.popup_centered()
|
||||
|
||||
func do_load_material(filename):
|
||||
pass
|
||||
|
||||
func select_material(id):
|
||||
var m = $Material/OptionButton.get_item_text(id)
|
||||
if m == "none":
|
||||
texture_albedo = null
|
||||
texture_mr = null
|
||||
texture_normal = null
|
||||
else:
|
||||
texture_albedo = load("res://addons/procedural_material/paint_tool/materials/%s_albedo.png" % m)
|
||||
texture_mr = load("res://addons/procedural_material/paint_tool/materials/%s_mr.png" % m)
|
||||
texture_normal = load("res://addons/procedural_material/paint_tool/materials/%s_normal_map.png" % m)
|
||||
albedo_material.set_shader_param("brush_texture", texture_albedo)
|
||||
mr_material.set_shader_param("brush_texture", texture_mr)
|
||||
normal_material.set_shader_param("brush_texture", texture_normal)
|
||||
|
||||
func _on_resized():
|
||||
update_brush_parameters()
|
||||
|
||||
func dump_viewport(viewport, filename):
|
||||
var viewport_texture = viewport.get_texture()
|
||||
var viewport_image = viewport_texture.get_data()
|
||||
viewport_image.save_png(filename)
|
||||
|
||||
func debug():
|
||||
dump_viewport($View2Texture/Viewport, "view2texture.png")
|
||||
dump_viewport($Texture2View/Viewport, "texture2view.png")
|
||||
dump_viewport($FixSeams/Viewport, "seamsfixed.png")
|
||||
|
||||
func save():
|
||||
var mat = $Viewport/PaintedMesh.get_surface_material(0).duplicate()
|
||||
dump_viewport($AlbedoPaint/Viewport, object_name+"_albedo.png")
|
||||
dump_viewport($MRPaint/Viewport, object_name+"_mr.png")
|
||||
dump_viewport($NormalPaint/Viewport, object_name+"_nm.png")
|
||||
emit_signal("update_material", { material=mat, albedo=object_name+"_albedo.png", mr=object_name+"_mr.png", nm=object_name+"_nm.png" })
|
||||
|
27
addons/procedural_material/paint_tool/paint.shader
Normal file
@ -0,0 +1,27 @@
|
||||
shader_type canvas_item;
|
||||
|
||||
uniform sampler2D self_tex;
|
||||
uniform sampler2D tex2view_tex;
|
||||
uniform sampler2D brush_texture : hint_white;
|
||||
uniform vec2 brush_pos = vec2(0.5, 0.5);
|
||||
uniform vec2 brush_ppos = vec2(0.5, 0.5);
|
||||
uniform vec2 brush_size = vec2(0.25, 0.25);
|
||||
uniform float brush_strength = 1.0;
|
||||
uniform vec4 brush_color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
|
||||
float brush(float v) {
|
||||
return clamp(v / (1.0-brush_strength), 0.0, 1.0);
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
vec4 t2v = texture(tex2view_tex, UV);
|
||||
vec2 xy = t2v.xy;
|
||||
vec2 b = brush_pos/brush_size;
|
||||
vec2 bv = (brush_ppos-brush_pos)/brush_size;
|
||||
vec2 p = xy/brush_size;
|
||||
float x = clamp(dot(p-b, bv)/dot(bv, bv), 0.0, 1.0);
|
||||
float a = 1.0-length(p-(b+x*bv));
|
||||
a = brush(max(0.0, a))*brush_color.w*t2v.z;
|
||||
vec4 color = brush_color*texture(brush_texture, 2.0*vec2(brush_size.y/brush_size.x, 1.0)*xy);
|
||||
COLOR = vec4(mix(texture(self_tex, UV).xyz, color.xyz, a), 1.0);
|
||||
}
|
1080
addons/procedural_material/paint_tool/paint.tscn
Normal file
28
addons/procedural_material/paint_tool/paint_nm.shader
Normal file
@ -0,0 +1,28 @@
|
||||
shader_type canvas_item;
|
||||
|
||||
uniform sampler2D self_tex;
|
||||
uniform sampler2D tex2view_tex;
|
||||
uniform sampler2D brush_texture : hint_normal;
|
||||
uniform vec2 brush_pos = vec2(0.5, 0.5);
|
||||
uniform vec2 brush_ppos = vec2(0.5, 0.5);
|
||||
uniform vec2 brush_size = vec2(0.25, 0.25);
|
||||
uniform float brush_strength = 1.0;
|
||||
|
||||
float brush(float v) {
|
||||
return clamp(v / (1.0-brush_strength), 0.0, 1.0);
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
vec4 t2v = textureLod(tex2view_tex, UV, 0.0);
|
||||
vec2 xy = t2v.xy;
|
||||
vec2 b = brush_pos/brush_size;
|
||||
vec2 bv = (brush_ppos-brush_pos)/brush_size;
|
||||
vec2 p = xy/brush_size;
|
||||
float x = clamp(dot(p-b, bv)/dot(bv, bv), 0.0, 1.0);
|
||||
float a = 1.0-length(p-(b+x*bv));
|
||||
a = brush(max(0.0, a))*t2v.z;
|
||||
vec3 old = texture(self_tex, UV).xyz;
|
||||
vec3 new = texture(brush_texture, 2.0*vec2(brush_size.y/brush_size.x, 1.0)*xy).xyz;
|
||||
vec3 color = normalize(mix(old, new, a)-vec3(0.5));
|
||||
COLOR = vec4(0.5*color+0.5, 1.0);
|
||||
}
|
8
addons/procedural_material/paint_tool/paint_window.gd
Normal file
@ -0,0 +1,8 @@
|
||||
tool
|
||||
extends WindowDialog
|
||||
|
||||
func _ready():
|
||||
pass
|
||||
|
||||
func set_object(o):
|
||||
$PaintTool.set_mesh(o.name, o.mesh)
|
28
addons/procedural_material/paint_tool/paint_window.tscn
Normal file
@ -0,0 +1,28 @@
|
||||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://addons/procedural_material/paint_tool/paint_window.gd" type="Script" id=1]
|
||||
[ext_resource path="res://addons/procedural_material/paint_tool/paint.tscn" type="PackedScene" id=2]
|
||||
|
||||
[node name="PaintWindow" type="WindowDialog" index="0"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_right = 1277.0
|
||||
margin_bottom = 721.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 0
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
popup_exclusive = true
|
||||
window_title = "Material Spray"
|
||||
resizable = true
|
||||
script = ExtResource( 1 )
|
||||
_sections_unfolded = [ "Popup" ]
|
||||
|
||||
[node name="PaintTool" parent="." index="1" instance=ExtResource( 2 )]
|
||||
|
||||
|
29
addons/procedural_material/paint_tool/pt_button.tscn
Normal file
@ -0,0 +1,29 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/procedural_material/paint_tool/icons/paint.png" type="Texture" id=1]
|
||||
|
||||
[node name="TextureButton" type="TextureButton"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_right = 24.0
|
||||
margin_bottom = 24.0
|
||||
rect_min_size = Vector2( 24, 24 )
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
focus_mode = 2
|
||||
mouse_filter = 0
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
group = null
|
||||
texture_normal = ExtResource( 1 )
|
||||
expand = true
|
||||
_sections_unfolded = [ "Rect", "Textures" ]
|
||||
|
||||
|
6
addons/procedural_material/paint_tool/show_uv.shader
Normal file
@ -0,0 +1,6 @@
|
||||
shader_type spatial;
|
||||
render_mode unshaded;
|
||||
|
||||
void fragment() {
|
||||
ALBEDO = vec3(UV, 0.0);
|
||||
}
|
21
addons/procedural_material/paint_tool/showbrush.shader
Normal file
@ -0,0 +1,21 @@
|
||||
shader_type canvas_item;
|
||||
|
||||
uniform sampler2D brush_texture : hint_albedo;
|
||||
uniform vec2 brush_pos = vec2(0.5, 0.5);
|
||||
uniform vec2 brush_ppos = vec2(0.5, 0.5);
|
||||
uniform vec2 brush_size = vec2(0.25, 0.25);
|
||||
uniform float brush_strength = 0.5;
|
||||
|
||||
float brush(float v) {
|
||||
return clamp(v / (1.0-brush_strength), 0.0, 1.0);
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
vec2 b = brush_pos/brush_size;
|
||||
vec2 bv = (brush_ppos-brush_pos)/brush_size;
|
||||
vec2 p = UV/brush_size;
|
||||
float x = clamp(dot(p-b, bv)/dot(bv, bv), 0.0, 1.0);
|
||||
float a = 1.0-length(p-(b+x*bv));
|
||||
a = brush(max(0.0, a));
|
||||
COLOR = vec4(vec3(1.0), 0.5*a);
|
||||
}
|
61
addons/procedural_material/paint_tool/texture2view.shader
Normal file
@ -0,0 +1,61 @@
|
||||
shader_type spatial;
|
||||
render_mode unshaded, cull_front;
|
||||
|
||||
uniform sampler2D view2texture;
|
||||
uniform mat4 model_transform;
|
||||
uniform float fovy_degrees = 45;
|
||||
uniform float z_near = 0.01;
|
||||
uniform float z_far = 60.0;
|
||||
uniform float aspect = 1.0;
|
||||
|
||||
varying vec4 global_position;
|
||||
varying vec3 normal;
|
||||
|
||||
mat4 get_projection_matrix() {
|
||||
float PI = 3.14159265359;
|
||||
|
||||
float rads = fovy_degrees / 2.0 * PI / 180.0;
|
||||
|
||||
float deltaZ = z_far - z_near;
|
||||
float sine = sin(rads);
|
||||
|
||||
if (deltaZ == 0.0 || sine == 0.0 || aspect == 0.0)
|
||||
return mat4(0.0);
|
||||
|
||||
float cotangent = cos(rads) / sine;
|
||||
|
||||
mat4 matrix = mat4(1.0);
|
||||
matrix[0][0] = cotangent / aspect;
|
||||
matrix[1][1] = cotangent;
|
||||
matrix[2][2] = (z_far + z_near) / deltaZ;
|
||||
matrix[2][3] = 1.0; //try +1
|
||||
matrix[3][2] = 2.0 * z_near * z_far / deltaZ;
|
||||
|
||||
matrix[3][3] = 0.0;
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
void vertex() {
|
||||
global_position = model_transform*vec4(VERTEX, 1.0);
|
||||
normal = (model_transform*vec4(NORMAL, 0.0)).xyz;
|
||||
VERTEX=vec3(UV.x, UV.y, 0.0);
|
||||
COLOR=vec4(1.0);
|
||||
}
|
||||
|
||||
vec2 fix_unshaded(vec2 xy) {
|
||||
return 0.9999857*pow(xy, vec2(2.223058));
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
vec4 color = get_projection_matrix()*vec4(global_position.xyz, 1.0);
|
||||
color.xyz /= color.w;
|
||||
vec3 xyz = vec3(0.5-0.5*color.x, 0.5+0.5*color.y, -0.5*color.z);
|
||||
vec4 v2t = textureLod(view2texture, xyz.xy, 0.0);
|
||||
vec2 delta = v2t.xy-UV.xy;
|
||||
float visible = 0.0;
|
||||
if (color.x > -1.0 && color.x < 1.0 && color.y > -1.0 && color.y < 1.0) {
|
||||
visible = clamp(10.0*dot(normalize(normal), normalize(color.xyz)), 0.0, 1.0)*max(0.0, 1.0-4.0*pow(dot(delta, delta), 0.3));
|
||||
}
|
||||
ALBEDO = vec3(fix_unshaded(xyz.xy), visible);
|
||||
}
|
21
addons/procedural_material/paint_tool/view2texture.shader
Normal file
@ -0,0 +1,21 @@
|
||||
shader_type spatial;
|
||||
render_mode unshaded;
|
||||
|
||||
/*
|
||||
0 0
|
||||
0.025 0.173
|
||||
0.05 0.247
|
||||
0.1 0.349
|
||||
0.2 0.486
|
||||
0.3 0.584
|
||||
0.4 0.663
|
||||
0.5 0.733
|
||||
1 1
|
||||
*/
|
||||
vec3 fix_unshaded(vec3 xy) {
|
||||
return 0.9999857*pow(xy, vec3(2.223058));
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
ALBEDO = fix_unshaded(vec3(UV, VERTEX.z));
|
||||
}
|
@ -1,20 +1,96 @@
|
||||
tool
|
||||
extends EditorPlugin
|
||||
|
||||
var editor = null
|
||||
var mm_button = null
|
||||
var material_maker = null
|
||||
var edited_object = null
|
||||
|
||||
var pt_button = null
|
||||
var paint_tool = null
|
||||
|
||||
func _enter_tree():
|
||||
editor = preload("res://addons/procedural_material/pm_editor.tscn").instance()
|
||||
add_control_to_bottom_panel(editor, "ProceduralMaterial")
|
||||
#material_maker = preload("res://addons/procedural_material/pm_material_maker.tscn").instance()
|
||||
#add_control_to_bottom_panel(material_maker, "ProceduralMaterial")
|
||||
print("Adding menu item")
|
||||
mm_button = Button.new()
|
||||
mm_button.connect("pressed", self, "open_material_maker")
|
||||
mm_button.text = "Material Maker"
|
||||
add_control_to_container(CONTAINER_TOOLBAR, mm_button)
|
||||
print("done")
|
||||
|
||||
func _exit_tree():
|
||||
remove_control_from_bottom_panel(editor)
|
||||
editor.queue_free()
|
||||
editor = null
|
||||
#remove_control_from_bottom_panel(material_maker)
|
||||
if mm_button != null:
|
||||
remove_control_from_container(CONTAINER_TOOLBAR, mm_button)
|
||||
mm_button.queue_free()
|
||||
if pt_button != null:
|
||||
remove_control_from_container(CONTAINER_SPATIAL_EDITOR_MENU, pt_button)
|
||||
pt_button.queue_free()
|
||||
pt_button = null
|
||||
if material_maker != null:
|
||||
material_maker.hide()
|
||||
material_maker.queue_free()
|
||||
material_maker = null
|
||||
if paint_tool != null:
|
||||
paint_tool.hide()
|
||||
paint_tool.queue_free()
|
||||
paint_tool = null
|
||||
|
||||
func _get_state():
|
||||
var s = {}
|
||||
var s = { mm_button=mm_button, material_maker=material_maker }
|
||||
return s
|
||||
|
||||
func _set_state(s):
|
||||
pass
|
||||
mm_button = s.mm_button
|
||||
material_maker = s.material_maker
|
||||
|
||||
func open_material_maker():
|
||||
material_maker = load("res://addons/procedural_material/window_dialog.tscn").instance()
|
||||
add_child(material_maker)
|
||||
material_maker.popup_centered()
|
||||
|
||||
func handles(object):
|
||||
return object is MeshInstance
|
||||
|
||||
func edit(object):
|
||||
edited_object = object
|
||||
|
||||
func make_visible(b):
|
||||
if b:
|
||||
pt_button = preload("res://addons/procedural_material/paint_tool/pt_button.tscn").instance()
|
||||
pt_button.connect("pressed", self, "paint")
|
||||
add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, pt_button)
|
||||
else:
|
||||
edited_object = null
|
||||
remove_control_from_container(CONTAINER_SPATIAL_EDITOR_MENU, pt_button)
|
||||
pt_button.queue_free()
|
||||
pt_button = null
|
||||
print(pt_button)
|
||||
|
||||
func paint():
|
||||
paint_tool = preload("res://addons/procedural_material/paint_tool/paint_window.tscn").instance()
|
||||
add_child(paint_tool)
|
||||
paint_tool.set_object(edited_object)
|
||||
paint_tool.connect("popup_hide", self, "free_paint_tool")
|
||||
paint_tool.get_node("PaintTool").connect("update_material", self, "assign_material")
|
||||
paint_tool.popup_centered()
|
||||
|
||||
func free_paint_tool():
|
||||
paint_tool.queue_free()
|
||||
paint_tool = null
|
||||
|
||||
func assign_material(m):
|
||||
var texture
|
||||
var editor_file_system = get_editor_interface().get_resource_filesystem()
|
||||
editor_file_system.scan()
|
||||
editor_file_system.update_file(m.albedo)
|
||||
texture = load(m.albedo)
|
||||
m.material.albedo_texture = texture
|
||||
editor_file_system.update_file(m.mr)
|
||||
texture = load(m.mr)
|
||||
m.material.metallic_texture = texture
|
||||
m.material.roughness_texture = texture
|
||||
editor_file_system.update_file(m.nm)
|
||||
texture = load(m.nm)
|
||||
m.material.normal_texture = texture
|
||||
edited_object.set_surface_material(0, m.material)
|
||||
|
26
addons/procedural_material/window_dialog.tscn
Normal file
@ -0,0 +1,26 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/procedural_material/main_window.tscn" type="PackedScene" id=1]
|
||||
|
||||
[node name="WindowDialog" type="WindowDialog" index="0"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_right = 1124.0
|
||||
margin_bottom = 619.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 0
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
popup_exclusive = true
|
||||
window_title = "Material Maker"
|
||||
resizable = true
|
||||
_sections_unfolded = [ "Popup" ]
|
||||
|
||||
[node name="MainWindow" parent="." index="1" instance=ExtResource( 1 )]
|
||||
|
||||
|
BIN
test/suzanne.mesh
Normal file
244
test/test.tscn
Normal file
@ -0,0 +1,244 @@
|
||||
[gd_scene load_steps=8 format=2]
|
||||
|
||||
[ext_resource path="res://test/suzanne.mesh" type="ArrayMesh" id=1]
|
||||
[ext_resource path="res://addons/procedural_material/panoramas/park.hdr" type="Texture" id=2]
|
||||
|
||||
[sub_resource type="CubeMesh" id=1]
|
||||
|
||||
custom_aabb = AABB( 0, 0, 0, 0, 0, 0 )
|
||||
size = Vector3( 2, 2, 2 )
|
||||
subdivide_width = 0
|
||||
subdivide_height = 0
|
||||
subdivide_depth = 0
|
||||
|
||||
[sub_resource type="SpatialMaterial" id=2]
|
||||
|
||||
render_priority = 0
|
||||
flags_transparent = false
|
||||
flags_unshaded = false
|
||||
flags_vertex_lighting = false
|
||||
flags_no_depth_test = false
|
||||
flags_use_point_size = false
|
||||
flags_world_triplanar = false
|
||||
flags_fixed_size = false
|
||||
flags_albedo_tex_force_srgb = false
|
||||
vertex_color_use_as_albedo = false
|
||||
vertex_color_is_srgb = false
|
||||
params_diffuse_mode = 0
|
||||
params_specular_mode = 0
|
||||
params_blend_mode = 0
|
||||
params_cull_mode = 0
|
||||
params_depth_draw_mode = 0
|
||||
params_line_width = 1.0
|
||||
params_point_size = 1.0
|
||||
params_billboard_mode = 0
|
||||
params_grow = false
|
||||
params_use_alpha_scissor = false
|
||||
albedo_color = Color( 1, 1, 1, 1 )
|
||||
metallic = 1.0
|
||||
metallic_specular = 0.5
|
||||
metallic_texture_channel = 0
|
||||
roughness = 1.0
|
||||
roughness_texture_channel = 0
|
||||
emission_enabled = false
|
||||
normal_enabled = false
|
||||
rim_enabled = false
|
||||
clearcoat_enabled = false
|
||||
anisotropy_enabled = false
|
||||
ao_enabled = false
|
||||
depth_enabled = false
|
||||
subsurf_scatter_enabled = false
|
||||
transmission_enabled = false
|
||||
refraction_enabled = false
|
||||
detail_enabled = false
|
||||
uv1_scale = Vector3( 1, 1, 1 )
|
||||
uv1_offset = Vector3( 0, 0, 0 )
|
||||
uv1_triplanar = false
|
||||
uv1_triplanar_sharpness = 1.0
|
||||
uv2_scale = Vector3( 1, 1, 1 )
|
||||
uv2_offset = Vector3( 0, 0, 0 )
|
||||
uv2_triplanar = false
|
||||
uv2_triplanar_sharpness = 1.0
|
||||
proximity_fade_enable = false
|
||||
distance_fade_enable = false
|
||||
_sections_unfolded = [ "Albedo", "Detail" ]
|
||||
|
||||
[sub_resource type="PrismMesh" id=3]
|
||||
|
||||
custom_aabb = AABB( 0, 0, 0, 0, 0, 0 )
|
||||
left_to_right = 0.5
|
||||
size = Vector3( 2, 2, 2 )
|
||||
subdivide_width = 0
|
||||
subdivide_height = 0
|
||||
subdivide_depth = 0
|
||||
|
||||
[sub_resource type="PanoramaSky" id=4]
|
||||
|
||||
radiance_size = 4
|
||||
panorama = ExtResource( 2 )
|
||||
|
||||
[sub_resource type="Environment" id=5]
|
||||
|
||||
background_mode = 2
|
||||
background_sky = SubResource( 4 )
|
||||
background_sky_custom_fov = 0.0
|
||||
background_color = Color( 0, 0, 0, 1 )
|
||||
background_energy = 1.0
|
||||
background_canvas_max_layer = 0
|
||||
ambient_light_color = Color( 0, 0, 0, 1 )
|
||||
ambient_light_energy = 1.0
|
||||
ambient_light_sky_contribution = 1.0
|
||||
fog_enabled = false
|
||||
fog_color = Color( 0.5, 0.6, 0.7, 1 )
|
||||
fog_sun_color = Color( 1, 0.9, 0.7, 1 )
|
||||
fog_sun_amount = 0.0
|
||||
fog_depth_enabled = true
|
||||
fog_depth_begin = 10.0
|
||||
fog_depth_curve = 1.0
|
||||
fog_transmit_enabled = false
|
||||
fog_transmit_curve = 1.0
|
||||
fog_height_enabled = false
|
||||
fog_height_min = 0.0
|
||||
fog_height_max = 100.0
|
||||
fog_height_curve = 1.0
|
||||
tonemap_mode = 0
|
||||
tonemap_exposure = 1.0
|
||||
tonemap_white = 1.0
|
||||
auto_exposure_enabled = false
|
||||
auto_exposure_scale = 0.4
|
||||
auto_exposure_min_luma = 0.05
|
||||
auto_exposure_max_luma = 8.0
|
||||
auto_exposure_speed = 0.5
|
||||
ss_reflections_enabled = false
|
||||
ss_reflections_max_steps = 64
|
||||
ss_reflections_fade_in = 0.15
|
||||
ss_reflections_fade_out = 2.0
|
||||
ss_reflections_depth_tolerance = 0.2
|
||||
ss_reflections_roughness = true
|
||||
ssao_enabled = false
|
||||
ssao_radius = 1.0
|
||||
ssao_intensity = 1.0
|
||||
ssao_radius2 = 0.0
|
||||
ssao_intensity2 = 1.0
|
||||
ssao_bias = 0.01
|
||||
ssao_light_affect = 0.0
|
||||
ssao_color = Color( 0, 0, 0, 1 )
|
||||
ssao_quality = 0
|
||||
ssao_blur = 3
|
||||
ssao_edge_sharpness = 4.0
|
||||
dof_blur_far_enabled = false
|
||||
dof_blur_far_distance = 10.0
|
||||
dof_blur_far_transition = 5.0
|
||||
dof_blur_far_amount = 0.1
|
||||
dof_blur_far_quality = 1
|
||||
dof_blur_near_enabled = false
|
||||
dof_blur_near_distance = 2.0
|
||||
dof_blur_near_transition = 1.0
|
||||
dof_blur_near_amount = 0.1
|
||||
dof_blur_near_quality = 1
|
||||
glow_enabled = false
|
||||
glow_levels/1 = false
|
||||
glow_levels/2 = false
|
||||
glow_levels/3 = true
|
||||
glow_levels/4 = false
|
||||
glow_levels/5 = true
|
||||
glow_levels/6 = false
|
||||
glow_levels/7 = false
|
||||
glow_intensity = 0.8
|
||||
glow_strength = 1.0
|
||||
glow_bloom = 0.19
|
||||
glow_blend_mode = 2
|
||||
glow_hdr_threshold = 1.0
|
||||
glow_hdr_scale = 2.0
|
||||
glow_bicubic_upscale = false
|
||||
adjustment_enabled = false
|
||||
adjustment_brightness = 1.0
|
||||
adjustment_contrast = 1.0
|
||||
adjustment_saturation = 1.0
|
||||
_sections_unfolded = [ "Background" ]
|
||||
|
||||
[node name="Spatial" type="Spatial" index="0"]
|
||||
|
||||
[node name="Cube" type="MeshInstance" parent="." index="0"]
|
||||
|
||||
layers = 1
|
||||
material_override = null
|
||||
cast_shadow = 1
|
||||
extra_cull_margin = 0.0
|
||||
use_in_baked_light = false
|
||||
lod_min_distance = 0.0
|
||||
lod_min_hysteresis = 0.0
|
||||
lod_max_distance = 0.0
|
||||
lod_max_hysteresis = 0.0
|
||||
mesh = SubResource( 1 )
|
||||
skeleton = NodePath("..")
|
||||
material/0 = SubResource( 2 )
|
||||
_sections_unfolded = [ "material" ]
|
||||
|
||||
[node name="Suzanne" type="MeshInstance" parent="." index="1"]
|
||||
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 1, 0 )
|
||||
layers = 1
|
||||
material_override = null
|
||||
cast_shadow = 1
|
||||
extra_cull_margin = 0.0
|
||||
use_in_baked_light = false
|
||||
lod_min_distance = 0.0
|
||||
lod_min_hysteresis = 0.0
|
||||
lod_max_distance = 0.0
|
||||
lod_max_hysteresis = 0.0
|
||||
mesh = ExtResource( 1 )
|
||||
skeleton = NodePath("..")
|
||||
material/0 = null
|
||||
_sections_unfolded = [ "material" ]
|
||||
|
||||
[node name="Prism" type="MeshInstance" parent="." index="2"]
|
||||
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -4, 0, 0 )
|
||||
layers = 1
|
||||
material_override = null
|
||||
cast_shadow = 1
|
||||
extra_cull_margin = 0.0
|
||||
use_in_baked_light = false
|
||||
lod_min_distance = 0.0
|
||||
lod_min_hysteresis = 0.0
|
||||
lod_max_distance = 0.0
|
||||
lod_max_hysteresis = 0.0
|
||||
mesh = SubResource( 3 )
|
||||
skeleton = NodePath("..")
|
||||
material/0 = SubResource( 2 )
|
||||
_sections_unfolded = [ "material" ]
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="." index="3"]
|
||||
|
||||
environment = SubResource( 5 )
|
||||
|
||||
[node name="DirectionalLight" type="DirectionalLight" parent="." index="4"]
|
||||
|
||||
transform = Transform( 1, 0, 0, 0, -4.37114e-008, 1, 0, -1, -4.37114e-008, 0, 6, 0 )
|
||||
layers = 1
|
||||
light_color = Color( 1, 1, 1, 1 )
|
||||
light_energy = 1.0
|
||||
light_indirect_energy = 1.0
|
||||
light_negative = false
|
||||
light_specular = 0.5
|
||||
light_bake_mode = 1
|
||||
light_cull_mask = -1
|
||||
shadow_enabled = false
|
||||
shadow_color = Color( 0, 0, 0, 1 )
|
||||
shadow_bias = 0.1
|
||||
shadow_contact = 0.0
|
||||
shadow_reverse_cull_face = false
|
||||
editor_only = false
|
||||
directional_shadow_mode = 2
|
||||
directional_shadow_split_1 = 0.1
|
||||
directional_shadow_split_2 = 0.2
|
||||
directional_shadow_split_3 = 0.5
|
||||
directional_shadow_blend_splits = false
|
||||
directional_shadow_normal_bias = 0.8
|
||||
directional_shadow_bias_split_scale = 0.25
|
||||
directional_shadow_depth_range = 0
|
||||
directional_shadow_max_distance = 200.0
|
||||
_sections_unfolded = [ "Light" ]
|
||||
|
||||
|