This method is called when a node is selected in the graph.
3897 {
3898 const TRUNC_TEXT = 20;
3899
3900
3902 if (!propertypanelcontent) {
3903 console.error('No property panel content widget found!');
3904 return;
3905 }
3906
3907 while (propertypanelcontent.firstChild) {
3908 propertypanelcontent.removeChild(propertypanelcontent.firstChild);
3909 }
3910
3911
3913 if (node && node.nodedef_icon) {
3914 panelIcon.src = node.nodedef_icon;
3915 }
3916 else if (this.ui.icon_map) {
3917 if (!node || node.type == 'graph/subgraph') {
3918 panelIcon.src = this.ui.icon_map['_default_graph_'];
3919 } else {
3920 panelIcon.src = this.ui.icon_map['_default_'];
3921 }
3922 }
3923
3924 propertypanelcontent.innerHTML = "";
3925
3926 let colorSpaces = this.handler.getColorSpaces();
3927 let targetUnits = this.handler.getUnits();
3928
3929 let inUnselectedNodeGraph = false
3932 inUnselectedNodeGraph = true
3933
3934
3935
3936
3937 }
3938 else if (!node && !
graphcanvas.graph._is_subgraph) {
3941
3942 for (let item of docInfo) {
3943
3944 let elem = document.createElement("div");
3945 elem.className = "row px-1 py-0";
3946 let label = document.createElement("div");
3947 label.className = "col py-0 col-form-label-sm text-left";
3948 label.style = this.fontSizeStyle;
3949 label.innerHTML = "<b>" + item[0] + "</b>";
3950 elem.appendChild(label);
3951
3952 if (item[0] == 'Colorspace' && colorSpaces.length > 0) {
3953
3954 var inputCol = document.createElement("div");
3955 inputCol.className = "col text-left";
3957 select.onchange = function (e) {
3959 }
3960 inputCol.appendChild(select);
3961 elem.appendChild(inputCol);
3962 }
3963 else if (item[0] == 'Distance' && targetUnits.length > 0) {
3964
3965 var inputCol = document.createElement("div");
3966 inputCol.className = "col text-left";
3968 select.onchange = function (e) {
3970 }
3971 inputCol.appendChild(select);
3972 elem.appendChild(inputCol);
3973 }
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985 propertypanelcontent.appendChild(elem);
3986 }
3987 return;
3988 }
3989
3990 var _category = node.nodedef_node;
3991 var _type = node.nodedef_type;
3992
3993 var isNodeGraph = node.type == 'graph/subgraph';
3994 if (isNodeGraph) {
3995
3996 _category = 'nodegraph';
3997 if (node.outputs) {
3998 if (node.outputs.length > 1) {
3999 _type = 'multi';
4000 }
4001 else if (node.outputs.length > 0) {
4002 _type = node.outputs[0].type;
4003 }
4004 }
4005 else {
4006 _type = '';
4007 }
4008 }
4009 else {
4010 if (_category == 'surfacematerial') {
4011 _type = '';
4012 }
4013 }
4014
4015
4016 var elem = document.createElement("div");
4017 elem.className = "row px-1 py-1";
4018
4019
4020 var label = document.createElement("div");
4021 label.className = "col-4 px-1 py-0 col-form-label-sm text-end";
4022 label.style = this.fontSizeStyle;
4023 label.innerHTML = "<b>" + _category;
4024 if (_type.length > 0) {
4025 label.innerHTML += '<br>' + _type;
4026 }
4027 label.innerHTML += "</b>";
4028 elem.appendChild(label);
4029
4030
4031 var inputCol = document.createElement("div");
4032 inputCol.className = "col py-0";
4033 var nameInput = document.createElement("input");
4034 nameInput.style = this.fontSizeStyle;
4035 nameInput.type = "text";
4036 nameInput.value = node.title;
4037 nameInput.className = "form-control form-control-sm";
4038 let that = this;
4039 nameInput.onchange = function (e) {
4040 var oldTitle = node.title;
4042 if (newTitle != oldTitle)
4043 {
4044 that.monitor.onNodeRenamed(node, newTitle);
4045 node.title = newTitle;
4046 }
4047 e.target.value = node.title;
4048
4049 if (node.graph._is_subgraph) {
4050 if (node.nodedef_node == 'input') {
4051
4052 node.graph.renameInput(oldTitle, node.title);
4053 }
4054 else if (node.nodedef_node == 'output') {
4055
4056 node.graph.renameOutput(oldTitle, node.title);
4057 }
4058 }
4059
4060
4061 node.setSize(node.computeSize());
4062 node.setDirtyCanvas(true, true);
4063 }
4064 inputCol.appendChild(nameInput);
4065
4066
4067 if (node.nodedef_node != 'input' && node.nodedef_node != 'output'
4068 && node.type != 'graph/subgraph') {
4069 var imagePreview = document.createElement("img");
4070 imagePreview.src = "./Icons/no_image.png";
4071 var previewSet = false;
4072
4073 imagePreview.style.display = "none";
4074 imagePreview.src = "./Icons/no_image.png";
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087 imagePreview.id = "propertypanel_preview";
4088 imagePreview.className = "img-fluid form-control form-control-sm";
4089 inputCol.appendChild(imagePreview);
4090 }
4091
4092 elem.appendChild(label);
4093 elem.appendChild(inputCol);
4094
4095
4096 if (!isNodeGraph)
4097 {
4098 var filterCol = document.createElement("div");
4099 filterCol.className = "col-2 py-0";
4100 filterCol.width = 16;
4101 var filterIcon = document.createElement("button");
4102
4103
4104 if (node.showDefaultValueInputs == null)
4105 {
4106 node.showDefaultValueInputs = true;
4107 }
4108 var img = document.createElement("img");
4109 if (node.showDefaultValueInputs)
4110 {
4111 img.src = "./Icons/funnel_white.svg";
4112 filterIcon.className = "btn btn-sm btn-outline-secondary";
4113 }
4114 else
4115 {
4116 img.src = "./Icons/funnel-fill_white.svg";
4117 filterIcon.className = "btn btn-sm btn-outline-warning";
4118 }
4119 filterIcon.appendChild(img);
4120 filterIcon.onclick = function (e) {
4121 node.showDefaultValueInputs = !node.showDefaultValueInputs;
4123 }
4124 filterCol.appendChild(filterIcon);
4125 elem.appendChild(filterCol);
4126 }
4127
4128 propertypanelcontent.appendChild(elem);
4129
4130 let hr = document.createElement("hr");
4131 hr.classList.add("my-1");
4132 propertypanelcontent.appendChild(hr);
4133
4134 let current_details = null;
4135 let first_details = true;
4136 let nodeInputs = node.inputs;
4137
4138
4139 let targetNodes = [];
4140 for (var i in nodeInputs) {
4141 let nodeInput = nodeInputs[i];
4142
4143 let inputName = nodeInput.name;
4144 let nodeInputLink = nodeInput.link;
4145 let uiName = inputName;
4146
4147 uiName = uiName.replace(/_/g, ' ');
4148 let uimin = null;
4149 let uimax = null;
4150 let colorspace = '';
4151 let units = '';
4152 let defaultgeomprop = '';
4153
4154
4155
4156 let property_info = node.getPropertyInfo(inputName);
4157 let ng_property_info = null;
4158 if (isNodeGraph)
4159 {
4160
4161 let sg = node.subgraph;
4162 if (sg)
4163 {
4164 let sg_nodes = sg._nodes;
4165 for (var sg_node of sg_nodes)
4166 {
4167 if (sg_node.title == inputName)
4168 {
4169
4170 ng_property_info = sg_node.getPropertyInfo("in");
4171 if (ng_property_info)
4172 {
4173
4174 break;
4175 }
4176 }
4177 }
4178 }
4179 }
4180
4181
4182 var skipInterorConnectedInput = false;
4183 if (node.graph._is_subgraph) {
4184
4185
4186 var sg_node = node.graph._subgraph_node;
4187 if (sg_node) {
4188
4189 var slot = sg_node.findInputSlot(node.title);
4190 if (slot != null) {
4191 if (sg_node.inputs) {
4192
4193 var slotInput = sg_node.inputs[slot];
4194
4195 if (slotInput != null && slotInput.link != null) {
4196 skipInterorConnectedInput = true;
4197 }
4198 }
4199 else {
4200
4201 }
4202 }
4203 }
4204 }
4205
4206 if (skipInterorConnectedInput) {
4207 console.log('Skip interior connected input: ', nodeInput);
4208 continue;
4209 }
4210
4211
4212 if (ng_property_info) {
4213
4214 property_info = ng_property_info;
4215 }
4216 if (property_info) {
4217
4218 if (property_info.defaultgeomprop)
4219 {
4220 defaultgeomprop = property_info.defaultgeomprop;
4221 }
4222 if (property_info.colorspace) {
4223 colorspace = property_info.colorspace;
4224 }
4225 if (property_info.unit) {
4226 units = property_info.unit;
4227 }
4228 if (property_info.uiname) {
4229 uiName = property_info.uiname;
4230 }
4231 if (property_info.uimin) {
4232 uimin = property_info.uimin;
4233 }
4234 if (property_info.uimax) {
4235 uimax = property_info.uimax;
4236 }
4237 if (property_info.uifolder && property_info.uifolder.length > 0) {
4238
4239 if (current_details == null || current_details.id != property_info.uifolder) {
4240
4241 current_details = document.createElement("details");
4242 current_details.id = property_info.uifolder;
4243 current_details.open = first_details;
4244 current_details.classList.add('w-100', 'p-1', 'border', 'border-secondary', 'rounded', 'my-1');
4245 first_details = false;
4246 var summary = document.createElement('summary')
4247 summary.style = this.fontSizeStyle;
4248 summary.innerHTML = "<b>" + property_info.uifolder + "</b>"
4249
4250 current_details.appendChild(summary);
4251
4252 }
4253 else {
4254
4255 }
4256 }
4257 else {
4258 current_details = null;
4259 }
4260
4261 }
4262 else {
4263 current_details = null;
4264 }
4265
4266 var elem = null;
4267
4268
4269 if (nodeInputLink) {
4270 let upstreamLink = null;
4271
4272 let nodegraph = node.graph;
4273 let link = nodegraph.links[nodeInputLink];
4274
4275 let linkId = link && link.origin_id;
4276 let linkNode = linkId && nodegraph.getNodeById(linkId);
4277
4278 if (linkNode) {
4279
4280
4281 let linkSlot = link.origin_slot;
4282
4283 let linkOutput = linkNode.outputs[linkSlot];
4284
4285 upstreamLink = linkNode.title + '.' + linkOutput.name;
4286
4287
4288 let id = "__pp:" + inputName;
4289 let buttonText = upstreamLink;
4290
4291 if (buttonText.length > TRUNC_TEXT) {
4292 buttonText = buttonText.substring(0, TRUNC_TEXT) + "...";
4293 }
4295
4296 input.onclick = function (e) {
4297
4298 var inputName = e.target.id;
4299 inputName = inputName.replace('__pp:', '');
4300 inputName = inputName.replace('_text', '');
4301 inputName = inputName.replace('_img', '');
4302 console.log('Clicked traversal button:', inputName);
4303
4304 console.log('Jump to node:', linkNode.title);
4308 node.setDirtyCanvas(true, true);
4309 }
4310
4311
4312 elem = document.createElement("div");
4313 elem.className = "row px-1 py-0";
4314
4315 input.id = "__pp:" + inputName;
4316
4317 var label = document.createElement("div");
4318
4319 label.className = "col-4 px-1 py-0 col-form-label-sm text-end";
4320 label.style = this.fontSizeStyle;
4321 label.innerHTML = uiName;
4322 label.for = input.id;
4323 elem.appendChild(label);
4324
4325
4326 if (useFormControl) {
4327 input.classList.add("form-control");
4328 }
4329 input.classList.add("form-control-sm");
4330
4332 input.disabled = true;
4333
4334 var propvalue = document.createElement("div");
4335 propvalue.className = "col p-1";
4336 propvalue.appendChild(input);
4337
4338 elem.appendChild(propvalue);
4339 }
4340 }
4341
4342 else {
4343
4344 targetNodes[i] = node;
4345 let targetNode = targetNodes[i];
4346 let propertyKey = inputName;
4347
4348 var property = targetNode.properties[inputName];
4349 if (property == null) {
4350 if (isNodeGraph) {
4351 var subgraph = targetNode.subgraph;
4352 if (subgraph) {
4353
4354 var subNode = subgraph.findNodeByTitle(inputName);
4355 if (subNode) {
4356 targetNodes[i] = subNode;
4357 propertyKey = 'in';
4358 property = targetNodes[i].properties['in'];
4359
4360 }
4361 }
4362 }
4363 if (property == null) {
4364 console.log('Update: Cannot find property value for input:', inputName);
4365 continue;
4366 }
4367 }
4368
4369
4370 if (defaultgeomprop)
4371 {
4372
4373 continue;
4374 }
4375
4376
4377 if (!node.showDefaultValueInputs && !isNodeGraph)
4378 {
4379 let isDefault = node.isDefaultValue(inputName);
4380 if (isDefault)
4381 {
4382 continue;
4383 }
4384 }
4385
4386
4387 elem = document.createElement("div");
4388 elem.className = "row px-1 py-0";
4389
4390 var input = null;
4391 var input_btn = null;
4392 let input_slider = null;
4393 var colorspace_unit_btn = null;
4394 var useFormControl = true;
4395
4396
4397 if (colorspace.length > 0) {
4398
4399
4400
4402 let theNode = targetNodes[i];
4403 colorspace_unit_btn.onchange = function (e) {
4404
4405 theNode.setPropertyInfo(inputName, 'colorspace', e.target.value);
4406 }
4407 }
4408 else if (units.length > 0 && property_info.unittype) {
4409
4410 colorspace_unit_btn = this.
createUnitsInput(targetUnits, property_info.unittype, units);
4411 let theNode = targetNodes[i];
4412 colorspace_unit_btn.onchange = function (e) {
4413 theNode.setPropertyInfo(inputName, 'unit', e.target.value);
4414 }
4415 }
4416
4417 let proptype = nodeInput.type;
4418 if (proptype == 'float' || proptype == 'integer') {
4419 var isFloat = proptype == 'float';
4420
4421 input = document.createElement("input");
4422 input.id = propertyKey + '_box';
4423 input.style = this.fontSizeStyle;
4424 input.type = 'number';
4425 input.classList.add("form-control", "form-control-sm", "ps-0");
4426 input.setAttribute('propertyKey', propertyKey);
4427
4428 input_slider = document.createElement("input");
4429 input_slider.id = propertyKey + '_slider';
4430
4431 input_slider.type = 'range';
4432 input_slider.classList.add('form-range', 'custom-slider', 'pe-0');
4433 input_slider.setAttribute('propertyKey', propertyKey);
4434
4435 if (uimin) {
4436 input.min = uimin;
4437 }
4438 else {
4439 input.min = Math.min(property, 0);
4440 }
4441 if (uimax) {
4442 input.max = uimax;
4443 }
4444 else {
4445 if (isFloat)
4446 {
4447 input.max = Math.max(property*3, 10.0);
4448 }
4449 else {
4450 input.max = Math.max(property*3, 100);
4451 }
4452 }
4453
4454
4455 input_slider.min = input.min;
4456 input_slider.max = input.max;
4457 if (isFloat) {
4458 input.step = (input.max - input.min) / 100.0;
4459 input_slider.step = input.step;
4460 }
4461 else {
4462 input_slider.step = 1;
4463 input.step = 1;
4464 }
4465
4466 input.value = input_slider.value = property;
4467
4468
4469
4470
4471
4472
4473
4474
4475 let theBox = input;
4476 let theSlider = input_slider;
4477 let theNode = targetNodes[i];
4478 input_slider.onchange = function (e) {
4479 var pi = e.target.getAttribute('propertyKey');
4480 var val = parseFloat(e.target.value);
4481 theNode.setProperty(pi, val);
4482
4483 }
4484 input_slider.oninput = function(e) {
4485 var pi = e.target.getAttribute('propertyKey');
4486 var val = parseFloat(e.target.value);
4487 theNode.setProperty(pi, val);
4488 theBox.value = e.target.value;
4489 }
4490
4491 input.onchange = function (e) {
4492 var pi = e.target.getAttribute('propertyKey');
4493 var val = parseFloat(e.target.value);
4494 theNode.setProperty(pi, val);
4495
4496 }
4497 input.oninput = function(e) {
4498 var pi = e.target.getAttribute('propertyKey');
4499 var val = parseFloat(e.target.value);
4500 theNode.setProperty(pi, val);
4501 theSlider.value = e.target.value;
4502 }
4503 }
4504 else if (proptype == 'string' || proptype == 'filename') {
4505 input = document.createElement("input");
4506 input.style = this.fontSizeStyle;
4507 input.type = "text";
4508 if (proptype == 'filename') {
4509 var curImage = property;
4511
4512 input_btn = document.createElement("button");
4513 input_btn.classList.add("btn", "btn-sm", "btn-outline-secondary");
4514 input_btn.innerHTML = "+";
4515 input_btn.setAttribute('propertyKey', propertyKey);
4516 var fileId = "__pp:" + inputName;
4517 let theNode = targetNodes[i];
4518 input_btn.onclick = function (e) {
4519 var pi = e.target.getAttribute('propertyKey');
4521 }
4522 }
4523
4524 else
4525 {
4526
4527
4528 if (property_info && property_info.enum) {
4529
4530
4531
4532
4533 input = document.createElement("select");
4534 input.style = this.fontSizeStyle;
4535 input.classList.add("form-control", "form-control-sm");
4536
4537 input.setAttribute('propertyKey', propertyKey);
4538 let theNode = targetNodes[i];
4539 let enums = property_info.enum;
4540 for (let j = 0; j < enums.length; j++) {
4541 let option = document.createElement("option");
4542 option.value = enums[j];
4543 option.text = enums[j];
4544 input.add(option);
4545 }
4546 input.value = property;
4547 input.setAttribute('propertyKey', propertyKey);
4548 input.onchange = function (e) {
4549 var pi = e.target.getAttribute('propertyKey');
4550 theNode.setProperty(pi, e.target.value);
4551
4552 }
4553 }
4554 }
4555
4556 if (property_info && !property_info.enm) {
4557 input.value = property;
4558 input.setAttribute('propertyKey', propertyKey);
4559 let theNode = targetNodes[i];
4560 let isFilename = proptype == 'filename';
4561 let that = this;
4562 input.onchange = function (e) {
4563 var pi = e.target.getAttribute('propertyKey');
4564
4565 theNode.setProperty(pi, e.target.value);
4566 if (isFilename) {
4567
4568 that.updateImagePreview(e.target.value);
4569 }
4570 else {
4571
4572 }
4573 }
4574 }
4575 }
4576 else if (proptype == 'boolean') {
4577
4578 input = document.createElement("input");
4579 input.style = this.fontSizeStyle;
4580 input.type = "checkbox";
4581 input.classList = "form-check-input";
4582 useFormControl = false;
4583 input.checked = property;
4584 input.setAttribute('propertyKey', propertyKey);
4585 let theNode = targetNodes[i];
4586 input.onchange = function (e) {
4587 var pi = e.target.getAttribute('propertyKey');
4588
4589 theNode.setProperty(pi, e.target.checked);
4590
4591 }
4592 }
4593
4594 else if (proptype == 'vector2' || proptype == 'vector3' || proptype == 'vector4')
4595 {
4596
4597 var vector_size = ['vector2', 'vector3', 'vector4'].indexOf(proptype) + 2;
4598 input = document.createElement("div");
4599 useFormControl = false;
4600
4601 input.className = "row py-1 ps-4 pe-0";
4602
4603 for (let v=0; v<vector_size; v++)
4604 {
4605
4606 let subinput = document.createElement("input");
4607 subinput.style = this.fontSizeStyle;
4608 subinput.type = 'number';
4609 subinput.classList.add("form-control");
4610 subinput.classList.add("form-control-sm");
4611 subinput.setAttribute('propertyKey', propertyKey);
4612
4613 let subinput_slider = document.createElement("input");
4614 subinput_slider.id = propertyKey + '_slider';
4615 subinput_slider.type = 'range';
4616 subinput_slider.classList.add('form-range', 'custom-slider', 'pe-0');
4617 subinput_slider.setAttribute('propertyKey', propertyKey);
4618
4619 if (uimin) {
4620 subinput.min = uimin[v];
4621 }
4622 else {
4623 subinput.min = Math.min(property[v]*3, 0);
4624 }
4625 if (uimax) {
4626 subinput.max = uimax[v];
4627 }
4628 else {
4629 subinput.max = Math.max(property[v]*3, 10.0);
4630 }
4631
4632 subinput_slider.min = subinput.min;
4633 subinput_slider.max = subinput.max;
4634 subinput.step = (subinput.max - subinput.min) / 100.0;
4635 subinput_slider.step = subinput.step;
4636
4637 subinput.value = subinput_slider.value = property[v];
4638
4639 let theNode = targetNodes[i];
4640 let vector_index = v;
4641 let theBox = subinput;
4642 let theSlider = subinput_slider;
4643 theBox.onchange = function (e) {
4644 let pi = e.target.getAttribute('propertyKey');
4645 let value = parseFloat(e.target.value);
4646 let newValue = theNode.properties[pi].map(item => item);
4647 newValue[vector_index] = value;
4648 theNode.setProperty(pi, newValue);
4649
4650
4651 }
4652 theBox.oninput = function(e) {
4653 let pi = e.target.getAttribute('propertyKey');
4654 let value = parseFloat(e.target.value);
4655 let newValue = theNode.properties[pi].map(item => item);
4656 newValue[vector_index] = value;
4657 theNode.setProperty(pi, newValue);
4658 theSlider.value = e.target.value;
4659 }
4660
4661 theSlider.onchange = function (e) {
4662 let pi = e.target.getAttribute('propertyKey');
4663 let value = parseFloat(e.target.value);
4664 let newValue = theNode.properties[pi].map(item => item);
4665 newValue[vector_index] = value;
4666 theNode.setProperty(pi, newValue);
4667
4668 }
4669 theSlider.oninput = function(e) {
4670 let pi = e.target.getAttribute('propertyKey');
4671 let value = parseFloat(e.target.value);
4672 let newValue = theNode.properties[pi].map(item => item);
4673 newValue[vector_index] = value;
4674 theNode.setProperty(pi, newValue);
4675 theBox.value = e.target.value;
4676 }
4677
4678
4679 let propvalue_slider = document.createElement("div");
4680 propvalue_slider.className = "col p-0";
4681 propvalue_slider.appendChild(subinput_slider);
4682
4683 let propvalue_box = document.createElement("div");
4684 propvalue_box.className = "col p-0";
4685 propvalue_box.appendChild(subinput);
4686
4687 let input_row = document.createElement("div");
4688 input_row.className = "row p-0";
4689 input_row.appendChild(propvalue_slider);
4690 input_row.appendChild(propvalue_box);
4691
4692 input.appendChild(input_row);
4693 }
4694 }
4695 else if (proptype == 'color3' || proptype == 'color4') {
4696 input = document.createElement("input");
4697 input.type = "color";
4698
4699 if (property.length == 4) {
4700 input.value = this.
rgbToHex([ property[0], property[1], property[2] ]);
4701 }
4702 else {
4703 input.value = this.
rgbToHex(property);
4704 }
4705 input.setAttribute('propertyKey', propertyKey);
4706 let theNode = targetNodes[i];
4707 input.onchange = function (e) {
4708
4709 var hex = e.target.value;
4710 let fprecision = 4
4711 let rgb = [0,0,0]
4712 rgb[0] = parseInt(hex.substring(1, 3), 16) / 255.0;
4713 rgb[0] = parseFloat(rgb[0].toFixed(fprecision));
4714 rgb[1] = parseInt(hex.substring(3, 5), 16) / 255.0;
4715 rgb[1] = parseFloat(rgb[1].toFixed(fprecision));
4716 rgb[2] = parseInt(hex.substring(5, 7), 16) / 255.0;
4717 rgb[2] = parseFloat(rgb[2].toFixed(fprecision));
4718 if (proptype == 'color4')
4719 rgb[3] = 1.0;
4720
4721 var pi = e.target.getAttribute('propertyKey');
4722 theNode.setProperty(pi, rgb);
4723 }
4724 let func = function (e) {
4725
4726 var hex = e.target.value;
4727 let rgb = [0, 0, 0];
4728 let fprecision = 4
4729 rgb[0] = parseInt(hex.substring(1, 3), 16) / 255.0;
4730 rgb[0] = parseFloat(rgb[0].toFixed(fprecision));
4731 rgb[1] = parseInt(hex.substring(3, 5), 16) / 255.0;
4732 rgb[1] = parseFloat(rgb[1].toFixed(fprecision));
4733 rgb[2] = parseInt(hex.substring(5, 7), 16) / 255.0;
4734 rgb[2] = parseFloat(rgb[2].toFixed(fprecision));
4735 if (proptype == 'color4')
4736 rgb[3] = 1.0;
4737
4738 var pi = e.target.getAttribute('propertyKey');
4739 theNode.setProperty(pi, rgb);
4740 }
4741 input.onchange = func;
4742 input.oninput = func;
4743 }
4744 else {
4745 input = document.createElement("input");
4746 input.style = this.fontSizeStyle;
4747 input.type = "text";
4748 input.value = property;
4749 let propertyKey = inputName;
4750 let theNode = targetNodes[i];
4751 input.onchange = function (e) {
4752 theNode.setProperty(propertyKey, e.target.value);
4753
4754 }
4755 }
4756
4757 if (input) {
4758 input.id = "__pp:" + inputName;
4759
4760
4761 var label = document.createElement("div");
4762 label.className = "col-4 p-0 col-form-label-sm text-end";
4763 label.style = this.fontSizeStyle;
4764 label.innerHTML = uiName;
4765 label.for = input.id;
4766 elem.appendChild(label);
4767
4768
4769 if (useFormControl) {
4770 input.classList.add("form-control");
4771 }
4772 input.classList.add("form-control-sm");
4773
4775 input.disabled = true;
4776
4777 var propvalue = document.createElement("div");
4778 propvalue.className = "col py-0";
4779 if (input_slider)
4780 {
4781 propvalue.classList.add('ps-1');
4782 }
4783 propvalue.appendChild(input);
4784
4785 if (input_btn) {
4786 var propbutton = document.createElement("div");
4787 propbutton.className = "col-2 py-0";
4788
4789 propbutton.appendChild(input_btn);
4790 elem.appendChild(propbutton);
4791 }
4792 if (colorspace_unit_btn) {
4793
4794 var propbutton = document.createElement("div");
4795 propbutton.className = "col col-form-label-sm";
4796 var details = document.createElement("details");
4797 var summary = document.createElement('summary')
4798 summary.style = this.fontSizeStyle;
4799 if (colorspace.length > 0)
4800 summary.innerHTML = "Colorspace";
4801 else if (targetUnits.length > 0)
4802 summary.innerHTML = "Units";
4803 details.appendChild(summary);
4804 details.appendChild(colorspace_unit_btn);
4805 propbutton.appendChild(details);
4806 propvalue.appendChild(propbutton);
4807 }
4808
4809 if (input_slider)
4810 {
4811 var propvalue_slider = document.createElement("div");
4812 propvalue_slider.className = "col py-0 pe-0";
4813 propvalue_slider.appendChild(input_slider);
4814 elem.appendChild(propvalue_slider);
4815 }
4816
4817 elem.appendChild(propvalue);
4818 }
4819 }
4820
4821 if (elem) {
4822 if (current_details) {
4823
4824 current_details.appendChild(elem);
4825
4826 if (current_details.parentElement == null) {
4827 propertypanelcontent.appendChild(current_details);
4828 }
4829 }
4830 else {
4831 propertypanelcontent.appendChild(elem);
4832
4833 }
4834 }
4835 }
4836
4837
4838
4839 let output_details = null;
4840 let nodeOutputs = null;
4842
4843
4844 if (!inUnselectedNodeGraph)
4845 nodeOutputs = node.outputs;
4846 for (let k in nodeOutputs) {
4847 let nodeOutput = nodeOutputs[k];
4848
4849 let nodeOutputLinks = nodeOutput.links;
4850 for (let j in nodeOutputLinks) {
4851 let link_id = nodeOutputLinks[j];
4852
4853
4854
4856
4857 if (link) {
4858 if (!output_details) {
4859 output_details = document.createElement("details");
4860 output_details.id = "pp::outputs";
4861 output_details.open = true;
4862 output_details.classList.add('w-100', 'p-1', 'border', 'border-secondary', 'rounded', 'my-1');
4863 first_details = false;
4864 var summary = document.createElement('summary');
4865 {
4866 summary.style = this.fontSizeStyle;
4867 summary.innerHTML = "<b>Outputs</b>"
4868 }
4869
4870 output_details.appendChild(summary);
4871 }
4872
4873
4874
4875 const targetNode =
graphcanvas.graph.getNodeById(link.target_id);
4876
4877 if (targetNode) {
4878
4879 let targetSlot = link.target_slot;
4880 let targetInput = targetNode.inputs[targetSlot];
4881
4882
4883 let downstreamLink = targetNode.title + '.' + targetInput.name;
4884
4885 let id = "__pp:" + nodeOutput.name;
4886 let buttonText = downstreamLink;
4887
4888 if (buttonText.length > TRUNC_TEXT) {
4889 buttonText = buttonText.substring(0, TRUNC_TEXT) + "...";
4890 }
4892
4893 output.onclick = function (e) {
4894
4895 var inputName = e.target.id;
4896 inputName = inputName.replace('__pp:', '');
4897 inputName = inputName.replace('_text', '');
4898 inputName = inputName.replace('_img', '');
4899 console.log('Clicked traversal button:', inputName);
4900
4901 console.log('Jump to node:', targetNode.title);
4905 node.setDirtyCanvas(true, true);
4906 }
4907
4908
4909 elem = document.createElement("div");
4910 elem.className = "row px-1 py-0";
4911
4912 let outputName = nodeOutput.name;
4913 output.id = "__pp:" + outputName;
4914
4915 var label = document.createElement("div");
4916
4917 label.className = "col-4 px-1 py-0 col-form-label-sm text-end";
4918 label.style = this.fontSizeStyle;
4919 label.innerHTML = outputName;
4920 label.for = nodeOutput.id;
4921 elem.appendChild(label);
4922
4923
4924 if (useFormControl) {
4925 output.classList.add("form-control");
4926 }
4927 output.classList.add("form-control-sm");
4928
4930 output.disabled = true;
4931
4932 var propvalue = document.createElement("div");
4933 propvalue.className = "col p-1";
4934 propvalue.appendChild(output);
4935
4936 elem.appendChild(propvalue);
4937
4938 output_details.appendChild(elem);
4939
4940 } else {
4941 console.log(`- Node with ID ${link.target_id} not found.`);
4942 console.log(
'--- Available nodes:',
graphcanvas.graph._nodes_by_id);
4943 }
4944 } else {
4945 console.log(`- Link with ID ${link_id} not found.`);
4946 }
4947 }
4948
4949 }
4950 if (output_details) {
4951 propertypanelcontent.appendChild(output_details);
4952 }
4953 }
createColorSpaceInput(colorSpaces, activeItem)
Create a color space input element.
rgbToHex(rgb)
Utility to convert a color from RGB to hex.
createButtonWithImageAndText(imageSrc, text, id)
Create a DOM button with an image and text.
updateImagePreview(curImage)
Update the image preview in the property panel.
setTargetDistanceUnit(unit)
Set the global distance unit for the editor.
createUnitsInput(units, unittype, activeItem)
Create a units input element.
getTargetDistanceUnit()
Get the global distance unit for the editor.
setSourceColorSpace(colorSpace)
Set global color space for the editor.
getSourceColorSpace()
Get the global color space for the editor.
openImageDialog(theNode, updateProp, wantURI)
Open a dialog to select a image file to load.